packages feed

dns 1.3.0 → 1.4.0

raw patch · 6 files changed

+161/−12 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Network.DNS.Resolver: RCHostPort :: HostName -> PortNumber -> FileOrNumericHost
+ Network.DNS.Utils: normalize :: Domain -> Domain
+ Network.DNS.Utils: normalizeCase :: Domain -> Domain
+ Network.DNS.Utils: normalizeRoot :: Domain -> Domain

Files

Network/DNS.hs view
@@ -20,6 +20,10 @@   --   you may need to use the 'lookup', 'lookupAuth', or 'lookupRaw'   --   functions. +  , module Network.DNS.Utils+  -- | The "Network.DNS.Utils" module contains utility functions used+  --   for processing DNS data.+   , module Network.DNS.Types   -- | All of the types that the other modules use. @@ -34,6 +38,7 @@  import Network.DNS.Lookup import Network.DNS.Resolver+import Network.DNS.Utils import Network.DNS.Types import Network.DNS.Decode import Network.DNS.Encode
Network/DNS/Lookup.hs view
@@ -112,11 +112,11 @@ -- --   Examples: -----   >>> let hostname = Data.ByteString.Char8.pack "www.mew.org"+--   >>> let hostname = Data.ByteString.Char8.pack "www.wide.ad.jp" --   >>> --   >>> rs <- makeResolvSeed defaultResolvConf --   >>> withResolver rs $ \resolver -> lookupAAAA resolver hostname---   Right [2001:240:11e:c00:00:00:00:101]+--   Right [2001:200:dff:fff1:216:3eff:fe4b:651c] -- lookupAAAA :: Resolver -> Domain -> IO (Either DNSError [IPv6]) lookupAAAA rlv dom = do@@ -177,12 +177,12 @@ --   Examples: -- --   >>> import Data.List (sort)---   >>> let hostname = Data.ByteString.Char8.pack "iij.ad.jp"+--   >>> let hostname = Data.ByteString.Char8.pack "wide.ad.jp" --   >>> --   >>> rs <- makeResolvSeed defaultResolvConf --   >>> ips <- withResolver rs $ \resolver -> lookupAviaMX resolver hostname --   >>> fmap sort ips---   Right [202.232.30.70,202.232.30.144]+--   Right [133.138.10.34,203.178.136.49] -- --   Since there is more than one result, it is necessary to sort the --   list in order to check for equality.
Network/DNS/Resolver.hs view
@@ -28,7 +28,7 @@ import Network.DNS.Encode import Network.DNS.Internal import Network.Socket (HostName, Socket, SocketType(Datagram), sClose, socket, connect)-import Network.Socket (AddrInfoFlag(..), AddrInfo(..), defaultHints, getAddrInfo)+import Network.Socket (AddrInfoFlag(..), AddrInfo(..), SockAddr(..), PortNumber(..), defaultHints, getAddrInfo) import Prelude hiding (lookup) import System.Random (getStdRandom, randomR) import System.Timeout (timeout)@@ -55,6 +55,7 @@ -- data FileOrNumericHost = RCFilePath FilePath -- ^ A path for \"resolv.conf\"                        | RCHostName HostName -- ^ A numeric IP address+                       | RCHostPort HostName PortNumber -- ^ A numeric IP address and port number  -- | Type for resolver configuration. The easiest way to construct a --   @ResolvConf@ object is to modify the 'defaultResolvConf'.@@ -129,14 +130,15 @@                                  <*> pure (resolvBufsize conf)   where     addr = case resolvInfo conf of-        RCHostName numhost -> makeAddrInfo numhost-        RCFilePath file -> toAddr <$> readFile file >>= makeAddrInfo+        RCHostName numhost -> makeAddrInfo numhost Nothing+        RCHostPort numhost mport -> makeAddrInfo numhost $ Just mport+        RCFilePath file -> toAddr <$> readFile file >>= \i -> makeAddrInfo i Nothing     toAddr cs = let l:_ = filter ("nameserver" `isPrefixOf`) $ lines cs                 in extract l     extract = reverse . dropWhile isSpace . reverse . dropWhile isSpace . drop 11 -makeAddrInfo :: HostName -> IO AddrInfo-makeAddrInfo addr = do+makeAddrInfo :: HostName -> Maybe PortNumber -> IO AddrInfo+makeAddrInfo addr mport = do     proto <- getProtocolNumber "udp"     let hints = defaultHints {             addrFlags = [AI_ADDRCONFIG, AI_NUMERICHOST, AI_PASSIVE]@@ -144,7 +146,11 @@           , addrProtocol = proto           }     a:_ <- getAddrInfo (Just hints) (Just addr) (Just "domain")-    return a+    let connectPort = case addrAddress a of+                        SockAddrInet pn ha -> SockAddrInet (maybe pn id mport) ha+                        SockAddrInet6 pn fi ha sid -> SockAddrInet6 (maybe pn id mport) fi ha sid+                        unix -> unix +    return $ a { addrAddress = connectPort }  ---------------------------------------------------------------- 
Network/DNS/StateBinary.hs view
@@ -7,7 +7,7 @@ import Control.Monad.State (State, StateT) import qualified Control.Monad.State as ST import Control.Monad.Trans.Resource (ResourceT)-import qualified Data.Attoparsec as A+import qualified Data.Attoparsec.ByteString as A import qualified Data.Attoparsec.ByteString.Lazy as AL import qualified Data.Attoparsec.Types as T import Data.ByteString (ByteString)
+ Network/DNS/Utils.hs view
@@ -0,0 +1,137 @@+-- | Miscellaneous utility functions for processing DNS data.+--+module Network.DNS.Utils (+    normalize+  , normalizeCase+  , normalizeRoot+  ) where++import qualified Data.ByteString.Char8 as BS (+    append+  , last+  , map+  , null+  , pack )+import Data.Char ( toLower )++import Network.DNS.Types ( Domain )+++-- | Perform both 'normalizeCase' and 'normalizeRoot' on the given+--   'Domain'. When comparing DNS names taken from user input, this is+--   often necessary to avoid unexpected results.+--+--   /Examples/:+--+--   >>> let domain1 = BS.pack "ExAmPlE.COM"+--   >>> let domain2 = BS.pack "example.com."+--   >>> domain1 == domain2+--   False+--   >>> normalize domain1 == normalize domain2+--   True+--+--   The 'normalize' function should be idempotent:+--+--   >>> normalize (normalize domain1) == normalize domain1+--   True+--+--   Ensure that we don't crash on the empty 'Domain':+--+--   >>> import qualified Data.ByteString.Char8 as BS ( empty )+--   >>> normalize BS.empty+--   "."+--+normalize :: Domain -> Domain+normalize = normalizeCase . normalizeRoot+++-- | Normalize the case of the given DNS name for comparisons.+--+--   According to RFC #1035, \"For all parts of the DNS that are part+--   of the official protocol, all comparisons between character+--   strings (e.g., labels, domain names, etc.) are done in a+--   case-insensitive manner.\" This function chooses to lowercase+--   its argument, but that should be treated as an implementation+--   detail if at all possible.+--+--   /Examples/:+--+--   >>> let domain1 = BS.pack "ExAmPlE.COM"+--   >>> let domain2 = BS.pack "exAMPle.com"+--   >>> domain1 == domain2+--   False+--   >>> normalizeCase domain1 == normalizeCase domain2+--   True+--+--   The 'normalizeCase' function should be idempotent:+--+--   >>> normalizeCase (normalizeCase domain2) == normalizeCase domain2+--   True+--+--   Ensure that we don't crash on the empty 'Domain':+--+--   >>> import qualified Data.ByteString.Char8 as BS ( empty )+--   >>> normalizeCase BS.empty+--   ""+--+normalizeCase :: Domain -> Domain+normalizeCase = BS.map toLower+++-- | Normalize the given name by appending a trailing dot (the DNS+--   root) if one does not already exist.+--+--   Warning: this does not produce an equivalent DNS name! However,+--   users are often unaware of the effect that the absence of the+--   root will have. In user interface design, it may therefore be+--   wise to act as if the user supplied the trailing dot during+--   comparisons.+--+--   Per RFC #1034,+--+--   \"Since a complete domain name ends with the root label, this leads+--   to a printed form which ends in a dot. We use this property to+--   distinguish between:+--+--   * a character string which represents a complete domain name+--     (often called \'absolute\'). For example, \'poneria.ISI.EDU.\'+--+--   * a character string that represents the starting labels of a+--     domain name which is incomplete, and should be completed by+--     local software using knowledge of the local domain (often+--     called \'relative\'). For example, \'poneria\' used in the+--     ISI.EDU domain.+--+--   Relative names are either taken relative to a well known origin,+--   or to a list of domains used as a search list. Relative names+--   appear mostly at the user interface, where their interpretation+--   varies from implementation to implementation, and in master+--   files, where they are relative to a single origin domain name.\"+--+--   /Examples/:+--+--   >>> let domain1 = BS.pack "example.com"+--   >>> let domain2 = BS.pack "example.com."+--   >>> domain1 == domain2+--   False+--   >>> normalizeRoot domain1 == normalizeRoot domain2+--   True+--+--   The 'normalizeRoot' function should be idempotent:+--+--   >>> normalizeRoot (normalizeRoot domain1) == normalizeRoot domain1+--   True+--+--   Ensure that we don't crash on the empty 'Domain':+--+--   >>> import qualified Data.ByteString.Char8 as BS ( empty )+--   >>> normalizeRoot BS.empty+--   "."+--+normalizeRoot :: Domain -> Domain+normalizeRoot d+  | BS.null d = trailing_dot+  | BS.last d == '.' = d+  | otherwise = d `BS.append` trailing_dot+    where+      trailing_dot = BS.pack "."
dns.cabal view
@@ -1,5 +1,5 @@ Name:                   dns-Version:                1.3.0+Version:                1.4.0 Author:                 Kazu Yamamoto <kazu@iij.ad.jp> Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp> License:                BSD3@@ -18,6 +18,7 @@   Exposed-Modules:      Network.DNS                         Network.DNS.Lookup                         Network.DNS.Resolver+                        Network.DNS.Utils                         Network.DNS.Types                         Network.DNS.Encode                         Network.DNS.Decode