aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Shilovsky <piastryyy@gmail.com>2010-12-13 11:08:35 -0500
committerSteve French <sfrench@us.ibm.com>2011-01-06 14:07:53 -0500
commita9f1b85e5ba80519dea6974e3574fa7a30cc5e29 (patch)
tree255a962ea1d02110c5b31ebb981ce1f588960688
parentdf8fbc241aa3c451248b1f19fff3a3f604b107f9 (diff)
CIFS: Simplify ipv*_connect functions into one (try #4)
Make connect logic more ip-protocol independent and move RFC1001 stuff into a separate function. Also replace union addr in TCP_Server_Info structure with sockaddr_storage. Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com> Reviewed-and-Tested-by: Jeff Layton <jlayton@samba.org> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/cache.c16
-rw-r--r--fs/cifs/cifs_spnego.c10
-rw-r--r--fs/cifs/cifsfs.c15
-rw-r--r--fs/cifs/cifsglob.h5
-rw-r--r--fs/cifs/connect.c383
-rw-r--r--fs/cifs/transport.c2
6 files changed, 184 insertions, 247 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_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/cifsfs.c b/fs/cifs/cifsfs.c
index 3936aa7f2c22..9df5c0b94d0f 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -351,18 +351,19 @@ cifs_evict_inode(struct inode *inode)
351static void 351static void
352cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) 352cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
353{ 353{
354 struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
355 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
356
354 seq_printf(s, ",addr="); 357 seq_printf(s, ",addr=");
355 358
356 switch (server->addr.sockAddr.sin_family) { 359 switch (server->dstaddr.ss_family) {
357 case AF_INET: 360 case AF_INET:
358 seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr); 361 seq_printf(s, "%pI4", &sa->sin_addr.s_addr);
359 break; 362 break;
360 case AF_INET6: 363 case AF_INET6:
361 seq_printf(s, "%pI6", 364 seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr);
362 &server->addr.sockAddr6.sin6_addr.s6_addr); 365 if (sa6->sin6_scope_id)
363 if (server->addr.sockAddr6.sin6_scope_id) 366 seq_printf(s, "%%%u", sa6->sin6_scope_id);
364 seq_printf(s, "%%%u",
365 server->addr.sockAddr6.sin6_scope_id);
366 break; 367 break;
367 default: 368 default:
368 seq_printf(s, "(unknown)"); 369 seq_printf(s, "(unknown)");
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7136c0c3e2f9..dfd2d46275ab 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*/
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index cc1a8604a790..b90c7411f4f0 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -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);
@@ -1459,30 +1458,37 @@ static bool
1459match_address(struct TCP_Server_Info *server, struct sockaddr *addr, 1458match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
1460 struct sockaddr *srcaddr) 1459 struct sockaddr *srcaddr)
1461{ 1460{
1462 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1463 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1464
1465 switch (addr->sa_family) { 1461 switch (addr->sa_family) {
1466 case AF_INET: 1462 case AF_INET: {
1467 if (addr4->sin_addr.s_addr != 1463 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1468 server->addr.sockAddr.sin_addr.s_addr) 1464 struct sockaddr_in *srv_addr4 =
1465 (struct sockaddr_in *)&server->dstaddr;
1466
1467 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
1469 return false; 1468 return false;
1470 if (addr4->sin_port && 1469 if (addr4->sin_port && addr4->sin_port != srv_addr4->sin_port)
1471 addr4->sin_port != server->addr.sockAddr.sin_port)
1472 return false; 1470 return false;
1473 break; 1471 break;
1474 case AF_INET6: 1472 }
1473 case AF_INET6: {
1474 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1475 struct sockaddr_in6 *srv_addr6 =
1476 (struct sockaddr_in6 *)&server->dstaddr;
1477
1475 if (!ipv6_addr_equal(&addr6->sin6_addr, 1478 if (!ipv6_addr_equal(&addr6->sin6_addr,
1476 &server->addr.sockAddr6.sin6_addr)) 1479 &srv_addr6->sin6_addr))
1477 return false; 1480 return false;
1478 if (addr6->sin6_scope_id != 1481 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
1479 server->addr.sockAddr6.sin6_scope_id)
1480 return false; 1482 return false;
1481 if (addr6->sin6_port && 1483 if (addr6->sin6_port &&
1482 addr6->sin6_port != server->addr.sockAddr6.sin6_port) 1484 addr6->sin6_port != srv_addr6->sin6_port)
1483 return false; 1485 return false;
1484 break; 1486 break;
1485 } 1487 }
1488 default:
1489 WARN_ON(1);
1490 return false; /* don't expect to be here */
1491 }
1486 1492
1487 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr)) 1493 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
1488 return false; 1494 return false;
@@ -1681,14 +1687,13 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1681 cFYI(1, "attempting ipv6 connect"); 1687 cFYI(1, "attempting ipv6 connect");
1682 /* BB should we allow ipv6 on port 139? */ 1688 /* BB should we allow ipv6 on port 139? */
1683 /* other OS never observed in Wild doing 139 with v6 */ 1689 /* other OS never observed in Wild doing 139 with v6 */
1684 memcpy(&tcp_ses->addr.sockAddr6, sin_server6, 1690 memcpy(&tcp_ses->dstaddr, sin_server6,
1685 sizeof(struct sockaddr_in6)); 1691 sizeof(struct sockaddr_in6));
1686 rc = ipv6_connect(tcp_ses); 1692 } else
1687 } else { 1693 memcpy(&tcp_ses->dstaddr, sin_server,
1688 memcpy(&tcp_ses->addr.sockAddr, sin_server, 1694 sizeof(struct sockaddr_in));
1689 sizeof(struct sockaddr_in)); 1695
1690 rc = ipv4_connect(tcp_ses); 1696 rc = ip_connect(tcp_ses);
1691 }
1692 if (rc < 0) { 1697 if (rc < 0) {
1693 cERROR(1, "Error connecting to socket. Aborting operation"); 1698 cERROR(1, "Error connecting to socket. Aborting operation");
1694 goto out_err_crypto_release; 1699 goto out_err_crypto_release;
@@ -1793,6 +1798,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1793{ 1798{
1794 int rc = -ENOMEM, xid; 1799 int rc = -ENOMEM, xid;
1795 struct cifsSesInfo *ses; 1800 struct cifsSesInfo *ses;
1801 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
1802 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
1796 1803
1797 xid = GetXid(); 1804 xid = GetXid();
1798 1805
@@ -1836,12 +1843,10 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
1836 1843
1837 /* new SMB session uses our server ref */ 1844 /* new SMB session uses our server ref */
1838 ses->server = server; 1845 ses->server = server;
1839 if (server->addr.sockAddr6.sin6_family == AF_INET6) 1846 if (server->dstaddr.ss_family == AF_INET6)
1840 sprintf(ses->serverName, "%pI6", 1847 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
1841 &server->addr.sockAddr6.sin6_addr);
1842 else 1848 else
1843 sprintf(ses->serverName, "%pI4", 1849 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
1844 &server->addr.sockAddr.sin_addr.s_addr);
1845 1850
1846 if (volume_info->username) 1851 if (volume_info->username)
1847 strncpy(ses->userName, volume_info->username, 1852 strncpy(ses->userName, volume_info->username,
@@ -2136,19 +2141,106 @@ bind_socket(struct TCP_Server_Info *server)
2136} 2141}
2137 2142
2138static int 2143static int
2139ipv4_connect(struct TCP_Server_Info *server) 2144ip_rfc1001_connect(struct TCP_Server_Info *server)
2140{ 2145{
2141 int rc = 0; 2146 int rc = 0;
2142 int val; 2147 /*
2143 bool connected = false; 2148 * some servers require RFC1001 sessinit before sending
2144 __be16 orig_port = 0; 2149 * negprot - BB check reconnection in case where second
2150 * sessinit is sent but no second negprot
2151 */
2152 struct rfc1002_session_packet *ses_init_buf;
2153 struct smb_hdr *smb_buf;
2154 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2155 GFP_KERNEL);
2156 if (ses_init_buf) {
2157 ses_init_buf->trailer.session_req.called_len = 32;
2158
2159 if (server->server_RFC1001_name &&
2160 server->server_RFC1001_name[0] != 0)
2161 rfc1002mangle(ses_init_buf->trailer.
2162 session_req.called_name,
2163 server->server_RFC1001_name,
2164 RFC1001_NAME_LEN_WITH_NULL);
2165 else
2166 rfc1002mangle(ses_init_buf->trailer.
2167 session_req.called_name,
2168 DEFAULT_CIFS_CALLED_NAME,
2169 RFC1001_NAME_LEN_WITH_NULL);
2170
2171 ses_init_buf->trailer.session_req.calling_len = 32;
2172
2173 /*
2174 * calling name ends in null (byte 16) from old smb
2175 * convention.
2176 */
2177 if (server->workstation_RFC1001_name &&
2178 server->workstation_RFC1001_name[0] != 0)
2179 rfc1002mangle(ses_init_buf->trailer.
2180 session_req.calling_name,
2181 server->workstation_RFC1001_name,
2182 RFC1001_NAME_LEN_WITH_NULL);
2183 else
2184 rfc1002mangle(ses_init_buf->trailer.
2185 session_req.calling_name,
2186 "LINUX_CIFS_CLNT",
2187 RFC1001_NAME_LEN_WITH_NULL);
2188
2189 ses_init_buf->trailer.session_req.scope1 = 0;
2190 ses_init_buf->trailer.session_req.scope2 = 0;
2191 smb_buf = (struct smb_hdr *)ses_init_buf;
2192
2193 /* sizeof RFC1002_SESSION_REQUEST with no scope */
2194 smb_buf->smb_buf_length = 0x81000044;
2195 rc = smb_send(server, smb_buf, 0x44);
2196 kfree(ses_init_buf);
2197 /*
2198 * RFC1001 layer in at least one server
2199 * requires very short break before negprot
2200 * presumably because not expecting negprot
2201 * to follow so fast. This is a simple
2202 * solution that works without
2203 * complicating the code and causes no
2204 * significant slowing down on mount
2205 * for everyone else
2206 */
2207 usleep_range(1000, 2000);
2208 }
2209 /*
2210 * else the negprot may still work without this
2211 * even though malloc failed
2212 */
2213
2214 return rc;
2215}
2216
2217static int
2218generic_ip_connect(struct TCP_Server_Info *server)
2219{
2220 int rc = 0;
2221 unsigned short int sport;
2222 int slen, sfamily;
2145 struct socket *socket = server->ssocket; 2223 struct socket *socket = server->ssocket;
2224 struct sockaddr *saddr;
2225
2226 saddr = (struct sockaddr *) &server->dstaddr;
2227
2228 if (server->dstaddr.ss_family == AF_INET6) {
2229 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
2230 slen = sizeof(struct sockaddr_in6);
2231 sfamily = AF_INET6;
2232 } else {
2233 sport = ((struct sockaddr_in *) saddr)->sin_port;
2234 slen = sizeof(struct sockaddr_in);
2235 sfamily = AF_INET;
2236 }
2146 2237
2147 if (socket == NULL) { 2238 if (socket == NULL) {
2148 rc = sock_create_kern(PF_INET, SOCK_STREAM, 2239 rc = sock_create_kern(sfamily, SOCK_STREAM,
2149 IPPROTO_TCP, &socket); 2240 IPPROTO_TCP, &socket);
2150 if (rc < 0) { 2241 if (rc < 0) {
2151 cERROR(1, "Error %d creating socket", rc); 2242 cERROR(1, "Error %d creating socket", rc);
2243 server->ssocket = NULL;
2152 return rc; 2244 return rc;
2153 } 2245 }
2154 2246
@@ -2156,63 +2248,28 @@ ipv4_connect(struct TCP_Server_Info *server)
2156 cFYI(1, "Socket created"); 2248 cFYI(1, "Socket created");
2157 server->ssocket = socket; 2249 server->ssocket = socket;
2158 socket->sk->sk_allocation = GFP_NOFS; 2250 socket->sk->sk_allocation = GFP_NOFS;
2159 cifs_reclassify_socket4(socket); 2251 if (sfamily == AF_INET6)
2252 cifs_reclassify_socket6(socket);
2253 else
2254 cifs_reclassify_socket4(socket);
2160 } 2255 }
2161 2256
2162 rc = bind_socket(server); 2257 rc = bind_socket(server);
2163 if (rc < 0) 2258 if (rc < 0)
2164 return rc; 2259 return rc;
2165 2260
2166 /* user overrode default port */ 2261 rc = socket->ops->connect(socket, saddr, slen, 0);
2167 if (server->addr.sockAddr.sin_port) { 2262 if (rc < 0) {
2168 rc = socket->ops->connect(socket, (struct sockaddr *) 2263 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); 2264 sock_release(socket);
2207 server->ssocket = NULL; 2265 server->ssocket = NULL;
2208 return rc; 2266 return rc;
2209 } 2267 }
2210 2268
2211
2212 /* 2269 /*
2213 * Eventually check for other socket options to change from 2270 * Eventually check for other socket options to change from
2214 * the default. sock_setsockopt not used because it expects 2271 * the default. sock_setsockopt not used because it expects
2215 * user space buffer 2272 * user space buffer
2216 */ 2273 */
2217 socket->sk->sk_rcvtimeo = 7 * HZ; 2274 socket->sk->sk_rcvtimeo = 7 * HZ;
2218 socket->sk->sk_sndtimeo = 5 * HZ; 2275 socket->sk->sk_sndtimeo = 5 * HZ;
@@ -2226,7 +2283,7 @@ ipv4_connect(struct TCP_Server_Info *server)
2226 } 2283 }
2227 2284
2228 if (server->tcp_nodelay) { 2285 if (server->tcp_nodelay) {
2229 val = 1; 2286 int val = 1;
2230 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, 2287 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
2231 (char *)&val, sizeof(val)); 2288 (char *)&val, sizeof(val));
2232 if (rc) 2289 if (rc)
@@ -2237,161 +2294,39 @@ ipv4_connect(struct TCP_Server_Info *server)
2237 socket->sk->sk_sndbuf, 2294 socket->sk->sk_sndbuf,
2238 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); 2295 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
2239 2296
2240 /* send RFC1001 sessinit */ 2297 if (sport == htons(RFC1001_PORT))
2241 if (server->addr.sockAddr.sin_port == htons(RFC1001_PORT)) { 2298 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 2299
2300 return rc; 2300 return rc;
2301} 2301}
2302 2302
2303static int 2303static int
2304ipv6_connect(struct TCP_Server_Info *server) 2304ip_connect(struct TCP_Server_Info *server)
2305{ 2305{
2306 int rc = 0; 2306 unsigned short int *sport;
2307 int val; 2307 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
2308 bool connected = false; 2308 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2309 __be16 orig_port = 0;
2310 struct socket *socket = server->ssocket;
2311 2309
2312 if (socket == NULL) { 2310 if (server->dstaddr.ss_family == AF_INET6)
2313 rc = sock_create_kern(PF_INET6, SOCK_STREAM, 2311 sport = &addr6->sin6_port;
2314 IPPROTO_TCP, &socket); 2312 else
2315 if (rc < 0) { 2313 sport = &addr->sin_port;
2316 cERROR(1, "Error %d creating ipv6 socket", rc);
2317 socket = NULL;
2318 return rc;
2319 }
2320 2314
2321 /* BB other socket options to set KEEPALIVE, NODELAY? */ 2315 if (*sport == 0) {
2322 cFYI(1, "ipv6 Socket created"); 2316 int rc;
2323 server->ssocket = socket;
2324 socket->sk->sk_allocation = GFP_NOFS;
2325 cifs_reclassify_socket6(socket);
2326 }
2327 2317
2328 rc = bind_socket(server); 2318 /* try with 445 port at first */
2329 if (rc < 0) 2319 *sport = htons(CIFS_PORT);
2330 return rc;
2331 2320
2332 /* user overrode default port */ 2321 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) 2322 if (rc >= 0)
2362 connected = true; 2323 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 2324
2384 if (server->tcp_nodelay) { 2325 /* if it failed, try with 139 port */
2385 val = 1; 2326 *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 } 2327 }
2391 2328
2392 server->ssocket = socket; 2329 return generic_ip_connect(server);
2393
2394 return rc;
2395} 2330}
2396 2331
2397void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, 2332void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
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;