implement working AXFR
authorEugene Crosser <crosser@average.org>
Sat, 19 Apr 2014 13:24:59 +0000 (17:24 +0400)
committerEugene Crosser <crosser@average.org>
Sat, 19 Apr 2014 13:25:17 +0000 (17:25 +0400)
PowerDns.hs
pdns-pipe-nmc.hs

index 81e0ac9efac8c88f3a9746fc8821981af58f69fa..ac92109269a5df7f33d1e1a772f50eda7ddc615b 100644 (file)
@@ -3,11 +3,12 @@ module PowerDns ( RRType(..)
                 , PdnsRequest(..)
                 , pdnsParse
                 , pdnsReport
-                , pdnsOut
+                , pdnsOutQ
                 , pdnsOutXfr
                 ) where
 
 import Data.Text.Lazy (splitOn, pack)
+import Data.Map.Lazy (foldrWithKey)
 
 import NmcDom
 
@@ -64,7 +65,7 @@ pdnsParse ver s =
   let
     getInt s = case reads s :: [(Int, String)] of
       [(x, _)] -> x
-      _        -> -1
+      _        -> (-1)
     getLIp ver xs
       | ver >= 2  = case xs of
                       x:_       -> Just x
@@ -98,26 +99,44 @@ pdnsReport :: String -> String
 pdnsReport err = "LOG\tError: " ++ err ++ "\nFAIL\n"
 
 -- | Produce answer to the Q request
-pdnsOut :: Int -> Int -> String -> RRType -> Either String NmcDom -> String
-pdnsOut ver id name rrtype edom =
+pdnsOutQ :: Int -> Int -> String -> RRType -> Either String NmcDom -> String
+pdnsOutQ ver id name rrt edom =
   let
-    rrl = case rrtype of
-      RRTypeANY -> [RRTypeSRV, RRTypeA, RRTypeAAAA, RRTypeCNAME
+    rrl = case rrt of
+      RRTypeANY -> [ RRTypeSRV, RRTypeA, RRTypeAAAA, RRTypeCNAME
                    , RRTypeDNAME, RRTypeRP, RRTypeLOC, RRTypeNS
-                   , RRTypeDS, RRTypeMX]
-      rrt       -> [rrt]
+                   , RRTypeDS, RRTypeMX -- SOA not included
+                   ]
+      x         -> [x]
   in
-    (formatDom ver id name rrl edom) ++ "END\n"
+    case edom of
+      Left  err ->
+        pdnsReport $ err ++ " in the " ++ (show rrt) ++ " query for " ++ name
+      Right dom ->
+        formatDom ver id rrl name dom "END\n"
 
 -- | Produce answer to the AXFR request
 pdnsOutXfr :: Int -> Int -> String -> Either String NmcDom -> String
-pdnsOutXfr ver id name edom = "" -- FIXME
-
-formatDom ver id name rrl edom = case edom of
-  Left  err ->
-    pdnsReport $ err ++ " in the " ++ (show rrl) ++ " query for " ++ name
-  Right dom ->
-    foldr (\x a -> (formatRR ver id name dom x) ++ a) "" rrl
+pdnsOutXfr ver id name edom =
+  let
+    allrrs = [ RRTypeSRV, RRTypeA, RRTypeAAAA, RRTypeCNAME
+             , RRTypeDNAME, RRTypeRP, RRTypeLOC, RRTypeNS
+             , RRTypeDS, RRTypeMX, RRTypeSOA
+             ]
+    walkDom f acc name dom =
+      f name dom $ case domMap dom of
+        Nothing -> acc
+        Just dm ->
+          foldrWithKey (\n d a -> walkDom f a (n ++ "." ++ name) d) acc dm
+  in
+    case edom of
+      Left  err ->
+        pdnsReport $ err ++ " in the AXFR request for " ++ name
+      Right dom ->
+        walkDom (formatDom ver id allrrs) "END\n" name dom
+
+formatDom ver id rrl name dom acc =
+  foldr (\x a -> (formatRR ver id name dom x) ++ a) acc rrl
 
 formatRR ver id name dom rrtype =
   foldr (\x a -> "DATA\t" ++ v3ext ++ name ++ "\tIN\t" ++ (show rrtype)
index 459253099479e52e77ca3a4ec1d384a0f739e068..ab3e410de5951ed572dd20fdda70a0956a0b9f0e 100644 (file)
@@ -54,8 +54,8 @@ qRsp rsp =
     case parseJsonRpc (responseBody rsp) :: Either JsonRpcError NmcRes of
       Left  jerr -> 
         case (jrpcErrCode jerr) of
-          -4 -> Right "{}"      -- this is how non-existent entry is returned
-          _  -> Left $ "JsonRpc error response: " ++ (show jerr)
+          (-4) -> Right "{}"    -- this is how non-existent entry is returned
+          _    -> Left $ "JsonRpc error response: " ++ (show jerr)
       Right jrsp -> Right $ resValue jrsp
 
 -- NMC interface
@@ -118,7 +118,7 @@ mainPdnsNmc = do
           case preq of
             PdnsRequestQ qname qtype id _ _ _ -> do
               io $ queryDom (queryOpNmc cfg mgr id) qname
-                     >>= putStr . (pdnsOut ver count qname qtype)
+                     >>= putStr . (pdnsOutQ ver count qname qtype)
   -- debug
               io $ putStrLn $ "LOG\tRequest number " ++ (show count)
                            ++ " id: " ++ (show id)
@@ -139,6 +139,13 @@ mainPdnsNmc = do
 
   runStateT mainloop (0, empty) >> return ()
 
+-- helper for command-line tools
+
+pdnsOut key qt dom =
+  case qt of
+    "AXFR" -> pdnsOutXfr 1 (-1) key dom
+    _      -> pdnsOutQ 1 (-1) key (rrType qt) dom
+
 -- query by key from Namecoin
 
 mainOne key qt = do
@@ -146,14 +153,14 @@ mainOne key qt = do
   mgr <- newManager def
   dom <- queryDom (queryOpNmc cfg mgr (-1)) key
   putStrLn $ ppShow dom
-  putStr $ pdnsOut 1 (-1) key qt dom
+  putStr $ pdnsOut key qt dom
 
 -- using file backend for testing json domain data
 
 mainFile key qt = do
   dom <- queryDom queryOpFile key
   putStrLn $ ppShow dom
-  putStr $ pdnsOut 1 (-1) key qt dom
+  putStr $ pdnsOut key qt dom
 
 -- Entry point
 
@@ -161,6 +168,6 @@ main = do
   args <- getArgs
   case args of
     []                 -> mainPdnsNmc
-    [key, qtype]       -> mainOne key (rrType qtype)
-    ["-f" ,key, qtype] -> mainFile key (rrType qtype)
-    _ -> error $ "usage: empty args, or \"[-f] <fqdn> <QTYPE>\" (type in caps)"
+    [key, qtype]       -> mainOne key qtype
+    ["-f" ,key, qtype] -> mainFile key qtype
+    _ -> error $ "usage: empty args, or \"[-f] <fqdn> {<TYPE>|ANY|AXFR}\" (type in caps)"