Ticket #1212: ipv6.4.patch

File ipv6.4.patch, 21.7 KB (added by guest, 7 years ago)
Line 
1
2New patches:
3
4[Add IPv6 support.
5Bryan O'Sullivan <bos@serpentine.com>**20070403065512
6 
7 The only public API changes are to Network.Socket, which has the following
8 exported names added (no existing names have been removed):
9 
10     -- IPv6 address components
11     HostAddress6
12     FlowInfo
13     ScopeID
14 
15     -- Name -> address lookup
16     getAddrInfo
17     AddrInfo
18     AddrInfoFlag
19     defaultHints
20 
21     -- Address -> name lookup
22     getNameInfo
23     NameInfoFlag
24 
25 The SockAddr type acquires a new branch, SockAddr6.  (This could cause
26 new "non-exhaustive matches" warnings when compiling pre-existing client
27 code that pattern-matches on SockAddr values.  However, it will not
28 cause runtime pattern failure errors in clients using the pre-existing
29 IPv4 entry points, as they will never see IPv6 addresses.)
30 
31 This change moves a few type names from Network.BSD to Network.Socket:
32 
33     HostName
34     ServiceName
35 
36 These names are still re-exported from Network.BSD, so pre-existing code
37 should not be affected.
38] {
39hunk ./Network/BSD.hsc 117
40-type HostName     = String
41hunk ./Network/BSD.hsc 118
42-type ServiceName  = String
43hunk ./Network/BSD.hsc 299
44--- | This is the default protocol for the given service.
45-defaultProtocol :: ProtocolNumber
46-defaultProtocol = 0
47-
48hunk ./Network/Socket.hsc 54
49+#if defined(IPV6_SOCKET_SUPPORT)
50+    HostAddress6,
51+    FlowInfo,
52+    ScopeID,
53+#endif
54hunk ./Network/Socket.hsc 65
55+    -- * Address operations
56+
57+#if defined(IPV6_SOCKET_SUPPORT)
58+    AddrInfo(..),
59+
60+    AddrInfoFlag(..),
61+
62+    HostName,
63+    ServiceName,
64+
65+    defaultHints,           -- :: AddrInfo
66+    defaultProtocol,        -- :: ProtocolNumber
67+
68+    getAddrInfo,            -- :: Maybe AddrInfo -> Maybe HostName -> Maybe ServiceName -> IO [AddrInfo]
69+
70+    NameInfoFlag(..),
71+
72+    getNameInfo,            -- :: [NameInfoFlag] -> Bool -> Bool -> SockAddr -> IO (Maybe HostName, Maybe ServiceName)
73+#endif
74+
75hunk ./Network/Socket.hsc 148
76+#if defined(IPV6_SOCKET_SUPPORT)
77+    iN6ADDR_ANY,       -- :: HostAddress6
78+#endif
79hunk ./Network/Socket.hsc 194
80+import Data.Bits
81+import Data.List (foldl')
82hunk ./Network/Socket.hsc 197
83-import Foreign.Ptr ( Ptr, castPtr, plusPtr )
84+import Foreign.Ptr ( Ptr, castPtr, nullPtr, plusPtr )
85hunk ./Network/Socket.hsc 200
86-import Foreign.C.String ( withCString, peekCString, peekCStringLen, castCharToCChar )
87+import Foreign.C.String ( CString, withCString, peekCString, peekCStringLen, castCharToCChar )
88hunk ./Network/Socket.hsc 204
89-import Foreign.Marshal.Utils ( with )
90+import Foreign.Marshal.Utils ( maybeWith, with )
91hunk ./Network/Socket.hsc 227
92+type HostName       = String
93+type ServiceName    = String
94+
95hunk ./Network/Socket.hsc 291
96+-- | This is the default protocol for a given service.
97+defaultProtocol :: ProtocolNumber
98+defaultProtocol = 0
99+
100hunk ./Network/Socket.hsc 300
101+#if defined(IPV6_SOCKET_SUPPORT)
102+type HostAddress6 = (Word32, Word32, Word32, Word32)
103+#endif
104+
105hunk ./Network/Socket.hsc 374
106--- families. Currently only Unix domain sockets and the Internet family
107--- are supported.
108+-- families. Currently only Unix domain sockets and the Internet
109+-- families are supported.
110+
111+#if defined(IPV6_SOCKET_SUPPORT)
112+type FlowInfo = Word32
113+type ScopeID = Word32
114+#endif
115hunk ./Network/Socket.hsc 386
116+#if defined(IPV6_SOCKET_SUPPORT)
117+  | SockAddrInet6
118+        PortNumber      -- sin6_port (network byte order)
119+        FlowInfo        -- sin6_flowinfo (ditto)
120+        HostAddress6    -- sin6_addr (ditto)
121+        ScopeID         -- sin6_scope_id (ditto)
122+#endif
123hunk ./Network/Socket.hsc 417
124+#if defined(IPV6_SOCKET_SUPPORT)
125+  showsPrec _ addr@(SockAddrInet6 port _ _ _)
126+   = showChar '['
127+   . showString (unsafePerformIO $
128+                 fst `liftM` getNameInfo [NI_NUMERICHOST] True False addr >>=
129+                 maybe (fail "showsPrec: impossible internal error") return)
130+   . showString "]:"
131+   . shows port
132+
133+instance Storable HostAddress6 where
134+    sizeOf _    = (#const sizeof(struct in6_addr))
135+    alignment _ = alignment (undefined :: CInt)
136+
137+    peek p = do
138+        a <- (#peek struct in6_addr, s6_addr32[0]) p
139+        b <- (#peek struct in6_addr, s6_addr32[1]) p
140+        c <- (#peek struct in6_addr, s6_addr32[2]) p
141+        d <- (#peek struct in6_addr, s6_addr32[3]) p
142+        return (a, b, c, d)
143+
144+    poke p (a, b, c, d) = do
145+        (#poke struct in6_addr, s6_addr32[0]) p a
146+        (#poke struct in6_addr, s6_addr32[1]) p b
147+        (#poke struct in6_addr, s6_addr32[2]) p c
148+        (#poke struct in6_addr, s6_addr32[3]) p d
149+#endif
150hunk ./Network/Socket.hsc 464
151+#if defined(IPV6_SOCKET_SUPPORT)
152+pokeSockAddr p (SockAddrInet6 (PortNum port) flow addr scope) = do
153+#if defined(darwin_TARGET_OS)
154+       zeroMemory p (#const sizeof(struct sockaddr_in6))
155+#endif
156+       (#poke struct sockaddr_in6, sin6_family) p ((#const AF_INET6) :: CSaFamily)
157+       (#poke struct sockaddr_in6, sin6_port) p port
158+       (#poke struct sockaddr_in6, sin6_flowinfo) p flow
159+       (#poke struct sockaddr_in6, sin6_addr) p addr   
160+       (#poke struct sockaddr_in6, sin6_scope_id) p scope
161+#endif
162+
163+peekSockAddr :: Ptr SockAddr -> IO SockAddr
164hunk ./Network/Socket.hsc 490
165+#if defined(IPV6_SOCKET_SUPPORT)
166+       (#const AF_INET6) -> do
167+               port <- (#peek struct sockaddr_in6, sin6_port) p
168+               flow <- (#peek struct sockaddr_in6, sin6_flowinfo) p
169+               addr <- (#peek struct sockaddr_in6, sin6_addr) p
170+               scope <- (#peek struct sockaddr_in6, sin6_scope_id) p
171+               return (SockAddrInet6 (PortNum port) flow addr scope)
172+#endif
173hunk ./Network/Socket.hsc 515
174+#if defined(IPV6_SOCKET_SUPPORT)
175+sizeOfSockAddr (SockAddrInet6 _ _ _ _) = #const sizeof(struct sockaddr_in6)
176+#endif
177hunk ./Network/Socket.hsc 901
178+#if defined(IPV6_SOCKET_SUPPORT)
179+socketPort sock@(MkSocket _ AF_INET6 _ _ _) = do
180+    (SockAddrInet6 port _ _ _) <- getSocketName sock
181+    return port
182+#endif
183hunk ./Network/Socket.hsc 1243
184+unpackSocketType:: CInt -> SocketType
185hunk ./Network/Socket.hsc 1886
186+unpackSocketType t = case t of
187+       0 -> NoSocketType
188+#ifdef SOCK_STREAM
189+       (#const SOCK_STREAM) -> Stream
190+#endif
191+#ifdef SOCK_DGRAM
192+       (#const SOCK_DGRAM) -> Datagram
193+#endif
194+#ifdef SOCK_RAW
195+       (#const SOCK_RAW) -> Raw
196+#endif
197+#ifdef SOCK_RDM
198+       (#const SOCK_RDM) -> RDM
199+#endif
200+#ifdef SOCK_SEQPACKET
201+       (#const SOCK_SEQPACKET) -> SeqPacket
202+#endif
203+
204hunk ./Network/Socket.hsc 1910
205+-- | The IPv4 wild card address.
206+
207hunk ./Network/Socket.hsc 1915
208+#if defined(IPV6_SOCKET_SUPPORT)
209+-- | The IPv6 wild card address.
210+
211+iN6ADDR_ANY :: HostAddress6
212+iN6ADDR_ANY = (0, 0, 0, 0)
213+#endif
214+
215hunk ./Network/Socket.hsc 2047
216+
217+-- | Pack a list of values into a bitmask.  The possible mappings from
218+-- value to bit-to-set are given as the first argument.  We assume
219+-- that each value can cause exactly one bit to be set; unpackBits will
220+-- break if this property is not true.
221+
222+packBits :: (Eq a, Bits b) => [(a, b)] -> [a] -> b
223+
224+packBits mapping xs = foldl' pack 0 mapping
225+    where pack acc (k, v) | k `elem` xs = acc .|. v
226+                          | otherwise   = acc
227+
228+-- | Unpack a bitmask into a list of values.
229+
230+unpackBits :: Bits b => [(a, b)] -> b -> [a]
231+
232+unpackBits [] 0    = []
233+unpackBits [] r    = error ("unpackBits: unhandled bits set: " ++ show r)
234+unpackBits ((k,v):xs) r
235+    | r .&. v /= 0 = k : unpackBits xs (r .&. complement v)
236+    | otherwise    = unpackBits xs r
237+
238+-----------------------------------------------------------------------------
239+-- Address and service lookups
240+
241+#if defined(IPV6_SOCKET_SUPPORT)
242+
243+-- | Flags that control the querying behaviour of 'getAddrInfo'.
244+data AddrInfoFlag
245+    = AI_ADDRCONFIG
246+    | AI_CANONNAME
247+    | AI_NUMERICHOST
248+    | AI_PASSIVE
249+    deriving (Eq, Read, Show)
250+
251+INSTANCE_TYPEABLE0(AddrInfoFlag,addrInfoFlagTc,"AddrInfoFlag")
252+
253+aiFlagMapping :: [(AddrInfoFlag, CInt)]
254+
255+aiFlagMapping =
256+    [(AI_ADDRCONFIG, #const AI_ADDRCONFIG),
257+     (AI_CANONNAME, #const AI_CANONNAME),
258+     (AI_NUMERICHOST, #const AI_NUMERICHOST),
259+     (AI_PASSIVE, #const AI_PASSIVE)]
260+
261+data AddrInfo =
262+    AddrInfo {
263+        addrFlags :: [AddrInfoFlag],
264+        addrFamily :: Family,
265+        addrSocketType :: SocketType,
266+        addrProtocol :: ProtocolNumber,
267+        addrAddress :: SockAddr,
268+        addrCanonName :: Maybe String
269+        }
270+    deriving (Eq, Show)
271+
272+INSTANCE_TYPEABLE0(AddrInfo,addrInfoTc,"AddrInfo")
273+
274+instance Storable AddrInfo where
275+    sizeOf    _ = #const sizeof(struct addrinfo)
276+    alignment _ = alignment (undefined :: CInt)
277+
278+    peek p = do
279+       ai_flags <- (#peek struct addrinfo, ai_flags) p
280+       ai_family <- (#peek struct addrinfo, ai_family) p
281+       ai_socktype <- (#peek struct addrinfo, ai_socktype) p
282+       ai_protocol <- (#peek struct addrinfo, ai_protocol) p
283+        ai_addr <- (#peek struct addrinfo, ai_addr) p >>= peekSockAddr
284+       ai_canonname_ptr <- (#peek struct addrinfo, ai_canonname) p
285+
286+        ai_canonname <- if ai_canonname_ptr == nullPtr
287+                        then return Nothing
288+                        else liftM Just $ peekCString ai_canonname_ptr
289+                             
290+        return (AddrInfo
291+                {
292+                 addrFlags = unpackBits aiFlagMapping ai_flags,
293+                 addrFamily = unpackFamily ai_family,
294+                 addrSocketType = unpackSocketType ai_socktype,
295+                 addrProtocol = ai_protocol,
296+                 addrAddress = ai_addr,
297+                 addrCanonName = ai_canonname
298+                })
299+
300+    poke p (AddrInfo flags family socketType protocol _ _) = do
301+        (#poke struct addrinfo, ai_flags) p (packBits aiFlagMapping flags)
302+        (#poke struct addrinfo, ai_family) p (packFamily family)
303+        (#poke struct addrinfo, ai_socktype) p (packSocketType socketType)
304+        (#poke struct addrinfo, ai_protocol) p protocol
305+
306+        -- stuff below is probably not needed, but let's zero it for safety
307+
308+        (#poke struct addrinfo, ai_addrlen) p (0::CSize)
309+        (#poke struct addrinfo, ai_addr) p nullPtr
310+        (#poke struct addrinfo, ai_canonname) p nullPtr
311+        (#poke struct addrinfo, ai_next) p nullPtr
312+
313+data NameInfoFlag
314+    = NI_DGRAM
315+    | NI_NAMEREQD
316+    | NI_NOFQDN
317+    | NI_NUMERICHOST
318+    | NI_NUMERICSERV
319+    deriving (Eq, Read, Show)
320+
321+INSTANCE_TYPEABLE0(NameInfoFlag,nameInfoFlagTc,"NameInfoFlag")
322+
323+niFlagMapping :: [(NameInfoFlag, CInt)]
324+
325+niFlagMapping = [(NI_DGRAM, #const NI_DGRAM),
326+                 (NI_NAMEREQD, #const NI_NAMEREQD),
327+                 (NI_NOFQDN, #const NI_NOFQDN),
328+                 (NI_NUMERICHOST, #const NI_NUMERICHOST),
329+                 (NI_NUMERICSERV, #const NI_NUMERICSERV)]
330+
331+-- | Default hints for address lookup with 'getAddrInfo'.  The values
332+-- of the 'addrAddress' and 'addrCanonName' fields are 'undefined',
333+-- and are never inspected by 'getAddrInfo'.
334+
335+defaultHints :: AddrInfo
336+
337+defaultHints = AddrInfo {
338+                         addrFlags = [],
339+                         addrFamily = AF_UNSPEC,
340+                         addrSocketType = NoSocketType,
341+                         addrProtocol = defaultProtocol,
342+                         addrAddress = undefined,
343+                         addrCanonName = undefined
344+                        }
345+
346+-- | Resolve a host or service name to one or more addresses.
347+-- The 'AddrInfo' values that this function returns contain 'SockAddr'
348+-- values that you can pass directly to 'connect' or
349+-- 'bindSocket'.
350+--
351+-- This function is protocol independent.  It can return both IPv4 and
352+-- IPv6 address information.
353+--
354+-- The 'AddrInfo' argument specifies the preferred query behaviour,
355+-- socket options, or protocol.  You can override these conveniently
356+-- using Haskell's record update syntax on 'defaultHints', for example
357+-- as follows:
358+--
359+-- @
360+--   myHints = defaultHints { addrFlags = aI_ADDRCONFIG + aI_CANONNAME }
361+-- @
362+--
363+-- Values for 'addrFlags' control query behaviour.  The supported
364+-- flags are as follows:
365+--
366+--   [@AI_PASSIVE@] If no 'HostName' value is provided, the network
367+--     address in each 'SockAddr'
368+--     will be left as a "wild card", i.e. as either 'iNADDR_ANY'
369+--     or 'iN6ADDR_ANY'.  This is useful for server applications that
370+--     will accept connections from any client.
371+--
372+--   [@AI_CANONNAME@] The 'addrCanonName' field of the first returned
373+--     'AddrInfo' will contain the "canonical name" of the host.
374+--
375+--   [@AI_NUMERICHOST@] The 'HostName' argument /must/ be a numeric
376+--     address in string form, and network name lookups will not be
377+--      attempted.
378+--
379+--   [@AI_ADDRCONFIG@] The list of returned 'AddrInfo' values will only
380+--     contain IPv4 addresses if the local system has at least one
381+--     IPv4 interface configured, and likewise for IPv6.
382+--
383+-- You must provide a 'Just' value for at least one of the 'HostName'
384+-- or 'ServiceName' arguments.  'HostName' can be either a numeric
385+-- network address (dotted quad for IPv4, colon-separated hex for
386+-- IPv6) or a hostname.  In the latter case, its addresses will be
387+-- looked up unless 'AI_NUMERICHOST' is specified as a hint.  If you
388+-- do not provide a 'HostName' value /and/ do not set 'AI_PASSIVE' as
389+-- a hint, network addresses in the result will contain the address of
390+-- the loopback interface.
391+--
392+-- If the query fails, this function throws an IO exception instead of
393+-- returning an empty list.  Otherwise, it returns a non-empty list
394+-- of 'AddrInfo' values.
395+--
396+-- There are several reasons why a query might result in several
397+-- values.  For example, the queried-for host could be multihomed, or
398+-- the service might be available via several protocols.
399+--
400+-- Note: the order of arguments is slightly different to that defined
401+-- for @getaddrinfo@ in RFC 2553.  The 'AddrInfo' parameter comes first
402+-- to make partial application easier.
403+--
404+-- Example:
405+-- @
406+--   let hints = defaultHints { addrFlags = [AI_ADDRCONFIG, AI_CANONNAME] }
407+--   addrs <- getAddrInfo (Just hints) (Just "www.haskell.org") (Just "http")
408+--   let addr = head addrs
409+--   sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
410+--   connect sock (addrAddress addr)
411+-- @
412+
413+getAddrInfo :: Maybe AddrInfo -- ^ preferred socket type or protocol
414+            -> Maybe HostName -- ^ host name to look up
415+            -> Maybe ServiceName -- ^ service name to look up
416+            -> IO [AddrInfo] -- ^ resolved addresses, with "best" first
417+
418+getAddrInfo hints node service =
419+  maybeWith withCString node $ \c_node ->
420+    maybeWith withCString service $ \c_service ->
421+      maybeWith with hints $ \c_hints ->
422+        alloca $ \ptr_ptr_addrs -> do
423+          ret <- c_getaddrinfo c_node c_service c_hints ptr_ptr_addrs
424+          case ret of
425+            0 -> do ptr_addrs <- peek ptr_ptr_addrs
426+                    ais <- followAddrInfo ptr_addrs
427+                    c_freeaddrinfo ptr_addrs
428+                    return ais
429+            _ -> do err <- gai_strerror ret
430+                    ioError (IOError Nothing NoSuchThing "getAddrInfo" err
431+                             Nothing)
432+
433+followAddrInfo :: Ptr AddrInfo -> IO [AddrInfo]
434+
435+followAddrInfo ptr_ai | ptr_ai == nullPtr = return []
436+                      | otherwise = do
437+    a <- peek ptr_ai
438+    as <- (#peek struct addrinfo, ai_next) ptr_ai >>= followAddrInfo
439+    return (a:as)
440+
441+foreign import ccall safe "getaddrinfo"
442+    c_getaddrinfo :: CString -> CString -> Ptr AddrInfo -> Ptr (Ptr AddrInfo)
443+                  -> IO CInt
444+
445+foreign import ccall safe "freeaddrinfo"
446+    c_freeaddrinfo :: Ptr AddrInfo -> IO ()
447+
448+gai_strerror :: CInt -> IO String
449+
450+gai_strerror n = c_gai_strerror n >>= peekCString
451+
452+foreign import ccall safe "gai_strerror"
453+    c_gai_strerror :: CInt -> IO CString
454+
455+withCStringIf :: Bool -> Int -> (CSize -> CString -> IO a) -> IO a
456+withCStringIf False _ f = f 0 nullPtr
457+withCStringIf True n f = allocaBytes n (f (fromIntegral n))
458+                   
459+-- | Resolve an address to a host or service name.
460+-- This function is protocol independent.
461+--
462+-- The list of 'NameInfoFlag' values controls query behaviour.  The
463+-- supported flags are as follows:
464+--
465+--   [@NI_NOFQDN@] If a host is local, return only the
466+--     hostname part of the FQDN.
467+--
468+--   [@NI_NUMERICHOST@] The name of the host is not
469+--     looked up.  Instead, a numeric representation of the host's
470+--     address is returned.
471+--
472+--   [@NI_NUMERICSERV@] The name of the service is not
473+--     looked up.  Instead, a numeric representation of the
474+--     service is returned.
475+--
476+--   [@NI_NAMEREQD@] If the hostname cannot be looked up, an IO error
477+--     is thrown.
478+--
479+--   [@NI_DGRAM@] Resolve a datagram-based service name.  This is
480+--     required for the few protocols that have different port numbers
481+--     for their datagram-based versions than for their stream-based
482+--     versions.
483+--
484+-- Hostname and service name lookups can be expensive.  You can
485+-- specify which lookups to perform via the two 'Bool' arguments.  If
486+-- one of these is 'False', the corresponding value in the returned
487+-- tuple will be 'Nothing', and no lookup will be performed.
488+--
489+-- If a host or service's name cannot be looked up, then the numeric
490+-- form of the address or service will be returned.
491+--
492+-- If the query fails, this function throws an IO exception.
493+
494+getNameInfo :: [NameInfoFlag] -- ^ flags to control lookup behaviour
495+            -> Bool -- ^ whether to look up a hostname
496+            -> Bool -- ^ whether to look up a service name
497+            -> SockAddr -- ^ the address to look up
498+            -> IO (Maybe HostName, Maybe ServiceName)
499+
500+getNameInfo flags doHost doService addr =
501+  withCStringIf doHost (#const NI_MAXHOST) $ \c_hostlen c_host ->
502+    withCStringIf doService (#const NI_MAXSERV) $ \c_servlen c_serv -> do
503+      withSockAddr addr $ \ptr_addr sz -> do
504+        ret <- c_getnameinfo ptr_addr (fromIntegral sz) c_host c_hostlen
505+                             c_serv c_servlen (packBits niFlagMapping flags)
506+        case ret of
507+          0 -> do
508+            let peekIf doIf c_val = if doIf
509+                                     then liftM Just $ peekCString c_val
510+                                     else return Nothing
511+            host <- peekIf doHost c_host
512+            serv <- peekIf doService c_serv
513+            return (host, serv)
514+          _ -> do err <- gai_strerror ret
515+                  ioError (IOError Nothing NoSuchThing "getNameInfo" err
516+                           Nothing)
517+
518+foreign import ccall safe "getnameinfo"
519+    c_getnameinfo :: Ptr SockAddr -> CInt{-CSockLen???-} -> CString -> CSize -> CString
520+                  -> CSize -> CInt -> IO CInt
521+#endif
522hunk ./configure.ac 37
523+dnl --------------------------------------------------
524+dnl * test for in6_addr as proxy for IPv6 support
525+dnl --------------------------------------------------
526+AC_MSG_CHECKING(for in6_addr in netinet/in.h)
527+AC_EGREP_HEADER(in6_addr, netinet/in.h,
528+ [ AC_DEFINE([HAVE_IN6_ADDR], [1], [Define to 1 if in6_addr is available.]) AC_MSG_RESULT(yes) ],
529+ AC_MSG_RESULT(no))
530+
531hunk ./include/HsNet.h 28
532+
533+#ifdef HAVE_IN6_ADDR
534+# define IPV6_SOCKET_SUPPORT 1
535+#else
536+# undef IPV6_SOCKET_SUPPORT
537+#endif
538}
539
540Context:
541
542[apply changes from patch "make this test deterministic on a multiprocessor" in testsuite
543Simon Marlow <simonmar@microsoft.com>**20070221142822]
544[tests for use with GHC's test framework, moved from the testsuite
545Simon Marlow <simonmar@microsoft.com>**20070221142258]
546[README about building from darcs
547Ross Paterson <ross@soi.city.ac.uk>**20070218110201]
548[don't install Typeable.h, fixes #1106
549Simon Marlow <simonmar@microsoft.com>**20070201125821]
550[network doesn't really need the html package
551Ian Lynagh <igloo@earth.li>**20070111122348]
552[includes -> install-includes
553Ross Paterson <ross@soi.city.ac.uk>**20060829123744]
554[change title to Haskell Hierarchical Libraries
555Ross Paterson <ross@soi.city.ac.uk>**20060827131348]
556[exclude Setup.hs from build
557Ross Paterson <ross@soi.city.ac.uk>**20060824183533]
558[add boilerplate Setup.hs
559Ross Paterson <ross@soi.city.ac.uk>**20060824115019]
560[Update Network.BSD header to not mention symlinks.
561Ian Lynagh <igloo@earth.li>**20060823184314]
562[Removed Network.CGI from the network package. A backwards-compatible new Network.CGI is available in the cgi package.
563bringert@cs.chalmers.se**20060814095652]
564[remove deprecated Network.BSD.{readlink,symlink}
565Simon Marlow <simonmar@microsoft.com>**20060811153755]
566[bump version to 2.0
567Simon Marlow <simonmar@microsoft.com>**20060811152554]
568[depend on html (for the time being)
569Simon Marlow <simonmar@microsoft.com>**20060810121424]
570[initWinSock(): have defn match proto
571sof@galois.com**20060613224903]
572[only GHC has rtsSupportsBoundThreads
573Ross Paterson <ross@soi.city.ac.uk>**20060531200123]
574[add files used by configure
575Ross Paterson <ross@soi.city.ac.uk>**20060518174356]
576[Import unsafePerformIO
577Sven Panne <sven.panne@aedion.de>**20060507171832]
578[Import MVar type
579Sven Panne <sven.panne@aedion.de>**20060507170308]
580[Add various address families
581Simon Marlow <simonmar@microsoft.com>**20060503081915]
582[Fix for #265, build problem on AIX
583Simon Marlow <simonmar@microsoft.com>**20060316143337
584 Not the fix from the ticket, but this one at least doesn't require
585 modifying the configure script.
586]
587[workaround for non-thread-safety of some functions in Network.BSD
588Simon Marlow <simonmar@microsoft.com>**20060126153014
589 Various functions in Network.BSD are non-thread-safe,
590 eg. getHostByName, because the underlying gethostbyname() provided by
591 the C library uses static storage.  The workaround here is to use a
592 giant lock around these functions.
593 
594 In some cases, even the API we provide is itself unsafe, relying on
595 implicit state (eg. getHostEntry), but this commit makes no attempt to
596 fix that.  We should deprecate this library in favour of a complete
597 replacement at some point (before 6.6 would be nice).
598 
599 Thanks to Einar Kartunnen for the patch.
600]
601[Fix Ticket 647, Socket bug on Mac OS X
602wolfgang.thaller@gmx.net**20060121050509
603 Patch kindly provided by Greg Wright
604]
605[TAG Initial conversion from CVS complete
606John Goerzen <jgoerzen@complete.org>**20060112154134]
607Patch bundle hash:
6085ea614c8eadaf4f27ea7d0cb4a95a7268ecf8cac