diff options
| -rw-r--r-- | fs/cifs/AUTHORS | 2 | ||||
| -rw-r--r-- | fs/cifs/CHANGES | 9 | ||||
| -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 | 5 | ||||
| -rw-r--r-- | fs/cifs/cifsencrypt.c | 30 | ||||
| -rw-r--r-- | fs/cifs/cifsencrypt.h | 3 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 75 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 15 | ||||
| -rw-r--r-- | fs/cifs/cifspdu.h | 2 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 49 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 681 | ||||
| -rw-r--r-- | fs/cifs/dir.c | 9 | ||||
| -rw-r--r-- | fs/cifs/file.c | 25 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 58 | ||||
| -rw-r--r-- | fs/cifs/misc.c | 9 | ||||
| -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 |
22 files changed, 823 insertions, 611 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/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 1e7b87497f26..c4c306f7b06f 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
| @@ -20,7 +20,7 @@ | |||
| 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's 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/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..974c8f0e615e 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, NIP6_FMT, | ||
| 365 | NIP6(server->addr.sockAddr6.sin6_addr)); | ||
| 366 | break; | ||
| 367 | case AF_INET: | ||
| 368 | seq_printf(s, NIPQUAD_FMT, | ||
| 369 | NIPQUAD(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; |
| @@ -1029,6 +1046,7 @@ static int cifs_oplock_thread(void *dummyarg) | |||
| 1029 | return 0; | 1046 | return 0; |
| 1030 | } | 1047 | } |
| 1031 | 1048 | ||
| 1049 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 1032 | static int cifs_dnotify_thread(void *dummyarg) | 1050 | static int cifs_dnotify_thread(void *dummyarg) |
| 1033 | { | 1051 | { |
| 1034 | struct list_head *tmp; | 1052 | struct list_head *tmp; |
| @@ -1054,6 +1072,7 @@ static int cifs_dnotify_thread(void *dummyarg) | |||
| 1054 | 1072 | ||
| 1055 | return 0; | 1073 | return 0; |
| 1056 | } | 1074 | } |
| 1075 | #endif | ||
| 1057 | 1076 | ||
| 1058 | static int __init | 1077 | static int __init |
| 1059 | init_cifs(void) | 1078 | init_cifs(void) |
| @@ -1131,16 +1150,20 @@ init_cifs(void) | |||
| 1131 | goto out_unregister_dfs_key_type; | 1150 | goto out_unregister_dfs_key_type; |
| 1132 | } | 1151 | } |
| 1133 | 1152 | ||
| 1153 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 1134 | dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd"); | 1154 | dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd"); |
| 1135 | if (IS_ERR(dnotifyThread)) { | 1155 | if (IS_ERR(dnotifyThread)) { |
| 1136 | rc = PTR_ERR(dnotifyThread); | 1156 | rc = PTR_ERR(dnotifyThread); |
| 1137 | cERROR(1, ("error %d create dnotify thread", rc)); | 1157 | cERROR(1, ("error %d create dnotify thread", rc)); |
| 1138 | goto out_stop_oplock_thread; | 1158 | goto out_stop_oplock_thread; |
| 1139 | } | 1159 | } |
| 1160 | #endif | ||
| 1140 | 1161 | ||
| 1141 | return 0; | 1162 | return 0; |
| 1142 | 1163 | ||
| 1164 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 1143 | out_stop_oplock_thread: | 1165 | out_stop_oplock_thread: |
| 1166 | #endif | ||
| 1144 | kthread_stop(oplockThread); | 1167 | kthread_stop(oplockThread); |
| 1145 | out_unregister_dfs_key_type: | 1168 | out_unregister_dfs_key_type: |
| 1146 | #ifdef CONFIG_CIFS_DFS_UPCALL | 1169 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| @@ -1179,8 +1202,10 @@ exit_cifs(void) | |||
| 1179 | cifs_destroy_inodecache(); | 1202 | cifs_destroy_inodecache(); |
| 1180 | cifs_destroy_mids(); | 1203 | cifs_destroy_mids(); |
| 1181 | cifs_destroy_request_bufs(); | 1204 | cifs_destroy_request_bufs(); |
| 1182 | kthread_stop(oplockThread); | 1205 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 1183 | kthread_stop(dnotifyThread); | 1206 | kthread_stop(dnotifyThread); |
| 1207 | #endif | ||
| 1208 | kthread_stop(oplockThread); | ||
| 1184 | } | 1209 | } |
| 1185 | 1210 | ||
| 1186 | MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); | 1211 | MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 074de0b5064d..2ce04c73d74e 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -101,5 +101,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
| 101 | extern const struct export_operations cifs_export_ops; | 101 | extern const struct export_operations cifs_export_ops; |
| 102 | #endif /* EXPERIMENTAL */ | 102 | #endif /* EXPERIMENTAL */ |
| 103 | 103 | ||
| 104 | #define CIFS_VERSION "1.55" | 104 | #define CIFS_VERSION "1.56" |
| 105 | #endif /* _CIFSFS_H */ | 105 | #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 9d8b978137ad..06f6779988bf 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -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 6d51696dc762..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)) { |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 683dee4d2f76..d2ea95bef1c1 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 */ |
| @@ -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, NIP6_FMT, |
| 2274 | NIP6(srvTcp->addr.sockAddr6.sin6_addr)); | ||
| 2275 | else | ||
| 2276 | sprintf(pSesInfo->serverName, NIPQUAD_FMT, | ||
| 2277 | NIPQUAD(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 2f02c52db666..838d9c720a5c 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -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/file.c b/fs/cifs/file.c index f0a81e631ae6..b1e1fc6a6e6a 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); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8b7305e73d7e..f247da9f4edc 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 | */ |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 8a82d076450b..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 | ||
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; |
