aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/AUTHORS2
-rw-r--r--fs/cifs/CHANGES9
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/README12
-rw-r--r--fs/cifs/cifs_dfs_ref.c48
-rw-r--r--fs/cifs/cifs_fs_sb.h7
-rw-r--r--fs/cifs/cifs_spnego.c6
-rw-r--r--fs/cifs/cifsencrypt.c30
-rw-r--r--fs/cifs/cifsencrypt.h3
-rw-r--r--fs/cifs/cifsfs.c82
-rw-r--r--fs/cifs/cifsfs.h3
-rw-r--r--fs/cifs/cifsglob.h15
-rw-r--r--fs/cifs/cifspdu.h2
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/cifssmb.c52
-rw-r--r--fs/cifs/connect.c685
-rw-r--r--fs/cifs/dir.c21
-rw-r--r--fs/cifs/fcntl.c118
-rw-r--r--fs/cifs/file.c102
-rw-r--r--fs/cifs/inode.c68
-rw-r--r--fs/cifs/ioctl.c2
-rw-r--r--fs/cifs/misc.c13
-rw-r--r--fs/cifs/sess.c5
-rw-r--r--fs/cifs/smbdes.c5
-rw-r--r--fs/cifs/smbencrypt.c9
-rw-r--r--fs/cifs/transport.c378
26 files changed, 902 insertions, 782 deletions
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
index 9c136d7803d9..7f7fa3c302af 100644
--- a/fs/cifs/AUTHORS
+++ b/fs/cifs/AUTHORS
@@ -36,7 +36,9 @@ Miklos Szeredi
36Kazeon team for various fixes especially for 2.4 version. 36Kazeon team for various fixes especially for 2.4 version.
37Asser Ferno (Change Notify support) 37Asser Ferno (Change Notify support)
38Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup 38Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup
39Gunter Kukkukk (testing and suggestions for support of old servers)
39Igor Mammedov (DFS support) 40Igor Mammedov (DFS support)
41Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code)
40 42
41Test case and Bug Report contributors 43Test case and Bug Report contributors
42------------------------------------- 44-------------------------------------
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index e078b7aea143..080703a15f44 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,12 @@
1Version 1.56
2------------
3Add "forcemandatorylock" mount option to allow user to use mandatory
4rather than posix (advisory) byte range locks, even though server would
5support posix byte range locks. Fix query of root inode when prefixpath
6specified and user does not have access to query information about the
7top of the share. Fix problem in 2.6.28 resolving DFS paths to
8Samba servers (worked to Windows).
9
1Version 1.55 10Version 1.55
2------------ 11------------
3Various fixes to make delete of open files behavior more predictable 12Various fixes to make delete of open files behavior more predictable
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 6ba43fb346fb..9948c0030e86 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -5,7 +5,7 @@ obj-$(CONFIG_CIFS) += cifs.o
5 5
6cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ 6cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
7 link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ 7 link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \
8 md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o \ 8 md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \
9 readdir.o ioctl.o sess.o export.o cifsacl.o 9 readdir.o ioctl.o sess.o export.o cifsacl.o
10 10
11cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o 11cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
diff --git a/fs/cifs/README b/fs/cifs/README
index a439dc1739b3..da4515e3be20 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -463,9 +463,19 @@ A partial list of the supported mount options follows:
463 with cifs style mandatory byte range locks (and most 463 with cifs style mandatory byte range locks (and most
464 cifs servers do not yet support requesting advisory 464 cifs servers do not yet support requesting advisory
465 byte range locks). 465 byte range locks).
466 forcemandatorylock Even if the server supports posix (advisory) byte range
467 locking, send only mandatory lock requests. For some
468 (presumably rare) applications, originally coded for
469 DOS/Windows, which require Windows style mandatory byte range
470 locking, they may be able to take advantage of this option,
471 forcing the cifs client to only send mandatory locks
472 even if the cifs server would support posix advisory locks.
473 "forcemand" is accepted as a shorter form of this mount
474 option.
466 nodfs Disable DFS (global name space support) even if the 475 nodfs Disable DFS (global name space support) even if the
467 server claims to support it. This can help work around 476 server claims to support it. This can help work around
468 a problem with parsing of DFS paths with Samba 3.0.24 server. 477 a problem with parsing of DFS paths with Samba server
478 versions 3.0.24 and 3.0.25.
469 remount remount the share (often used to change from ro to rw mounts 479 remount remount the share (often used to change from ro to rw mounts
470 or vice versa) 480 or vice versa)
471 cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for 481 cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index e1c18362ba46..85c0a74d034d 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -122,7 +122,7 @@ static char *compose_mount_options(const char *sb_mountdata,
122 char **devname) 122 char **devname)
123{ 123{
124 int rc; 124 int rc;
125 char *mountdata; 125 char *mountdata = NULL;
126 int md_len; 126 int md_len;
127 char *tkn_e; 127 char *tkn_e;
128 char *srvIP = NULL; 128 char *srvIP = NULL;
@@ -136,10 +136,9 @@ static char *compose_mount_options(const char *sb_mountdata,
136 *devname = cifs_get_share_name(ref->node_name); 136 *devname = cifs_get_share_name(ref->node_name);
137 rc = dns_resolve_server_name_to_ip(*devname, &srvIP); 137 rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
138 if (rc != 0) { 138 if (rc != 0) {
139 cERROR(1, ("%s: Failed to resolve server part of %s to IP", 139 cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d",
140 __func__, *devname)); 140 __func__, *devname, rc));;
141 mountdata = ERR_PTR(rc); 141 goto compose_mount_options_err;
142 goto compose_mount_options_out;
143 } 142 }
144 /* md_len = strlen(...) + 12 for 'sep+prefixpath=' 143 /* md_len = strlen(...) + 12 for 'sep+prefixpath='
145 * assuming that we have 'unc=' and 'ip=' in 144 * assuming that we have 'unc=' and 'ip=' in
@@ -149,8 +148,8 @@ static char *compose_mount_options(const char *sb_mountdata,
149 strlen(ref->node_name) + 12; 148 strlen(ref->node_name) + 12;
150 mountdata = kzalloc(md_len+1, GFP_KERNEL); 149 mountdata = kzalloc(md_len+1, GFP_KERNEL);
151 if (mountdata == NULL) { 150 if (mountdata == NULL) {
152 mountdata = ERR_PTR(-ENOMEM); 151 rc = -ENOMEM;
153 goto compose_mount_options_out; 152 goto compose_mount_options_err;
154 } 153 }
155 154
156 /* copy all options except of unc,ip,prefixpath */ 155 /* copy all options except of unc,ip,prefixpath */
@@ -197,18 +196,32 @@ static char *compose_mount_options(const char *sb_mountdata,
197 196
198 /* find & copy prefixpath */ 197 /* find & copy prefixpath */
199 tkn_e = strchr(ref->node_name + 2, '\\'); 198 tkn_e = strchr(ref->node_name + 2, '\\');
200 if (tkn_e == NULL) /* invalid unc, missing share name*/ 199 if (tkn_e == NULL) {
201 goto compose_mount_options_out; 200 /* invalid unc, missing share name*/
201 rc = -EINVAL;
202 goto compose_mount_options_err;
203 }
202 204
205 /*
206 * this function gives us a path with a double backslash prefix. We
207 * require a single backslash for DFS. Temporarily increment fullpath
208 * to put it in the proper form and decrement before freeing it.
209 */
203 fullpath = build_path_from_dentry(dentry); 210 fullpath = build_path_from_dentry(dentry);
211 if (!fullpath) {
212 rc = -ENOMEM;
213 goto compose_mount_options_err;
214 }
215 ++fullpath;
204 tkn_e = strchr(tkn_e + 1, '\\'); 216 tkn_e = strchr(tkn_e + 1, '\\');
205 if (tkn_e || strlen(fullpath) - (ref->path_consumed)) { 217 if (tkn_e || (strlen(fullpath) - ref->path_consumed)) {
206 strncat(mountdata, &sep, 1); 218 strncat(mountdata, &sep, 1);
207 strcat(mountdata, "prefixpath="); 219 strcat(mountdata, "prefixpath=");
208 if (tkn_e) 220 if (tkn_e)
209 strcat(mountdata, tkn_e + 1); 221 strcat(mountdata, tkn_e + 1);
210 strcat(mountdata, fullpath + (ref->path_consumed)); 222 strcat(mountdata, fullpath + ref->path_consumed);
211 } 223 }
224 --fullpath;
212 kfree(fullpath); 225 kfree(fullpath);
213 226
214 /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/ 227 /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
@@ -217,6 +230,11 @@ static char *compose_mount_options(const char *sb_mountdata,
217compose_mount_options_out: 230compose_mount_options_out:
218 kfree(srvIP); 231 kfree(srvIP);
219 return mountdata; 232 return mountdata;
233
234compose_mount_options_err:
235 kfree(mountdata);
236 mountdata = ERR_PTR(rc);
237 goto compose_mount_options_out;
220} 238}
221 239
222 240
@@ -309,13 +327,19 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
309 goto out_err; 327 goto out_err;
310 } 328 }
311 329
330 /*
331 * The MSDFS spec states that paths in DFS referral requests and
332 * responses must be prefixed by a single '\' character instead of
333 * the double backslashes usually used in the UNC. This function
334 * gives us the latter, so we must adjust the result.
335 */
312 full_path = build_path_from_dentry(dentry); 336 full_path = build_path_from_dentry(dentry);
313 if (full_path == NULL) { 337 if (full_path == NULL) {
314 rc = -ENOMEM; 338 rc = -ENOMEM;
315 goto out_err; 339 goto out_err;
316 } 340 }
317 341
318 rc = get_dfs_path(xid, ses , full_path, cifs_sb->local_nls, 342 rc = get_dfs_path(xid, ses , full_path + 1, cifs_sb->local_nls,
319 &num_referrals, &referrals, 343 &num_referrals, &referrals,
320 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 344 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
321 345
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 877c85409f1f..c4c306f7b06f 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -19,8 +19,8 @@
19#define _CIFS_FS_SB_H 19#define _CIFS_FS_SB_H
20 20
21#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */ 21#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
22#define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */ 22#define CIFS_MOUNT_SET_UID 2 /* set current's euid in create etc. */
23#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ 23#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ 24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ 25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ 26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
@@ -30,7 +30,8 @@
30#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ 30#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */
31#define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */ 31#define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */
32#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ 32#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */
33#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ 33#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */
34#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */
34 35
35struct cifs_sb_info { 36struct cifs_sb_info {
36 struct cifsTconInfo *tcon; /* primary mount */ 37 struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 0ab2fb5afef1..3fd3a9df043a 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -121,11 +121,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
121 121
122 /* add the server address */ 122 /* add the server address */
123 if (server->addr.sockAddr.sin_family == AF_INET) 123 if (server->addr.sockAddr.sin_family == AF_INET)
124 sprintf(dp, "ip4=" NIPQUAD_FMT, 124 sprintf(dp, "ip4=%pI4", &server->addr.sockAddr.sin_addr);
125 NIPQUAD(server->addr.sockAddr.sin_addr));
126 else if (server->addr.sockAddr.sin_family == AF_INET6) 125 else if (server->addr.sockAddr.sin_family == AF_INET6)
127 sprintf(dp, "ip6=" NIP6_SEQFMT, 126 sprintf(dp, "ip6=%pi6", &server->addr.sockAddr6.sin6_addr);
128 NIP6(server->addr.sockAddr6.sin6_addr));
129 else 127 else
130 goto out; 128 goto out;
131 129
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index bd5f13d38450..d4839cf0cb2c 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -37,7 +37,7 @@
37 37
38extern void mdfour(unsigned char *out, unsigned char *in, int n); 38extern void mdfour(unsigned char *out, unsigned char *in, int n);
39extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); 39extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
40extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, 40extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
41 unsigned char *p24); 41 unsigned char *p24);
42 42
43static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, 43static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
@@ -280,25 +280,22 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
280} 280}
281 281
282#ifdef CONFIG_CIFS_WEAK_PW_HASH 282#ifdef CONFIG_CIFS_WEAK_PW_HASH
283void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key) 283void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
284 char *lnm_session_key)
284{ 285{
285 int i; 286 int i;
286 char password_with_pad[CIFS_ENCPWD_SIZE]; 287 char password_with_pad[CIFS_ENCPWD_SIZE];
287 288
288 if (ses->server == NULL)
289 return;
290
291 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); 289 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
292 if (ses->password) 290 if (password)
293 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); 291 strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);
294 292
295 if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0) 293 if (!encrypt && extended_security & CIFSSEC_MAY_PLNTXT) {
296 if (extended_security & CIFSSEC_MAY_PLNTXT) { 294 memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE);
297 memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); 295 memcpy(lnm_session_key, password_with_pad,
298 memcpy(lnm_session_key, password_with_pad, 296 CIFS_ENCPWD_SIZE);
299 CIFS_ENCPWD_SIZE); 297 return;
300 return; 298 }
301 }
302 299
303 /* calculate old style session key */ 300 /* calculate old style session key */
304 /* calling toupper is less broken than repeatedly 301 /* calling toupper is less broken than repeatedly
@@ -314,7 +311,8 @@ void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key)
314 for (i = 0; i < CIFS_ENCPWD_SIZE; i++) 311 for (i = 0; i < CIFS_ENCPWD_SIZE; i++)
315 password_with_pad[i] = toupper(password_with_pad[i]); 312 password_with_pad[i] = toupper(password_with_pad[i]);
316 313
317 SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key); 314 SMBencrypt(password_with_pad, cryptkey, lnm_session_key);
315
318 /* clear password before we return/free memory */ 316 /* clear password before we return/free memory */
319 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); 317 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
320} 318}
diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h
index 152fa2dcfc6c..15d2ec006474 100644
--- a/fs/cifs/cifsencrypt.h
+++ b/fs/cifs/cifsencrypt.h
@@ -26,7 +26,8 @@
26extern void mdfour(unsigned char *out, unsigned char *in, int n); 26extern void mdfour(unsigned char *out, unsigned char *in, int n);
27/* smbdes.c */ 27/* smbdes.c */
28extern void E_P16(unsigned char *p14, unsigned char *p16); 28extern void E_P16(unsigned char *p14, unsigned char *p16);
29extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); 29extern void E_P24(unsigned char *p21, const unsigned char *c8,
30 unsigned char *p24);
30 31
31 32
32 33
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d9cf467309e8..13ea53251dcf 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -66,7 +66,9 @@ unsigned int sign_CIFS_PDUs = 1;
66extern struct task_struct *oplockThread; /* remove sparse warning */ 66extern struct task_struct *oplockThread; /* remove sparse warning */
67struct task_struct *oplockThread = NULL; 67struct task_struct *oplockThread = NULL;
68/* extern struct task_struct * dnotifyThread; remove sparse warning */ 68/* extern struct task_struct * dnotifyThread; remove sparse warning */
69#ifdef CONFIG_CIFS_EXPERIMENTAL
69static struct task_struct *dnotifyThread = NULL; 70static struct task_struct *dnotifyThread = NULL;
71#endif
70static const struct super_operations cifs_super_ops; 72static const struct super_operations cifs_super_ops;
71unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; 73unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
72module_param(CIFSMaxBufSize, int, 0); 74module_param(CIFSMaxBufSize, int, 0);
@@ -337,39 +339,58 @@ static int
337cifs_show_options(struct seq_file *s, struct vfsmount *m) 339cifs_show_options(struct seq_file *s, struct vfsmount *m)
338{ 340{
339 struct cifs_sb_info *cifs_sb; 341 struct cifs_sb_info *cifs_sb;
342 struct cifsTconInfo *tcon;
343 struct TCP_Server_Info *server;
340 344
341 cifs_sb = CIFS_SB(m->mnt_sb); 345 cifs_sb = CIFS_SB(m->mnt_sb);
342 346
343 if (cifs_sb) { 347 if (cifs_sb) {
344 if (cifs_sb->tcon) { 348 tcon = cifs_sb->tcon;
345/* BB add prepath to mount options displayed */ 349 if (tcon) {
346 seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); 350 seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
347 if (cifs_sb->tcon->ses) { 351 if (tcon->ses) {
348 if (cifs_sb->tcon->ses->userName) 352 if (tcon->ses->userName)
349 seq_printf(s, ",username=%s", 353 seq_printf(s, ",username=%s",
350 cifs_sb->tcon->ses->userName); 354 tcon->ses->userName);
351 if (cifs_sb->tcon->ses->domainName) 355 if (tcon->ses->domainName)
352 seq_printf(s, ",domain=%s", 356 seq_printf(s, ",domain=%s",
353 cifs_sb->tcon->ses->domainName); 357 tcon->ses->domainName);
358 server = tcon->ses->server;
359 if (server) {
360 seq_printf(s, ",addr=");
361 switch (server->addr.sockAddr6.
362 sin6_family) {
363 case AF_INET6:
364 seq_printf(s, "%pI6",
365 &server->addr.sockAddr6.sin6_addr);
366 break;
367 case AF_INET:
368 seq_printf(s, "%pI4",
369 &server->addr.sockAddr.sin_addr.s_addr);
370 break;
371 }
372 }
354 } 373 }
355 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) || 374 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
356 !(cifs_sb->tcon->unix_ext)) 375 !(tcon->unix_ext))
357 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); 376 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
358 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || 377 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
359 !(cifs_sb->tcon->unix_ext)) 378 !(tcon->unix_ext))
360 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); 379 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
361 if (!cifs_sb->tcon->unix_ext) { 380 if (!tcon->unix_ext) {
362 seq_printf(s, ",file_mode=0%o,dir_mode=0%o", 381 seq_printf(s, ",file_mode=0%o,dir_mode=0%o",
363 cifs_sb->mnt_file_mode, 382 cifs_sb->mnt_file_mode,
364 cifs_sb->mnt_dir_mode); 383 cifs_sb->mnt_dir_mode);
365 } 384 }
366 if (cifs_sb->tcon->seal) 385 if (tcon->seal)
367 seq_printf(s, ",seal"); 386 seq_printf(s, ",seal");
368 if (cifs_sb->tcon->nocase) 387 if (tcon->nocase)
369 seq_printf(s, ",nocase"); 388 seq_printf(s, ",nocase");
370 if (cifs_sb->tcon->retry) 389 if (tcon->retry)
371 seq_printf(s, ",hard"); 390 seq_printf(s, ",hard");
372 } 391 }
392 if (cifs_sb->prepath)
393 seq_printf(s, ",prepath=%s", cifs_sb->prepath);
373 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 394 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
374 seq_printf(s, ",posixpaths"); 395 seq_printf(s, ",posixpaths");
375 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) 396 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
@@ -417,9 +438,8 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
417 xid = GetXid(); 438 xid = GetXid();
418 if (pTcon) { 439 if (pTcon) {
419 cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); 440 cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
420 } else { 441 } else
421 rc = -EIO; 442 rc = -EIO;
422 }
423 443
424 FreeXid(xid); 444 FreeXid(xid);
425 return rc; 445 return rc;
@@ -441,9 +461,8 @@ int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
441 xid = GetXid(); 461 xid = GetXid();
442 if (pTcon) { 462 if (pTcon) {
443 cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); 463 cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
444 } else { 464 } else
445 rc = -EIO; 465 rc = -EIO;
446 }
447 466
448 FreeXid(xid); 467 FreeXid(xid);
449 return rc; 468 return rc;
@@ -464,9 +483,8 @@ int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation)
464 xid = GetXid(); 483 xid = GetXid();
465 if (pTcon) { 484 if (pTcon) {
466 cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation)); 485 cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
467 } else { 486 } else
468 rc = -EIO; 487 rc = -EIO;
469 }
470 488
471 FreeXid(xid); 489 FreeXid(xid);
472 return rc; 490 return rc;
@@ -479,17 +497,16 @@ int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats)
479 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 497 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
480 struct cifsTconInfo *pTcon; 498 struct cifsTconInfo *pTcon;
481 499
482 if (cifs_sb) { 500 if (cifs_sb)
483 pTcon = cifs_sb->tcon; 501 pTcon = cifs_sb->tcon;
484 } else { 502 else
485 return -EIO; 503 return -EIO;
486 } 504
487 xid = GetXid(); 505 xid = GetXid();
488 if (pTcon) { 506 if (pTcon) {
489 cFYI(1, ("pqstats %p", qstats)); 507 cFYI(1, ("pqstats %p", qstats));
490 } else { 508 } else
491 rc = -EIO; 509 rc = -EIO;
492 }
493 510
494 FreeXid(xid); 511 FreeXid(xid);
495 return rc; 512 return rc;
@@ -730,7 +747,6 @@ const struct file_operations cifs_file_ops = {
730#endif /* CONFIG_CIFS_POSIX */ 747#endif /* CONFIG_CIFS_POSIX */
731 748
732#ifdef CONFIG_CIFS_EXPERIMENTAL 749#ifdef CONFIG_CIFS_EXPERIMENTAL
733 .dir_notify = cifs_dir_notify,
734 .setlease = cifs_setlease, 750 .setlease = cifs_setlease,
735#endif /* CONFIG_CIFS_EXPERIMENTAL */ 751#endif /* CONFIG_CIFS_EXPERIMENTAL */
736}; 752};
@@ -751,7 +767,6 @@ const struct file_operations cifs_file_direct_ops = {
751#endif /* CONFIG_CIFS_POSIX */ 767#endif /* CONFIG_CIFS_POSIX */
752 .llseek = cifs_llseek, 768 .llseek = cifs_llseek,
753#ifdef CONFIG_CIFS_EXPERIMENTAL 769#ifdef CONFIG_CIFS_EXPERIMENTAL
754 .dir_notify = cifs_dir_notify,
755 .setlease = cifs_setlease, 770 .setlease = cifs_setlease,
756#endif /* CONFIG_CIFS_EXPERIMENTAL */ 771#endif /* CONFIG_CIFS_EXPERIMENTAL */
757}; 772};
@@ -772,7 +787,6 @@ const struct file_operations cifs_file_nobrl_ops = {
772#endif /* CONFIG_CIFS_POSIX */ 787#endif /* CONFIG_CIFS_POSIX */
773 788
774#ifdef CONFIG_CIFS_EXPERIMENTAL 789#ifdef CONFIG_CIFS_EXPERIMENTAL
775 .dir_notify = cifs_dir_notify,
776 .setlease = cifs_setlease, 790 .setlease = cifs_setlease,
777#endif /* CONFIG_CIFS_EXPERIMENTAL */ 791#endif /* CONFIG_CIFS_EXPERIMENTAL */
778}; 792};
@@ -792,7 +806,6 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
792#endif /* CONFIG_CIFS_POSIX */ 806#endif /* CONFIG_CIFS_POSIX */
793 .llseek = cifs_llseek, 807 .llseek = cifs_llseek,
794#ifdef CONFIG_CIFS_EXPERIMENTAL 808#ifdef CONFIG_CIFS_EXPERIMENTAL
795 .dir_notify = cifs_dir_notify,
796 .setlease = cifs_setlease, 809 .setlease = cifs_setlease,
797#endif /* CONFIG_CIFS_EXPERIMENTAL */ 810#endif /* CONFIG_CIFS_EXPERIMENTAL */
798}; 811};
@@ -801,9 +814,6 @@ const struct file_operations cifs_dir_ops = {
801 .readdir = cifs_readdir, 814 .readdir = cifs_readdir,
802 .release = cifs_closedir, 815 .release = cifs_closedir,
803 .read = generic_read_dir, 816 .read = generic_read_dir,
804#ifdef CONFIG_CIFS_EXPERIMENTAL
805 .dir_notify = cifs_dir_notify,
806#endif /* CONFIG_CIFS_EXPERIMENTAL */
807 .unlocked_ioctl = cifs_ioctl, 817 .unlocked_ioctl = cifs_ioctl,
808 .llseek = generic_file_llseek, 818 .llseek = generic_file_llseek,
809}; 819};
@@ -1029,6 +1039,7 @@ static int cifs_oplock_thread(void *dummyarg)
1029 return 0; 1039 return 0;
1030} 1040}
1031 1041
1042#ifdef CONFIG_CIFS_EXPERIMENTAL
1032static int cifs_dnotify_thread(void *dummyarg) 1043static int cifs_dnotify_thread(void *dummyarg)
1033{ 1044{
1034 struct list_head *tmp; 1045 struct list_head *tmp;
@@ -1054,6 +1065,7 @@ static int cifs_dnotify_thread(void *dummyarg)
1054 1065
1055 return 0; 1066 return 0;
1056} 1067}
1068#endif
1057 1069
1058static int __init 1070static int __init
1059init_cifs(void) 1071init_cifs(void)
@@ -1131,16 +1143,20 @@ init_cifs(void)
1131 goto out_unregister_dfs_key_type; 1143 goto out_unregister_dfs_key_type;
1132 } 1144 }
1133 1145
1146#ifdef CONFIG_CIFS_EXPERIMENTAL
1134 dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd"); 1147 dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
1135 if (IS_ERR(dnotifyThread)) { 1148 if (IS_ERR(dnotifyThread)) {
1136 rc = PTR_ERR(dnotifyThread); 1149 rc = PTR_ERR(dnotifyThread);
1137 cERROR(1, ("error %d create dnotify thread", rc)); 1150 cERROR(1, ("error %d create dnotify thread", rc));
1138 goto out_stop_oplock_thread; 1151 goto out_stop_oplock_thread;
1139 } 1152 }
1153#endif
1140 1154
1141 return 0; 1155 return 0;
1142 1156
1157#ifdef CONFIG_CIFS_EXPERIMENTAL
1143 out_stop_oplock_thread: 1158 out_stop_oplock_thread:
1159#endif
1144 kthread_stop(oplockThread); 1160 kthread_stop(oplockThread);
1145 out_unregister_dfs_key_type: 1161 out_unregister_dfs_key_type:
1146#ifdef CONFIG_CIFS_DFS_UPCALL 1162#ifdef CONFIG_CIFS_DFS_UPCALL
@@ -1179,8 +1195,10 @@ exit_cifs(void)
1179 cifs_destroy_inodecache(); 1195 cifs_destroy_inodecache();
1180 cifs_destroy_mids(); 1196 cifs_destroy_mids();
1181 cifs_destroy_request_bufs(); 1197 cifs_destroy_request_bufs();
1182 kthread_stop(oplockThread); 1198#ifdef CONFIG_CIFS_EXPERIMENTAL
1183 kthread_stop(dnotifyThread); 1199 kthread_stop(dnotifyThread);
1200#endif
1201 kthread_stop(oplockThread);
1184} 1202}
1185 1203
1186MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); 1204MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 074de0b5064d..7ac481841f87 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -76,7 +76,6 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
76extern const struct file_operations cifs_dir_ops; 76extern const struct file_operations cifs_dir_ops;
77extern int cifs_dir_open(struct inode *inode, struct file *file); 77extern int cifs_dir_open(struct inode *inode, struct file *file);
78extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); 78extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
79extern int cifs_dir_notify(struct file *, unsigned long arg);
80 79
81/* Functions related to dir entries */ 80/* Functions related to dir entries */
82extern struct dentry_operations cifs_dentry_ops; 81extern struct dentry_operations cifs_dentry_ops;
@@ -101,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
101extern const struct export_operations cifs_export_ops; 100extern const struct export_operations cifs_export_ops;
102#endif /* EXPERIMENTAL */ 101#endif /* EXPERIMENTAL */
103 102
104#define CIFS_VERSION "1.55" 103#define CIFS_VERSION "1.56"
105#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index c57c0565547f..94c1ca0ec953 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -47,7 +47,11 @@
47 */ 47 */
48#define CIFS_MAX_REQ 50 48#define CIFS_MAX_REQ 50
49 49
50#define SERVER_NAME_LENGTH 15 50#define RFC1001_NAME_LEN 15
51#define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1)
52
53/* currently length of NIP6_FMT */
54#define SERVER_NAME_LENGTH 40
51#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) 55#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
52 56
53/* used to define string lengths for reversing unicode strings */ 57/* used to define string lengths for reversing unicode strings */
@@ -125,8 +129,7 @@ struct TCP_Server_Info {
125 struct list_head smb_ses_list; 129 struct list_head smb_ses_list;
126 int srv_count; /* reference counter */ 130 int srv_count; /* reference counter */
127 /* 15 character server name + 0x20 16th byte indicating type = srv */ 131 /* 15 character server name + 0x20 16th byte indicating type = srv */
128 char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; 132 char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
129 char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
130 char *hostname; /* hostname portion of UNC string */ 133 char *hostname; /* hostname portion of UNC string */
131 struct socket *ssocket; 134 struct socket *ssocket;
132 union { 135 union {
@@ -151,7 +154,7 @@ struct TCP_Server_Info {
151 atomic_t num_waiters; /* blocked waiting to get in sendrecv */ 154 atomic_t num_waiters; /* blocked waiting to get in sendrecv */
152#endif 155#endif
153 enum statusEnum tcpStatus; /* what we think the status is */ 156 enum statusEnum tcpStatus; /* what we think the status is */
154 struct semaphore tcpSem; 157 struct mutex srv_mutex;
155 struct task_struct *tsk; 158 struct task_struct *tsk;
156 char server_GUID[16]; 159 char server_GUID[16];
157 char secMode; 160 char secMode;
@@ -171,7 +174,7 @@ struct TCP_Server_Info {
171 __u16 CurrentMid; /* multiplex id - rotating counter */ 174 __u16 CurrentMid; /* multiplex id - rotating counter */
172 char cryptKey[CIFS_CRYPTO_KEY_SIZE]; 175 char cryptKey[CIFS_CRYPTO_KEY_SIZE];
173 /* 16th byte of RFC1001 workstation name is always null */ 176 /* 16th byte of RFC1001 workstation name is always null */
174 char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; 177 char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
175 __u32 sequence_number; /* needed for CIFS PDU signature */ 178 __u32 sequence_number; /* needed for CIFS PDU signature */
176 struct mac_key mac_signing_key; 179 struct mac_key mac_signing_key;
177 char ntlmv2_hash[16]; 180 char ntlmv2_hash[16];
@@ -239,6 +242,7 @@ struct cifsTconInfo {
239 struct cifsSesInfo *ses; /* pointer to session associated with */ 242 struct cifsSesInfo *ses; /* pointer to session associated with */
240 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */ 243 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
241 char *nativeFileSystem; 244 char *nativeFileSystem;
245 char *password; /* for share-level security */
242 __u16 tid; /* The 2 byte tree id */ 246 __u16 tid; /* The 2 byte tree id */
243 __u16 Flags; /* optional support bits */ 247 __u16 Flags; /* optional support bits */
244 enum statusEnum tidStatus; 248 enum statusEnum tidStatus;
@@ -422,7 +426,6 @@ struct mid_q_entry {
422 unsigned long when_sent; /* time when smb send finished */ 426 unsigned long when_sent; /* time when smb send finished */
423 unsigned long when_received; /* when demux complete (taken off wire) */ 427 unsigned long when_received; /* when demux complete (taken off wire) */
424#endif 428#endif
425 struct cifsSesInfo *ses; /* smb was sent to this server */
426 struct task_struct *tsk; /* task waiting for response */ 429 struct task_struct *tsk; /* task waiting for response */
427 struct smb_hdr *resp_buf; /* response buffer */ 430 struct smb_hdr *resp_buf; /* response buffer */
428 int midState; /* wish this were enum but can not pass to wait_event */ 431 int midState; /* wish this were enum but can not pass to wait_event */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index d2a073edd1b8..b4e2e9f0ee3d 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1922,7 +1922,7 @@ typedef struct smb_com_transaction2_get_dfs_refer_req {
1922/* DFS server target type */ 1922/* DFS server target type */
1923#define DFS_TYPE_LINK 0x0000 /* also for sysvol targets */ 1923#define DFS_TYPE_LINK 0x0000 /* also for sysvol targets */
1924#define DFS_TYPE_ROOT 0x0001 1924#define DFS_TYPE_ROOT 0x0001
1925 1925
1926/* Referral Entry Flags */ 1926/* Referral Entry Flags */
1927#define DFS_NAME_LIST_REF 0x0200 1927#define DFS_NAME_LIST_REF 0x0200
1928 1928
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 6f21ecb85ce5..06f6779988bf 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -39,7 +39,7 @@ extern int smb_send(struct socket *, struct smb_hdr *,
39 unsigned int /* length */ , struct sockaddr *, bool); 39 unsigned int /* length */ , struct sockaddr *, bool);
40extern unsigned int _GetXid(void); 40extern unsigned int _GetXid(void);
41extern void _FreeXid(unsigned int); 41extern void _FreeXid(unsigned int);
42#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid)); 42#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
43#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} 43#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
44extern char *build_path_from_dentry(struct dentry *); 44extern char *build_path_from_dentry(struct dentry *);
45extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 45extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
@@ -330,7 +330,8 @@ extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
330extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, 330extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
331 const struct nls_table *); 331 const struct nls_table *);
332#ifdef CONFIG_CIFS_WEAK_PW_HASH 332#ifdef CONFIG_CIFS_WEAK_PW_HASH
333extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); 333extern void calc_lanman_hash(const char *password, const char *cryptkey,
334 bool encrypt, char *lnm_session_key);
334#endif /* CIFS_WEAK_PW_HASH */ 335#endif /* CIFS_WEAK_PW_HASH */
335extern int CIFSSMBCopy(int xid, 336extern int CIFSSMBCopy(int xid,
336 struct cifsTconInfo *source_tcon, 337 struct cifsTconInfo *source_tcon,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 2af8626ced43..552642a507c4 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1382,13 +1382,13 @@ openRetry:
1382 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) 1382 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1383 *pOplock |= CIFS_CREATE_ACTION; 1383 *pOplock |= CIFS_CREATE_ACTION;
1384 if (pfile_info) { 1384 if (pfile_info) {
1385 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime, 1385 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1386 36 /* CreationTime to Attributes */); 1386 36 /* CreationTime to Attributes */);
1387 /* the file_info buf is endian converted by caller */ 1387 /* the file_info buf is endian converted by caller */
1388 pfile_info->AllocationSize = pSMBr->AllocationSize; 1388 pfile_info->AllocationSize = pSMBr->AllocationSize;
1389 pfile_info->EndOfFile = pSMBr->EndOfFile; 1389 pfile_info->EndOfFile = pSMBr->EndOfFile;
1390 pfile_info->NumberOfLinks = cpu_to_le32(1); 1390 pfile_info->NumberOfLinks = cpu_to_le32(1);
1391 pfile_info->DeletePending = 0; 1391 pfile_info->DeletePending = 0;
1392 } 1392 }
1393 } 1393 }
1394 1394
@@ -1414,8 +1414,13 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1414 cFYI(1, ("Reading %d bytes on fid %d", count, netfid)); 1414 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1415 if (tcon->ses->capabilities & CAP_LARGE_FILES) 1415 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1416 wct = 12; 1416 wct = 12;
1417 else 1417 else {
1418 wct = 10; /* old style read */ 1418 wct = 10; /* old style read */
1419 if ((lseek >> 32) > 0) {
1420 /* can not handle this big offset for old */
1421 return -EIO;
1422 }
1423 }
1419 1424
1420 *nbytes = 0; 1425 *nbytes = 0;
1421 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB); 1426 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
@@ -1431,8 +1436,6 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1431 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 1436 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1432 if (wct == 12) 1437 if (wct == 12)
1433 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 1438 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1434 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1435 return -EIO;
1436 1439
1437 pSMB->Remaining = 0; 1440 pSMB->Remaining = 0;
1438 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 1441 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
@@ -1519,8 +1522,13 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1519 1522
1520 if (tcon->ses->capabilities & CAP_LARGE_FILES) 1523 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1521 wct = 14; 1524 wct = 14;
1522 else 1525 else {
1523 wct = 12; 1526 wct = 12;
1527 if ((offset >> 32) > 0) {
1528 /* can not handle big offset for old srv */
1529 return -EIO;
1530 }
1531 }
1524 1532
1525 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB, 1533 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1526 (void **) &pSMBr); 1534 (void **) &pSMBr);
@@ -1535,8 +1543,6 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1535 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1543 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1536 if (wct == 14) 1544 if (wct == 14)
1537 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1545 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1538 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1539 return -EIO;
1540 1546
1541 pSMB->Reserved = 0xFFFFFFFF; 1547 pSMB->Reserved = 0xFFFFFFFF;
1542 pSMB->WriteMode = 0; 1548 pSMB->WriteMode = 0;
@@ -1558,7 +1564,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1558 pSMB->DataOffset = 1564 pSMB->DataOffset =
1559 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); 1565 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1560 if (buf) 1566 if (buf)
1561 memcpy(pSMB->Data, buf, bytes_sent); 1567 memcpy(pSMB->Data, buf, bytes_sent);
1562 else if (ubuf) { 1568 else if (ubuf) {
1563 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) { 1569 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1564 cifs_buf_release(pSMB); 1570 cifs_buf_release(pSMB);
@@ -1621,10 +1627,15 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1621 1627
1622 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count)); 1628 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1623 1629
1624 if (tcon->ses->capabilities & CAP_LARGE_FILES) 1630 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1625 wct = 14; 1631 wct = 14;
1626 else 1632 } else {
1627 wct = 12; 1633 wct = 12;
1634 if ((offset >> 32) > 0) {
1635 /* can not handle big offset for old srv */
1636 return -EIO;
1637 }
1638 }
1628 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB); 1639 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1629 if (rc) 1640 if (rc)
1630 return rc; 1641 return rc;
@@ -1637,8 +1648,6 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1637 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1648 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1638 if (wct == 14) 1649 if (wct == 14)
1639 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1650 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1640 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1641 return -EIO;
1642 pSMB->Reserved = 0xFFFFFFFF; 1651 pSMB->Reserved = 0xFFFFFFFF;
1643 pSMB->WriteMode = 0; 1652 pSMB->WriteMode = 0;
1644 pSMB->Remaining = 0; 1653 pSMB->Remaining = 0;
@@ -1862,10 +1871,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1862 rc = -EIO; /* bad smb */ 1871 rc = -EIO; /* bad smb */
1863 goto plk_err_exit; 1872 goto plk_err_exit;
1864 } 1873 }
1865 if (pLockData == NULL) {
1866 rc = -EINVAL;
1867 goto plk_err_exit;
1868 }
1869 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 1874 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1870 data_count = le16_to_cpu(pSMBr->t2.DataCount); 1875 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1871 if (data_count < sizeof(struct cifs_posix_lock)) { 1876 if (data_count < sizeof(struct cifs_posix_lock)) {
@@ -3983,7 +3988,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3983 3988
3984 node->flags = le16_to_cpu(pSMBr->DFSFlags); 3989 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3985 if (is_unicode) { 3990 if (is_unicode) {
3986 __le16 *tmp = kmalloc(strlen(searchName)*2, GFP_KERNEL); 3991 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3992 GFP_KERNEL);
3987 cifsConvertToUCS((__le16 *) tmp, searchName, 3993 cifsConvertToUCS((__le16 *) tmp, searchName,
3988 PATH_MAX, nls_codepage, remap); 3994 PATH_MAX, nls_codepage, remap);
3989 node->path_consumed = hostlen_fromUCS(tmp, 3995 node->path_consumed = hostlen_fromUCS(tmp,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c7d341714586..e9ea394ee075 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -89,6 +89,7 @@ struct smb_vol {
89 bool nullauth:1; /* attempt to authenticate with null user */ 89 bool nullauth:1; /* attempt to authenticate with null user */
90 bool nocase:1; /* request case insensitive filenames */ 90 bool nocase:1; /* request case insensitive filenames */
91 bool nobrl:1; /* disable sending byte range locks to srv */ 91 bool nobrl:1; /* disable sending byte range locks to srv */
92 bool mand_lock:1; /* send mandatory not posix byte range lock reqs */
92 bool seal:1; /* request transport encryption on share */ 93 bool seal:1; /* request transport encryption on share */
93 bool nodfs:1; /* Do not request DFS, even if available */ 94 bool nodfs:1; /* Do not request DFS, even if available */
94 bool local_lease:1; /* check leases only on local system, not remote */ 95 bool local_lease:1; /* check leases only on local system, not remote */
@@ -101,25 +102,17 @@ struct smb_vol {
101 char *prepath; 102 char *prepath;
102}; 103};
103 104
104static int ipv4_connect(struct sockaddr_in *psin_server, 105static int ipv4_connect(struct TCP_Server_Info *server);
105 struct socket **csocket, 106static int ipv6_connect(struct TCP_Server_Info *server);
106 char *netb_name,
107 char *server_netb_name,
108 bool noblocksnd,
109 bool nosndbuf); /* ipv6 never set sndbuf size */
110static int ipv6_connect(struct sockaddr_in6 *psin_server,
111 struct socket **csocket, bool noblocksnd);
112
113
114 /*
115 * cifs tcp session reconnection
116 *
117 * mark tcp session as reconnecting so temporarily locked
118 * mark all smb sessions as reconnecting for tcp session
119 * reconnect tcp session
120 * wake up waiters on reconnection? - (not needed currently)
121 */
122 107
108/*
109 * cifs tcp session reconnection
110 *
111 * mark tcp session as reconnecting so temporarily locked
112 * mark all smb sessions as reconnecting for tcp session
113 * reconnect tcp session
114 * wake up waiters on reconnection? - (not needed currently)
115 */
123static int 116static int
124cifs_reconnect(struct TCP_Server_Info *server) 117cifs_reconnect(struct TCP_Server_Info *server)
125{ 118{
@@ -156,7 +149,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
156 } 149 }
157 read_unlock(&cifs_tcp_ses_lock); 150 read_unlock(&cifs_tcp_ses_lock);
158 /* do not want to be sending data on a socket we are freeing */ 151 /* do not want to be sending data on a socket we are freeing */
159 down(&server->tcpSem); 152 mutex_lock(&server->srv_mutex);
160 if (server->ssocket) { 153 if (server->ssocket) {
161 cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state, 154 cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
162 server->ssocket->flags)); 155 server->ssocket->flags));
@@ -182,21 +175,15 @@ cifs_reconnect(struct TCP_Server_Info *server)
182 } 175 }
183 } 176 }
184 spin_unlock(&GlobalMid_Lock); 177 spin_unlock(&GlobalMid_Lock);
185 up(&server->tcpSem); 178 mutex_unlock(&server->srv_mutex);
186 179
187 while ((server->tcpStatus != CifsExiting) && 180 while ((server->tcpStatus != CifsExiting) &&
188 (server->tcpStatus != CifsGood)) { 181 (server->tcpStatus != CifsGood)) {
189 try_to_freeze(); 182 try_to_freeze();
190 if (server->addr.sockAddr6.sin6_family == AF_INET6) { 183 if (server->addr.sockAddr6.sin6_family == AF_INET6)
191 rc = ipv6_connect(&server->addr.sockAddr6, 184 rc = ipv6_connect(server);
192 &server->ssocket, server->noautotune); 185 else
193 } else { 186 rc = ipv4_connect(server);
194 rc = ipv4_connect(&server->addr.sockAddr,
195 &server->ssocket,
196 server->workstation_RFC1001_name,
197 server->server_RFC1001_name,
198 server->noblocksnd, server->noautotune);
199 }
200 if (rc) { 187 if (rc) {
201 cFYI(1, ("reconnect error %d", rc)); 188 cFYI(1, ("reconnect error %d", rc));
202 msleep(3000); 189 msleep(3000);
@@ -776,7 +763,7 @@ multi_t2_fnd:
776 set_current_state(TASK_RUNNING); 763 set_current_state(TASK_RUNNING);
777 } 764 }
778 765
779 return 0; 766 module_put_and_exit(0);
780} 767}
781 768
782/* extract the host portion of the UNC string */ 769/* extract the host portion of the UNC string */
@@ -836,8 +823,8 @@ cifs_parse_mount_options(char *options, const char *devname,
836 /* null target name indicates to use *SMBSERVR default called name 823 /* null target name indicates to use *SMBSERVR default called name
837 if we end up sending RFC1001 session initialize */ 824 if we end up sending RFC1001 session initialize */
838 vol->target_rfc1001_name[0] = 0; 825 vol->target_rfc1001_name[0] = 0;
839 vol->linux_uid = current->uid; /* current->euid instead? */ 826 vol->linux_uid = current_uid(); /* use current_euid() instead? */
840 vol->linux_gid = current->gid; 827 vol->linux_gid = current_gid();
841 vol->dir_mode = S_IRWXUGO; 828 vol->dir_mode = S_IRWXUGO;
842 /* 2767 perms indicate mandatory locking support */ 829 /* 2767 perms indicate mandatory locking support */
843 vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP); 830 vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
@@ -1260,6 +1247,17 @@ cifs_parse_mount_options(char *options, const char *devname,
1260 if (vol->file_mode == 1247 if (vol->file_mode ==
1261 (S_IALLUGO & ~(S_ISUID | S_IXGRP))) 1248 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1262 vol->file_mode = S_IALLUGO; 1249 vol->file_mode = S_IALLUGO;
1250 } else if (strnicmp(data, "forcemandatorylock", 9) == 0) {
1251 /* will take the shorter form "forcemand" as well */
1252 /* This mount option will force use of mandatory
1253 (DOS/Windows style) byte range locks, instead of
1254 using posix advisory byte range locks, even if the
1255 Unix extensions are available and posix locks would
1256 be supported otherwise. If Unix extensions are not
1257 negotiated this has no effect since mandatory locks
1258 would be used (mandatory locks is all that those
1259 those servers support) */
1260 vol->mand_lock = 1;
1263 } else if (strnicmp(data, "setuids", 7) == 0) { 1261 } else if (strnicmp(data, "setuids", 7) == 0) {
1264 vol->setuids = 1; 1262 vol->setuids = 1;
1265 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1263 } else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -1417,6 +1415,143 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
1417 force_sig(SIGKILL, task); 1415 force_sig(SIGKILL, task);
1418} 1416}
1419 1417
1418static struct TCP_Server_Info *
1419cifs_get_tcp_session(struct smb_vol *volume_info)
1420{
1421 struct TCP_Server_Info *tcp_ses = NULL;
1422 struct sockaddr addr;
1423 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
1424 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
1425 int rc;
1426
1427 memset(&addr, 0, sizeof(struct sockaddr));
1428
1429 if (volume_info->UNCip && volume_info->UNC) {
1430 rc = cifs_inet_pton(AF_INET, volume_info->UNCip,
1431 &sin_server->sin_addr.s_addr);
1432
1433 if (rc <= 0) {
1434 /* not ipv4 address, try ipv6 */
1435 rc = cifs_inet_pton(AF_INET6, volume_info->UNCip,
1436 &sin_server6->sin6_addr.in6_u);
1437 if (rc > 0)
1438 addr.sa_family = AF_INET6;
1439 } else {
1440 addr.sa_family = AF_INET;
1441 }
1442
1443 if (rc <= 0) {
1444 /* we failed translating address */
1445 rc = -EINVAL;
1446 goto out_err;
1447 }
1448
1449 cFYI(1, ("UNC: %s ip: %s", volume_info->UNC,
1450 volume_info->UNCip));
1451 } else if (volume_info->UNCip) {
1452 /* BB using ip addr as tcp_ses name to connect to the
1453 DFS root below */
1454 cERROR(1, ("Connecting to DFS root not implemented yet"));
1455 rc = -EINVAL;
1456 goto out_err;
1457 } else /* which tcp_sess DFS root would we conect to */ {
1458 cERROR(1,
1459 ("CIFS mount error: No UNC path (e.g. -o "
1460 "unc=//192.168.1.100/public) specified"));
1461 rc = -EINVAL;
1462 goto out_err;
1463 }
1464
1465 /* see if we already have a matching tcp_ses */
1466 tcp_ses = cifs_find_tcp_session(&addr);
1467 if (tcp_ses)
1468 return tcp_ses;
1469
1470 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
1471 if (!tcp_ses) {
1472 rc = -ENOMEM;
1473 goto out_err;
1474 }
1475
1476 tcp_ses->hostname = extract_hostname(volume_info->UNC);
1477 if (IS_ERR(tcp_ses->hostname)) {
1478 rc = PTR_ERR(tcp_ses->hostname);
1479 goto out_err;
1480 }
1481
1482 tcp_ses->noblocksnd = volume_info->noblocksnd;
1483 tcp_ses->noautotune = volume_info->noautotune;
1484 atomic_set(&tcp_ses->inFlight, 0);
1485 init_waitqueue_head(&tcp_ses->response_q);
1486 init_waitqueue_head(&tcp_ses->request_q);
1487 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
1488 mutex_init(&tcp_ses->srv_mutex);
1489 memcpy(tcp_ses->workstation_RFC1001_name,
1490 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1491 memcpy(tcp_ses->server_RFC1001_name,
1492 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1493 tcp_ses->sequence_number = 0;
1494 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
1495 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
1496
1497 /*
1498 * at this point we are the only ones with the pointer
1499 * to the struct since the kernel thread not created yet
1500 * no need to spinlock this init of tcpStatus or srv_count
1501 */
1502 tcp_ses->tcpStatus = CifsNew;
1503 ++tcp_ses->srv_count;
1504
1505 if (addr.sa_family == AF_INET6) {
1506 cFYI(1, ("attempting ipv6 connect"));
1507 /* BB should we allow ipv6 on port 139? */
1508 /* other OS never observed in Wild doing 139 with v6 */
1509 memcpy(&tcp_ses->addr.sockAddr6, sin_server6,
1510 sizeof(struct sockaddr_in6));
1511 sin_server6->sin6_port = htons(volume_info->port);
1512 rc = ipv6_connect(tcp_ses);
1513 } else {
1514 memcpy(&tcp_ses->addr.sockAddr, sin_server,
1515 sizeof(struct sockaddr_in));
1516 sin_server->sin_port = htons(volume_info->port);
1517 rc = ipv4_connect(tcp_ses);
1518 }
1519 if (rc < 0) {
1520 cERROR(1, ("Error connecting to socket. Aborting operation"));
1521 goto out_err;
1522 }
1523
1524 /*
1525 * since we're in a cifs function already, we know that
1526 * this will succeed. No need for try_module_get().
1527 */
1528 __module_get(THIS_MODULE);
1529 tcp_ses->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread,
1530 tcp_ses, "cifsd");
1531 if (IS_ERR(tcp_ses->tsk)) {
1532 rc = PTR_ERR(tcp_ses->tsk);
1533 cERROR(1, ("error %d create cifsd thread", rc));
1534 module_put(THIS_MODULE);
1535 goto out_err;
1536 }
1537
1538 /* thread spawned, put it on the list */
1539 write_lock(&cifs_tcp_ses_lock);
1540 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
1541 write_unlock(&cifs_tcp_ses_lock);
1542
1543 return tcp_ses;
1544
1545out_err:
1546 if (tcp_ses) {
1547 kfree(tcp_ses->hostname);
1548 if (tcp_ses->ssocket)
1549 sock_release(tcp_ses->ssocket);
1550 kfree(tcp_ses);
1551 }
1552 return ERR_PTR(rc);
1553}
1554
1420static struct cifsSesInfo * 1555static struct cifsSesInfo *
1421cifs_find_smb_ses(struct TCP_Server_Info *server, char *username) 1556cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
1422{ 1557{
@@ -1593,93 +1728,96 @@ static void rfc1002mangle(char *target, char *source, unsigned int length)
1593 1728
1594 1729
1595static int 1730static int
1596ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, 1731ipv4_connect(struct TCP_Server_Info *server)
1597 char *netbios_name, char *target_name,
1598 bool noblocksnd, bool noautotune)
1599{ 1732{
1600 int rc = 0; 1733 int rc = 0;
1601 int connected = 0; 1734 bool connected = false;
1602 __be16 orig_port = 0; 1735 __be16 orig_port = 0;
1736 struct socket *socket = server->ssocket;
1603 1737
1604 if (*csocket == NULL) { 1738 if (socket == NULL) {
1605 rc = sock_create_kern(PF_INET, SOCK_STREAM, 1739 rc = sock_create_kern(PF_INET, SOCK_STREAM,
1606 IPPROTO_TCP, csocket); 1740 IPPROTO_TCP, &socket);
1607 if (rc < 0) { 1741 if (rc < 0) {
1608 cERROR(1, ("Error %d creating socket", rc)); 1742 cERROR(1, ("Error %d creating socket", rc));
1609 *csocket = NULL;
1610 return rc; 1743 return rc;
1611 } else {
1612 /* BB other socket options to set KEEPALIVE, NODELAY? */
1613 cFYI(1, ("Socket created"));
1614 (*csocket)->sk->sk_allocation = GFP_NOFS;
1615 cifs_reclassify_socket4(*csocket);
1616 } 1744 }
1745
1746 /* BB other socket options to set KEEPALIVE, NODELAY? */
1747 cFYI(1, ("Socket created"));
1748 server->ssocket = socket;
1749 socket->sk->sk_allocation = GFP_NOFS;
1750 cifs_reclassify_socket4(socket);
1617 } 1751 }
1618 1752
1619 psin_server->sin_family = AF_INET; 1753 /* user overrode default port */
1620 if (psin_server->sin_port) { /* user overrode default port */ 1754 if (server->addr.sockAddr.sin_port) {
1621 rc = (*csocket)->ops->connect(*csocket, 1755 rc = socket->ops->connect(socket, (struct sockaddr *)
1622 (struct sockaddr *) psin_server, 1756 &server->addr.sockAddr,
1623 sizeof(struct sockaddr_in), 0); 1757 sizeof(struct sockaddr_in), 0);
1624 if (rc >= 0) 1758 if (rc >= 0)
1625 connected = 1; 1759 connected = true;
1626 } 1760 }
1627 1761
1628 if (!connected) { 1762 if (!connected) {
1629 /* save original port so we can retry user specified port 1763 /* save original port so we can retry user specified port
1630 later if fall back ports fail this time */ 1764 later if fall back ports fail this time */
1631 orig_port = psin_server->sin_port; 1765 orig_port = server->addr.sockAddr.sin_port;
1632 1766
1633 /* do not retry on the same port we just failed on */ 1767 /* do not retry on the same port we just failed on */
1634 if (psin_server->sin_port != htons(CIFS_PORT)) { 1768 if (server->addr.sockAddr.sin_port != htons(CIFS_PORT)) {
1635 psin_server->sin_port = htons(CIFS_PORT); 1769 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
1636 1770 rc = socket->ops->connect(socket,
1637 rc = (*csocket)->ops->connect(*csocket, 1771 (struct sockaddr *)
1638 (struct sockaddr *) psin_server, 1772 &server->addr.sockAddr,
1639 sizeof(struct sockaddr_in), 0); 1773 sizeof(struct sockaddr_in), 0);
1640 if (rc >= 0) 1774 if (rc >= 0)
1641 connected = 1; 1775 connected = true;
1642 } 1776 }
1643 } 1777 }
1644 if (!connected) { 1778 if (!connected) {
1645 psin_server->sin_port = htons(RFC1001_PORT); 1779 server->addr.sockAddr.sin_port = htons(RFC1001_PORT);
1646 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) 1780 rc = socket->ops->connect(socket, (struct sockaddr *)
1647 psin_server, 1781 &server->addr.sockAddr,
1648 sizeof(struct sockaddr_in), 0); 1782 sizeof(struct sockaddr_in), 0);
1649 if (rc >= 0) 1783 if (rc >= 0)
1650 connected = 1; 1784 connected = true;
1651 } 1785 }
1652 1786
1653 /* give up here - unless we want to retry on different 1787 /* give up here - unless we want to retry on different
1654 protocol families some day */ 1788 protocol families some day */
1655 if (!connected) { 1789 if (!connected) {
1656 if (orig_port) 1790 if (orig_port)
1657 psin_server->sin_port = orig_port; 1791 server->addr.sockAddr.sin_port = orig_port;
1658 cFYI(1, ("Error %d connecting to server via ipv4", rc)); 1792 cFYI(1, ("Error %d connecting to server via ipv4", rc));
1659 sock_release(*csocket); 1793 sock_release(socket);
1660 *csocket = NULL; 1794 server->ssocket = NULL;
1661 return rc; 1795 return rc;
1662 } 1796 }
1663 /* Eventually check for other socket options to change from 1797
1664 the default. sock_setsockopt not used because it expects 1798
1665 user space buffer */ 1799 /*
1666 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx", 1800 * Eventually check for other socket options to change from
1667 (*csocket)->sk->sk_sndbuf, 1801 * the default. sock_setsockopt not used because it expects
1668 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); 1802 * user space buffer
1669 (*csocket)->sk->sk_rcvtimeo = 7 * HZ; 1803 */
1670 if (!noblocksnd) 1804 socket->sk->sk_rcvtimeo = 7 * HZ;
1671 (*csocket)->sk->sk_sndtimeo = 3 * HZ; 1805 socket->sk->sk_sndtimeo = 3 * HZ;
1672 1806
1673 /* make the bufsizes depend on wsize/rsize and max requests */ 1807 /* make the bufsizes depend on wsize/rsize and max requests */
1674 if (noautotune) { 1808 if (server->noautotune) {
1675 if ((*csocket)->sk->sk_sndbuf < (200 * 1024)) 1809 if (socket->sk->sk_sndbuf < (200 * 1024))
1676 (*csocket)->sk->sk_sndbuf = 200 * 1024; 1810 socket->sk->sk_sndbuf = 200 * 1024;
1677 if ((*csocket)->sk->sk_rcvbuf < (140 * 1024)) 1811 if (socket->sk->sk_rcvbuf < (140 * 1024))
1678 (*csocket)->sk->sk_rcvbuf = 140 * 1024; 1812 socket->sk->sk_rcvbuf = 140 * 1024;
1679 } 1813 }
1680 1814
1815 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
1816 socket->sk->sk_sndbuf,
1817 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo));
1818
1681 /* send RFC1001 sessinit */ 1819 /* send RFC1001 sessinit */
1682 if (psin_server->sin_port == htons(RFC1001_PORT)) { 1820 if (server->addr.sockAddr.sin_port == htons(RFC1001_PORT)) {
1683 /* some servers require RFC1001 sessinit before sending 1821 /* some servers require RFC1001 sessinit before sending
1684 negprot - BB check reconnection in case where second 1822 negprot - BB check reconnection in case where second
1685 sessinit is sent but no second negprot */ 1823 sessinit is sent but no second negprot */
@@ -1689,31 +1827,42 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1689 GFP_KERNEL); 1827 GFP_KERNEL);
1690 if (ses_init_buf) { 1828 if (ses_init_buf) {
1691 ses_init_buf->trailer.session_req.called_len = 32; 1829 ses_init_buf->trailer.session_req.called_len = 32;
1692 if (target_name && (target_name[0] != 0)) { 1830 if (server->server_RFC1001_name &&
1693 rfc1002mangle(ses_init_buf->trailer.session_req.called_name, 1831 server->server_RFC1001_name[0] != 0)
1694 target_name, 16); 1832 rfc1002mangle(ses_init_buf->trailer.
1695 } else { 1833 session_req.called_name,
1696 rfc1002mangle(ses_init_buf->trailer.session_req.called_name, 1834 server->server_RFC1001_name,
1697 DEFAULT_CIFS_CALLED_NAME, 16); 1835 RFC1001_NAME_LEN_WITH_NULL);
1698 } 1836 else
1837 rfc1002mangle(ses_init_buf->trailer.
1838 session_req.called_name,
1839 DEFAULT_CIFS_CALLED_NAME,
1840 RFC1001_NAME_LEN_WITH_NULL);
1699 1841
1700 ses_init_buf->trailer.session_req.calling_len = 32; 1842 ses_init_buf->trailer.session_req.calling_len = 32;
1843
1701 /* calling name ends in null (byte 16) from old smb 1844 /* calling name ends in null (byte 16) from old smb
1702 convention. */ 1845 convention. */
1703 if (netbios_name && (netbios_name[0] != 0)) { 1846 if (server->workstation_RFC1001_name &&
1704 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name, 1847 server->workstation_RFC1001_name[0] != 0)
1705 netbios_name, 16); 1848 rfc1002mangle(ses_init_buf->trailer.
1706 } else { 1849 session_req.calling_name,
1707 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name, 1850 server->workstation_RFC1001_name,
1708 "LINUX_CIFS_CLNT", 16); 1851 RFC1001_NAME_LEN_WITH_NULL);
1709 } 1852 else
1853 rfc1002mangle(ses_init_buf->trailer.
1854 session_req.calling_name,
1855 "LINUX_CIFS_CLNT",
1856 RFC1001_NAME_LEN_WITH_NULL);
1857
1710 ses_init_buf->trailer.session_req.scope1 = 0; 1858 ses_init_buf->trailer.session_req.scope1 = 0;
1711 ses_init_buf->trailer.session_req.scope2 = 0; 1859 ses_init_buf->trailer.session_req.scope2 = 0;
1712 smb_buf = (struct smb_hdr *)ses_init_buf; 1860 smb_buf = (struct smb_hdr *)ses_init_buf;
1713 /* sizeof RFC1002_SESSION_REQUEST with no scope */ 1861 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1714 smb_buf->smb_buf_length = 0x81000044; 1862 smb_buf->smb_buf_length = 0x81000044;
1715 rc = smb_send(*csocket, smb_buf, 0x44, 1863 rc = smb_send(socket, smb_buf, 0x44,
1716 (struct sockaddr *)psin_server, noblocksnd); 1864 (struct sockaddr *) &server->addr.sockAddr,
1865 server->noblocksnd);
1717 kfree(ses_init_buf); 1866 kfree(ses_init_buf);
1718 msleep(1); /* RFC1001 layer in at least one server 1867 msleep(1); /* RFC1001 layer in at least one server
1719 requires very short break before negprot 1868 requires very short break before negprot
@@ -1733,79 +1882,81 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1733} 1882}
1734 1883
1735static int 1884static int
1736ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket, 1885ipv6_connect(struct TCP_Server_Info *server)
1737 bool noblocksnd)
1738{ 1886{
1739 int rc = 0; 1887 int rc = 0;
1740 int connected = 0; 1888 bool connected = false;
1741 __be16 orig_port = 0; 1889 __be16 orig_port = 0;
1890 struct socket *socket = server->ssocket;
1742 1891
1743 if (*csocket == NULL) { 1892 if (socket == NULL) {
1744 rc = sock_create_kern(PF_INET6, SOCK_STREAM, 1893 rc = sock_create_kern(PF_INET6, SOCK_STREAM,
1745 IPPROTO_TCP, csocket); 1894 IPPROTO_TCP, &socket);
1746 if (rc < 0) { 1895 if (rc < 0) {
1747 cERROR(1, ("Error %d creating ipv6 socket", rc)); 1896 cERROR(1, ("Error %d creating ipv6 socket", rc));
1748 *csocket = NULL; 1897 socket = NULL;
1749 return rc; 1898 return rc;
1750 } else {
1751 /* BB other socket options to set KEEPALIVE, NODELAY? */
1752 cFYI(1, ("ipv6 Socket created"));
1753 (*csocket)->sk->sk_allocation = GFP_NOFS;
1754 cifs_reclassify_socket6(*csocket);
1755 } 1899 }
1756 }
1757 1900
1758 psin_server->sin6_family = AF_INET6; 1901 /* BB other socket options to set KEEPALIVE, NODELAY? */
1902 cFYI(1, ("ipv6 Socket created"));
1903 server->ssocket = socket;
1904 socket->sk->sk_allocation = GFP_NOFS;
1905 cifs_reclassify_socket6(socket);
1906 }
1759 1907
1760 if (psin_server->sin6_port) { /* user overrode default port */ 1908 /* user overrode default port */
1761 rc = (*csocket)->ops->connect(*csocket, 1909 if (server->addr.sockAddr6.sin6_port) {
1762 (struct sockaddr *) psin_server, 1910 rc = socket->ops->connect(socket,
1911 (struct sockaddr *) &server->addr.sockAddr6,
1763 sizeof(struct sockaddr_in6), 0); 1912 sizeof(struct sockaddr_in6), 0);
1764 if (rc >= 0) 1913 if (rc >= 0)
1765 connected = 1; 1914 connected = true;
1766 } 1915 }
1767 1916
1768 if (!connected) { 1917 if (!connected) {
1769 /* save original port so we can retry user specified port 1918 /* save original port so we can retry user specified port
1770 later if fall back ports fail this time */ 1919 later if fall back ports fail this time */
1771 1920
1772 orig_port = psin_server->sin6_port; 1921 orig_port = server->addr.sockAddr6.sin6_port;
1773 /* do not retry on the same port we just failed on */ 1922 /* do not retry on the same port we just failed on */
1774 if (psin_server->sin6_port != htons(CIFS_PORT)) { 1923 if (server->addr.sockAddr6.sin6_port != htons(CIFS_PORT)) {
1775 psin_server->sin6_port = htons(CIFS_PORT); 1924 server->addr.sockAddr6.sin6_port = htons(CIFS_PORT);
1776 1925 rc = socket->ops->connect(socket, (struct sockaddr *)
1777 rc = (*csocket)->ops->connect(*csocket, 1926 &server->addr.sockAddr6,
1778 (struct sockaddr *) psin_server,
1779 sizeof(struct sockaddr_in6), 0); 1927 sizeof(struct sockaddr_in6), 0);
1780 if (rc >= 0) 1928 if (rc >= 0)
1781 connected = 1; 1929 connected = true;
1782 } 1930 }
1783 } 1931 }
1784 if (!connected) { 1932 if (!connected) {
1785 psin_server->sin6_port = htons(RFC1001_PORT); 1933 server->addr.sockAddr6.sin6_port = htons(RFC1001_PORT);
1786 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) 1934 rc = socket->ops->connect(socket, (struct sockaddr *)
1787 psin_server, sizeof(struct sockaddr_in6), 0); 1935 &server->addr.sockAddr6,
1936 sizeof(struct sockaddr_in6), 0);
1788 if (rc >= 0) 1937 if (rc >= 0)
1789 connected = 1; 1938 connected = true;
1790 } 1939 }
1791 1940
1792 /* give up here - unless we want to retry on different 1941 /* give up here - unless we want to retry on different
1793 protocol families some day */ 1942 protocol families some day */
1794 if (!connected) { 1943 if (!connected) {
1795 if (orig_port) 1944 if (orig_port)
1796 psin_server->sin6_port = orig_port; 1945 server->addr.sockAddr6.sin6_port = orig_port;
1797 cFYI(1, ("Error %d connecting to server via ipv6", rc)); 1946 cFYI(1, ("Error %d connecting to server via ipv6", rc));
1798 sock_release(*csocket); 1947 sock_release(socket);
1799 *csocket = NULL; 1948 server->ssocket = NULL;
1800 return rc; 1949 return rc;
1801 } 1950 }
1802 /* Eventually check for other socket options to change from
1803 the default. sock_setsockopt not used because it expects
1804 user space buffer */
1805 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1806 if (!noblocksnd)
1807 (*csocket)->sk->sk_sndtimeo = 3 * HZ;
1808 1951
1952 /*
1953 * Eventually check for other socket options to change from
1954 * the default. sock_setsockopt not used because it expects
1955 * user space buffer
1956 */
1957 socket->sk->sk_rcvtimeo = 7 * HZ;
1958 socket->sk->sk_sndtimeo = 3 * HZ;
1959 server->ssocket = socket;
1809 1960
1810 return rc; 1961 return rc;
1811} 1962}
@@ -2011,6 +2162,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
2011 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; 2162 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2012 if (pvolume_info->nobrl) 2163 if (pvolume_info->nobrl)
2013 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; 2164 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2165 if (pvolume_info->mand_lock)
2166 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
2014 if (pvolume_info->cifs_acl) 2167 if (pvolume_info->cifs_acl)
2015 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; 2168 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2016 if (pvolume_info->override_uid) 2169 if (pvolume_info->override_uid)
@@ -2035,32 +2188,30 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2035{ 2188{
2036 int rc = 0; 2189 int rc = 0;
2037 int xid; 2190 int xid;
2038 struct socket *csocket = NULL; 2191 struct smb_vol *volume_info;
2039 struct sockaddr addr;
2040 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2041 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
2042 struct smb_vol volume_info;
2043 struct cifsSesInfo *pSesInfo = NULL; 2192 struct cifsSesInfo *pSesInfo = NULL;
2044 struct cifsTconInfo *tcon = NULL; 2193 struct cifsTconInfo *tcon = NULL;
2045 struct TCP_Server_Info *srvTcp = NULL; 2194 struct TCP_Server_Info *srvTcp = NULL;
2046 2195
2047 xid = GetXid(); 2196 xid = GetXid();
2048 2197
2049/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */ 2198 volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
2199 if (!volume_info) {
2200 rc = -ENOMEM;
2201 goto out;
2202 }
2050 2203
2051 memset(&addr, 0, sizeof(struct sockaddr)); 2204 if (cifs_parse_mount_options(mount_data, devname, volume_info)) {
2052 memset(&volume_info, 0, sizeof(struct smb_vol));
2053 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
2054 rc = -EINVAL; 2205 rc = -EINVAL;
2055 goto out; 2206 goto out;
2056 } 2207 }
2057 2208
2058 if (volume_info.nullauth) { 2209 if (volume_info->nullauth) {
2059 cFYI(1, ("null user")); 2210 cFYI(1, ("null user"));
2060 volume_info.username = ""; 2211 volume_info->username = "";
2061 } else if (volume_info.username) { 2212 } else if (volume_info->username) {
2062 /* BB fixme parse for domain name here */ 2213 /* BB fixme parse for domain name here */
2063 cFYI(1, ("Username: %s", volume_info.username)); 2214 cFYI(1, ("Username: %s", volume_info->username));
2064 } else { 2215 } else {
2065 cifserror("No username specified"); 2216 cifserror("No username specified");
2066 /* In userspace mount helper we can get user name from alternate 2217 /* In userspace mount helper we can get user name from alternate
@@ -2069,139 +2220,29 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2069 goto out; 2220 goto out;
2070 } 2221 }
2071 2222
2072 if (volume_info.UNCip && volume_info.UNC) {
2073 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
2074 &sin_server->sin_addr.s_addr);
2075
2076 if (rc <= 0) {
2077 /* not ipv4 address, try ipv6 */
2078 rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
2079 &sin_server6->sin6_addr.in6_u);
2080 if (rc > 0)
2081 addr.sa_family = AF_INET6;
2082 } else {
2083 addr.sa_family = AF_INET;
2084 }
2085
2086 if (rc <= 0) {
2087 /* we failed translating address */
2088 rc = -EINVAL;
2089 goto out;
2090 }
2091
2092 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
2093 /* success */
2094 rc = 0;
2095 } else if (volume_info.UNCip) {
2096 /* BB using ip addr as server name to connect to the
2097 DFS root below */
2098 cERROR(1, ("Connecting to DFS root not implemented yet"));
2099 rc = -EINVAL;
2100 goto out;
2101 } else /* which servers DFS root would we conect to */ {
2102 cERROR(1,
2103 ("CIFS mount error: No UNC path (e.g. -o "
2104 "unc=//192.168.1.100/public) specified"));
2105 rc = -EINVAL;
2106 goto out;
2107 }
2108 2223
2109 /* this is needed for ASCII cp to Unicode converts */ 2224 /* this is needed for ASCII cp to Unicode converts */
2110 if (volume_info.iocharset == NULL) { 2225 if (volume_info->iocharset == NULL) {
2111 cifs_sb->local_nls = load_nls_default(); 2226 cifs_sb->local_nls = load_nls_default();
2112 /* load_nls_default can not return null */ 2227 /* load_nls_default can not return null */
2113 } else { 2228 } else {
2114 cifs_sb->local_nls = load_nls(volume_info.iocharset); 2229 cifs_sb->local_nls = load_nls(volume_info->iocharset);
2115 if (cifs_sb->local_nls == NULL) { 2230 if (cifs_sb->local_nls == NULL) {
2116 cERROR(1, ("CIFS mount error: iocharset %s not found", 2231 cERROR(1, ("CIFS mount error: iocharset %s not found",
2117 volume_info.iocharset)); 2232 volume_info->iocharset));
2118 rc = -ELIBACC; 2233 rc = -ELIBACC;
2119 goto out; 2234 goto out;
2120 } 2235 }
2121 } 2236 }
2122 2237
2123 srvTcp = cifs_find_tcp_session(&addr); 2238 /* get a reference to a tcp session */
2124 if (!srvTcp) { /* create socket */ 2239 srvTcp = cifs_get_tcp_session(volume_info);
2125 if (addr.sa_family == AF_INET6) { 2240 if (IS_ERR(srvTcp)) {
2126 cFYI(1, ("attempting ipv6 connect")); 2241 rc = PTR_ERR(srvTcp);
2127 /* BB should we allow ipv6 on port 139? */ 2242 goto out;
2128 /* other OS never observed in Wild doing 139 with v6 */
2129 sin_server6->sin6_port = htons(volume_info.port);
2130 rc = ipv6_connect(sin_server6, &csocket,
2131 volume_info.noblocksnd);
2132 } else {
2133 sin_server->sin_port = htons(volume_info.port);
2134 rc = ipv4_connect(sin_server, &csocket,
2135 volume_info.source_rfc1001_name,
2136 volume_info.target_rfc1001_name,
2137 volume_info.noblocksnd,
2138 volume_info.noautotune);
2139 }
2140 if (rc < 0) {
2141 cERROR(1, ("Error connecting to socket. "
2142 "Aborting operation"));
2143 if (csocket != NULL)
2144 sock_release(csocket);
2145 goto out;
2146 }
2147
2148 srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2149 if (!srvTcp) {
2150 rc = -ENOMEM;
2151 sock_release(csocket);
2152 goto out;
2153 } else {
2154 srvTcp->noblocksnd = volume_info.noblocksnd;
2155 srvTcp->noautotune = volume_info.noautotune;
2156 if (addr.sa_family == AF_INET6)
2157 memcpy(&srvTcp->addr.sockAddr6, sin_server6,
2158 sizeof(struct sockaddr_in6));
2159 else
2160 memcpy(&srvTcp->addr.sockAddr, sin_server,
2161 sizeof(struct sockaddr_in));
2162 atomic_set(&srvTcp->inFlight, 0);
2163 /* BB Add code for ipv6 case too */
2164 srvTcp->ssocket = csocket;
2165 srvTcp->hostname = extract_hostname(volume_info.UNC);
2166 if (IS_ERR(srvTcp->hostname)) {
2167 rc = PTR_ERR(srvTcp->hostname);
2168 sock_release(csocket);
2169 goto out;
2170 }
2171 init_waitqueue_head(&srvTcp->response_q);
2172 init_waitqueue_head(&srvTcp->request_q);
2173 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
2174 /* at this point we are the only ones with the pointer
2175 to the struct since the kernel thread not created yet
2176 so no need to spinlock this init of tcpStatus */
2177 srvTcp->tcpStatus = CifsNew;
2178 init_MUTEX(&srvTcp->tcpSem);
2179 srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
2180 if (IS_ERR(srvTcp->tsk)) {
2181 rc = PTR_ERR(srvTcp->tsk);
2182 cERROR(1, ("error %d create cifsd thread", rc));
2183 srvTcp->tsk = NULL;
2184 sock_release(csocket);
2185 kfree(srvTcp->hostname);
2186 goto out;
2187 }
2188 rc = 0;
2189 memcpy(srvTcp->workstation_RFC1001_name,
2190 volume_info.source_rfc1001_name, 16);
2191 memcpy(srvTcp->server_RFC1001_name,
2192 volume_info.target_rfc1001_name, 16);
2193 srvTcp->sequence_number = 0;
2194 INIT_LIST_HEAD(&srvTcp->tcp_ses_list);
2195 INIT_LIST_HEAD(&srvTcp->smb_ses_list);
2196 ++srvTcp->srv_count;
2197 write_lock(&cifs_tcp_ses_lock);
2198 list_add(&srvTcp->tcp_ses_list,
2199 &cifs_tcp_ses_list);
2200 write_unlock(&cifs_tcp_ses_lock);
2201 }
2202 } 2243 }
2203 2244
2204 pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username); 2245 pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username);
2205 if (pSesInfo) { 2246 if (pSesInfo) {
2206 cFYI(1, ("Existing smb sess found (status=%d)", 2247 cFYI(1, ("Existing smb sess found (status=%d)",
2207 pSesInfo->status)); 2248 pSesInfo->status));
@@ -2228,31 +2269,38 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2228 2269
2229 /* new SMB session uses our srvTcp ref */ 2270 /* new SMB session uses our srvTcp ref */
2230 pSesInfo->server = srvTcp; 2271 pSesInfo->server = srvTcp;
2231 sprintf(pSesInfo->serverName, "%u.%u.%u.%u", 2272 if (srvTcp->addr.sockAddr6.sin6_family == AF_INET6)
2232 NIPQUAD(sin_server->sin_addr.s_addr)); 2273 sprintf(pSesInfo->serverName, "%pI6",
2274 &srvTcp->addr.sockAddr6.sin6_addr);
2275 else
2276 sprintf(pSesInfo->serverName, "%pI4",
2277 &srvTcp->addr.sockAddr.sin_addr.s_addr);
2233 2278
2234 write_lock(&cifs_tcp_ses_lock); 2279 write_lock(&cifs_tcp_ses_lock);
2235 list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list); 2280 list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
2236 write_unlock(&cifs_tcp_ses_lock); 2281 write_unlock(&cifs_tcp_ses_lock);
2237 2282
2238 /* volume_info.password freed at unmount */ 2283 /* volume_info->password freed at unmount */
2239 if (volume_info.password) { 2284 if (volume_info->password) {
2240 pSesInfo->password = volume_info.password; 2285 pSesInfo->password = kstrdup(volume_info->password,
2241 /* set to NULL to prevent freeing on exit */ 2286 GFP_KERNEL);
2242 volume_info.password = NULL; 2287 if (!pSesInfo->password) {
2288 rc = -ENOMEM;
2289 goto mount_fail_check;
2290 }
2243 } 2291 }
2244 if (volume_info.username) 2292 if (volume_info->username)
2245 strncpy(pSesInfo->userName, volume_info.username, 2293 strncpy(pSesInfo->userName, volume_info->username,
2246 MAX_USERNAME_SIZE); 2294 MAX_USERNAME_SIZE);
2247 if (volume_info.domainname) { 2295 if (volume_info->domainname) {
2248 int len = strlen(volume_info.domainname); 2296 int len = strlen(volume_info->domainname);
2249 pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL); 2297 pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
2250 if (pSesInfo->domainName) 2298 if (pSesInfo->domainName)
2251 strcpy(pSesInfo->domainName, 2299 strcpy(pSesInfo->domainName,
2252 volume_info.domainname); 2300 volume_info->domainname);
2253 } 2301 }
2254 pSesInfo->linux_uid = volume_info.linux_uid; 2302 pSesInfo->linux_uid = volume_info->linux_uid;
2255 pSesInfo->overrideSecFlg = volume_info.secFlg; 2303 pSesInfo->overrideSecFlg = volume_info->secFlg;
2256 down(&pSesInfo->sesSem); 2304 down(&pSesInfo->sesSem);
2257 2305
2258 /* BB FIXME need to pass vol->secFlgs BB */ 2306 /* BB FIXME need to pass vol->secFlgs BB */
@@ -2263,14 +2311,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2263 2311
2264 /* search for existing tcon to this server share */ 2312 /* search for existing tcon to this server share */
2265 if (!rc) { 2313 if (!rc) {
2266 setup_cifs_sb(&volume_info, cifs_sb); 2314 setup_cifs_sb(volume_info, cifs_sb);
2267 2315
2268 tcon = cifs_find_tcon(pSesInfo, volume_info.UNC); 2316 tcon = cifs_find_tcon(pSesInfo, volume_info->UNC);
2269 if (tcon) { 2317 if (tcon) {
2270 cFYI(1, ("Found match on UNC path")); 2318 cFYI(1, ("Found match on UNC path"));
2271 /* existing tcon already has a reference */ 2319 /* existing tcon already has a reference */
2272 cifs_put_smb_ses(pSesInfo); 2320 cifs_put_smb_ses(pSesInfo);
2273 if (tcon->seal != volume_info.seal) 2321 if (tcon->seal != volume_info->seal)
2274 cERROR(1, ("transport encryption setting " 2322 cERROR(1, ("transport encryption setting "
2275 "conflicts with existing tid")); 2323 "conflicts with existing tid"));
2276 } else { 2324 } else {
@@ -2279,11 +2327,20 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2279 rc = -ENOMEM; 2327 rc = -ENOMEM;
2280 goto mount_fail_check; 2328 goto mount_fail_check;
2281 } 2329 }
2330
2282 tcon->ses = pSesInfo; 2331 tcon->ses = pSesInfo;
2332 if (volume_info->password) {
2333 tcon->password = kstrdup(volume_info->password,
2334 GFP_KERNEL);
2335 if (!tcon->password) {
2336 rc = -ENOMEM;
2337 goto mount_fail_check;
2338 }
2339 }
2283 2340
2284 /* check for null share name ie connect to dfs root */ 2341 /* check for null share name ie connect to dfs root */
2285 if ((strchr(volume_info.UNC + 3, '\\') == NULL) 2342 if ((strchr(volume_info->UNC + 3, '\\') == NULL)
2286 && (strchr(volume_info.UNC + 3, '/') == NULL)) { 2343 && (strchr(volume_info->UNC + 3, '/') == NULL)) {
2287 /* rc = connect_to_dfs_path(...) */ 2344 /* rc = connect_to_dfs_path(...) */
2288 cFYI(1, ("DFS root not supported")); 2345 cFYI(1, ("DFS root not supported"));
2289 rc = -ENODEV; 2346 rc = -ENODEV;
@@ -2292,10 +2349,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2292 /* BB Do we need to wrap sesSem around 2349 /* BB Do we need to wrap sesSem around
2293 * this TCon call and Unix SetFS as 2350 * this TCon call and Unix SetFS as
2294 * we do on SessSetup and reconnect? */ 2351 * we do on SessSetup and reconnect? */
2295 rc = CIFSTCon(xid, pSesInfo, volume_info.UNC, 2352 rc = CIFSTCon(xid, pSesInfo, volume_info->UNC,
2296 tcon, cifs_sb->local_nls); 2353 tcon, cifs_sb->local_nls);
2297 cFYI(1, ("CIFS Tcon rc = %d", rc)); 2354 cFYI(1, ("CIFS Tcon rc = %d", rc));
2298 if (volume_info.nodfs) { 2355 if (volume_info->nodfs) {
2299 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; 2356 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2300 cFYI(1, ("DFS disabled (%d)", 2357 cFYI(1, ("DFS disabled (%d)",
2301 tcon->Flags)); 2358 tcon->Flags));
@@ -2303,7 +2360,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2303 } 2360 }
2304 if (rc) 2361 if (rc)
2305 goto mount_fail_check; 2362 goto mount_fail_check;
2306 tcon->seal = volume_info.seal; 2363 tcon->seal = volume_info->seal;
2307 write_lock(&cifs_tcp_ses_lock); 2364 write_lock(&cifs_tcp_ses_lock);
2308 list_add(&tcon->tcon_list, &pSesInfo->tcon_list); 2365 list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
2309 write_unlock(&cifs_tcp_ses_lock); 2366 write_unlock(&cifs_tcp_ses_lock);
@@ -2313,9 +2370,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2313 to a share so for resources mounted more than once 2370 to a share so for resources mounted more than once
2314 to the same server share the last value passed in 2371 to the same server share the last value passed in
2315 for the retry flag is used */ 2372 for the retry flag is used */
2316 tcon->retry = volume_info.retry; 2373 tcon->retry = volume_info->retry;
2317 tcon->nocase = volume_info.nocase; 2374 tcon->nocase = volume_info->nocase;
2318 tcon->local_lease = volume_info.local_lease; 2375 tcon->local_lease = volume_info->local_lease;
2319 } 2376 }
2320 if (pSesInfo) { 2377 if (pSesInfo) {
2321 if (pSesInfo->capabilities & CAP_LARGE_FILES) { 2378 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
@@ -2352,7 +2409,7 @@ mount_fail_check:
2352 if (tcon->ses->capabilities & CAP_UNIX) 2409 if (tcon->ses->capabilities & CAP_UNIX)
2353 /* reset of caps checks mount to see if unix extensions 2410 /* reset of caps checks mount to see if unix extensions
2354 disabled for just this mount */ 2411 disabled for just this mount */
2355 reset_cifs_unix_caps(xid, tcon, sb, &volume_info); 2412 reset_cifs_unix_caps(xid, tcon, sb, volume_info);
2356 else 2413 else
2357 tcon->unix_ext = 0; /* server does not support them */ 2414 tcon->unix_ext = 0; /* server does not support them */
2358 2415
@@ -2371,18 +2428,22 @@ mount_fail_check:
2371 cifs_sb->rsize = min(cifs_sb->rsize, 2428 cifs_sb->rsize = min(cifs_sb->rsize,
2372 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); 2429 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2373 2430
2374 /* volume_info.password is freed above when existing session found 2431 /* volume_info->password is freed above when existing session found
2375 (in which case it is not needed anymore) but when new sesion is created 2432 (in which case it is not needed anymore) but when new sesion is created
2376 the password ptr is put in the new session structure (in which case the 2433 the password ptr is put in the new session structure (in which case the
2377 password will be freed at unmount time) */ 2434 password will be freed at unmount time) */
2378out: 2435out:
2379 /* zero out password before freeing */ 2436 /* zero out password before freeing */
2380 if (volume_info.password != NULL) { 2437 if (volume_info) {
2381 memset(volume_info.password, 0, strlen(volume_info.password)); 2438 if (volume_info->password != NULL) {
2382 kfree(volume_info.password); 2439 memset(volume_info->password, 0,
2440 strlen(volume_info->password));
2441 kfree(volume_info->password);
2442 }
2443 kfree(volume_info->UNC);
2444 kfree(volume_info->prepath);
2445 kfree(volume_info);
2383 } 2446 }
2384 kfree(volume_info.UNC);
2385 kfree(volume_info.prepath);
2386 FreeXid(xid); 2447 FreeXid(xid);
2387 return rc; 2448 return rc;
2388} 2449}
@@ -2533,7 +2594,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2533 __u16 action = le16_to_cpu(pSMBr->resp.Action); 2594 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2534 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); 2595 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2535 if (action & GUEST_LOGIN) 2596 if (action & GUEST_LOGIN)
2536 cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */ 2597 cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
2537 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format 2598 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
2538 (little endian) */ 2599 (little endian) */
2539 cFYI(1, ("UID = %d ", ses->Suid)); 2600 cFYI(1, ("UID = %d ", ses->Suid));
@@ -2679,13 +2740,11 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2679 len)); 2740 len));
2680 } 2741 }
2681 } else { 2742 } else {
2682 cERROR(1, 2743 cERROR(1, ("Security Blob Length extends beyond "
2683 (" Security Blob Length extends beyond "
2684 "end of SMB")); 2744 "end of SMB"));
2685 } 2745 }
2686 } else { 2746 } else {
2687 cERROR(1, 2747 cERROR(1, ("Invalid Word count %d: ",
2688 (" Invalid Word count %d: ",
2689 smb_buffer_response->WordCount)); 2748 smb_buffer_response->WordCount));
2690 rc = -EIO; 2749 rc = -EIO;
2691 } 2750 }
@@ -2843,7 +2902,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2843 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); 2902 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2844 2903
2845 if (action & GUEST_LOGIN) 2904 if (action & GUEST_LOGIN)
2846 cFYI(1, (" Guest login")); 2905 cFYI(1, ("Guest login"));
2847 /* Do we want to set anything in SesInfo struct when guest login? */ 2906 /* Do we want to set anything in SesInfo struct when guest login? */
2848 2907
2849 bcc_ptr = pByteArea(smb_buffer_response); 2908 bcc_ptr = pByteArea(smb_buffer_response);
@@ -2851,8 +2910,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2851 2910
2852 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr; 2911 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2853 if (SecurityBlob2->MessageType != NtLmChallenge) { 2912 if (SecurityBlob2->MessageType != NtLmChallenge) {
2854 cFYI(1, 2913 cFYI(1, ("Unexpected NTLMSSP message type received %d",
2855 ("Unexpected NTLMSSP message type received %d",
2856 SecurityBlob2->MessageType)); 2914 SecurityBlob2->MessageType));
2857 } else if (ses) { 2915 } else if (ses) {
2858 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ 2916 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
@@ -3024,8 +3082,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
3024 cERROR(1, ("No session structure passed in.")); 3082 cERROR(1, ("No session structure passed in."));
3025 } 3083 }
3026 } else { 3084 } else {
3027 cERROR(1, 3085 cERROR(1, ("Invalid Word count %d:",
3028 (" Invalid Word count %d:",
3029 smb_buffer_response->WordCount)); 3086 smb_buffer_response->WordCount));
3030 rc = -EIO; 3087 rc = -EIO;
3031 } 3088 }
@@ -3264,7 +3321,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3264 __u16 action = le16_to_cpu(pSMBr->resp.Action); 3321 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3265 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); 3322 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3266 if (action & GUEST_LOGIN) 3323 if (action & GUEST_LOGIN)
3267 cFYI(1, (" Guest login")); /* BB Should we set anything 3324 cFYI(1, ("Guest login")); /* BB Should we set anything
3268 in SesInfo struct ? */ 3325 in SesInfo struct ? */
3269/* if (SecurityBlob2->MessageType != NtLm??) { 3326/* if (SecurityBlob2->MessageType != NtLm??) {
3270 cFYI("Unexpected message type on auth response is %d")); 3327 cFYI("Unexpected message type on auth response is %d"));
@@ -3487,12 +3544,14 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3487 NTLMv2 password here) */ 3544 NTLMv2 password here) */
3488#ifdef CONFIG_CIFS_WEAK_PW_HASH 3545#ifdef CONFIG_CIFS_WEAK_PW_HASH
3489 if ((extended_security & CIFSSEC_MAY_LANMAN) && 3546 if ((extended_security & CIFSSEC_MAY_LANMAN) &&
3490 (ses->server->secType == LANMAN)) 3547 (ses->server->secType == LANMAN))
3491 calc_lanman_hash(ses, bcc_ptr); 3548 calc_lanman_hash(tcon->password, ses->server->cryptKey,
3549 ses->server->secMode &
3550 SECMODE_PW_ENCRYPT ? true : false,
3551 bcc_ptr);
3492 else 3552 else
3493#endif /* CIFS_WEAK_PW_HASH */ 3553#endif /* CIFS_WEAK_PW_HASH */
3494 SMBNTencrypt(ses->password, 3554 SMBNTencrypt(tcon->password, ses->server->cryptKey,
3495 ses->server->cryptKey,
3496 bcc_ptr); 3555 bcc_ptr);
3497 3556
3498 bcc_ptr += CIFS_SESS_KEY_SIZE; 3557 bcc_ptr += CIFS_SESS_KEY_SIZE;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e962e75e6f7b..838d9c720a5c 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -235,11 +235,11 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
235 }; 235 };
236 236
237 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 237 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
238 args.uid = (__u64) current->fsuid; 238 args.uid = (__u64) current_fsuid();
239 if (inode->i_mode & S_ISGID) 239 if (inode->i_mode & S_ISGID)
240 args.gid = (__u64) inode->i_gid; 240 args.gid = (__u64) inode->i_gid;
241 else 241 else
242 args.gid = (__u64) current->fsgid; 242 args.gid = (__u64) current_fsgid();
243 } else { 243 } else {
244 args.uid = NO_CHANGE_64; 244 args.uid = NO_CHANGE_64;
245 args.gid = NO_CHANGE_64; 245 args.gid = NO_CHANGE_64;
@@ -271,13 +271,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
271 if ((oplock & CIFS_CREATE_ACTION) && 271 if ((oplock & CIFS_CREATE_ACTION) &&
272 (cifs_sb->mnt_cifs_flags & 272 (cifs_sb->mnt_cifs_flags &
273 CIFS_MOUNT_SET_UID)) { 273 CIFS_MOUNT_SET_UID)) {
274 newinode->i_uid = current->fsuid; 274 newinode->i_uid = current_fsuid();
275 if (inode->i_mode & S_ISGID) 275 if (inode->i_mode & S_ISGID)
276 newinode->i_gid = 276 newinode->i_gid =
277 inode->i_gid; 277 inode->i_gid;
278 else 278 else
279 newinode->i_gid = 279 newinode->i_gid =
280 current->fsgid; 280 current_fsgid();
281 } 281 }
282 } 282 }
283 } 283 }
@@ -375,8 +375,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
375 .device = device_number, 375 .device = device_number,
376 }; 376 };
377 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 377 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
378 args.uid = (__u64) current->fsuid; 378 args.uid = (__u64) current_fsuid();
379 args.gid = (__u64) current->fsgid; 379 args.gid = (__u64) current_fsgid();
380 } else { 380 } else {
381 args.uid = NO_CHANGE_64; 381 args.uid = NO_CHANGE_64;
382 args.gid = NO_CHANGE_64; 382 args.gid = NO_CHANGE_64;
@@ -483,7 +483,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
483 483
484 xid = GetXid(); 484 xid = GetXid();
485 485
486 cFYI(1, (" parent inode = 0x%p name is: %s and dentry = 0x%p", 486 cFYI(1, ("parent inode = 0x%p name is: %s and dentry = 0x%p",
487 parent_dir_inode, direntry->d_name.name, direntry)); 487 parent_dir_inode, direntry->d_name.name, direntry));
488 488
489 /* check whether path exists */ 489 /* check whether path exists */
@@ -515,12 +515,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
515 } 515 }
516 516
517 if (direntry->d_inode != NULL) { 517 if (direntry->d_inode != NULL) {
518 cFYI(1, (" non-NULL inode in lookup")); 518 cFYI(1, ("non-NULL inode in lookup"));
519 } else { 519 } else {
520 cFYI(1, (" NULL inode in lookup")); 520 cFYI(1, ("NULL inode in lookup"));
521 } 521 }
522 cFYI(1, 522 cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
523 (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
524 523
525 if (pTcon->unix_ext) 524 if (pTcon->unix_ext)
526 rc = cifs_get_inode_info_unix(&newInode, full_path, 525 rc = cifs_get_inode_info_unix(&newInode, full_path,
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
deleted file mode 100644
index 5a57581eb4b2..000000000000
--- a/fs/cifs/fcntl.c
+++ /dev/null
@@ -1,118 +0,0 @@
1/*
2 * fs/cifs/fcntl.c
3 *
4 * vfs operations that deal with the file control API
5 *
6 * Copyright (C) International Business Machines Corp., 2003,2004
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/fs.h>
24#include <linux/stat.h>
25#include <linux/fcntl.h>
26#include "cifsglob.h"
27#include "cifsproto.h"
28#include "cifs_unicode.h"
29#include "cifs_debug.h"
30#include "cifsfs.h"
31
32static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
33{
34 __u32 cifs_ntfy_flags = 0;
35
36 /* No way on Linux VFS to ask to monitor xattr
37 changes (and no stream support either */
38 if (fcntl_notify_flags & DN_ACCESS)
39 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
40 if (fcntl_notify_flags & DN_MODIFY) {
41 /* What does this mean on directories? */
42 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE |
43 FILE_NOTIFY_CHANGE_SIZE;
44 }
45 if (fcntl_notify_flags & DN_CREATE) {
46 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
47 FILE_NOTIFY_CHANGE_LAST_WRITE;
48 }
49 if (fcntl_notify_flags & DN_DELETE)
50 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
51 if (fcntl_notify_flags & DN_RENAME) {
52 /* BB review this - checking various server behaviors */
53 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
54 FILE_NOTIFY_CHANGE_FILE_NAME;
55 }
56 if (fcntl_notify_flags & DN_ATTRIB) {
57 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
58 FILE_NOTIFY_CHANGE_ATTRIBUTES;
59 }
60/* if (fcntl_notify_flags & DN_MULTISHOT) {
61 cifs_ntfy_flags |= ;
62 } */ /* BB fixme - not sure how to handle this with CIFS yet */
63
64 return cifs_ntfy_flags;
65}
66
67int cifs_dir_notify(struct file *file, unsigned long arg)
68{
69 int xid;
70 int rc = -EINVAL;
71 int oplock = 0;
72 struct cifs_sb_info *cifs_sb;
73 struct cifsTconInfo *pTcon;
74 char *full_path = NULL;
75 __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
76 __u16 netfid;
77
78 if (experimEnabled == 0)
79 return 0;
80
81 xid = GetXid();
82 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
83 pTcon = cifs_sb->tcon;
84
85 full_path = build_path_from_dentry(file->f_path.dentry);
86
87 if (full_path == NULL) {
88 rc = -ENOMEM;
89 } else {
90 cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg));
91 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
92 GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
93 &netfid, &oplock, NULL, cifs_sb->local_nls,
94 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
95 /* BB fixme - add this handle to a notify handle list */
96 if (rc) {
97 cFYI(1, ("Could not open directory for notify"));
98 } else {
99 filter = convert_to_cifs_notify_flags(arg);
100 if (filter != 0) {
101 rc = CIFSSMBNotify(xid, pTcon,
102 0 /* no subdirs */, netfid,
103 filter, file, arg & DN_MULTISHOT,
104 cifs_sb->local_nls);
105 } else {
106 rc = -EINVAL;
107 }
108 /* BB add code to close file eventually (at unmount
109 it would close automatically but may be a way
110 to do it easily when inode freed or when
111 notify info is cleared/changed */
112 cFYI(1, ("notify rc %d", rc));
113 }
114 }
115
116 FreeXid(xid);
117 return rc;
118}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index b691b893a848..12bb656fbe75 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -644,10 +644,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
644 __u64 length; 644 __u64 length;
645 bool wait_flag = false; 645 bool wait_flag = false;
646 struct cifs_sb_info *cifs_sb; 646 struct cifs_sb_info *cifs_sb;
647 struct cifsTconInfo *pTcon; 647 struct cifsTconInfo *tcon;
648 __u16 netfid; 648 __u16 netfid;
649 __u8 lockType = LOCKING_ANDX_LARGE_FILES; 649 __u8 lockType = LOCKING_ANDX_LARGE_FILES;
650 bool posix_locking; 650 bool posix_locking = 0;
651 651
652 length = 1 + pfLock->fl_end - pfLock->fl_start; 652 length = 1 + pfLock->fl_end - pfLock->fl_start;
653 rc = -EACCES; 653 rc = -EACCES;
@@ -698,7 +698,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
698 cFYI(1, ("Unknown type of lock")); 698 cFYI(1, ("Unknown type of lock"));
699 699
700 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 700 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
701 pTcon = cifs_sb->tcon; 701 tcon = cifs_sb->tcon;
702 702
703 if (file->private_data == NULL) { 703 if (file->private_data == NULL) {
704 FreeXid(xid); 704 FreeXid(xid);
@@ -706,9 +706,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
706 } 706 }
707 netfid = ((struct cifsFileInfo *)file->private_data)->netfid; 707 netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
708 708
709 posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 709 if ((tcon->ses->capabilities & CAP_UNIX) &&
710 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability)); 710 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
711 711 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
712 posix_locking = 1;
712 /* BB add code here to normalize offset and length to 713 /* BB add code here to normalize offset and length to
713 account for negative length which we can not accept over the 714 account for negative length which we can not accept over the
714 wire */ 715 wire */
@@ -719,7 +720,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
719 posix_lock_type = CIFS_RDLCK; 720 posix_lock_type = CIFS_RDLCK;
720 else 721 else
721 posix_lock_type = CIFS_WRLCK; 722 posix_lock_type = CIFS_WRLCK;
722 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */, 723 rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
723 length, pfLock, 724 length, pfLock,
724 posix_lock_type, wait_flag); 725 posix_lock_type, wait_flag);
725 FreeXid(xid); 726 FreeXid(xid);
@@ -727,10 +728,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
727 } 728 }
728 729
729 /* BB we could chain these into one lock request BB */ 730 /* BB we could chain these into one lock request BB */
730 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 731 rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start,
731 0, 1, lockType, 0 /* wait flag */ ); 732 0, 1, lockType, 0 /* wait flag */ );
732 if (rc == 0) { 733 if (rc == 0) {
733 rc = CIFSSMBLock(xid, pTcon, netfid, length, 734 rc = CIFSSMBLock(xid, tcon, netfid, length,
734 pfLock->fl_start, 1 /* numUnlock */ , 735 pfLock->fl_start, 1 /* numUnlock */ ,
735 0 /* numLock */ , lockType, 736 0 /* numLock */ , lockType,
736 0 /* wait flag */ ); 737 0 /* wait flag */ );
@@ -767,7 +768,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
767 if (numUnlock == 1) 768 if (numUnlock == 1)
768 posix_lock_type = CIFS_UNLCK; 769 posix_lock_type = CIFS_UNLCK;
769 770
770 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, 771 rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */,
771 length, pfLock, 772 length, pfLock,
772 posix_lock_type, wait_flag); 773 posix_lock_type, wait_flag);
773 } else { 774 } else {
@@ -775,7 +776,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
775 (struct cifsFileInfo *)file->private_data; 776 (struct cifsFileInfo *)file->private_data;
776 777
777 if (numLock) { 778 if (numLock) {
778 rc = CIFSSMBLock(xid, pTcon, netfid, length, 779 rc = CIFSSMBLock(xid, tcon, netfid, length,
779 pfLock->fl_start, 780 pfLock->fl_start,
780 0, numLock, lockType, wait_flag); 781 0, numLock, lockType, wait_flag);
781 782
@@ -796,7 +797,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
796 if (pfLock->fl_start <= li->offset && 797 if (pfLock->fl_start <= li->offset &&
797 (pfLock->fl_start + length) >= 798 (pfLock->fl_start + length) >=
798 (li->offset + li->length)) { 799 (li->offset + li->length)) {
799 stored_rc = CIFSSMBLock(xid, pTcon, 800 stored_rc = CIFSSMBLock(xid, tcon,
800 netfid, 801 netfid,
801 li->length, li->offset, 802 li->length, li->offset,
802 1, 0, li->type, false); 803 1, 0, li->type, false);
@@ -1475,7 +1476,11 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
1475 cFYI(1, ("write_end for page %p from pos %lld with %d bytes", 1476 cFYI(1, ("write_end for page %p from pos %lld with %d bytes",
1476 page, pos, copied)); 1477 page, pos, copied));
1477 1478
1478 if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE) 1479 if (PageChecked(page)) {
1480 if (copied == len)
1481 SetPageUptodate(page);
1482 ClearPageChecked(page);
1483 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
1479 SetPageUptodate(page); 1484 SetPageUptodate(page);
1480 1485
1481 if (!PageUptodate(page)) { 1486 if (!PageUptodate(page)) {
@@ -2062,39 +2067,70 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
2062{ 2067{
2063 pgoff_t index = pos >> PAGE_CACHE_SHIFT; 2068 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2064 loff_t offset = pos & (PAGE_CACHE_SIZE - 1); 2069 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
2070 loff_t page_start = pos & PAGE_MASK;
2071 loff_t i_size;
2072 struct page *page;
2073 int rc = 0;
2065 2074
2066 cFYI(1, ("write_begin from %lld len %d", (long long)pos, len)); 2075 cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
2067 2076
2068 *pagep = __grab_cache_page(mapping, index); 2077 page = grab_cache_page_write_begin(mapping, index, flags);
2069 if (!*pagep) 2078 if (!page) {
2070 return -ENOMEM; 2079 rc = -ENOMEM;
2071 2080 goto out;
2072 if (PageUptodate(*pagep)) 2081 }
2073 return 0;
2074 2082
2075 /* If we are writing a full page it will be up to date, 2083 if (PageUptodate(page))
2076 no need to read from the server */ 2084 goto out;
2077 if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE)
2078 return 0;
2079 2085
2080 if ((file->f_flags & O_ACCMODE) != O_WRONLY) { 2086 /*
2081 int rc; 2087 * If we write a full page it will be up to date, no need to read from
2088 * the server. If the write is short, we'll end up doing a sync write
2089 * instead.
2090 */
2091 if (len == PAGE_CACHE_SIZE)
2092 goto out;
2082 2093
2083 /* might as well read a page, it is fast enough */ 2094 /*
2084 rc = cifs_readpage_worker(file, *pagep, &offset); 2095 * optimize away the read when we have an oplock, and we're not
2096 * expecting to use any of the data we'd be reading in. That
2097 * is, when the page lies beyond the EOF, or straddles the EOF
2098 * and the write will cover all of the existing data.
2099 */
2100 if (CIFS_I(mapping->host)->clientCanCacheRead) {
2101 i_size = i_size_read(mapping->host);
2102 if (page_start >= i_size ||
2103 (offset == 0 && (pos + len) >= i_size)) {
2104 zero_user_segments(page, 0, offset,
2105 offset + len,
2106 PAGE_CACHE_SIZE);
2107 /*
2108 * PageChecked means that the parts of the page
2109 * to which we're not writing are considered up
2110 * to date. Once the data is copied to the
2111 * page, it can be set uptodate.
2112 */
2113 SetPageChecked(page);
2114 goto out;
2115 }
2116 }
2085 2117
2086 /* we do not need to pass errors back 2118 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
2087 e.g. if we do not have read access to the file 2119 /*
2088 because cifs_write_end will attempt synchronous writes 2120 * might as well read a page, it is fast enough. If we get
2089 -- shaggy */ 2121 * an error, we don't need to return it. cifs_write_end will
2122 * do a sync write instead since PG_uptodate isn't set.
2123 */
2124 cifs_readpage_worker(file, page, &page_start);
2090 } else { 2125 } else {
2091 /* we could try using another file handle if there is one - 2126 /* we could try using another file handle if there is one -
2092 but how would we lock it to prevent close of that handle 2127 but how would we lock it to prevent close of that handle
2093 racing with this read? In any case 2128 racing with this read? In any case
2094 this will be written out by write_end so is fine */ 2129 this will be written out by write_end so is fine */
2095 } 2130 }
2096 2131out:
2097 return 0; 2132 *pagep = page;
2133 return rc;
2098} 2134}
2099 2135
2100const struct address_space_operations cifs_addr_ops = { 2136const struct address_space_operations cifs_addr_ops = {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index ff8c68de4a92..5ab9896fdcb2 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/inode.c 2 * fs/cifs/inode.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2007 4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -621,6 +621,47 @@ static const struct inode_operations cifs_ipc_inode_ops = {
621 .lookup = cifs_lookup, 621 .lookup = cifs_lookup,
622}; 622};
623 623
624static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
625{
626 int pplen = cifs_sb->prepathlen;
627 int dfsplen;
628 char *full_path = NULL;
629
630 /* if no prefix path, simply set path to the root of share to "" */
631 if (pplen == 0) {
632 full_path = kmalloc(1, GFP_KERNEL);
633 if (full_path)
634 full_path[0] = 0;
635 return full_path;
636 }
637
638 if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
639 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
640 else
641 dfsplen = 0;
642
643 full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
644 if (full_path == NULL)
645 return full_path;
646
647 if (dfsplen) {
648 strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
649 /* switch slash direction in prepath depending on whether
650 * windows or posix style path names
651 */
652 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
653 int i;
654 for (i = 0; i < dfsplen; i++) {
655 if (full_path[i] == '\\')
656 full_path[i] = '/';
657 }
658 }
659 }
660 strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
661 full_path[dfsplen + pplen] = 0; /* add trailing null */
662 return full_path;
663}
664
624/* gets root inode */ 665/* gets root inode */
625struct inode *cifs_iget(struct super_block *sb, unsigned long ino) 666struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
626{ 667{
@@ -628,6 +669,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
628 struct cifs_sb_info *cifs_sb; 669 struct cifs_sb_info *cifs_sb;
629 struct inode *inode; 670 struct inode *inode;
630 long rc; 671 long rc;
672 char *full_path;
631 673
632 inode = iget_locked(sb, ino); 674 inode = iget_locked(sb, ino);
633 if (!inode) 675 if (!inode)
@@ -636,13 +678,17 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
636 return inode; 678 return inode;
637 679
638 cifs_sb = CIFS_SB(inode->i_sb); 680 cifs_sb = CIFS_SB(inode->i_sb);
639 xid = GetXid(); 681 full_path = build_path_to_root(cifs_sb);
682 if (full_path == NULL)
683 return ERR_PTR(-ENOMEM);
640 684
685 xid = GetXid();
641 if (cifs_sb->tcon->unix_ext) 686 if (cifs_sb->tcon->unix_ext)
642 rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); 687 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
688 xid);
643 else 689 else
644 rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid, 690 rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb,
645 NULL); 691 xid, NULL);
646 if (rc && cifs_sb->tcon->ipc) { 692 if (rc && cifs_sb->tcon->ipc) {
647 cFYI(1, ("ipc connection - fake read inode")); 693 cFYI(1, ("ipc connection - fake read inode"));
648 inode->i_mode |= S_IFDIR; 694 inode->i_mode |= S_IFDIR;
@@ -652,6 +698,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
652 inode->i_uid = cifs_sb->mnt_uid; 698 inode->i_uid = cifs_sb->mnt_uid;
653 inode->i_gid = cifs_sb->mnt_gid; 699 inode->i_gid = cifs_sb->mnt_gid;
654 } else if (rc) { 700 } else if (rc) {
701 kfree(full_path);
655 _FreeXid(xid); 702 _FreeXid(xid);
656 iget_failed(inode); 703 iget_failed(inode);
657 return ERR_PTR(rc); 704 return ERR_PTR(rc);
@@ -659,6 +706,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
659 706
660 unlock_new_inode(inode); 707 unlock_new_inode(inode);
661 708
709 kfree(full_path);
662 /* can not call macro FreeXid here since in a void func 710 /* can not call macro FreeXid here since in a void func
663 * TODO: This is no longer true 711 * TODO: This is no longer true
664 */ 712 */
@@ -1143,11 +1191,11 @@ mkdir_get_info:
1143 .device = 0, 1191 .device = 0,
1144 }; 1192 };
1145 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 1193 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1146 args.uid = (__u64)current->fsuid; 1194 args.uid = (__u64)current_fsuid();
1147 if (inode->i_mode & S_ISGID) 1195 if (inode->i_mode & S_ISGID)
1148 args.gid = (__u64)inode->i_gid; 1196 args.gid = (__u64)inode->i_gid;
1149 else 1197 else
1150 args.gid = (__u64)current->fsgid; 1198 args.gid = (__u64)current_fsgid();
1151 } else { 1199 } else {
1152 args.uid = NO_CHANGE_64; 1200 args.uid = NO_CHANGE_64;
1153 args.gid = NO_CHANGE_64; 1201 args.gid = NO_CHANGE_64;
@@ -1184,13 +1232,13 @@ mkdir_get_info:
1184 if (cifs_sb->mnt_cifs_flags & 1232 if (cifs_sb->mnt_cifs_flags &
1185 CIFS_MOUNT_SET_UID) { 1233 CIFS_MOUNT_SET_UID) {
1186 direntry->d_inode->i_uid = 1234 direntry->d_inode->i_uid =
1187 current->fsuid; 1235 current_fsuid();
1188 if (inode->i_mode & S_ISGID) 1236 if (inode->i_mode & S_ISGID)
1189 direntry->d_inode->i_gid = 1237 direntry->d_inode->i_gid =
1190 inode->i_gid; 1238 inode->i_gid;
1191 else 1239 else
1192 direntry->d_inode->i_gid = 1240 direntry->d_inode->i_gid =
1193 current->fsgid; 1241 current_fsgid();
1194 } 1242 }
1195 } 1243 }
1196 } 1244 }
@@ -1593,7 +1641,7 @@ do_expand:
1593 i_size_write(inode, offset); 1641 i_size_write(inode, offset);
1594 spin_unlock(&inode->i_lock); 1642 spin_unlock(&inode->i_lock);
1595out_truncate: 1643out_truncate:
1596 if (inode->i_op && inode->i_op->truncate) 1644 if (inode->i_op->truncate)
1597 inode->i_op->truncate(inode); 1645 inode->i_op->truncate(inode);
1598 return 0; 1646 return 0;
1599out_sig: 1647out_sig:
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 0088a5b52564..f94650683a00 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -65,7 +65,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
65 switch (command) { 65 switch (command) {
66 case CIFS_IOC_CHECKUMOUNT: 66 case CIFS_IOC_CHECKUMOUNT:
67 cFYI(1, ("User unmount attempted")); 67 cFYI(1, ("User unmount attempted"));
68 if (cifs_sb->mnt_uid == current->uid) 68 if (cifs_sb->mnt_uid == current_uid())
69 rc = 0; 69 rc = 0;
70 else { 70 else {
71 rc = -EACCES; 71 rc = -EACCES;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 9ee3f689c2b0..4c89c572891a 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -97,7 +97,10 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
97 kfree(buf_to_free->serverOS); 97 kfree(buf_to_free->serverOS);
98 kfree(buf_to_free->serverDomain); 98 kfree(buf_to_free->serverDomain);
99 kfree(buf_to_free->serverNOS); 99 kfree(buf_to_free->serverNOS);
100 kfree(buf_to_free->password); 100 if (buf_to_free->password) {
101 memset(buf_to_free->password, 0, strlen(buf_to_free->password));
102 kfree(buf_to_free->password);
103 }
101 kfree(buf_to_free->domainName); 104 kfree(buf_to_free->domainName);
102 kfree(buf_to_free); 105 kfree(buf_to_free);
103} 106}
@@ -129,6 +132,10 @@ tconInfoFree(struct cifsTconInfo *buf_to_free)
129 } 132 }
130 atomic_dec(&tconInfoAllocCount); 133 atomic_dec(&tconInfoAllocCount);
131 kfree(buf_to_free->nativeFileSystem); 134 kfree(buf_to_free->nativeFileSystem);
135 if (buf_to_free->password) {
136 memset(buf_to_free->password, 0, strlen(buf_to_free->password));
137 kfree(buf_to_free->password);
138 }
132 kfree(buf_to_free); 139 kfree(buf_to_free);
133} 140}
134 141
@@ -338,13 +345,13 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
338 /* BB Add support for establishing new tCon and SMB Session */ 345 /* BB Add support for establishing new tCon and SMB Session */
339 /* with userid/password pairs found on the smb session */ 346 /* with userid/password pairs found on the smb session */
340 /* for other target tcp/ip addresses BB */ 347 /* for other target tcp/ip addresses BB */
341 if (current->fsuid != treeCon->ses->linux_uid) { 348 if (current_fsuid() != treeCon->ses->linux_uid) {
342 cFYI(1, ("Multiuser mode and UID " 349 cFYI(1, ("Multiuser mode and UID "
343 "did not match tcon uid")); 350 "did not match tcon uid"));
344 read_lock(&cifs_tcp_ses_lock); 351 read_lock(&cifs_tcp_ses_lock);
345 list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) { 352 list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
346 ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list); 353 ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
347 if (ses->linux_uid == current->fsuid) { 354 if (ses->linux_uid == current_fsuid()) {
348 if (ses->server == treeCon->ses->server) { 355 if (ses->server == treeCon->ses->server) {
349 cFYI(1, ("found matching uid substitute right smb_uid")); 356 cFYI(1, ("found matching uid substitute right smb_uid"));
350 buffer->Uid = ses->Suid; 357 buffer->Uid = ses->Suid;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 2851d5da0c8c..5f22de7b79a9 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -417,7 +417,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
417 /* BB calculate hash with password */ 417 /* BB calculate hash with password */
418 /* and copy into bcc */ 418 /* and copy into bcc */
419 419
420 calc_lanman_hash(ses, lnm_session_key); 420 calc_lanman_hash(ses->password, ses->server->cryptKey,
421 ses->server->secMode & SECMODE_PW_ENCRYPT ?
422 true : false, lnm_session_key);
423
421 ses->flags |= CIFS_SES_LANMAN; 424 ses->flags |= CIFS_SES_LANMAN;
422 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE); 425 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
423 bcc_ptr += CIFS_SESS_KEY_SIZE; 426 bcc_ptr += CIFS_SESS_KEY_SIZE;
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
index 04943c976f98..224a1f478966 100644
--- a/fs/cifs/smbdes.c
+++ b/fs/cifs/smbdes.c
@@ -318,7 +318,8 @@ str_to_key(unsigned char *str, unsigned char *key)
318} 318}
319 319
320static void 320static void
321smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw) 321smbhash(unsigned char *out, const unsigned char *in, unsigned char *key,
322 int forw)
322{ 323{
323 int i; 324 int i;
324 char *outb; /* outb[64] */ 325 char *outb; /* outb[64] */
@@ -363,7 +364,7 @@ E_P16(unsigned char *p14, unsigned char *p16)
363} 364}
364 365
365void 366void
366E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) 367E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
367{ 368{
368 smbhash(p24, c8, p21, 1); 369 smbhash(p24, c8, p21, 1);
369 smbhash(p24 + 8, c8, p21 + 7, 1); 370 smbhash(p24 + 8, c8, p21 + 7, 1);
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index ff3232fa1015..93fb09a99c69 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -49,9 +49,10 @@
49 49
50/*The following definitions come from libsmb/smbencrypt.c */ 50/*The following definitions come from libsmb/smbencrypt.c */
51 51
52void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); 52void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
53 unsigned char *p24);
53void E_md4hash(const unsigned char *passwd, unsigned char *p16); 54void E_md4hash(const unsigned char *passwd, unsigned char *p16);
54static void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, 55static void SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8,
55 unsigned char p24[24]); 56 unsigned char p24[24]);
56void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); 57void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
57 58
@@ -61,7 +62,7 @@ void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
61 encrypted password into p24 */ 62 encrypted password into p24 */
62/* Note that password must be uppercased and null terminated */ 63/* Note that password must be uppercased and null terminated */
63void 64void
64SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) 65SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24)
65{ 66{
66 unsigned char p14[15], p21[21]; 67 unsigned char p14[15], p21[21];
67 68
@@ -212,7 +213,7 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
212 213
213/* Does the des encryption from the NT or LM MD4 hash. */ 214/* Does the des encryption from the NT or LM MD4 hash. */
214static void 215static void
215SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, 216SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8,
216 unsigned char p24[24]) 217 unsigned char p24[24])
217{ 218{
218 unsigned char p21[21]; 219 unsigned char p21[21];
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index ff8243a8fe3e..7ebe6599ed3a 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -37,15 +37,11 @@ extern mempool_t *cifs_mid_poolp;
37extern struct kmem_cache *cifs_oplock_cachep; 37extern struct kmem_cache *cifs_oplock_cachep;
38 38
39static struct mid_q_entry * 39static struct mid_q_entry *
40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) 40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
41{ 41{
42 struct mid_q_entry *temp; 42 struct mid_q_entry *temp;
43 43
44 if (ses == NULL) { 44 if (server == NULL) {
45 cERROR(1, ("Null session passed in to AllocMidQEntry"));
46 return NULL;
47 }
48 if (ses->server == NULL) {
49 cERROR(1, ("Null TCP session in AllocMidQEntry")); 45 cERROR(1, ("Null TCP session in AllocMidQEntry"));
50 return NULL; 46 return NULL;
51 } 47 }
@@ -62,12 +58,11 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
62 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ 58 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
63 /* when mid allocated can be before when sent */ 59 /* when mid allocated can be before when sent */
64 temp->when_alloc = jiffies; 60 temp->when_alloc = jiffies;
65 temp->ses = ses;
66 temp->tsk = current; 61 temp->tsk = current;
67 } 62 }
68 63
69 spin_lock(&GlobalMid_Lock); 64 spin_lock(&GlobalMid_Lock);
70 list_add_tail(&temp->qhead, &ses->server->pending_mid_q); 65 list_add_tail(&temp->qhead, &server->pending_mid_q);
71 atomic_inc(&midCount); 66 atomic_inc(&midCount);
72 temp->midState = MID_REQUEST_ALLOCATED; 67 temp->midState = MID_REQUEST_ALLOCATED;
73 spin_unlock(&GlobalMid_Lock); 68 spin_unlock(&GlobalMid_Lock);
@@ -349,37 +344,38 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
349 if (long_op == CIFS_ASYNC_OP) { 344 if (long_op == CIFS_ASYNC_OP) {
350 /* oplock breaks must not be held up */ 345 /* oplock breaks must not be held up */
351 atomic_inc(&ses->server->inFlight); 346 atomic_inc(&ses->server->inFlight);
352 } else { 347 return 0;
353 spin_lock(&GlobalMid_Lock); 348 }
354 while (1) { 349
355 if (atomic_read(&ses->server->inFlight) >= 350 spin_lock(&GlobalMid_Lock);
356 cifs_max_pending){ 351 while (1) {
357 spin_unlock(&GlobalMid_Lock); 352 if (atomic_read(&ses->server->inFlight) >=
353 cifs_max_pending){
354 spin_unlock(&GlobalMid_Lock);
358#ifdef CONFIG_CIFS_STATS2 355#ifdef CONFIG_CIFS_STATS2
359 atomic_inc(&ses->server->num_waiters); 356 atomic_inc(&ses->server->num_waiters);
360#endif 357#endif
361 wait_event(ses->server->request_q, 358 wait_event(ses->server->request_q,
362 atomic_read(&ses->server->inFlight) 359 atomic_read(&ses->server->inFlight)
363 < cifs_max_pending); 360 < cifs_max_pending);
364#ifdef CONFIG_CIFS_STATS2 361#ifdef CONFIG_CIFS_STATS2
365 atomic_dec(&ses->server->num_waiters); 362 atomic_dec(&ses->server->num_waiters);
366#endif 363#endif
367 spin_lock(&GlobalMid_Lock); 364 spin_lock(&GlobalMid_Lock);
368 } else { 365 } else {
369 if (ses->server->tcpStatus == CifsExiting) { 366 if (ses->server->tcpStatus == CifsExiting) {
370 spin_unlock(&GlobalMid_Lock);
371 return -ENOENT;
372 }
373
374 /* can not count locking commands against total
375 as they are allowed to block on server */
376
377 /* update # of requests on the wire to server */
378 if (long_op != CIFS_BLOCKING_OP)
379 atomic_inc(&ses->server->inFlight);
380 spin_unlock(&GlobalMid_Lock); 367 spin_unlock(&GlobalMid_Lock);
381 break; 368 return -ENOENT;
382 } 369 }
370
371 /* can not count locking commands against total
372 as they are allowed to block on server */
373
374 /* update # of requests on the wire to server */
375 if (long_op != CIFS_BLOCKING_OP)
376 atomic_inc(&ses->server->inFlight);
377 spin_unlock(&GlobalMid_Lock);
378 break;
383 } 379 }
384 } 380 }
385 return 0; 381 return 0;
@@ -390,17 +386,21 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
390{ 386{
391 if (ses->server->tcpStatus == CifsExiting) { 387 if (ses->server->tcpStatus == CifsExiting) {
392 return -ENOENT; 388 return -ENOENT;
393 } else if (ses->server->tcpStatus == CifsNeedReconnect) { 389 }
390
391 if (ses->server->tcpStatus == CifsNeedReconnect) {
394 cFYI(1, ("tcp session dead - return to caller to retry")); 392 cFYI(1, ("tcp session dead - return to caller to retry"));
395 return -EAGAIN; 393 return -EAGAIN;
396 } else if (ses->status != CifsGood) { 394 }
395
396 if (ses->status != CifsGood) {
397 /* check if SMB session is bad because we are setting it up */ 397 /* check if SMB session is bad because we are setting it up */
398 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 398 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
399 (in_buf->Command != SMB_COM_NEGOTIATE)) 399 (in_buf->Command != SMB_COM_NEGOTIATE))
400 return -EAGAIN; 400 return -EAGAIN;
401 /* else ok - we are setting up session */ 401 /* else ok - we are setting up session */
402 } 402 }
403 *ppmidQ = AllocMidQEntry(in_buf, ses); 403 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
404 if (*ppmidQ == NULL) 404 if (*ppmidQ == NULL)
405 return -ENOMEM; 405 return -ENOMEM;
406 return 0; 406 return 0;
@@ -415,11 +415,8 @@ static int wait_for_response(struct cifsSesInfo *ses,
415 415
416 for (;;) { 416 for (;;) {
417 curr_timeout = timeout + jiffies; 417 curr_timeout = timeout + jiffies;
418 wait_event(ses->server->response_q, 418 wait_event_timeout(ses->server->response_q,
419 (!(midQ->midState == MID_REQUEST_SUBMITTED)) || 419 midQ->midState != MID_REQUEST_SUBMITTED, timeout);
420 time_after(jiffies, curr_timeout) ||
421 ((ses->server->tcpStatus != CifsGood) &&
422 (ses->server->tcpStatus != CifsNew)));
423 420
424 if (time_after(jiffies, curr_timeout) && 421 if (time_after(jiffies, curr_timeout) &&
425 (midQ->midState == MID_REQUEST_SUBMITTED) && 422 (midQ->midState == MID_REQUEST_SUBMITTED) &&
@@ -521,11 +518,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
521 and avoid races inside tcp sendmsg code that could cause corruption 518 and avoid races inside tcp sendmsg code that could cause corruption
522 of smb data */ 519 of smb data */
523 520
524 down(&ses->server->tcpSem); 521 mutex_lock(&ses->server->srv_mutex);
525 522
526 rc = allocate_mid(ses, in_buf, &midQ); 523 rc = allocate_mid(ses, in_buf, &midQ);
527 if (rc) { 524 if (rc) {
528 up(&ses->server->tcpSem); 525 mutex_unlock(&ses->server->srv_mutex);
529 cifs_small_buf_release(in_buf); 526 cifs_small_buf_release(in_buf);
530 /* Update # of requests on wire to server */ 527 /* Update # of requests on wire to server */
531 atomic_dec(&ses->server->inFlight); 528 atomic_dec(&ses->server->inFlight);
@@ -533,6 +530,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
533 return rc; 530 return rc;
534 } 531 }
535 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); 532 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
533 if (rc) {
534 mutex_unlock(&ses->server->srv_mutex);
535 cifs_small_buf_release(in_buf);
536 goto out;
537 }
536 538
537 midQ->midState = MID_REQUEST_SUBMITTED; 539 midQ->midState = MID_REQUEST_SUBMITTED;
538#ifdef CONFIG_CIFS_STATS2 540#ifdef CONFIG_CIFS_STATS2
@@ -546,7 +548,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
546 midQ->when_sent = jiffies; 548 midQ->when_sent = jiffies;
547#endif 549#endif
548 550
549 up(&ses->server->tcpSem); 551 mutex_unlock(&ses->server->srv_mutex);
550 cifs_small_buf_release(in_buf); 552 cifs_small_buf_release(in_buf);
551 553
552 if (rc < 0) 554 if (rc < 0)
@@ -581,10 +583,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
581 wait_for_response(ses, midQ, timeout, 10 * HZ); 583 wait_for_response(ses, midQ, timeout, 10 * HZ);
582 584
583 spin_lock(&GlobalMid_Lock); 585 spin_lock(&GlobalMid_Lock);
584 if (midQ->resp_buf) { 586
585 spin_unlock(&GlobalMid_Lock); 587 if (midQ->resp_buf == NULL) {
586 receive_len = midQ->resp_buf->smb_buf_length;
587 } else {
588 cERROR(1, ("No response to cmd %d mid %d", 588 cERROR(1, ("No response to cmd %d mid %d",
589 midQ->command, midQ->mid)); 589 midQ->command, midQ->mid));
590 if (midQ->midState == MID_REQUEST_SUBMITTED) { 590 if (midQ->midState == MID_REQUEST_SUBMITTED) {
@@ -612,53 +612,59 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
612 return rc; 612 return rc;
613 } 613 }
614 614
615 spin_unlock(&GlobalMid_Lock);
616 receive_len = midQ->resp_buf->smb_buf_length;
617
615 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 618 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
616 cERROR(1, ("Frame too large received. Length: %d Xid: %d", 619 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
617 receive_len, xid)); 620 receive_len, xid));
618 rc = -EIO; 621 rc = -EIO;
619 } else { /* rcvd frame is ok */ 622 goto out;
620 if (midQ->resp_buf && 623 }
621 (midQ->midState == MID_RESPONSE_RECEIVED)) { 624
622 625 /* rcvd frame is ok */
623 iov[0].iov_base = (char *)midQ->resp_buf; 626
624 if (midQ->largeBuf) 627 if (midQ->resp_buf &&
625 *pRespBufType = CIFS_LARGE_BUFFER; 628 (midQ->midState == MID_RESPONSE_RECEIVED)) {
626 else 629
627 *pRespBufType = CIFS_SMALL_BUFFER; 630 iov[0].iov_base = (char *)midQ->resp_buf;
628 iov[0].iov_len = receive_len + 4; 631 if (midQ->largeBuf)
629 632 *pRespBufType = CIFS_LARGE_BUFFER;
630 dump_smb(midQ->resp_buf, 80); 633 else
631 /* convert the length into a more usable form */ 634 *pRespBufType = CIFS_SMALL_BUFFER;
632 if ((receive_len > 24) && 635 iov[0].iov_len = receive_len + 4;
633 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 636
634 SECMODE_SIGN_ENABLED))) { 637 dump_smb(midQ->resp_buf, 80);
635 rc = cifs_verify_signature(midQ->resp_buf, 638 /* convert the length into a more usable form */
639 if ((receive_len > 24) &&
640 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
641 SECMODE_SIGN_ENABLED))) {
642 rc = cifs_verify_signature(midQ->resp_buf,
636 &ses->server->mac_signing_key, 643 &ses->server->mac_signing_key,
637 midQ->sequence_number+1); 644 midQ->sequence_number+1);
638 if (rc) { 645 if (rc) {
639 cERROR(1, ("Unexpected SMB signature")); 646 cERROR(1, ("Unexpected SMB signature"));
640 /* BB FIXME add code to kill session */ 647 /* BB FIXME add code to kill session */
641 }
642 } 648 }
643
644 /* BB special case reconnect tid and uid here? */
645 rc = map_smb_to_linux_error(midQ->resp_buf,
646 flags & CIFS_LOG_ERROR);
647
648 /* convert ByteCount if necessary */
649 if (receive_len >= sizeof(struct smb_hdr) - 4
650 /* do not count RFC1001 header */ +
651 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
652 BCC(midQ->resp_buf) =
653 le16_to_cpu(BCC_LE(midQ->resp_buf));
654 if ((flags & CIFS_NO_RESP) == 0)
655 midQ->resp_buf = NULL; /* mark it so buf will
656 not be freed by
657 DeleteMidQEntry */
658 } else {
659 rc = -EIO;
660 cFYI(1, ("Bad MID state?"));
661 } 649 }
650
651 /* BB special case reconnect tid and uid here? */
652 rc = map_smb_to_linux_error(midQ->resp_buf,
653 flags & CIFS_LOG_ERROR);
654
655 /* convert ByteCount if necessary */
656 if (receive_len >= sizeof(struct smb_hdr) - 4
657 /* do not count RFC1001 header */ +
658 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
659 BCC(midQ->resp_buf) =
660 le16_to_cpu(BCC_LE(midQ->resp_buf));
661 if ((flags & CIFS_NO_RESP) == 0)
662 midQ->resp_buf = NULL; /* mark it so buf will
663 not be freed by
664 DeleteMidQEntry */
665 } else {
666 rc = -EIO;
667 cFYI(1, ("Bad MID state?"));
662 } 668 }
663 669
664out: 670out:
@@ -695,6 +701,12 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
695 to the same server. We may make this configurable later or 701 to the same server. We may make this configurable later or
696 use ses->maxReq */ 702 use ses->maxReq */
697 703
704 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
705 cERROR(1, ("Illegal length, greater than maximum frame, %d",
706 in_buf->smb_buf_length));
707 return -EIO;
708 }
709
698 rc = wait_for_free_request(ses, long_op); 710 rc = wait_for_free_request(ses, long_op);
699 if (rc) 711 if (rc)
700 return rc; 712 return rc;
@@ -703,29 +715,22 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
703 and avoid races inside tcp sendmsg code that could cause corruption 715 and avoid races inside tcp sendmsg code that could cause corruption
704 of smb data */ 716 of smb data */
705 717
706 down(&ses->server->tcpSem); 718 mutex_lock(&ses->server->srv_mutex);
707 719
708 rc = allocate_mid(ses, in_buf, &midQ); 720 rc = allocate_mid(ses, in_buf, &midQ);
709 if (rc) { 721 if (rc) {
710 up(&ses->server->tcpSem); 722 mutex_unlock(&ses->server->srv_mutex);
711 /* Update # of requests on wire to server */ 723 /* Update # of requests on wire to server */
712 atomic_dec(&ses->server->inFlight); 724 atomic_dec(&ses->server->inFlight);
713 wake_up(&ses->server->request_q); 725 wake_up(&ses->server->request_q);
714 return rc; 726 return rc;
715 } 727 }
716 728
717 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
718 cERROR(1, ("Illegal length, greater than maximum frame, %d",
719 in_buf->smb_buf_length));
720 DeleteMidQEntry(midQ);
721 up(&ses->server->tcpSem);
722 /* Update # of requests on wire to server */
723 atomic_dec(&ses->server->inFlight);
724 wake_up(&ses->server->request_q);
725 return -EIO;
726 }
727
728 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 729 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
730 if (rc) {
731 mutex_unlock(&ses->server->srv_mutex);
732 goto out;
733 }
729 734
730 midQ->midState = MID_REQUEST_SUBMITTED; 735 midQ->midState = MID_REQUEST_SUBMITTED;
731#ifdef CONFIG_CIFS_STATS2 736#ifdef CONFIG_CIFS_STATS2
@@ -738,7 +743,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
738 atomic_dec(&ses->server->inSend); 743 atomic_dec(&ses->server->inSend);
739 midQ->when_sent = jiffies; 744 midQ->when_sent = jiffies;
740#endif 745#endif
741 up(&ses->server->tcpSem); 746 mutex_unlock(&ses->server->srv_mutex);
742 747
743 if (rc < 0) 748 if (rc < 0)
744 goto out; 749 goto out;
@@ -772,10 +777,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
772 wait_for_response(ses, midQ, timeout, 10 * HZ); 777 wait_for_response(ses, midQ, timeout, 10 * HZ);
773 778
774 spin_lock(&GlobalMid_Lock); 779 spin_lock(&GlobalMid_Lock);
775 if (midQ->resp_buf) { 780 if (midQ->resp_buf == NULL) {
776 spin_unlock(&GlobalMid_Lock);
777 receive_len = midQ->resp_buf->smb_buf_length;
778 } else {
779 cERROR(1, ("No response for cmd %d mid %d", 781 cERROR(1, ("No response for cmd %d mid %d",
780 midQ->command, midQ->mid)); 782 midQ->command, midQ->mid));
781 if (midQ->midState == MID_REQUEST_SUBMITTED) { 783 if (midQ->midState == MID_REQUEST_SUBMITTED) {
@@ -803,47 +805,52 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
803 return rc; 805 return rc;
804 } 806 }
805 807
808 spin_unlock(&GlobalMid_Lock);
809 receive_len = midQ->resp_buf->smb_buf_length;
810
806 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 811 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
807 cERROR(1, ("Frame too large received. Length: %d Xid: %d", 812 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
808 receive_len, xid)); 813 receive_len, xid));
809 rc = -EIO; 814 rc = -EIO;
810 } else { /* rcvd frame is ok */ 815 goto out;
811 816 }
812 if (midQ->resp_buf && out_buf 817
813 && (midQ->midState == MID_RESPONSE_RECEIVED)) { 818 /* rcvd frame is ok */
814 out_buf->smb_buf_length = receive_len; 819
815 memcpy((char *)out_buf + 4, 820 if (midQ->resp_buf && out_buf
816 (char *)midQ->resp_buf + 4, 821 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
817 receive_len); 822 out_buf->smb_buf_length = receive_len;
818 823 memcpy((char *)out_buf + 4,
819 dump_smb(out_buf, 92); 824 (char *)midQ->resp_buf + 4,
820 /* convert the length into a more usable form */ 825 receive_len);
821 if ((receive_len > 24) && 826
822 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 827 dump_smb(out_buf, 92);
823 SECMODE_SIGN_ENABLED))) { 828 /* convert the length into a more usable form */
824 rc = cifs_verify_signature(out_buf, 829 if ((receive_len > 24) &&
830 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
831 SECMODE_SIGN_ENABLED))) {
832 rc = cifs_verify_signature(out_buf,
825 &ses->server->mac_signing_key, 833 &ses->server->mac_signing_key,
826 midQ->sequence_number+1); 834 midQ->sequence_number+1);
827 if (rc) { 835 if (rc) {
828 cERROR(1, ("Unexpected SMB signature")); 836 cERROR(1, ("Unexpected SMB signature"));
829 /* BB FIXME add code to kill session */ 837 /* BB FIXME add code to kill session */
830 }
831 } 838 }
839 }
832 840
833 *pbytes_returned = out_buf->smb_buf_length; 841 *pbytes_returned = out_buf->smb_buf_length;
834 842
835 /* BB special case reconnect tid and uid here? */ 843 /* BB special case reconnect tid and uid here? */
836 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); 844 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
837 845
838 /* convert ByteCount if necessary */ 846 /* convert ByteCount if necessary */
839 if (receive_len >= sizeof(struct smb_hdr) - 4 847 if (receive_len >= sizeof(struct smb_hdr) - 4
840 /* do not count RFC1001 header */ + 848 /* do not count RFC1001 header */ +
841 (2 * out_buf->WordCount) + 2 /* bcc */ ) 849 (2 * out_buf->WordCount) + 2 /* bcc */ )
842 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 850 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
843 } else { 851 } else {
844 rc = -EIO; 852 rc = -EIO;
845 cERROR(1, ("Bad MID state?")); 853 cERROR(1, ("Bad MID state?"));
846 }
847 } 854 }
848 855
849out: 856out:
@@ -866,16 +873,16 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
866 873
867 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0); 874 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
868 in_buf->Mid = mid; 875 in_buf->Mid = mid;
869 down(&ses->server->tcpSem); 876 mutex_lock(&ses->server->srv_mutex);
870 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 877 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
871 if (rc) { 878 if (rc) {
872 up(&ses->server->tcpSem); 879 mutex_unlock(&ses->server->srv_mutex);
873 return rc; 880 return rc;
874 } 881 }
875 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 882 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
876 (struct sockaddr *) &(ses->server->addr.sockAddr), 883 (struct sockaddr *) &(ses->server->addr.sockAddr),
877 ses->server->noblocksnd); 884 ses->server->noblocksnd);
878 up(&ses->server->tcpSem); 885 mutex_unlock(&ses->server->srv_mutex);
879 return rc; 886 return rc;
880} 887}
881 888
@@ -933,6 +940,12 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
933 to the same server. We may make this configurable later or 940 to the same server. We may make this configurable later or
934 use ses->maxReq */ 941 use ses->maxReq */
935 942
943 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
944 cERROR(1, ("Illegal length, greater than maximum frame, %d",
945 in_buf->smb_buf_length));
946 return -EIO;
947 }
948
936 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP); 949 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
937 if (rc) 950 if (rc)
938 return rc; 951 return rc;
@@ -941,24 +954,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
941 and avoid races inside tcp sendmsg code that could cause corruption 954 and avoid races inside tcp sendmsg code that could cause corruption
942 of smb data */ 955 of smb data */
943 956
944 down(&ses->server->tcpSem); 957 mutex_lock(&ses->server->srv_mutex);
945 958
946 rc = allocate_mid(ses, in_buf, &midQ); 959 rc = allocate_mid(ses, in_buf, &midQ);
947 if (rc) { 960 if (rc) {
948 up(&ses->server->tcpSem); 961 mutex_unlock(&ses->server->srv_mutex);
949 return rc; 962 return rc;
950 } 963 }
951 964
952 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 965 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
953 up(&ses->server->tcpSem); 966 if (rc) {
954 cERROR(1, ("Illegal length, greater than maximum frame, %d",
955 in_buf->smb_buf_length));
956 DeleteMidQEntry(midQ); 967 DeleteMidQEntry(midQ);
957 return -EIO; 968 mutex_unlock(&ses->server->srv_mutex);
969 return rc;
958 } 970 }
959 971
960 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
961
962 midQ->midState = MID_REQUEST_SUBMITTED; 972 midQ->midState = MID_REQUEST_SUBMITTED;
963#ifdef CONFIG_CIFS_STATS2 973#ifdef CONFIG_CIFS_STATS2
964 atomic_inc(&ses->server->inSend); 974 atomic_inc(&ses->server->inSend);
@@ -970,7 +980,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
970 atomic_dec(&ses->server->inSend); 980 atomic_dec(&ses->server->inSend);
971 midQ->when_sent = jiffies; 981 midQ->when_sent = jiffies;
972#endif 982#endif
973 up(&ses->server->tcpSem); 983 mutex_unlock(&ses->server->srv_mutex);
974 984
975 if (rc < 0) { 985 if (rc < 0) {
976 DeleteMidQEntry(midQ); 986 DeleteMidQEntry(midQ);
@@ -1052,44 +1062,48 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
1052 cERROR(1, ("Frame too large received. Length: %d Xid: %d", 1062 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1053 receive_len, xid)); 1063 receive_len, xid));
1054 rc = -EIO; 1064 rc = -EIO;
1055 } else { /* rcvd frame is ok */ 1065 goto out;
1056 1066 }
1057 if (midQ->resp_buf && out_buf
1058 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
1059 out_buf->smb_buf_length = receive_len;
1060 memcpy((char *)out_buf + 4,
1061 (char *)midQ->resp_buf + 4,
1062 receive_len);
1063
1064 dump_smb(out_buf, 92);
1065 /* convert the length into a more usable form */
1066 if ((receive_len > 24) &&
1067 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1068 SECMODE_SIGN_ENABLED))) {
1069 rc = cifs_verify_signature(out_buf,
1070 &ses->server->mac_signing_key,
1071 midQ->sequence_number+1);
1072 if (rc) {
1073 cERROR(1, ("Unexpected SMB signature"));
1074 /* BB FIXME add code to kill session */
1075 }
1076 }
1077 1067
1078 *pbytes_returned = out_buf->smb_buf_length; 1068 /* rcvd frame is ok */
1079 1069
1080 /* BB special case reconnect tid and uid here? */ 1070 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
1081 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); 1071 rc = -EIO;
1072 cERROR(1, ("Bad MID state?"));
1073 goto out;
1074 }
1082 1075
1083 /* convert ByteCount if necessary */ 1076 out_buf->smb_buf_length = receive_len;
1084 if (receive_len >= sizeof(struct smb_hdr) - 4 1077 memcpy((char *)out_buf + 4,
1085 /* do not count RFC1001 header */ + 1078 (char *)midQ->resp_buf + 4,
1086 (2 * out_buf->WordCount) + 2 /* bcc */ ) 1079 receive_len);
1087 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 1080
1088 } else { 1081 dump_smb(out_buf, 92);
1089 rc = -EIO; 1082 /* convert the length into a more usable form */
1090 cERROR(1, ("Bad MID state?")); 1083 if ((receive_len > 24) &&
1084 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1085 SECMODE_SIGN_ENABLED))) {
1086 rc = cifs_verify_signature(out_buf,
1087 &ses->server->mac_signing_key,
1088 midQ->sequence_number+1);
1089 if (rc) {
1090 cERROR(1, ("Unexpected SMB signature"));
1091 /* BB FIXME add code to kill session */
1091 } 1092 }
1092 } 1093 }
1094
1095 *pbytes_returned = out_buf->smb_buf_length;
1096
1097 /* BB special case reconnect tid and uid here? */
1098 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1099
1100 /* convert ByteCount if necessary */
1101 if (receive_len >= sizeof(struct smb_hdr) - 4
1102 /* do not count RFC1001 header */ +
1103 (2 * out_buf->WordCount) + 2 /* bcc */ )
1104 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1105
1106out:
1093 DeleteMidQEntry(midQ); 1107 DeleteMidQEntry(midQ);
1094 if (rstart && rc == -EACCES) 1108 if (rstart && rc == -EACCES)
1095 return -ERESTARTSYS; 1109 return -ERESTARTSYS;