Commit 5698952aa07e83659df7456635c302efe7cfd600

  • avatar
  • Peter Simons (Committer)
  • Fri Feb 26 00:00:02 CET 2010
  • avatar
  • Григорий Холомьёв <omever @gm…l.com> (Author)
  • Fri Nov 13 19:57:17 CET 2009
Added support for resolving SRV records.
ADNS.hs
(6 / 2)
  
1717module ADNS
1818 ( HostName, HostAddress
1919 , Resolver, initResolver, InitFlag(..)
20 , queryA, queryPTR, queryMX
20 , queryA, queryPTR, queryMX, querySRV
2121 , dummyDNS
2222 )
2323 where
2424
25import Network ( HostName )
25import Network ( HostName, PortID )
2626import Network.Socket ( HostAddress )
2727import ADNS.Base
2828import ADNS.Resolver
2929
3030queryA :: Resolver -> HostName -> IO (Maybe [HostAddress])
3131queryA = query resolveA
32
33-- | For quering SRV records. Result is the list of tuples (host, port)
34querySRV :: Resolver -> HostName -> IO (Maybe [(HostName, PortID)])
35querySRV = query resolveSRV
3236
3337queryPTR :: Resolver -> HostAddress -> IO (Maybe [HostName])
3438queryPTR = query resolvePTR
  
112112
113113data RRType = A | CNAME | MX | NS | PTR
114114 | NSEC
115 | SRV
115116 | RRType Int
116117 deriving (Read)
117118
127127 NS -> showString "NS"
128128 PTR -> showString "PTR"
129129 NSEC -> showString "NSEC"
130 SRV -> showString "SRV"
130131 (RRType i) -> showString "TYPE" . shows i
131132
132133instance Enum RRType where
136136 toEnum #{const adns_r_mx} = MX
137137 toEnum #{const adns_r_ns} = NS
138138 toEnum #{const adns_r_ptr} = PTR
139 toEnum #{const adns_r_srv} = SRV
139140 toEnum x = case x .&. #{const adns_rrt_typemask} of
140141 47 -> NSEC
141142 i -> RRType i
146146 fromEnum MX = #{const adns_r_mx}
147147 fromEnum NS = #{const adns_r_ns}
148148 fromEnum PTR = #{const adns_r_ptr}
149 fromEnum SRV = #{const adns_r_srv}
149150 fromEnum x = #{const adns_r_unknown} .|. case x of
150151 NSEC -> 47
151152 (RRType i) -> i
313313 p <- #{peek adns_rr_byteblock, data} ptr
314314 return (RRByteblock (fromEnum l) p)
315315
316-- |Original definition:
317--
318-- > typedef struct {
319-- > int priority, weight, port;
320-- > char *host;
321-- > } adns_rr_srvraw;
322
323data RRSrvRaw = RRSrvRaw Int Int Int (Ptr CChar)
324
325instance Storable RRSrvRaw where
326 sizeOf _ = #{size adns_rr_srvraw}
327 alignment _ = alignment (undefined :: CInt)
328 poke _ _ = fail "poke is undefined for Network.DNS.ADNS.RRSrvRaw"
329 peek ptr = do
330 pr <- #{peek adns_rr_srvraw, priority} ptr :: IO CInt
331 w <- #{peek adns_rr_srvraw, weight} ptr :: IO CInt
332 po <- #{peek adns_rr_srvraw, port} ptr :: IO CInt
333 h <- #{peek adns_rr_srvraw, host} ptr
334 return (RRSrvRaw (fromEnum pr) (fromEnum w) (fromEnum po) h)
335
316336data Answer = Answer
317337 { status :: Status
318338 -- ^ Status code for this query.
355355 | RRPTR String
356356 | RRNSEC String
357357 | RRUNKNOWN String
358 | RRSRV Int Int Int String
358359 deriving (Show)
359360
360361instance Storable Answer where
397397 parseByType A = peek (castPtr ptr) >>= return . RRA . RRAddr
398398 parseByType NS = peek (castPtr ptr) >>= return . RRNS
399399 parseByType PTR = peek (castPtr ptr) >>= peekCString >>= return . RRPTR
400 parseByType SRV = do (RRSrvRaw prio weight port host) <- peek (castPtr ptr)
401 host' <- peekCString host
402 return (RRSRV prio weight port host')
400403 parseByType MX = do (RRIntHostAddr i addr) <- peek (castPtr ptr)
401404 return (RRMX i addr)
402405 parseByType CNAME = peek (castPtr ptr) >>= peekCString >>= return . RRCNAME
  
1616 ( Resolver
1717 , initResolver
1818 , toPTR
19 , resolveA, resolvePTR, resolveMX
19 , resolveA, resolvePTR, resolveMX, resolveSRV
2020 , query
2121 , dummyDNS
2222 )
2828import Data.List ( sortBy )
2929import Data.Map ( Map )
3030import qualified Data.Map as Map
31import Network ( HostName )
31import Network
3232import Network.Socket ( HostAddress )
3333import ADNS.Base
3434import ADNS.Endian
5858 if rc /= sOK
5959 then return (Left rc)
6060 else return (Right [ addr | RRA (RRAddr addr) <- rs ])
61
62-- |Resolve a hostname's 'SRV' records.
63
64resolveSRV :: Resolver -> HostName -> IO (Either Status [(HostName, PortID)])
65resolveSRV resolver x = do
66 Answer rc _ _ _ rs <- resolver x SRV [] >>= takeMVar
67 if rc /= sOK
68 then return (Left rc)
69 else do
70 let cmp (RRSRV p1 _ _ _) (RRSRV p2 _ _ _) = compare p1 p2
71 cmp _ _ = error $ showString "unexpected record in SRV lookup: " (show rs)
72 rs' = sortBy cmp rs
73 as = [ (host, PortNumber $ toEnum port) | (RRSRV _ _ port host) <- rs' ]
74 return (Right as)
6175
6276-- |Get the 'PTR' records assigned to a host address. Note
6377-- that although the API allows for a record to have more
README
(2 / 2)
  
11An asynchronous DNS resolver for Haskell_
22=========================================
33
4:Latest Release: hsdns-1.4.tar.gz_
4:Latest Release: hsdns-1.4.1.tar.gz_
55:Darcs: darcs_ get http://cryp.to/hsdns/
66
77Synopsis
5656
5757.. _Reference Documentation: docs/index.html
5858
59.. _hsdns-1.4.tar.gz: http://cryp.to/hsdns/hsdns-1.4.tar.gz
59.. _hsdns-1.4.1.tar.gz: http://cryp.to/hsdns/hsdns-1.4.1.tar.gz
6060
6161.. _adns-reverse-lookup.hs: example/adns-reverse-lookup.hs
  
1{-
2 Resolve a hostnames' SRV records, then show it
3-}
4
5module Main ( main ) where
6
7import Control.Monad ( when )
8import System.Environment ( getArgs )
9import Network.Socket ( inet_ntoa )
10import Data.List ( elem )
11import ADNS
12
13main :: IO ()
14main = do
15 names <- getArgs
16 when (null names) (putStrLn "Usage: hostname [hostname ...]")
17 initResolver [Debug] $ \resolver -> do
18 a <- querySRV resolver $ head names
19 case a of
20 Just addr -> do
21 putStrLn $ "RESULT:\n" ++ (concat $ map (\b -> (fst b) ++ (show $ snd b) ++ "\n") addr)
22 _ -> putStrLn $ "Error in SRV " ++ (show a)
23
24-- ----- Configure Emacs -----
25--
26-- Local Variables: ***
27-- haskell-program-name: "ghci -ladns" ***
28-- End: ***
  
11Name: hsdns
2Version: 1.4
2Version: 1.4.1
33Author: Peter Simons <simons@cryp.to>,
44 Lutz Donnerhacke <lutz@iks-jena.de>
55Maintainer: Peter Simons <simons@cryp.to>