Advertisement

Detecting IP Version Capabilities

Started by April 08, 2018 01:12 AM
3 comments, last by hplus0603 6 years, 7 months ago

I'm working directly with BSD / Winsock sockets. For a time I was using ENet with a handful of modifications, and for a time life was good. Then I realised ENet only supports IPv4. There are forks of ENet that are IPv6, but not that explicitly support both. My overall requirements aren't very stringent, so I'm pretty comfortable with rolling my own instead.

 

The prevailing wisdom seems to be to use a single socket where dual-stack support exists, and create two separate sockets as a fallback. The problem I'm facing is how to detect the availability of dual-stack sockets in the first place?

You can't really "detect" dual-stack support at runtime in any meaningful way. You have to provide this as a compile-time option.

The good news is that Linux, macOS, Windows, iOS, and Android all support dual stack, so ... why do you worry about not?

To know which stack or stacks is/are used by the network the user is connected to, simply call getaddrinfo() on the target DNS host name. If it's IPv4 only, you'll get an IPv4 address. If it's IPv6 only, you'll get a 4-in-6 wrapped address. Just use the data that getaddrinfo() returns, straight up!

 

enum Bool { True, False, FileNotFound };
Advertisement

So it's safe just to create an IPv6 socket and bind to an IPv6 address (where one is available) and be done with it? That's much less scary than my reading had me believe! I'm stuck on a purely IPv4 network for the time being, so testing things first hand has been problematic to say the least...

So it's safe just to create an IPv6 socket and bind to an IPv6 address (where one is available) and be done with it?

You'll want a single socket, and you want to bind it to the "both stacks" interface if possible. You typically create an IPV6 versino socket, set some socket option (turn off IPV6_ONLY for example) before binding, and it will also accept IPV4. Same thing for connections; call getaddrinfo() and use whatever socket-type/protocol/port/address it returns.

If creating an IPV6 socket fails, or setting the V6_ONLY socket option to 0 fails, then you can fall back to closing that socket and creating an IP4 socket and binding it to IP4 IPADDR_ANY.

 

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement