aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSachin Prabhu <sprabhu@redhat.com>2012-03-23 14:40:56 -0400
committerJeff Layton <jlayton@redhat.com>2012-03-23 14:40:56 -0400
commit8830d7e07a5e38bc47650a7554b7c1cfd49902bf (patch)
tree278232f4b1546137f94c19789f01b6d1e8946507 /fs
parent27ac5755aee0c99b9148ccceccb800270b9e5628 (diff)
cifs: use standard token parser for mount options
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@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/connect.c1338
1 files changed, 814 insertions, 524 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 855d8c08e3a4..3d72218bd962 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -40,6 +40,8 @@
40#include <linux/module.h> 40#include <linux/module.h>
41#include <keys/user-type.h> 41#include <keys/user-type.h>
42#include <net/ipv6.h> 42#include <net/ipv6.h>
43#include <linux/parser.h>
44
43#include "cifspdu.h" 45#include "cifspdu.h"
44#include "cifsglob.h" 46#include "cifsglob.h"
45#include "cifsproto.h" 47#include "cifsproto.h"
@@ -63,6 +65,191 @@ extern mempool_t *cifs_req_poolp;
63#define TLINK_ERROR_EXPIRE (1 * HZ) 65#define TLINK_ERROR_EXPIRE (1 * HZ)
64#define TLINK_IDLE_EXPIRE (600 * HZ) 66#define TLINK_IDLE_EXPIRE (600 * HZ)
65 67
68enum {
69
70 /* Mount options that take no arguments */
71 Opt_user_xattr, Opt_nouser_xattr,
72 Opt_forceuid, Opt_noforceuid,
73 Opt_noblocksend, Opt_noautotune,
74 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
75 Opt_mapchars, Opt_nomapchars, Opt_sfu,
76 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
77 Opt_noposixpaths, Opt_nounix,
78 Opt_nocase,
79 Opt_brl, Opt_nobrl,
80 Opt_forcemandatorylock, Opt_setuids,
81 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
82 Opt_nohard, Opt_nosoft,
83 Opt_nointr, Opt_intr,
84 Opt_nostrictsync, Opt_strictsync,
85 Opt_serverino, Opt_noserverino,
86 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
87 Opt_acl, Opt_noacl, Opt_locallease,
88 Opt_sign, Opt_seal, Opt_direct,
89 Opt_strictcache, Opt_noac,
90 Opt_fsc, Opt_mfsymlinks,
91 Opt_multiuser,
92
93 /* Mount options which take numeric value */
94 Opt_backupuid, Opt_backupgid, Opt_uid,
95 Opt_cruid, Opt_gid, Opt_file_mode,
96 Opt_dirmode, Opt_port,
97 Opt_rsize, Opt_wsize, Opt_actimeo,
98
99 /* Mount options which take string value */
100 Opt_user, Opt_pass, Opt_ip,
101 Opt_unc, Opt_domain,
102 Opt_srcaddr, Opt_prefixpath,
103 Opt_iocharset, Opt_sockopt,
104 Opt_netbiosname, Opt_servern,
105 Opt_ver, Opt_sec,
106
107 /* Mount options to be ignored */
108 Opt_ignore,
109
110 /* Options which could be blank */
111 Opt_blank_pass,
112
113 Opt_err
114};
115
116static const match_table_t cifs_mount_option_tokens = {
117
118 { Opt_user_xattr, "user_xattr" },
119 { Opt_nouser_xattr, "nouser_xattr" },
120 { Opt_forceuid, "forceuid" },
121 { Opt_noforceuid, "noforceuid" },
122 { Opt_noblocksend, "noblocksend" },
123 { Opt_noautotune, "noautotune" },
124 { Opt_hard, "hard" },
125 { Opt_soft, "soft" },
126 { Opt_perm, "perm" },
127 { Opt_noperm, "noperm" },
128 { Opt_mapchars, "mapchars" },
129 { Opt_nomapchars, "nomapchars" },
130 { Opt_sfu, "sfu" },
131 { Opt_nosfu, "nosfu" },
132 { Opt_nodfs, "nodfs" },
133 { Opt_posixpaths, "posixpaths" },
134 { Opt_noposixpaths, "noposixpaths" },
135 { Opt_nounix, "nounix" },
136 { Opt_nounix, "nolinux" },
137 { Opt_nocase, "nocase" },
138 { Opt_nocase, "ignorecase" },
139 { Opt_brl, "brl" },
140 { Opt_nobrl, "nobrl" },
141 { Opt_nobrl, "nolock" },
142 { Opt_forcemandatorylock, "forcemandatorylock" },
143 { Opt_setuids, "setuids" },
144 { Opt_nosetuids, "nosetuids" },
145 { Opt_dynperm, "dynperm" },
146 { Opt_nodynperm, "nodynperm" },
147 { Opt_nohard, "nohard" },
148 { Opt_nosoft, "nosoft" },
149 { Opt_nointr, "nointr" },
150 { Opt_intr, "intr" },
151 { Opt_nostrictsync, "nostrictsync" },
152 { Opt_strictsync, "strictsync" },
153 { Opt_serverino, "serverino" },
154 { Opt_noserverino, "noserverino" },
155 { Opt_rwpidforward, "rwpidforward" },
156 { Opt_cifsacl, "cifsacl" },
157 { Opt_nocifsacl, "nocifsacl" },
158 { Opt_acl, "acl" },
159 { Opt_noacl, "noacl" },
160 { Opt_locallease, "locallease" },
161 { Opt_sign, "sign" },
162 { Opt_seal, "seal" },
163 { Opt_direct, "direct" },
164 { Opt_direct, "forceddirectio" },
165 { Opt_strictcache, "strictcache" },
166 { Opt_noac, "noac" },
167 { Opt_fsc, "fsc" },
168 { Opt_mfsymlinks, "mfsymlinks" },
169 { Opt_multiuser, "multiuser" },
170
171 { Opt_backupuid, "backupuid=%s" },
172 { Opt_backupgid, "backupgid=%s" },
173 { Opt_uid, "uid=%s" },
174 { Opt_cruid, "cruid=%s" },
175 { Opt_gid, "gid=%s" },
176 { Opt_file_mode, "file_mode=%s" },
177 { Opt_dirmode, "dirmode=%s" },
178 { Opt_dirmode, "dir_mode=%s" },
179 { Opt_port, "port=%s" },
180 { Opt_rsize, "rsize=%s" },
181 { Opt_wsize, "wsize=%s" },
182 { Opt_actimeo, "actimeo=%s" },
183
184 { Opt_user, "user=%s" },
185 { Opt_user, "username=%s" },
186 { Opt_blank_pass, "pass=" },
187 { Opt_pass, "pass=%s" },
188 { Opt_pass, "password=%s" },
189 { Opt_ip, "ip=%s" },
190 { Opt_ip, "addr=%s" },
191 { Opt_unc, "unc=%s" },
192 { Opt_unc, "target=%s" },
193 { Opt_unc, "path=%s" },
194 { Opt_domain, "dom=%s" },
195 { Opt_domain, "domain=%s" },
196 { Opt_domain, "workgroup=%s" },
197 { Opt_srcaddr, "srcaddr=%s" },
198 { Opt_prefixpath, "prefixpath=%s" },
199 { Opt_iocharset, "iocharset=%s" },
200 { Opt_sockopt, "sockopt=%s" },
201 { Opt_netbiosname, "netbiosname=%s" },
202 { Opt_servern, "servern=%s" },
203 { Opt_ver, "ver=%s" },
204 { Opt_ver, "vers=%s" },
205 { Opt_ver, "version=%s" },
206 { Opt_sec, "sec=%s" },
207
208 { Opt_ignore, "cred" },
209 { Opt_ignore, "credentials" },
210 { Opt_ignore, "guest" },
211 { Opt_ignore, "rw" },
212 { Opt_ignore, "ro" },
213 { Opt_ignore, "suid" },
214 { Opt_ignore, "nosuid" },
215 { Opt_ignore, "exec" },
216 { Opt_ignore, "noexec" },
217 { Opt_ignore, "nodev" },
218 { Opt_ignore, "noauto" },
219 { Opt_ignore, "dev" },
220 { Opt_ignore, "mand" },
221 { Opt_ignore, "nomand" },
222 { Opt_ignore, "_netdev" },
223
224 { Opt_err, NULL }
225};
226
227enum {
228 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
229 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
230 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i,
231 Opt_sec_nontlm, Opt_sec_lanman,
232 Opt_sec_none,
233
234 Opt_sec_err
235};
236
237static const match_table_t cifs_secflavor_tokens = {
238 { Opt_sec_krb5, "krb5" },
239 { Opt_sec_krb5i, "krb5i" },
240 { Opt_sec_krb5p, "krb5p" },
241 { Opt_sec_ntlmsspi, "ntlmsspi" },
242 { Opt_sec_ntlmssp, "ntlmssp" },
243 { Opt_ntlm, "ntlm" },
244 { Opt_sec_ntlmi, "ntlmi" },
245 { Opt_sec_ntlmv2i, "ntlmv2i" },
246 { Opt_sec_nontlm, "nontlm" },
247 { Opt_sec_lanman, "lanman" },
248 { Opt_sec_none, "none" },
249
250 { Opt_sec_err, NULL }
251};
252
66static int ip_connect(struct TCP_Server_Info *server); 253static int ip_connect(struct TCP_Server_Info *server);
67static int generic_ip_connect(struct TCP_Server_Info *server); 254static int generic_ip_connect(struct TCP_Server_Info *server);
68static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); 255static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
@@ -920,13 +1107,79 @@ extract_hostname(const char *unc)
920 return dst; 1107 return dst;
921} 1108}
922 1109
1110static int get_option_ul(substring_t args[], unsigned long *option)
1111{
1112 int rc;
1113 char *string;
1114
1115 string = match_strdup(args);
1116 if (string == NULL)
1117 return -ENOMEM;
1118 rc = kstrtoul(string, 10, option);
1119 kfree(string);
1120
1121 return rc;
1122}
1123
1124
1125static int cifs_parse_security_flavors(char *value,
1126 struct smb_vol *vol)
1127{
1128
1129 substring_t args[MAX_OPT_ARGS];
1130
1131 switch (match_token(value, cifs_secflavor_tokens, args)) {
1132 case Opt_sec_krb5:
1133 vol->secFlg |= CIFSSEC_MAY_KRB5;
1134 break;
1135 case Opt_sec_krb5i:
1136 vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN;
1137 break;
1138 case Opt_sec_krb5p:
1139 /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */
1140 cERROR(1, "Krb5 cifs privacy not supported");
1141 break;
1142 case Opt_sec_ntlmssp:
1143 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
1144 break;
1145 case Opt_sec_ntlmsspi:
1146 vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN;
1147 break;
1148 case Opt_ntlm:
1149 /* ntlm is default so can be turned off too */
1150 vol->secFlg |= CIFSSEC_MAY_NTLM;
1151 break;
1152 case Opt_sec_ntlmi:
1153 vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN;
1154 break;
1155 case Opt_sec_nontlm:
1156 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1157 break;
1158 case Opt_sec_ntlmv2i:
1159 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN;
1160 break;
1161#ifdef CONFIG_CIFS_WEAK_PW_HASH
1162 case Opt_sec_lanman:
1163 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1164 break;
1165#endif
1166 case Opt_sec_none:
1167 vol->nullauth = 1;
1168 break;
1169 default:
1170 cERROR(1, "bad security option: %s", value);
1171 return 1;
1172 }
1173
1174 return 0;
1175}
1176
923static int 1177static int
924cifs_parse_mount_options(const char *mountdata, const char *devname, 1178cifs_parse_mount_options(const char *mountdata, const char *devname,
925 struct smb_vol *vol) 1179 struct smb_vol *vol)
926{ 1180{
927 char *value, *data, *end; 1181 char *data, *end;
928 char *mountdata_copy = NULL, *options; 1182 char *mountdata_copy = NULL, *options;
929 int err;
930 unsigned int temp_len, i, j; 1183 unsigned int temp_len, i, j;
931 char separator[2]; 1184 char separator[2];
932 short int override_uid = -1; 1185 short int override_uid = -1;
@@ -934,9 +1187,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
934 bool uid_specified = false; 1187 bool uid_specified = false;
935 bool gid_specified = false; 1188 bool gid_specified = false;
936 char *nodename = utsname()->nodename; 1189 char *nodename = utsname()->nodename;
1190 char *string = NULL;
1191 char *tmp_end, *value;
1192 char delim;
937 1193
938 separator[0] = ','; 1194 separator[0] = ',';
939 separator[1] = 0; 1195 separator[1] = 0;
1196 delim = separator[0];
940 1197
941 /* 1198 /*
942 * does not have to be perfect mapping since field is 1199 * does not have to be perfect mapping since field is
@@ -975,6 +1232,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
975 1232
976 options = mountdata_copy; 1233 options = mountdata_copy;
977 end = options + strlen(options); 1234 end = options + strlen(options);
1235
978 if (strncmp(options, "sep=", 4) == 0) { 1236 if (strncmp(options, "sep=", 4) == 0) {
979 if (options[4] != 0) { 1237 if (options[4] != 0) {
980 separator[0] = options[4]; 1238 separator[0] = options[4];
@@ -987,609 +1245,638 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
987 vol->backupgid_specified = false; /* no backup intent for a group */ 1245 vol->backupgid_specified = false; /* no backup intent for a group */
988 1246
989 while ((data = strsep(&options, separator)) != NULL) { 1247 while ((data = strsep(&options, separator)) != NULL) {
1248 substring_t args[MAX_OPT_ARGS];
1249 unsigned long option;
1250 int token;
1251
990 if (!*data) 1252 if (!*data)
991 continue; 1253 continue;
992 if ((value = strchr(data, '=')) != NULL)
993 *value++ = '\0';
994 1254
995 /* Have to parse this before we parse for "user" */ 1255 token = match_token(data, cifs_mount_option_tokens, args);
996 if (strnicmp(data, "user_xattr", 10) == 0) { 1256
1257 switch (token) {
1258
1259 /* Ingnore the following */
1260 case Opt_ignore:
1261 break;
1262
1263 /* Boolean values */
1264 case Opt_user_xattr:
997 vol->no_xattr = 0; 1265 vol->no_xattr = 0;
998 } else if (strnicmp(data, "nouser_xattr", 12) == 0) { 1266 break;
1267 case Opt_nouser_xattr:
999 vol->no_xattr = 1; 1268 vol->no_xattr = 1;
1000 } else if (strnicmp(data, "user", 4) == 0) { 1269 break;
1001 if (!value) { 1270 case Opt_forceuid:
1002 printk(KERN_WARNING
1003 "CIFS: invalid or missing username\n");
1004 goto cifs_parse_mount_err;
1005 } else if (!*value) {
1006 /* null user, ie anonymous, authentication */
1007 vol->nullauth = 1;
1008 }
1009 if (strnlen(value, MAX_USERNAME_SIZE) <
1010 MAX_USERNAME_SIZE) {
1011 vol->username = kstrdup(value, GFP_KERNEL);
1012 if (!vol->username) {
1013 printk(KERN_WARNING "CIFS: no memory "
1014 "for username\n");
1015 goto cifs_parse_mount_err;
1016 }
1017 } else {
1018 printk(KERN_WARNING "CIFS: username too long\n");
1019 goto cifs_parse_mount_err;
1020 }
1021 } else if (strnicmp(data, "pass", 4) == 0) {
1022 if (!value) {
1023 vol->password = NULL;
1024 continue;
1025 } else if (value[0] == 0) {
1026 /* check if string begins with double comma
1027 since that would mean the password really
1028 does start with a comma, and would not
1029 indicate an empty string */
1030 if (value[1] != separator[0]) {
1031 vol->password = NULL;
1032 continue;
1033 }
1034 }
1035 temp_len = strlen(value);
1036 /* removed password length check, NTLM passwords
1037 can be arbitrarily long */
1038
1039 /* if comma in password, the string will be
1040 prematurely null terminated. Commas in password are
1041 specified across the cifs mount interface by a double
1042 comma ie ,, and a comma used as in other cases ie ','
1043 as a parameter delimiter/separator is single and due
1044 to the strsep above is temporarily zeroed. */
1045
1046 /* NB: password legally can have multiple commas and
1047 the only illegal character in a password is null */
1048
1049 if ((value[temp_len] == 0) &&
1050 (value + temp_len < end) &&
1051 (value[temp_len+1] == separator[0])) {
1052 /* reinsert comma */
1053 value[temp_len] = separator[0];
1054 temp_len += 2; /* move after second comma */
1055 while (value[temp_len] != 0) {
1056 if (value[temp_len] == separator[0]) {
1057 if (value[temp_len+1] ==
1058 separator[0]) {
1059 /* skip second comma */
1060 temp_len++;
1061 } else {
1062 /* single comma indicating start
1063 of next parm */
1064 break;
1065 }
1066 }
1067 temp_len++;
1068 }
1069 if (value[temp_len] == 0) {
1070 options = NULL;
1071 } else {
1072 value[temp_len] = 0;
1073 /* point option to start of next parm */
1074 options = value + temp_len + 1;
1075 }
1076 /* go from value to value + temp_len condensing
1077 double commas to singles. Note that this ends up
1078 allocating a few bytes too many, which is ok */
1079 vol->password = kzalloc(temp_len, GFP_KERNEL);
1080 if (vol->password == NULL) {
1081 printk(KERN_WARNING "CIFS: no memory "
1082 "for password\n");
1083 goto cifs_parse_mount_err;
1084 }
1085 for (i = 0, j = 0; i < temp_len; i++, j++) {
1086 vol->password[j] = value[i];
1087 if (value[i] == separator[0]
1088 && value[i+1] == separator[0]) {
1089 /* skip second comma */
1090 i++;
1091 }
1092 }
1093 vol->password[j] = 0;
1094 } else {
1095 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1096 if (vol->password == NULL) {
1097 printk(KERN_WARNING "CIFS: no memory "
1098 "for password\n");
1099 goto cifs_parse_mount_err;
1100 }
1101 strcpy(vol->password, value);
1102 }
1103 } else if (!strnicmp(data, "ip", 2) ||
1104 !strnicmp(data, "addr", 4)) {
1105 if (!value || !*value) {
1106 vol->UNCip = NULL;
1107 } else if (strnlen(value, INET6_ADDRSTRLEN) <
1108 INET6_ADDRSTRLEN) {
1109 vol->UNCip = kstrdup(value, GFP_KERNEL);
1110 if (!vol->UNCip) {
1111 printk(KERN_WARNING "CIFS: no memory "
1112 "for UNC IP\n");
1113 goto cifs_parse_mount_err;
1114 }
1115 } else {
1116 printk(KERN_WARNING "CIFS: ip address "
1117 "too long\n");
1118 goto cifs_parse_mount_err;
1119 }
1120 } else if (strnicmp(data, "sec", 3) == 0) {
1121 if (!value || !*value) {
1122 cERROR(1, "no security value specified");
1123 continue;
1124 } else if (strnicmp(value, "krb5i", 5) == 0) {
1125 vol->secFlg |= CIFSSEC_MAY_KRB5 |
1126 CIFSSEC_MUST_SIGN;
1127 } else if (strnicmp(value, "krb5p", 5) == 0) {
1128 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
1129 CIFSSEC_MAY_KRB5; */
1130 cERROR(1, "Krb5 cifs privacy not supported");
1131 goto cifs_parse_mount_err;
1132 } else if (strnicmp(value, "krb5", 4) == 0) {
1133 vol->secFlg |= CIFSSEC_MAY_KRB5;
1134 } else if (strnicmp(value, "ntlmsspi", 8) == 0) {
1135 vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
1136 CIFSSEC_MUST_SIGN;
1137 } else if (strnicmp(value, "ntlmssp", 7) == 0) {
1138 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
1139 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
1140 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
1141 CIFSSEC_MUST_SIGN;
1142 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
1143 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1144 } else if (strnicmp(value, "ntlmi", 5) == 0) {
1145 vol->secFlg |= CIFSSEC_MAY_NTLM |
1146 CIFSSEC_MUST_SIGN;
1147 } else if (strnicmp(value, "ntlm", 4) == 0) {
1148 /* ntlm is default so can be turned off too */
1149 vol->secFlg |= CIFSSEC_MAY_NTLM;
1150 } else if (strnicmp(value, "nontlm", 6) == 0) {
1151 /* BB is there a better way to do this? */
1152 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1153#ifdef CONFIG_CIFS_WEAK_PW_HASH
1154 } else if (strnicmp(value, "lanman", 6) == 0) {
1155 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1156#endif
1157 } else if (strnicmp(value, "none", 4) == 0) {
1158 vol->nullauth = 1;
1159 } else {
1160 cERROR(1, "bad security option: %s", value);
1161 goto cifs_parse_mount_err;
1162 }
1163 } else if (strnicmp(data, "vers", 3) == 0) {
1164 if (!value || !*value) {
1165 cERROR(1, "no protocol version specified"
1166 " after vers= mount option");
1167 } else if ((strnicmp(value, "cifs", 4) == 0) ||
1168 (strnicmp(value, "1", 1) == 0)) {
1169 /* this is the default */
1170 continue;
1171 }
1172 } else if ((strnicmp(data, "unc", 3) == 0)
1173 || (strnicmp(data, "target", 6) == 0)
1174 || (strnicmp(data, "path", 4) == 0)) {
1175 if (!value || !*value) {
1176 printk(KERN_WARNING "CIFS: invalid path to "
1177 "network resource\n");
1178 goto cifs_parse_mount_err;
1179 }
1180 if ((temp_len = strnlen(value, 300)) < 300) {
1181 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1182 if (vol->UNC == NULL)
1183 goto cifs_parse_mount_err;
1184 strcpy(vol->UNC, value);
1185 if (strncmp(vol->UNC, "//", 2) == 0) {
1186 vol->UNC[0] = '\\';
1187 vol->UNC[1] = '\\';
1188 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1189 printk(KERN_WARNING
1190 "CIFS: UNC Path does not begin "
1191 "with // or \\\\ \n");
1192 goto cifs_parse_mount_err;
1193 }
1194 } else {
1195 printk(KERN_WARNING "CIFS: UNC name too long\n");
1196 goto cifs_parse_mount_err;
1197 }
1198 } else if ((strnicmp(data, "domain", 3) == 0)
1199 || (strnicmp(data, "workgroup", 5) == 0)) {
1200 if (!value || !*value) {
1201 printk(KERN_WARNING "CIFS: invalid domain name\n");
1202 goto cifs_parse_mount_err;
1203 }
1204 /* BB are there cases in which a comma can be valid in
1205 a domain name and need special handling? */
1206 if (strnlen(value, 256) < 256) {
1207 vol->domainname = kstrdup(value, GFP_KERNEL);
1208 if (!vol->domainname) {
1209 printk(KERN_WARNING "CIFS: no memory "
1210 "for domainname\n");
1211 goto cifs_parse_mount_err;
1212 }
1213 cFYI(1, "Domain name set");
1214 } else {
1215 printk(KERN_WARNING "CIFS: domain name too "
1216 "long\n");
1217 goto cifs_parse_mount_err;
1218 }
1219 } else if (strnicmp(data, "srcaddr", 7) == 0) {
1220 vol->srcaddr.ss_family = AF_UNSPEC;
1221
1222 if (!value || !*value) {
1223 printk(KERN_WARNING "CIFS: srcaddr value"
1224 " not specified.\n");
1225 goto cifs_parse_mount_err;
1226 }
1227 i = cifs_convert_address((struct sockaddr *)&vol->srcaddr,
1228 value, strlen(value));
1229 if (i == 0) {
1230 printk(KERN_WARNING "CIFS: Could not parse"
1231 " srcaddr: %s\n",
1232 value);
1233 goto cifs_parse_mount_err;
1234 }
1235 } else if (strnicmp(data, "prefixpath", 10) == 0) {
1236 if (!value || !*value) {
1237 printk(KERN_WARNING
1238 "CIFS: invalid path prefix\n");
1239 goto cifs_parse_mount_err;
1240 }
1241 if ((temp_len = strnlen(value, 1024)) < 1024) {
1242 if (value[0] != '/')
1243 temp_len++; /* missing leading slash */
1244 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1245 if (vol->prepath == NULL)
1246 goto cifs_parse_mount_err;
1247 if (value[0] != '/') {
1248 vol->prepath[0] = '/';
1249 strcpy(vol->prepath+1, value);
1250 } else
1251 strcpy(vol->prepath, value);
1252 cFYI(1, "prefix path %s", vol->prepath);
1253 } else {
1254 printk(KERN_WARNING "CIFS: prefix too long\n");
1255 goto cifs_parse_mount_err;
1256 }
1257 } else if (strnicmp(data, "iocharset", 9) == 0) {
1258 if (!value || !*value) {
1259 printk(KERN_WARNING "CIFS: invalid iocharset "
1260 "specified\n");
1261 goto cifs_parse_mount_err;
1262 }
1263 if (strnlen(value, 65) < 65) {
1264 if (strnicmp(value, "default", 7)) {
1265 vol->iocharset = kstrdup(value,
1266 GFP_KERNEL);
1267
1268 if (!vol->iocharset) {
1269 printk(KERN_WARNING "CIFS: no "
1270 "memory for"
1271 "charset\n");
1272 goto cifs_parse_mount_err;
1273 }
1274 }
1275 /* if iocharset not set then load_nls_default
1276 is used by caller */
1277 cFYI(1, "iocharset set to %s", value);
1278 } else {
1279 printk(KERN_WARNING "CIFS: iocharset name "
1280 "too long.\n");
1281 goto cifs_parse_mount_err;
1282 }
1283 } else if (!strnicmp(data, "uid", 3) && value && *value) {
1284 vol->linux_uid = simple_strtoul(value, &value, 0);
1285 uid_specified = true;
1286 } else if (!strnicmp(data, "cruid", 5) && value && *value) {
1287 vol->cred_uid = simple_strtoul(value, &value, 0);
1288 } else if (!strnicmp(data, "forceuid", 8)) {
1289 override_uid = 1; 1271 override_uid = 1;
1290 } else if (!strnicmp(data, "noforceuid", 10)) { 1272 break;
1273 case Opt_noforceuid:
1291 override_uid = 0; 1274 override_uid = 0;
1292 } else if (!strnicmp(data, "gid", 3) && value && *value) { 1275 break;
1293 vol->linux_gid = simple_strtoul(value, &value, 0); 1276 case Opt_noblocksend:
1294 gid_specified = true;
1295 } else if (!strnicmp(data, "forcegid", 8)) {
1296 override_gid = 1;
1297 } else if (!strnicmp(data, "noforcegid", 10)) {
1298 override_gid = 0;
1299 } else if (strnicmp(data, "file_mode", 4) == 0) {
1300 if (value && *value) {
1301 vol->file_mode =
1302 simple_strtoul(value, &value, 0);
1303 }
1304 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1305 if (value && *value) {
1306 vol->dir_mode =
1307 simple_strtoul(value, &value, 0);
1308 }
1309 } else if (strnicmp(data, "dirmode", 4) == 0) {
1310 if (value && *value) {
1311 vol->dir_mode =
1312 simple_strtoul(value, &value, 0);
1313 }
1314 } else if (strnicmp(data, "port", 4) == 0) {
1315 if (value && *value) {
1316 vol->port =
1317 simple_strtoul(value, &value, 0);
1318 }
1319 } else if (strnicmp(data, "rsize", 5) == 0) {
1320 if (value && *value) {
1321 vol->rsize =
1322 simple_strtoul(value, &value, 0);
1323 }
1324 } else if (strnicmp(data, "wsize", 5) == 0) {
1325 if (value && *value) {
1326 vol->wsize =
1327 simple_strtoul(value, &value, 0);
1328 }
1329 } else if (strnicmp(data, "sockopt", 5) == 0) {
1330 if (!value || !*value) {
1331 cERROR(1, "no socket option specified");
1332 continue;
1333 } else if (strnicmp(value, "TCP_NODELAY", 11) == 0) {
1334 vol->sockopt_tcp_nodelay = 1;
1335 }
1336 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1337 if (!value || !*value || (*value == ' ')) {
1338 cFYI(1, "invalid (empty) netbiosname");
1339 } else {
1340 memset(vol->source_rfc1001_name, 0x20,
1341 RFC1001_NAME_LEN);
1342 /*
1343 * FIXME: are there cases in which a comma can
1344 * be valid in workstation netbios name (and
1345 * need special handling)?
1346 */
1347 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1348 /* don't ucase netbiosname for user */
1349 if (value[i] == 0)
1350 break;
1351 vol->source_rfc1001_name[i] = value[i];
1352 }
1353 /* The string has 16th byte zero still from
1354 set at top of the function */
1355 if (i == RFC1001_NAME_LEN && value[i] != 0)
1356 printk(KERN_WARNING "CIFS: netbiosname"
1357 " longer than 15 truncated.\n");
1358 }
1359 } else if (strnicmp(data, "servern", 7) == 0) {
1360 /* servernetbiosname specified override *SMBSERVER */
1361 if (!value || !*value || (*value == ' ')) {
1362 cFYI(1, "empty server netbiosname specified");
1363 } else {
1364 /* last byte, type, is 0x20 for servr type */
1365 memset(vol->target_rfc1001_name, 0x20,
1366 RFC1001_NAME_LEN_WITH_NULL);
1367
1368 for (i = 0; i < 15; i++) {
1369 /* BB are there cases in which a comma can be
1370 valid in this workstation netbios name
1371 (and need special handling)? */
1372
1373 /* user or mount helper must uppercase
1374 the netbiosname */
1375 if (value[i] == 0)
1376 break;
1377 else
1378 vol->target_rfc1001_name[i] =
1379 value[i];
1380 }
1381 /* The string has 16th byte zero still from
1382 set at top of the function */
1383 if (i == RFC1001_NAME_LEN && value[i] != 0)
1384 printk(KERN_WARNING "CIFS: server net"
1385 "biosname longer than 15 truncated.\n");
1386 }
1387 } else if (strnicmp(data, "actimeo", 7) == 0) {
1388 if (value && *value) {
1389 vol->actimeo = HZ * simple_strtoul(value,
1390 &value, 0);
1391 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1392 cERROR(1, "CIFS: attribute cache"
1393 "timeout too large");
1394 goto cifs_parse_mount_err;
1395 }
1396 }
1397 } else if (strnicmp(data, "credentials", 4) == 0) {
1398 /* ignore */
1399 } else if (strnicmp(data, "version", 3) == 0) {
1400 /* ignore */
1401 } else if (strnicmp(data, "guest", 5) == 0) {
1402 /* ignore */
1403 } else if (strnicmp(data, "rw", 2) == 0 && strlen(data) == 2) {
1404 /* ignore */
1405 } else if (strnicmp(data, "ro", 2) == 0) {
1406 /* ignore */
1407 } else if (strnicmp(data, "noblocksend", 11) == 0) {
1408 vol->noblocksnd = 1; 1277 vol->noblocksnd = 1;
1409 } else if (strnicmp(data, "noautotune", 10) == 0) { 1278 break;
1279 case Opt_noautotune:
1410 vol->noautotune = 1; 1280 vol->noautotune = 1;
1411 } else if ((strnicmp(data, "suid", 4) == 0) || 1281 break;
1412 (strnicmp(data, "nosuid", 6) == 0) || 1282 case Opt_hard:
1413 (strnicmp(data, "exec", 4) == 0) ||
1414 (strnicmp(data, "noexec", 6) == 0) ||
1415 (strnicmp(data, "nodev", 5) == 0) ||
1416 (strnicmp(data, "noauto", 6) == 0) ||
1417 (strnicmp(data, "dev", 3) == 0)) {
1418 /* The mount tool or mount.cifs helper (if present)
1419 uses these opts to set flags, and the flags are read
1420 by the kernel vfs layer before we get here (ie
1421 before read super) so there is no point trying to
1422 parse these options again and set anything and it
1423 is ok to just ignore them */
1424 continue;
1425 } else if (strnicmp(data, "hard", 4) == 0) {
1426 vol->retry = 1; 1283 vol->retry = 1;
1427 } else if (strnicmp(data, "soft", 4) == 0) { 1284 break;
1285 case Opt_soft:
1428 vol->retry = 0; 1286 vol->retry = 0;
1429 } else if (strnicmp(data, "perm", 4) == 0) { 1287 break;
1288 case Opt_perm:
1430 vol->noperm = 0; 1289 vol->noperm = 0;
1431 } else if (strnicmp(data, "noperm", 6) == 0) { 1290 break;
1291 case Opt_noperm:
1432 vol->noperm = 1; 1292 vol->noperm = 1;
1433 } else if (strnicmp(data, "mapchars", 8) == 0) { 1293 break;
1294 case Opt_mapchars:
1434 vol->remap = 1; 1295 vol->remap = 1;
1435 } else if (strnicmp(data, "nomapchars", 10) == 0) { 1296 break;
1297 case Opt_nomapchars:
1436 vol->remap = 0; 1298 vol->remap = 0;
1437 } else if (strnicmp(data, "sfu", 3) == 0) { 1299 break;
1300 case Opt_sfu:
1438 vol->sfu_emul = 1; 1301 vol->sfu_emul = 1;
1439 } else if (strnicmp(data, "nosfu", 5) == 0) { 1302 break;
1303 case Opt_nosfu:
1440 vol->sfu_emul = 0; 1304 vol->sfu_emul = 0;
1441 } else if (strnicmp(data, "nodfs", 5) == 0) { 1305 break;
1306 case Opt_nodfs:
1442 vol->nodfs = 1; 1307 vol->nodfs = 1;
1443 } else if (strnicmp(data, "posixpaths", 10) == 0) { 1308 break;
1309 case Opt_posixpaths:
1444 vol->posix_paths = 1; 1310 vol->posix_paths = 1;
1445 } else if (strnicmp(data, "noposixpaths", 12) == 0) { 1311 break;
1312 case Opt_noposixpaths:
1446 vol->posix_paths = 0; 1313 vol->posix_paths = 0;
1447 } else if (strnicmp(data, "nounix", 6) == 0) { 1314 break;
1448 vol->no_linux_ext = 1; 1315 case Opt_nounix:
1449 } else if (strnicmp(data, "nolinux", 7) == 0) {
1450 vol->no_linux_ext = 1; 1316 vol->no_linux_ext = 1;
1451 } else if ((strnicmp(data, "nocase", 6) == 0) || 1317 break;
1452 (strnicmp(data, "ignorecase", 10) == 0)) { 1318 case Opt_nocase:
1453 vol->nocase = 1; 1319 vol->nocase = 1;
1454 } else if (strnicmp(data, "mand", 4) == 0) { 1320 break;
1455 /* ignore */ 1321 case Opt_brl:
1456 } else if (strnicmp(data, "nomand", 6) == 0) {
1457 /* ignore */
1458 } else if (strnicmp(data, "_netdev", 7) == 0) {
1459 /* ignore */
1460 } else if (strnicmp(data, "brl", 3) == 0) {
1461 vol->nobrl = 0; 1322 vol->nobrl = 0;
1462 } else if ((strnicmp(data, "nobrl", 5) == 0) || 1323 break;
1463 (strnicmp(data, "nolock", 6) == 0)) { 1324 case Opt_nobrl:
1464 vol->nobrl = 1; 1325 vol->nobrl = 1;
1465 /* turn off mandatory locking in mode 1326 /* turn off mandatory locking in mode
1466 if remote locking is turned off since the 1327 * if remote locking is turned off since the
1467 local vfs will do advisory */ 1328 * local vfs will do advisory */
1468 if (vol->file_mode == 1329 if (vol->file_mode ==
1469 (S_IALLUGO & ~(S_ISUID | S_IXGRP))) 1330 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1470 vol->file_mode = S_IALLUGO; 1331 vol->file_mode = S_IALLUGO;
1471 } else if (strnicmp(data, "forcemandatorylock", 9) == 0) { 1332 break;
1472 /* will take the shorter form "forcemand" as well */ 1333 case Opt_forcemandatorylock:
1473 /* This mount option will force use of mandatory
1474 (DOS/Windows style) byte range locks, instead of
1475 using posix advisory byte range locks, even if the
1476 Unix extensions are available and posix locks would
1477 be supported otherwise. If Unix extensions are not
1478 negotiated this has no effect since mandatory locks
1479 would be used (mandatory locks is all that those
1480 those servers support) */
1481 vol->mand_lock = 1; 1334 vol->mand_lock = 1;
1482 } else if (strnicmp(data, "setuids", 7) == 0) { 1335 break;
1336 case Opt_setuids:
1483 vol->setuids = 1; 1337 vol->setuids = 1;
1484 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1338 break;
1339 case Opt_nosetuids:
1485 vol->setuids = 0; 1340 vol->setuids = 0;
1486 } else if (strnicmp(data, "dynperm", 7) == 0) { 1341 break;
1342 case Opt_dynperm:
1487 vol->dynperm = true; 1343 vol->dynperm = true;
1488 } else if (strnicmp(data, "nodynperm", 9) == 0) { 1344 break;
1345 case Opt_nodynperm:
1489 vol->dynperm = false; 1346 vol->dynperm = false;
1490 } else if (strnicmp(data, "nohard", 6) == 0) { 1347 break;
1348 case Opt_nohard:
1491 vol->retry = 0; 1349 vol->retry = 0;
1492 } else if (strnicmp(data, "nosoft", 6) == 0) { 1350 break;
1351 case Opt_nosoft:
1493 vol->retry = 1; 1352 vol->retry = 1;
1494 } else if (strnicmp(data, "nointr", 6) == 0) { 1353 break;
1354 case Opt_nointr:
1495 vol->intr = 0; 1355 vol->intr = 0;
1496 } else if (strnicmp(data, "intr", 4) == 0) { 1356 break;
1357 case Opt_intr:
1497 vol->intr = 1; 1358 vol->intr = 1;
1498 } else if (strnicmp(data, "nostrictsync", 12) == 0) { 1359 break;
1360 case Opt_nostrictsync:
1499 vol->nostrictsync = 1; 1361 vol->nostrictsync = 1;
1500 } else if (strnicmp(data, "strictsync", 10) == 0) { 1362 break;
1363 case Opt_strictsync:
1501 vol->nostrictsync = 0; 1364 vol->nostrictsync = 0;
1502 } else if (strnicmp(data, "serverino", 7) == 0) { 1365 break;
1366 case Opt_serverino:
1503 vol->server_ino = 1; 1367 vol->server_ino = 1;
1504 } else if (strnicmp(data, "noserverino", 9) == 0) { 1368 break;
1369 case Opt_noserverino:
1505 vol->server_ino = 0; 1370 vol->server_ino = 0;
1506 } else if (strnicmp(data, "rwpidforward", 12) == 0) { 1371 break;
1372 case Opt_rwpidforward:
1507 vol->rwpidforward = 1; 1373 vol->rwpidforward = 1;
1508 } else if (strnicmp(data, "cifsacl", 7) == 0) { 1374 break;
1375 case Opt_cifsacl:
1509 vol->cifs_acl = 1; 1376 vol->cifs_acl = 1;
1510 } else if (strnicmp(data, "nocifsacl", 9) == 0) { 1377 break;
1378 case Opt_nocifsacl:
1511 vol->cifs_acl = 0; 1379 vol->cifs_acl = 0;
1512 } else if (strnicmp(data, "acl", 3) == 0) { 1380 break;
1381 case Opt_acl:
1513 vol->no_psx_acl = 0; 1382 vol->no_psx_acl = 0;
1514 } else if (strnicmp(data, "noacl", 5) == 0) { 1383 break;
1384 case Opt_noacl:
1515 vol->no_psx_acl = 1; 1385 vol->no_psx_acl = 1;
1516 } else if (strnicmp(data, "locallease", 6) == 0) { 1386 break;
1387 case Opt_locallease:
1517 vol->local_lease = 1; 1388 vol->local_lease = 1;
1518 } else if (strnicmp(data, "sign", 4) == 0) { 1389 break;
1390 case Opt_sign:
1519 vol->secFlg |= CIFSSEC_MUST_SIGN; 1391 vol->secFlg |= CIFSSEC_MUST_SIGN;
1520 } else if (strnicmp(data, "seal", 4) == 0) { 1392 break;
1393 case Opt_seal:
1521 /* we do not do the following in secFlags because seal 1394 /* we do not do the following in secFlags because seal
1522 is a per tree connection (mount) not a per socket 1395 * is a per tree connection (mount) not a per socket
1523 or per-smb connection option in the protocol */ 1396 * or per-smb connection option in the protocol
1524 /* vol->secFlg |= CIFSSEC_MUST_SEAL; */ 1397 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1398 */
1525 vol->seal = 1; 1399 vol->seal = 1;
1526 } else if (strnicmp(data, "direct", 6) == 0) { 1400 break;
1527 vol->direct_io = 1; 1401 case Opt_direct:
1528 } else if (strnicmp(data, "forcedirectio", 13) == 0) {
1529 vol->direct_io = 1; 1402 vol->direct_io = 1;
1530 } else if (strnicmp(data, "strictcache", 11) == 0) { 1403 break;
1404 case Opt_strictcache:
1531 vol->strict_io = 1; 1405 vol->strict_io = 1;
1532 } else if (strnicmp(data, "noac", 4) == 0) { 1406 break;
1407 case Opt_noac:
1533 printk(KERN_WARNING "CIFS: Mount option noac not " 1408 printk(KERN_WARNING "CIFS: Mount option noac not "
1534 "supported. Instead set " 1409 "supported. Instead set "
1535 "/proc/fs/cifs/LookupCacheEnabled to 0\n"); 1410 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1536 } else if (strnicmp(data, "fsc", 3) == 0) { 1411 break;
1412 case Opt_fsc:
1537#ifndef CONFIG_CIFS_FSCACHE 1413#ifndef CONFIG_CIFS_FSCACHE
1538 cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE " 1414 cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
1539 "kernel config option set"); 1415 "kernel config option set");
1540 goto cifs_parse_mount_err; 1416 goto cifs_parse_mount_err;
1541#endif 1417#endif
1542 vol->fsc = true; 1418 vol->fsc = true;
1543 } else if (strnicmp(data, "mfsymlinks", 10) == 0) { 1419 break;
1420 case Opt_mfsymlinks:
1544 vol->mfsymlinks = true; 1421 vol->mfsymlinks = true;
1545 } else if (strnicmp(data, "multiuser", 8) == 0) { 1422 break;
1423 case Opt_multiuser:
1546 vol->multiuser = true; 1424 vol->multiuser = true;
1547 } else if (!strnicmp(data, "backupuid", 9) && value && *value) { 1425 break;
1548 err = kstrtouint(value, 0, &vol->backupuid); 1426
1549 if (err < 0) { 1427 /* Numeric Values */
1428 case Opt_backupuid:
1429 if (get_option_ul(args, &option)) {
1550 cERROR(1, "%s: Invalid backupuid value", 1430 cERROR(1, "%s: Invalid backupuid value",
1551 __func__); 1431 __func__);
1552 goto cifs_parse_mount_err; 1432 goto cifs_parse_mount_err;
1553 } 1433 }
1434 vol->backupuid = option;
1554 vol->backupuid_specified = true; 1435 vol->backupuid_specified = true;
1555 } else if (!strnicmp(data, "backupgid", 9) && value && *value) { 1436 break;
1556 err = kstrtouint(value, 0, &vol->backupgid); 1437 case Opt_backupgid:
1557 if (err < 0) { 1438 if (get_option_ul(args, &option)) {
1558 cERROR(1, "%s: Invalid backupgid value", 1439 cERROR(1, "%s: Invalid backupgid value",
1559 __func__); 1440 __func__);
1560 goto cifs_parse_mount_err; 1441 goto cifs_parse_mount_err;
1561 } 1442 }
1443 vol->backupgid = option;
1562 vol->backupgid_specified = true; 1444 vol->backupgid_specified = true;
1563 } else 1445 break;
1564 printk(KERN_WARNING "CIFS: Unknown mount option %s\n", 1446 case Opt_uid:
1565 data); 1447 if (get_option_ul(args, &option)) {
1566 } 1448 cERROR(1, "%s: Invalid uid value",
1567 if (vol->UNC == NULL) { 1449 __func__);
1568 if (devname == NULL) { 1450 goto cifs_parse_mount_err;
1569 printk(KERN_WARNING "CIFS: Missing UNC name for mount " 1451 }
1570 "target\n"); 1452 vol->linux_uid = option;
1571 goto cifs_parse_mount_err; 1453 uid_specified = true;
1572 } 1454 break;
1573 if ((temp_len = strnlen(devname, 300)) < 300) { 1455 case Opt_cruid:
1574 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); 1456 if (get_option_ul(args, &option)) {
1575 if (vol->UNC == NULL) 1457 cERROR(1, "%s: Invalid cruid value",
1458 __func__);
1459 goto cifs_parse_mount_err;
1460 }
1461 vol->cred_uid = option;
1462 break;
1463 case Opt_gid:
1464 if (get_option_ul(args, &option)) {
1465 cERROR(1, "%s: Invalid gid value",
1466 __func__);
1467 goto cifs_parse_mount_err;
1468 }
1469 vol->linux_gid = option;
1470 gid_specified = true;
1471 break;
1472 case Opt_file_mode:
1473 if (get_option_ul(args, &option)) {
1474 cERROR(1, "%s: Invalid file_mode value",
1475 __func__);
1476 goto cifs_parse_mount_err;
1477 }
1478 vol->file_mode = option;
1479 break;
1480 case Opt_dirmode:
1481 if (get_option_ul(args, &option)) {
1482 cERROR(1, "%s: Invalid dir_mode value",
1483 __func__);
1484 goto cifs_parse_mount_err;
1485 }
1486 vol->dir_mode = option;
1487 break;
1488 case Opt_port:
1489 if (get_option_ul(args, &option)) {
1490 cERROR(1, "%s: Invalid port value",
1491 __func__);
1492 goto cifs_parse_mount_err;
1493 }
1494 vol->port = option;
1495 break;
1496 case Opt_rsize:
1497 if (get_option_ul(args, &option)) {
1498 cERROR(1, "%s: Invalid rsize value",
1499 __func__);
1500 goto cifs_parse_mount_err;
1501 }
1502 vol->rsize = option;
1503 break;
1504 case Opt_wsize:
1505 if (get_option_ul(args, &option)) {
1506 cERROR(1, "%s: Invalid wsize value",
1507 __func__);
1508 goto cifs_parse_mount_err;
1509 }
1510 vol->wsize = option;
1511 break;
1512 case Opt_actimeo:
1513 if (get_option_ul(args, &option)) {
1514 cERROR(1, "%s: Invalid actimeo value",
1515 __func__);
1516 goto cifs_parse_mount_err;
1517 }
1518 vol->actimeo = HZ * option;
1519 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1520 cERROR(1, "CIFS: attribute cache"
1521 "timeout too large");
1522 goto cifs_parse_mount_err;
1523 }
1524 break;
1525
1526 /* String Arguments */
1527
1528 case Opt_user:
1529 string = match_strdup(args);
1530 if (string == NULL)
1531 goto out_nomem;
1532
1533 if (!*string) {
1534 /* null user, ie. anonymous authentication */
1535 vol->nullauth = 1;
1536 } else if (strnlen(string, MAX_USERNAME_SIZE) >
1537 MAX_USERNAME_SIZE) {
1538 printk(KERN_WARNING "CIFS: username too long\n");
1539 goto cifs_parse_mount_err;
1540 }
1541 vol->username = kstrdup(string, GFP_KERNEL);
1542 if (!vol->username) {
1543 printk(KERN_WARNING "CIFS: no memory "
1544 "for username\n");
1545 goto cifs_parse_mount_err;
1546 }
1547 break;
1548 case Opt_blank_pass:
1549 vol->password = NULL;
1550 break;
1551 case Opt_pass:
1552 /* passwords have to be handled differently
1553 * to allow the character used for deliminator
1554 * to be passed within them
1555 */
1556
1557 /* Obtain the value string */
1558 value = strchr(data, '=');
1559 if (value != NULL)
1560 *value++ = '\0';
1561
1562 /* Set tmp_end to end of the string */
1563 tmp_end = (char *) value + strlen(value);
1564
1565 /* Check if following character is the deliminator
1566 * If yes, we have encountered a double deliminator
1567 * reset the NULL character to the deliminator
1568 */
1569 if (tmp_end < end && tmp_end[1] == delim)
1570 tmp_end[0] = delim;
1571
1572 /* Keep iterating until we get to a single deliminator
1573 * OR the end
1574 */
1575 while ((tmp_end = strchr(tmp_end, delim)) != NULL &&
1576 (tmp_end[1] == delim)) {
1577 tmp_end = (char *) &tmp_end[2];
1578 }
1579
1580 /* Reset var options to point to next element */
1581 if (tmp_end) {
1582 tmp_end[0] = '\0';
1583 options = (char *) &tmp_end[1];
1584 } else
1585 /* Reached the end of the mount option string */
1586 options = end;
1587
1588 /* Now build new password string */
1589 temp_len = strlen(value);
1590 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1591 if (vol->password == NULL) {
1592 printk(KERN_WARNING "CIFS: no memory "
1593 "for password\n");
1594 goto cifs_parse_mount_err;
1595 }
1596
1597 for (i = 0, j = 0; i < temp_len; i++, j++) {
1598 vol->password[j] = value[i];
1599 if ((value[i] == delim) &&
1600 value[i+1] == delim)
1601 /* skip the second deliminator */
1602 i++;
1603 }
1604 vol->password[j] = '\0';
1605 break;
1606 case Opt_ip:
1607 string = match_strdup(args);
1608 if (string == NULL)
1609 goto out_nomem;
1610
1611 if (!*string) {
1612 vol->UNCip = NULL;
1613 } else if (strnlen(string, INET6_ADDRSTRLEN) >
1614 INET6_ADDRSTRLEN) {
1615 printk(KERN_WARNING "CIFS: ip address "
1616 "too long\n");
1617 goto cifs_parse_mount_err;
1618 }
1619 vol->UNCip = kstrdup(string, GFP_KERNEL);
1620 if (!vol->UNCip) {
1621 printk(KERN_WARNING "CIFS: no memory "
1622 "for UNC IP\n");
1623 goto cifs_parse_mount_err;
1624 }
1625 break;
1626 case Opt_unc:
1627 string = match_strdup(args);
1628 if (string == NULL)
1629 goto out_nomem;
1630
1631 if (!*string) {
1632 printk(KERN_WARNING "CIFS: invalid path to "
1633 "network resource\n");
1634 goto cifs_parse_mount_err;
1635 }
1636
1637 temp_len = strnlen(string, 300);
1638 if (temp_len == 300) {
1639 printk(KERN_WARNING "CIFS: UNC name too long\n");
1576 goto cifs_parse_mount_err; 1640 goto cifs_parse_mount_err;
1577 strcpy(vol->UNC, devname); 1641 }
1578 if (strncmp(vol->UNC, "//", 2) == 0) { 1642
1643 if (strncmp(string, "//", 2) == 0) {
1579 vol->UNC[0] = '\\'; 1644 vol->UNC[0] = '\\';
1580 vol->UNC[1] = '\\'; 1645 vol->UNC[1] = '\\';
1581 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { 1646 } else if (strncmp(string, "\\\\", 2) != 0) {
1582 printk(KERN_WARNING "CIFS: UNC Path does not " 1647 printk(KERN_WARNING "CIFS: UNC Path does not "
1583 "begin with // or \\\\ \n"); 1648 "begin with // or \\\\\n");
1584 goto cifs_parse_mount_err; 1649 goto cifs_parse_mount_err;
1585 } 1650 }
1586 value = strpbrk(vol->UNC+2, "/\\"); 1651
1587 if (value) 1652 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1588 *value = '\\'; 1653 if (vol->UNC == NULL) {
1589 } else { 1654 printk(KERN_WARNING "CIFS: no memory "
1590 printk(KERN_WARNING "CIFS: UNC name too long\n"); 1655 "for UNC\n");
1656 goto cifs_parse_mount_err;
1657 }
1658 strcpy(vol->UNC, string);
1659 break;
1660 case Opt_domain:
1661 string = match_strdup(args);
1662 if (string == NULL)
1663 goto out_nomem;
1664
1665 if (!*string) {
1666 printk(KERN_WARNING "CIFS: invalid domain"
1667 " name\n");
1668 goto cifs_parse_mount_err;
1669 } else if (strnlen(string, 256) == 256) {
1670 printk(KERN_WARNING "CIFS: domain name too"
1671 " long\n");
1672 goto cifs_parse_mount_err;
1673 }
1674
1675 vol->domainname = kstrdup(string, GFP_KERNEL);
1676 if (!vol->domainname) {
1677 printk(KERN_WARNING "CIFS: no memory "
1678 "for domainname\n");
1679 goto cifs_parse_mount_err;
1680 }
1681 cFYI(1, "Domain name set");
1682 break;
1683 case Opt_srcaddr:
1684 string = match_strdup(args);
1685 if (string == NULL)
1686 goto out_nomem;
1687
1688 if (!*string) {
1689 printk(KERN_WARNING "CIFS: srcaddr value not"
1690 " specified\n");
1691 goto cifs_parse_mount_err;
1692 } else if (!cifs_convert_address(
1693 (struct sockaddr *)&vol->srcaddr,
1694 string, strlen(string))) {
1695 printk(KERN_WARNING "CIFS: Could not parse"
1696 " srcaddr: %s\n", string);
1697 goto cifs_parse_mount_err;
1698 }
1699 break;
1700 case Opt_prefixpath:
1701 string = match_strdup(args);
1702 if (string == NULL)
1703 goto out_nomem;
1704
1705 if (!*string) {
1706 printk(KERN_WARNING "CIFS: Invalid path"
1707 " prefix\n");
1708 goto cifs_parse_mount_err;
1709 }
1710 temp_len = strnlen(string, 1024);
1711 if (string[0] != '/')
1712 temp_len++; /* missing leading slash */
1713 if (temp_len > 1024) {
1714 printk(KERN_WARNING "CIFS: prefix too long\n");
1715 goto cifs_parse_mount_err;
1716 }
1717
1718 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1719 if (vol->prepath == NULL) {
1720 printk(KERN_WARNING "CIFS: no memory "
1721 "for path prefix\n");
1722 goto cifs_parse_mount_err;
1723 }
1724
1725 if (string[0] != '/') {
1726 vol->prepath[0] = '/';
1727 strcpy(vol->prepath+1, string);
1728 } else
1729 strcpy(vol->prepath, string);
1730
1731 break;
1732 case Opt_iocharset:
1733 string = match_strdup(args);
1734 if (string == NULL)
1735 goto out_nomem;
1736
1737 if (!*string) {
1738 printk(KERN_WARNING "CIFS: Invalid iocharset"
1739 " specified\n");
1740 goto cifs_parse_mount_err;
1741 } else if (strnlen(string, 1024) >= 65) {
1742 printk(KERN_WARNING "CIFS: iocharset name "
1743 "too long.\n");
1744 goto cifs_parse_mount_err;
1745 }
1746
1747 if (strnicmp(string, "default", 7) != 0) {
1748 vol->iocharset = kstrdup(string,
1749 GFP_KERNEL);
1750 if (!vol->iocharset) {
1751 printk(KERN_WARNING "CIFS: no memory"
1752 "for charset\n");
1753 goto cifs_parse_mount_err;
1754 }
1755 }
1756 /* if iocharset not set then load_nls_default
1757 * is used by caller
1758 */
1759 cFYI(1, "iocharset set to %s", string);
1760 break;
1761 case Opt_sockopt:
1762 string = match_strdup(args);
1763 if (string == NULL)
1764 goto out_nomem;
1765
1766 if (!*string) {
1767 printk(KERN_WARNING "CIFS: No socket option"
1768 " specified\n");
1769 goto cifs_parse_mount_err;
1770 }
1771 if (strnicmp(string, "TCP_NODELAY", 11) == 0)
1772 vol->sockopt_tcp_nodelay = 1;
1773 break;
1774 case Opt_netbiosname:
1775 string = match_strdup(args);
1776 if (string == NULL)
1777 goto out_nomem;
1778
1779 if (!*string) {
1780 printk(KERN_WARNING "CIFS: Invalid (empty)"
1781 " netbiosname\n");
1782 break;
1783 }
1784
1785 memset(vol->source_rfc1001_name, 0x20,
1786 RFC1001_NAME_LEN);
1787 /*
1788 * FIXME: are there cases in which a comma can
1789 * be valid in workstation netbios name (and
1790 * need special handling)?
1791 */
1792 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1793 /* don't ucase netbiosname for user */
1794 if (string[i] == 0)
1795 break;
1796 vol->source_rfc1001_name[i] = string[i];
1797 }
1798 /* The string has 16th byte zero still from
1799 * set at top of the function
1800 */
1801 if (i == RFC1001_NAME_LEN && string[i] != 0)
1802 printk(KERN_WARNING "CIFS: netbiosname"
1803 " longer than 15 truncated.\n");
1804
1805 break;
1806 case Opt_servern:
1807 /* servernetbiosname specified override *SMBSERVER */
1808 string = match_strdup(args);
1809 if (string == NULL)
1810 goto out_nomem;
1811
1812 if (!*string) {
1813 printk(KERN_WARNING "CIFS: Empty server"
1814 " netbiosname specified\n");
1815 break;
1816 }
1817 /* last byte, type, is 0x20 for servr type */
1818 memset(vol->target_rfc1001_name, 0x20,
1819 RFC1001_NAME_LEN_WITH_NULL);
1820
1821 /* BB are there cases in which a comma can be
1822 valid in this workstation netbios name
1823 (and need special handling)? */
1824
1825 /* user or mount helper must uppercase the
1826 netbios name */
1827 for (i = 0; i < 15; i++) {
1828 if (string[i] == 0)
1829 break;
1830 vol->target_rfc1001_name[i] = string[i];
1831 }
1832 /* The string has 16th byte zero still from
1833 set at top of the function */
1834 if (i == RFC1001_NAME_LEN && string[i] != 0)
1835 printk(KERN_WARNING "CIFS: server net"
1836 "biosname longer than 15 truncated.\n");
1837 break;
1838 case Opt_ver:
1839 string = match_strdup(args);
1840 if (string == NULL)
1841 goto out_nomem;
1842
1843 if (!*string) {
1844 cERROR(1, "no protocol version specified"
1845 " after vers= mount option");
1846 goto cifs_parse_mount_err;
1847 }
1848
1849 if (strnicmp(string, "cifs", 4) == 0 ||
1850 strnicmp(string, "1", 1) == 0) {
1851 /* This is the default */
1852 break;
1853 }
1854 /* For all other value, error */
1855 printk(KERN_WARNING "CIFS: Invalid version"
1856 " specified\n");
1591 goto cifs_parse_mount_err; 1857 goto cifs_parse_mount_err;
1858 case Opt_sec:
1859 string = match_strdup(args);
1860 if (string == NULL)
1861 goto out_nomem;
1862
1863 if (!*string) {
1864 printk(KERN_WARNING "CIFS: no security flavor"
1865 " specified\n");
1866 break;
1867 }
1868
1869 if (cifs_parse_security_flavors(string, vol) != 0)
1870 goto cifs_parse_mount_err;
1871 break;
1872 default:
1873 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1874 data);
1875 break;
1592 } 1876 }
1877 /* Free up any allocated string */
1878 kfree(string);
1879 string = NULL;
1593 } 1880 }
1594 1881
1595#ifndef CONFIG_KEYS 1882#ifndef CONFIG_KEYS
@@ -1619,7 +1906,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1619 kfree(mountdata_copy); 1906 kfree(mountdata_copy);
1620 return 0; 1907 return 0;
1621 1908
1909out_nomem:
1910 printk(KERN_WARNING "Could not allocate temporary buffer\n");
1622cifs_parse_mount_err: 1911cifs_parse_mount_err:
1912 kfree(string);
1623 kfree(mountdata_copy); 1913 kfree(mountdata_copy);
1624 return 1; 1914 return 1;
1625} 1915}