cifs: use standard token parser for mount options
Subsystems (2)
PATCH 1/1 cifs: use standard token parser for mount options
Use the standard token parser instead of the long if confidtion 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.
fs/cifs/connect.c +808 -524
@@ -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,187 @@ 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, + + 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_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);
@@ -924,13 +1107,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 ;
@@ -938,9 +1187,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
@@ -979,6 +1232,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 ];
@@ -991,609 +1245,636 @@ 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; + } + vol->nullauth =0 ; +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
@@ -1623,7 +1904,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 ; }
Quoted 11 lines · Scott Lovenberg
On Fri, Mar 9, 2012 at 10:33, Sachin Prabhu <[email protected] <mailto:[email protected]>> wrote:
Use the standard token parser instead of the long if confidtion to parse
cifs mount options.This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.html
Quoted 9 lines
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.Signed-off-by Sachin Prabhu <[email protected]<mailto:[email protected]>>
[CC'ing the list my response... kernel.org didn't like my HTML formatted email]
Thanks. :) IIRC, Jeff was getting panics on a Fedora box using this patch. I never got around to fixing it. I'll still sign off on it though.
Thanks Scott,
Steve/Jeff, can I get your comments on this patch please.
Sachin Prabhu
----- Original Message -----
Quoted 39 lines · Scott Lovenberg
Quoted 22 lines
On Fri, Mar 9, 2012 at 10:33, Sachin Prabhu <[email protected] <mailto:[email protected]>> wrote:
Use the standard token parser instead of the long if confidtion to
parse
cifs mount options.This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.Quoted 3 lines
Signed-off-by Sachin Prabhu <[email protected]<mailto:[email protected]>>
[CC'ing the list my response... kernel.org didn't like my HTML formatted
email]
Thanks. :) IIRC, Jeff was getting panics on a Fedora box using this patch. I never got around to fixing it. I'll still sign off on it though.--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 6 lines · On Wed, 14 Mar 2012 14:17:26 -0400 (EDT) Sachin Prabhu…
Thanks Scott,
Steve/Jeff, can I get your comments on this patch please.
Sachin Prabhu
Does it address the oops that we saw with Scott's patch? Here's what I wrote when I hit that oops before.
----------------------------[snip]---------------------------
Finally got around to trying this out and I get the following oops when mounting a share with these options:
sec=krb5i,multises,noauto
general protection fault: 0000 [#1] SMP last sysfs file: /sys/devices/virtual/bdi/cifs-1/uevent CPU 0 Modules linked in: cifs nfsd lockd nfs_acl exportfs rpcsec_gss_krb5 auth_rpcgss des_generic sunrpc ipv6 microcode i2c_piix4 i2c_core virtio_net joydev virtio_balloon virtio_blk virtio_pci virtio_ring virtio [last unloaded: mperf]
Pid: 1542, comm: mount.cifs Not tainted 2.6.35-0.2.rc3.git0.fc14.x86_64 #1 /
RIP: 0010:[<ffffffff8123728c>] [<ffffffff8123728c>] strchr+0x14/0x1d RSP: 0018:ffff880039a65bd8 EFLAGS: 00010246 RAX: 7365735f626d735f RBX: 0000000000000000 RCX: ffff88003cb4d041 RDX: ffff880039a65c6d RSI: 0000000000000025 RDI: 7365735f626d735f RBP: ffff880039a65bd8 R08: 000000000000002c R09: 000000000000002c R10: 00000000000080d0 R11: ffffffff8113bc6c R12: ffff88003cb4d041 R13: ffffffffa0219d40 R14: 0000000000000000 R15: 7365735f626d735f FS: 00007f1fbcba6720(0000) GS:ffff880004600000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000001a31818 CR3: 000000003a287000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process mount.cifs (pid: 1542, threadinfo ffff880039a64000, task ffff880039adc8a0) Stack: ffff880039a65c48 ffffffff8123b1ee ffff88003a18b990 ffff880039a65cd8 <0> ffff88003cb4d041 ffffffff8111cd42 ffffffffa0202f86 7365735f626d735f <0> ffff88003997de30 ffff88003997de30 ffff88003cc94840 00000000ffffffff Call Trace: [<ffffffff8123b1ee>] match_token+0x4b/0x1a8 [<ffffffff8111cd42>] ? __kmalloc+0x17c/0x18e [<ffffffffa0202f86>] ? cifs_mount+0x639/0x1737 [cifs] [<ffffffffa0202c11>] cifs_mount+0x2c4/0x1737 [cifs] [<ffffffffa01f5aa4>] ? cifs_get_sb+0x110/0x2e4 [cifs] [<ffffffffa01f5b00>] cifs_get_sb+0x16c/0x2e4 [cifs] [<ffffffff8112c946>] vfs_kern_mount+0xbd/0x19b [<ffffffff8112ca8c>] do_kern_mount+0x4d/0xed [<ffffffff8114368a>] do_mount+0x776/0x7ed [<ffffffff811128aa>] ? alloc_pages_current+0xa7/0xca [<ffffffff81143789>] sys_mount+0x88/0xc2 [<ffffffff81009c32>] system_call_fastpath+0x16/0x1b Code: 14 84 c0 74 0e 48 ff c7 48 ff c6 48 ff ca 48 85 d2 75 e1 31 c0 c9 c3 55 48 89 f8 48 89 e5 eb 0b 84 d2 75 04 31 c0 eb 0a 48 ff c0 <8a> 10 40 38 f2 75 ee c9 c3 55 48 89 f8 48 89 e5 eb 03 48 ff c0 RIP [<ffffffff8123728c>] strchr+0x14/0x1d RSP <ffff880039a65bd8> ---[ end trace 50d173d44b64b1d9 ]---
It's crashing in this match_token() call:
gdb) list *(cifs_mount+0x2c4)0xdcf7 is in cifs_mount (fs/cifs/connect.c:1094).
1089 while ((data = strsep(&options, separator)) != NULL) {
1090 if (!*data)
1091 continue;
1092 if ((value = strchr(data, '=')) != NULL)
1093 *value++ = '\0';
1094 switch (match_token(data, cifs_mount_options, args)) {
1095 case Opt_user_xattr:
1096 vol->no_xattr = 0;
1097 break;
1098 case Opt_nouser_xattr:
(gdb) quit
Signature · 1 line
Jeff Layton <[email protected]>
I don't mind reviewing this, but it does appear to change behaviour significantly from existing code. Does this fix a reported bug?
The linux cifs kernel driver, like some other network clients, allows partial option matching to ease usability for users of other platforms (e.g. "pass" or "passwd" or "password" are intentionally all accepted since we match on the first four bytes of that keyword). Is there a way to get that to work with your patchset. I worry that some users will be confused that their mount options won't work if this is taken.
Quoted 79 lines · Jeff Layton
Quoted 6 lines · On Wed, 14 Mar 2012 14:17:26 -0400 (EDT) Sachin Prabhu…
Thanks Scott,
Steve/Jeff, can I get your comments on this patch please.
Sachin Prabhu
Does it address the oops that we saw with Scott's patch? Here's what I wrote when I hit that oops before.
----------------------------[snip]---------------------------
Finally got around to trying this out and I get the following oops when mounting a share with these options:
sec=krb5i,multises,noauto
general protection fault: 0000 [#1] SMP last sysfs file: /sys/devices/virtual/bdi/cifs-1/uevent CPU 0 Modules linked in: cifs nfsd lockd nfs_acl exportfs rpcsec_gss_krb5 auth_rpcgss des_generic sunrpc ipv6 microcode i2c_piix4 i2c_core virtio_net joydev virtio_balloon virtio_blk virtio_pci virtio_ring virtio [last unloaded: mperf]Pid: 1542, comm: mount.cifs Not tainted 2.6.35-0.2.rc3.git0.fc14.x86_64 #1 /
RIP: 0010:[<ffffffff8123728c>] [<ffffffff8123728c>] strchr+0x14/0x1dRSP: 0018:ffff880039a65bd8 EFLAGS: 00010246
RAX:7365735f626d735fRBX: 0000000000000000 RCX:ffff88003cb4d041
RDX:ffff880039a65c6dRSI: 0000000000000025 RDI:7365735f626d735f
RBP:ffff880039a65bd8R08:000000000000002cR09:000000000000002c
R10:00000000000080d0R11:ffffffff8113bc6cR12:ffff88003cb4d041
R13:ffffffffa0219d40R14: 0000000000000000 R15:7365735f626d735f
FS: 00007f1fbcba6720(0000) GS:ffff880004600000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0:000000008005003b
CR2:0000000001a31818CR3:000000003a287000CR4:00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6:00000000ffff0ff0DR7: 0000000000000400 Process mount.cifs (pid: 1542, threadinfoffff880039a64000, taskffff880039adc8a0)Stack: ffff880039a65c48 ffffffff8123b1ee ffff88003a18b990 ffff880039a65cd8 <0> ffff88003cb4d041 ffffffff8111cd42 ffffffffa0202f86 7365735f626d735f <0> ffff88003997de30 ffff88003997de30 ffff88003cc94840 00000000ffffffff Call Trace: [<ffffffff8123b1ee>] match_token+0x4b/0x1a8 [<ffffffff8111cd42>] ? __kmalloc+0x17c/0x18e [<ffffffffa0202f86>] ? cifs_mount+0x639/0x1737 [cifs] [<ffffffffa0202c11>] cifs_mount+0x2c4/0x1737 [cifs] [<ffffffffa01f5aa4>] ? cifs_get_sb+0x110/0x2e4 [cifs] [<ffffffffa01f5b00>] cifs_get_sb+0x16c/0x2e4 [cifs] [<ffffffff8112c946>] vfs_kern_mount+0xbd/0x19b [<ffffffff8112ca8c>] do_kern_mount+0x4d/0xed [<ffffffff8114368a>] do_mount+0x776/0x7ed [<ffffffff811128aa>] ? alloc_pages_current+0xa7/0xca [<ffffffff81143789>] sys_mount+0x88/0xc2 [<ffffffff81009c32>] system_call_fastpath+0x16/0x1b Code: 14 84 c0 74 0e 48 ff c7 48 ff c6 48 ff ca 48 85 d2 75 e1 31 c0 c9 c3 55 48 89 f8 48 89 e5 eb 0b 84 d2 75 04 31 c0 eb 0a 48 ff c0 <8a> 10 40 38 f2 75 ee c9 c3 55 48 89 f8 48 89 e5 eb 03 48 ff c0 RIP [<ffffffff8123728c>] strchr+0x14/0x1d RSP <ffff880039a65bd8> ---[ end trace 50d173d44b64b1d9 ]---It's crashing in this
match_token()call:gdb) list *(cifs_mount+0x2c4)
0xdcf7is incifs_mount(fs/cifs/connect.c:1094).
1089 while ((data =strsep(&options, separator)) != NULL) { 1090 if (!*data)
1091 continue;
1092 if ((value =strchr(data, '=')) != NULL) 1093 *value++ = '\0';
1094 switch (match_token(data, cifs_mount_options, args)) { 1095 caseOpt_user_xattr:
1096 vol->no_xattr = 0;
1097 break;
1098 caseOpt_nouser_xattr:
(gdb) quit--
Jeff Layton <[email protected]>
Signature · 3 lines
Thanks, Steve
Quoted 11 lines · Steve French
I don't mind reviewing this, but it does appear to change behaviour significantly from existing code. Does this fix a reported bug?
The linux cifs kernel driver, like some other network clients, allows partial option matching to ease usability for users of other platforms (e.g. "pass" or "passwd" or "password" are intentionally all accepted since we match on the first four bytes of that keyword). Is there a way to get that to work with your patchset. I worry that some users will be confused that their mount options won't work if this is taken.
Unfortunately, that sometimes screws us up a bit on the userland side. (ref : http://patchwork.ozlabs.org/patch/54454/).
Some background: the original reason for this patch was to make it consistent with the NFS parsing code (and a few other file systems parsing). This was on the tail end of me cleaning up the cifs-utils parsing because I thought it was a bit hard to read and scaled poorly for 80+ options. That was the original intent (also, in my free time I'm kind of looking for a trophy patch to the kernel, it doesn't hurt the resume. :))
Does this make sense? Does anyone else find the else/if tree a bit much to wade through? Especially at the security parsing where you're a few level deep.
Quoted 12 lines · Scott Lovenberg
Quoted 11 lines · Steve French
I don't mind reviewing this, but it does appear to change behaviour significantly from existing code. Does this fix a reported bug?
The linux cifs kernel driver, like some other network clients, allows partial option matching to ease usability for users of other platforms (e.g. "pass" or "passwd" or "password" are intentionally all accepted since we match on the first four bytes of that keyword). Is there a way to get that to work with your patchset. I worry that some users will be confused that their mount options won't work if this is taken.
Quoted 5 lines
Unfortunately, that sometimes screws us up a bit on the userland side. (ref : http://patchwork.ozlabs.org/patch/54454/).
Some background: the original reason for this patch was to make it consistent with the NFS parsing code (and a few other file systems parsing). This was on the tail end of me cleaning up the cifs-utils parsing because I thought it was a bit hard to read and scaled poorly for 80+ options. That was the original intent (also, in my free time I'm kind of looking for a trophy patch to the kernel, it doesn't hurt the resume. :))
Does this make sense? Does anyone else find the else/if tree a bit much to wade through? Especially at the security parsing where you're a few level deep.
P.S. - I originally had a patch that matches the parsing from the cifs-utils that is a somewhere-in-between for achieving both goals (readability, functionality). Essentially, I just moved the option parsing to a function that contained the else/if tree. I can dig it up if anyone is interested.
----- Original Message -----
Quoted 12 lines
I don't mind reviewing this, but it does appear to change behaviour significantly from existing code. Does this fix a reported bug?
The linux cifs kernel driver, like some other network clients, allows partial option matching to ease usability for users of other platforms (e.g. "pass" or "passwd" or "password" are intentionally all accepted since we match on the first four bytes of that keyword). Is there a way to get that to work with your patchset. I worry that some users will be confused that their mount options won't work if this is taken.
The reason I was looking at this code was because I was helping Jeff include in the sloppy mount option for cifs. The current if/elseif block is difficult to read through. There are also hidden gotchas like ordering the if blocks correctly if in case a mount option is also a substring in a different mount option. The decision to use the standard token parser was simply for consistency and to make the code easier to understand.
Multiple versions of mount options can be accepted for the same mount option. For example, in the patch sent earlier, for the password, we accept the following mount options to pass the password.
+ { Opt_pass, "pass=%s" },
+ { Opt_pass, "password=%s" },
So the user can use pass or password and they will both be accepted as the mount option to set the password. We can add more options if I have missed any.
The only difference I see is that the options matching is case sensitive and therefore will reject upper case mount options.
Also, in my opinion the number of mount options is large at the moment and we should consider deprecating a few of the mount options.
Sachin Prabhu
Quoted 111 lines
Quoted 94 lines · Jeff Layton
Quoted 6 lines · On Wed, 14 Mar 2012 14:17:26 -0400 (EDT) Sachin Prabhu…
Thanks Scott,
Steve/Jeff, can I get your comments on this patch please.
Sachin Prabhu
Does it address the oops that we saw with Scott's patch? Here's what I
wrote when I hit that oops before.----------------------------[snip]---------------------------
Finally got around to trying this out and I get the following oops when
mounting a share with these options:sec=krb5i,multises,noauto
general protection fault: 0000 [#1] SMP last sysfs file: /sys/devices/virtual/bdi/cifs-1/uevent CPU 0 Modules linked in: cifs nfsd lockd nfs_acl exportfs rpcsec_gss_krb5
auth_rpcgssdes_genericsunrpc ipv6 microcodei2c_piix4i2c_corevirtio_netjoydevvirtio_balloonvirtio_blkvirtio_pcivirtio_ringvirtio [last unloaded: mperf]Pid: 1542, comm: mount.cifs Not tainted
2.6.35-0.2.rc3.git0.fc14.x86_64 #1 /RIP: 0010:[<ffffffff8123728c>] [<ffffffff8123728c>] strchr+0x14/0x1dRSP: 0018:ffff880039a65bd8 EFLAGS: 00010246
RAX:7365735f626d735fRBX: 0000000000000000 RCX:ffff88003cb4d041
RDX:ffff880039a65c6dRSI: 0000000000000025 RDI:7365735f626d735f
RBP:ffff880039a65bd8R08:000000000000002cR09:000000000000002c
R10:00000000000080d0R11:ffffffff8113bc6cR12:ffff88003cb4d041
R13:ffffffffa0219d40R14: 0000000000000000 R15:7365735f626d735f
FS: 00007f1fbcba6720(0000) GS:ffff880004600000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0:000000008005003b
CR2:0000000001a31818CR3:000000003a287000CR4:00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6:00000000ffff0ff0DR7: 0000000000000400 Process mount.cifs (pid: 1542, threadinfoffff880039a64000, taskffff880039adc8a0)Stack:ffff880039a65c48
ffffffff8123b1eeffff88003a18b990ffff880039a65cd8
<0>ffff88003cb4d041ffffffff8111cd42ffffffffa0202f867365735f626d735f
<0>ffff88003997de30ffff88003997de30ffff88003cc9484000000000ffffffffCall Trace: [<ffffffff8123b1ee>] match_token+0x4b/0x1a8 [<ffffffff8111cd42>] ? __kmalloc+0x17c/0x18e [<ffffffffa0202f86>] ? cifs_mount+0x639/0x1737 [cifs] [<ffffffffa0202c11>] cifs_mount+0x2c4/0x1737 [cifs] [<ffffffffa01f5aa4>] ? cifs_get_sb+0x110/0x2e4 [cifs] [<ffffffffa01f5b00>] cifs_get_sb+0x16c/0x2e4 [cifs] [<ffffffff8112c946>] vfs_kern_mount+0xbd/0x19b [<ffffffff8112ca8c>] do_kern_mount+0x4d/0xed [<ffffffff8114368a>] do_mount+0x776/0x7ed [<ffffffff811128aa>] ? alloc_pages_current+0xa7/0xca [<ffffffff81143789>] sys_mount+0x88/0xc2 [<ffffffff81009c32>] system_call_fastpath+0x16/0x1b Code: 14 84 c0 74 0e 48 ff c7 48 ff c6 48 ff ca 48 85 d2 75 e1 31c0 c9 c3 55 48 89 f8 48 89 e5 eb 0b 84 d2 75 04 31 c0 eb 0a 48 ff c0 <8a> 10 40 38 f2 75 ee c9 c3 55 48 89 f8 48 89 e5 eb 03 48 ff c0
RIP [<ffffffff8123728c>]strchr+0x14/0x1d
RSP <ffff880039a65bd8>---[ end trace 50d173d44b64b1d9 ]---It's crashing in this
match_token()call:gdb) list *(cifs_mount+0x2c4)
0xdcf7is incifs_mount(fs/cifs/connect.c:1094).
1089 while ((data =strsep(&options, separator)) != NULL) {
1090 if (!*data)
1091 continue;
1092 if ((value =strchr(data, '=')) != NULL) 1093 *value++ = '\0';
1094 switch (match_token(data, cifs_mount_options, args)) {
1095 caseOpt_user_xattr:
1096 vol->no_xattr = 0; 1097 break;
1098 caseOpt_nouser_xattr:
(gdb) quitQuoted 2 lines
--
Jeff Layton <[email protected]>--
Thanks,Steve
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 21 lines · Sachin Prabhu
----- Original Message -----
Quoted 12 lines
I don't mind reviewing this, but it does appear to change behaviour significantly from existing code. Does this fix a reported bug?
The linux cifs kernel driver, like some other network clients, allows partial option matching to ease usability for users of other platforms (e.g. "pass" or "passwd" or "password" are intentionally all accepted since we match on the first four bytes of that keyword). Is there a way to get that to work with your patchset. I worry that some users will be confused that their mount options won't work if this is taken.
The reason I was looking at this code was because I was helping Jeff include in the sloppy mount option for cifs. The current if/elseif block is difficult to read through. There are also hidden gotchas like ordering the if blocks correctly if in case a mount option is also a substring in a different mount option. The decision to use the standard token parser was simply for consistency and to make the code easier to understand.
Multiple versions of mount options can be accepted for the same mount option. For example, in the patch sent earlier, for the password, we accept the following mount options to pass the password.
(quoted diff) +2
-0+ { Opt_pass, "pass=%s" }, + { Opt_pass, "password=%s" },
Quoted 9 lines
So the user can use pass or password and they will both be accepted as the mount option to set the password. We can add more options if I have missed any.
The only difference I see is that the options matching is case sensitive and therefore will reject upper case mount options.
Also, in my opinion the number of mount options is large at the moment and we should consider deprecating a few of the mount options.
Sachin Prabhu
Would this patchset be a reasonable compromise? This is the one I was talking about in my last email. http://samba.2283325.n4.nabble.com/Add-token-parsing-for-kernel-CIFS-mount-options-td2517375.html
Also, some mount options are synonyms for other mount options, they can be combined.
Which were you thinking about deprecating? RHEL/SLED probably aren't going to like shipping a kernel with deprecated mount options. That's more of a political problem, but a problem nonetheless.
Quoted 5 lines · Jeff Layton
Quoted 2 lines · On Wed, 14 Mar 2012 14:17:26 -0400 (EDT) Sachin Prabhu…
Thanks Scott,
Quoted 8 lines
Quoted 4 lines
Steve/Jeff, can I get your comments on this patch please.
Sachin Prabhu
Does it address the oops that we saw with Scott's patch? Here's what I wrote when I hit that oops before.
Jeff,
The patch here was a complete re-write. I have tested it with similar mount options on my local system and it didn't crash.
Sachin Prabhu
Quoted 64 lines
----------------------------[snip]---------------------------
Finally got around to trying this out and I get the following oops when mounting a share with these options:
sec=krb5i,multises,noauto
general protection fault: 0000 [#1] SMP last sysfs file: /sys/devices/virtual/bdi/cifs-1/uevent CPU 0 Modules linked in: cifs nfsd lockd nfs_acl exportfs rpcsec_gss_krb5 auth_rpcgss des_generic sunrpc ipv6 microcode i2c_piix4 i2c_core virtio_net joydev virtio_balloon virtio_blk virtio_pci virtio_ring virtio [last unloaded: mperf]Pid: 1542, comm: mount.cifs Not tainted 2.6.35-0.2.rc3.git0.fc14.x86_64 #1 /
RIP: 0010:[<ffffffff8123728c>] [<ffffffff8123728c>] strchr+0x14/0x1d RSP: 0018:ffff880039a65bd8 EFLAGS: 00010246 RAX: 7365735f626d735f RBX: 0000000000000000 RCX: ffff88003cb4d041 RDX: ffff880039a65c6d RSI: 0000000000000025 RDI: 7365735f626d735f RBP: ffff880039a65bd8 R08: 000000000000002c R09: 000000000000002c R10: 00000000000080d0 R11: ffffffff8113bc6c R12: ffff88003cb4d041 R13: ffffffffa0219d40 R14: 0000000000000000 R15: 7365735f626d735f FS: 00007f1fbcba6720(0000) GS:ffff880004600000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000001a31818 CR3: 000000003a287000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process mount.cifs (pid: 1542, threadinfo ffff880039a64000, task ffff880039adc8a0) Stack: ffff880039a65c48 ffffffff8123b1ee ffff88003a18b990 ffff880039a65cd8 <0> ffff88003cb4d041 ffffffff8111cd42 ffffffffa0202f86 7365735f626d735f <0> ffff88003997de30 ffff88003997de30 ffff88003cc94840 00000000ffffffff Call Trace: [<ffffffff8123b1ee>] match_token+0x4b/0x1a8 [<ffffffff8111cd42>] ? __kmalloc+0x17c/0x18e [<ffffffffa0202f86>] ? cifs_mount+0x639/0x1737 [cifs] [<ffffffffa0202c11>] cifs_mount+0x2c4/0x1737 [cifs] [<ffffffffa01f5aa4>] ? cifs_get_sb+0x110/0x2e4 [cifs] [<ffffffffa01f5b00>] cifs_get_sb+0x16c/0x2e4 [cifs] [<ffffffff8112c946>] vfs_kern_mount+0xbd/0x19b [<ffffffff8112ca8c>] do_kern_mount+0x4d/0xed [<ffffffff8114368a>] do_mount+0x776/0x7ed [<ffffffff811128aa>] ? alloc_pages_current+0xa7/0xca [<ffffffff81143789>] sys_mount+0x88/0xc2 [<ffffffff81009c32>] system_call_fastpath+0x16/0x1b Code: 14 84 c0 74 0e 48 ff c7 48 ff c6 48 ff ca 48 85 d2 75 e1 31 c0 c9 c3 55 48 89 f8 48 89 e5 eb 0b 84 d2 75 04 31 c0 eb 0a 48 ff c0 <8a> 10 40 38 f2 75 ee c9 c3 55 48 89 f8 48 89 e5 eb 03 48 ff c0 RIP [<ffffffff8123728c>] strchr+0x14/0x1d RSP <ffff880039a65bd8> ---[ end trace 50d173d44b64b1d9 ]---It's crashing in this
match_token()call:gdb) list *(cifs_mount+0x2c4)
0xdcf7is incifs_mount(fs/cifs/connect.c:1094).
1089 while ((data =strsep(&options, separator)) != NULL) {
1090 if (!*data)
1091 continue;
1092 if ((value =strchr(data, '=')) != NULL)
1093 *value++ = '\0';
1094 switch (match_token(data, cifs_mount_options, args)) {
1095 caseOpt_user_xattr:
1096vol->no_xattr= 0;
1097 break;
1098 caseOpt_nouser_xattr:
(gdb) quit
Quoted 32 lines · Scott Lovenberg
Quoted 21 lines · Sachin Prabhu
----- Original Message -----
Quoted 12 lines
I don't mind reviewing this, but it does appear to change behaviour significantly from existing code. Does this fix a reported bug?
The linux cifs kernel driver, like some other network clients, allows partial option matching to ease usability for users of other platforms (e.g. "pass" or "passwd" or "password" are intentionally all accepted since we match on the first four bytes of that keyword). Is there a way to get that to work with your patchset. I worry that some users will be confused that their mount options won't work if this is taken.
The reason I was looking at this code was because I was helping Jeff include in the sloppy mount option for cifs. The current if/elseif block is difficult to read through. There are also hidden gotchas like ordering the if blocks correctly if in case a mount option is also a substring in a different mount option. The decision to use the standard token parser was simply for consistency and to make the code easier to understand.
Multiple versions of mount options can be accepted for the same mount option. For example, in the patch sent earlier, for the password, we accept the following mount options to pass the password.
(quoted diff) +2
-0+ { Opt_pass, "pass=%s" }, + { Opt_pass, "password=%s" },Quoted 9 lines
So the user can use pass or password and they will both be accepted as the mount option to set the password. We can add more options if I have missed any.
The only difference I see is that the options matching is case sensitive and therefore will reject upper case mount options.
Also, in my opinion the number of mount options is large at the moment and we should consider deprecating a few of the mount options.
Sachin Prabhu
Quoted 6 lines
Would this patchset be a reasonable compromise? This is the one I was talking about in my last email.
http://samba.2283325.n4.nabble.com/Add-token-parsing-for-kernel-CIFS-mount-options-td2517375.htmlAlso, some mount options are synonyms for other mount options, they can be combined.
That patch will definitely help when it comes to cleaning up the code to make it easier to read. However this will still result in cifs using its own parser instead of relying on the default one.
Also we will still need to carefully order the if conditions to prevent cases where one mount option is a substring of the another causing false positives.
ex: In the current parser, 'nouser_xattr' must be checked for before we check for 'user' mount option.
Quoted 3 lines
Which were you thinking about deprecating? RHEL/SLED probably aren't going to like shipping a kernel with deprecated mount options. That's more of a political problem, but a problem nonetheless.
I would start by reducing the synonyms.
For example, dom, domain, workgroup all allow the user to set the workgroup. ip & addr allow the user to set the ip addresses.
Sachin Prabhu
Quoted 22 lines · Sachin Prabhu
----- Original Message -----
Quoted 12 lines
I don't mind reviewing this, but it does appear to change behaviour significantly from existing code. Does this fix a reported bug?
The linux cifs kernel driver, like some other network clients, allows partial option matching to ease usability for users of other platforms (e.g. "pass" or "passwd" or "password" are intentionally all accepted since we match on the first four bytes of that keyword). Is there a way to get that to work with your patchset. I worry that some users will be confused that their mount options won't work if this is taken.
The reason I was looking at this code was because I was helping Jeff include in the sloppy mount option for cifs. The current if/elseif block is difficult to read through. There are also hidden gotchas like ordering the if blocks correctly if in case a mount option is also a substring in a different mount option. The decision to use the standard token parser was simply for consistency and to make the code easier to understand.
Multiple versions of mount options can be accepted for the same mount option. For example, in the patch sent earlier, for the password, we accept the following mount options to pass the password.
+ {
Opt_pass, "pass=%s" },
+ {Opt_pass, "password=%s" },
Quoted 6 lines
So the user can use pass or password and they will both be accepted as the mount option to set the password. We can add more options if I have missed any.
The only difference I see is that the options matching is case sensitive and therefore will reject upper case mount options.
Also, in my opinion the number of mount options is large at the moment and we should consider deprecating a few of the mount options.
We should have far fewer mount options with SMB2, so that will help the usability.
With SMB2 there is far less need for the varoius mount options that deal with compatibility to broken old servers or to workaround protocol limitations,
and certain other features in SMB2 would be enabled by default and no point in allowing them to be disabled unless we run into badly broken smb2 servers.
Signature · 3 lines
Thanks, Steve
Quoted 3 lines · On Wed, 14 Mar 2012 14:30:23 -0500 Steve French…
I don't mind reviewing this, but it does appear to change behaviour significantly from existing code. Does this fix a reported bug?
Technically no, but it's horribly ugly code and that makes it difficult to maintain. Look . It's long been a pain point for cifs.ko maintenance. Now that we're looking at SMB2 code, I for one am keen on eliminating that pain now before it's a similar problem there.
Quoted 9 lines
The linux cifs kernel driver, like some other network clients, allows partial option matching to ease usability for users of other platforms (e.g. "pass" or "passwd" or "password" are intentionally all accepted since we match on the first four bytes of that keyword). Is there a way to get that to work with your patchset. I worry that some users will be confused that their mount options won't work if this is taken.
I consider the existing behavior a bug (though a minor one). The question is not so much those, but the fact that the existing parser also accepts stuff like "passfoobarbaz=".
We can certainly make the standard token parser accept common and *advertised* mount option abbreviations. If it breaks someone who's using "passfoobarbz=" then I personally don't care very much. We've never claimed that that option would work, and thus if it breaks then I wouldn't consider it a bug.
Signature · 1 line
Jeff Layton <[email protected]>
Quoted 1,479 lines · On Fri, 09 Mar 2012 15:33:17 +0000 Sachin Prabhu…
Use the standard token parser instead of the long if confidtion to parse cifs mount options.
This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.
Signed-off-by Sachin Prabhu <[email protected]>fs/cifs/connect.c +805
-524@@ -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,187 @@ 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, + + 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_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);@@ -924,13 +1107,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 ;@@ -938,9 +1187,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 @@ -979,6 +1232,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 ];@@ -991,609 +1245,636 @@ 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; + } + vol->nullauth =0 ; +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
fs/cifs/connect.c cifs_parse_mount_options(const char *mountdata, const char *devname, · line 1913
Quoted 10 lines
fs/cifs/connect.c +3
-0@@ -1623,7 +1904,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 ; }
Looks good. I suggest that Steve merge this early for 3.4 so it has maximum soak time.
Quoted 12 lines · On Fri, 09 Mar 2012 15:33:17 +0000 Sachin Prabhu…
Use the standard token parser instead of the long if confidtion to parse cifs mount options.
This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.
Signed-off-by Sachin Prabhu <[email protected]>
In testing this today, I found a problem. I tried to mount up a share with sec=none as the options. With that, I got this error:
CIFS: Unknown mount option pass=
The problem is that the mount.cifs helper will pass a blank "pass=" option to the kernel. It seems like the standard option parser doesn't have a way to allow you to specify an optional argument. That may need to be added in order for this to work.
Signature · 1 line
Jeff Layton <[email protected]>
Quoted 20 lines · Jeff Layton
Quoted 12 lines · On Fri, 09 Mar 2012 15:33:17 +0000 Sachin Prabhu…
Use the standard token parser instead of the long if confidtion to parse cifs mount options.
This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.
Signed-off-by Sachin Prabhu <[email protected]>In testing this today, I found a problem. I tried to mount up a share with sec=none as the options. With that, I got this error:
Quoted 6 lines
CIFS: Unknown mount option pass=
The problem is that the mount.cifs helper will pass a blank "pass=" option to the kernel. It seems like the standard option parser doesn't have a way to allow you to specify an optional argument. That may need to be added in order for this to work.
We could use it in this manner.
----
Allow mount option pass to be a blank value.
When using sec=none, the mount.cifs helper will pass a blank 'pass=' mount option. This should be handled by the parser.
--- fs/cifs/connect.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
fs/cifs/connect.c +7 -0
@@ -107,6 +107,9 @@ enum {/* Mount options to be ignored */ Opt_ignore, +/* Options which could be blank */ + Opt_blank_pass, + Opt_err };
@@ -180,6 +183,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_user, "user=%s" }, { Opt_user, "username=%s" }, + { Opt_blank_pass, "pass=" }, { Opt_pass, "pass=%s" }, { Opt_pass, "password=%s" }, { Opt_ip, "ip=%s" },
@@ -1546,6 +1550,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->nullauth =0 ;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
Signature · 1 line
1.7.7.6
Quoted 63 lines · Sachin Prabhu
Quoted 19 lines · Jeff Layton
Quoted 12 lines · On Fri, 09 Mar 2012 15:33:17 +0000 Sachin…
Use the standard token parser instead of the long if confidtion to parse cifs mount options.
This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.
Signed-off-by Sachin Prabhu<[email protected]>In testing this today, I found a problem. I tried to mount up a share with sec=none as the options. With that, I got this error:
Quoted 6 lines
CIFS: Unknown mount option pass=
The problem is that the mount.cifs helper will pass a blank "pass=" option to the kernel. It seems like the standard option parser doesn't have a way to allow you to specify an optional argument. That may need to be added in order for this to work.
We could use it in this manner.
----
Allow mount option pass to be a blank value.When using sec=none, the mount.cifs helper will pass a blank 'pass=' mount option. This should be handled by the parser.
Signed-off-by Sachin Prabhu<[email protected]>--- fs/cifs/connect.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)fs/cifs/connect.c +4
-0@@ -107,6 +107,9 @@ enum {/* Mount options to be ignored */ Opt_ignore, +/* Options which could be blank */ + Opt_blank_pass, + Opt_err };@@ -180,6 +183,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_user, "user=%s" }, { Opt_user, "username=%s" }, + { Opt_blank_pass, "pass=" }, { Opt_pass, "pass=%s" }, { Opt_pass, "password=%s" }, { Opt_ip, "ip=%s" },
fs/cifs/connect.c cifs_parse_mount_options(const char *mountdata, const char *devname, · line 1558
Quoted 9 lines
fs/cifs/connect.c +3
-0@@ -1546,6 +1550,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->nullauth =0 ;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
Are there any other options that are implicitly set? Or, more generally, will this solution scale?
Quoted 68 lines · Scott Lovenberg
Quoted 67 lines · Sachin Prabhu
Quoted 19 lines · Jeff Layton
Quoted 12 lines · On Fri, 09 Mar 2012 15:33:17 +0000 Sachin…
Use the standard token parser instead of the long if confidtion to parse cifs mount options.
This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.
Signed-off-by Sachin Prabhu<[email protected]>In testing this today, I found a problem. I tried to mount up a share with sec=none as the options. With that, I got this error:
Quoted 6 lines
CIFS: Unknown mount option pass=
The problem is that the mount.cifs helper will pass a blank "pass=" option to the kernel. It seems like the standard option parser doesn't have a way to allow you to specify an optional argument. That may need to be added in order for this to work.
We could use it in this manner.
----
Allow mount option pass to be a blank value.When using sec=none, the mount.cifs helper will pass a blank 'pass=' mount option. This should be handled by the parser.
Signed-off-by Sachin Prabhu<[email protected]>--- fs/cifs/connect.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)fs/cifs/connect.c +5
-0@@ -107,6 +107,9 @@ enum {/* Mount options to be ignored */ Opt_ignore, +/* Options which could be blank */ + Opt_blank_pass, + Opt_err };@@ -180,6 +183,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_user, "user=%s" }, { Opt_user, "username=%s" }, + { Opt_blank_pass, "pass=" }, { Opt_pass, "pass=%s" }, { Opt_pass, "password=%s" }, { Opt_ip, "ip=%s" },@@ -1546,6 +1550,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->nullauth =0 ;break ; +case Opt_blank_pass:
Quoted 8 lines
fs/cifs/connect.c cifs_parse_mount_options(const char *mountdata, const char *devname, · line 1558
Quoted 5 lines
fs/cifs/connect.c +2
-0+ vol->password =NULL ; +break ;case Opt_pass:/* passwords have to be handled differently * to allow the character used for deliminator Are there any other options that are implicitly set? Or, more generally, will this solution scale?
For a one off case like this, a solution like this is acceptable. If there are more number of such options where we can could pass a blank, we could add some code to make parsing them easier.
I don't see us facing much problems scaling here.
Sachin Prabhu
Quoted 14 lines · Scott Lovenberg
> Are there any other options that are implicitly set? Or, more
> generally, will this solution scale?For a one off case like this, a solution like this is acceptable. If
there are more number of such options where we can could pass a blank,
we could add some code to make parsing them easier.I don't see us facing much problems scaling here.
Quoted 7 lines
Sachin Prabhu
Sorry if this seemed like a silly question, I'm just always curious about coding styles and studying the craft. I realized after I asked how silly it sounded. :)
I am in the same boat. We are all learning here.
Sachin Prabhu
Quoted 65 lines · On Wed, 21 Mar 2012 18:33:07 +0000 Sachin Prabhu…
Quoted 20 lines · Jeff Layton
Quoted 12 lines · On Fri, 09 Mar 2012 15:33:17 +0000 Sachin Prabhu…
Use the standard token parser instead of the long if confidtion to parse cifs mount options.
This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.
Signed-off-by Sachin Prabhu <[email protected]>In testing this today, I found a problem. I tried to mount up a share with sec=none as the options. With that, I got this error:
Quoted 6 lines
CIFS: Unknown mount option pass=
The problem is that the mount.cifs helper will pass a blank "pass=" option to the kernel. It seems like the standard option parser doesn't have a way to allow you to specify an optional argument. That may need to be added in order for this to work.
We could use it in this manner.
----
Allow mount option pass to be a blank value.When using sec=none, the mount.cifs helper will pass a blank 'pass=' mount option. This should be handled by the parser.
Signed-off-by Sachin Prabhu <[email protected]>--- fs/cifs/connect.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)fs/cifs/connect.c +4
-0@@ -107,6 +107,9 @@ enum {/* Mount options to be ignored */ Opt_ignore, +/* Options which could be blank */ + Opt_blank_pass, + Opt_err };@@ -180,6 +183,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_user, "user=%s" }, { Opt_user, "username=%s" }, + { Opt_blank_pass, "pass=" }, { Opt_pass, "pass=%s" }, { Opt_pass, "password=%s" }, { Opt_ip, "ip=%s" },
fs/cifs/connect.c cifs_parse_mount_options(const char *mountdata, const char *devname, · line 1558
Quoted 9 lines
fs/cifs/connect.c +3
-0@@ -1546,6 +1550,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->nullauth =0 ;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
ACK.
Since Steve hasn't committed this yet, care to send a respin of the original? I don't think there are any others that require the ability to handle a blank option, but we can always add that later if needed.
Signature · 1 line
Jeff Layton <[email protected]>
Sachin,
I am a little worried about merge conflicts - am about 1/3 of the way through merging (and reviewing) Pavel's and similarly have started to merge Jeff's patches, so make sure you rebase them on what is in cifs-2.6.git tree on samba.org
Quoted 86 lines · Jeff Layton
Quoted 71 lines · On Wed, 21 Mar 2012 18:33:07 +0000 Sachin Prabhu…
Quoted 20 lines · Jeff Layton
Quoted 12 lines · On Fri, 09 Mar 2012 15:33:17 +0000 Sachin Prabhu…
Use the standard token parser instead of the long if confidtion to parse cifs mount options.
This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.
Signed-off-by Sachin Prabhu <[email protected]>In testing this today, I found a problem. I tried to mount up a share with sec=none as the options. With that, I got this error:
Quoted 6 lines
CIFS: Unknown mount option pass=
The problem is that the mount.cifs helper will pass a blank "pass=" option to the kernel. It seems like the standard option parser doesn't have a way to allow you to specify an optional argument. That may need to be added in order for this to work.
We could use it in this manner.
----
Allow mount option pass to be a blank value.When using sec=none, the mount.cifs helper will pass a blank 'pass=' mount option. This should be handled by the parser.
Signed-off-by Sachin Prabhu <[email protected]>---
fs/cifs/connect.c | 7 +++++++1 files changed, 7 insertions(+), 0 deletions(-)fs/cifs/connect.c +3
-0@@ -107,6 +107,9 @@ enum { /* Mount options to be ignored */ Opt_ignore, + /* Options which could be blank */ + Opt_blank_pass, +
Opt_err
};fs/cifs/connect.c +4
-0@@ -180,6 +183,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_user, "user=%s" }, { Opt_user, "username=%s" }, + { Opt_blank_pass, "pass=" }, { Opt_pass, "pass=%s" }, { Opt_pass, "password=%s" }, { Opt_ip, "ip=%s" },@@ -1546,6 +1550,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->nullauth = 0; break; + case Opt_blank_pass: + vol->password = NULL; + break;Quoted 3 lines
case
Opt_pass:
/* passwords have to be handled differently
* to allow the character used for deliminatorACK.
Since Steve hasn't committed this yet, care to send a respin of the original? I don't think there are any others that require the ability to handle a blank option, but we can always add that later if needed.
--
Jeff Layton <[email protected]>
Signature · 3 lines
Thanks, Steve
Quoted 6 lines · On Wed, 21 Mar 2012 15:33:57 -0500 Steve French…
Sachin,
I am a little worried about merge conflicts - am about 1/3 of the way through merging (and reviewing) Pavel's and similarly have started to merge Jeff's patches, so make sure you rebase them on what is in cifs-2.6.git tree on samba.org
I applied Sachin's patch on top of Pavel's set and mine and it merged just fine...
Quoted 90 lines · Jeff Layton
Quoted 86 lines
Quoted 71 lines · On Wed, 21 Mar 2012 18:33:07 +0000 Sachin Prabhu…
Quoted 20 lines · Jeff Layton
Quoted 12 lines · On Fri, 09 Mar 2012 15:33:17 +0000 Sachin Prabhu…
Use the standard token parser instead of the long if confidtion to parse cifs mount options.
This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.
Signed-off-by Sachin Prabhu <[email protected]>In testing this today, I found a problem. I tried to mount up a share with sec=none as the options. With that, I got this error:
Quoted 6 lines
CIFS: Unknown mount option pass=
The problem is that the mount.cifs helper will pass a blank "pass=" option to the kernel. It seems like the standard option parser doesn't have a way to allow you to specify an optional argument. That may need to be added in order for this to work.
We could use it in this manner.
----
Allow mount option pass to be a blank value.When using sec=none, the mount.cifs helper will pass a blank 'pass=' mount option. This should be handled by the parser.
Signed-off-by Sachin Prabhu <[email protected]>---
fs/cifs/connect.c | 7 +++++++1 files changed, 7 insertions(+), 0 deletions(-)fs/cifs/connect.c +3
-0@@ -107,6 +107,9 @@ enum { /* Mount options to be ignored */ Opt_ignore, + /* Options which could be blank */ + Opt_blank_pass, +
Opt_err
};fs/cifs/connect.c +4
-0@@ -180,6 +183,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_user, "user=%s" }, { Opt_user, "username=%s" }, + { Opt_blank_pass, "pass=" }, { Opt_pass, "pass=%s" }, { Opt_pass, "password=%s" }, { Opt_ip, "ip=%s" },@@ -1546,6 +1550,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->nullauth = 0; break; + case Opt_blank_pass: + vol->password = NULL; + break;Quoted 3 lines
case
Opt_pass:
/* passwords have to be handled differently
* to allow the character used for deliminatorACK.
Since Steve hasn't committed this yet, care to send a respin of the original? I don't think there are any others that require the ability to handle a blank option, but we can always add that later if needed.
--
Jeff Layton <[email protected]>
Signature · 1 line
Jeff Layton <[email protected]>
PATCH v2 1/1 cifs: use standard token parser for mount options
In reply to a message not in the archiveUse 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.
--- fs/cifs/connect.c | 1338 ++++++++++++++++++++++++++++++++--------------------- 1 files changed, 814 insertions(+), 524 deletions(-)
fs/cifs/connect.c +814 -524
@@ -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 ; }
Signature · 1 line
1.7.7.6
Quoted 6 lines · Steve French
Sachin,
I am a little worried about merge conflicts - am about 1/3 of the way through merging (and reviewing) Pavel's and similarly have started to merge Jeff's patches, so make sure you rebase them on what is in cifs-2.6.git tree on samba.org
Done. Version 2 of patch sent to the list along with some bug fixes which Jeff encountered in his testing.
Sachin Prabhu
Quoted 90 lines · Jeff Layton
Quoted 86 lines
Quoted 65 lines · On Wed, 21 Mar 2012 18:33:07 +0000 Sachin Prabhu…
Quoted 20 lines · Jeff Layton
Quoted 12 lines · On Fri, 09 Mar 2012 15:33:17 +0000 Sachin Prabhu…
Use the standard token parser instead of the long if confidtion to parse cifs mount options.
This was first proposed by Scott Lovenberg
http://lists.samba.org/archive/linux-cifs-client/2010-May/006079.htmlMount 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.
Signed-off-by Sachin Prabhu <[email protected]>In testing this today, I found a problem. I tried to mount up a share with sec=none as the options. With that, I got this error:
Quoted 6 lines
CIFS: Unknown mount option pass=
The problem is that the mount.cifs helper will pass a blank "pass=" option to the kernel. It seems like the standard option parser doesn't have a way to allow you to specify an optional argument. That may need to be added in order for this to work.
We could use it in this manner.
----
Allow mount option pass to be a blank value.When using sec=none, the mount.cifs helper will pass a blank 'pass=' mount option. This should be handled by the parser.
Signed-off-by Sachin Prabhu <[email protected]>--- fs/cifs/connect.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)fs/cifs/connect.c +4
-0@@ -107,6 +107,9 @@ enum {/* Mount options to be ignored */ Opt_ignore, +/* Options which could be blank */ + Opt_blank_pass, + Opt_err };@@ -180,6 +183,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_user, "user=%s" }, { Opt_user, "username=%s" }, + { Opt_blank_pass, "pass=" }, { Opt_pass, "pass=%s" }, { Opt_pass, "password=%s" }, { Opt_ip, "ip=%s" },fs/cifs/connect.c cifs_parse_mount_options(const char *mountdata, const char *devname, · line 1558
Quoted 9 lines
fs/cifs/connect.c +3
-0@@ -1546,6 +1550,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->nullauth =0 ;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 ACK.
Since Steve hasn't committed this yet, care to send a respin of the original? I don't think there are any others that require the ability to handle a blank option, but we can always add that later if needed.
--
Jeff Layton <[email protected]>
Quoted 1,492 lines · On Thu, 22 Mar 2012 15:26:47 +0000 Sachin Prabhu…
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.htmlMount 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 setvol->nullauthto 0. This causes a problem when using sec=none while also using a username.Signed-off-by Sachin Prabhu <[email protected]>--- fs/cifs/connect.c | 1338 ++++++++++++++++++++++++++++++++--------------------- 1 files changed, 814 insertions(+), 524 deletions(-)fs/cifs/connect.c +811
-524@@ -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
fs/cifs/connect.c cifs_parse_mount_options(const char *mountdata, const char *devname, · line 1921
Quoted 10 lines
fs/cifs/connect.c +3
-0@@ -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 ; }