packages feed

dns 2.0.8 → 2.0.9

raw patch · 7 files changed

+99/−21 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Network.DNS.Decode: receiveVC :: Socket -> IO DNSMessage
+ Network.DNS.Encode: encodeVC :: ByteString -> ByteString

Files

Changelog view
@@ -1,3 +1,5 @@+2.0.9+	- Implemented TCP fallback after a truncated UDP response. [#46](https://github.com/kazu-yamamoto/dns/pull/46) 2.0.8 	- Better handling of encoding and decoding the "root" domain ".". [#45](https://github.com/kazu-yamamoto/dns/pull/45) 2.0.7
Network/DNS/Decode.hs view
@@ -4,6 +4,7 @@     decode   , decodeMany   , receive+  , receiveVC   ) where  import Control.Applicative (many)@@ -15,8 +16,9 @@ import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy as BL-import Data.Conduit (($$), Source)+import Data.Conduit (($$), ($$+), ($$+-), (=$), Source) import Data.Conduit.Network (sourceSocket)+import qualified Data.Conduit.Binary as CB import Data.IP (IP(..), toIPv4, toIPv6b) import Data.Typeable (Typeable) import Data.Word (Word16)@@ -42,6 +44,19 @@  receive :: Socket -> IO DNSMessage receive = receiveDNSFormat . sourceSocket++-- | Receive and parse a single virtual-circuit (TCP) response.  It+--   is up to the caller to implement any desired timeout.  This+--   (and the other response decoding functions) may throw ParseError+--   when the server response is incomplete or malformed.++receiveVC :: Socket -> IO DNSMessage+receiveVC sock = runResourceT $ do+    (src, lenbytes) <- sourceSocket sock $$+ CB.take 2+    let len = case (map fromIntegral $ BL.unpack lenbytes) of+                hi:lo:[] -> 256 * hi + lo+                _        -> 0+    src $$+- CB.isolate len =$ sinkSGet decodeResponse >>= return . fst  ---------------------------------------------------------------- 
Network/DNS/Encode.hs view
@@ -2,6 +2,7 @@  module Network.DNS.Encode (     encode+  , encodeVC   , composeQuery   , composeQueryAD   ) where@@ -60,6 +61,11 @@  encode :: DNSMessage -> ByteString encode msg = runSPut (encodeDNSMessage msg)++encodeVC :: ByteString -> ByteString+encodeVC query =+    let len = BB.toLazyByteString $ BB.int16BE $ fromIntegral $ BL.length query+    in len <> query  ---------------------------------------------------------------- 
Network/DNS/Internal.hs view
@@ -115,9 +115,8 @@     -- | The name server was unable to process this query due to a     --   problem with the name server.   | ServerFailure-    -- | Meaningful only for responses from an authoritative name-    -- server, this code signifies that the-    -- domain name referenced in the query does not exist.+    -- | This code signifies that the domain name referenced in the+    --   query does not exist.   | NameError     -- | The name server does not support the requested kind of query.   | NotImplemented
Network/DNS/Lookup.hs view
@@ -373,8 +373,9 @@  ---------------------------------------------------------------- --- | Look up all \'SRV\' records for the given hostname. A SRV record---   comprises four fields,+-- | Look up all \'SRV\' records for the given hostname. SRV records+--   consist (see <https://tools.ietf.org/html/rfc2782>) of the+--   following four fields: -- --     * Priority (lower is more-preferred) --@@ -391,12 +392,18 @@ -- --   Examples: -----   >>> let hostname = Data.ByteString.Char8.pack "_sip._tcp.cisco.com"+--   >>> let q = Data.ByteString.Char8.pack "_xmpp-server._tcp.jabber.ietf.org" --   >>> --   >>> rs <- makeResolvSeed defaultResolvConf---   >>> withResolver rs $ \resolver -> lookupSRV resolver hostname---   Right [(1,0,5060,"vcsgw.cisco.com.")]---+--   >>> withResolver rs $ \resolver -> lookupSRV resolver q+--   Right [(5,0,5269,"jabber.ietf.org.")]++-- Though the "jabber.ietf.orgs" SRV record may prove reasonably stable, as+-- with anything else published in DNS it is subject to change.  Also, this+-- example only works when connected to the Internet.  Perhaps the above+-- example should be displayed in a format that is not recognized as a test+-- by "doctest".+ lookupSRV :: Resolver -> Domain -> IO (Either DNSError [(Int,Int,Int,Domain)]) lookupSRV rlv dom = do   erds <- DNS.lookup rlv dom SRV
Network/DNS/Resolver.hs view
@@ -28,8 +28,11 @@ import Network.DNS.Encode import Network.DNS.Internal import qualified Data.ByteString.Char8 as BS-import Network.Socket (HostName, Socket, SocketType(Datagram), close, socket, connect)-import Network.Socket (AddrInfoFlag(..), AddrInfo(..), SockAddr(..), PortNumber(..), defaultHints, getAddrInfo)+import Network.Socket (HostName, Socket, SocketType(Stream, Datagram))+import Network.Socket (AddrInfoFlag(..), AddrInfo(..), SockAddr(..))+import Network.Socket (Family(AF_INET, AF_INET6), PortNumber(..))+import Network.Socket (close, socket, connect, getPeerName, getAddrInfo)+import Network.Socket (defaultHints, defaultProtocol) import Prelude hiding (lookup) import System.Random (getStdRandom, randomR) import System.Timeout (timeout)@@ -267,10 +270,14 @@ lookupAuth = lookupSection authority  --- | Look up a name and return the entire DNS Response. Sample output---   is included below, however it is /not/ tested -- the sequence---   number is unpredictable (it has to be!).+-- | Look up a name and return the entire DNS Response.  If the+--   initial UDP query elicits a truncated answer, the query is+--   retried over TCP.  The TCP retry may extend the total time+--   taken by one more timeout beyond timeout * tries. --+--   Sample output is included below, however it is /not/ tested+--   the sequence number is unpredictable (it has to be!).+-- --   The example code: -- --   @@@ -310,10 +317,30 @@ lookupRaw :: Resolver -> Domain -> TYPE -> IO (Either DNSError DNSMessage) lookupRaw = lookupRawInternal receive False +-- | Same as lookupRaw, but the query sets the AD bit, which solicits the+--   the authentication status in the server reply.  In most applications+--   (other than diagnostic tools) that want authenticated data It is+--   unwise to trust the AD bit in the responses of non-local servers, this+--   interface should in most cases only be used with a loopback resolver.+-- lookupRawAD :: Resolver -> Domain -> TYPE -> IO (Either DNSError DNSMessage) lookupRawAD = lookupRawInternal receive True -+-- Lookup loop, we try UDP until we get a response.  If the response+-- is truncated, we try TCP once, with no further UDP retries.+-- EDNS0 support would significantly reduce the need for TCP retries.+--+-- For now, we optimize for low latency high-availability caches+-- (e.g.  running on a loopback interface), where TCP is cheap+-- enough.  We could attempt to complete the TCP lookup within the+-- original time budget of the truncated UDP query, by wrapping both+-- within a a single 'timeout' thereby staying within the original+-- time budget, but it seems saner to give TCP a full opportunity to+-- return results.  TCP latency after a truncated UDP reply will be+-- atypical.+--+-- Future improvements might also include support for TCP on the+-- initial query, and of course support for multiple nameservers.  lookupRawInternal ::     (Socket -> IO DNSMessage)@@ -342,15 +369,37 @@               Nothing  -> loop query checkSeqno (cnt + 1) False               Just res -> do                   let valid = checkSeqno res-                  if valid then-                      return $ Right res-                    else-                      loop query checkSeqno (cnt + 1) False+                  case valid of+                      False  -> loop query checkSeqno (cnt + 1) False+                      True | False <- trunCation $ flags $ header res+                             -> return $ Right res+                      _      -> tcpRetry query     sock = dnsSock rlv     tm = dnsTimeout rlv     retry = dnsRetry rlv     q = makeQuestion dom typ     check seqno res = identifier (header res) == seqno+    tcpRetry query = do+        peer <- getPeerName sock+        bracket (tcpOpen peer)+                (maybe (return ()) close)+                (tcpLookup query peer)+    tcpOpen peer = do+        case (peer) of+            SockAddrInet _ _ ->+                socket AF_INET Stream defaultProtocol >>= return . Just+            SockAddrInet6 _ _ _ _ ->+                socket AF_INET6 Stream defaultProtocol >>= return . Just+            _ -> return Nothing -- Only IPv4 and IPv6 are possible+    tcpLookup _ _ Nothing = return $ Left ServerFailure -- can't happen+    tcpLookup query peer (Just vc) = do+        response <- timeout tm $ do+            connect vc $ peer+            sendAll vc $ encodeVC query+            receiveVC vc+        case response of+            Nothing  -> return $ Left TimeoutExpired+            Just res -> return $ Right res  #if mingw32_HOST_OS == 1     -- Windows does not support sendAll in Network.ByteString.Lazy.
dns.cabal view
@@ -1,5 +1,5 @@ Name:                   dns-Version:                2.0.8+Version:                2.0.9 Author:                 Kazu Yamamoto <kazu@iij.ad.jp> Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp> License:                BSD3