#2391 Network.listenOn (PortNumber n) Sometimes Picks IPv6

Aaron Denney wnoise at ofb.net
Mon Jul 21 06:09:06 EDT 2008

On 2008-07-21, Curt Sampson <cjs at starling-software.com> wrote:
> So this has been sitting around for a bit:
>     http://hackage.haskell.org/trac/ghc/ticket/2391
> And I'm sort of hoping we can get it resolved soon so that a fixed
> version is included in GHC 6.10.
> My basic thoughts are:
> 1. Listening on both IPV4 and IPV6, if I recall correctly,
> introduces all sorts of interesting problems, and basically, you
> don't want to go there. Or am I wrong about that?

I don't see why it would introduce any more problems than listening
on multiple IPv4 addresses, which is routine.  However, this isn't
something that listenOn can easily do by itself.

The difficulty is, of course, is that listening on multiple points
means having to multiplex them and select between them.  I had heard
that some OSes attempt to make it easier to transparently run old IPv4
programs by interpreting binding to all IPv4 addresses to include binding
to IPv6, (or even vice-versa!), making it easy for addresses you don't
want bound (say, because you want a different daemon handling it) to be bound.

Basically, my position is that listenOn is the wrong interface -- it
should take the host addresses as well as the port.  The ports are the
same namespace -- it shouldn't matter (much) whether TCP is running over
IPv4 or IPv6.

> 2. We should default to IPv4 if someone uses the current interface, as
> that's what most people will be expecting, as that's the Linux (and
> probably Windows) behvaiour.

For a friendly interface, I'd have guessed they'd want to bind to both.
But again, that's not trivial to portably shoehorn into one listening

When IPv6 is enabled, it calls getaddrinfo(), which should return both
IPv6 and IPv4 connection results.  But it looks like only the first one
is being used, when both are valid:

>    addrs <- getAddrInfo (Just hints) Nothing (Just serv)
>    let addr = head addrs

We could get around this by returning a composite pseudo-socket,
representing both, and modifying Network.accept to take this
pseudo-socket and wait for connections on any of the real sockets.
But it's a bit ugly.  And these pseudo-sockets won't work with
Network.Socket.accept.  If we give it a new type, I'm not entirely
sure it's that bad a thing though.

Aaron Denney

More information about the Libraries mailing list