packages feed

hsdns-1.7: example/adns-test-and-traverse.hs

module Main ( main ) where

import ADNS
import ADNS.Base
import Control.Concurrent.MVar
import System.Environment

main :: IO ()
main = initResolver [NoErrPrint, NoServerWarn] $ \resolver -> do
  args <- getArgs
  case args of
    [name]   -> traverseDNSSEC resolver name
    [t,name] -> work resolver (read t) name
    _ -> putStrLn "Usage: t [typeid] fqdn"

-- | Test function to see the raw results of a given query type
work :: Resolver -> RRType -> String -> IO ()
work resolver t n = do
  putStrLn $ showString "Querying " . shows t $ showString " for " n
  print =<< takeMVar =<< resolver n t [QuoteOk_Query]

-- | Example implementation to traverse a DNSSEC signed zone.
--
-- This implementation is clearly wrong, because any real zone traversal
-- is done using the NSEC records in the authority section of a NXDOMAIN
-- response.
--
-- Unfortunly the adns library does not provide access to other sections
-- than the answer section, so this walk is done by querying NSEC directly.
--
-- If there are signed subzones, the traversal switches to the subzone
-- and stops if this subzone is traversed. You may continue the traversal
-- by providing the next entry after the subzone.
--
-- You may try this mechanism on "dnssec.iks-jena.de"

traverseDNSSEC :: Resolver -> String -> IO ()
traverseDNSSEC resolver x = do
  putStrLn x
  answer <- takeMVar =<< resolver x NSEC [QuoteOk_Query]
  case rrs answer of
     [RRNSEC y] | not (x `endsWith` ('.':y)) -> traverseDNSSEC resolver y
     _  -> return ()

endsWith :: String -> String -> Bool
endsWith x y = startsWith (reverse x) (reverse y)

startsWith :: String -> String -> Bool
startsWith (x:xs) (y:ys) = x == y && startsWith xs ys
startsWith _      ys     = null ys