From 349c5a80e0b729b0e030a1ff3e47667d8afa0d36 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 11 Jul 2015 02:34:50 -0400 Subject: [PATCH] Add the Reversible class. Make the Host reversing oh so much more complicated (and fun) with Reversible. Add a Network.DNS.RBL.Tests module that only exports tests. Get the test suite working again. --- .ghci | 2 + harbl.cabal | 18 ++--- harbl/src/Network/DNS/RBL.hs | 20 +++++- harbl/src/Network/DNS/RBL/Domain.hs | 87 ++++++++++++++++++++++++- harbl/src/Network/DNS/RBL/Host.hs | 86 +++++++++--------------- harbl/src/Network/DNS/RBL/Reversible.hs | 11 ++++ harbl/src/Network/DNS/RBL/Tests.hs | 12 ++++ test/TestSuite.hs | 3 +- 8 files changed, 169 insertions(+), 70 deletions(-) create mode 100644 harbl/src/Network/DNS/RBL/Reversible.hs create mode 100644 harbl/src/Network/DNS/RBL/Tests.hs diff --git a/.ghci b/.ghci index dae4f7c..6632251 100644 --- a/.ghci +++ b/.ghci @@ -8,6 +8,7 @@ src/Network/DNS/RBL/Host.hs src/Network/DNS/RBL/IPv4Pattern.hs src/Network/DNS/RBL/Pretty.hs + src/Network/DNS/RBL/Reversible.hs src/Network/DNS/RBL/Site.hs :} @@ -16,6 +17,7 @@ import Network.DNS.RBL.Domain import Network.DNS.RBL.Host import Network.DNS.RBL.IPv4Pattern import Network.DNS.RBL.Pretty +import Network.DNS.RBL.Reversible import Network.DNS.RBL.Site -- And import the stuff from Parsec we need for debugging. diff --git a/harbl.cabal b/harbl.cabal index 8f4401f..8a5191b 100644 --- a/harbl.cabal +++ b/harbl.cabal @@ -25,16 +25,17 @@ library exposed-modules: Network.DNS.RBL + Network.DNS.RBL.Tests other-modules: Network.DNS.RBL.Domain Network.DNS.RBL.Host Network.DNS.RBL.IPv4Pattern Network.DNS.RBL.Pretty + Network.DNS.RBL.Reversible Network.DNS.RBL.Site - hs-source-dirs: - harbl/src/ + hs-source-dirs: harbl/src ghc-options: -Wall @@ -65,11 +66,9 @@ executable harbl harbl, parsec >= 3 - main-is: - Main.hs + main-is: Main.hs - hs-source-dirs: - harbl-cli/src/ + hs-source-dirs: harbl-cli/src ghc-options: -Wall @@ -92,14 +91,11 @@ executable harbl test-suite testsuite type: exitcode-stdio-1.0 - hs-source-dirs: src test + hs-source-dirs: test main-is: TestSuite.hs build-depends: base >= 4.6 && < 5, - bytestring >= 0.9, - dns >= 2, - iproute >= 1.4, - parsec >= 3, + harbl, tasty >= 0.8, tasty-hunit >= 0.8 diff --git a/harbl/src/Network/DNS/RBL.hs b/harbl/src/Network/DNS/RBL.hs index c3268fd..c166901 100644 --- a/harbl/src/Network/DNS/RBL.hs +++ b/harbl/src/Network/DNS/RBL.hs @@ -14,6 +14,7 @@ import Data.IP ( IPv4 ) import Data.List ( intercalate ) import Data.Maybe ( catMaybes ) import Network.DNS ( + Domain, DNSError, Resolver, defaultResolvConf, @@ -21,9 +22,10 @@ import Network.DNS ( makeResolvSeed, withResolver ) -import Network.DNS.RBL.Host ( Host, host, reverse_labels ) +import Network.DNS.RBL.Host ( Host(..), host ) import Network.DNS.RBL.IPv4Pattern ( addresses ) import Network.DNS.RBL.Pretty ( Pretty(..) ) +import Network.DNS.RBL.Reversible ( Reversible(..) ) import Network.DNS.RBL.Site ( Site(..), sites ) @@ -49,6 +51,20 @@ listing_message (ListingDetails h (Site d _ w) codes) = return_codes = intercalate "," (map show codes) +-- | Make the given 'Host' relative (if it was absolute), and reverse +-- its labels. This is done in order to look it up in the DNS in +-- standard reverse lookup form. For example, if we wanted to look +-- up @192.168.0.1@ on @rbl.example.com@, we would want to look up +-- the name @1.0.168.192.rbl.example.com@. +-- +reverse_host :: Host -> Domain +reverse_host h = + pack $ case (backwards h) of + (HostRelative _) -> pretty_show h + (HostAbsolute d) -> pretty_show d + + + -- | This code is stolen from 'Network.DNS.lookupRDNS', which I'm -- pretty sure I wrote anyway. -- @@ -56,7 +72,7 @@ dnslookup :: Resolver -> Host -> Host -> IO (Either DNSError [IPv4]) dnslookup rlv rbl h = lookupA rlv dom where suffix = pack $ "." ++ (pretty_show rbl) - dom = (reverse_labels h) `append` suffix + dom = (reverse_host h) `append` suffix -- | See 'lookup_single'. The \"prime\" version here takes an diff --git a/harbl/src/Network/DNS/RBL/Domain.hs b/harbl/src/Network/DNS/RBL/Domain.hs index 75170a7..4dd5d1d 100644 --- a/harbl/src/Network/DNS/RBL/Domain.hs +++ b/harbl/src/Network/DNS/RBL/Domain.hs @@ -15,7 +15,7 @@ -- (octets). -- module Network.DNS.RBL.Domain ( - Domain, + Domain(..), domain ) where @@ -30,6 +30,7 @@ import qualified Text.Parsec as Parsec ( digit, letter) import Text.Parsec.String ( Parser ) import Network.DNS.RBL.Pretty ( Pretty(..) ) +import Network.DNS.RBL.Reversible ( Reversible(..) ) -- * Digits @@ -496,6 +497,68 @@ instance Pretty Subdomain where pretty_show (SubdomainMultipleLabel l s) = (pretty_show l) ++ "." ++ (pretty_show s) + +instance Reversible Subdomain where + -- | Reverse the labels of the given subdomain. + -- + -- ==== _Examples_ + -- + -- >>> import Text.Parsec ( parse ) + -- + -- Standard usage: + -- + -- >>> let (Right r) = parse subdomain "" "com" + -- >>> pretty_print $ backwards r + -- com + -- + -- >>> let (Right r) = parse subdomain "" "example.com" + -- >>> pretty_print $ backwards r + -- com.example + -- + -- >>> let (Right r) = parse subdomain "" "www.example.com" + -- >>> pretty_print $ backwards r + -- com.example.www + -- + -- >>> let (Right r) = parse subdomain "" "new.www.example.com" + -- >>> pretty_print $ backwards r + -- com.example.www.new + -- + + -- It's easy to reverse a single label... + backwards s@(SubdomainSingleLabel _) = s + + -- For multiple labels we have two cases. The first is where we have + -- exactly two labels, and we just need to swap them. + backwards (SubdomainMultipleLabel l (SubdomainSingleLabel m)) = + SubdomainMultipleLabel m (SubdomainSingleLabel l) + + -- And now the hard case. If we reversed @s@, then the "head" of + -- the result (@last_s@) should be the last label in the entire + -- subdomain. Stick @last_s@ on the front of the result. That makes + -- enough sense. + -- + -- But what to do about the rest? We need to get \"init s\" + -- somehow. Well, we have the reverse of it... why not waste a bunch + -- of time and reverse that, too? With @init s@ in hand, we can + -- prepend @l@ to that, and THEN reverse the entire thing. What we'll + -- wind up with looks like @[last_s, init_s_rev, l]@ which you can + -- pretend you recognize as the subdomain in reverse. + -- + backwards (SubdomainMultipleLabel l s) = + case (backwards s) of + SubdomainMultipleLabel last_s init_s_rev -> + let init_s = backwards init_s_rev + in + SubdomainMultipleLabel + last_s + (backwards (SubdomainMultipleLabel l init_s)) + + -- Reversing a multiple label thing gives you back a multiple + -- label thing but there's no way to promise that. + impossible -> impossible + + + -- | Parse an RFC1035 \"subdomain\". The given grammar is, -- -- ::=