views:

45

answers:

1

I'm using getaddrinfo to start a local server accepting connections only on the localhost:

struct addrinfo *res;
struct addrinfo hints = {0};
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
getaddrinfo(NULL, portbuf, &hints, &res);

This seems to work fine, giving me the IPv6 address ::1 when IPv6 is present and IPv4 address when it is not.
Except sometimes on Windows 2008 R2 (at least that's the only system where I've seen it, but I saw it twice, both times on a customer system) it gets bound to 127.0.0.1 instead of IPv6!
This then messes me up because if you bind ::1 it will accept both connections to 127.1 and to ::1, but if you bind 127.1, then IPv6 connections are not accepted.

+3  A: 

getaddrinfo() returns you a list of matching addresses, in an unspecified order. You should traverse the list (following the ai_next pointer), and create a listening socket bound to each address returned.

caf
Don't know.. I'm not convinced. I thought it was OK to just listen on IPv6 and rely on the fact that IPv4 will also be accepted (above Windows 2003). I do loop through all addresses when I connect, but why bather when accepting?I do realize that I will have to make changes since I can't rely on IPv6 address being the first one returned. What I want to understand is what causes it to be not the first one. Because all systems that I built have IPv6 first, but all systems that this customer builds get IPv4 first. There must be something in the configuration.
MK
@MK: It's just the most reliable way, that's all. If you'd rather just listen on one address, you could traverse the list until you find the best one (presumably, the `AF_INET6` address if there is one).
caf