views:

54

answers:

1

I am trying to write a server application that listens to both IPv6 and IPv4 connections. The proper way to accomplish this seems to be listening on IPv6 address, which will also accept IPv4 connections.

The relevant piece of code is:

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, MYPORT, &hints, &res);

(pretty much copypasted from Beej's Guide)

The problem is that at least on my system, getaddrinfo returns an entry with AF_INET first and AF_INET6 second -- whereas client's getaddrinfo returns AF_INET6 first, as per spec. With my naive approach, server picks IPv4, client picks IPv6 and the connection fails.

I tried to fix this by setting hints.ai_family = AF_INET6, but that fails on systems where IPv6 is not available.

I see two obvious solutions:
a) try asking for IPv6 first and fall back to IPv4 if that fails, or
b) walk through results of getaddrinfo, look for IPv6, and if is not present, pick the first entry
but i don't like either one too much ;) I feel that there should be a way to convince getaddrinfo to do the right thing, or perhaps a different way to accomplish my goal.

+2  A: 

The order of the address that getaddrinfo() returns is unspecified, so you have to be prepared to handle either case. That probably means traversing the list, keeping track of the "best address seen so far".

Alternatively, you could try to bind() and listen() on all the addresses returned by getaddrinfo(). This is probably the best option, since I believe some OSes do not accept IPv4 connections to IPv6 sockets listening on 0::0.

caf
+1 Listen on *all* addresses.
schot
+1 for listening on 0::0
divinci
Windows Vista and later support dual-stack sockets, where a single IPv6 socket can handle both IPv4 and IPv6 traffic at the same time on the same port. This is done by disabling the new IPV6_V6ONLY socket option prior to binding the socket. On older Windows versions, you have to use separate sockets for IPv4 and IPv6 instead.
Remy Lebeau - TeamB
i didn't know that some systems don't accept IPv4 and IPv6 on the same socket. guess i'll have to listen on all addresses
matejcik