diff options
author | Steve French <sfrench@us.ibm.com> | 2008-11-13 22:35:10 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-11-13 22:35:10 -0500 |
commit | 3ec332ef7a38c2327e18d087d4120a8e3bd3dc6e (patch) | |
tree | 5c1c7aebeee05cbd6cd02d5aebb3b0c2f8e62ddb /fs/cifs/connect.c | |
parent | fb396016647ae9de5b3bd8c4ee4f7b9cc7148bd5 (diff) |
[CIFS] clean up server protocol handling
We're currently declaring both a sockaddr_in and sockaddr6_in on the
stack, but we really only need storage for one of them. Declare a
sockaddr struct and cast it to the proper type. Also, eliminate the
protocolType field in the TCP_Server_Info struct. It's redundant since
we have a sa_family field in the sockaddr anyway.
We may need to revisit this if SCTP is ever implemented, but for now
this will simplify the code.
CIFS over IPv6 also has a number of problems currently. This fixes all
of them that I found. Eventually, it would be nice to move more of the
code to be protocol independent, but this is a start.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 57 |
1 files changed, 30 insertions, 27 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c1cd1217c990..30ab8dc68e17 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -193,7 +193,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
193 | while ((server->tcpStatus != CifsExiting) && | 193 | while ((server->tcpStatus != CifsExiting) && |
194 | (server->tcpStatus != CifsGood)) { | 194 | (server->tcpStatus != CifsGood)) { |
195 | try_to_freeze(); | 195 | try_to_freeze(); |
196 | if (server->protocolType == IPV6) { | 196 | if (server->addr.sockAddr6.sin6_family == AF_INET6) { |
197 | rc = ipv6_connect(&server->addr.sockAddr6, | 197 | rc = ipv6_connect(&server->addr.sockAddr6, |
198 | &server->ssocket, server->noautotune); | 198 | &server->ssocket, server->noautotune); |
199 | } else { | 199 | } else { |
@@ -1983,10 +1983,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1983 | { | 1983 | { |
1984 | int rc = 0; | 1984 | int rc = 0; |
1985 | int xid; | 1985 | int xid; |
1986 | int address_type = AF_INET; | ||
1987 | struct socket *csocket = NULL; | 1986 | struct socket *csocket = NULL; |
1988 | struct sockaddr_in sin_server; | 1987 | struct sockaddr addr; |
1989 | struct sockaddr_in6 sin_server6; | 1988 | struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr; |
1989 | struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr; | ||
1990 | struct smb_vol volume_info; | 1990 | struct smb_vol volume_info; |
1991 | struct cifsSesInfo *pSesInfo = NULL; | 1991 | struct cifsSesInfo *pSesInfo = NULL; |
1992 | struct cifsSesInfo *existingCifsSes = NULL; | 1992 | struct cifsSesInfo *existingCifsSes = NULL; |
@@ -1997,6 +1997,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1997 | 1997 | ||
1998 | /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */ | 1998 | /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */ |
1999 | 1999 | ||
2000 | memset(&addr, 0, sizeof(struct sockaddr)); | ||
2000 | memset(&volume_info, 0, sizeof(struct smb_vol)); | 2001 | memset(&volume_info, 0, sizeof(struct smb_vol)); |
2001 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { | 2002 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { |
2002 | rc = -EINVAL; | 2003 | rc = -EINVAL; |
@@ -2019,16 +2020,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2019 | 2020 | ||
2020 | if (volume_info.UNCip && volume_info.UNC) { | 2021 | if (volume_info.UNCip && volume_info.UNC) { |
2021 | rc = cifs_inet_pton(AF_INET, volume_info.UNCip, | 2022 | rc = cifs_inet_pton(AF_INET, volume_info.UNCip, |
2022 | &sin_server.sin_addr.s_addr); | 2023 | &sin_server->sin_addr.s_addr); |
2023 | 2024 | ||
2024 | if (rc <= 0) { | 2025 | if (rc <= 0) { |
2025 | /* not ipv4 address, try ipv6 */ | 2026 | /* not ipv4 address, try ipv6 */ |
2026 | rc = cifs_inet_pton(AF_INET6, volume_info.UNCip, | 2027 | rc = cifs_inet_pton(AF_INET6, volume_info.UNCip, |
2027 | &sin_server6.sin6_addr.in6_u); | 2028 | &sin_server6->sin6_addr.in6_u); |
2028 | if (rc > 0) | 2029 | if (rc > 0) |
2029 | address_type = AF_INET6; | 2030 | addr.sa_family = AF_INET6; |
2030 | } else { | 2031 | } else { |
2031 | address_type = AF_INET; | 2032 | addr.sa_family = AF_INET; |
2032 | } | 2033 | } |
2033 | 2034 | ||
2034 | if (rc <= 0) { | 2035 | if (rc <= 0) { |
@@ -2068,39 +2069,38 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2068 | } | 2069 | } |
2069 | } | 2070 | } |
2070 | 2071 | ||
2071 | if (address_type == AF_INET) | 2072 | if (addr.sa_family == AF_INET) |
2072 | existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr, | 2073 | existingCifsSes = cifs_find_tcp_session(&sin_server->sin_addr, |
2073 | NULL /* no ipv6 addr */, | 2074 | NULL /* no ipv6 addr */, |
2074 | volume_info.username, &srvTcp); | 2075 | volume_info.username, &srvTcp); |
2075 | else if (address_type == AF_INET6) { | 2076 | else if (addr.sa_family == AF_INET6) { |
2076 | cFYI(1, ("looking for ipv6 address")); | 2077 | cFYI(1, ("looking for ipv6 address")); |
2077 | existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */, | 2078 | existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */, |
2078 | &sin_server6.sin6_addr, | 2079 | &sin_server6->sin6_addr, |
2079 | volume_info.username, &srvTcp); | 2080 | volume_info.username, &srvTcp); |
2080 | } else { | 2081 | } else { |
2081 | rc = -EINVAL; | 2082 | rc = -EINVAL; |
2082 | goto out; | 2083 | goto out; |
2083 | } | 2084 | } |
2084 | 2085 | ||
2085 | if (!srvTcp) { /* create socket */ | 2086 | if (!srvTcp) { |
2086 | if (volume_info.port) | 2087 | if (addr.sa_family == AF_INET6) { |
2087 | sin_server.sin_port = htons(volume_info.port); | ||
2088 | else | ||
2089 | sin_server.sin_port = 0; | ||
2090 | if (address_type == AF_INET6) { | ||
2091 | cFYI(1, ("attempting ipv6 connect")); | 2088 | cFYI(1, ("attempting ipv6 connect")); |
2092 | /* BB should we allow ipv6 on port 139? */ | 2089 | /* BB should we allow ipv6 on port 139? */ |
2093 | /* other OS never observed in Wild doing 139 with v6 */ | 2090 | /* other OS never observed in Wild doing 139 with v6 */ |
2094 | rc = ipv6_connect(&sin_server6, &csocket, | 2091 | sin_server6->sin6_port = htons(volume_info.port); |
2092 | rc = ipv6_connect(sin_server6, &csocket, | ||
2095 | volume_info.noblocksnd); | 2093 | volume_info.noblocksnd); |
2096 | } else | 2094 | } else { |
2097 | rc = ipv4_connect(&sin_server, &csocket, | 2095 | sin_server->sin_port = htons(volume_info.port); |
2096 | rc = ipv4_connect(sin_server, &csocket, | ||
2098 | volume_info.source_rfc1001_name, | 2097 | volume_info.source_rfc1001_name, |
2099 | volume_info.target_rfc1001_name, | 2098 | volume_info.target_rfc1001_name, |
2100 | volume_info.noblocksnd, | 2099 | volume_info.noblocksnd, |
2101 | volume_info.noautotune); | 2100 | volume_info.noautotune); |
2101 | } | ||
2102 | if (rc < 0) { | 2102 | if (rc < 0) { |
2103 | cERROR(1, ("Error connecting to IPv4 socket. " | 2103 | cERROR(1, ("Error connecting to socket. " |
2104 | "Aborting operation")); | 2104 | "Aborting operation")); |
2105 | if (csocket != NULL) | 2105 | if (csocket != NULL) |
2106 | sock_release(csocket); | 2106 | sock_release(csocket); |
@@ -2115,12 +2115,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2115 | } else { | 2115 | } else { |
2116 | srvTcp->noblocksnd = volume_info.noblocksnd; | 2116 | srvTcp->noblocksnd = volume_info.noblocksnd; |
2117 | srvTcp->noautotune = volume_info.noautotune; | 2117 | srvTcp->noautotune = volume_info.noautotune; |
2118 | memcpy(&srvTcp->addr.sockAddr, &sin_server, | 2118 | if (addr.sa_family == AF_INET6) |
2119 | sizeof(struct sockaddr_in)); | 2119 | memcpy(&srvTcp->addr.sockAddr6, sin_server6, |
2120 | sizeof(struct sockaddr_in6)); | ||
2121 | else | ||
2122 | memcpy(&srvTcp->addr.sockAddr, sin_server, | ||
2123 | sizeof(struct sockaddr_in)); | ||
2120 | atomic_set(&srvTcp->inFlight, 0); | 2124 | atomic_set(&srvTcp->inFlight, 0); |
2121 | /* BB Add code for ipv6 case too */ | 2125 | /* BB Add code for ipv6 case too */ |
2122 | srvTcp->ssocket = csocket; | 2126 | srvTcp->ssocket = csocket; |
2123 | srvTcp->protocolType = IPV4; | ||
2124 | srvTcp->hostname = extract_hostname(volume_info.UNC); | 2127 | srvTcp->hostname = extract_hostname(volume_info.UNC); |
2125 | if (IS_ERR(srvTcp->hostname)) { | 2128 | if (IS_ERR(srvTcp->hostname)) { |
2126 | rc = PTR_ERR(srvTcp->hostname); | 2129 | rc = PTR_ERR(srvTcp->hostname); |
@@ -2172,7 +2175,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2172 | else { | 2175 | else { |
2173 | pSesInfo->server = srvTcp; | 2176 | pSesInfo->server = srvTcp; |
2174 | sprintf(pSesInfo->serverName, "%u.%u.%u.%u", | 2177 | sprintf(pSesInfo->serverName, "%u.%u.%u.%u", |
2175 | NIPQUAD(sin_server.sin_addr.s_addr)); | 2178 | NIPQUAD(sin_server->sin_addr.s_addr)); |
2176 | } | 2179 | } |
2177 | 2180 | ||
2178 | if (!rc) { | 2181 | if (!rc) { |
@@ -2211,7 +2214,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2211 | setup_cifs_sb(&volume_info, cifs_sb); | 2214 | setup_cifs_sb(&volume_info, cifs_sb); |
2212 | 2215 | ||
2213 | tcon = | 2216 | tcon = |
2214 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, | 2217 | find_unc(sin_server->sin_addr.s_addr, volume_info.UNC, |
2215 | volume_info.username); | 2218 | volume_info.username); |
2216 | if (tcon) { | 2219 | if (tcon) { |
2217 | cFYI(1, ("Found match on UNC path")); | 2220 | cFYI(1, ("Found match on UNC path")); |