Opened 12 years ago

Closed 11 years ago

#2103 closed bug (fixed)

Some functions in network library do not work on NetBSD

Reported by: iquiw Owned by:
Priority: high Milestone: 6.8.3
Component: libraries/network Version: 6.8.3
Keywords: network Cc:
Operating System: NetBSD Architecture: x86
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

I found two problems in network library that occurs on NetBSD.
I created a patch to fix them. I tested it on NetBSD only.

(1) listenOn does not work with numerical port number.
This is caused by getAddrInfo used in listen' function.
On NetBSD, we need to specify addrSocketType of addrinfo hints for getAddrInfo.
I think this bug happens on FreeBSD also though I did not confirm it.

(2) getNameInfo fails always.
This is because of difference of sockaddr structure.
struct sockaddr_* has its struct size as the first member of struct on *BSD system, but pokeSockAddr does not poke it.
AFAIK, only NetBSD check this size strictly.

Attachments (1)

network-NetBSD.patch (1.6 KB) - added by iquiw 12 years ago.

Download all attachments as: .zip

Change History (13)

Changed 12 years ago by iquiw

Attachment: network-NetBSD.patch added

comment:1 Changed 12 years ago by iquiw

Keywords: network added

Sample programs to causes the problems.

(1) sample1.hs

import Network

main = listenOn (PortNumber 8000)

Before the attached patch is applied,

$ runghc sample1.hs
sample1.hs: getAddrInfo: does not exist (servname not supported for ai_socktype)

After, no error.

(2) sample2.hs

import Network

main = print =<< getAddrInfo Nothing Nothing (Just "http")

Before the patch,

$ runghc sample2.hs
[AddrInfo {addrFlags = [], addrFamily = AF_INET6, addrSocketType = Datagram, addrProtocol = 17, addrAddress = [b.hs: getNameInfo: does not exist (Non-recoverable failure in name resolution)

After,

$ runghc sample2.hs
[AddrInfo {addrFlags = [], addrFamily = AF_INET6, addrSocketType = Datagram, addrProtocol = 17, addrAddress = [::1]:80, addrCanonName = Nothing},AddrInfo {addrFlags = [], addrFamily = AF_INET6, addrSocketType = Stream, addrProtocol = 6, addrAddress = [::1]:80, addrCanonName = Nothing},AddrInfo {addrFlags = [], addrFamily = AF_INET, addrSocketType = Datagram, addrProtocol = 17, addrAddress = 127.0.0.1:80, addrCanonName = Nothing},AddrInfo {addrFlags = [], addrFamily = AF_INET, addrSocketType = Stream, addrProtocol = 6, addrAddress = 127.0.0.1:80, addrCanonName = Nothing}]

comment:2 Changed 12 years ago by iquiw

Summary: Some functions do not work on NetBSDSome functions in network library do not work on NetBSD

comment:3 Changed 12 years ago by igloo

difficulty: Unknown
Milestone: 6.8.3

Thanks for the report and patch! We'll take a look.

comment:4 Changed 12 years ago by igloo

Resolution: fixed
Status: newclosed

Patch applied, thanks!

comment:5 Changed 11 years ago by cjs

Architecture: Unknownx86
Resolution: fixed
severity: normalmajor
Status: closedreopened
Version: 6.8.26.8.3

Listen does not appear to be entirely fixed yet. This program, when run, does not appear to be listening on port 4444, when tested both via looking at "netstat -anf inet" (port 4444 is not present) and by trying to connect on localhost (the connection is refused).

import IO
import Network

p4444 = PortNumber 4444
punix = UnixSocket "/tmp/l"

main_bad = do
    s <- listenOn p4444
    (h, hostName, portNum) <- Network.accept s
    putStrLn $ "Connection from " ++ hostName ++ ":" ++ show portNum
    hPutStrLn h "Bye!"
    hClose h

The program does work on a Unix-domain socket.

comment:6 Changed 11 years ago by simonmar

Milestone: 6.8.36.10.1
Priority: normalhigh

comment:7 Changed 11 years ago by igloo

The network package currently doesn't have a maintainer, and as far as I know none of the developers have a NetBSD machine, so if anyone out there with a NetBSD machine is able to look into this then that would be very helpful.

By the way, note that the network package isn't part of the actual GHC release, and even if you got it bundled with a bindist, you can still upgrade it separately.

comment:8 Changed 11 years ago by iquiw

I don't know whether it is bug or not.
NetBSD's getaddrinfo() returns IPv6 addrinfo first, so I think the socket in the program is bound to IPv6 address.

Here is output of "netstat -nf inet6" when the program runs.

$ netstat -nf inet6
Active Internet6 connections
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
tcp6       0      0  *.4444                 *.*                    LISTEN
tcp6       0      0  *.6000                 *.*                    LISTEN
tcp6       0      0  *.25                   *.*                    LISTEN
tcp6       0      0  *.22                   *.*                    LISTEN
udp6       0      0  *.*     

comment:9 Changed 11 years ago by cjs

iquiw: Thanks! I'd never thought to check IPv6. Indeed, it is listening on IPv6, and I can successfully connect to it (using telnet) and see the output. I think there ought to be a way to use IPv4 with Network, but I'll file another report for that.

However, I still seem to have some issues here. Before I filed my first comment here, I also tried using Network.Socket, with no luck. This program appears not to listen on any network protocol:

import IO
import Network.Socket

main = do
    s <- socket AF_INET Stream defaultProtocol
    bindSocket s (SockAddrInet (PortNum 4444) iNADDR_ANY)
    listen s 7
    print s
    (ss, sa) <- Network.Socket.accept s
    print ss
    print sa

Just to check, I did an IPv6 version of this, and it has the same issue, though I'm not perfectly certain that a FlowInfo and ScopeID of 0 are correct.

import IO
import Network.Socket

main = do
    s <- socket AF_INET6 Stream defaultProtocol
    bindSocket s (SockAddrInet6 (PortNum 4444) 0 iN6ADDR_ANY 0)
    listen s 7
    print s
    (ss, sa) <- Network.Socket.accept s
    print ss
    print sa

comment:10 Changed 11 years ago by cjs

By the way, I am available much of the day and evening, Tokyo time, for IM conversations, testing, and so on; drop me an e-mail at <cjs@…> if you want to get in touch that way.

comment:11 Changed 11 years ago by iquiw

PortNum stores port number in network byte order internally. So you can either

(1) get rid of PortNum constructor and use just "4444".

bindSocket s (SockAddrInet 4444 iNADDR_ANY)

or

(2) connect to port 23569 (= htons(4444) on x86 machine)

comment:12 Changed 11 years ago by igloo

Milestone: 6.10.16.8.3
Resolution: fixed
Status: reopenedclosed

Thanks for clearing that up, iquiw!

Note: See TracTickets for help on using tickets.