packages feed

ip6addr 0.3 → 0.3.1

raw patch · 5 files changed

+129/−77 lines, 5 files

Files

ChangeLog view
@@ -1,13 +1,25 @@-2010-11-20	Michel Boucey <michel.boucey@gmail.com>+2010-10-26      Michel Boucey <michel.boucey@gmail.com> +	- Version 0.3.1 released.+	- The command-line tool 'ip6addrcan' now rewrites the+          embedded IPv4 adress in hexadecimal digits to output+          pure IPv6 text representation. But some IPv6 adresses+          with well-known prefixes (IPv4-compatible, IPv4-mapped,+          IPv4-translated, IPv4-translatable, ISATAP) keeps+          visible the embedded IPv4 dotted representation to keep+          visible in the text representation the fact they deals+          with IPv4 to IPv6 transition process.++2010-10-20	Michel Boucey <michel.boucey@gmail.com>+ 	- Version 0.3 released. 	- The command-line tool 'ip6addrval' is renamed (for the 	  last time) 'ip6addrcan'. This tool now outputs rewrited 	  valid IPv6 addresses canonized in conformation with 	  RFC 5952, which updates RFC 4291.-	- ip6addrgen is not updated yet from RFC 4291 to RFC 5952.-	  Outputted adresses from ip6addrgen have to be pipelined-	  through ip6addrcan.+	- 'ip6addrgen' is not updated yet from RFC 4291 to RFC 5952.+	  Outputted adresses from 'ip6addrgen' have to be pipelined+	  through 'ip6addrcan'.  2010-08-09	Michel Boucey <michel.boucey@gmail.com> 
ip6addr.cabal view
@@ -1,5 +1,5 @@ Name:           ip6addr-Version:        0.3+Version:        0.3.1 Author:         Michel Boucey <michel.boucey@gmail.com> Maintainer:     Michel Boucey <michel.boucey@gmail.com> Homepage:       http://www.cybervisible.fr/ip6addr
src/IP6AddrCan.hs view
@@ -41,7 +41,7 @@         Nothing -> hPutStrLn stderr i >> evalInputsErr is     where a = removeCidrSuffix i 			   -version = "ip6addrcan version 0.3"+version = "ip6addrcan version 0.3.1"  help   = "Usage: ip6addrcan [-v|-h] | [-e] [address ...]\n" 
src/IP6AddrGen.hs view
@@ -105,7 +105,7 @@         ([Help],_,_) -> putStrLn (usageInfo help options) >> exit         (_,_,_) -> putStrLn (usageInfo help options) >> exit -version = "ip6addrgen version 0.2"+version = "ip6addrgen version 0.3.1"  help = "Usage: ip6addrgen [-v|-h] | [-n] [-p]\n" 
src/IPv6Addr.hs view
@@ -1,17 +1,23 @@-module IPv6Addr (maybeIPv6Addr) where+module IPv6Addr where -import Data.Char (isDigit,isHexDigit,toLower)+import Data.Char (intToDigit,isDigit,isHexDigit,toLower) import Data.List (group,groupBy,intercalate,intersperse,elemIndex) import Data.Function (on) import Data.Maybe+import Numeric +type IPv6Addr = String++data IPv4AddrToken = Dot | EightBits String deriving (Eq)++data IPv6AddrToken = SixteenBits String | AllZeros | Colon | DoubleColon+                     | IPv4Addr String deriving (Eq)+ tokenizedBy :: String -> Char -> [String] tokenizedBy s c = groupBy ((==) `on` ( == c)) s  -- Parsing embedded IPv4 address -data IPv4AddrToken = Dot | EightBits String  deriving (Eq,Show)- dot :: String -> Maybe IPv4AddrToken dot s = if s == "." then Just Dot else Nothing @@ -33,15 +39,10 @@     do         let r = map ipv4Token (s `tokenizedBy` '.')         if (Nothing `notElem` r) && (length r == 7)-           then Just (IPv4Addr s) else Nothing+            then Just (IPv4Addr s) else Nothing  -- Parsing IPv6 Address -type IPv6Addr = String--data IPv6AddrToken = SixteenBits String | AllZeros  | Colon  | DoubleColon-                     | IPv4Addr String deriving (Eq,Show)- colon :: String -> Maybe IPv6AddrToken colon s = if s == ":" then Just Colon  else Nothing @@ -57,7 +58,7 @@               if length s' < 5 && all isHexDigit s'                  then case s' of                      "" -> Just AllZeros-                     -- Hexadecimal digits MUST be in lowercase (RFC 4.3)+                     -- Hexadecimal digits MUST be in lowercase (RFC 5952 4.3)                      otherwise -> Just (SixteenBits (map toLower s'))                  else Nothing     else Nothing@@ -71,31 +72,34 @@            | otherwise = Nothing            where s' = sixteenBits s -ipv6TokenToString :: IPv6AddrToken -> String-ipv6TokenToString (SixteenBits t) = t-ipv6TokenToString Colon = ":"-ipv6TokenToString DoubleColon = "::"+ipv6AddrTokenToString :: IPv6AddrToken -> String+ipv6AddrTokenToString (SixteenBits t) = t+ipv6AddrTokenToString Colon = ":"+ipv6AddrTokenToString DoubleColon = "::" -- "A single 16-bit 0000 field MUST be represented as 0" (RFC 5952, 4.1)-ipv6TokenToString AllZeros = "0"-ipv6TokenToString (IPv4Addr i) = i+ipv6AddrTokenToString AllZeros = "0"+ipv6AddrTokenToString (IPv4Addr i) = i +ipv6AddrToString :: [Maybe IPv6AddrToken] -> IPv6Addr+ipv6AddrToString t = concatMap ipv6AddrTokenToString (catMaybes t)+ countIPv4Addr :: [Maybe IPv6AddrToken] -> Int countIPv4Addr ts =     foldr oneMoreIPv4Token 0 ts         where-                   oneMoreIPv4Token t c =-                       case t of-                           Just (IPv4Addr _) -> c + 1-                           otherwise -> c+            oneMoreIPv4Token t c =+                case t of+                    Just (IPv4Addr _) -> c + 1+                    otherwise -> c  countDoubleColon :: [Maybe IPv6AddrToken] -> Int countDoubleColon ts =     foldr oneMoreDoubleColon 0 ts         where-                   oneMoreDoubleColon t c =-                       case t of-                           Just DoubleColon -> c + 1-                           otherwise -> c+            oneMoreDoubleColon t c =+                case t of+                    Just DoubleColon -> c + 1+                    otherwise -> c  firstValidToken :: [Maybe IPv6AddrToken] -> Bool firstValidToken ts =@@ -129,16 +133,50 @@   maybeIPv6Addr :: String -> Maybe IPv6Addr maybeIPv6Addr "::" = Just "::"+maybeIPv6Addr "::1" = Just "::1" maybeIPv6Addr s =     do-        let s'  = map ipv6AddrToken (s `tokenizedBy` ':')-        if ipv6AddrConstraints s'+        let ts = map ipv6AddrToken (s `tokenizedBy` ':')+        if ipv6AddrConstraints ts             then-                (if Just DoubleColon `notElem` s' then-                    Just (replaceTheLongestZerosRun s') else-                    Just (replaceTheLongestZerosRun (expendDoubleColon s')))+                (if Just DoubleColon `notElem` ts+                    then Just $ ipv6AddrToString (ipv4AddrToHex $ replaceTheLongestZerosRun ts)+                    else Just $ ipv6AddrToString (ipv4AddrToHex $ replaceTheLongestZerosRun (expendDoubleColon ts)))             else Nothing-			++-- The embedded IPv4 address have to be rewritten to output a pure IPv6 Address+-- text representation in hexadecimal digits. But some well-known prefixed IPv6+-- addresses have to keep visible in their text representation the fact that they+-- deals with IPv4 to IPv6 transition process (RFC 5952 Section 5) :+--+-- 	IPv4-compatible IPv6 address like "::1.2.3.4"+-- 	IPv4-mapped IPv6 address like "::ffff:1.2.3.4"+-- 	IPv4-translated address like "::ffff:0:1.2.3.4"+-- 	IPv4-translatable address like "64:ff9b::1.2.3.4"+-- 	ISATAP address like "fe80::5efe:1.2.3.4"+ipv4AddrToHex :: [Maybe IPv6AddrToken] -> [Maybe IPv6AddrToken]+ipv4AddrToHex [Just DoubleColon,Just (IPv4Addr a)] =+    [Just DoubleColon,Just Colon,Just (IPv4Addr a)]+ipv4AddrToHex [Just DoubleColon,Just (SixteenBits "ffff"),Just Colon,Just (IPv4Addr a)] =+    [Just DoubleColon,Just (SixteenBits "ffff"),Just Colon,Just (IPv4Addr a)]+ipv4AddrToHex [Just DoubleColon,Just (SixteenBits "ffff"),Just Colon,Just AllZeros,Just Colon,Just (IPv4Addr a)] =+    [Just DoubleColon,Just (SixteenBits "ffff"),Just Colon,Just AllZeros,Just Colon,Just (IPv4Addr a)]+ipv4AddrToHex [Just (SixteenBits "64"),Just Colon,Just (SixteenBits "ff9b"),Just DoubleColon,Just (IPv4Addr a)] =+    [Just (SixteenBits "64"),Just Colon,Just (SixteenBits "ff9b"),Just DoubleColon,Just (IPv4Addr a)]+ipv4AddrToHex [Just (SixteenBits "fe80"),Just DoubleColon,Just (SixteenBits "5efe"),Just Colon,Just (IPv4Addr a)] =+    [Just (SixteenBits "fe80"),Just DoubleColon,Just (SixteenBits "5efe"),Just Colon,Just (IPv4Addr a)]+ipv4AddrToHex ts =+    do+        let t = last ts+        case t of+            Just (IPv4Addr a) -> do+                let m = map (\x -> showIntAtBase 16 intToDigit (read x::Int) "")+                        $ filter (/= ".") (a `tokenizedBy` '.')+                init ts ++ [Just (SixteenBits ((!!) m 0 ++ addZero((!!) m 1))),Just Colon,Just (SixteenBits ((!!) m 2 ++ addZero((!!) m 3)))]+                    where+                        addZero s = if length s < 2 then '0':s else s+            otherwise -> ts+ expendDoubleColon :: [Maybe IPv6AddrToken] -> [Maybe IPv6AddrToken] expendDoubleColon mit = do     let s = splitAt (fromJust $ elemIndex (Just DoubleColon) mit) mit@@ -147,53 +185,55 @@     let fste = if null fsts then [] else fsts ++ [Just Colon]     let snde = if null snds then [] else Just Colon : snds     fste ++ allZerosTokensReplacement(quantityOfAllZerosTokenToReplace mit) ++ snde-		-quantityOfAllZerosTokenToReplace x =-    8 - foldl (\c x -> if (x /= Just DoubleColon) && (x /= Just Colon)-                            then c+1 else c) 0 x--allZerosTokensReplacement x = intersperse (Just Colon) (replicate x (Just AllZeros))+    where+        quantityOfAllZerosTokenToReplace x =+            8 - foldl (\c x -> if (x /= Just DoubleColon) && (x /= Just Colon)+                               then c+1 else c) 0 x+        allZerosTokensReplacement x =+            intersperse (Just Colon) (replicate x (Just AllZeros))  -- "the longest run of consecutive 16-bit 0 fields MUST be shortened" (RFC 5952, 4.2.3) -- All the stuff to deal with replacement of the longest zeros run by a double colon -longestLengthZerosRun x = maximum $ map longest x-                    where-                        longest t =-                            case t of-                                (True,i) -> i-                                otherwise -> 0+longestLengthZerosRun :: (Num a, Ord a) => [(Bool, a)] -> a+longestLengthZerosRun x =+    maximum $ map longest x+        where+            longest t =+                case t of+                    (True,i) -> i+                    otherwise -> 0 +replaceTheLongestZerosRun :: [Maybe IPv6AddrToken] -> [Maybe IPv6AddrToken]+replaceTheLongestZerosRun s' =+    zerosToDoubleColon s' (zerosRunToReplace $ zerosRunsList s')+        where+            zerosRunToReplace t =+                let l = longestLengthZerosRun t+                in (firstLongestZerosRunIndex t l,l)+ firstLongestZerosRunIndex :: (Num b) => [(Bool, b)] -> b -> b-firstLongestZerosRunIndex x y = sum $ snd $ unzip $ takeWhile (/=(True,y)) x+firstLongestZerosRunIndex x y =+    sum . snd . unzip $ takeWhile (/=(True,y)) x  zerosRunsList :: [Maybe IPv6AddrToken] -> [(Bool, Int)]-zerosRunsList x = map helper $ groupZerosRuns x-                  where-                      helper h =-                          if head h == "0"-                          then (True,lh)-                          else (False,lh)-                          where lh = length h--groupZerosRuns :: [Maybe IPv6AddrToken] -> [[String]]-groupZerosRuns lts = group $ filter (/=":") $ map ipv6TokenToString $ catMaybes lts--onlyStringTokens :: [Maybe IPv6AddrToken] -> [String]-onlyStringTokens x = filter (/=":") $ map ipv6TokenToString $ catMaybes x--replaceTheLongestZerosRun :: [Maybe IPv6AddrToken] -> IPv6Addr-replaceTheLongestZerosRun s' = zerosToDoubleColon (onlyStringTokens s') (zerosRunToReplace $ zerosRunsList s')--zerosRunToReplace :: [(Bool, Int)] -> (Int, Int)-zerosRunToReplace t =-    let l = longestLengthZerosRun t-    in (firstLongestZerosRunIndex t l,l)+zerosRunsList x =+    map helper $ groupZerosRuns x+        where+            helper h =+                if head h == Just AllZeros+                then (True,lh) else (False,lh)+                    where lh = length h+            groupZerosRuns =+                group . filter (/= Just Colon) -zerosToDoubleColon :: [String] -> (Int,Int) -> IPv6Addr+zerosToDoubleColon :: [Maybe IPv6AddrToken] -> (Int,Int) -> [Maybe IPv6AddrToken] -- No all zeros token, so no double colon replacement...-zerosToDoubleColon ls (_,0) = intercalate ":" ls--- "The symbol '::' MUST NOT be used to shorten just one 16-bit 0 field" (RFC 4.2.2)-zerosToDoubleColon ls (_,1) = intercalate ":" ls+zerosToDoubleColon ls (_,0) = ls+-- "The symbol '::' MUST NOT be used to shorten just one 16-bit 0 field" (RFC 5952 4.2.2)+zerosToDoubleColon ls (_,1) = ls zerosToDoubleColon ls (i,l) =-    concat $ intersperse ":" (take i ls) ++ ["::"] ++ intersperse ":" (drop (i+l) ls)+    let ls' = filter (/= Just Colon) ls+    in intersperse (Just Colon) (take i ls')+    ++ [Just DoubleColon]+    ++ intersperse (Just Colon) (drop (i+l) ls')