From 08477065972186327dba55ba0da92892c84b6c16 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Feb 2013 15:52:26 +0100 Subject: [PATCH] socketlib: properly fix the IPv6 to IPv4 fallback code. With the current code, we do have the following on a system where IPv6 is completely disabled: socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = -1 EAFNOSUPPORT (Address family not supported by protocol) socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 bind(3, {sa_family=AF_INET6, sin6_port=htons(5002), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EAFNOSUPPORT (Address family not supported by protocol) The correct fix is to make a new call to getAddr() to ensure that the entire struct addrinfo will be correctly filled out again with AF_INET this time. This patch fixes. --- socketlib.c | 54 ++++++++++++++++++++++++++++++++--------------------- socketlib.h | 2 +- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/socketlib.c b/socketlib.c index 9efdf221..eb44bcf4 100644 --- a/socketlib.c +++ b/socketlib.c @@ -39,9 +39,11 @@ #include #include -int common_setup(struct addrinfo *pAddrInfo) -{ +int common_setup(struct addrinfo **ppAddrInfo, int pPort) +{ int tSock; + struct addrinfo *pAddrInfo = *ppAddrInfo; + //printAddrs(pAddrInfo); tSock = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, 0); #ifdef AF_INET6 @@ -49,7 +51,17 @@ int common_setup(struct addrinfo *pAddrInfo) { //Fallback to ipv4 perror("Failed to create ipv6 socket. Trying ipv4"); - pAddrInfo->ai_family = AF_INET; + (*ppAddrInfo)->ai_family = AF_INET; + if (pPort != -1) + { + char tService[SERVLEN]; + sprintf(tService, "%d", pPort); // copies port to string + int tFamily = AF_INET; + if(getAddr(NULL, tService, tFamily, SOCK_STREAM, ppAddrInfo)) + { + return ERROR; // getAddr prints out error message + } + } tSock = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, 0); } #endif @@ -63,7 +75,7 @@ int setup_client(struct addrinfo *server_host) while(tIdx++ < RETRY_COUNT) { - tSockDesc = common_setup(server_host); + tSockDesc = common_setup(&server_host, -1); if (tSockDesc < 0 && tIdx >= RETRY_COUNT) { perror("Error: Could not create socket"); @@ -107,9 +119,23 @@ int getAddr(char *pHostname, char *pService, int pFamily, int pSockType, struct return tError; } -int setup_server(struct addrinfo *server_addr) +int setup_server(struct addrinfo *server_addr, int pPort) { - int tSock = common_setup(server_addr); + char tService[SERVLEN]; + sprintf(tService, "%d", pPort); // copies port to string + int tFamily = AF_INET; + #ifdef AF_INET6 + //printf("Listening on IPv6 Socket\n"); + tFamily = AF_INET6; + #else + //printf("Listening on IPv4 Socket"); + #endif + if(getAddr(NULL, tService, tFamily, SOCK_STREAM, &server_addr)) + { + return ERROR; // getAddr prints out error message + } + + int tSock = common_setup(&server_addr, pPort); if (tSock < 0) { perror("Error: Could not create server socket"); @@ -154,21 +180,7 @@ int acceptClient(int pSock, struct addrinfo *server_addr) int setupListenServer(struct addrinfo **pAddrInfo, int pPort) { - char tService[SERVLEN]; - sprintf(tService, "%d", pPort); // copies port to string - int tFamily = AF_INET; - #ifdef AF_INET6 - //printf("Listening on IPv6 Socket\n"); - tFamily = AF_INET6; - #else - //printf("Listening on IPv4 Socket"); - #endif - if(getAddr(NULL, tService, tFamily, SOCK_STREAM, pAddrInfo)) - { - return ERROR; // getAddr prints out error message - } - - int tSocketDescriptor = setup_server(*pAddrInfo); + int tSocketDescriptor = setup_server(*pAddrInfo, pPort); char tAddr[INET6_ADDRSTRLEN]; socklen_t tSize = INET6_ADDRSTRLEN; inet_ntop((*pAddrInfo)->ai_family, (*pAddrInfo)->ai_addr, tAddr, tSize); diff --git a/socketlib.h b/socketlib.h index 6d501f33..5cb1bf08 100644 --- a/socketlib.h +++ b/socketlib.h @@ -24,7 +24,7 @@ #define DEFAULT_UNIX "/unix" int setup_client(struct addrinfo *server_info); -int setup_server(struct addrinfo *server_address); +int setup_server(struct addrinfo *server_address, int pPort); int setupListenServer(struct addrinfo **pAddrInfo, int pPort); int acceptClient(int pSock, struct addrinfo *server_addr); void delay(long pMillisecs, struct timeval *pRes);