+type LookupResult = (Domain, Maybe [Domain])
+
+-- | Perform a query, but take the result from the authority section
+-- of the response rather than the answer section. Code shamelessly
+-- stolen from Network.DNS.lookup.
+lookup_authority :: Resolver -> Domain -> TYPE -> IO (Maybe [RDATA])
+lookup_authority rlv dom typ = (>>= toRDATA) <$> lookupRaw rlv dom typ
+ where
+ correct r = rrtype r == typ
+ listToMaybe [] = Nothing
+ listToMaybe xs = Just xs
+ toRDATA = listToMaybe . map rdata . filter correct . authority
+
+-- | Like lookupNS, except we take the result from the authority
+-- section of the response (as opposed to the answer section).
+lookupNS_authority :: Resolver -> Domain -> IO (Maybe [Domain])
+lookupNS_authority rlv dom = toNS <$> DNS.lookup_authority rlv dom NS
+ where
+ toNS = fmap (map unTag)
+ unTag (RD_NS dm) = dm
+ unTag _ = error "lookupNS_authority"
+
+
+-- | Takes a String representing either a hostname or an IP
+-- address. If a hostname was supplied, it is resolved to either an
+-- IPv4 or Nothing. If an IP address is supplied, it is returned as an
+-- IPv4.
+--
+-- Examples:
+--
+-- >>> resolve_address "example.com"
+-- Just 93.184.216.119
+-- >>> resolve_address "93.184.216.119"
+-- Just 93.184.216.119
+--
+resolve_address :: String -> IO (Maybe IPv4)
+resolve_address s =
+ case read_result of
+ Just _ -> return read_result
+ Nothing -> do
+ default_rs <- makeResolvSeed defaultResolvConf
+ withResolver default_rs $ \resolver -> do
+ result <- lookupA resolver (BS.pack s)
+ return $ case result of
+ Just (x:_) -> Just x
+ _ -> Nothing
+ where
+ read_result :: Maybe IPv4
+ read_result = readMaybe s
+
+
+-- | This calls lookupMX, and returns the result as the second
+-- component of a tuple whose first component is the domain name
+-- itself.
+--
+-- Examples:
+--
+-- The example domain, example.com, has no MX record.
+--
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> let domain = BS.pack "example.com."
+-- >>> withResolver rs $ \resolver -> lookupMX' resolver domain
+-- ("example.com.",Nothing)
+--
+lookupMX' :: Resolver -> Domain -> IO LookupResult
+lookupMX' resolver domain =
+ liftM (pair_em . drop_priority) $ lookupMX resolver domain
+ where
+ drop_priority :: Maybe [(Domain, Int)] -> Maybe [Domain]
+ drop_priority = fmap (map fst)
+
+ pair_em :: a -> (Domain, a)
+ pair_em = (,) domain
+
+
+-- | This calls lookupNS, and returns the result as the second
+-- component of a tuple whose first component is the domain name
+-- itself.
+--
+-- Examples:
+--
+-- The example domain, example.com, does have NS records, but the
+-- order in which they are returned is variable, so we have to sort
+-- them to get a reliable result.
+--
+-- >>> import Data.List (sort)
+-- >>> let sort_snd (x,y) = (x, sort <$> y)
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> let domain = BS.pack "example.com."
+-- >>> withResolver rs $ \resolver -> sort_snd <$> lookupNS' resolver domain
+-- ("example.com.",Just ["a.iana-servers.net.","b.iana-servers.net."])
+--
+lookupNS' :: Resolver -> Domain -> IO LookupResult
+lookupNS' resolver domain = do
+ answer_result <- lookupNS resolver domain
+ auth_result <- lookupNS_authority resolver domain
+ liftM pair_em $ return $ combine answer_result auth_result
+ where
+ pair_em :: a -> (Domain, a)
+ pair_em = (,) domain
+
+ combine :: (Maybe [Domain]) -> (Maybe [Domain]) -> (Maybe [Domain])
+ combine Nothing Nothing = Nothing
+ combine m1 Nothing = m1
+ combine Nothing m2 = m2
+ combine (Just ds1) (Just ds2) = Just (ds1 ++ ds2)
+
+-- | Perform both normalize_case and normalize_root.