From 6c076a2622dd9a6bfc96ed05f8478b5150db176a Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 2 May 2010 14:39:08 -0400 Subject: [PATCH] Update Main and Cidr to use the new modules instead of converting to/from bit strings. --- src/Cidr.hs | 180 ++++----------------------------------------- src/IPv4Address.hs | 13 +--- src/Main.hs | 37 ++++------ src/Octet.hs | 16 ++++ 4 files changed, 49 insertions(+), 197 deletions(-) diff --git a/src/Cidr.hs b/src/Cidr.hs index 553bd15..efd3ae0 100644 --- a/src/Cidr.hs +++ b/src/Cidr.hs @@ -1,76 +1,25 @@ module Cidr -( Cidr, - from_string, - is_valid_cidr, - min_first_octet, - max_first_octet, - min_second_octet, - max_second_octet, - min_third_octet, - max_third_octet, - min_fourth_octet, - max_fourth_octet +( Cidr(..), + cidr_from_string, + is_valid_cidr ) where -import Data.Char (digitToInt, intToDigit) -import Numeric (readInt, showIntAtBase) import Text.Regex.Posix +import IPv4Address import ListUtils +import Octet -type Maskbits = Int -type Octet = Int -type OctetList = (Octet, Octet, Octet, Octet) -type BaseTwoOctetList = (String, String, String, String) -data Cidr = Cidr { octet1 :: Octet, - octet2 :: Octet, - octet3 :: Octet, - octet4 :: Octet, +data Cidr = Cidr { ipv4address :: IPv4Address, maskbits :: Maskbits } - deriving (Show) + deriving (Eq, Show) -- Will return True if the passed String is in CIDR notation, False -- otherwise. is_valid_cidr :: String -> Bool is_valid_cidr cidr = cidr =~ "([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}" -first :: (a,b,c,d) -> a -first (w,_,_,_) = w - -second :: (a,b,c,d) -> b -second (_,x,_,_) = x - -third :: (a,b,c,d) -> c -third (_,_,y,_) = y - -fourth :: (a,b,c,d) -> d -fourth (_,_,_,z) = z - -min_first_octet :: Cidr -> Octet -min_first_octet cidr = first (min_octets cidr) - -min_second_octet :: Cidr -> Octet -min_second_octet cidr = second (min_octets cidr) - -min_third_octet :: Cidr -> Octet -min_third_octet cidr = third (min_octets cidr) - -min_fourth_octet :: Cidr -> Octet -min_fourth_octet cidr = fourth (min_octets cidr) - -max_first_octet :: Cidr -> Octet -max_first_octet cidr = first (max_octets cidr) - -max_second_octet :: Cidr -> Octet -max_second_octet cidr = second (max_octets cidr) - -max_third_octet :: Cidr -> Octet -max_third_octet cidr = third (max_octets cidr) - -max_fourth_octet :: Cidr -> Octet -max_fourth_octet cidr = fourth (max_octets cidr) - -- Returns the mask portion of a CIDR address. That is, everything -- after the trailing slash. @@ -79,115 +28,18 @@ maskbits_from_string s = read ((splitWith (`elem` "/") s) !! 1) -- Takes an IP address String in CIDR notation, and returns a list of --- its octets (converted to Int). -octets_from_string :: String -> [Octet] +-- its octets (as Ints). +octets_from_string :: String -> [Int] octets_from_string s = map read (take 4 (splitWith (`elem` "./") s)) -from_string :: String -> Cidr -from_string s = Cidr (octs !! 0) (octs !! 1) (octs !! 2) (octs !! 3) mbits +cidr_from_string :: String -> Cidr +cidr_from_string s = Cidr addr mbits where + addr = IPv4Address (oct1) (oct2) (oct3) (oct4) + oct1 = octet_from_int (octs !! 0) + oct2 = octet_from_int (octs !! 1) + oct3 = octet_from_int (octs !! 2) + oct4 = octet_from_int (octs !! 3) octs = octets_from_string s mbits = maskbits_from_string s - - --- The base_two_to_base_ten function requires a way to determine --- whether or not the character it's currently parsing is valid. This --- should do it. -is_binary_digit :: Char -> Bool -is_binary_digit c = - if c `elem` ['0','1'] then - True - else - False - - --- Takes an Int, and returns its base-two representation as a String. -base_two :: Int -> String -base_two n = showIntAtBase 2 intToDigit n "" - - --- Takes a set of octets, and converts them to base-two --- individually. The results are then zero-padded on the left to 8 --- characters, and concatenated together. -octets_base_two :: Cidr -> String -octets_base_two cidr = - s1 ++ s2 ++ s3 ++ s4 - where - s1 = ((pad_left_to 8 '0') . base_two) (octet1 cidr) - s2 = ((pad_left_to 8 '0') . base_two) (octet2 cidr) - s3 = ((pad_left_to 8 '0') . base_two) (octet3 cidr) - s4 = ((pad_left_to 8 '0') . base_two) (octet4 cidr) - - -base_two_octetlist_to_octetlist :: BaseTwoOctetList -> OctetList -base_two_octetlist_to_octetlist b2ol = - (oct1, oct2, oct3, oct4) - where - oct1 = base_two_to_base_ten (first b2ol) - oct2 = base_two_to_base_ten (second b2ol) - oct3 = base_two_to_base_ten (third b2ol) - oct4 = base_two_to_base_ten (fourth b2ol) - - --- Convert a base-two String to an Int. -base_two_to_base_ten :: String -> Int -base_two_to_base_ten s = - if (length parsed) == 0 then - 0 - else - fst (parsed !! 0) - where - parsed = readInt 2 is_binary_digit digitToInt s - - --- Returns the minimum address (as a base-two string) satisfying the --- given CIDR string. -min_base_two_address :: Cidr -> String -min_base_two_address cidr = - pad_right_to 32 '0' netpart - where - netpart = take (maskbits cidr) (octets_base_two cidr) - - --- Returns the maximum address (as a base-two string) satisfying the --- given CIDR string. -max_base_two_address :: Cidr -> String -max_base_two_address cidr = - pad_right_to 32 '1' netpart - where - netpart = take (maskbits cidr) (octets_base_two cidr) - - --- The octet components of min_base_two_address, as a base-two String. -min_base_two_octets :: Cidr -> BaseTwoOctetList -min_base_two_octets cidr = - (oct1, oct2, oct3, oct4) - where - addr = min_base_two_address cidr - oct1 = fst (splitAt 8 addr) - oct2 = fst (splitAt 8 (snd (splitAt 8 addr))) - oct3 = fst (splitAt 8 (snd (splitAt 16 addr))) - oct4 = snd (splitAt 24 addr) - - --- The octet components of max_base_two_address, as a base-two String. -max_base_two_octets :: Cidr -> BaseTwoOctetList -max_base_two_octets cidr = - (oct1, oct2, oct3, oct4) - where - addr = max_base_two_address cidr - oct1 = fst (splitAt 8 addr) - oct2 = fst (splitAt 8 (snd (splitAt 8 addr))) - oct3 = fst (splitAt 8 (snd (splitAt 16 addr))) - oct4 = snd (splitAt 24 addr) - - --- The octet components of min_base_two_address, as Ints. -min_octets :: Cidr -> OctetList -min_octets cidr = base_two_octetlist_to_octetlist (min_base_two_octets cidr) - - --- The octet components of max_base_two_address, as Ints. -max_octets :: Cidr -> OctetList -max_octets cidr = base_two_octetlist_to_octetlist (max_base_two_octets cidr) diff --git a/src/IPv4Address.hs b/src/IPv4Address.hs index fed567e..6cfed3a 100644 --- a/src/IPv4Address.hs +++ b/src/IPv4Address.hs @@ -1,15 +1,4 @@ -module IPv4Address ( - IPv4Address, - ipv4address_from_string, - min_octet1, - min_octet2, - min_octet3, - min_octet4, - max_octet1, - max_octet2, - max_octet3, - max_octet4 -) where +module IPv4Address where import Bit import Octet diff --git a/src/Main.hs b/src/Main.hs index 7b3bd7b..a86eebf 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -2,17 +2,9 @@ import Data.List (intercalate, intersperse) import System.Exit (ExitCode(..), exitWith) import System.IO (stderr, hPutStrLn) -import Cidr (Cidr, - from_string, - is_valid_cidr, - min_first_octet, - min_second_octet, - min_third_octet, - min_fourth_octet, - max_first_octet, - max_second_octet, - max_third_octet, - max_fourth_octet) +import Cidr (Cidr(..), + cidr_from_string, + is_valid_cidr) import CommandLine (help_set, help_text, @@ -20,7 +12,10 @@ import CommandLine (help_set, Mode(..), parse_errors, parse_mode) - + +import IPv4Address +import Octet + -- Some exit codes, used in the ExitFailure constructor. exit_invalid_cidr :: Int exit_invalid_cidr = 1 @@ -59,14 +54,14 @@ cidr_to_regex cidr = range2 = numeric_range min2 max2 range3 = numeric_range min3 max3 range4 = numeric_range min4 max4 - min1 = min_first_octet cidr - min2 = min_second_octet cidr - min3 = min_third_octet cidr - min4 = min_fourth_octet cidr - max1 = max_first_octet cidr - max2 = max_second_octet cidr - max3 = max_third_octet cidr - max4 = max_fourth_octet cidr + min1 = octet_to_int (min_octet1 (ipv4address cidr) (maskbits cidr)) + min2 = octet_to_int (min_octet2 (ipv4address cidr) (maskbits cidr)) + min3 = octet_to_int (min_octet3 (ipv4address cidr) (maskbits cidr)) + min4 = octet_to_int (min_octet4 (ipv4address cidr) (maskbits cidr)) + max1 = octet_to_int (max_octet1 (ipv4address cidr) (maskbits cidr)) + max2 = octet_to_int (max_octet2 (ipv4address cidr) (maskbits cidr)) + max3 = octet_to_int (max_octet3 (ipv4address cidr) (maskbits cidr)) + max4 = octet_to_int (max_octet4 (ipv4address cidr) (maskbits cidr)) @@ -125,7 +120,7 @@ main = do let cidr_strings = lines input mapM validate_or_die cidr_strings - let cidrs = map Cidr.from_string cidr_strings + let cidrs = map Cidr.cidr_from_string cidr_strings -- Get the mode of operation. mode <- CommandLine.parse_mode diff --git a/src/Octet.hs b/src/Octet.hs index 28d3d7d..f8af4df 100644 --- a/src/Octet.hs +++ b/src/Octet.hs @@ -30,6 +30,22 @@ octet_to_int x = 0 * (bit_to_int (b8 x)) +-- Supply an integer greater than 255 at your own risk. +octet_from_int :: Int -> Octet +octet_from_int x + | (x < 0) = min_octet + | otherwise = (Octet a1 a2 a3 a4 a5 a6 a7 a8) + where + a1 = if (x `mod` 128) > 0 then One else Zero + a2 = if (x `mod` 64) > 0 then One else Zero + a3 = if (x `mod` 32) > 0 then One else Zero + a4 = if (x `mod` 16) > 0 then One else Zero + a5 = if (x `mod` 8) > 0 then One else Zero + a6 = if (x `mod` 4) > 0 then One else Zero + a7 = if (x `mod` 2) > 0 then One else Zero + a8 = if (x `mod` 1) > 0 then One else Zero + + -- The octet with the least possible value. min_octet :: Octet min_octet = Octet Zero Zero Zero Zero Zero Zero Zero Zero -- 2.43.2