id,summary,reporter,owner,description,type,status,priority,milestone,component,version,resolution,keywords,cc
11,Network.listenOn (PortNumber n) Sometimes Picks IPv6,tibbe,bos,"When I run the following program on a NetBSD system, it listens on *.4444 for IPv6, not IPv4. This could certainly happen on other operating systems as well, though I've not tested others. Whether it happens or not could even vary from release to release.

{{{
import IO
import Network

main = do
    s <- listenOn (PortNumber 4444)
    (h, hostName, portNum) <- Network.accept s
    putStrLn $ ""Connection from "" ++ hostName ++ "":"" ++ show portNum
    hPutStrLn h ""Bye!""
    hClose h
}}}

I've verified that telnet 127.0.0.1 4444 produces a ""connection refused"" message, but telnet ::1 4444 connects and displays ""Bye!""

I'd go so far to say that this is a bug. At best, one could argue that this behaviour is not entirely intuitive.

I propose that we (re-?)define `PortID`'s `PortNumber` constructor to refer only to IPv4 protocol ports, and add a new `PortNumber6` constructor for IPv6 ports.

Another option would be to do force `PortNumber` always to bind to IPv4, but not add `PortNumber6`. I prefer this less because we should be encouraging the use of IPv6, and because having `PortNumber6` serves as obvious documentation for what `PortNumber` and `PortNumber6` do.

A third option would be to attempt to listen on both IPv4 and IPv6, when both are available, but this sort of thing is fraught with many problems, the details of which are much more than I'd want to get into in this bug report. 

----

I saw exactly the same problem on FreeBSD.

    I propose that we (re-?)define `PortID`'s `PortNumber` constructor to refer only to IPv4 protocol ports, and add a new `PortNumber6` constructor for IPv6 ports.

That sounds highly reasonable. I prefer that way.

----

This sounds like a peculiarity of the BSD networking stack. On Linux, the code correctly chooses a wildcard address that responds to both IPv4 and IPv6 traffic.

I'd strongly suggest that a BSD user dig into the platform-specific problem. Suggesting an API change without any investigation of the underlying issue is not the right approach.

----

Actually, the linux code incorrectly binds to both; this opens up a security problem, though I can't remember the exact details right now. This is exactly the reason for the default sysctl setting of ""net.inet6.ip6.v6only = 1"", IIRC.

----

Here is a document discussing the security issues with IPv4-mapped addresses:

    ftp://ftp.itojun.org/pub/paper/draft-itojun-v6ops-v4mapped-harmful-01.txt

I'd say we definitely don't want to have to force people to enable this just to use Network, which is in the end supposed to make life simpler for basic networking.

----

The Linux behaviour does not appear to me to be incorrect, and the document to which you refer is concerned with threats due to the use of IPv4-mapped addresses on the wire.

The code in the `Network` module uses the `Network.Socket` code for its implementation. There are currently several knobs for controlling `getAddrInfo` that it does not use. Perhaps if you read up on a few of them and try them out, you might find a behaviour that you could then propose as more desirable.
",defect,new,major,,network,,,,pho@… cjs@…
