aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/CHANGES7
-rw-r--r--fs/cifs/README12
-rw-r--r--fs/cifs/cifs_debug.c51
-rw-r--r--fs/cifs/cifsacl.h36
-rw-r--r--fs/cifs/cifsencrypt.c55
-rw-r--r--fs/cifs/cifsfs.c11
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h16
-rw-r--r--fs/cifs/cifspdu.h8
-rw-r--r--fs/cifs/cifsproto.h20
-rw-r--r--fs/cifs/cifssmb.c98
-rw-r--r--fs/cifs/connect.c55
-rw-r--r--fs/cifs/dir.c8
-rw-r--r--fs/cifs/file.c58
-rw-r--r--fs/cifs/inode.c9
-rw-r--r--fs/cifs/misc.c17
-rw-r--r--fs/cifs/transport.c39
17 files changed, 359 insertions, 143 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 943ef9b82244..1d2137561c55 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,8 @@
1Version 1.40
2------------
3Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
4of readpages by eliminating one extra memcpy.
5
1Version 1.39 6Version 1.39
2------------ 7------------
3Defer close of a file handle slightly if pending writes depend on that handle 8Defer close of a file handle slightly if pending writes depend on that handle
@@ -7,6 +12,8 @@ Fix SFU style symlinks and mknod needed for servers which do not support the
7CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative 12CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative
8dentries so files that the client sees as deleted but that later get created 13dentries so files that the client sees as deleted but that later get created
9on the server will be recognized. Add client side permission check on setattr. 14on the server will be recognized. Add client side permission check on setattr.
15Timeout stuck requests better (where server has never responded or sent corrupt
16responses)
10 17
11Version 1.38 18Version 1.38
12------------ 19------------
diff --git a/fs/cifs/README b/fs/cifs/README
index e5d09a2fc7a5..b0070d1b149d 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -436,7 +436,17 @@ A partial list of the supported mount options follows:
436 SFU does). In the future the bottom 9 bits of the mode 436 SFU does). In the future the bottom 9 bits of the mode
437 mode also will be emulated using queries of the security 437 mode also will be emulated using queries of the security
438 descriptor (ACL). 438 descriptor (ACL).
439 439sec Security mode. Allowed values are:
440 none attempt to connection as a null user (no name)
441 krb5 Use Kerberos version 5 authentication
442 krb5i Use Kerberos authentication and packet signing
443 ntlm Use NTLM password hashing (default)
444 ntlmi Use NTLM password hashing with signing (if
445 /proc/fs/cifs/PacketSigningEnabled on or if
446 server requires signing also can be the default)
447 ntlmv2 Use NTLMv2 password hashing
448 ntlmv2i Use NTLMv2 password hashing with packet signing
449
440The mount.cifs mount helper also accepts a few mount options before -o 450The mount.cifs mount helper also accepts a few mount options before -o
441including: 451including:
442 452
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 22a444a3fe4c..f4124a32bef8 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -219,6 +219,10 @@ cifs_stats_write(struct file *file, const char __user *buffer,
219 219
220 if (c == '1' || c == 'y' || c == 'Y' || c == '0') { 220 if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
221 read_lock(&GlobalSMBSeslock); 221 read_lock(&GlobalSMBSeslock);
222#ifdef CONFIG_CIFS_STATS2
223 atomic_set(&totBufAllocCount, 0);
224 atomic_set(&totSmBufAllocCount, 0);
225#endif /* CONFIG_CIFS_STATS2 */
222 list_for_each(tmp, &GlobalTreeConnectionList) { 226 list_for_each(tmp, &GlobalTreeConnectionList) {
223 tcon = list_entry(tmp, struct cifsTconInfo, 227 tcon = list_entry(tmp, struct cifsTconInfo,
224 cifsConnectionList); 228 cifsConnectionList);
@@ -276,6 +280,14 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
276 smBufAllocCount.counter,cifs_min_small); 280 smBufAllocCount.counter,cifs_min_small);
277 length += item_length; 281 length += item_length;
278 buf += item_length; 282 buf += item_length;
283#ifdef CONFIG_CIFS_STATS2
284 item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
285 atomic_read(&totBufAllocCount),
286 atomic_read(&totSmBufAllocCount));
287 length += item_length;
288 buf += item_length;
289#endif /* CONFIG_CIFS_STATS2 */
290
279 item_length = 291 item_length =
280 sprintf(buf,"Operations (MIDs): %d\n", 292 sprintf(buf,"Operations (MIDs): %d\n",
281 midCount.counter); 293 midCount.counter);
@@ -389,8 +401,8 @@ static read_proc_t ntlmv2_enabled_read;
389static write_proc_t ntlmv2_enabled_write; 401static write_proc_t ntlmv2_enabled_write;
390static read_proc_t packet_signing_enabled_read; 402static read_proc_t packet_signing_enabled_read;
391static write_proc_t packet_signing_enabled_write; 403static write_proc_t packet_signing_enabled_write;
392static read_proc_t quotaEnabled_read; 404static read_proc_t experimEnabled_read;
393static write_proc_t quotaEnabled_write; 405static write_proc_t experimEnabled_write;
394static read_proc_t linuxExtensionsEnabled_read; 406static read_proc_t linuxExtensionsEnabled_read;
395static write_proc_t linuxExtensionsEnabled_write; 407static write_proc_t linuxExtensionsEnabled_write;
396 408
@@ -430,9 +442,9 @@ cifs_proc_init(void)
430 pde->write_proc = oplockEnabled_write; 442 pde->write_proc = oplockEnabled_write;
431 443
432 pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs, 444 pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
433 quotaEnabled_read, NULL); 445 experimEnabled_read, NULL);
434 if (pde) 446 if (pde)
435 pde->write_proc = quotaEnabled_write; 447 pde->write_proc = experimEnabled_write;
436 448
437 pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs, 449 pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
438 linuxExtensionsEnabled_read, NULL); 450 linuxExtensionsEnabled_read, NULL);
@@ -574,14 +586,13 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
574} 586}
575 587
576static int 588static int
577quotaEnabled_read(char *page, char **start, off_t off, 589experimEnabled_read(char *page, char **start, off_t off,
578 int count, int *eof, void *data) 590 int count, int *eof, void *data)
579{ 591{
580 int len; 592 int len;
581 593
582 len = sprintf(page, "%d\n", experimEnabled); 594 len = sprintf(page, "%d\n", experimEnabled);
583/* could also check if quotas are enabled in kernel 595
584 as a whole first */
585 len -= off; 596 len -= off;
586 *start = page + off; 597 *start = page + off;
587 598
@@ -596,21 +607,23 @@ quotaEnabled_read(char *page, char **start, off_t off,
596 return len; 607 return len;
597} 608}
598static int 609static int
599quotaEnabled_write(struct file *file, const char __user *buffer, 610experimEnabled_write(struct file *file, const char __user *buffer,
600 unsigned long count, void *data) 611 unsigned long count, void *data)
601{ 612{
602 char c; 613 char c;
603 int rc; 614 int rc;
604 615
605 rc = get_user(c, buffer); 616 rc = get_user(c, buffer);
606 if (rc) 617 if (rc)
607 return rc; 618 return rc;
608 if (c == '0' || c == 'n' || c == 'N') 619 if (c == '0' || c == 'n' || c == 'N')
609 experimEnabled = 0; 620 experimEnabled = 0;
610 else if (c == '1' || c == 'y' || c == 'Y') 621 else if (c == '1' || c == 'y' || c == 'Y')
611 experimEnabled = 1; 622 experimEnabled = 1;
623 else if (c == '2')
624 experimEnabled = 2;
612 625
613 return count; 626 return count;
614} 627}
615 628
616static int 629static int
@@ -620,8 +633,6 @@ linuxExtensionsEnabled_read(char *page, char **start, off_t off,
620 int len; 633 int len;
621 634
622 len = sprintf(page, "%d\n", linuxExtEnabled); 635 len = sprintf(page, "%d\n", linuxExtEnabled);
623/* could also check if quotas are enabled in kernel
624 as a whole first */
625 len -= off; 636 len -= off;
626 *start = page + off; 637 *start = page + off;
627 638
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
new file mode 100644
index 000000000000..4cfcdf2e6304
--- /dev/null
+++ b/fs/cifs/cifsacl.h
@@ -0,0 +1,36 @@
1/*
2 * fs/cifs/cifsacl.h
3 *
4 * Copyright (c) International Business Machines Corp., 2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#ifndef _CIFSACL_H
23#define _CIFSACL_H
24
25struct cifs_sid {
26 __u8 revision; /* revision level */
27 __u8 num_subauths;
28 __u8 authority[6];
29 __u8 sub_auth[4];
30 /* next sub_auth if any ... */
31} __attribute__((packed));
32
33/* everyone */
34const cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
35/* group users */
36const cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index fe2bb7c4c912..a2c24858d40f 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsencrypt.c 2 * fs/cifs/cifsencrypt.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2003 4 * Copyright (C) International Business Machines Corp., 2005
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
@@ -82,6 +82,59 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
82 return rc; 82 return rc;
83} 83}
84 84
85static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
86 const char * key, char * signature)
87{
88 struct MD5Context context;
89
90 if((iov == NULL) || (signature == NULL))
91 return -EINVAL;
92
93 MD5Init(&context);
94 MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
95
96/* MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
97
98 MD5Final(signature,&context);
99
100 return -EOPNOTSUPP;
101/* return 0; */
102}
103
104
105int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
106 __u32 * pexpected_response_sequence_number)
107{
108 int rc = 0;
109 char smb_signature[20];
110 struct smb_hdr * cifs_pdu = iov[0].iov_base;
111
112 if((cifs_pdu == NULL) || (server == NULL))
113 return -EINVAL;
114
115 if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
116 return rc;
117
118 spin_lock(&GlobalMid_Lock);
119 cifs_pdu->Signature.Sequence.SequenceNumber =
120 cpu_to_le32(server->sequence_number);
121 cifs_pdu->Signature.Sequence.Reserved = 0;
122
123 *pexpected_response_sequence_number = server->sequence_number++;
124 server->sequence_number++;
125 spin_unlock(&GlobalMid_Lock);
126
127 rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key,
128 smb_signature);
129 if(rc)
130 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
131 else
132 memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
133
134 return rc;
135
136}
137
85int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key, 138int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
86 __u32 expected_sequence_number) 139 __u32 expected_sequence_number)
87{ 140{
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 2a13a2bac8f1..582d66ca6da5 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -733,7 +733,7 @@ cifs_init_request_bufs(void)
733 kmem_cache_destroy(cifs_req_cachep); 733 kmem_cache_destroy(cifs_req_cachep);
734 return -ENOMEM; 734 return -ENOMEM;
735 } 735 }
736 /* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and 736 /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
737 almost all handle based requests (but not write response, nor is it 737 almost all handle based requests (but not write response, nor is it
738 sufficient for path based requests). A smaller size would have 738 sufficient for path based requests). A smaller size would have
739 been more efficient (compacting multiple slab items on one 4k page) 739 been more efficient (compacting multiple slab items on one 4k page)
@@ -742,7 +742,8 @@ cifs_init_request_bufs(void)
742 efficient to alloc 1 per page off the slab compared to 17K (5page) 742 efficient to alloc 1 per page off the slab compared to 17K (5page)
743 alloc of large cifs buffers even when page debugging is on */ 743 alloc of large cifs buffers even when page debugging is on */
744 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", 744 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
745 MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); 745 MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
746 NULL, NULL);
746 if (cifs_sm_req_cachep == NULL) { 747 if (cifs_sm_req_cachep == NULL) {
747 mempool_destroy(cifs_req_poolp); 748 mempool_destroy(cifs_req_poolp);
748 kmem_cache_destroy(cifs_req_cachep); 749 kmem_cache_destroy(cifs_req_cachep);
@@ -954,6 +955,12 @@ init_cifs(void)
954 atomic_set(&tconInfoReconnectCount, 0); 955 atomic_set(&tconInfoReconnectCount, 0);
955 956
956 atomic_set(&bufAllocCount, 0); 957 atomic_set(&bufAllocCount, 0);
958 atomic_set(&smBufAllocCount, 0);
959#ifdef CONFIG_CIFS_STATS2
960 atomic_set(&totBufAllocCount, 0);
961 atomic_set(&totSmBufAllocCount, 0);
962#endif /* CONFIG_CIFS_STATS2 */
963
957 atomic_set(&midCount, 0); 964 atomic_set(&midCount, 0);
958 GlobalCurrentXid = 0; 965 GlobalCurrentXid = 0;
959 GlobalTotalActiveXid = 0; 966 GlobalTotalActiveXid = 0;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 9ec40e0e54fc..821a8eb22559 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
99extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 99extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
100extern int cifs_ioctl (struct inode * inode, struct file * filep, 100extern int cifs_ioctl (struct inode * inode, struct file * filep,
101 unsigned int command, unsigned long arg); 101 unsigned int command, unsigned long arg);
102#define CIFS_VERSION "1.39" 102#define CIFS_VERSION "1.40"
103#endif /* _CIFSFS_H */ 103#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1ba08f8c5bc4..862e403ff211 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -285,6 +285,7 @@ struct cifs_search_info {
285 unsigned endOfSearch:1; 285 unsigned endOfSearch:1;
286 unsigned emptyDir:1; 286 unsigned emptyDir:1;
287 unsigned unicode:1; 287 unsigned unicode:1;
288 unsigned smallBuf:1; /* so we know which buf_release function to call */
288}; 289};
289 290
290struct cifsFileInfo { 291struct cifsFileInfo {
@@ -420,7 +421,12 @@ struct dir_notify_req {
420#define MID_RESPONSE_RECEIVED 4 421#define MID_RESPONSE_RECEIVED 4
421#define MID_RETRY_NEEDED 8 /* session closed while this request out */ 422#define MID_RETRY_NEEDED 8 /* session closed while this request out */
422#define MID_NO_RESP_NEEDED 0x10 423#define MID_NO_RESP_NEEDED 0x10
423#define MID_SMALL_BUFFER 0x20 /* 112 byte response buffer instead of 4K */ 424
425/* Types of response buffer returned from SendReceive2 */
426#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
427#define CIFS_SMALL_BUFFER 1
428#define CIFS_LARGE_BUFFER 2
429#define CIFS_IOVEC 4 /* array of response buffers */
424 430
425/* 431/*
426 ***************************************************************** 432 *****************************************************************
@@ -505,8 +511,12 @@ GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
505GLOBAL_EXTERN atomic_t tconInfoReconnectCount; 511GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
506 512
507/* Various Debug counters to remove someday (BB) */ 513/* Various Debug counters to remove someday (BB) */
508GLOBAL_EXTERN atomic_t bufAllocCount; 514GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */
509GLOBAL_EXTERN atomic_t smBufAllocCount; 515#ifdef CONFIG_CIFS_STATS2
516GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */
517GLOBAL_EXTERN atomic_t totSmBufAllocCount;
518#endif
519GLOBAL_EXTERN atomic_t smBufAllocCount;
510GLOBAL_EXTERN atomic_t midCount; 520GLOBAL_EXTERN atomic_t midCount;
511 521
512/* Misc globals */ 522/* Misc globals */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 33e1859fd2f6..3c09fb9cc569 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifspdu.h 2 * fs/cifs/cifspdu.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2002 4 * Copyright (c) International Business Machines Corp., 2002,2005
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
@@ -80,7 +80,11 @@
80#define NT_TRANSACT_GET_USER_QUOTA 0x07 80#define NT_TRANSACT_GET_USER_QUOTA 0x07
81#define NT_TRANSACT_SET_USER_QUOTA 0x08 81#define NT_TRANSACT_SET_USER_QUOTA 0x08
82 82
83#define MAX_CIFS_HDR_SIZE 256 /* is future chained NTCreateXReadX bigger? */ 83#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
84/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
85/* among the requests (NTCreateX response is bigger with wct of 34) */
86#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
87#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */
84 88
85/* internal cifs vfs structures */ 89/* internal cifs vfs structures */
86/***************************************************************** 90/*****************************************************************
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1b73f4f4c5ce..8ef0ce47f5b6 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -48,8 +48,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
48 struct smb_hdr * /* out */ , 48 struct smb_hdr * /* out */ ,
49 int * /* bytes returned */ , const int long_op); 49 int * /* bytes returned */ , const int long_op);
50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
51 struct kvec *, int /* nvec */, 51 struct kvec *, int /* nvec to send */,
52 int * /* bytes returned */ , const int long_op); 52 int * /* type of buf returned */ , const int long_op);
53extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 53extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
54extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 54extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
55extern int is_valid_oplock_break(struct smb_hdr *smb); 55extern int is_valid_oplock_break(struct smb_hdr *smb);
@@ -93,11 +93,12 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
93 const struct nls_table *); 93 const struct nls_table *);
94 94
95extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, 95extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
96 const char *searchName, const struct nls_table *nls_codepage, 96 const char *searchName, const struct nls_table *nls_codepage,
97 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep); 97 __u16 *searchHandle, struct cifs_search_info * psrch_inf,
98 int map, const char dirsep);
98 99
99extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, 100extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
100 __u16 searchHandle, struct cifs_search_info * psrch_inf); 101 __u16 searchHandle, struct cifs_search_info * psrch_inf);
101 102
102extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, 103extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
103 const __u16 search_handle); 104 const __u16 search_handle);
@@ -230,19 +231,18 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
230 const int smb_file_id); 231 const int smb_file_id);
231 232
232extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 233extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
233 const int netfid, unsigned int count, 234 const int netfid, unsigned int count,
234 const __u64 lseek, unsigned int *nbytes, char **buf); 235 const __u64 lseek, unsigned int *nbytes, char **buf,
236 int * return_buf_type);
235extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, 237extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
236 const int netfid, const unsigned int count, 238 const int netfid, const unsigned int count,
237 const __u64 lseek, unsigned int *nbytes, 239 const __u64 lseek, unsigned int *nbytes,
238 const char *buf, const char __user *ubuf, 240 const char *buf, const char __user *ubuf,
239 const int long_op); 241 const int long_op);
240#ifdef CONFIG_CIFS_EXPERIMENTAL
241extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 242extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
242 const int netfid, const unsigned int count, 243 const int netfid, const unsigned int count,
243 const __u64 offset, unsigned int *nbytes, 244 const __u64 offset, unsigned int *nbytes,
244 struct kvec *iov, const int nvec, const int long_op); 245 struct kvec *iov, const int nvec, const int long_op);
245#endif /* CONFIG_CIFS_EXPERIMENTAL */
246extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 246extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
247 const unsigned char *searchName, __u64 * inode_number, 247 const unsigned char *searchName, __u64 * inode_number,
248 const struct nls_table *nls_codepage, 248 const struct nls_table *nls_codepage,
@@ -269,6 +269,8 @@ extern void tconInfoFree(struct cifsTconInfo *);
269extern int cifs_reconnect(struct TCP_Server_Info *server); 269extern int cifs_reconnect(struct TCP_Server_Info *server);
270 270
271extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); 271extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
272extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
273 __u32 *);
272extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, 274extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
273 __u32 expected_sequence_number); 275 __u32 expected_sequence_number);
274extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 276extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6867e556d37e..1620991cd4d2 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -958,21 +958,19 @@ openRetry:
958 return rc; 958 return rc;
959} 959}
960 960
961/* If no buffer passed in, then caller wants to do the copy
962 as in the case of readpages so the SMB buffer must be
963 freed by the caller */
964
965int 961int
966CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 962CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
967 const int netfid, const unsigned int count, 963 const int netfid, const unsigned int count,
968 const __u64 lseek, unsigned int *nbytes, char **buf) 964 const __u64 lseek, unsigned int *nbytes, char **buf,
965 int * pbuf_type)
969{ 966{
970 int rc = -EACCES; 967 int rc = -EACCES;
971 READ_REQ *pSMB = NULL; 968 READ_REQ *pSMB = NULL;
972 READ_RSP *pSMBr = NULL; 969 READ_RSP *pSMBr = NULL;
973 char *pReadData = NULL; 970 char *pReadData = NULL;
974 int bytes_returned;
975 int wct; 971 int wct;
972 int resp_buf_type = 0;
973 struct kvec iov[1];
976 974
977 cFYI(1,("Reading %d bytes on fid %d",count,netfid)); 975 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
978 if(tcon->ses->capabilities & CAP_LARGE_FILES) 976 if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -981,8 +979,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
981 wct = 10; /* old style read */ 979 wct = 10; /* old style read */
982 980
983 *nbytes = 0; 981 *nbytes = 0;
984 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB, 982 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
985 (void **) &pSMBr);
986 if (rc) 983 if (rc)
987 return rc; 984 return rc;
988 985
@@ -990,13 +987,13 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
990 if (tcon->ses->server == NULL) 987 if (tcon->ses->server == NULL)
991 return -ECONNABORTED; 988 return -ECONNABORTED;
992 989
993 pSMB->AndXCommand = 0xFF; /* none */ 990 pSMB->AndXCommand = 0xFF; /* none */
994 pSMB->Fid = netfid; 991 pSMB->Fid = netfid;
995 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 992 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
996 if(wct == 12) 993 if(wct == 12)
997 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 994 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
998 else if((lseek >> 32) > 0) /* can not handle this big offset for old */ 995 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
999 return -EIO; 996 return -EIO;
1000 997
1001 pSMB->Remaining = 0; 998 pSMB->Remaining = 0;
1002 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 999 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
@@ -1005,14 +1002,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1005 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */ 1002 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1006 else { 1003 else {
1007 /* old style read */ 1004 /* old style read */
1008 struct smb_com_readx_req * pSMBW = 1005 struct smb_com_readx_req * pSMBW =
1009 (struct smb_com_readx_req *)pSMB; 1006 (struct smb_com_readx_req *)pSMB;
1010 pSMBW->ByteCount = 0; 1007 pSMBW->ByteCount = 0;
1011 } 1008 }
1012 1009
1013 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1010 iov[0].iov_base = (char *)pSMB;
1014 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1011 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1012 rc = SendReceive2(xid, tcon->ses, iov,
1013 1 /* num iovecs */,
1014 &resp_buf_type, 0);
1015 cifs_stats_inc(&tcon->num_reads); 1015 cifs_stats_inc(&tcon->num_reads);
1016 pSMBr = (READ_RSP *)iov[0].iov_base;
1016 if (rc) { 1017 if (rc) {
1017 cERROR(1, ("Send error in read = %d", rc)); 1018 cERROR(1, ("Send error in read = %d", rc));
1018 } else { 1019 } else {
@@ -1022,33 +1023,43 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1022 *nbytes = data_length; 1023 *nbytes = data_length;
1023 1024
1024 /*check that DataLength would not go beyond end of SMB */ 1025 /*check that DataLength would not go beyond end of SMB */
1025 if ((data_length > CIFSMaxBufSize) 1026 if ((data_length > CIFSMaxBufSize)
1026 || (data_length > count)) { 1027 || (data_length > count)) {
1027 cFYI(1,("bad length %d for count %d",data_length,count)); 1028 cFYI(1,("bad length %d for count %d",data_length,count));
1028 rc = -EIO; 1029 rc = -EIO;
1029 *nbytes = 0; 1030 *nbytes = 0;
1030 } else { 1031 } else {
1031 pReadData = 1032 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1032 (char *) (&pSMBr->hdr.Protocol) +
1033 le16_to_cpu(pSMBr->DataOffset); 1033 le16_to_cpu(pSMBr->DataOffset);
1034/* if(rc = copy_to_user(buf, pReadData, data_length)) { 1034/* if(rc = copy_to_user(buf, pReadData, data_length)) {
1035 cERROR(1,("Faulting on read rc = %d",rc)); 1035 cERROR(1,("Faulting on read rc = %d",rc));
1036 rc = -EFAULT; 1036 rc = -EFAULT;
1037 }*/ /* can not use copy_to_user when using page cache*/ 1037 }*/ /* can not use copy_to_user when using page cache*/
1038 if(*buf) 1038 if(*buf)
1039 memcpy(*buf,pReadData,data_length); 1039 memcpy(*buf,pReadData,data_length);
1040 } 1040 }
1041 } 1041 }
1042 if(*buf)
1043 cifs_buf_release(pSMB);
1044 else
1045 *buf = (char *)pSMB;
1046 1042
1047 /* Note: On -EAGAIN error only caller can retry on handle based calls 1043 cifs_small_buf_release(pSMB);
1044 if(*buf) {
1045 if(resp_buf_type == CIFS_SMALL_BUFFER)
1046 cifs_small_buf_release(iov[0].iov_base);
1047 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1048 cifs_buf_release(iov[0].iov_base);
1049 } else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
1050 *buf = iov[0].iov_base;
1051 if(resp_buf_type == CIFS_SMALL_BUFFER)
1052 *pbuf_type = CIFS_SMALL_BUFFER;
1053 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1054 *pbuf_type = CIFS_LARGE_BUFFER;
1055 }
1056
1057 /* Note: On -EAGAIN error only caller can retry on handle based calls
1048 since file handle passed in no longer valid */ 1058 since file handle passed in no longer valid */
1049 return rc; 1059 return rc;
1050} 1060}
1051 1061
1062
1052int 1063int
1053CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, 1064CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1054 const int netfid, const unsigned int count, 1065 const int netfid, const unsigned int count,
@@ -1155,7 +1166,6 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1155 return rc; 1166 return rc;
1156} 1167}
1157 1168
1158#ifdef CONFIG_CIFS_EXPERIMENTAL
1159int 1169int
1160CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1170CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1161 const int netfid, const unsigned int count, 1171 const int netfid, const unsigned int count,
@@ -1164,10 +1174,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1164{ 1174{
1165 int rc = -EACCES; 1175 int rc = -EACCES;
1166 WRITE_REQ *pSMB = NULL; 1176 WRITE_REQ *pSMB = NULL;
1167 int bytes_returned, wct; 1177 int wct;
1168 int smb_hdr_len; 1178 int smb_hdr_len;
1179 int resp_buf_type = 0;
1169 1180
1170 /* BB removeme BB */
1171 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count)); 1181 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1172 1182
1173 if(tcon->ses->capabilities & CAP_LARGE_FILES) 1183 if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -1210,22 +1220,34 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1210 pSMBW->ByteCount = cpu_to_le16(count + 5); 1220 pSMBW->ByteCount = cpu_to_le16(count + 5);
1211 } 1221 }
1212 iov[0].iov_base = pSMB; 1222 iov[0].iov_base = pSMB;
1213 iov[0].iov_len = smb_hdr_len + 4; 1223 if(wct == 14)
1224 iov[0].iov_len = smb_hdr_len + 4;
1225 else /* wct == 12 pad bigger by four bytes */
1226 iov[0].iov_len = smb_hdr_len + 8;
1227
1214 1228
1215 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned, 1229 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1216 long_op); 1230 long_op);
1217 cifs_stats_inc(&tcon->num_writes); 1231 cifs_stats_inc(&tcon->num_writes);
1218 if (rc) { 1232 if (rc) {
1219 cFYI(1, ("Send error Write2 = %d", rc)); 1233 cFYI(1, ("Send error Write2 = %d", rc));
1220 *nbytes = 0; 1234 *nbytes = 0;
1235 } else if(resp_buf_type == 0) {
1236 /* presumably this can not happen, but best to be safe */
1237 rc = -EIO;
1238 *nbytes = 0;
1221 } else { 1239 } else {
1222 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB; 1240 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1223 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1241 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1224 *nbytes = (*nbytes) << 16; 1242 *nbytes = (*nbytes) << 16;
1225 *nbytes += le16_to_cpu(pSMBr->Count); 1243 *nbytes += le16_to_cpu(pSMBr->Count);
1226 } 1244 }
1227 1245
1228 cifs_small_buf_release(pSMB); 1246 cifs_small_buf_release(pSMB);
1247 if(resp_buf_type == CIFS_SMALL_BUFFER)
1248 cifs_small_buf_release(iov[0].iov_base);
1249 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1250 cifs_buf_release(iov[0].iov_base);
1229 1251
1230 /* Note: On -EAGAIN error only caller can retry on handle based calls 1252 /* Note: On -EAGAIN error only caller can retry on handle based calls
1231 since file handle passed in no longer valid */ 1253 since file handle passed in no longer valid */
@@ -1234,8 +1256,6 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1234} 1256}
1235 1257
1236 1258
1237#endif /* CIFS_EXPERIMENTAL */
1238
1239int 1259int
1240CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 1260CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1241 const __u16 smb_file_id, const __u64 len, 1261 const __u16 smb_file_id, const __u64 len,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c467de857610..45c9d726c002 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -82,6 +82,12 @@ struct smb_vol {
82 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 82 unsigned remap:1; /* set to remap seven reserved chars in filenames */
83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ 83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
84 unsigned sfu_emul:1; 84 unsigned sfu_emul:1;
85 unsigned krb5:1;
86 unsigned ntlm:1;
87 unsigned ntlmv2:1;
88 unsigned nullauth:1; /* attempt to authenticate with null user */
89 unsigned sign:1;
90 unsigned seal:1; /* encrypt */
85 unsigned nocase; /* request case insensitive filenames */ 91 unsigned nocase; /* request case insensitive filenames */
86 unsigned nobrl; /* disable sending byte range locks to srv */ 92 unsigned nobrl; /* disable sending byte range locks to srv */
87 unsigned int rsize; 93 unsigned int rsize;
@@ -508,7 +514,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
508 /* else length ok */ 514 /* else length ok */
509 reconnect = 0; 515 reconnect = 0;
510 516
511 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { 517 if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
512 isLargeBuf = TRUE; 518 isLargeBuf = TRUE;
513 memcpy(bigbuf, smallbuf, 4); 519 memcpy(bigbuf, smallbuf, 4);
514 smb_buffer = bigbuf; 520 smb_buffer = bigbuf;
@@ -777,7 +783,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
777 783
778 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 784 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
779 vol->rw = TRUE; 785 vol->rw = TRUE;
780 786 vol->ntlm = TRUE;
781 /* default is always to request posix paths. */ 787 /* default is always to request posix paths. */
782 vol->posix_paths = 1; 788 vol->posix_paths = 1;
783 789
@@ -903,6 +909,39 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
903 printk(KERN_WARNING "CIFS: ip address too long\n"); 909 printk(KERN_WARNING "CIFS: ip address too long\n");
904 return 1; 910 return 1;
905 } 911 }
912 } else if (strnicmp(data, "sec", 3) == 0) {
913 if (!value || !*value) {
914 cERROR(1,("no security value specified"));
915 continue;
916 } else if (strnicmp(value, "krb5i", 5) == 0) {
917 vol->sign = 1;
918 vol->krb5 = 1;
919 } else if (strnicmp(value, "krb5p", 5) == 0) {
920 /* vol->seal = 1;
921 vol->krb5 = 1; */
922 cERROR(1,("Krb5 cifs privacy not supported"));
923 return 1;
924 } else if (strnicmp(value, "krb5", 4) == 0) {
925 vol->krb5 = 1;
926 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
927 vol->ntlmv2 = 1;
928 vol->sign = 1;
929 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
930 vol->ntlmv2 = 1;
931 } else if (strnicmp(value, "ntlmi", 5) == 0) {
932 vol->ntlm = 1;
933 vol->sign = 1;
934 } else if (strnicmp(value, "ntlm", 4) == 0) {
935 /* ntlm is default so can be turned off too */
936 vol->ntlm = 1;
937 } else if (strnicmp(value, "nontlm", 6) == 0) {
938 vol->ntlm = 0;
939 } else if (strnicmp(value, "none", 4) == 0) {
940 vol->nullauth = 1;
941 } else {
942 cERROR(1,("bad security option: %s", value));
943 return 1;
944 }
906 } else if ((strnicmp(data, "unc", 3) == 0) 945 } else if ((strnicmp(data, "unc", 3) == 0)
907 || (strnicmp(data, "target", 6) == 0) 946 || (strnicmp(data, "target", 6) == 0)
908 || (strnicmp(data, "path", 4) == 0)) { 947 || (strnicmp(data, "path", 4) == 0)) {
@@ -1546,7 +1585,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1546 cFYI(1, ("Username: %s ", volume_info.username)); 1585 cFYI(1, ("Username: %s ", volume_info.username));
1547 1586
1548 } else { 1587 } else {
1549 cifserror("No username specified "); 1588 cifserror("No username specified");
1550 /* In userspace mount helper we can get user name from alternate 1589 /* In userspace mount helper we can get user name from alternate
1551 locations such as env variables and files on disk */ 1590 locations such as env variables and files on disk */
1552 kfree(volume_info.UNC); 1591 kfree(volume_info.UNC);
@@ -1587,7 +1626,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1587 return -EINVAL; 1626 return -EINVAL;
1588 } else /* which servers DFS root would we conect to */ { 1627 } else /* which servers DFS root would we conect to */ {
1589 cERROR(1, 1628 cERROR(1,
1590 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); 1629 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
1591 kfree(volume_info.UNC); 1630 kfree(volume_info.UNC);
1592 kfree(volume_info.password); 1631 kfree(volume_info.password);
1593 FreeXid(xid); 1632 FreeXid(xid);
@@ -1626,7 +1665,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1626 1665
1627 1666
1628 if (srvTcp) { 1667 if (srvTcp) {
1629 cFYI(1, ("Existing tcp session with server found ")); 1668 cFYI(1, ("Existing tcp session with server found"));
1630 } else { /* create socket */ 1669 } else { /* create socket */
1631 if(volume_info.port) 1670 if(volume_info.port)
1632 sin_server.sin_port = htons(volume_info.port); 1671 sin_server.sin_port = htons(volume_info.port);
@@ -1689,11 +1728,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1689 1728
1690 if (existingCifsSes) { 1729 if (existingCifsSes) {
1691 pSesInfo = existingCifsSes; 1730 pSesInfo = existingCifsSes;
1692 cFYI(1, ("Existing smb sess found ")); 1731 cFYI(1, ("Existing smb sess found"));
1693 kfree(volume_info.password); 1732 kfree(volume_info.password);
1694 /* volume_info.UNC freed at end of function */ 1733 /* volume_info.UNC freed at end of function */
1695 } else if (!rc) { 1734 } else if (!rc) {
1696 cFYI(1, ("Existing smb sess not found ")); 1735 cFYI(1, ("Existing smb sess not found"));
1697 pSesInfo = sesInfoAlloc(); 1736 pSesInfo = sesInfoAlloc();
1698 if (pSesInfo == NULL) 1737 if (pSesInfo == NULL)
1699 rc = -ENOMEM; 1738 rc = -ENOMEM;
@@ -1777,7 +1816,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1777 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, 1816 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1778 volume_info.username); 1817 volume_info.username);
1779 if (tcon) { 1818 if (tcon) {
1780 cFYI(1, ("Found match on UNC path ")); 1819 cFYI(1, ("Found match on UNC path"));
1781 /* we can have only one retry value for a connection 1820 /* we can have only one retry value for a connection
1782 to a share so for resources mounted more than once 1821 to a share so for resources mounted more than once
1783 to the same server share the last value passed in 1822 to the same server share the last value passed in
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 32cc96cafa3e..fed55e3c53df 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * vfs operations that deal with dentries 4 * vfs operations that deal with dentries
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2002,2003 6 * Copyright (C) International Business Machines Corp., 2002,2005
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * 8 *
9 * This library is free software; you can redistribute it and/or modify 9 * This library is free software; you can redistribute it and/or modify
@@ -200,8 +200,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
200 (oplock & CIFS_CREATE_ACTION)) 200 (oplock & CIFS_CREATE_ACTION))
201 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 201 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
202 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, 202 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
203 (__u64)current->euid, 203 (__u64)current->fsuid,
204 (__u64)current->egid, 204 (__u64)current->fsgid,
205 0 /* dev */, 205 0 /* dev */,
206 cifs_sb->local_nls, 206 cifs_sb->local_nls,
207 cifs_sb->mnt_cifs_flags & 207 cifs_sb->mnt_cifs_flags &
@@ -325,7 +325,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
325 else if (pTcon->ses->capabilities & CAP_UNIX) { 325 else if (pTcon->ses->capabilities & CAP_UNIX) {
326 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 326 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
327 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 327 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
328 mode,(__u64)current->euid,(__u64)current->egid, 328 mode,(__u64)current->fsuid,(__u64)current->fsgid,
329 device_number, cifs_sb->local_nls, 329 device_number, cifs_sb->local_nls,
330 cifs_sb->mnt_cifs_flags & 330 cifs_sb->mnt_cifs_flags &
331 CIFS_MOUNT_MAP_SPECIAL_CHR); 331 CIFS_MOUNT_MAP_SPECIAL_CHR);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 14a1c72ced92..c249b628fd1c 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -555,13 +555,13 @@ int cifs_closedir(struct inode *inode, struct file *file)
555 } 555 }
556 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; 556 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
557 if (ptmp) { 557 if (ptmp) {
558 /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir")); 558 cFYI(1, ("closedir free smb buf in srch struct"));
559 pCFileStruct->srch_inf.ntwrk_buf_start = NULL; 559 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
560 cifs_buf_release(ptmp); 560 cifs_buf_release(ptmp);
561 } 561 }
562 ptmp = pCFileStruct->search_resume_name; 562 ptmp = pCFileStruct->search_resume_name;
563 if (ptmp) { 563 if (ptmp) {
564 /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir")); 564 cFYI(1, ("closedir free resume name"));
565 pCFileStruct->search_resume_name = NULL; 565 pCFileStruct->search_resume_name = NULL;
566 kfree(ptmp); 566 kfree(ptmp);
567 } 567 }
@@ -870,10 +870,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
870 if (rc != 0) 870 if (rc != 0)
871 break; 871 break;
872 } 872 }
873#ifdef CONFIG_CIFS_EXPERIMENTAL
874 /* BB FIXME We can not sign across two buffers yet */ 873 /* BB FIXME We can not sign across two buffers yet */
875 if((experimEnabled) && ((pTcon->ses->server->secMode & 874 if((pTcon->ses->server->secMode &
876 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) { 875 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
877 struct kvec iov[2]; 876 struct kvec iov[2];
878 unsigned int len; 877 unsigned int len;
879 878
@@ -889,7 +888,6 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
889 iov, 1, long_op); 888 iov, 1, long_op);
890 } else 889 } else
891 /* BB FIXME fixup indentation of line below */ 890 /* BB FIXME fixup indentation of line below */
892#endif
893 rc = CIFSSMBWrite(xid, pTcon, 891 rc = CIFSSMBWrite(xid, pTcon,
894 open_file->netfid, 892 open_file->netfid,
895 min_t(const int, cifs_sb->wsize, 893 min_t(const int, cifs_sb->wsize,
@@ -1026,7 +1024,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1026 return rc; 1024 return rc;
1027} 1025}
1028 1026
1029#ifdef CONFIG_CIFS_EXPERIMENTAL
1030static int cifs_writepages(struct address_space *mapping, 1027static int cifs_writepages(struct address_space *mapping,
1031 struct writeback_control *wbc) 1028 struct writeback_control *wbc)
1032{ 1029{
@@ -1229,7 +1226,6 @@ retry:
1229 1226
1230 return rc; 1227 return rc;
1231} 1228}
1232#endif
1233 1229
1234static int cifs_writepage(struct page* page, struct writeback_control *wbc) 1230static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1235{ 1231{
@@ -1428,6 +1424,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1428 rc = -EAGAIN; 1424 rc = -EAGAIN;
1429 smb_read_data = NULL; 1425 smb_read_data = NULL;
1430 while (rc == -EAGAIN) { 1426 while (rc == -EAGAIN) {
1427 int buf_type = CIFS_NO_BUFFER;
1431 if ((open_file->invalidHandle) && 1428 if ((open_file->invalidHandle) &&
1432 (!open_file->closePend)) { 1429 (!open_file->closePend)) {
1433 rc = cifs_reopen_file(file->f_dentry->d_inode, 1430 rc = cifs_reopen_file(file->f_dentry->d_inode,
@@ -1436,20 +1433,22 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1436 break; 1433 break;
1437 } 1434 }
1438 rc = CIFSSMBRead(xid, pTcon, 1435 rc = CIFSSMBRead(xid, pTcon,
1439 open_file->netfid, 1436 open_file->netfid,
1440 current_read_size, *poffset, 1437 current_read_size, *poffset,
1441 &bytes_read, &smb_read_data); 1438 &bytes_read, &smb_read_data,
1439 &buf_type);
1442 pSMBr = (struct smb_com_read_rsp *)smb_read_data; 1440 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1443 if (copy_to_user(current_offset, 1441 if (copy_to_user(current_offset,
1444 smb_read_data + 4 /* RFC1001 hdr */ 1442 smb_read_data + 4 /* RFC1001 hdr */
1445 + le16_to_cpu(pSMBr->DataOffset), 1443 + le16_to_cpu(pSMBr->DataOffset),
1446 bytes_read)) { 1444 bytes_read)) {
1447 rc = -EFAULT; 1445 rc = -EFAULT;
1448 FreeXid(xid); 1446 }
1449 return rc;
1450 }
1451 if (smb_read_data) { 1447 if (smb_read_data) {
1452 cifs_buf_release(smb_read_data); 1448 if(buf_type == CIFS_SMALL_BUFFER)
1449 cifs_small_buf_release(smb_read_data);
1450 else if(buf_type == CIFS_LARGE_BUFFER)
1451 cifs_buf_release(smb_read_data);
1453 smb_read_data = NULL; 1452 smb_read_data = NULL;
1454 } 1453 }
1455 } 1454 }
@@ -1482,6 +1481,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1482 int xid; 1481 int xid;
1483 char *current_offset; 1482 char *current_offset;
1484 struct cifsFileInfo *open_file; 1483 struct cifsFileInfo *open_file;
1484 int buf_type = CIFS_NO_BUFFER;
1485 1485
1486 xid = GetXid(); 1486 xid = GetXid();
1487 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 1487 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1518,9 +1518,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1518 break; 1518 break;
1519 } 1519 }
1520 rc = CIFSSMBRead(xid, pTcon, 1520 rc = CIFSSMBRead(xid, pTcon,
1521 open_file->netfid, 1521 open_file->netfid,
1522 current_read_size, *poffset, 1522 current_read_size, *poffset,
1523 &bytes_read, &current_offset); 1523 &bytes_read, &current_offset,
1524 &buf_type);
1524 } 1525 }
1525 if (rc || (bytes_read == 0)) { 1526 if (rc || (bytes_read == 0)) {
1526 if (total_read) { 1527 if (total_read) {
@@ -1618,6 +1619,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1618 struct smb_com_read_rsp *pSMBr; 1619 struct smb_com_read_rsp *pSMBr;
1619 struct pagevec lru_pvec; 1620 struct pagevec lru_pvec;
1620 struct cifsFileInfo *open_file; 1621 struct cifsFileInfo *open_file;
1622 int buf_type = CIFS_NO_BUFFER;
1621 1623
1622 xid = GetXid(); 1624 xid = GetXid();
1623 if (file->private_data == NULL) { 1625 if (file->private_data == NULL) {
@@ -1674,14 +1676,17 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1674 } 1676 }
1675 1677
1676 rc = CIFSSMBRead(xid, pTcon, 1678 rc = CIFSSMBRead(xid, pTcon,
1677 open_file->netfid, 1679 open_file->netfid,
1678 read_size, offset, 1680 read_size, offset,
1679 &bytes_read, &smb_read_data); 1681 &bytes_read, &smb_read_data,
1680 1682 &buf_type);
1681 /* BB more RC checks ? */ 1683 /* BB more RC checks ? */
1682 if (rc== -EAGAIN) { 1684 if (rc== -EAGAIN) {
1683 if (smb_read_data) { 1685 if (smb_read_data) {
1684 cifs_buf_release(smb_read_data); 1686 if(buf_type == CIFS_SMALL_BUFFER)
1687 cifs_small_buf_release(smb_read_data);
1688 else if(buf_type == CIFS_LARGE_BUFFER)
1689 cifs_buf_release(smb_read_data);
1685 smb_read_data = NULL; 1690 smb_read_data = NULL;
1686 } 1691 }
1687 } 1692 }
@@ -1738,7 +1743,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1738 break; 1743 break;
1739 } 1744 }
1740 if (smb_read_data) { 1745 if (smb_read_data) {
1741 cifs_buf_release(smb_read_data); 1746 if(buf_type == CIFS_SMALL_BUFFER)
1747 cifs_small_buf_release(smb_read_data);
1748 else if(buf_type == CIFS_LARGE_BUFFER)
1749 cifs_buf_release(smb_read_data);
1742 smb_read_data = NULL; 1750 smb_read_data = NULL;
1743 } 1751 }
1744 bytes_read = 0; 1752 bytes_read = 0;
@@ -1875,9 +1883,7 @@ struct address_space_operations cifs_addr_ops = {
1875 .readpage = cifs_readpage, 1883 .readpage = cifs_readpage,
1876 .readpages = cifs_readpages, 1884 .readpages = cifs_readpages,
1877 .writepage = cifs_writepage, 1885 .writepage = cifs_writepage,
1878#ifdef CONFIG_CIFS_EXPERIMENTAL
1879 .writepages = cifs_writepages, 1886 .writepages = cifs_writepages,
1880#endif
1881 .prepare_write = cifs_prepare_write, 1887 .prepare_write = cifs_prepare_write,
1882 .commit_write = cifs_commit_write, 1888 .commit_write = cifs_commit_write,
1883 .set_page_dirty = __set_page_dirty_nobuffers, 1889 .set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 411c1f7f84da..f65310cc60a1 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -229,11 +229,12 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
229 cifs_sb->mnt_cifs_flags & 229 cifs_sb->mnt_cifs_flags &
230 CIFS_MOUNT_MAP_SPECIAL_CHR); 230 CIFS_MOUNT_MAP_SPECIAL_CHR);
231 if (rc==0) { 231 if (rc==0) {
232 int buf_type = CIFS_NO_BUFFER;
232 /* Read header */ 233 /* Read header */
233 rc = CIFSSMBRead(xid, pTcon, 234 rc = CIFSSMBRead(xid, pTcon,
234 netfid, 235 netfid,
235 24 /* length */, 0 /* offset */, 236 24 /* length */, 0 /* offset */,
236 &bytes_read, &pbuf); 237 &bytes_read, &pbuf, &buf_type);
237 if((rc == 0) && (bytes_read >= 8)) { 238 if((rc == 0) && (bytes_read >= 8)) {
238 if(memcmp("IntxBLK", pbuf, 8) == 0) { 239 if(memcmp("IntxBLK", pbuf, 8) == 0) {
239 cFYI(1,("Block device")); 240 cFYI(1,("Block device"));
@@ -267,7 +268,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
267 } else { 268 } else {
268 inode->i_mode |= S_IFREG; /* then it is a file */ 269 inode->i_mode |= S_IFREG; /* then it is a file */
269 rc = -EOPNOTSUPP; /* or some unknown SFU type */ 270 rc = -EOPNOTSUPP; /* or some unknown SFU type */
270 } 271 }
271 CIFSSMBClose(xid, pTcon, netfid); 272 CIFSSMBClose(xid, pTcon, netfid);
272 } 273 }
273 return rc; 274 return rc;
@@ -750,8 +751,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
750 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 751 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
751 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 752 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
752 mode, 753 mode,
753 (__u64)current->euid, 754 (__u64)current->fsuid,
754 (__u64)current->egid, 755 (__u64)current->fsgid,
755 0 /* dev_t */, 756 0 /* dev_t */,
756 cifs_sb->local_nls, 757 cifs_sb->local_nls,
757 cifs_sb->mnt_cifs_flags & 758 cifs_sb->mnt_cifs_flags &
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 94baf6c8ecbd..812c6bb0fe38 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/misc.c 2 * fs/cifs/misc.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004 4 * Copyright (C) International Business Machines Corp., 2002,2005
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
@@ -161,6 +161,9 @@ cifs_buf_get(void)
161 if (ret_buf) { 161 if (ret_buf) {
162 memset(ret_buf, 0, sizeof(struct smb_hdr) + 3); 162 memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
163 atomic_inc(&bufAllocCount); 163 atomic_inc(&bufAllocCount);
164#ifdef CONFIG_CIFS_STATS2
165 atomic_inc(&totBufAllocCount);
166#endif /* CONFIG_CIFS_STATS2 */
164 } 167 }
165 168
166 return ret_buf; 169 return ret_buf;
@@ -195,6 +198,10 @@ cifs_small_buf_get(void)
195 /* No need to clear memory here, cleared in header assemble */ 198 /* No need to clear memory here, cleared in header assemble */
196 /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ 199 /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
197 atomic_inc(&smBufAllocCount); 200 atomic_inc(&smBufAllocCount);
201#ifdef CONFIG_CIFS_STATS2
202 atomic_inc(&totSmBufAllocCount);
203#endif /* CONFIG_CIFS_STATS2 */
204
198 } 205 }
199 return ret_buf; 206 return ret_buf;
200} 207}
@@ -292,7 +299,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
292 struct cifsSesInfo * ses; 299 struct cifsSesInfo * ses;
293 char *temp = (char *) buffer; 300 char *temp = (char *) buffer;
294 301
295 memset(temp,0,MAX_CIFS_HDR_SIZE); 302 memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */
296 303
297 buffer->smb_buf_length = 304 buffer->smb_buf_length =
298 (2 * word_count) + sizeof (struct smb_hdr) - 305 (2 * word_count) + sizeof (struct smb_hdr) -
@@ -348,12 +355,12 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
348 /* BB Add support for establishing new tCon and SMB Session */ 355 /* BB Add support for establishing new tCon and SMB Session */
349 /* with userid/password pairs found on the smb session */ 356 /* with userid/password pairs found on the smb session */
350 /* for other target tcp/ip addresses BB */ 357 /* for other target tcp/ip addresses BB */
351 if(current->uid != treeCon->ses->linux_uid) { 358 if(current->fsuid != treeCon->ses->linux_uid) {
352 cFYI(1,("Multiuser mode and UID did not match tcon uid ")); 359 cFYI(1,("Multiuser mode and UID did not match tcon uid"));
353 read_lock(&GlobalSMBSeslock); 360 read_lock(&GlobalSMBSeslock);
354 list_for_each(temp_item, &GlobalSMBSessionList) { 361 list_for_each(temp_item, &GlobalSMBSessionList) {
355 ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); 362 ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
356 if(ses->linux_uid == current->uid) { 363 if(ses->linux_uid == current->fsuid) {
357 if(ses->server == treeCon->ses->server) { 364 if(ses->server == treeCon->ses->server) {
358 cFYI(1,("found matching uid substitute right smb_uid")); 365 cFYI(1,("found matching uid substitute right smb_uid"));
359 buffer->Uid = ses->Suid; 366 buffer->Uid = ses->Suid;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index f8871196098c..c96a148c39b2 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -206,7 +206,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
206 return rc; 206 return rc;
207} 207}
208 208
209#ifdef CONFIG_CIFS_EXPERIMENTAL
210static int 209static int
211smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, 210smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
212 struct sockaddr *sin) 211 struct sockaddr *sin)
@@ -299,7 +298,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
299 298
300int 299int
301SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 300SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
302 struct kvec *iov, int n_vec, int *pbytes_returned, 301 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
303 const int long_op) 302 const int long_op)
304{ 303{
305 int rc = 0; 304 int rc = 0;
@@ -307,6 +306,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
307 unsigned long timeout; 306 unsigned long timeout;
308 struct mid_q_entry *midQ; 307 struct mid_q_entry *midQ;
309 struct smb_hdr *in_buf = iov[0].iov_base; 308 struct smb_hdr *in_buf = iov[0].iov_base;
309
310 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
310 311
311 if (ses == NULL) { 312 if (ses == NULL) {
312 cERROR(1,("Null smb session")); 313 cERROR(1,("Null smb session"));
@@ -392,8 +393,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
392 return -ENOMEM; 393 return -ENOMEM;
393 } 394 }
394 395
395/* BB FIXME */ 396 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
396/* rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
397 397
398 midQ->midState = MID_REQUEST_SUBMITTED; 398 midQ->midState = MID_REQUEST_SUBMITTED;
399#ifdef CONFIG_CIFS_STATS2 399#ifdef CONFIG_CIFS_STATS2
@@ -492,18 +492,21 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
492 492
493 if (midQ->resp_buf && 493 if (midQ->resp_buf &&
494 (midQ->midState == MID_RESPONSE_RECEIVED)) { 494 (midQ->midState == MID_RESPONSE_RECEIVED)) {
495 in_buf->smb_buf_length = receive_len;
496 /* BB verify that length would not overrun small buf */
497 memcpy((char *)in_buf + 4,
498 (char *)midQ->resp_buf + 4,
499 receive_len);
500 495
501 dump_smb(in_buf, 80); 496 iov[0].iov_base = (char *)midQ->resp_buf;
497 if(midQ->largeBuf)
498 *pRespBufType = CIFS_LARGE_BUFFER;
499 else
500 *pRespBufType = CIFS_SMALL_BUFFER;
501 iov[0].iov_len = receive_len + 4;
502 iov[1].iov_len = 0;
503
504 dump_smb(midQ->resp_buf, 80);
502 /* convert the length into a more usable form */ 505 /* convert the length into a more usable form */
503 if((receive_len > 24) && 506 if((receive_len > 24) &&
504 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | 507 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
505 SECMODE_SIGN_ENABLED))) { 508 SECMODE_SIGN_ENABLED))) {
506 rc = cifs_verify_signature(in_buf, 509 rc = cifs_verify_signature(midQ->resp_buf,
507 ses->server->mac_signing_key, 510 ses->server->mac_signing_key,
508 midQ->sequence_number+1); 511 midQ->sequence_number+1);
509 if(rc) { 512 if(rc) {
@@ -512,18 +515,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
512 } 515 }
513 } 516 }
514 517
515 *pbytes_returned = in_buf->smb_buf_length;
516
517 /* BB special case reconnect tid and uid here? */ 518 /* BB special case reconnect tid and uid here? */
518 /* BB special case Errbadpassword and pwdexpired here */ 519 /* BB special case Errbadpassword and pwdexpired here */
519 rc = map_smb_to_linux_error(in_buf); 520 rc = map_smb_to_linux_error(midQ->resp_buf);
520 521
521 /* convert ByteCount if necessary */ 522 /* convert ByteCount if necessary */
522 if (receive_len >= 523 if (receive_len >=
523 sizeof (struct smb_hdr) - 524 sizeof (struct smb_hdr) -
524 4 /* do not count RFC1001 header */ + 525 4 /* do not count RFC1001 header */ +
525 (2 * in_buf->WordCount) + 2 /* bcc */ ) 526 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
526 BCC(in_buf) = le16_to_cpu(BCC_LE(in_buf)); 527 BCC(midQ->resp_buf) =
528 le16_to_cpu(BCC_LE(midQ->resp_buf));
529 midQ->resp_buf = NULL; /* mark it so will not be freed
530 by DeleteMidQEntry */
527 } else { 531 } else {
528 rc = -EIO; 532 rc = -EIO;
529 cFYI(1,("Bad MID state?")); 533 cFYI(1,("Bad MID state?"));
@@ -549,7 +553,6 @@ out_unlock2:
549 553
550 return rc; 554 return rc;
551} 555}
552#endif /* CIFS_EXPERIMENTAL */
553 556
554int 557int
555SendReceive(const unsigned int xid, struct cifsSesInfo *ses, 558SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
@@ -790,7 +793,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
790 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 793 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
791 } else { 794 } else {
792 rc = -EIO; 795 rc = -EIO;
793 cERROR(1,("Bad MID state? ")); 796 cERROR(1,("Bad MID state?"));
794 } 797 }
795 } 798 }
796cifs_no_response_exit: 799cifs_no_response_exit: