Skip to content

Commit

Permalink
socketlib: properly fix the IPv6 to IPv4 fallback code.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ffainelli committed Feb 22, 2013
1 parent 4746bb1 commit 0847706
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 22 deletions.
54 changes: 33 additions & 21 deletions socketlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,29 @@
#include <openssl/bio.h>
#include <openssl/buffer.h>

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
if((tSock==-1) && (pAddrInfo->ai_family == AF_INET6) && (errno == EAFNOSUPPORT))
{
//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
Expand All @@ -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");
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion socketlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 0847706

Please sign in to comment.