diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/AUTHORS | 2 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 9 | ||||
-rw-r--r-- | fs/cifs/Makefile | 2 | ||||
-rw-r--r-- | fs/cifs/README | 12 | ||||
-rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 48 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 7 | ||||
-rw-r--r-- | fs/cifs/cifs_spnego.c | 6 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 30 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 82 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 15 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 5 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 52 | ||||
-rw-r--r-- | fs/cifs/connect.c | 685 | ||||
-rw-r--r-- | fs/cifs/dir.c | 21 | ||||
-rw-r--r-- | fs/cifs/fcntl.c | 118 | ||||
-rw-r--r-- | fs/cifs/file.c | 102 | ||||
-rw-r--r-- | fs/cifs/inode.c | 68 | ||||
-rw-r--r-- | fs/cifs/ioctl.c | 2 | ||||
-rw-r--r-- | fs/cifs/misc.c | 13 | ||||
-rw-r--r-- | fs/cifs/sess.c | 5 | ||||
-rw-r--r-- | fs/cifs/smbdes.c | 5 | ||||
-rw-r--r-- | fs/cifs/smbencrypt.c | 9 | ||||
-rw-r--r-- | fs/cifs/transport.c | 378 |
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 | |||
36 | Kazeon team for various fixes especially for 2.4 version. | 36 | Kazeon team for various fixes especially for 2.4 version. |
37 | Asser Ferno (Change Notify support) | 37 | Asser Ferno (Change Notify support) |
38 | Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup | 38 | Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup |
39 | Gunter Kukkukk (testing and suggestions for support of old servers) | ||
39 | Igor Mammedov (DFS support) | 40 | Igor Mammedov (DFS support) |
41 | Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code) | ||
40 | 42 | ||
41 | Test case and Bug Report contributors | 43 | Test 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 @@ | |||
1 | Version 1.56 | ||
2 | ------------ | ||
3 | Add "forcemandatorylock" mount option to allow user to use mandatory | ||
4 | rather than posix (advisory) byte range locks, even though server would | ||
5 | support posix byte range locks. Fix query of root inode when prefixpath | ||
6 | specified and user does not have access to query information about the | ||
7 | top of the share. Fix problem in 2.6.28 resolving DFS paths to | ||
8 | Samba servers (worked to Windows). | ||
9 | |||
1 | Version 1.55 | 10 | Version 1.55 |
2 | ------------ | 11 | ------------ |
3 | Various fixes to make delete of open files behavior more predictable | 12 | Various 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 | ||
6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ | 6 | cifs-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 | ||
11 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o | 11 | cifs-$(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, | |||
217 | compose_mount_options_out: | 230 | compose_mount_options_out: |
218 | kfree(srvIP); | 231 | kfree(srvIP); |
219 | return mountdata; | 232 | return mountdata; |
233 | |||
234 | compose_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 | ||
35 | struct cifs_sb_info { | 36 | struct 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 | ||
38 | extern void mdfour(unsigned char *out, unsigned char *in, int n); | 38 | extern void mdfour(unsigned char *out, unsigned char *in, int n); |
39 | extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); | 39 | extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); |
40 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | 40 | extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, |
41 | unsigned char *p24); | 41 | unsigned char *p24); |
42 | 42 | ||
43 | static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, | 43 | static 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 |
283 | void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key) | 283 | void 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 @@ | |||
26 | extern void mdfour(unsigned char *out, unsigned char *in, int n); | 26 | extern void mdfour(unsigned char *out, unsigned char *in, int n); |
27 | /* smbdes.c */ | 27 | /* smbdes.c */ |
28 | extern void E_P16(unsigned char *p14, unsigned char *p16); | 28 | extern void E_P16(unsigned char *p14, unsigned char *p16); |
29 | extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); | 29 | extern 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; | |||
66 | extern struct task_struct *oplockThread; /* remove sparse warning */ | 66 | extern struct task_struct *oplockThread; /* remove sparse warning */ |
67 | struct task_struct *oplockThread = NULL; | 67 | struct 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 | ||
69 | static struct task_struct *dnotifyThread = NULL; | 70 | static struct task_struct *dnotifyThread = NULL; |
71 | #endif | ||
70 | static const struct super_operations cifs_super_ops; | 72 | static const struct super_operations cifs_super_ops; |
71 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; | 73 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; |
72 | module_param(CIFSMaxBufSize, int, 0); | 74 | module_param(CIFSMaxBufSize, int, 0); |
@@ -337,39 +339,58 @@ static int | |||
337 | cifs_show_options(struct seq_file *s, struct vfsmount *m) | 339 | cifs_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 | ||
1032 | static int cifs_dnotify_thread(void *dummyarg) | 1043 | static 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 | ||
1058 | static int __init | 1070 | static int __init |
1059 | init_cifs(void) | 1071 | init_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 | ||
1186 | MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); | 1204 | MODULE_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 *); | |||
76 | extern const struct file_operations cifs_dir_ops; | 76 | extern const struct file_operations cifs_dir_ops; |
77 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 77 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
78 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | 78 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); |
79 | extern int cifs_dir_notify(struct file *, unsigned long arg); | ||
80 | 79 | ||
81 | /* Functions related to dir entries */ | 80 | /* Functions related to dir entries */ |
82 | extern struct dentry_operations cifs_dentry_ops; | 81 | extern struct dentry_operations cifs_dentry_ops; |
@@ -101,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
101 | extern const struct export_operations cifs_export_ops; | 100 | extern 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); |
40 | extern unsigned int _GetXid(void); | 40 | extern unsigned int _GetXid(void); |
41 | extern void _FreeXid(unsigned int); | 41 | extern 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));} |
44 | extern char *build_path_from_dentry(struct dentry *); | 44 | extern char *build_path_from_dentry(struct dentry *); |
45 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); | 45 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); |
@@ -330,7 +330,8 @@ extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); | |||
330 | extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | 330 | extern 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 |
333 | extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); | 333 | extern 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 */ |
335 | extern int CIFSSMBCopy(int xid, | 336 | extern 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 | ||
104 | static int ipv4_connect(struct sockaddr_in *psin_server, | 105 | static int ipv4_connect(struct TCP_Server_Info *server); |
105 | struct socket **csocket, | 106 | static 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 */ | ||
110 | static 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 | */ | ||
123 | static int | 116 | static int |
124 | cifs_reconnect(struct TCP_Server_Info *server) | 117 | cifs_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 | ||
1418 | static struct TCP_Server_Info * | ||
1419 | cifs_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 | |||
1545 | out_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 | |||
1420 | static struct cifsSesInfo * | 1555 | static struct cifsSesInfo * |
1421 | cifs_find_smb_ses(struct TCP_Server_Info *server, char *username) | 1556 | cifs_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 | ||
1595 | static int | 1730 | static int |
1596 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | 1731 | ipv4_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 | ||
1735 | static int | 1884 | static int |
1736 | ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket, | 1885 | ipv6_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) */ |
2378 | out: | 2435 | out: |
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 | |||
32 | static __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 | |||
67 | int 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 | 2131 | out: | |
2097 | return 0; | 2132 | *pagep = page; |
2133 | return rc; | ||
2098 | } | 2134 | } |
2099 | 2135 | ||
2100 | const struct address_space_operations cifs_addr_ops = { | 2136 | const 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 | ||
624 | static 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 */ |
625 | struct inode *cifs_iget(struct super_block *sb, unsigned long ino) | 666 | struct 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); |
1595 | out_truncate: | 1643 | out_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; |
1599 | out_sig: | 1647 | out_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 | ||
320 | static void | 320 | static void |
321 | smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw) | 321 | smbhash(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 | ||
365 | void | 366 | void |
366 | E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) | 367 | E_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 | ||
52 | void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); | 52 | void SMBencrypt(unsigned char *passwd, const unsigned char *c8, |
53 | unsigned char *p24); | ||
53 | void E_md4hash(const unsigned char *passwd, unsigned char *p16); | 54 | void E_md4hash(const unsigned char *passwd, unsigned char *p16); |
54 | static void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, | 55 | static void SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8, |
55 | unsigned char p24[24]); | 56 | unsigned char p24[24]); |
56 | void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); | 57 | void 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 */ |
63 | void | 64 | void |
64 | SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) | 65 | SMBencrypt(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. */ |
214 | static void | 215 | static void |
215 | SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, | 216 | SMBOWFencrypt(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; | |||
37 | extern struct kmem_cache *cifs_oplock_cachep; | 37 | extern struct kmem_cache *cifs_oplock_cachep; |
38 | 38 | ||
39 | static struct mid_q_entry * | 39 | static struct mid_q_entry * |
40 | AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) | 40 | AllocMidQEntry(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 | ||
664 | out: | 670 | out: |
@@ -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 | ||
849 | out: | 856 | out: |
@@ -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 | |||
1106 | out: | ||
1093 | DeleteMidQEntry(midQ); | 1107 | DeleteMidQEntry(midQ); |
1094 | if (rstart && rc == -EACCES) | 1108 | if (rstart && rc == -EACCES) |
1095 | return -ERESTARTSYS; | 1109 | return -ERESTARTSYS; |