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