diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-10 10:47:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-10 10:47:11 -0500 |
commit | f3ea597251ac859a1c0e7b9e266877f1ac828009 (patch) | |
tree | 4cd4dd499d36fbb0699e854b038e2260cff7d5cd /fs | |
parent | f9f265f35578c5fb2266d0e2a1aa5b57f6fdb36a (diff) | |
parent | 20054bd65703f7504a9daceabc2a060828fde36c (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.c | 16 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 22 | ||||
-rw-r--r-- | fs/cifs/cifs_spnego.c | 10 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 6 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 17 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 9 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 5 | ||||
-rw-r--r-- | fs/cifs/connect.c | 462 | ||||
-rw-r--r-- | fs/cifs/dir.c | 6 | ||||
-rw-r--r-- | fs/cifs/file.c | 233 | ||||
-rw-r--r-- | fs/cifs/inode.c | 6 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 1 | ||||
-rw-r--r-- | fs/cifs/sess.c | 135 | ||||
-rw-r--r-- | fs/cifs/transport.c | 2 |
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 * | |||
98 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | 98 | cifs_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 */ | ||
75 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | 76 | int 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 */ | ||
152 | int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | 152 | int 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) | |||
361 | static void | 363 | static void |
362 | cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) | 364 | cifs_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 | ||
118 | static int ipv4_connect(struct TCP_Server_Info *server); | 118 | static int ip_connect(struct TCP_Server_Info *server); |
119 | static int ipv6_connect(struct TCP_Server_Info *server); | 119 | static int generic_ip_connect(struct TCP_Server_Info *server); |
120 | static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); | 120 | static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); |
121 | static void cifs_prune_tlinks(struct work_struct *work); | 121 | static 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 | */ | ||
1458 | static bool | ||
1459 | match_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 | ||
1458 | static bool | 1488 | static bool |
1459 | match_address(struct TCP_Server_Info *server, struct sockaddr *addr, | 1489 | match_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 | ||
2138 | static int | 2172 | static int |
2139 | ipv4_connect(struct TCP_Server_Info *server) | 2173 | ip_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 | |||
2246 | static int | ||
2247 | generic_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 | ||
2303 | static int | 2332 | static int |
2304 | ipv6_connect(struct TCP_Server_Info *server) | 2333 | ip_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 | ||
2397 | void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, | 2361 | void 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 | ||
107 | static 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 | |||
141 | client_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 | |||
154 | int cifs_posix_open(char *full_path, struct inode **pinode, | 107 | int 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 | ||
169 | static int | ||
170 | cifs_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 | |||
234 | out: | ||
235 | kfree(buf); | ||
236 | return rc; | ||
237 | } | ||
238 | |||
216 | struct cifsFileInfo * | 239 | struct cifsFileInfo * |
217 | cifs_new_fileinfo(__u16 fileHandle, struct file *file, | 240 | cifs_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 | ||
483 | out: | 431 | out: |
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 | |||
567 | static 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 | |||
577 | int | 567 | int |
578 | CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, | 568 | CIFS_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; |