diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/connect.c | 146 |
1 files changed, 69 insertions, 77 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c2ed0f57a66c..a36f4bd5a764 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -101,12 +101,7 @@ struct smb_vol { | |||
101 | char *prepath; | 101 | char *prepath; |
102 | }; | 102 | }; |
103 | 103 | ||
104 | static int ipv4_connect(struct sockaddr_in *psin_server, | 104 | static int ipv4_connect(struct TCP_Server_Info *server); |
105 | struct socket **csocket, | ||
106 | char *netb_name, | ||
107 | char *server_netb_name, | ||
108 | bool noblocksnd, | ||
109 | bool nosndbuf); /* ipv6 never set sndbuf size */ | ||
110 | static int ipv6_connect(struct sockaddr_in6 *psin_server, | 105 | static int ipv6_connect(struct sockaddr_in6 *psin_server, |
111 | struct socket **csocket, bool noblocksnd); | 106 | struct socket **csocket, bool noblocksnd); |
112 | 107 | ||
@@ -187,16 +182,11 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
187 | while ((server->tcpStatus != CifsExiting) && | 182 | while ((server->tcpStatus != CifsExiting) && |
188 | (server->tcpStatus != CifsGood)) { | 183 | (server->tcpStatus != CifsGood)) { |
189 | try_to_freeze(); | 184 | try_to_freeze(); |
190 | if (server->addr.sockAddr6.sin6_family == AF_INET6) { | 185 | if (server->addr.sockAddr6.sin6_family == AF_INET6) |
191 | rc = ipv6_connect(&server->addr.sockAddr6, | 186 | rc = ipv6_connect(&server->addr.sockAddr6, |
192 | &server->ssocket, server->noautotune); | 187 | &server->ssocket, server->noautotune); |
193 | } else { | 188 | else |
194 | rc = ipv4_connect(&server->addr.sockAddr, | 189 | rc = ipv4_connect(server); |
195 | &server->ssocket, | ||
196 | server->workstation_RFC1001_name, | ||
197 | server->server_RFC1001_name, | ||
198 | server->noblocksnd, server->noautotune); | ||
199 | } | ||
200 | if (rc) { | 190 | if (rc) { |
201 | cFYI(1, ("reconnect error %d", rc)); | 191 | cFYI(1, ("reconnect error %d", rc)); |
202 | msleep(3000); | 192 | msleep(3000); |
@@ -1517,11 +1507,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1517 | memcpy(&tcp_ses->addr.sockAddr, sin_server, | 1507 | memcpy(&tcp_ses->addr.sockAddr, sin_server, |
1518 | sizeof(struct sockaddr_in)); | 1508 | sizeof(struct sockaddr_in)); |
1519 | sin_server->sin_port = htons(volume_info->port); | 1509 | sin_server->sin_port = htons(volume_info->port); |
1520 | rc = ipv4_connect(sin_server, &tcp_ses->ssocket, | 1510 | rc = ipv4_connect(tcp_ses); |
1521 | volume_info->source_rfc1001_name, | ||
1522 | volume_info->target_rfc1001_name, | ||
1523 | volume_info->noblocksnd, | ||
1524 | volume_info->noautotune); | ||
1525 | } | 1511 | } |
1526 | if (rc < 0) { | 1512 | if (rc < 0) { |
1527 | cERROR(1, ("Error connecting to socket. Aborting operation")); | 1513 | cERROR(1, ("Error connecting to socket. Aborting operation")); |
@@ -1735,93 +1721,96 @@ static void rfc1002mangle(char *target, char *source, unsigned int length) | |||
1735 | 1721 | ||
1736 | 1722 | ||
1737 | static int | 1723 | static int |
1738 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | 1724 | ipv4_connect(struct TCP_Server_Info *server) |
1739 | char *netbios_name, char *target_name, | ||
1740 | bool noblocksnd, bool noautotune) | ||
1741 | { | 1725 | { |
1742 | int rc = 0; | 1726 | int rc = 0; |
1743 | int connected = 0; | 1727 | bool connected = false; |
1744 | __be16 orig_port = 0; | 1728 | __be16 orig_port = 0; |
1729 | struct socket *socket = server->ssocket; | ||
1745 | 1730 | ||
1746 | if (*csocket == NULL) { | 1731 | if (socket == NULL) { |
1747 | rc = sock_create_kern(PF_INET, SOCK_STREAM, | 1732 | rc = sock_create_kern(PF_INET, SOCK_STREAM, |
1748 | IPPROTO_TCP, csocket); | 1733 | IPPROTO_TCP, &socket); |
1749 | if (rc < 0) { | 1734 | if (rc < 0) { |
1750 | cERROR(1, ("Error %d creating socket", rc)); | 1735 | cERROR(1, ("Error %d creating socket", rc)); |
1751 | *csocket = NULL; | ||
1752 | return rc; | 1736 | return rc; |
1753 | } else { | ||
1754 | /* BB other socket options to set KEEPALIVE, NODELAY? */ | ||
1755 | cFYI(1, ("Socket created")); | ||
1756 | (*csocket)->sk->sk_allocation = GFP_NOFS; | ||
1757 | cifs_reclassify_socket4(*csocket); | ||
1758 | } | 1737 | } |
1738 | |||
1739 | /* BB other socket options to set KEEPALIVE, NODELAY? */ | ||
1740 | cFYI(1, ("Socket created")); | ||
1741 | server->ssocket = socket; | ||
1742 | socket->sk->sk_allocation = GFP_NOFS; | ||
1743 | cifs_reclassify_socket4(socket); | ||
1759 | } | 1744 | } |
1760 | 1745 | ||
1761 | psin_server->sin_family = AF_INET; | 1746 | /* user overrode default port */ |
1762 | if (psin_server->sin_port) { /* user overrode default port */ | 1747 | if (server->addr.sockAddr.sin_port) { |
1763 | rc = (*csocket)->ops->connect(*csocket, | 1748 | rc = socket->ops->connect(socket, (struct sockaddr *) |
1764 | (struct sockaddr *) psin_server, | 1749 | &server->addr.sockAddr, |
1765 | sizeof(struct sockaddr_in), 0); | 1750 | sizeof(struct sockaddr_in), 0); |
1766 | if (rc >= 0) | 1751 | if (rc >= 0) |
1767 | connected = 1; | 1752 | connected = true; |
1768 | } | 1753 | } |
1769 | 1754 | ||
1770 | if (!connected) { | 1755 | if (!connected) { |
1771 | /* save original port so we can retry user specified port | 1756 | /* save original port so we can retry user specified port |
1772 | later if fall back ports fail this time */ | 1757 | later if fall back ports fail this time */ |
1773 | orig_port = psin_server->sin_port; | 1758 | orig_port = server->addr.sockAddr.sin_port; |
1774 | 1759 | ||
1775 | /* do not retry on the same port we just failed on */ | 1760 | /* do not retry on the same port we just failed on */ |
1776 | if (psin_server->sin_port != htons(CIFS_PORT)) { | 1761 | if (server->addr.sockAddr.sin_port != htons(CIFS_PORT)) { |
1777 | psin_server->sin_port = htons(CIFS_PORT); | 1762 | server->addr.sockAddr.sin_port = htons(CIFS_PORT); |
1778 | 1763 | rc = socket->ops->connect(socket, | |
1779 | rc = (*csocket)->ops->connect(*csocket, | 1764 | (struct sockaddr *) |
1780 | (struct sockaddr *) psin_server, | 1765 | &server->addr.sockAddr, |
1781 | sizeof(struct sockaddr_in), 0); | 1766 | sizeof(struct sockaddr_in), 0); |
1782 | if (rc >= 0) | 1767 | if (rc >= 0) |
1783 | connected = 1; | 1768 | connected = true; |
1784 | } | 1769 | } |
1785 | } | 1770 | } |
1786 | if (!connected) { | 1771 | if (!connected) { |
1787 | psin_server->sin_port = htons(RFC1001_PORT); | 1772 | server->addr.sockAddr.sin_port = htons(RFC1001_PORT); |
1788 | rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) | 1773 | rc = socket->ops->connect(socket, (struct sockaddr *) |
1789 | psin_server, | 1774 | &server->addr.sockAddr, |
1790 | sizeof(struct sockaddr_in), 0); | 1775 | sizeof(struct sockaddr_in), 0); |
1791 | if (rc >= 0) | 1776 | if (rc >= 0) |
1792 | connected = 1; | 1777 | connected = true; |
1793 | } | 1778 | } |
1794 | 1779 | ||
1795 | /* give up here - unless we want to retry on different | 1780 | /* give up here - unless we want to retry on different |
1796 | protocol families some day */ | 1781 | protocol families some day */ |
1797 | if (!connected) { | 1782 | if (!connected) { |
1798 | if (orig_port) | 1783 | if (orig_port) |
1799 | psin_server->sin_port = orig_port; | 1784 | server->addr.sockAddr.sin_port = orig_port; |
1800 | cFYI(1, ("Error %d connecting to server via ipv4", rc)); | 1785 | cFYI(1, ("Error %d connecting to server via ipv4", rc)); |
1801 | sock_release(*csocket); | 1786 | sock_release(socket); |
1802 | *csocket = NULL; | 1787 | server->ssocket = NULL; |
1803 | return rc; | 1788 | return rc; |
1804 | } | 1789 | } |
1805 | /* Eventually check for other socket options to change from | 1790 | |
1806 | the default. sock_setsockopt not used because it expects | 1791 | |
1807 | user space buffer */ | 1792 | /* |
1808 | cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx", | 1793 | * Eventually check for other socket options to change from |
1809 | (*csocket)->sk->sk_sndbuf, | 1794 | * the default. sock_setsockopt not used because it expects |
1810 | (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); | 1795 | * user space buffer |
1811 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; | 1796 | */ |
1812 | if (!noblocksnd) | 1797 | socket->sk->sk_rcvtimeo = 7 * HZ; |
1813 | (*csocket)->sk->sk_sndtimeo = 3 * HZ; | 1798 | socket->sk->sk_sndtimeo = 3 * HZ; |
1814 | 1799 | ||
1815 | /* make the bufsizes depend on wsize/rsize and max requests */ | 1800 | /* make the bufsizes depend on wsize/rsize and max requests */ |
1816 | if (noautotune) { | 1801 | if (server->noautotune) { |
1817 | if ((*csocket)->sk->sk_sndbuf < (200 * 1024)) | 1802 | if (socket->sk->sk_sndbuf < (200 * 1024)) |
1818 | (*csocket)->sk->sk_sndbuf = 200 * 1024; | 1803 | socket->sk->sk_sndbuf = 200 * 1024; |
1819 | if ((*csocket)->sk->sk_rcvbuf < (140 * 1024)) | 1804 | if (socket->sk->sk_rcvbuf < (140 * 1024)) |
1820 | (*csocket)->sk->sk_rcvbuf = 140 * 1024; | 1805 | socket->sk->sk_rcvbuf = 140 * 1024; |
1821 | } | 1806 | } |
1822 | 1807 | ||
1808 | cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx", | ||
1809 | socket->sk->sk_sndbuf, | ||
1810 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo)); | ||
1811 | |||
1823 | /* send RFC1001 sessinit */ | 1812 | /* send RFC1001 sessinit */ |
1824 | if (psin_server->sin_port == htons(RFC1001_PORT)) { | 1813 | if (server->addr.sockAddr.sin_port == htons(RFC1001_PORT)) { |
1825 | /* some servers require RFC1001 sessinit before sending | 1814 | /* some servers require RFC1001 sessinit before sending |
1826 | negprot - BB check reconnection in case where second | 1815 | negprot - BB check reconnection in case where second |
1827 | sessinit is sent but no second negprot */ | 1816 | sessinit is sent but no second negprot */ |
@@ -1831,39 +1820,42 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1831 | GFP_KERNEL); | 1820 | GFP_KERNEL); |
1832 | if (ses_init_buf) { | 1821 | if (ses_init_buf) { |
1833 | ses_init_buf->trailer.session_req.called_len = 32; | 1822 | ses_init_buf->trailer.session_req.called_len = 32; |
1834 | if (target_name && (target_name[0] != 0)) { | 1823 | if (server->server_RFC1001_name && |
1824 | server->server_RFC1001_name[0] != 0) | ||
1835 | rfc1002mangle(ses_init_buf->trailer. | 1825 | rfc1002mangle(ses_init_buf->trailer. |
1836 | session_req.called_name, | 1826 | session_req.called_name, |
1837 | target_name, | 1827 | server->server_RFC1001_name, |
1838 | RFC1001_NAME_LEN_WITH_NULL); | 1828 | RFC1001_NAME_LEN_WITH_NULL); |
1839 | } else { | 1829 | else |
1840 | rfc1002mangle(ses_init_buf->trailer. | 1830 | rfc1002mangle(ses_init_buf->trailer. |
1841 | session_req.called_name, | 1831 | session_req.called_name, |
1842 | DEFAULT_CIFS_CALLED_NAME, | 1832 | DEFAULT_CIFS_CALLED_NAME, |
1843 | RFC1001_NAME_LEN_WITH_NULL); | 1833 | RFC1001_NAME_LEN_WITH_NULL); |
1844 | } | ||
1845 | 1834 | ||
1846 | ses_init_buf->trailer.session_req.calling_len = 32; | 1835 | ses_init_buf->trailer.session_req.calling_len = 32; |
1836 | |||
1847 | /* calling name ends in null (byte 16) from old smb | 1837 | /* calling name ends in null (byte 16) from old smb |
1848 | convention. */ | 1838 | convention. */ |
1849 | if (netbios_name && (netbios_name[0] != 0)) { | 1839 | if (server->workstation_RFC1001_name && |
1840 | server->workstation_RFC1001_name[0] != 0) | ||
1850 | rfc1002mangle(ses_init_buf->trailer. | 1841 | rfc1002mangle(ses_init_buf->trailer. |
1851 | session_req.calling_name, | 1842 | session_req.calling_name, |
1852 | netbios_name, | 1843 | server->workstation_RFC1001_name, |
1853 | RFC1001_NAME_LEN_WITH_NULL); | 1844 | RFC1001_NAME_LEN_WITH_NULL); |
1854 | } else { | 1845 | else |
1855 | rfc1002mangle(ses_init_buf->trailer. | 1846 | rfc1002mangle(ses_init_buf->trailer. |
1856 | session_req.calling_name, | 1847 | session_req.calling_name, |
1857 | "LINUX_CIFS_CLNT", | 1848 | "LINUX_CIFS_CLNT", |
1858 | RFC1001_NAME_LEN_WITH_NULL); | 1849 | RFC1001_NAME_LEN_WITH_NULL); |
1859 | } | 1850 | |
1860 | ses_init_buf->trailer.session_req.scope1 = 0; | 1851 | ses_init_buf->trailer.session_req.scope1 = 0; |
1861 | ses_init_buf->trailer.session_req.scope2 = 0; | 1852 | ses_init_buf->trailer.session_req.scope2 = 0; |
1862 | smb_buf = (struct smb_hdr *)ses_init_buf; | 1853 | smb_buf = (struct smb_hdr *)ses_init_buf; |
1863 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ | 1854 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ |
1864 | smb_buf->smb_buf_length = 0x81000044; | 1855 | smb_buf->smb_buf_length = 0x81000044; |
1865 | rc = smb_send(*csocket, smb_buf, 0x44, | 1856 | rc = smb_send(socket, smb_buf, 0x44, |
1866 | (struct sockaddr *)psin_server, noblocksnd); | 1857 | (struct sockaddr *) &server->addr.sockAddr, |
1858 | server->noblocksnd); | ||
1867 | kfree(ses_init_buf); | 1859 | kfree(ses_init_buf); |
1868 | msleep(1); /* RFC1001 layer in at least one server | 1860 | msleep(1); /* RFC1001 layer in at least one server |
1869 | requires very short break before negprot | 1861 | requires very short break before negprot |