Ticket #2103 (closed bug: fixed)

Opened 5 years ago

Last modified 5 years ago

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: Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

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

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

Change History

Changed 5 years ago by iquiw

Changed 5 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}]

Changed 5 years ago by iquiw

  • summary changed from Some functions do not work on NetBSD to Some functions in network library do not work on NetBSD

Changed 5 years ago by igloo

  • difficulty set to Unknown
  • milestone set to 6.8.3

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

Changed 5 years ago by igloo

  • status changed from new to closed
  • resolution set to fixed

Patch applied, thanks!

Changed 5 years ago by cjs

  • status changed from closed to reopened
  • version changed from 6.8.2 to 6.8.3
  • resolution fixed deleted
  • architecture changed from Unknown to x86
  • severity changed from normal to major

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.

Changed 5 years ago by simonmar

  • priority changed from normal to high
  • milestone changed from 6.8.3 to 6.10.1

Changed 5 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.

Changed 5 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  *.*     

Changed 5 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

Changed 5 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.

Changed 5 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)

Changed 5 years ago by igloo

  • status changed from reopened to closed
  • resolution set to fixed
  • milestone changed from 6.10.1 to 6.8.3

Thanks for clearing that up, iquiw!

Note: See TracTickets for help on using tickets.