packages feed

IPv6Addr 0.4 → 0.5

raw patch · 7 files changed

+97/−65 lines, 7 filesdep +iproutedep +networkdep ~basedep ~bytestringdep ~network-info

Dependencies added: iproute, network

Dependency ranges changed: base, bytestring, network-info

Files

IPv6Addr.cabal view
@@ -1,8 +1,8 @@ Name:		IPv6Addr-Version:	0.4+Version:	0.5 License:	BSD3 License-File:	LICENSE-Copyright:      Copyright © 2011-2013 - Michel Boucey+Copyright:      Copyright © 2011-2014 - Michel Boucey Author:		Michel Boucey <michel.boucey@gmail.com> Maintainer:	Michel Boucey <michel.boucey@gmail.com> Bug-Reports:    mailto:michel.boucey@gmail.com@@ -18,9 +18,11 @@  Library   Build-Depends: attoparsec,-                 base >= 3 && <= 5,-                 bytestring >= 0.9,-                 network-info >= 0.2,+                 base < 5,+                 bytestring,+                 iproute,+                 network,+                 network-info,                  random,                  text 
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2011-2013 - Michel Boucey+Copyright (c) 2011-2014 - Michel Boucey  All rights reserved. 
Text/IPv6Addr.hs view
@@ -1,7 +1,7 @@ -- -----------------------------------------------------------------------------  -- Module      :  Text.IPv6Addr--- Copyright   :  (c) Michel Boucey 2011-2013+-- Copyright   :  Copyright © Michel Boucey 2011-2014 -- License     :  BSD-style -- Maintainer  :  michel.boucey@gmail.com --@@ -16,19 +16,29 @@     , maybeIPv6Addr     , maybePureIPv6Addr     , maybeFullIPv6Addr+    , sameIPv6Addr+    , fromIPv6Addr+    , toIPv6+    , toHostName+    , toIP6ARPA     , getIPv6AddrOf-    , ip6arpa     , randIPv6Addr     ) where -import Control.Applicative ((<$>))+import Control.Applicative (pure,(<$>),(<*>))+import Data.IP (IPv6) import Data.Maybe (fromJust) import qualified Data.Text as T+import Network (HostName)+import System.Random (randomRIO)  import Text.IPv6Addr.Internal-import Text.IPv6Addr.Manip (sixteenBitArbToken,partialRandAddr)+import Text.IPv6Addr.Manip (randIPv6AddrChunk,randPartialIPv6Addr) import Text.IPv6Addr.Types +instance Eq IPv6Addr where+    (==) (IPv6Addr a) (IPv6Addr b) = show (maybePureIPv6Addr a) == show (maybePureIPv6Addr b)+ -- | Returns 'Just' the text representation of a canonized -- 'IPv6Addr' in conformation with RFC 5952, or 'Nothing'. --@@ -39,45 +49,63 @@  -- | Returns 'Just' a pure 'IPv6Addr', or 'Nothing'. ----- > maybePureIPv6Addr "::ffff:192.0.2.128" == Just (IPv6Addr "::ffff:c000:280")+-- > mabePureIPv6Addr "::ffff:192.0.2.128" == Just (IPv6Addr "::ffff:c000:280") -- maybePureIPv6Addr :: T.Text -> Maybe IPv6Addr maybePureIPv6Addr t = maybeTokPureIPv6Addr t >>= ipv6TokensToIPv6Addr --- | Returns 'Just' a pure and expanded 'IPv6Addr', or 'Nothing'.+-- | Returns 'Just' a pure and fully expanded 'IPv6Addr', or 'Nothing'. ----- > maybeFullIPv6Addr "::ffff:192.0.2.128" == Just (IPv6Addr "0000:0000:0000:0000:0000:ffff:c000:0280")+-- > mayebFullIPv6Addr "::ffff:192.0.2.128" == Just (IPv6Addr "0000:0000:0000:0000:0000:ffff:c000:0280") -- maybeFullIPv6Addr :: T.Text -> Maybe IPv6Addr-maybeFullIPv6Addr t =-    maybeTokPureIPv6Addr t >>= (ipv6TokensToIPv6Addr . expandTokens . fromDoubleColon)+maybeFullIPv6Addr t = maybeTokPureIPv6Addr t >>= (ipv6TokensToIPv6Addr . expandTokens . fromDoubleColon) --- | Returns 'Just' the reverse lookup domain name corresponding of the given IPv6 address--- (RFC 3596 Section 2.5), or 'Nothing'.+-- | Returns 'True' if arguments are two textual representations of the same IPv6 address.+sameIPv6Addr :: T.Text -> T.Text -> Bool+sameIPv6Addr a b =+    case maybePureIPv6Addr a of+        Nothing -> False+        Just a' -> case maybePureIPv6Addr b of+                       Nothing -> False+                       Just b' -> a' == b'++-- | Returns the reverse lookup domain name corresponding of the given IPv6 address (RFC 3596 Section 2.5). ----- > ip6arpa (IPv6Addr "4321:0:1:2:3:4:567:89ab") == Just "b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa."+-- > toIP6ARPA (IPv6Addr "4321:0:1:2:3:4:567:89ab") == "b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.ARPA." ---ip6arpa :: IPv6Addr -> T.Text-ip6arpa t =-    rev (fromIPv6Addr $ fromJust $ maybeFullIPv6Addr $ fromIPv6Addr t) T.empty+toIP6ARPA :: IPv6Addr -> T.Text+toIP6ARPA a =+    T.append (T.reverse $ T.concatMap trans $ fromIPv6Addr $ fromJust $ maybeFullIPv6Addr $ fromIPv6Addr a) (T.pack "IP6.ARPA.")   where-    rev i o = if i == T.empty-                  then o `T.append` T.pack "ip6.arpa."-                  else do let c = T.last i-                          rev (T.init i)-                              (if c /= ':'-                                   then o `T.append` T.pack [c] `T.append` T.pack "."-                                   else o)+    trans ':' = T.empty+    trans c   = T.append (T.pack ".") (T.pack [c]) --- | Returns 'Just' the canonized 'IPv6Addr' of the given network interface,+-- | Given an 'IPv6Addr', returns the corresponding 'HostName'.+toHostName :: IPv6Addr -> HostName+toHostName = show++-- | Given an 'IPv6addr', returns the corresponding 'IPv6' address.+toIPv6 :: IPv6Addr -> IPv6+toIPv6 a = read $ show a++-- | Returns 'Just' the canonized 'IPv6Addr' of the given local network interface, -- or 'Nothing'. -- -- > getIPv6AddrOf "eth0" -- getIPv6AddrOf :: String -> IO (Maybe IPv6Addr)-getIPv6AddrOf s =-    maybe Nothing (maybeIPv6Addr . T.pack . show) <$> (lookup s <$> networkInterfacesIPv6AddrList)+getIPv6AddrOf s = maybe Nothing (maybeIPv6Addr . T.pack . show) <$> (lookup s <$> networkInterfacesIPv6AddrList) --- | Returns a random 'IPv6Addr'+-- | Returns a random 'IPv6Addr'. randIPv6Addr :: IO IPv6Addr-randIPv6Addr = IPv6Addr . ipv6TokensToText <$> partialRandAddr 8+randIPv6Addr = do+    r   <- randomRIO (1,8)+    tks <- case r of+              8 -> randPartialIPv6Addr 8+              _ -> do r' <- randomRIO (1,8-r)+                      case r + r' of+                          7 -> concat <$> sequence [randPartialIPv6Addr r,pure [Colon,AllZeros,Colon],randPartialIPv6Addr r']+                          8 -> randPartialIPv6Addr 8+                          _ -> concat <$> sequence [randPartialIPv6Addr r,pure [DoubleColon],randPartialIPv6Addr r']+    return $ fromJust $ ipv6TokensToIPv6Addr tks
Text/IPv6Addr/Internal.hs view
@@ -2,7 +2,7 @@  -- |  -- Module      :  Text.IPv6Addr--- Copyright   :  (c) Michel Boucey 2011-2013+-- Copyright   :  Copyright © Michel Boucey 2011-2014 -- License     :  BSD-Style -- Maintainer  :  michel.boucey@gmail.com --@@ -55,8 +55,7 @@ ipv6TokenToText (SixteenBit s) = s  ipv6TokenToText Colon = T.pack ":" ipv6TokenToText DoubleColon = T.pack "::"--- "A single 16-bit 0000 field MUST be represented as 0" (RFC 5952, 4.1)-ipv6TokenToText AllZeros = tok0  -- +ipv6TokenToText AllZeros = tok0 -- "A single 16-bit 0000 field MUST be represented as 0" (RFC 5952, 4.1) ipv6TokenToText (IPv4Addr a) = a  -- | Returns 'True' if a list of 'IPv6AddrToken' constitutes a valid IPv6 Address.@@ -178,8 +177,7 @@     tokffff = T.pack "ffff"     tok5efe = T.pack "5efe" --- | Rewrites 'Just' an embedded 'IPv4Addr' into the corresponding list of pure--- 'IPv6Addr' tokens.+-- | Rewrites 'Just' an embedded 'IPv4Addr' into the corresponding list of pure 'IPv6Addr' tokens. -- -- > ipv4AddrToIPv6AddrTokens (IPv4Addr "127.0.0.1") == [SixteenBits "7f0",Colon,SixteenBits "1"] --@@ -188,9 +186,9 @@     case t of         IPv4Addr a -> do             let m = toHex a-            [ SixteenBit ((!!) m 0 `T.append` addZero ((!!) m 1))+            [  SixteenBit ((!!) m 0 `T.append` addZero ((!!) m 1))              , Colon-             , SixteenBit ((!!) m 2 `T.append` addZero ((!!) m 3))]+             , SixteenBit ((!!) m 2 `T.append` addZero ((!!) m 3)) ]         _          -> [t]       where         toHex a = map (\x -> T.pack $ showHex (read (T.unpack x)::Int) "") $ T.split (=='.') a@@ -257,7 +255,7 @@  fullSixteenBit :: T.Text -> Maybe IPv6AddrToken fullSixteenBit t =-    case parse fourHexaChars t of+    case parse ipv6AddrFullChunk t of         Done a b  -> if a==T.empty then Just $ SixteenBit $ T.pack b else Nothing         _         -> Nothing @@ -273,7 +271,7 @@  sixteenBit :: Parser IPv6AddrToken sixteenBit = do-    r <- fourHexaChars <|> count 3 hexaChar <|> count 2 hexaChar <|> count 1 hexaChar+    r <- ipv6AddrFullChunk <|> count 3 hexaChar <|> count 2 hexaChar <|> count 1 hexaChar     -- "Leading zeros MUST be suppressed" (RFC 5952, 4.1)     let r' = T.dropWhile (=='0') $ T.pack r     return $ if T.null r'@@ -315,8 +313,8 @@     string $ T.pack ":"     return Colon -fourHexaChars :: Parser String-fourHexaChars = count 4 hexaChar+ipv6AddrFullChunk :: Parser String+ipv6AddrFullChunk = count 4 hexaChar  hexaChar :: Parser Char hexaChar = satisfy (inClass "0-9a-fA-F")
Text/IPv6Addr/Manip.hs view
@@ -2,7 +2,7 @@  -- | -- Module      :  Text.IPv6Addr--- Copyright   :  (c) Michel Boucey 2011-2013+-- Copyright   :  Copyright © Michel Boucey 2011-2014 -- License     :  BSD-Style -- Maintainer  :  michel.boucey@gmail.com --@@ -12,8 +12,8 @@ -- -----------------------------------------------------------------------------  module Text.IPv6Addr.Manip-    ( sixteenBitArbToken-    , partialRandAddr+    ( randIPv6AddrChunk+    , randPartialIPv6Addr     , macAddrToIPv6AddrTokens     , getTokIPv6AddrOf     , getTokMacAddrOf@@ -32,24 +32,24 @@ import Text.IPv6Addr.Internal import Text.IPv6Addr.Types --- | Returns 'Just' an arbitrary 'SixteenBit' token based on a mask \"____\", each+-- | Returns 'Just' a random 'SixteenBit' token based on a mask \"____\", each -- underscore being replaced by a random hexadecimal digit. ----- > sixteenBitArbToken "_f__" == Just (SixteenBit "bfd4")+-- > randIPv6AddrChunk "_f__" == Just (SixteenBit "bfd4") -- -sixteenBitArbToken :: String -> IO IPv6AddrToken-sixteenBitArbToken m =+randIPv6AddrChunk :: String -> IO IPv6AddrToken+randIPv6AddrChunk m =     mapM getHex m >>= \g -> return $ SixteenBit $ T.dropWhile (=='0') $ T.pack g   where     getHex c-        | c == '_'  = randomRIO(0,15) >>= \r -> return $ intToDigit r+        | c == '_'  = intToDigit <$> randomRIO (0,15)         | otherwise = return c --- | Generates a partial 'IPv6Addr' with n 'SixteenBit'-partialRandAddr :: Int -> IO [IPv6AddrToken]-partialRandAddr n-    | n > 0 && n < 9 = intersperse Colon <$> replicateM n (sixteenBitArbToken "____")-    | otherwise = return []+-- | Generates a random partial 'IPv6Addr' with n 'SixteenBit'+randPartialIPv6Addr :: Int -> IO [IPv6AddrToken]+randPartialIPv6Addr n+    | n > 0 && n < 9 = intersperse Colon <$> replicateM n (randIPv6AddrChunk "____")+    | otherwise      = return []  -- | Given a MAC address, returns the corresponding 'IPv6AddrToken' list, or an empty list. --@@ -58,7 +58,7 @@ macAddrToIPv6AddrTokens :: T.Text -> Maybe [IPv6AddrToken] macAddrToIPv6AddrTokens t =     case parse macAddr t of-        Done a b -> if a==T.empty then intersperse Colon <$> b else Nothing+        Done a b -> if a == T.empty then intersperse Colon <$> b else Nothing         _        -> Nothing  --
Text/IPv6Addr/Types.hs view
@@ -2,7 +2,7 @@  -- | -- Module      :  Text.IPv6Addr--- Copyright   :  (c) Michel Boucey 2011-2013+-- Copyright   :  Copyright © Michel Boucey 2011-2014 -- License     :  BSD-Style -- Maintainer  :  michel.boucey@gmail.com --@@ -15,7 +15,10 @@  import qualified Data.Text as T -data IPv6Addr = IPv6Addr T.Text deriving (Eq,Show)+data IPv6Addr = IPv6Addr T.Text++instance Show IPv6Addr where+    show (IPv6Addr addr) = T.unpack addr  data IPv6AddrToken     = SixteenBit T.Text  -- ^ A four hexadecimal digits group representing a 16-Bit chunk
tests/Main.hs view
@@ -94,9 +94,10 @@   , (~?=) (maybeFullIPv6Addr "a:bb:ccc:dddd:1cDc::1") (Just (IPv6Addr "000a:00bb:0ccc:dddd:1cdc:0000:0000:0001"))   , (~?=) (maybeFullIPv6Addr "FE80::0202:B3FF:FE1E:8329") (Just (IPv6Addr "fe80:0000:0000:0000:0202:b3ff:fe1e:8329"))   , (~?=) (maybeFullIPv6Addr "aDb6::CE67") (Just (IPv6Addr "adb6:0000:0000:0000:0000:0000:0000:ce67"))-  , (~?=) (ip6arpa (IPv6Addr "::1")) "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."-  , (~?=) (ip6arpa (IPv6Addr "2b02:0b08:0:7::0001")) "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.0.0.0.0.0.0.0.8.0.b.0.2.0.b.2.ip6.arpa."-  , (~?=) (ip6arpa (IPv6Addr "2b02:b08:0:7::1")) "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.0.0.0.0.0.0.0.8.0.b.0.2.0.b.2.ip6.arpa."-  , (~?=) (ip6arpa (IPv6Addr "fdda:5cc1:23:4::1f")) "f.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.4.0.0.0.3.2.0.0.1.c.c.5.a.d.d.f.ip6.arpa."-  , (~?=) (ip6arpa (IPv6Addr "4321:0:1:2:3:4:567:89ab")) "b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa."+  , (~?=) (toIP6ARPA (IPv6Addr "::1")) "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA."+  , (~?=) (toIP6ARPA (IPv6Addr "2b02:0b08:0:7::0001")) "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.0.0.0.0.0.0.0.8.0.b.0.2.0.b.2.IP6.ARPA."+  , (~?=) (toIP6ARPA (IPv6Addr "2b02:b08:0:7::1")) "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.0.0.0.0.0.0.0.8.0.b.0.2.0.b.2.IP6.ARPA."+  , (~?=) (toIP6ARPA (IPv6Addr "fdda:5cc1:23:4::1f")) "f.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.4.0.0.0.3.2.0.0.1.c.c.5.a.d.d.f.IP6.ARPA."+  , (~?=) (toIP6ARPA (IPv6Addr "2001:db8::")) "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.IP6.ARPA."+  , (~?=) (toIP6ARPA (IPv6Addr "4321:0:1:2:3:4:567:89ab")) "b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.ARPA."   ]