[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>

+33 -31
+2 -2
fs/cifs/cifs_spnego.c
··· 73 73 * strlen(";sec=ntlmsspi") */ 74 74 #define MAX_MECH_STR_LEN 13 75 75 76 - /* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */ 77 - #define MAX_IPV6_ADDR_LEN 42 76 + /* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/128 */ 77 + #define MAX_IPV6_ADDR_LEN 43 78 78 79 79 /* strlen of "host=" */ 80 80 #define HOST_KEY_LEN 5
+1 -2
fs/cifs/cifsglob.h
··· 85 85 }; 86 86 87 87 enum protocolEnum { 88 - IPV4 = 0, 89 - IPV6, 88 + TCP = 0, 90 89 SCTP 91 90 /* Netbios frames protocol not supported at this time */ 92 91 };
+30 -27
fs/cifs/connect.c
··· 193 193 while ((server->tcpStatus != CifsExiting) && 194 194 (server->tcpStatus != CifsGood)) { 195 195 try_to_freeze(); 196 - if (server->protocolType == IPV6) { 196 + if (server->addr.sockAddr6.sin6_family == AF_INET6) { 197 197 rc = ipv6_connect(&server->addr.sockAddr6, 198 198 &server->ssocket, server->noautotune); 199 199 } else { ··· 1983 1983 { 1984 1984 int rc = 0; 1985 1985 int xid; 1986 - int address_type = AF_INET; 1987 1986 struct socket *csocket = NULL; 1988 - struct sockaddr_in sin_server; 1989 - struct sockaddr_in6 sin_server6; 1987 + struct sockaddr addr; 1988 + struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr; 1989 + struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr; 1990 1990 struct smb_vol volume_info; 1991 1991 struct cifsSesInfo *pSesInfo = NULL; 1992 1992 struct cifsSesInfo *existingCifsSes = NULL; ··· 1997 1997 1998 1998 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */ 1999 1999 2000 + memset(&addr, 0, sizeof(struct sockaddr)); 2000 2001 memset(&volume_info, 0, sizeof(struct smb_vol)); 2001 2002 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { 2002 2003 rc = -EINVAL; ··· 2020 2019 2021 2020 if (volume_info.UNCip && volume_info.UNC) { 2022 2021 rc = cifs_inet_pton(AF_INET, volume_info.UNCip, 2023 - &sin_server.sin_addr.s_addr); 2022 + &sin_server->sin_addr.s_addr); 2024 2023 2025 2024 if (rc <= 0) { 2026 2025 /* not ipv4 address, try ipv6 */ 2027 2026 rc = cifs_inet_pton(AF_INET6, volume_info.UNCip, 2028 - &sin_server6.sin6_addr.in6_u); 2027 + &sin_server6->sin6_addr.in6_u); 2029 2028 if (rc > 0) 2030 - address_type = AF_INET6; 2029 + addr.sa_family = AF_INET6; 2031 2030 } else { 2032 - address_type = AF_INET; 2031 + addr.sa_family = AF_INET; 2033 2032 } 2034 2033 2035 2034 if (rc <= 0) { ··· 2069 2068 } 2070 2069 } 2071 2070 2072 - if (address_type == AF_INET) 2073 - existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr, 2071 + if (addr.sa_family == AF_INET) 2072 + existingCifsSes = cifs_find_tcp_session(&sin_server->sin_addr, 2074 2073 NULL /* no ipv6 addr */, 2075 2074 volume_info.username, &srvTcp); 2076 - else if (address_type == AF_INET6) { 2075 + else if (addr.sa_family == AF_INET6) { 2077 2076 cFYI(1, ("looking for ipv6 address")); 2078 2077 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */, 2079 - &sin_server6.sin6_addr, 2078 + &sin_server6->sin6_addr, 2080 2079 volume_info.username, &srvTcp); 2081 2080 } else { 2082 2081 rc = -EINVAL; 2083 2082 goto out; 2084 2083 } 2085 2084 2086 - if (!srvTcp) { /* create socket */ 2087 - if (volume_info.port) 2088 - sin_server.sin_port = htons(volume_info.port); 2089 - else 2090 - sin_server.sin_port = 0; 2091 - if (address_type == AF_INET6) { 2085 + if (!srvTcp) { 2086 + if (addr.sa_family == AF_INET6) { 2092 2087 cFYI(1, ("attempting ipv6 connect")); 2093 2088 /* BB should we allow ipv6 on port 139? */ 2094 2089 /* other OS never observed in Wild doing 139 with v6 */ 2095 - rc = ipv6_connect(&sin_server6, &csocket, 2090 + sin_server6->sin6_port = htons(volume_info.port); 2091 + rc = ipv6_connect(sin_server6, &csocket, 2096 2092 volume_info.noblocksnd); 2097 - } else 2098 - rc = ipv4_connect(&sin_server, &csocket, 2093 + } else { 2094 + sin_server->sin_port = htons(volume_info.port); 2095 + rc = ipv4_connect(sin_server, &csocket, 2099 2096 volume_info.source_rfc1001_name, 2100 2097 volume_info.target_rfc1001_name, 2101 2098 volume_info.noblocksnd, 2102 2099 volume_info.noautotune); 2100 + } 2103 2101 if (rc < 0) { 2104 - cERROR(1, ("Error connecting to IPv4 socket. " 2102 + cERROR(1, ("Error connecting to socket. " 2105 2103 "Aborting operation")); 2106 2104 if (csocket != NULL) 2107 2105 sock_release(csocket); ··· 2115 2115 } else { 2116 2116 srvTcp->noblocksnd = volume_info.noblocksnd; 2117 2117 srvTcp->noautotune = volume_info.noautotune; 2118 - memcpy(&srvTcp->addr.sockAddr, &sin_server, 2119 - sizeof(struct sockaddr_in)); 2118 + if (addr.sa_family == AF_INET6) 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 2124 atomic_set(&srvTcp->inFlight, 0); 2121 2125 /* BB Add code for ipv6 case too */ 2122 2126 srvTcp->ssocket = csocket; 2123 - srvTcp->protocolType = IPV4; 2124 2127 srvTcp->hostname = extract_hostname(volume_info.UNC); 2125 2128 if (IS_ERR(srvTcp->hostname)) { 2126 2129 rc = PTR_ERR(srvTcp->hostname); ··· 2175 2172 else { 2176 2173 pSesInfo->server = srvTcp; 2177 2174 sprintf(pSesInfo->serverName, "%u.%u.%u.%u", 2178 - NIPQUAD(sin_server.sin_addr.s_addr)); 2175 + NIPQUAD(sin_server->sin_addr.s_addr)); 2179 2176 } 2180 2177 2181 2178 if (!rc) { ··· 2214 2211 setup_cifs_sb(&volume_info, cifs_sb); 2215 2212 2216 2213 tcon = 2217 - find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, 2214 + find_unc(sin_server->sin_addr.s_addr, volume_info.UNC, 2218 2215 volume_info.username); 2219 2216 if (tcon) { 2220 2217 cFYI(1, ("Found match on UNC path"));