aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 10:47:11 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 10:47:11 -0500
commitf3ea597251ac859a1c0e7b9e266877f1ac828009 (patch)
tree4cd4dd499d36fbb0699e854b038e2260cff7d5cd /fs
parentf9f265f35578c5fb2266d0e2a1aa5b57f6fdb36a (diff)
parent20054bd65703f7504a9daceabc2a060828fde36c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: cifs: use CreationTime like an i_generation field cifs: switch cifs_open and cifs_create to use CIFSSMBUnixSetFileInfo cifs: show "acl" in DebugData Features when it's compiled in cifs: move "ntlmssp" and "local_leases" options out of experimental code cifs: replace some hardcoded values with preprocessor constants cifs: remove unnecessary locking around sequence_number [CIFS] Fix minor merge conflict in fs/cifs/dir.c CIFS: Simplify cifs_open code CIFS: Simplify non-posix open stuff (try #2) CIFS: Add match_port check during looking for an existing connection (try #4) CIFS: Simplify ipv*_connect functions into one (try #4) cifs: Support NTLM2 session security during NTLMSSP authentication [try #5] cifs: don't overwrite dentry name in d_revalidate
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cache.c16
-rw-r--r--fs/cifs/cifs_debug.c22
-rw-r--r--fs/cifs/cifs_spnego.c10
-rw-r--r--fs/cifs/cifsencrypt.c6
-rw-r--r--fs/cifs/cifsfs.c17
-rw-r--r--fs/cifs/cifsglob.h9
-rw-r--r--fs/cifs/cifssmb.c5
-rw-r--r--fs/cifs/connect.c462
-rw-r--r--fs/cifs/dir.c6
-rw-r--r--fs/cifs/file.c233
-rw-r--r--fs/cifs/inode.c6
-rw-r--r--fs/cifs/readdir.c1
-rw-r--r--fs/cifs/sess.c135
-rw-r--r--fs/cifs/transport.c2
14 files changed, 417 insertions, 513 deletions
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index 224d7bbd1fcc..e654dfd092c3 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -64,7 +64,9 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
64 void *buffer, uint16_t maxbuf) 64 void *buffer, uint16_t maxbuf)
65{ 65{
66 const struct TCP_Server_Info *server = cookie_netfs_data; 66 const struct TCP_Server_Info *server = cookie_netfs_data;
67 const struct sockaddr *sa = (struct sockaddr *) &server->addr.sockAddr; 67 const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr;
68 const struct sockaddr_in *addr = (struct sockaddr_in *) sa;
69 const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa;
68 struct cifs_server_key *key = buffer; 70 struct cifs_server_key *key = buffer;
69 uint16_t key_len = sizeof(struct cifs_server_key); 71 uint16_t key_len = sizeof(struct cifs_server_key);
70 72
@@ -76,16 +78,16 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
76 */ 78 */
77 switch (sa->sa_family) { 79 switch (sa->sa_family) {
78 case AF_INET: 80 case AF_INET:
79 key->family = server->addr.sockAddr.sin_family; 81 key->family = sa->sa_family;
80 key->port = server->addr.sockAddr.sin_port; 82 key->port = addr->sin_port;
81 key->addr[0].ipv4_addr = server->addr.sockAddr.sin_addr; 83 key->addr[0].ipv4_addr = addr->sin_addr;
82 key_len += sizeof(key->addr[0].ipv4_addr); 84 key_len += sizeof(key->addr[0].ipv4_addr);
83 break; 85 break;
84 86
85 case AF_INET6: 87 case AF_INET6:
86 key->family = server->addr.sockAddr6.sin6_family; 88 key->family = sa->sa_family;
87 key->port = server->addr.sockAddr6.sin6_port; 89 key->port = addr6->sin6_port;
88 key->addr[0].ipv6_addr = server->addr.sockAddr6.sin6_addr; 90 key->addr[0].ipv6_addr = addr6->sin6_addr;
89 key_len += sizeof(key->addr[0].ipv6_addr); 91 key_len += sizeof(key->addr[0].ipv6_addr);
90 break; 92 break;
91 93
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 103ab8b605b0..ede98300a8cd 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -119,29 +119,27 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
119 "Display Internal CIFS Data Structures for Debugging\n" 119 "Display Internal CIFS Data Structures for Debugging\n"
120 "---------------------------------------------------\n"); 120 "---------------------------------------------------\n");
121 seq_printf(m, "CIFS Version %s\n", CIFS_VERSION); 121 seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
122 seq_printf(m, "Features: "); 122 seq_printf(m, "Features:");
123#ifdef CONFIG_CIFS_DFS_UPCALL 123#ifdef CONFIG_CIFS_DFS_UPCALL
124 seq_printf(m, "dfs"); 124 seq_printf(m, " dfs");
125 seq_putc(m, ' ');
126#endif 125#endif
127#ifdef CONFIG_CIFS_FSCACHE 126#ifdef CONFIG_CIFS_FSCACHE
128 seq_printf(m, "fscache"); 127 seq_printf(m, " fscache");
129 seq_putc(m, ' ');
130#endif 128#endif
131#ifdef CONFIG_CIFS_WEAK_PW_HASH 129#ifdef CONFIG_CIFS_WEAK_PW_HASH
132 seq_printf(m, "lanman"); 130 seq_printf(m, " lanman");
133 seq_putc(m, ' ');
134#endif 131#endif
135#ifdef CONFIG_CIFS_POSIX 132#ifdef CONFIG_CIFS_POSIX
136 seq_printf(m, "posix"); 133 seq_printf(m, " posix");
137 seq_putc(m, ' ');
138#endif 134#endif
139#ifdef CONFIG_CIFS_UPCALL 135#ifdef CONFIG_CIFS_UPCALL
140 seq_printf(m, "spnego"); 136 seq_printf(m, " spnego");
141 seq_putc(m, ' ');
142#endif 137#endif
143#ifdef CONFIG_CIFS_XATTR 138#ifdef CONFIG_CIFS_XATTR
144 seq_printf(m, "xattr"); 139 seq_printf(m, " xattr");
140#endif
141#ifdef CONFIG_CIFS_ACL
142 seq_printf(m, " acl");
145#endif 143#endif
146 seq_putc(m, '\n'); 144 seq_putc(m, '\n');
147 seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); 145 seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 87044906cd1f..4dfba8283165 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -98,6 +98,8 @@ struct key *
98cifs_get_spnego_key(struct cifsSesInfo *sesInfo) 98cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
99{ 99{
100 struct TCP_Server_Info *server = sesInfo->server; 100 struct TCP_Server_Info *server = sesInfo->server;
101 struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
102 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
101 char *description, *dp; 103 char *description, *dp;
102 size_t desc_len; 104 size_t desc_len;
103 struct key *spnego_key; 105 struct key *spnego_key;
@@ -127,10 +129,10 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
127 dp = description + strlen(description); 129 dp = description + strlen(description);
128 130
129 /* add the server address */ 131 /* add the server address */
130 if (server->addr.sockAddr.sin_family == AF_INET) 132 if (server->dstaddr.ss_family == AF_INET)
131 sprintf(dp, "ip4=%pI4", &server->addr.sockAddr.sin_addr); 133 sprintf(dp, "ip4=%pI4", &sa->sin_addr);
132 else if (server->addr.sockAddr.sin_family == AF_INET6) 134 else if (server->dstaddr.ss_family == AF_INET6)
133 sprintf(dp, "ip6=%pI6", &server->addr.sockAddr6.sin6_addr); 135 sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
134 else 136 else
135 goto out; 137 goto out;
136 138
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index f856732161ab..66f3d50d0676 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -72,6 +72,7 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
72 return 0; 72 return 0;
73} 73}
74 74
75/* must be called with server->srv_mutex held */
75int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, 76int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
76 __u32 *pexpected_response_sequence_number) 77 __u32 *pexpected_response_sequence_number)
77{ 78{
@@ -84,14 +85,12 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
84 if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 85 if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
85 return rc; 86 return rc;
86 87
87 spin_lock(&GlobalMid_Lock);
88 cifs_pdu->Signature.Sequence.SequenceNumber = 88 cifs_pdu->Signature.Sequence.SequenceNumber =
89 cpu_to_le32(server->sequence_number); 89 cpu_to_le32(server->sequence_number);
90 cifs_pdu->Signature.Sequence.Reserved = 0; 90 cifs_pdu->Signature.Sequence.Reserved = 0;
91 91
92 *pexpected_response_sequence_number = server->sequence_number++; 92 *pexpected_response_sequence_number = server->sequence_number++;
93 server->sequence_number++; 93 server->sequence_number++;
94 spin_unlock(&GlobalMid_Lock);
95 94
96 rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); 95 rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
97 if (rc) 96 if (rc)
@@ -149,6 +148,7 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
149 return rc; 148 return rc;
150} 149}
151 150
151/* must be called with server->srv_mutex held */
152int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, 152int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
153 __u32 *pexpected_response_sequence_number) 153 __u32 *pexpected_response_sequence_number)
154{ 154{
@@ -162,14 +162,12 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
162 if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 162 if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
163 return rc; 163 return rc;
164 164
165 spin_lock(&GlobalMid_Lock);
166 cifs_pdu->Signature.Sequence.SequenceNumber = 165 cifs_pdu->Signature.Sequence.SequenceNumber =
167 cpu_to_le32(server->sequence_number); 166 cpu_to_le32(server->sequence_number);
168 cifs_pdu->Signature.Sequence.Reserved = 0; 167 cifs_pdu->Signature.Sequence.Reserved = 0;
169 168
170 *pexpected_response_sequence_number = server->sequence_number++; 169 *pexpected_response_sequence_number = server->sequence_number++;
171 server->sequence_number++; 170 server->sequence_number++;
172 spin_unlock(&GlobalMid_Lock);
173 171
174 rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); 172 rc = cifs_calc_signature2(iov, n_vec, server, smb_signature);
175 if (rc) 173 if (rc)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 8e21e0fe65d5..5e7075d5f139 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -329,6 +329,8 @@ cifs_alloc_inode(struct super_block *sb)
329 cifs_inode->invalid_mapping = false; 329 cifs_inode->invalid_mapping = false;
330 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 330 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
331 cifs_inode->server_eof = 0; 331 cifs_inode->server_eof = 0;
332 cifs_inode->uniqueid = 0;
333 cifs_inode->createtime = 0;
332 334
333 /* Can not set i_flags here - they get immediately overwritten 335 /* Can not set i_flags here - they get immediately overwritten
334 to zero by the VFS */ 336 to zero by the VFS */
@@ -361,18 +363,19 @@ cifs_evict_inode(struct inode *inode)
361static void 363static void
362cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) 364cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
363{ 365{
366 struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
367 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
368
364 seq_printf(s, ",addr="); 369 seq_printf(s, ",addr=");
365 370
366 switch (server->addr.sockAddr.sin_family) { 371 switch (server->dstaddr.ss_family) {
367 case AF_INET: 372 case AF_INET:
368 seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr); 373 seq_printf(s, "%pI4", &sa->sin_addr.s_addr);
369 break; 374 break;
370 case AF_INET6: 375 case AF_INET6:
371 seq_printf(s, "%pI6", 376 seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr);
372 &server->addr.sockAddr6.sin6_addr.s6_addr); 377 if (sa6->sin6_scope_id)
373 if (server->addr.sockAddr6.sin6_scope_id) 378 seq_printf(s, "%%%u", sa6->sin6_scope_id);
374 seq_printf(s, "%%%u",
375 server->addr.sockAddr6.sin6_scope_id);
376 break; 379 break;
377 default: 380 default:
378 seq_printf(s, "(unknown)"); 381 seq_printf(s, "(unknown)");
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7136c0c3e2f9..606ca8bb7102 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -163,10 +163,7 @@ struct TCP_Server_Info {
163 char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; 163 char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
164 char *hostname; /* hostname portion of UNC string */ 164 char *hostname; /* hostname portion of UNC string */
165 struct socket *ssocket; 165 struct socket *ssocket;
166 union { 166 struct sockaddr_storage dstaddr;
167 struct sockaddr_in sockAddr;
168 struct sockaddr_in6 sockAddr6;
169 } addr;
170 struct sockaddr_storage srcaddr; /* locally bind to this IP */ 167 struct sockaddr_storage srcaddr; /* locally bind to this IP */
171 wait_queue_head_t response_q; 168 wait_queue_head_t response_q;
172 wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ 169 wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
@@ -210,7 +207,7 @@ struct TCP_Server_Info {
210 char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ 207 char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
211 /* 16th byte of RFC1001 workstation name is always null */ 208 /* 16th byte of RFC1001 workstation name is always null */
212 char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; 209 char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
213 __u32 sequence_number; /* needed for CIFS PDU signature */ 210 __u32 sequence_number; /* for signing, protected by srv_mutex */
214 struct session_key session_key; 211 struct session_key session_key;
215 unsigned long lstrp; /* when we got last response from this server */ 212 unsigned long lstrp; /* when we got last response from this server */
216 u16 dialect; /* dialect index that server chose */ 213 u16 dialect; /* dialect index that server chose */
@@ -456,6 +453,7 @@ struct cifsInodeInfo {
456 bool invalid_mapping:1; /* pagecache is invalid */ 453 bool invalid_mapping:1; /* pagecache is invalid */
457 u64 server_eof; /* current file size on server */ 454 u64 server_eof; /* current file size on server */
458 u64 uniqueid; /* server inode number */ 455 u64 uniqueid; /* server inode number */
456 u64 createtime; /* creation time on server */
459#ifdef CONFIG_CIFS_FSCACHE 457#ifdef CONFIG_CIFS_FSCACHE
460 struct fscache_cookie *fscache; 458 struct fscache_cookie *fscache;
461#endif 459#endif
@@ -576,6 +574,7 @@ struct cifs_fattr {
576 u64 cf_uniqueid; 574 u64 cf_uniqueid;
577 u64 cf_eof; 575 u64 cf_eof;
578 u64 cf_bytes; 576 u64 cf_bytes;
577 u64 cf_createtime;
579 uid_t cf_uid; 578 uid_t cf_uid;
580 gid_t cf_gid; 579 gid_t cf_gid;
581 umode_t cf_mode; 580 umode_t cf_mode;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 67acfb3acad2..2f6795e524d3 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -401,15 +401,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
401 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { 401 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
402 cFYI(1, "Kerberos only mechanism, enable extended security"); 402 cFYI(1, "Kerberos only mechanism, enable extended security");
403 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 403 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
404 } 404 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
405#ifdef CONFIG_CIFS_EXPERIMENTAL
406 else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
407 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 405 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
408 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { 406 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
409 cFYI(1, "NTLMSSP only mechanism, enable extended security"); 407 cFYI(1, "NTLMSSP only mechanism, enable extended security");
410 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 408 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
411 } 409 }
412#endif
413 410
414 count = 0; 411 count = 0;
415 for (i = 0; i < CIFS_NUM_PROT; i++) { 412 for (i = 0; i < CIFS_NUM_PROT; i++) {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index cc1a8604a790..a65d311d163a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -64,8 +64,8 @@ struct smb_vol {
64 char *UNC; 64 char *UNC;
65 char *UNCip; 65 char *UNCip;
66 char *iocharset; /* local code page for mapping to and from Unicode */ 66 char *iocharset; /* local code page for mapping to and from Unicode */
67 char source_rfc1001_name[16]; /* netbios name of client */ 67 char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
68 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ 68 char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
69 uid_t cred_uid; 69 uid_t cred_uid;
70 uid_t linux_uid; 70 uid_t linux_uid;
71 gid_t linux_gid; 71 gid_t linux_gid;
@@ -115,8 +115,8 @@ struct smb_vol {
115#define TLINK_ERROR_EXPIRE (1 * HZ) 115#define TLINK_ERROR_EXPIRE (1 * HZ)
116#define TLINK_IDLE_EXPIRE (600 * HZ) 116#define TLINK_IDLE_EXPIRE (600 * HZ)
117 117
118static int ipv4_connect(struct TCP_Server_Info *server); 118static int ip_connect(struct TCP_Server_Info *server);
119static int ipv6_connect(struct TCP_Server_Info *server); 119static int generic_ip_connect(struct TCP_Server_Info *server);
120static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); 120static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
121static void cifs_prune_tlinks(struct work_struct *work); 121static void cifs_prune_tlinks(struct work_struct *work);
122 122
@@ -200,10 +200,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
200 while ((server->tcpStatus != CifsExiting) && 200 while ((server->tcpStatus != CifsExiting) &&
201 (server->tcpStatus != CifsGood)) { 201 (server->tcpStatus != CifsGood)) {
202 try_to_freeze(); 202 try_to_freeze();
203 if (server->addr.sockAddr6.sin6_family == AF_INET6) 203
204 rc = ipv6_connect(server); 204 /* we should try only the port we connected to before */
205 else 205 rc = generic_ip_connect(server);
206 rc = ipv4_connect(server);
207 if (rc) { 206 if (rc) {
208 cFYI(1, "reconnect error %d", rc); 207 cFYI(1, "reconnect error %d", rc);
209 msleep(3000); 208 msleep(3000);
@@ -477,7 +476,7 @@ incomplete_rcv:
477 * initialize frame) 476 * initialize frame)
478 */ 477 */
479 cifs_set_port((struct sockaddr *) 478 cifs_set_port((struct sockaddr *)
480 &server->addr.sockAddr, CIFS_PORT); 479 &server->dstaddr, CIFS_PORT);
481 cifs_reconnect(server); 480 cifs_reconnect(server);
482 csocket = server->ssocket; 481 csocket = server->ssocket;
483 wake_up(&server->response_q); 482 wake_up(&server->response_q);
@@ -817,11 +816,11 @@ cifs_parse_mount_options(char *options, const char *devname,
817 * informational, only used for servers that do not support 816 * informational, only used for servers that do not support
818 * port 445 and it can be overridden at mount time 817 * port 445 and it can be overridden at mount time
819 */ 818 */
820 memset(vol->source_rfc1001_name, 0x20, 15); 819 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
821 for (i = 0; i < strnlen(nodename, 15); i++) 820 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
822 vol->source_rfc1001_name[i] = toupper(nodename[i]); 821 vol->source_rfc1001_name[i] = toupper(nodename[i]);
823 822
824 vol->source_rfc1001_name[15] = 0; 823 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
825 /* null target name indicates to use *SMBSERVR default called name 824 /* null target name indicates to use *SMBSERVR default called name
826 if we end up sending RFC1001 session initialize */ 825 if we end up sending RFC1001 session initialize */
827 vol->target_rfc1001_name[0] = 0; 826 vol->target_rfc1001_name[0] = 0;
@@ -985,13 +984,11 @@ cifs_parse_mount_options(char *options, const char *devname,
985 return 1; 984 return 1;
986 } else if (strnicmp(value, "krb5", 4) == 0) { 985 } else if (strnicmp(value, "krb5", 4) == 0) {
987 vol->secFlg |= CIFSSEC_MAY_KRB5; 986 vol->secFlg |= CIFSSEC_MAY_KRB5;
988#ifdef CONFIG_CIFS_EXPERIMENTAL
989 } else if (strnicmp(value, "ntlmsspi", 8) == 0) { 987 } else if (strnicmp(value, "ntlmsspi", 8) == 0) {
990 vol->secFlg |= CIFSSEC_MAY_NTLMSSP | 988 vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
991 CIFSSEC_MUST_SIGN; 989 CIFSSEC_MUST_SIGN;
992 } else if (strnicmp(value, "ntlmssp", 7) == 0) { 990 } else if (strnicmp(value, "ntlmssp", 7) == 0) {
993 vol->secFlg |= CIFSSEC_MAY_NTLMSSP; 991 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
994#endif
995 } else if (strnicmp(value, "ntlmv2i", 7) == 0) { 992 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
996 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | 993 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
997 CIFSSEC_MUST_SIGN; 994 CIFSSEC_MUST_SIGN;
@@ -1168,22 +1165,22 @@ cifs_parse_mount_options(char *options, const char *devname,
1168 if (!value || !*value || (*value == ' ')) { 1165 if (!value || !*value || (*value == ' ')) {
1169 cFYI(1, "invalid (empty) netbiosname"); 1166 cFYI(1, "invalid (empty) netbiosname");
1170 } else { 1167 } else {
1171 memset(vol->source_rfc1001_name, 0x20, 15); 1168 memset(vol->source_rfc1001_name, 0x20,
1172 for (i = 0; i < 15; i++) { 1169 RFC1001_NAME_LEN);
1173 /* BB are there cases in which a comma can be 1170 /*
1174 valid in this workstation netbios name (and need 1171 * FIXME: are there cases in which a comma can
1175 special handling)? */ 1172 * be valid in workstation netbios name (and
1176 1173 * need special handling)?
1177 /* We do not uppercase netbiosname for user */ 1174 */
1175 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1176 /* don't ucase netbiosname for user */
1178 if (value[i] == 0) 1177 if (value[i] == 0)
1179 break; 1178 break;
1180 else 1179 vol->source_rfc1001_name[i] = value[i];
1181 vol->source_rfc1001_name[i] =
1182 value[i];
1183 } 1180 }
1184 /* The string has 16th byte zero still from 1181 /* The string has 16th byte zero still from
1185 set at top of the function */ 1182 set at top of the function */
1186 if ((i == 15) && (value[i] != 0)) 1183 if (i == RFC1001_NAME_LEN && value[i] != 0)
1187 printk(KERN_WARNING "CIFS: netbiosname" 1184 printk(KERN_WARNING "CIFS: netbiosname"
1188 " longer than 15 truncated.\n"); 1185 " longer than 15 truncated.\n");
1189 } 1186 }
@@ -1193,7 +1190,8 @@ cifs_parse_mount_options(char *options, const char *devname,
1193 cFYI(1, "empty server netbiosname specified"); 1190 cFYI(1, "empty server netbiosname specified");
1194 } else { 1191 } else {
1195 /* last byte, type, is 0x20 for servr type */ 1192 /* last byte, type, is 0x20 for servr type */
1196 memset(vol->target_rfc1001_name, 0x20, 16); 1193 memset(vol->target_rfc1001_name, 0x20,
1194 RFC1001_NAME_LEN_WITH_NULL);
1197 1195
1198 for (i = 0; i < 15; i++) { 1196 for (i = 0; i < 15; i++) {
1199 /* BB are there cases in which a comma can be 1197 /* BB are there cases in which a comma can be
@@ -1210,7 +1208,7 @@ cifs_parse_mount_options(char *options, const char *devname,
1210 } 1208 }
1211 /* The string has 16th byte zero still from 1209 /* The string has 16th byte zero still from
1212 set at top of the function */ 1210 set at top of the function */
1213 if ((i == 15) && (value[i] != 0)) 1211 if (i == RFC1001_NAME_LEN && value[i] != 0)
1214 printk(KERN_WARNING "CIFS: server net" 1212 printk(KERN_WARNING "CIFS: server net"
1215 "biosname longer than 15 truncated.\n"); 1213 "biosname longer than 15 truncated.\n");
1216 } 1214 }
@@ -1341,10 +1339,8 @@ cifs_parse_mount_options(char *options, const char *devname,
1341 vol->no_psx_acl = 0; 1339 vol->no_psx_acl = 0;
1342 } else if (strnicmp(data, "noacl", 5) == 0) { 1340 } else if (strnicmp(data, "noacl", 5) == 0) {
1343 vol->no_psx_acl = 1; 1341 vol->no_psx_acl = 1;
1344#ifdef CONFIG_CIFS_EXPERIMENTAL
1345 } else if (strnicmp(data, "locallease", 6) == 0) { 1342 } else if (strnicmp(data, "locallease", 6) == 0) {
1346 vol->local_lease = 1; 1343 vol->local_lease = 1;
1347#endif
1348 } else if (strnicmp(data, "sign", 4) == 0) { 1344 } else if (strnicmp(data, "sign", 4) == 0) {
1349 vol->secFlg |= CIFSSEC_MUST_SIGN; 1345 vol->secFlg |= CIFSSEC_MUST_SIGN;
1350 } else if (strnicmp(data, "seal", 4) == 0) { 1346 } else if (strnicmp(data, "seal", 4) == 0) {
@@ -1454,35 +1450,71 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1454 } 1450 }
1455} 1451}
1456 1452
1453/*
1454 * If no port is specified in addr structure, we try to match with 445 port
1455 * and if it fails - with 139 ports. It should be called only if address
1456 * families of server and addr are equal.
1457 */
1458static bool
1459match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
1460{
1461 unsigned short int port, *sport;
1462
1463 switch (addr->sa_family) {
1464 case AF_INET:
1465 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
1466 port = ((struct sockaddr_in *) addr)->sin_port;
1467 break;
1468 case AF_INET6:
1469 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
1470 port = ((struct sockaddr_in6 *) addr)->sin6_port;
1471 break;
1472 default:
1473 WARN_ON(1);
1474 return false;
1475 }
1476
1477 if (!port) {
1478 port = htons(CIFS_PORT);
1479 if (port == *sport)
1480 return true;
1481
1482 port = htons(RFC1001_PORT);
1483 }
1484
1485 return port == *sport;
1486}
1457 1487
1458static bool 1488static bool
1459match_address(struct TCP_Server_Info *server, struct sockaddr *addr, 1489match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
1460 struct sockaddr *srcaddr) 1490 struct sockaddr *srcaddr)
1461{ 1491{
1462 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1463 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1464
1465 switch (addr->sa_family) { 1492 switch (addr->sa_family) {
1466 case AF_INET: 1493 case AF_INET: {
1467 if (addr4->sin_addr.s_addr != 1494 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1468 server->addr.sockAddr.sin_addr.s_addr) 1495 struct sockaddr_in *srv_addr4 =
1469 return false; 1496 (struct sockaddr_in *)&server->dstaddr;
1470 if (addr4->sin_port && 1497
1471 addr4->sin_port != server->addr.sockAddr.sin_port) 1498 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
1472 return false; 1499 return false;
1473 break; 1500 break;
1474 case AF_INET6: 1501 }
1502 case AF_INET6: {
1503 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1504 struct sockaddr_in6 *srv_addr6 =
1505 (struct sockaddr_in6 *)&server->dstaddr;
1506
1475 if (!ipv6_addr_equal(&addr6->sin6_addr, 1507 if (!ipv6_addr_equal(&addr6->sin6_addr,
1476 &server->addr.sockAddr6.sin6_addr)) 1508 &srv_addr6->sin6_addr))
1477 return false; 1509 return false;
1478 if (addr6->sin6_scope_id != 1510 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
1479 server->addr.sockAddr6.sin6_scope_id)
1480 return false;
1481 if (addr6->sin6_port &&
1482 addr6->sin6_port != server->addr.sockAddr6.sin6_port)
1483 return false; 1511 return false;
1484 break; 1512 break;
1485 } 1513 }
1514 default:
1515 WARN_ON(1);
1516 return false; /* don't expect to be here */
1517 }
1486 1518
1487 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr)) 1519 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
1488 return false; 1520 return false;
@@ -1549,6 +1581,9 @@ cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
1549 (struct sockaddr *)&vol->srcaddr)) 1581 (struct sockaddr *)&vol->srcaddr))
1550 continue; 1582 continue;
1551 1583
1584 if (!match_port(server, addr))
1585 continue;
1586
1552 if (!match_security(server, vol)) 1587 if (!match_security(server, vol))
1553 continue; 1588 continue;
1554 1589
@@ -1681,14 +1716,13 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1681 cFYI(1, "attempting ipv6 connect"); 1716 cFYI(1, "attempting ipv6 connect");
1682 /* BB should we allow ipv6 on port 139? */ 1717 /* BB should we allow ipv6 on port 139? */
1683 /* other OS never observed in Wild doing 139 with v6 */ 1718 /* other OS never observed in Wild doing 139 with v6 */
1684 memcpy(&tcp_ses->addr.sockAddr6, sin_server6, 1719 memcpy(&tcp_ses->dstaddr, sin_server6,
1685 sizeof(struct sockaddr_in6)); 1720 sizeof(struct sockaddr_in6));
1686 rc = ipv6_connect(tcp_ses); 1721 } else
1687 } else { 1722 memcpy(&tcp_ses->dstaddr, sin_server,
1688 memcpy(&tcp_ses->addr.sockAddr, sin_server, 1723 sizeof(struct sockaddr_in));
1689 sizeof(struct sockaddr_in)); 1724
1690 rc = ipv4_connect(tcp_ses); 1725 rc = ip_connect(tcp_ses);
1691 }
1692 if (rc < 0) { 1726 if (rc < 0) {
1693 cERROR(1, "Error connecting to socket. Aborting operation"); 1727 cERROR(1, "Error connecting to socket. Aborting operation");
1694 goto out_err_crypto_release; 1728 goto out_err_crypto_release;
@@ -1793,6 +1827,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1793{ 1827{
1794 int rc = -ENOMEM, xid; 1828 int rc = -ENOMEM, xid;
1795 struct cifsSesInfo *ses; 1829 struct cifsSesInfo *ses;
1830 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
1831 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
1796 1832
1797 xid = GetXid(); 1833 xid = GetXid();
1798 1834
@@ -1836,12 +1872,10 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1836 1872
1837 /* new SMB session uses our server ref */ 1873 /* new SMB session uses our server ref */
1838 ses->server = server; 1874 ses->server = server;
1839 if (server->addr.sockAddr6.sin6_family == AF_INET6) 1875 if (server->dstaddr.ss_family == AF_INET6)
1840 sprintf(ses->serverName, "%pI6", 1876 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
1841 &server->addr.sockAddr6.sin6_addr);
1842 else 1877 else
1843 sprintf(ses->serverName, "%pI4", 1878 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
1844 &server->addr.sockAddr.sin_addr.s_addr);
1845 1879
1846 if (volume_info->username) 1880 if (volume_info->username)
1847 strncpy(ses->userName, volume_info->username, 1881 strncpy(ses->userName, volume_info->username,
@@ -2136,19 +2170,106 @@ bind_socket(struct TCP_Server_Info *server)
2136} 2170}
2137 2171
2138static int 2172static int
2139ipv4_connect(struct TCP_Server_Info *server) 2173ip_rfc1001_connect(struct TCP_Server_Info *server)
2174{
2175 int rc = 0;
2176 /*
2177 * some servers require RFC1001 sessinit before sending
2178 * negprot - BB check reconnection in case where second
2179 * sessinit is sent but no second negprot
2180 */
2181 struct rfc1002_session_packet *ses_init_buf;
2182 struct smb_hdr *smb_buf;
2183 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2184 GFP_KERNEL);
2185 if (ses_init_buf) {
2186 ses_init_buf->trailer.session_req.called_len = 32;
2187
2188 if (server->server_RFC1001_name &&
2189 server->server_RFC1001_name[0] != 0)
2190 rfc1002mangle(ses_init_buf->trailer.
2191 session_req.called_name,
2192 server->server_RFC1001_name,
2193 RFC1001_NAME_LEN_WITH_NULL);
2194 else
2195 rfc1002mangle(ses_init_buf->trailer.
2196 session_req.called_name,
2197 DEFAULT_CIFS_CALLED_NAME,
2198 RFC1001_NAME_LEN_WITH_NULL);
2199
2200 ses_init_buf->trailer.session_req.calling_len = 32;
2201
2202 /*
2203 * calling name ends in null (byte 16) from old smb
2204 * convention.
2205 */
2206 if (server->workstation_RFC1001_name &&
2207 server->workstation_RFC1001_name[0] != 0)
2208 rfc1002mangle(ses_init_buf->trailer.
2209 session_req.calling_name,
2210 server->workstation_RFC1001_name,
2211 RFC1001_NAME_LEN_WITH_NULL);
2212 else
2213 rfc1002mangle(ses_init_buf->trailer.
2214 session_req.calling_name,
2215 "LINUX_CIFS_CLNT",
2216 RFC1001_NAME_LEN_WITH_NULL);
2217
2218 ses_init_buf->trailer.session_req.scope1 = 0;
2219 ses_init_buf->trailer.session_req.scope2 = 0;
2220 smb_buf = (struct smb_hdr *)ses_init_buf;
2221
2222 /* sizeof RFC1002_SESSION_REQUEST with no scope */
2223 smb_buf->smb_buf_length = 0x81000044;
2224 rc = smb_send(server, smb_buf, 0x44);
2225 kfree(ses_init_buf);
2226 /*
2227 * RFC1001 layer in at least one server
2228 * requires very short break before negprot
2229 * presumably because not expecting negprot
2230 * to follow so fast. This is a simple
2231 * solution that works without
2232 * complicating the code and causes no
2233 * significant slowing down on mount
2234 * for everyone else
2235 */
2236 usleep_range(1000, 2000);
2237 }
2238 /*
2239 * else the negprot may still work without this
2240 * even though malloc failed
2241 */
2242
2243 return rc;
2244}
2245
2246static int
2247generic_ip_connect(struct TCP_Server_Info *server)
2140{ 2248{
2141 int rc = 0; 2249 int rc = 0;
2142 int val; 2250 unsigned short int sport;
2143 bool connected = false; 2251 int slen, sfamily;
2144 __be16 orig_port = 0;
2145 struct socket *socket = server->ssocket; 2252 struct socket *socket = server->ssocket;
2253 struct sockaddr *saddr;
2254
2255 saddr = (struct sockaddr *) &server->dstaddr;
2256
2257 if (server->dstaddr.ss_family == AF_INET6) {
2258 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
2259 slen = sizeof(struct sockaddr_in6);
2260 sfamily = AF_INET6;
2261 } else {
2262 sport = ((struct sockaddr_in *) saddr)->sin_port;
2263 slen = sizeof(struct sockaddr_in);
2264 sfamily = AF_INET;
2265 }
2146 2266
2147 if (socket == NULL) { 2267 if (socket == NULL) {
2148 rc = sock_create_kern(PF_INET, SOCK_STREAM, 2268 rc = sock_create_kern(sfamily, SOCK_STREAM,
2149 IPPROTO_TCP, &socket); 2269 IPPROTO_TCP, &socket);
2150 if (rc < 0) { 2270 if (rc < 0) {
2151 cERROR(1, "Error %d creating socket", rc); 2271 cERROR(1, "Error %d creating socket", rc);
2272 server->ssocket = NULL;
2152 return rc; 2273 return rc;
2153 } 2274 }
2154 2275
@@ -2156,63 +2277,28 @@ ipv4_connect(struct TCP_Server_Info *server)
2156 cFYI(1, "Socket created"); 2277 cFYI(1, "Socket created");
2157 server->ssocket = socket; 2278 server->ssocket = socket;
2158 socket->sk->sk_allocation = GFP_NOFS; 2279 socket->sk->sk_allocation = GFP_NOFS;
2159 cifs_reclassify_socket4(socket); 2280 if (sfamily == AF_INET6)
2281 cifs_reclassify_socket6(socket);
2282 else
2283 cifs_reclassify_socket4(socket);
2160 } 2284 }
2161 2285
2162 rc = bind_socket(server); 2286 rc = bind_socket(server);
2163 if (rc < 0) 2287 if (rc < 0)
2164 return rc; 2288 return rc;
2165 2289
2166 /* user overrode default port */ 2290 rc = socket->ops->connect(socket, saddr, slen, 0);
2167 if (server->addr.sockAddr.sin_port) { 2291 if (rc < 0) {
2168 rc = socket->ops->connect(socket, (struct sockaddr *) 2292 cFYI(1, "Error %d connecting to server", rc);
2169 &server->addr.sockAddr,
2170 sizeof(struct sockaddr_in), 0);
2171 if (rc >= 0)
2172 connected = true;
2173 }
2174
2175 if (!connected) {
2176 /* save original port so we can retry user specified port
2177 later if fall back ports fail this time */
2178 orig_port = server->addr.sockAddr.sin_port;
2179
2180 /* do not retry on the same port we just failed on */
2181 if (server->addr.sockAddr.sin_port != htons(CIFS_PORT)) {
2182 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
2183 rc = socket->ops->connect(socket,
2184 (struct sockaddr *)
2185 &server->addr.sockAddr,
2186 sizeof(struct sockaddr_in), 0);
2187 if (rc >= 0)
2188 connected = true;
2189 }
2190 }
2191 if (!connected) {
2192 server->addr.sockAddr.sin_port = htons(RFC1001_PORT);
2193 rc = socket->ops->connect(socket, (struct sockaddr *)
2194 &server->addr.sockAddr,
2195 sizeof(struct sockaddr_in), 0);
2196 if (rc >= 0)
2197 connected = true;
2198 }
2199
2200 /* give up here - unless we want to retry on different
2201 protocol families some day */
2202 if (!connected) {
2203 if (orig_port)
2204 server->addr.sockAddr.sin_port = orig_port;
2205 cFYI(1, "Error %d connecting to server via ipv4", rc);
2206 sock_release(socket); 2293 sock_release(socket);
2207 server->ssocket = NULL; 2294 server->ssocket = NULL;
2208 return rc; 2295 return rc;
2209 } 2296 }
2210 2297
2211
2212 /* 2298 /*
2213 * Eventually check for other socket options to change from 2299 * Eventually check for other socket options to change from
2214 * the default. sock_setsockopt not used because it expects 2300 * the default. sock_setsockopt not used because it expects
2215 * user space buffer 2301 * user space buffer
2216 */ 2302 */
2217 socket->sk->sk_rcvtimeo = 7 * HZ; 2303 socket->sk->sk_rcvtimeo = 7 * HZ;
2218 socket->sk->sk_sndtimeo = 5 * HZ; 2304 socket->sk->sk_sndtimeo = 5 * HZ;
@@ -2226,7 +2312,7 @@ ipv4_connect(struct TCP_Server_Info *server)
2226 } 2312 }
2227 2313
2228 if (server->tcp_nodelay) { 2314 if (server->tcp_nodelay) {
2229 val = 1; 2315 int val = 1;
2230 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, 2316 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
2231 (char *)&val, sizeof(val)); 2317 (char *)&val, sizeof(val));
2232 if (rc) 2318 if (rc)
@@ -2237,161 +2323,39 @@ ipv4_connect(struct TCP_Server_Info *server)
2237 socket->sk->sk_sndbuf, 2323 socket->sk->sk_sndbuf,
2238 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); 2324 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
2239 2325
2240 /* send RFC1001 sessinit */ 2326 if (sport == htons(RFC1001_PORT))
2241 if (server->addr.sockAddr.sin_port == htons(RFC1001_PORT)) { 2327 rc = ip_rfc1001_connect(server);
2242 /* some servers require RFC1001 sessinit before sending
2243 negprot - BB check reconnection in case where second
2244 sessinit is sent but no second negprot */
2245 struct rfc1002_session_packet *ses_init_buf;
2246 struct smb_hdr *smb_buf;
2247 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2248 GFP_KERNEL);
2249 if (ses_init_buf) {
2250 ses_init_buf->trailer.session_req.called_len = 32;
2251 if (server->server_RFC1001_name &&
2252 server->server_RFC1001_name[0] != 0)
2253 rfc1002mangle(ses_init_buf->trailer.
2254 session_req.called_name,
2255 server->server_RFC1001_name,
2256 RFC1001_NAME_LEN_WITH_NULL);
2257 else
2258 rfc1002mangle(ses_init_buf->trailer.
2259 session_req.called_name,
2260 DEFAULT_CIFS_CALLED_NAME,
2261 RFC1001_NAME_LEN_WITH_NULL);
2262
2263 ses_init_buf->trailer.session_req.calling_len = 32;
2264
2265 /* calling name ends in null (byte 16) from old smb
2266 convention. */
2267 if (server->workstation_RFC1001_name &&
2268 server->workstation_RFC1001_name[0] != 0)
2269 rfc1002mangle(ses_init_buf->trailer.
2270 session_req.calling_name,
2271 server->workstation_RFC1001_name,
2272 RFC1001_NAME_LEN_WITH_NULL);
2273 else
2274 rfc1002mangle(ses_init_buf->trailer.
2275 session_req.calling_name,
2276 "LINUX_CIFS_CLNT",
2277 RFC1001_NAME_LEN_WITH_NULL);
2278
2279 ses_init_buf->trailer.session_req.scope1 = 0;
2280 ses_init_buf->trailer.session_req.scope2 = 0;
2281 smb_buf = (struct smb_hdr *)ses_init_buf;
2282 /* sizeof RFC1002_SESSION_REQUEST with no scope */
2283 smb_buf->smb_buf_length = 0x81000044;
2284 rc = smb_send(server, smb_buf, 0x44);
2285 kfree(ses_init_buf);
2286 msleep(1); /* RFC1001 layer in at least one server
2287 requires very short break before negprot
2288 presumably because not expecting negprot
2289 to follow so fast. This is a simple
2290 solution that works without
2291 complicating the code and causes no
2292 significant slowing down on mount
2293 for everyone else */
2294 }
2295 /* else the negprot may still work without this
2296 even though malloc failed */
2297
2298 }
2299 2328
2300 return rc; 2329 return rc;
2301} 2330}
2302 2331
2303static int 2332static int
2304ipv6_connect(struct TCP_Server_Info *server) 2333ip_connect(struct TCP_Server_Info *server)
2305{ 2334{
2306 int rc = 0; 2335 unsigned short int *sport;
2307 int val; 2336 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
2308 bool connected = false; 2337 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2309 __be16 orig_port = 0;
2310 struct socket *socket = server->ssocket;
2311 2338
2312 if (socket == NULL) { 2339 if (server->dstaddr.ss_family == AF_INET6)
2313 rc = sock_create_kern(PF_INET6, SOCK_STREAM, 2340 sport = &addr6->sin6_port;
2314 IPPROTO_TCP, &socket); 2341 else
2315 if (rc < 0) { 2342 sport = &addr->sin_port;
2316 cERROR(1, "Error %d creating ipv6 socket", rc);
2317 socket = NULL;
2318 return rc;
2319 }
2320 2343
2321 /* BB other socket options to set KEEPALIVE, NODELAY? */ 2344 if (*sport == 0) {
2322 cFYI(1, "ipv6 Socket created"); 2345 int rc;
2323 server->ssocket = socket;
2324 socket->sk->sk_allocation = GFP_NOFS;
2325 cifs_reclassify_socket6(socket);
2326 }
2327 2346
2328 rc = bind_socket(server); 2347 /* try with 445 port at first */
2329 if (rc < 0) 2348 *sport = htons(CIFS_PORT);
2330 return rc;
2331 2349
2332 /* user overrode default port */ 2350 rc = generic_ip_connect(server);
2333 if (server->addr.sockAddr6.sin6_port) {
2334 rc = socket->ops->connect(socket,
2335 (struct sockaddr *) &server->addr.sockAddr6,
2336 sizeof(struct sockaddr_in6), 0);
2337 if (rc >= 0)
2338 connected = true;
2339 }
2340
2341 if (!connected) {
2342 /* save original port so we can retry user specified port
2343 later if fall back ports fail this time */
2344
2345 orig_port = server->addr.sockAddr6.sin6_port;
2346 /* do not retry on the same port we just failed on */
2347 if (server->addr.sockAddr6.sin6_port != htons(CIFS_PORT)) {
2348 server->addr.sockAddr6.sin6_port = htons(CIFS_PORT);
2349 rc = socket->ops->connect(socket, (struct sockaddr *)
2350 &server->addr.sockAddr6,
2351 sizeof(struct sockaddr_in6), 0);
2352 if (rc >= 0)
2353 connected = true;
2354 }
2355 }
2356 if (!connected) {
2357 server->addr.sockAddr6.sin6_port = htons(RFC1001_PORT);
2358 rc = socket->ops->connect(socket, (struct sockaddr *)
2359 &server->addr.sockAddr6,
2360 sizeof(struct sockaddr_in6), 0);
2361 if (rc >= 0) 2351 if (rc >= 0)
2362 connected = true; 2352 return rc;
2363 }
2364
2365 /* give up here - unless we want to retry on different
2366 protocol families some day */
2367 if (!connected) {
2368 if (orig_port)
2369 server->addr.sockAddr6.sin6_port = orig_port;
2370 cFYI(1, "Error %d connecting to server via ipv6", rc);
2371 sock_release(socket);
2372 server->ssocket = NULL;
2373 return rc;
2374 }
2375
2376 /*
2377 * Eventually check for other socket options to change from
2378 * the default. sock_setsockopt not used because it expects
2379 * user space buffer
2380 */
2381 socket->sk->sk_rcvtimeo = 7 * HZ;
2382 socket->sk->sk_sndtimeo = 5 * HZ;
2383 2353
2384 if (server->tcp_nodelay) { 2354 /* if it failed, try with 139 port */
2385 val = 1; 2355 *sport = htons(RFC1001_PORT);
2386 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
2387 (char *)&val, sizeof(val));
2388 if (rc)
2389 cFYI(1, "set TCP_NODELAY socket option error %d", rc);
2390 } 2356 }
2391 2357
2392 server->ssocket = socket; 2358 return generic_ip_connect(server);
2393
2394 return rc;
2395} 2359}
2396 2360
2397void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, 2361void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index db2a58c00f7b..2e773825835e 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -293,10 +293,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
293 args.uid = NO_CHANGE_64; 293 args.uid = NO_CHANGE_64;
294 args.gid = NO_CHANGE_64; 294 args.gid = NO_CHANGE_64;
295 } 295 }
296 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, 296 CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle,
297 cifs_sb->local_nls, 297 current->tgid);
298 cifs_sb->mnt_cifs_flags &
299 CIFS_MOUNT_MAP_SPECIAL_CHR);
300 } else { 298 } else {
301 /* BB implement mode setting via Windows security 299 /* BB implement mode setting via Windows security
302 descriptors e.g. */ 300 descriptors e.g. */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5a28660ca2b5..d843631c028d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -104,53 +104,6 @@ static inline int cifs_get_disposition(unsigned int flags)
104 return FILE_OPEN; 104 return FILE_OPEN;
105} 105}
106 106
107static inline int cifs_open_inode_helper(struct inode *inode,
108 struct cifsTconInfo *pTcon, __u32 oplock, FILE_ALL_INFO *buf,
109 char *full_path, int xid)
110{
111 struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
112 struct timespec temp;
113 int rc;
114
115 if (pCifsInode->clientCanCacheRead) {
116 /* we have the inode open somewhere else
117 no need to discard cache data */
118 goto client_can_cache;
119 }
120
121 /* BB need same check in cifs_create too? */
122 /* if not oplocked, invalidate inode pages if mtime or file
123 size changed */
124 temp = cifs_NTtimeToUnix(buf->LastWriteTime);
125 if (timespec_equal(&inode->i_mtime, &temp) &&
126 (inode->i_size ==
127 (loff_t)le64_to_cpu(buf->EndOfFile))) {
128 cFYI(1, "inode unchanged on server");
129 } else {
130 if (inode->i_mapping) {
131 /* BB no need to lock inode until after invalidate
132 since namei code should already have it locked? */
133 rc = filemap_write_and_wait(inode->i_mapping);
134 mapping_set_error(inode->i_mapping, rc);
135 }
136 cFYI(1, "invalidating remote inode since open detected it "
137 "changed");
138 invalidate_remote_inode(inode);
139 }
140
141client_can_cache:
142 if (pTcon->unix_ext)
143 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
144 xid);
145 else
146 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
147 xid, NULL);
148
149 cifs_set_oplock_level(pCifsInode, oplock);
150
151 return rc;
152}
153
154int cifs_posix_open(char *full_path, struct inode **pinode, 107int cifs_posix_open(char *full_path, struct inode **pinode,
155 struct super_block *sb, int mode, unsigned int f_flags, 108 struct super_block *sb, int mode, unsigned int f_flags,
156 __u32 *poplock, __u16 *pnetfid, int xid) 109 __u32 *poplock, __u16 *pnetfid, int xid)
@@ -213,6 +166,76 @@ posix_open_ret:
213 return rc; 166 return rc;
214} 167}
215 168
169static int
170cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
171 struct cifsTconInfo *tcon, unsigned int f_flags, __u32 *poplock,
172 __u16 *pnetfid, int xid)
173{
174 int rc;
175 int desiredAccess;
176 int disposition;
177 FILE_ALL_INFO *buf;
178
179 desiredAccess = cifs_convert_flags(f_flags);
180
181/*********************************************************************
182 * open flag mapping table:
183 *
184 * POSIX Flag CIFS Disposition
185 * ---------- ----------------
186 * O_CREAT FILE_OPEN_IF
187 * O_CREAT | O_EXCL FILE_CREATE
188 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
189 * O_TRUNC FILE_OVERWRITE
190 * none of the above FILE_OPEN
191 *
192 * Note that there is not a direct match between disposition
193 * FILE_SUPERSEDE (ie create whether or not file exists although
194 * O_CREAT | O_TRUNC is similar but truncates the existing
195 * file rather than creating a new file as FILE_SUPERSEDE does
196 * (which uses the attributes / metadata passed in on open call)
197 *?
198 *? O_SYNC is a reasonable match to CIFS writethrough flag
199 *? and the read write flags match reasonably. O_LARGEFILE
200 *? is irrelevant because largefile support is always used
201 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
202 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
203 *********************************************************************/
204
205 disposition = cifs_get_disposition(f_flags);
206
207 /* BB pass O_SYNC flag through on file attributes .. BB */
208
209 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
210 if (!buf)
211 return -ENOMEM;
212
213 if (tcon->ses->capabilities & CAP_NT_SMBS)
214 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
215 desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
216 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
217 & CIFS_MOUNT_MAP_SPECIAL_CHR);
218 else
219 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
220 desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
221 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
222 & CIFS_MOUNT_MAP_SPECIAL_CHR);
223
224 if (rc)
225 goto out;
226
227 if (tcon->unix_ext)
228 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
229 xid);
230 else
231 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
232 xid, pnetfid);
233
234out:
235 kfree(buf);
236 return rc;
237}
238
216struct cifsFileInfo * 239struct cifsFileInfo *
217cifs_new_fileinfo(__u16 fileHandle, struct file *file, 240cifs_new_fileinfo(__u16 fileHandle, struct file *file,
218 struct tcon_link *tlink, __u32 oplock) 241 struct tcon_link *tlink, __u32 oplock)
@@ -317,10 +340,8 @@ int cifs_open(struct inode *inode, struct file *file)
317 struct cifsFileInfo *pCifsFile = NULL; 340 struct cifsFileInfo *pCifsFile = NULL;
318 struct cifsInodeInfo *pCifsInode; 341 struct cifsInodeInfo *pCifsInode;
319 char *full_path = NULL; 342 char *full_path = NULL;
320 int desiredAccess; 343 bool posix_open_ok = false;
321 int disposition;
322 __u16 netfid; 344 __u16 netfid;
323 FILE_ALL_INFO *buf = NULL;
324 345
325 xid = GetXid(); 346 xid = GetXid();
326 347
@@ -358,17 +379,7 @@ int cifs_open(struct inode *inode, struct file *file)
358 file->f_flags, &oplock, &netfid, xid); 379 file->f_flags, &oplock, &netfid, xid);
359 if (rc == 0) { 380 if (rc == 0) {
360 cFYI(1, "posix open succeeded"); 381 cFYI(1, "posix open succeeded");
361 382 posix_open_ok = true;
362 pCifsFile = cifs_new_fileinfo(netfid, file, tlink,
363 oplock);
364 if (pCifsFile == NULL) {
365 CIFSSMBClose(xid, tcon, netfid);
366 rc = -ENOMEM;
367 }
368
369 cifs_fscache_set_inode_cookie(inode, file);
370
371 goto out;
372 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { 383 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
373 if (tcon->ses->serverNOS) 384 if (tcon->ses->serverNOS)
374 cERROR(1, "server %s of type %s returned" 385 cERROR(1, "server %s of type %s returned"
@@ -385,103 +396,39 @@ int cifs_open(struct inode *inode, struct file *file)
385 or DFS errors */ 396 or DFS errors */
386 } 397 }
387 398
388 desiredAccess = cifs_convert_flags(file->f_flags); 399 if (!posix_open_ok) {
389 400 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
390/********************************************************************* 401 file->f_flags, &oplock, &netfid, xid);
391 * open flag mapping table: 402 if (rc)
392 * 403 goto out;
393 * POSIX Flag CIFS Disposition
394 * ---------- ----------------
395 * O_CREAT FILE_OPEN_IF
396 * O_CREAT | O_EXCL FILE_CREATE
397 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
398 * O_TRUNC FILE_OVERWRITE
399 * none of the above FILE_OPEN
400 *
401 * Note that there is not a direct match between disposition
402 * FILE_SUPERSEDE (ie create whether or not file exists although
403 * O_CREAT | O_TRUNC is similar but truncates the existing
404 * file rather than creating a new file as FILE_SUPERSEDE does
405 * (which uses the attributes / metadata passed in on open call)
406 *?
407 *? O_SYNC is a reasonable match to CIFS writethrough flag
408 *? and the read write flags match reasonably. O_LARGEFILE
409 *? is irrelevant because largefile support is always used
410 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
411 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
412 *********************************************************************/
413
414 disposition = cifs_get_disposition(file->f_flags);
415
416 /* BB pass O_SYNC flag through on file attributes .. BB */
417
418 /* Also refresh inode by passing in file_info buf returned by SMBOpen
419 and calling get_inode_info with returned buf (at least helps
420 non-Unix server case) */
421
422 /* BB we can not do this if this is the second open of a file
423 and the first handle has writebehind data, we might be
424 able to simply do a filemap_fdatawrite/filemap_fdatawait first */
425 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
426 if (!buf) {
427 rc = -ENOMEM;
428 goto out;
429 }
430
431 if (tcon->ses->capabilities & CAP_NT_SMBS)
432 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
433 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
434 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
435 & CIFS_MOUNT_MAP_SPECIAL_CHR);
436 else
437 rc = -EIO; /* no NT SMB support fall into legacy open below */
438
439 if (rc == -EIO) {
440 /* Old server, try legacy style OpenX */
441 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
442 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
443 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
444 & CIFS_MOUNT_MAP_SPECIAL_CHR);
445 }
446 if (rc) {
447 cFYI(1, "cifs_open returned 0x%x", rc);
448 goto out;
449 } 404 }
450 405
451 rc = cifs_open_inode_helper(inode, tcon, oplock, buf, full_path, xid);
452 if (rc != 0)
453 goto out;
454
455 pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock); 406 pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
456 if (pCifsFile == NULL) { 407 if (pCifsFile == NULL) {
408 CIFSSMBClose(xid, tcon, netfid);
457 rc = -ENOMEM; 409 rc = -ENOMEM;
458 goto out; 410 goto out;
459 } 411 }
460 412
461 cifs_fscache_set_inode_cookie(inode, file); 413 cifs_fscache_set_inode_cookie(inode, file);
462 414
463 if (oplock & CIFS_CREATE_ACTION) { 415 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
464 /* time to set mode which we can not set earlier due to 416 /* time to set mode which we can not set earlier due to
465 problems creating new read-only files */ 417 problems creating new read-only files */
466 if (tcon->unix_ext) { 418 struct cifs_unix_set_info_args args = {
467 struct cifs_unix_set_info_args args = { 419 .mode = inode->i_mode,
468 .mode = inode->i_mode, 420 .uid = NO_CHANGE_64,
469 .uid = NO_CHANGE_64, 421 .gid = NO_CHANGE_64,
470 .gid = NO_CHANGE_64, 422 .ctime = NO_CHANGE_64,
471 .ctime = NO_CHANGE_64, 423 .atime = NO_CHANGE_64,
472 .atime = NO_CHANGE_64, 424 .mtime = NO_CHANGE_64,
473 .mtime = NO_CHANGE_64, 425 .device = 0,
474 .device = 0, 426 };
475 }; 427 CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid,
476 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, 428 pCifsFile->pid);
477 cifs_sb->local_nls,
478 cifs_sb->mnt_cifs_flags &
479 CIFS_MOUNT_MAP_SPECIAL_CHR);
480 }
481 } 429 }
482 430
483out: 431out:
484 kfree(buf);
485 kfree(full_path); 432 kfree(full_path);
486 FreeXid(xid); 433 FreeXid(xid);
487 cifs_put_tlink(tlink); 434 cifs_put_tlink(tlink);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a853a89857a5..0c7e36910e31 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -518,6 +518,7 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
518 518
519 fattr->cf_eof = le64_to_cpu(info->EndOfFile); 519 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
520 fattr->cf_bytes = le64_to_cpu(info->AllocationSize); 520 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
521 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
521 522
522 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { 523 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
523 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; 524 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
@@ -779,6 +780,10 @@ cifs_find_inode(struct inode *inode, void *opaque)
779 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) 780 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
780 return 0; 781 return 0;
781 782
783 /* use createtime like an i_generation field */
784 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
785 return 0;
786
782 /* don't match inode of different type */ 787 /* don't match inode of different type */
783 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT)) 788 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
784 return 0; 789 return 0;
@@ -796,6 +801,7 @@ cifs_init_inode(struct inode *inode, void *opaque)
796 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; 801 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
797 802
798 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; 803 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
804 CIFS_I(inode)->createtime = fattr->cf_createtime;
799 return 0; 805 return 0;
800} 806}
801 807
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index ec5b68e3b928..76b1b37c9e6b 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -160,6 +160,7 @@ cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
160 fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); 160 fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
161 fattr->cf_eof = le64_to_cpu(info->EndOfFile); 161 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
162 fattr->cf_bytes = le64_to_cpu(info->AllocationSize); 162 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
163 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
163 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); 164 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
164 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); 165 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
165 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); 166 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7b01d3f6eed6..eb746486e49e 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -420,7 +420,6 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
420 return 0; 420 return 0;
421} 421}
422 422
423#ifdef CONFIG_CIFS_EXPERIMENTAL
424/* BB Move to ntlmssp.c eventually */ 423/* BB Move to ntlmssp.c eventually */
425 424
426/* We do not malloc the blob, it is passed in pbuffer, because 425/* We do not malloc the blob, it is passed in pbuffer, because
@@ -431,13 +430,14 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
431 NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer; 430 NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
432 __u32 flags; 431 __u32 flags;
433 432
433 memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
434 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 434 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
435 sec_blob->MessageType = NtLmNegotiate; 435 sec_blob->MessageType = NtLmNegotiate;
436 436
437 /* BB is NTLMV2 session security format easier to use here? */ 437 /* BB is NTLMV2 session security format easier to use here? */
438 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | 438 flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
439 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 439 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
440 NTLMSSP_NEGOTIATE_NTLM; 440 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC;
441 if (ses->server->secMode & 441 if (ses->server->secMode &
442 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { 442 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
443 flags |= NTLMSSP_NEGOTIATE_SIGN; 443 flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -446,7 +446,7 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
446 NTLMSSP_NEGOTIATE_EXTENDED_SEC; 446 NTLMSSP_NEGOTIATE_EXTENDED_SEC;
447 } 447 }
448 448
449 sec_blob->NegotiateFlags |= cpu_to_le32(flags); 449 sec_blob->NegotiateFlags = cpu_to_le32(flags);
450 450
451 sec_blob->WorkstationName.BufferOffset = 0; 451 sec_blob->WorkstationName.BufferOffset = 0;
452 sec_blob->WorkstationName.Length = 0; 452 sec_blob->WorkstationName.Length = 0;
@@ -477,7 +477,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
477 flags = NTLMSSP_NEGOTIATE_56 | 477 flags = NTLMSSP_NEGOTIATE_56 |
478 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | 478 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
479 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 479 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
480 NTLMSSP_NEGOTIATE_NTLM; 480 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC;
481 if (ses->server->secMode & 481 if (ses->server->secMode &
482 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 482 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
483 flags |= NTLMSSP_NEGOTIATE_SIGN; 483 flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -485,7 +485,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
485 flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 485 flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
486 486
487 tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); 487 tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE);
488 sec_blob->NegotiateFlags |= cpu_to_le32(flags); 488 sec_blob->NegotiateFlags = cpu_to_le32(flags);
489 489
490 sec_blob->LmChallengeResponse.BufferOffset = 490 sec_blob->LmChallengeResponse.BufferOffset =
491 cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE)); 491 cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
@@ -544,8 +544,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
544 sec_blob->WorkstationName.MaximumLength = 0; 544 sec_blob->WorkstationName.MaximumLength = 0;
545 tmp += 2; 545 tmp += 2;
546 546
547 if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && 547 if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) ||
548 !calc_seckey(ses)) { 548 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
549 && !calc_seckey(ses)) {
549 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); 550 memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
550 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); 551 sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
551 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); 552 sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
@@ -563,17 +564,6 @@ setup_ntlmv2_ret:
563 return rc; 564 return rc;
564} 565}
565 566
566
567static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
568 struct cifsSesInfo *ses)
569{
570 build_ntlmssp_negotiate_blob(&pSMB->req.SecurityBlob[0], ses);
571 pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
572
573 return;
574}
575#endif
576
577int 567int
578CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, 568CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
579 const struct nls_table *nls_cp) 569 const struct nls_table *nls_cp)
@@ -814,71 +804,70 @@ ssetup_ntlmssp_authenticate:
814 rc = -ENOSYS; 804 rc = -ENOSYS;
815 goto ssetup_exit; 805 goto ssetup_exit;
816#endif /* CONFIG_CIFS_UPCALL */ 806#endif /* CONFIG_CIFS_UPCALL */
817 } else { 807 } else if (type == RawNTLMSSP) {
818#ifdef CONFIG_CIFS_EXPERIMENTAL 808 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
819 if (type == RawNTLMSSP) { 809 cERROR(1, "NTLMSSP requires Unicode support");
820 if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { 810 rc = -ENOSYS;
821 cERROR(1, "NTLMSSP requires Unicode support"); 811 goto ssetup_exit;
822 rc = -ENOSYS; 812 }
813
814 cFYI(1, "ntlmssp session setup phase %d", phase);
815 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
816 capabilities |= CAP_EXTENDED_SECURITY;
817 pSMB->req.Capabilities |= cpu_to_le32(capabilities);
818 switch(phase) {
819 case NtLmNegotiate:
820 build_ntlmssp_negotiate_blob(
821 pSMB->req.SecurityBlob, ses);
822 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
823 iov[1].iov_base = pSMB->req.SecurityBlob;
824 pSMB->req.SecurityBlobLength =
825 cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
826 break;
827 case NtLmAuthenticate:
828 /*
829 * 5 is an empirical value, large enough to hold
830 * authenticate message plus max 10 of av paris,
831 * domain, user, workstation names, flags, etc.
832 */
833 ntlmsspblob = kzalloc(
834 5*sizeof(struct _AUTHENTICATE_MESSAGE),
835 GFP_KERNEL);
836 if (!ntlmsspblob) {
837 cERROR(1, "Can't allocate NTLMSSP blob");
838 rc = -ENOMEM;
823 goto ssetup_exit; 839 goto ssetup_exit;
824 } 840 }
825 841
826 cFYI(1, "ntlmssp session setup phase %d", phase); 842 rc = build_ntlmssp_auth_blob(ntlmsspblob,
827 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; 843 &blob_len, ses, nls_cp);
828 capabilities |= CAP_EXTENDED_SECURITY; 844 if (rc)
829 pSMB->req.Capabilities |= cpu_to_le32(capabilities);
830 if (phase == NtLmNegotiate) {
831 setup_ntlmssp_neg_req(pSMB, ses);
832 iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
833 iov[1].iov_base = &pSMB->req.SecurityBlob[0];
834 } else if (phase == NtLmAuthenticate) {
835 /* 5 is an empirical value, large enought to
836 * hold authenticate message, max 10 of
837 * av paris, doamin,user,workstation mames,
838 * flags etc..
839 */
840 ntlmsspblob = kmalloc(
841 5*sizeof(struct _AUTHENTICATE_MESSAGE),
842 GFP_KERNEL);
843 if (!ntlmsspblob) {
844 cERROR(1, "Can't allocate NTLMSSP");
845 rc = -ENOMEM;
846 goto ssetup_exit;
847 }
848
849 rc = build_ntlmssp_auth_blob(ntlmsspblob,
850 &blob_len, ses, nls_cp);
851 if (rc)
852 goto ssetup_exit;
853 iov[1].iov_len = blob_len;
854 iov[1].iov_base = ntlmsspblob;
855 pSMB->req.SecurityBlobLength =
856 cpu_to_le16(blob_len);
857 /* Make sure that we tell the server that we
858 are using the uid that it just gave us back
859 on the response (challenge) */
860 smb_buf->Uid = ses->Suid;
861 } else {
862 cERROR(1, "invalid phase %d", phase);
863 rc = -ENOSYS;
864 goto ssetup_exit; 845 goto ssetup_exit;
865 } 846 iov[1].iov_len = blob_len;
866 /* unicode strings must be word aligned */ 847 iov[1].iov_base = ntlmsspblob;
867 if ((iov[0].iov_len + iov[1].iov_len) % 2) { 848 pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
868 *bcc_ptr = 0; 849 /*
869 bcc_ptr++; 850 * Make sure that we tell the server that we are using
870 } 851 * the uid that it just gave us back on the response
871 unicode_oslm_strings(&bcc_ptr, nls_cp); 852 * (challenge)
872 } else { 853 */
873 cERROR(1, "secType %d not supported!", type); 854 smb_buf->Uid = ses->Suid;
855 break;
856 default:
857 cERROR(1, "invalid phase %d", phase);
874 rc = -ENOSYS; 858 rc = -ENOSYS;
875 goto ssetup_exit; 859 goto ssetup_exit;
876 } 860 }
877#else 861 /* unicode strings must be word aligned */
862 if ((iov[0].iov_len + iov[1].iov_len) % 2) {
863 *bcc_ptr = 0;
864 bcc_ptr++;
865 }
866 unicode_oslm_strings(&bcc_ptr, nls_cp);
867 } else {
878 cERROR(1, "secType %d not supported!", type); 868 cERROR(1, "secType %d not supported!", type);
879 rc = -ENOSYS; 869 rc = -ENOSYS;
880 goto ssetup_exit; 870 goto ssetup_exit;
881#endif
882 } 871 }
883 872
884 iov[2].iov_base = str_area; 873 iov[2].iov_base = str_area;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index e0588cdf4cc5..59ca81b16919 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -119,7 +119,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
119 if (ssocket == NULL) 119 if (ssocket == NULL)
120 return -ENOTSOCK; /* BB eventually add reconnect code here */ 120 return -ENOTSOCK; /* BB eventually add reconnect code here */
121 121
122 smb_msg.msg_name = (struct sockaddr *) &server->addr.sockAddr; 122 smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
123 smb_msg.msg_namelen = sizeof(struct sockaddr); 123 smb_msg.msg_namelen = sizeof(struct sockaddr);
124 smb_msg.msg_control = NULL; 124 smb_msg.msg_control = NULL;
125 smb_msg.msg_controllen = 0; 125 smb_msg.msg_controllen = 0;