1 {-# LANGUAGE OverloadedStrings #-}
5 import Control.Applicative
7 import Control.Exception
9 import Data.Either.Utils
10 import Data.List.Split
11 import Data.Aeson (decode)
12 import Network.JsonRpc.Client
15 confFile = "/etc/namecoin.conf"
17 -- Config file handling
19 data Config = Config { rpcuser :: String
20 , rpcpassword :: String
25 readConfig :: String -> IO Config
27 cp <- return . forceEither =<< readfile emptyCP f
28 return (Config { rpcuser = getSetting cp "rpcuser" ""
29 , rpcpassword = getSetting cp "rpcpassword" ""
30 , rpchost = getSetting cp "rpchost" "localhost"
31 , rpcport = getSetting cp "rpcport" "8336"
34 getSetting cp x dfl = case get cp "DEFAULT" x of
39 cfg <- readConfig confFile
40 return $ "http://" ++ rpcuser cfg ++ ":" ++ rpcpassword cfg ++
41 "@" ++ rpchost cfg ++ ":" ++ rpcport cfg ++ "/"
45 queryNmc :: String -> String -> RRType -> String -> IO (Either String NmcDom)
46 queryNmc uri fqdn qtype qid = do
47 case reverse (splitOn "." fqdn) of
49 ans <- detailledRemote Version1 [] uri "name_show" $ "d/" ++ dn
50 let mdom = decode (resValue ans) :: Maybe NmcDom
52 Nothing -> return $ Left ("Unparseable: " ++ (show (resValue ans)))
53 Just dom -> return $ Right dom
55 return $ Left "Only \".bit\" domain is supported"
59 data RRType = RRTypeSRV | RRTypeA | RRTypeAAAA | RRTypeCNAME
60 | RRTypeDNAME | RRTypeSOA | RRTypeRP | RRTypeLOC
62 | RRTypeANY | RRTypeError String
65 data PdnsRequest = PdnsRequestQ
69 , remoteIpAddress :: String
70 , localIpAddress :: Maybe String
71 , ednsSubnetAddress :: Maybe String
73 | PdnsRequestAXFR String
83 "CNAME" -> RRTypeCNAME
84 "DNAME" -> RRTypeDNAME
93 | ver >= 2 = case xs of
98 | ver >= 3 = case xs of
101 | otherwise = Nothing
104 "PING":[] -> Right PdnsRequestPing
105 "AXFR":x:[] -> Right (PdnsRequestAXFR x)
106 "Q":qn:"IN":qt:id:rip:xs -> Right (PdnsRequestQ
110 , remoteIpAddress = rip
111 , localIpAddress = getLIp ver xs
112 , ednsSubnetAddress = getRIp ver xs
116 pdnsOut :: String -> Either String PdnsRequest -> IO ()
117 pdnsOut _ (Left e) = putStrLn ("ERROR\tUnparseable request: " ++ e)
118 pdnsOut uri (Right rq) = case rq of
119 PdnsRequestQ qn qt id lip rip eip -> do
120 dom <- queryNmc uri qn qt id
122 Left e -> putStrLn ("ERROR\tNmc query error: " ++ e)
123 Right result -> print result
124 PdnsRequestAXFR xfrreq ->
125 putStrLn ("ERROR\t No support for AXFR " ++ xfrreq)
126 PdnsRequestPing -> putStrLn "OK"
134 loopErr e = forever $ do
135 putStrLn $ "FAIL\t" ++ e
140 ["HELO", "1"] -> return 1
141 ["HELO", "2"] -> return 2
142 ["HELO", "3"] -> return 3
143 ["HELO", x ] -> loopErr $ "unsupported ABI version " ++ (show x)
144 _ -> loopErr $ "bad HELO " ++ (show s)
146 putStrLn $ "OK\tDnsNmc ready to serve, protocol v." ++ (show ver)
147 forever $ getLine >>= (pdnsOut uri) . (pdnsParse ver)