Go's network package and IPv6 (and my ideal version thereof)

September 10, 2010

As the result of making a couple of chainsaw passes at really fixing my issues from yesterday, I've now got a better idea of what Go's network package is doing with IPv6 and what I think I want it to do.

Go's net package has a very Plan 9 (and Research Unix) approach to networking APIs, where it makes no particular attemtp to expose some version of the standard sockets API but instead goes its own, higher level way. As part of this it has three flavours of each sort of IP-based networking; for TCP, for example, these are tcp4 ('IPv4-only'), tcp6 ('IPv6-only'), and the generic tcp (cf the description of net.Dial()).

The question is what Unix socket type you use for each setting; IPv4, IPv6 with dual binding turned off, or IPv6 with dual binding turned on. How I think it would ideally work is this:

  • the *4 flavours use AF_INET (IPv4) sockets. (This is the current behavior and works fine.)

  • the *6 flavours use AF_INET6 (IPv6) sockets with dual binding off. This is consistent with the net package's documentation and is the only way to allow you to listen separately for IPv6 and IPv4 versions of the same port (including cooperating with non-Go programs that are listening on the IPv4 version of a port).

  • the generic flavours use IPv6 sockets with dual binding on (because that is the 'allows anything' option), with two exceptions. They use IPv4 sockets if either the system doesn't have IPv6 enabled at all or the connection involves only IPv4 addresses (because I think that the socket type used should match the actual wire level protocol that will get used when we know what it is).

The one wrinkle with getting to my ideal situation is that the current Go self tests explicitly make connections to IPv4 addresses using tcp6 networking. This is intrinsically unportable, as there are Unixes where you cannot enable dual binding (OpenBSD is the one I know of, although Go has not been ported to it). If you ignore that, you can make the code turn dual binding on for this case when you detect it.

(Sufficiently perverse tests will defeat this.)

Right now what Go does for the non *4 flavours on an IPv6-enabled system is to use IPv6 with the system default dual binding settings; this works okay on a machine that defaults to dual binding being on, but very badly on a machine with it defaulting to off. The Go people seem to want to turn dual binding on all the time when using IPv6 sockets in order to fix this; I maintain that this is the wrong decision, and besides it's not completely portable (cf OpenBSD).

I have a hacked up version of the Go net package that is most of the way to my ideal situation, but I think I'm missing a corner case or two. It turned out to be relatively easy to do but also somewhat ugly.

(As a language, I am half enthused and half unenthused about Go for reasons that don't fit within the margins of this entry.)

Written on 10 September 2010.
« Go, IPv6, and single binding machines
A simple thing that every package management system should have »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Fri Sep 10 01:32:53 2010
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.