On Thu, 22 Mar 2012 15:26:47 +0000 Sachin Prabhu <sprabhu@xxxxxxxxxx> wrote: > Use the standard token parser instead of the long if condition to parse > cifs mount options. > > This was first proposed by Scott Lovenberg > http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.html > > Mount options have been grouped together in terms of their input types. > Aliases for username, password, domain and credentials have been added. > The password parser has been modified to make it easier to read. > > Since the patch was first proposed, the following bugs have been fixed > 1) Allow blank 'pass' option to be passed by the cifs mount helper when > using sec=none. > 2) Do not explicitly set vol->nullauth to 0. This causes a problem > when using sec=none while also using a username. > > Signed-off-by: Sachin Prabhu <sprabhu@xxxxxxxxxx> > --- > fs/cifs/connect.c | 1338 ++++++++++++++++++++++++++++++++--------------------- > 1 files changed, 814 insertions(+), 524 deletions(-) > > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > index 5560e1d..06702d3 100644 > --- a/fs/cifs/connect.c > +++ b/fs/cifs/connect.c > @@ -40,6 +40,8 @@ > #include <linux/module.h> > #include <keys/user-type.h> > #include <net/ipv6.h> > +#include <linux/parser.h> > + > #include "cifspdu.h" > #include "cifsglob.h" > #include "cifsproto.h" > @@ -63,6 +65,191 @@ extern mempool_t *cifs_req_poolp; > #define TLINK_ERROR_EXPIRE (1 * HZ) > #define TLINK_IDLE_EXPIRE (600 * HZ) > > +enum { > + > + /* Mount options that take no arguments */ > + Opt_user_xattr, Opt_nouser_xattr, > + Opt_forceuid, Opt_noforceuid, > + Opt_noblocksend, Opt_noautotune, > + Opt_hard, Opt_soft, Opt_perm, Opt_noperm, > + Opt_mapchars, Opt_nomapchars, Opt_sfu, > + Opt_nosfu, Opt_nodfs, Opt_posixpaths, > + Opt_noposixpaths, Opt_nounix, > + Opt_nocase, > + Opt_brl, Opt_nobrl, > + Opt_forcemandatorylock, Opt_setuids, > + Opt_nosetuids, Opt_dynperm, Opt_nodynperm, > + Opt_nohard, Opt_nosoft, > + Opt_nointr, Opt_intr, > + Opt_nostrictsync, Opt_strictsync, > + Opt_serverino, Opt_noserverino, > + Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl, > + Opt_acl, Opt_noacl, Opt_locallease, > + Opt_sign, Opt_seal, Opt_direct, > + Opt_strictcache, Opt_noac, > + Opt_fsc, Opt_mfsymlinks, > + Opt_multiuser, > + > + /* Mount options which take numeric value */ > + Opt_backupuid, Opt_backupgid, Opt_uid, > + Opt_cruid, Opt_gid, Opt_file_mode, > + Opt_dirmode, Opt_port, > + Opt_rsize, Opt_wsize, Opt_actimeo, > + > + /* Mount options which take string value */ > + Opt_user, Opt_pass, Opt_ip, > + Opt_unc, Opt_domain, > + Opt_srcaddr, Opt_prefixpath, > + Opt_iocharset, Opt_sockopt, > + Opt_netbiosname, Opt_servern, > + Opt_ver, Opt_sec, > + > + /* Mount options to be ignored */ > + Opt_ignore, > + > + /* Options which could be blank */ > + Opt_blank_pass, > + > + Opt_err > +}; > + > +static const match_table_t cifs_mount_option_tokens = { > + > + { Opt_user_xattr, "user_xattr" }, > + { Opt_nouser_xattr, "nouser_xattr" }, > + { Opt_forceuid, "forceuid" }, > + { Opt_noforceuid, "noforceuid" }, > + { Opt_noblocksend, "noblocksend" }, > + { Opt_noautotune, "noautotune" }, > + { Opt_hard, "hard" }, > + { Opt_soft, "soft" }, > + { Opt_perm, "perm" }, > + { Opt_noperm, "noperm" }, > + { Opt_mapchars, "mapchars" }, > + { Opt_nomapchars, "nomapchars" }, > + { Opt_sfu, "sfu" }, > + { Opt_nosfu, "nosfu" }, > + { Opt_nodfs, "nodfs" }, > + { Opt_posixpaths, "posixpaths" }, > + { Opt_noposixpaths, "noposixpaths" }, > + { Opt_nounix, "nounix" }, > + { Opt_nounix, "nolinux" }, > + { Opt_nocase, "nocase" }, > + { Opt_nocase, "ignorecase" }, > + { Opt_brl, "brl" }, > + { Opt_nobrl, "nobrl" }, > + { Opt_nobrl, "nolock" }, > + { Opt_forcemandatorylock, "forcemandatorylock" }, > + { Opt_setuids, "setuids" }, > + { Opt_nosetuids, "nosetuids" }, > + { Opt_dynperm, "dynperm" }, > + { Opt_nodynperm, "nodynperm" }, > + { Opt_nohard, "nohard" }, > + { Opt_nosoft, "nosoft" }, > + { Opt_nointr, "nointr" }, > + { Opt_intr, "intr" }, > + { Opt_nostrictsync, "nostrictsync" }, > + { Opt_strictsync, "strictsync" }, > + { Opt_serverino, "serverino" }, > + { Opt_noserverino, "noserverino" }, > + { Opt_rwpidforward, "rwpidforward" }, > + { Opt_cifsacl, "cifsacl" }, > + { Opt_nocifsacl, "nocifsacl" }, > + { Opt_acl, "acl" }, > + { Opt_noacl, "noacl" }, > + { Opt_locallease, "locallease" }, > + { Opt_sign, "sign" }, > + { Opt_seal, "seal" }, > + { Opt_direct, "direct" }, > + { Opt_direct, "forceddirectio" }, > + { Opt_strictcache, "strictcache" }, > + { Opt_noac, "noac" }, > + { Opt_fsc, "fsc" }, > + { Opt_mfsymlinks, "mfsymlinks" }, > + { Opt_multiuser, "multiuser" }, > + > + { Opt_backupuid, "backupuid=%s" }, > + { Opt_backupgid, "backupgid=%s" }, > + { Opt_uid, "uid=%s" }, > + { Opt_cruid, "cruid=%s" }, > + { Opt_gid, "gid=%s" }, > + { Opt_file_mode, "file_mode=%s" }, > + { Opt_dirmode, "dirmode=%s" }, > + { Opt_dirmode, "dir_mode=%s" }, > + { Opt_port, "port=%s" }, > + { Opt_rsize, "rsize=%s" }, > + { Opt_wsize, "wsize=%s" }, > + { Opt_actimeo, "actimeo=%s" }, > + > + { Opt_user, "user=%s" }, > + { Opt_user, "username=%s" }, > + { Opt_blank_pass, "pass=" }, > + { Opt_pass, "pass=%s" }, > + { Opt_pass, "password=%s" }, > + { Opt_ip, "ip=%s" }, > + { Opt_ip, "addr=%s" }, > + { Opt_unc, "unc=%s" }, > + { Opt_unc, "target=%s" }, > + { Opt_unc, "path=%s" }, > + { Opt_domain, "dom=%s" }, > + { Opt_domain, "domain=%s" }, > + { Opt_domain, "workgroup=%s" }, > + { Opt_srcaddr, "srcaddr=%s" }, > + { Opt_prefixpath, "prefixpath=%s" }, > + { Opt_iocharset, "iocharset=%s" }, > + { Opt_sockopt, "sockopt=%s" }, > + { Opt_netbiosname, "netbiosname=%s" }, > + { Opt_servern, "servern=%s" }, > + { Opt_ver, "ver=%s" }, > + { Opt_ver, "vers=%s" }, > + { Opt_ver, "version=%s" }, > + { Opt_sec, "sec=%s" }, > + > + { Opt_ignore, "cred" }, > + { Opt_ignore, "credentials" }, > + { Opt_ignore, "guest" }, > + { Opt_ignore, "rw" }, > + { Opt_ignore, "ro" }, > + { Opt_ignore, "suid" }, > + { Opt_ignore, "nosuid" }, > + { Opt_ignore, "exec" }, > + { Opt_ignore, "noexec" }, > + { Opt_ignore, "nodev" }, > + { Opt_ignore, "noauto" }, > + { Opt_ignore, "dev" }, > + { Opt_ignore, "mand" }, > + { Opt_ignore, "nomand" }, > + { Opt_ignore, "_netdev" }, > + > + { Opt_err, NULL } > +}; > + > +enum { > + Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p, > + Opt_sec_ntlmsspi, Opt_sec_ntlmssp, > + Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i, > + Opt_sec_nontlm, Opt_sec_lanman, > + Opt_sec_none, > + > + Opt_sec_err > +}; > + > +static const match_table_t cifs_secflavor_tokens = { > + { Opt_sec_krb5, "krb5" }, > + { Opt_sec_krb5i, "krb5i" }, > + { Opt_sec_krb5p, "krb5p" }, > + { Opt_sec_ntlmsspi, "ntlmsspi" }, > + { Opt_sec_ntlmssp, "ntlmssp" }, > + { Opt_ntlm, "ntlm" }, > + { Opt_sec_ntlmi, "ntlmi" }, > + { Opt_sec_ntlmv2i, "ntlmv2i" }, > + { Opt_sec_nontlm, "nontlm" }, > + { Opt_sec_lanman, "lanman" }, > + { Opt_sec_none, "none" }, > + > + { Opt_sec_err, NULL } > +}; > + > static int ip_connect(struct TCP_Server_Info *server); > static int generic_ip_connect(struct TCP_Server_Info *server); > static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); > @@ -926,13 +1113,79 @@ extract_hostname(const char *unc) > return dst; > } > > +static int get_option_ul(substring_t args[], unsigned long *option) > +{ > + int rc; > + char *string; > + > + string = match_strdup(args); > + if (string == NULL) > + return -ENOMEM; > + rc = kstrtoul(string, 10, option); > + kfree(string); > + > + return rc; > +} > + > + > +static int cifs_parse_security_flavors(char *value, > + struct smb_vol *vol) > +{ > + > + substring_t args[MAX_OPT_ARGS]; > + > + switch (match_token(value, cifs_secflavor_tokens, args)) { > + case Opt_sec_krb5: > + vol->secFlg |= CIFSSEC_MAY_KRB5; > + break; > + case Opt_sec_krb5i: > + vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; > + break; > + case Opt_sec_krb5p: > + /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ > + cERROR(1, "Krb5 cifs privacy not supported"); > + break; > + case Opt_sec_ntlmssp: > + vol->secFlg |= CIFSSEC_MAY_NTLMSSP; > + break; > + case Opt_sec_ntlmsspi: > + vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN; > + break; > + case Opt_ntlm: > + /* ntlm is default so can be turned off too */ > + vol->secFlg |= CIFSSEC_MAY_NTLM; > + break; > + case Opt_sec_ntlmi: > + vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; > + break; > + case Opt_sec_nontlm: > + vol->secFlg |= CIFSSEC_MAY_NTLMV2; > + break; > + case Opt_sec_ntlmv2i: > + vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; > + break; > +#ifdef CONFIG_CIFS_WEAK_PW_HASH > + case Opt_sec_lanman: > + vol->secFlg |= CIFSSEC_MAY_LANMAN; > + break; > +#endif > + case Opt_sec_none: > + vol->nullauth = 1; > + break; > + default: > + cERROR(1, "bad security option: %s", value); > + return 1; > + } > + > + return 0; > +} > + > static int > cifs_parse_mount_options(const char *mountdata, const char *devname, > struct smb_vol *vol) > { > - char *value, *data, *end; > + char *data, *end; > char *mountdata_copy = NULL, *options; > - int err; > unsigned int temp_len, i, j; > char separator[2]; > short int override_uid = -1; > @@ -940,9 +1193,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, > bool uid_specified = false; > bool gid_specified = false; > char *nodename = utsname()->nodename; > + char *string = NULL; > + char *tmp_end, *value; > + char delim; > > separator[0] = ','; > separator[1] = 0; > + delim = separator[0]; > > /* > * does not have to be perfect mapping since field is > @@ -981,6 +1238,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, > > options = mountdata_copy; > end = options + strlen(options); > + > if (strncmp(options, "sep=", 4) == 0) { > if (options[4] != 0) { > separator[0] = options[4]; > @@ -993,609 +1251,638 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, > vol->backupgid_specified = false; /* no backup intent for a group */ > > while ((data = strsep(&options, separator)) != NULL) { > + substring_t args[MAX_OPT_ARGS]; > + unsigned long option; > + int token; > + > if (!*data) > continue; > - if ((value = strchr(data, '=')) != NULL) > - *value++ = '\0'; > > - /* Have to parse this before we parse for "user" */ > - if (strnicmp(data, "user_xattr", 10) == 0) { > + token = match_token(data, cifs_mount_option_tokens, args); > + > + switch (token) { > + > + /* Ingnore the following */ > + case Opt_ignore: > + break; > + > + /* Boolean values */ > + case Opt_user_xattr: > vol->no_xattr = 0; > - } else if (strnicmp(data, "nouser_xattr", 12) == 0) { > + break; > + case Opt_nouser_xattr: > vol->no_xattr = 1; > - } else if (strnicmp(data, "user", 4) == 0) { > - if (!value) { > - printk(KERN_WARNING > - "CIFS: invalid or missing username\n"); > - goto cifs_parse_mount_err; > - } else if (!*value) { > - /* null user, ie anonymous, authentication */ > - vol->nullauth = 1; > - } > - if (strnlen(value, MAX_USERNAME_SIZE) < > - MAX_USERNAME_SIZE) { > - vol->username = kstrdup(value, GFP_KERNEL); > - if (!vol->username) { > - printk(KERN_WARNING "CIFS: no memory " > - "for username\n"); > - goto cifs_parse_mount_err; > - } > - } else { > - printk(KERN_WARNING "CIFS: username too long\n"); > - goto cifs_parse_mount_err; > - } > - } else if (strnicmp(data, "pass", 4) == 0) { > - if (!value) { > - vol->password = NULL; > - continue; > - } else if (value[0] == 0) { > - /* check if string begins with double comma > - since that would mean the password really > - does start with a comma, and would not > - indicate an empty string */ > - if (value[1] != separator[0]) { > - vol->password = NULL; > - continue; > - } > - } > - temp_len = strlen(value); > - /* removed password length check, NTLM passwords > - can be arbitrarily long */ > - > - /* if comma in password, the string will be > - prematurely null terminated. Commas in password are > - specified across the cifs mount interface by a double > - comma ie ,, and a comma used as in other cases ie ',' > - as a parameter delimiter/separator is single and due > - to the strsep above is temporarily zeroed. */ > - > - /* NB: password legally can have multiple commas and > - the only illegal character in a password is null */ > - > - if ((value[temp_len] == 0) && > - (value + temp_len < end) && > - (value[temp_len+1] == separator[0])) { > - /* reinsert comma */ > - value[temp_len] = separator[0]; > - temp_len += 2; /* move after second comma */ > - while (value[temp_len] != 0) { > - if (value[temp_len] == separator[0]) { > - if (value[temp_len+1] == > - separator[0]) { > - /* skip second comma */ > - temp_len++; > - } else { > - /* single comma indicating start > - of next parm */ > - break; > - } > - } > - temp_len++; > - } > - if (value[temp_len] == 0) { > - options = NULL; > - } else { > - value[temp_len] = 0; > - /* point option to start of next parm */ > - options = value + temp_len + 1; > - } > - /* go from value to value + temp_len condensing > - double commas to singles. Note that this ends up > - allocating a few bytes too many, which is ok */ > - vol->password = kzalloc(temp_len, GFP_KERNEL); > - if (vol->password == NULL) { > - printk(KERN_WARNING "CIFS: no memory " > - "for password\n"); > - goto cifs_parse_mount_err; > - } > - for (i = 0, j = 0; i < temp_len; i++, j++) { > - vol->password[j] = value[i]; > - if (value[i] == separator[0] > - && value[i+1] == separator[0]) { > - /* skip second comma */ > - i++; > - } > - } > - vol->password[j] = 0; > - } else { > - vol->password = kzalloc(temp_len+1, GFP_KERNEL); > - if (vol->password == NULL) { > - printk(KERN_WARNING "CIFS: no memory " > - "for password\n"); > - goto cifs_parse_mount_err; > - } > - strcpy(vol->password, value); > - } > - } else if (!strnicmp(data, "ip", 2) || > - !strnicmp(data, "addr", 4)) { > - if (!value || !*value) { > - vol->UNCip = NULL; > - } else if (strnlen(value, INET6_ADDRSTRLEN) < > - INET6_ADDRSTRLEN) { > - vol->UNCip = kstrdup(value, GFP_KERNEL); > - if (!vol->UNCip) { > - printk(KERN_WARNING "CIFS: no memory " > - "for UNC IP\n"); > - goto cifs_parse_mount_err; > - } > - } else { > - printk(KERN_WARNING "CIFS: ip address " > - "too long\n"); > - goto cifs_parse_mount_err; > - } > - } else if (strnicmp(data, "sec", 3) == 0) { > - if (!value || !*value) { > - cERROR(1, "no security value specified"); > - continue; > - } else if (strnicmp(value, "krb5i", 5) == 0) { > - vol->secFlg |= CIFSSEC_MAY_KRB5 | > - CIFSSEC_MUST_SIGN; > - } else if (strnicmp(value, "krb5p", 5) == 0) { > - /* vol->secFlg |= CIFSSEC_MUST_SEAL | > - CIFSSEC_MAY_KRB5; */ > - cERROR(1, "Krb5 cifs privacy not supported"); > - goto cifs_parse_mount_err; > - } else if (strnicmp(value, "krb5", 4) == 0) { > - vol->secFlg |= CIFSSEC_MAY_KRB5; > - } else if (strnicmp(value, "ntlmsspi", 8) == 0) { > - vol->secFlg |= CIFSSEC_MAY_NTLMSSP | > - CIFSSEC_MUST_SIGN; > - } else if (strnicmp(value, "ntlmssp", 7) == 0) { > - vol->secFlg |= CIFSSEC_MAY_NTLMSSP; > - } else if (strnicmp(value, "ntlmv2i", 7) == 0) { > - vol->secFlg |= CIFSSEC_MAY_NTLMV2 | > - CIFSSEC_MUST_SIGN; > - } else if (strnicmp(value, "ntlmv2", 6) == 0) { > - vol->secFlg |= CIFSSEC_MAY_NTLMV2; > - } else if (strnicmp(value, "ntlmi", 5) == 0) { > - vol->secFlg |= CIFSSEC_MAY_NTLM | > - CIFSSEC_MUST_SIGN; > - } else if (strnicmp(value, "ntlm", 4) == 0) { > - /* ntlm is default so can be turned off too */ > - vol->secFlg |= CIFSSEC_MAY_NTLM; > - } else if (strnicmp(value, "nontlm", 6) == 0) { > - /* BB is there a better way to do this? */ > - vol->secFlg |= CIFSSEC_MAY_NTLMV2; > -#ifdef CONFIG_CIFS_WEAK_PW_HASH > - } else if (strnicmp(value, "lanman", 6) == 0) { > - vol->secFlg |= CIFSSEC_MAY_LANMAN; > -#endif > - } else if (strnicmp(value, "none", 4) == 0) { > - vol->nullauth = 1; > - } else { > - cERROR(1, "bad security option: %s", value); > - goto cifs_parse_mount_err; > - } > - } else if (strnicmp(data, "vers", 3) == 0) { > - if (!value || !*value) { > - cERROR(1, "no protocol version specified" > - " after vers= mount option"); > - } else if ((strnicmp(value, "cifs", 4) == 0) || > - (strnicmp(value, "1", 1) == 0)) { > - /* this is the default */ > - continue; > - } > - } else if ((strnicmp(data, "unc", 3) == 0) > - || (strnicmp(data, "target", 6) == 0) > - || (strnicmp(data, "path", 4) == 0)) { > - if (!value || !*value) { > - printk(KERN_WARNING "CIFS: invalid path to " > - "network resource\n"); > - goto cifs_parse_mount_err; > - } > - if ((temp_len = strnlen(value, 300)) < 300) { > - vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); > - if (vol->UNC == NULL) > - goto cifs_parse_mount_err; > - strcpy(vol->UNC, value); > - if (strncmp(vol->UNC, "//", 2) == 0) { > - vol->UNC[0] = '\\'; > - vol->UNC[1] = '\\'; > - } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { > - printk(KERN_WARNING > - "CIFS: UNC Path does not begin " > - "with // or \\\\ \n"); > - goto cifs_parse_mount_err; > - } > - } else { > - printk(KERN_WARNING "CIFS: UNC name too long\n"); > - goto cifs_parse_mount_err; > - } > - } else if ((strnicmp(data, "domain", 3) == 0) > - || (strnicmp(data, "workgroup", 5) == 0)) { > - if (!value || !*value) { > - printk(KERN_WARNING "CIFS: invalid domain name\n"); > - goto cifs_parse_mount_err; > - } > - /* BB are there cases in which a comma can be valid in > - a domain name and need special handling? */ > - if (strnlen(value, 256) < 256) { > - vol->domainname = kstrdup(value, GFP_KERNEL); > - if (!vol->domainname) { > - printk(KERN_WARNING "CIFS: no memory " > - "for domainname\n"); > - goto cifs_parse_mount_err; > - } > - cFYI(1, "Domain name set"); > - } else { > - printk(KERN_WARNING "CIFS: domain name too " > - "long\n"); > - goto cifs_parse_mount_err; > - } > - } else if (strnicmp(data, "srcaddr", 7) == 0) { > - vol->srcaddr.ss_family = AF_UNSPEC; > - > - if (!value || !*value) { > - printk(KERN_WARNING "CIFS: srcaddr value" > - " not specified.\n"); > - goto cifs_parse_mount_err; > - } > - i = cifs_convert_address((struct sockaddr *)&vol->srcaddr, > - value, strlen(value)); > - if (i == 0) { > - printk(KERN_WARNING "CIFS: Could not parse" > - " srcaddr: %s\n", > - value); > - goto cifs_parse_mount_err; > - } > - } else if (strnicmp(data, "prefixpath", 10) == 0) { > - if (!value || !*value) { > - printk(KERN_WARNING > - "CIFS: invalid path prefix\n"); > - goto cifs_parse_mount_err; > - } > - if ((temp_len = strnlen(value, 1024)) < 1024) { > - if (value[0] != '/') > - temp_len++; /* missing leading slash */ > - vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); > - if (vol->prepath == NULL) > - goto cifs_parse_mount_err; > - if (value[0] != '/') { > - vol->prepath[0] = '/'; > - strcpy(vol->prepath+1, value); > - } else > - strcpy(vol->prepath, value); > - cFYI(1, "prefix path %s", vol->prepath); > - } else { > - printk(KERN_WARNING "CIFS: prefix too long\n"); > - goto cifs_parse_mount_err; > - } > - } else if (strnicmp(data, "iocharset", 9) == 0) { > - if (!value || !*value) { > - printk(KERN_WARNING "CIFS: invalid iocharset " > - "specified\n"); > - goto cifs_parse_mount_err; > - } > - if (strnlen(value, 65) < 65) { > - if (strnicmp(value, "default", 7)) { > - vol->iocharset = kstrdup(value, > - GFP_KERNEL); > - > - if (!vol->iocharset) { > - printk(KERN_WARNING "CIFS: no " > - "memory for" > - "charset\n"); > - goto cifs_parse_mount_err; > - } > - } > - /* if iocharset not set then load_nls_default > - is used by caller */ > - cFYI(1, "iocharset set to %s", value); > - } else { > - printk(KERN_WARNING "CIFS: iocharset name " > - "too long.\n"); > - goto cifs_parse_mount_err; > - } > - } else if (!strnicmp(data, "uid", 3) && value && *value) { > - vol->linux_uid = simple_strtoul(value, &value, 0); > - uid_specified = true; > - } else if (!strnicmp(data, "cruid", 5) && value && *value) { > - vol->cred_uid = simple_strtoul(value, &value, 0); > - } else if (!strnicmp(data, "forceuid", 8)) { > + break; > + case Opt_forceuid: > override_uid = 1; > - } else if (!strnicmp(data, "noforceuid", 10)) { > + break; > + case Opt_noforceuid: > override_uid = 0; > - } else if (!strnicmp(data, "gid", 3) && value && *value) { > - vol->linux_gid = simple_strtoul(value, &value, 0); > - gid_specified = true; > - } else if (!strnicmp(data, "forcegid", 8)) { > - override_gid = 1; > - } else if (!strnicmp(data, "noforcegid", 10)) { > - override_gid = 0; > - } else if (strnicmp(data, "file_mode", 4) == 0) { > - if (value && *value) { > - vol->file_mode = > - simple_strtoul(value, &value, 0); > - } > - } else if (strnicmp(data, "dir_mode", 4) == 0) { > - if (value && *value) { > - vol->dir_mode = > - simple_strtoul(value, &value, 0); > - } > - } else if (strnicmp(data, "dirmode", 4) == 0) { > - if (value && *value) { > - vol->dir_mode = > - simple_strtoul(value, &value, 0); > - } > - } else if (strnicmp(data, "port", 4) == 0) { > - if (value && *value) { > - vol->port = > - simple_strtoul(value, &value, 0); > - } > - } else if (strnicmp(data, "rsize", 5) == 0) { > - if (value && *value) { > - vol->rsize = > - simple_strtoul(value, &value, 0); > - } > - } else if (strnicmp(data, "wsize", 5) == 0) { > - if (value && *value) { > - vol->wsize = > - simple_strtoul(value, &value, 0); > - } > - } else if (strnicmp(data, "sockopt", 5) == 0) { > - if (!value || !*value) { > - cERROR(1, "no socket option specified"); > - continue; > - } else if (strnicmp(value, "TCP_NODELAY", 11) == 0) { > - vol->sockopt_tcp_nodelay = 1; > - } > - } else if (strnicmp(data, "netbiosname", 4) == 0) { > - if (!value || !*value || (*value == ' ')) { > - cFYI(1, "invalid (empty) netbiosname"); > - } else { > - memset(vol->source_rfc1001_name, 0x20, > - RFC1001_NAME_LEN); > - /* > - * FIXME: are there cases in which a comma can > - * be valid in workstation netbios name (and > - * need special handling)? > - */ > - for (i = 0; i < RFC1001_NAME_LEN; i++) { > - /* don't ucase netbiosname for user */ > - if (value[i] == 0) > - break; > - vol->source_rfc1001_name[i] = value[i]; > - } > - /* The string has 16th byte zero still from > - set at top of the function */ > - if (i == RFC1001_NAME_LEN && value[i] != 0) > - printk(KERN_WARNING "CIFS: netbiosname" > - " longer than 15 truncated.\n"); > - } > - } else if (strnicmp(data, "servern", 7) == 0) { > - /* servernetbiosname specified override *SMBSERVER */ > - if (!value || !*value || (*value == ' ')) { > - cFYI(1, "empty server netbiosname specified"); > - } else { > - /* last byte, type, is 0x20 for servr type */ > - memset(vol->target_rfc1001_name, 0x20, > - RFC1001_NAME_LEN_WITH_NULL); > - > - for (i = 0; i < 15; i++) { > - /* BB are there cases in which a comma can be > - valid in this workstation netbios name > - (and need special handling)? */ > - > - /* user or mount helper must uppercase > - the netbiosname */ > - if (value[i] == 0) > - break; > - else > - vol->target_rfc1001_name[i] = > - value[i]; > - } > - /* The string has 16th byte zero still from > - set at top of the function */ > - if (i == RFC1001_NAME_LEN && value[i] != 0) > - printk(KERN_WARNING "CIFS: server net" > - "biosname longer than 15 truncated.\n"); > - } > - } else if (strnicmp(data, "actimeo", 7) == 0) { > - if (value && *value) { > - vol->actimeo = HZ * simple_strtoul(value, > - &value, 0); > - if (vol->actimeo > CIFS_MAX_ACTIMEO) { > - cERROR(1, "CIFS: attribute cache" > - "timeout too large"); > - goto cifs_parse_mount_err; > - } > - } > - } else if (strnicmp(data, "credentials", 4) == 0) { > - /* ignore */ > - } else if (strnicmp(data, "version", 3) == 0) { > - /* ignore */ > - } else if (strnicmp(data, "guest", 5) == 0) { > - /* ignore */ > - } else if (strnicmp(data, "rw", 2) == 0 && strlen(data) == 2) { > - /* ignore */ > - } else if (strnicmp(data, "ro", 2) == 0) { > - /* ignore */ > - } else if (strnicmp(data, "noblocksend", 11) == 0) { > + break; > + case Opt_noblocksend: > vol->noblocksnd = 1; > - } else if (strnicmp(data, "noautotune", 10) == 0) { > + break; > + case Opt_noautotune: > vol->noautotune = 1; > - } else if ((strnicmp(data, "suid", 4) == 0) || > - (strnicmp(data, "nosuid", 6) == 0) || > - (strnicmp(data, "exec", 4) == 0) || > - (strnicmp(data, "noexec", 6) == 0) || > - (strnicmp(data, "nodev", 5) == 0) || > - (strnicmp(data, "noauto", 6) == 0) || > - (strnicmp(data, "dev", 3) == 0)) { > - /* The mount tool or mount.cifs helper (if present) > - uses these opts to set flags, and the flags are read > - by the kernel vfs layer before we get here (ie > - before read super) so there is no point trying to > - parse these options again and set anything and it > - is ok to just ignore them */ > - continue; > - } else if (strnicmp(data, "hard", 4) == 0) { > + break; > + case Opt_hard: > vol->retry = 1; > - } else if (strnicmp(data, "soft", 4) == 0) { > + break; > + case Opt_soft: > vol->retry = 0; > - } else if (strnicmp(data, "perm", 4) == 0) { > + break; > + case Opt_perm: > vol->noperm = 0; > - } else if (strnicmp(data, "noperm", 6) == 0) { > + break; > + case Opt_noperm: > vol->noperm = 1; > - } else if (strnicmp(data, "mapchars", 8) == 0) { > + break; > + case Opt_mapchars: > vol->remap = 1; > - } else if (strnicmp(data, "nomapchars", 10) == 0) { > + break; > + case Opt_nomapchars: > vol->remap = 0; > - } else if (strnicmp(data, "sfu", 3) == 0) { > + break; > + case Opt_sfu: > vol->sfu_emul = 1; > - } else if (strnicmp(data, "nosfu", 5) == 0) { > + break; > + case Opt_nosfu: > vol->sfu_emul = 0; > - } else if (strnicmp(data, "nodfs", 5) == 0) { > + break; > + case Opt_nodfs: > vol->nodfs = 1; > - } else if (strnicmp(data, "posixpaths", 10) == 0) { > + break; > + case Opt_posixpaths: > vol->posix_paths = 1; > - } else if (strnicmp(data, "noposixpaths", 12) == 0) { > + break; > + case Opt_noposixpaths: > vol->posix_paths = 0; > - } else if (strnicmp(data, "nounix", 6) == 0) { > - vol->no_linux_ext = 1; > - } else if (strnicmp(data, "nolinux", 7) == 0) { > + break; > + case Opt_nounix: > vol->no_linux_ext = 1; > - } else if ((strnicmp(data, "nocase", 6) == 0) || > - (strnicmp(data, "ignorecase", 10) == 0)) { > + break; > + case Opt_nocase: > vol->nocase = 1; > - } else if (strnicmp(data, "mand", 4) == 0) { > - /* ignore */ > - } else if (strnicmp(data, "nomand", 6) == 0) { > - /* ignore */ > - } else if (strnicmp(data, "_netdev", 7) == 0) { > - /* ignore */ > - } else if (strnicmp(data, "brl", 3) == 0) { > + break; > + case Opt_brl: > vol->nobrl = 0; > - } else if ((strnicmp(data, "nobrl", 5) == 0) || > - (strnicmp(data, "nolock", 6) == 0)) { > + break; > + case Opt_nobrl: > vol->nobrl = 1; > /* turn off mandatory locking in mode > - if remote locking is turned off since the > - local vfs will do advisory */ > + * if remote locking is turned off since the > + * local vfs will do advisory */ > if (vol->file_mode == > (S_IALLUGO & ~(S_ISUID | S_IXGRP))) > vol->file_mode = S_IALLUGO; > - } else if (strnicmp(data, "forcemandatorylock", 9) == 0) { > - /* will take the shorter form "forcemand" as well */ > - /* This mount option will force use of mandatory > - (DOS/Windows style) byte range locks, instead of > - using posix advisory byte range locks, even if the > - Unix extensions are available and posix locks would > - be supported otherwise. If Unix extensions are not > - negotiated this has no effect since mandatory locks > - would be used (mandatory locks is all that those > - those servers support) */ > + break; > + case Opt_forcemandatorylock: > vol->mand_lock = 1; > - } else if (strnicmp(data, "setuids", 7) == 0) { > + break; > + case Opt_setuids: > vol->setuids = 1; > - } else if (strnicmp(data, "nosetuids", 9) == 0) { > + break; > + case Opt_nosetuids: > vol->setuids = 0; > - } else if (strnicmp(data, "dynperm", 7) == 0) { > + break; > + case Opt_dynperm: > vol->dynperm = true; > - } else if (strnicmp(data, "nodynperm", 9) == 0) { > + break; > + case Opt_nodynperm: > vol->dynperm = false; > - } else if (strnicmp(data, "nohard", 6) == 0) { > + break; > + case Opt_nohard: > vol->retry = 0; > - } else if (strnicmp(data, "nosoft", 6) == 0) { > + break; > + case Opt_nosoft: > vol->retry = 1; > - } else if (strnicmp(data, "nointr", 6) == 0) { > + break; > + case Opt_nointr: > vol->intr = 0; > - } else if (strnicmp(data, "intr", 4) == 0) { > + break; > + case Opt_intr: > vol->intr = 1; > - } else if (strnicmp(data, "nostrictsync", 12) == 0) { > + break; > + case Opt_nostrictsync: > vol->nostrictsync = 1; > - } else if (strnicmp(data, "strictsync", 10) == 0) { > + break; > + case Opt_strictsync: > vol->nostrictsync = 0; > - } else if (strnicmp(data, "serverino", 7) == 0) { > + break; > + case Opt_serverino: > vol->server_ino = 1; > - } else if (strnicmp(data, "noserverino", 9) == 0) { > + break; > + case Opt_noserverino: > vol->server_ino = 0; > - } else if (strnicmp(data, "rwpidforward", 12) == 0) { > + break; > + case Opt_rwpidforward: > vol->rwpidforward = 1; > - } else if (strnicmp(data, "cifsacl", 7) == 0) { > + break; > + case Opt_cifsacl: > vol->cifs_acl = 1; > - } else if (strnicmp(data, "nocifsacl", 9) == 0) { > + break; > + case Opt_nocifsacl: > vol->cifs_acl = 0; > - } else if (strnicmp(data, "acl", 3) == 0) { > + break; > + case Opt_acl: > vol->no_psx_acl = 0; > - } else if (strnicmp(data, "noacl", 5) == 0) { > + break; > + case Opt_noacl: > vol->no_psx_acl = 1; > - } else if (strnicmp(data, "locallease", 6) == 0) { > + break; > + case Opt_locallease: > vol->local_lease = 1; > - } else if (strnicmp(data, "sign", 4) == 0) { > + break; > + case Opt_sign: > vol->secFlg |= CIFSSEC_MUST_SIGN; > - } else if (strnicmp(data, "seal", 4) == 0) { > + break; > + case Opt_seal: > /* we do not do the following in secFlags because seal > - is a per tree connection (mount) not a per socket > - or per-smb connection option in the protocol */ > - /* vol->secFlg |= CIFSSEC_MUST_SEAL; */ > + * is a per tree connection (mount) not a per socket > + * or per-smb connection option in the protocol > + * vol->secFlg |= CIFSSEC_MUST_SEAL; > + */ > vol->seal = 1; > - } else if (strnicmp(data, "direct", 6) == 0) { > - vol->direct_io = 1; > - } else if (strnicmp(data, "forcedirectio", 13) == 0) { > + break; > + case Opt_direct: > vol->direct_io = 1; > - } else if (strnicmp(data, "strictcache", 11) == 0) { > + break; > + case Opt_strictcache: > vol->strict_io = 1; > - } else if (strnicmp(data, "noac", 4) == 0) { > + break; > + case Opt_noac: > printk(KERN_WARNING "CIFS: Mount option noac not " > "supported. Instead set " > "/proc/fs/cifs/LookupCacheEnabled to 0\n"); > - } else if (strnicmp(data, "fsc", 3) == 0) { > + break; > + case Opt_fsc: > #ifndef CONFIG_CIFS_FSCACHE > cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE " > "kernel config option set"); > goto cifs_parse_mount_err; > #endif > vol->fsc = true; > - } else if (strnicmp(data, "mfsymlinks", 10) == 0) { > + break; > + case Opt_mfsymlinks: > vol->mfsymlinks = true; > - } else if (strnicmp(data, "multiuser", 8) == 0) { > + break; > + case Opt_multiuser: > vol->multiuser = true; > - } else if (!strnicmp(data, "backupuid", 9) && value && *value) { > - err = kstrtouint(value, 0, &vol->backupuid); > - if (err < 0) { > + break; > + > + /* Numeric Values */ > + case Opt_backupuid: > + if (get_option_ul(args, &option)) { > cERROR(1, "%s: Invalid backupuid value", > __func__); > goto cifs_parse_mount_err; > } > + vol->backupuid = option; > vol->backupuid_specified = true; > - } else if (!strnicmp(data, "backupgid", 9) && value && *value) { > - err = kstrtouint(value, 0, &vol->backupgid); > - if (err < 0) { > + break; > + case Opt_backupgid: > + if (get_option_ul(args, &option)) { > cERROR(1, "%s: Invalid backupgid value", > __func__); > goto cifs_parse_mount_err; > } > + vol->backupgid = option; > vol->backupgid_specified = true; > - } else > - printk(KERN_WARNING "CIFS: Unknown mount option %s\n", > - data); > - } > - if (vol->UNC == NULL) { > - if (devname == NULL) { > - printk(KERN_WARNING "CIFS: Missing UNC name for mount " > - "target\n"); > - goto cifs_parse_mount_err; > - } > - if ((temp_len = strnlen(devname, 300)) < 300) { > - vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); > - if (vol->UNC == NULL) > + break; > + case Opt_uid: > + if (get_option_ul(args, &option)) { > + cERROR(1, "%s: Invalid uid value", > + __func__); > + goto cifs_parse_mount_err; > + } > + vol->linux_uid = option; > + uid_specified = true; > + break; > + case Opt_cruid: > + if (get_option_ul(args, &option)) { > + cERROR(1, "%s: Invalid cruid value", > + __func__); > + goto cifs_parse_mount_err; > + } > + vol->cred_uid = option; > + break; > + case Opt_gid: > + if (get_option_ul(args, &option)) { > + cERROR(1, "%s: Invalid gid value", > + __func__); > + goto cifs_parse_mount_err; > + } > + vol->linux_gid = option; > + gid_specified = true; > + break; > + case Opt_file_mode: > + if (get_option_ul(args, &option)) { > + cERROR(1, "%s: Invalid file_mode value", > + __func__); > + goto cifs_parse_mount_err; > + } > + vol->file_mode = option; > + break; > + case Opt_dirmode: > + if (get_option_ul(args, &option)) { > + cERROR(1, "%s: Invalid dir_mode value", > + __func__); > + goto cifs_parse_mount_err; > + } > + vol->dir_mode = option; > + break; > + case Opt_port: > + if (get_option_ul(args, &option)) { > + cERROR(1, "%s: Invalid port value", > + __func__); > + goto cifs_parse_mount_err; > + } > + vol->port = option; > + break; > + case Opt_rsize: > + if (get_option_ul(args, &option)) { > + cERROR(1, "%s: Invalid rsize value", > + __func__); > + goto cifs_parse_mount_err; > + } > + vol->rsize = option; > + break; > + case Opt_wsize: > + if (get_option_ul(args, &option)) { > + cERROR(1, "%s: Invalid wsize value", > + __func__); > + goto cifs_parse_mount_err; > + } > + vol->wsize = option; > + break; > + case Opt_actimeo: > + if (get_option_ul(args, &option)) { > + cERROR(1, "%s: Invalid actimeo value", > + __func__); > + goto cifs_parse_mount_err; > + } > + vol->actimeo = HZ * option; > + if (vol->actimeo > CIFS_MAX_ACTIMEO) { > + cERROR(1, "CIFS: attribute cache" > + "timeout too large"); > + goto cifs_parse_mount_err; > + } > + break; > + > + /* String Arguments */ > + > + case Opt_user: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + /* null user, ie. anonymous authentication */ > + vol->nullauth = 1; > + } else if (strnlen(string, MAX_USERNAME_SIZE) > > + MAX_USERNAME_SIZE) { > + printk(KERN_WARNING "CIFS: username too long\n"); > + goto cifs_parse_mount_err; > + } > + vol->username = kstrdup(string, GFP_KERNEL); > + if (!vol->username) { > + printk(KERN_WARNING "CIFS: no memory " > + "for username\n"); > + goto cifs_parse_mount_err; > + } > + break; > + case Opt_blank_pass: > + vol->password = NULL; > + break; > + case Opt_pass: > + /* passwords have to be handled differently > + * to allow the character used for deliminator > + * to be passed within them > + */ > + > + /* Obtain the value string */ > + value = strchr(data, '='); > + if (value != NULL) > + *value++ = '\0'; > + > + /* Set tmp_end to end of the string */ > + tmp_end = (char *) value + strlen(value); > + > + /* Check if following character is the deliminator > + * If yes, we have encountered a double deliminator > + * reset the NULL character to the deliminator > + */ > + if (tmp_end < end && tmp_end[1] == delim) > + tmp_end[0] = delim; > + > + /* Keep iterating until we get to a single deliminator > + * OR the end > + */ > + while ((tmp_end = strchr(tmp_end, delim)) != NULL && > + (tmp_end[1] == delim)) { > + tmp_end = (char *) &tmp_end[2]; > + } > + > + /* Reset var options to point to next element */ > + if (tmp_end) { > + tmp_end[0] = '\0'; > + options = (char *) &tmp_end[1]; > + } else > + /* Reached the end of the mount option string */ > + options = end; > + > + /* Now build new password string */ > + temp_len = strlen(value); > + vol->password = kzalloc(temp_len+1, GFP_KERNEL); > + if (vol->password == NULL) { > + printk(KERN_WARNING "CIFS: no memory " > + "for password\n"); > + goto cifs_parse_mount_err; > + } > + > + for (i = 0, j = 0; i < temp_len; i++, j++) { > + vol->password[j] = value[i]; > + if ((value[i] == delim) && > + value[i+1] == delim) > + /* skip the second deliminator */ > + i++; > + } > + vol->password[j] = '\0'; > + break; > + case Opt_ip: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + vol->UNCip = NULL; > + } else if (strnlen(string, INET6_ADDRSTRLEN) > > + INET6_ADDRSTRLEN) { > + printk(KERN_WARNING "CIFS: ip address " > + "too long\n"); > + goto cifs_parse_mount_err; > + } > + vol->UNCip = kstrdup(string, GFP_KERNEL); > + if (!vol->UNCip) { > + printk(KERN_WARNING "CIFS: no memory " > + "for UNC IP\n"); > + goto cifs_parse_mount_err; > + } > + break; > + case Opt_unc: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + printk(KERN_WARNING "CIFS: invalid path to " > + "network resource\n"); > + goto cifs_parse_mount_err; > + } > + > + temp_len = strnlen(string, 300); > + if (temp_len == 300) { > + printk(KERN_WARNING "CIFS: UNC name too long\n"); > goto cifs_parse_mount_err; > - strcpy(vol->UNC, devname); > - if (strncmp(vol->UNC, "//", 2) == 0) { > + } > + > + if (strncmp(string, "//", 2) == 0) { > vol->UNC[0] = '\\'; > vol->UNC[1] = '\\'; > - } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { > + } else if (strncmp(string, "\\\\", 2) != 0) { > printk(KERN_WARNING "CIFS: UNC Path does not " > - "begin with // or \\\\ \n"); > + "begin with // or \\\\\n"); > goto cifs_parse_mount_err; > } > - value = strpbrk(vol->UNC+2, "/\\"); > - if (value) > - *value = '\\'; > - } else { > - printk(KERN_WARNING "CIFS: UNC name too long\n"); > + > + vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); > + if (vol->UNC == NULL) { > + printk(KERN_WARNING "CIFS: no memory " > + "for UNC\n"); > + goto cifs_parse_mount_err; > + } > + strcpy(vol->UNC, string); > + break; > + case Opt_domain: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + printk(KERN_WARNING "CIFS: invalid domain" > + " name\n"); > + goto cifs_parse_mount_err; > + } else if (strnlen(string, 256) == 256) { > + printk(KERN_WARNING "CIFS: domain name too" > + " long\n"); > + goto cifs_parse_mount_err; > + } > + > + vol->domainname = kstrdup(string, GFP_KERNEL); > + if (!vol->domainname) { > + printk(KERN_WARNING "CIFS: no memory " > + "for domainname\n"); > + goto cifs_parse_mount_err; > + } > + cFYI(1, "Domain name set"); > + break; > + case Opt_srcaddr: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + printk(KERN_WARNING "CIFS: srcaddr value not" > + " specified\n"); > + goto cifs_parse_mount_err; > + } else if (!cifs_convert_address( > + (struct sockaddr *)&vol->srcaddr, > + string, strlen(string))) { > + printk(KERN_WARNING "CIFS: Could not parse" > + " srcaddr: %s\n", string); > + goto cifs_parse_mount_err; > + } > + break; > + case Opt_prefixpath: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + printk(KERN_WARNING "CIFS: Invalid path" > + " prefix\n"); > + goto cifs_parse_mount_err; > + } > + temp_len = strnlen(string, 1024); > + if (string[0] != '/') > + temp_len++; /* missing leading slash */ > + if (temp_len > 1024) { > + printk(KERN_WARNING "CIFS: prefix too long\n"); > + goto cifs_parse_mount_err; > + } > + > + vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); > + if (vol->prepath == NULL) { > + printk(KERN_WARNING "CIFS: no memory " > + "for path prefix\n"); > + goto cifs_parse_mount_err; > + } > + > + if (string[0] != '/') { > + vol->prepath[0] = '/'; > + strcpy(vol->prepath+1, string); > + } else > + strcpy(vol->prepath, string); > + > + break; > + case Opt_iocharset: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + printk(KERN_WARNING "CIFS: Invalid iocharset" > + " specified\n"); > + goto cifs_parse_mount_err; > + } else if (strnlen(string, 1024) >= 65) { > + printk(KERN_WARNING "CIFS: iocharset name " > + "too long.\n"); > + goto cifs_parse_mount_err; > + } > + > + if (strnicmp(string, "default", 7) != 0) { > + vol->iocharset = kstrdup(string, > + GFP_KERNEL); > + if (!vol->iocharset) { > + printk(KERN_WARNING "CIFS: no memory" > + "for charset\n"); > + goto cifs_parse_mount_err; > + } > + } > + /* if iocharset not set then load_nls_default > + * is used by caller > + */ > + cFYI(1, "iocharset set to %s", string); > + break; > + case Opt_sockopt: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + printk(KERN_WARNING "CIFS: No socket option" > + " specified\n"); > + goto cifs_parse_mount_err; > + } > + if (strnicmp(string, "TCP_NODELAY", 11) == 0) > + vol->sockopt_tcp_nodelay = 1; > + break; > + case Opt_netbiosname: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + printk(KERN_WARNING "CIFS: Invalid (empty)" > + " netbiosname\n"); > + break; > + } > + > + memset(vol->source_rfc1001_name, 0x20, > + RFC1001_NAME_LEN); > + /* > + * FIXME: are there cases in which a comma can > + * be valid in workstation netbios name (and > + * need special handling)? > + */ > + for (i = 0; i < RFC1001_NAME_LEN; i++) { > + /* don't ucase netbiosname for user */ > + if (string[i] == 0) > + break; > + vol->source_rfc1001_name[i] = string[i]; > + } > + /* The string has 16th byte zero still from > + * set at top of the function > + */ > + if (i == RFC1001_NAME_LEN && string[i] != 0) > + printk(KERN_WARNING "CIFS: netbiosname" > + " longer than 15 truncated.\n"); > + > + break; > + case Opt_servern: > + /* servernetbiosname specified override *SMBSERVER */ > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + printk(KERN_WARNING "CIFS: Empty server" > + " netbiosname specified\n"); > + break; > + } > + /* last byte, type, is 0x20 for servr type */ > + memset(vol->target_rfc1001_name, 0x20, > + RFC1001_NAME_LEN_WITH_NULL); > + > + /* BB are there cases in which a comma can be > + valid in this workstation netbios name > + (and need special handling)? */ > + > + /* user or mount helper must uppercase the > + netbios name */ > + for (i = 0; i < 15; i++) { > + if (string[i] == 0) > + break; > + vol->target_rfc1001_name[i] = string[i]; > + } > + /* The string has 16th byte zero still from > + set at top of the function */ > + if (i == RFC1001_NAME_LEN && string[i] != 0) > + printk(KERN_WARNING "CIFS: server net" > + "biosname longer than 15 truncated.\n"); > + break; > + case Opt_ver: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + cERROR(1, "no protocol version specified" > + " after vers= mount option"); > + goto cifs_parse_mount_err; > + } > + > + if (strnicmp(string, "cifs", 4) == 0 || > + strnicmp(string, "1", 1) == 0) { > + /* This is the default */ > + break; > + } > + /* For all other value, error */ > + printk(KERN_WARNING "CIFS: Invalid version" > + " specified\n"); > goto cifs_parse_mount_err; > + case Opt_sec: > + string = match_strdup(args); > + if (string == NULL) > + goto out_nomem; > + > + if (!*string) { > + printk(KERN_WARNING "CIFS: no security flavor" > + " specified\n"); > + break; > + } > + > + if (cifs_parse_security_flavors(string, vol) != 0) > + goto cifs_parse_mount_err; > + break; > + default: > + printk(KERN_WARNING "CIFS: Unknown mount option %s\n", > + data); > + break; > } > + /* Free up any allocated string */ > + kfree(string); > + string = NULL; > } > > #ifndef CONFIG_KEYS > @@ -1625,7 +1912,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, > kfree(mountdata_copy); > return 0; > > +out_nomem: > + printk(KERN_WARNING "Could not allocate temporary buffer\n"); > cifs_parse_mount_err: > + kfree(string); > kfree(mountdata_copy); > return 1; > } Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx> -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html