-- ----------------------------------------------------------------------------- -- | -- Module : Text.IPv6Addr -- Copyright : (c) Michel Boucey 2011-2013 -- License : BSD-Style -- Maintainer : michel.boucey@gmail.com -- Stability : provisional -- -- Dealing with IPv6 address text representations, -- canonization and manipulations. -- -- ----------------------------------------------------------------------------- module Text.IPv6Addr.Manip ( module Text.IPv6Addr.Internal , sixteenBitsArbToken , partialRandAddr , macAddrToIPv6AddrTokens , getTokIPv6AddrOf , getTokMacAddrOf ) where import Control.Monad (replicateM) import Data.Char (intToDigit,isHexDigit) import Data.List (intersperse) import Data.Maybe (catMaybes,fromJust) import qualified Data.Text as T import System.Random (randomRIO) import Network.Info import Text.IPv6Addr.Internal import Text.IPv6Addr.Types -- | Returns 'Just' an arbitrary 'SixteenBits' token based on a mask \"____\", each -- underscore being replaced by a random hexadecimal digit. -- -- > sixteenBitsArbToken "_f__" == Just (SixteenBits "bfd4") -- sixteenBitsArbToken :: String -> IO (Maybe IPv6AddrToken) sixteenBitsArbToken m = mapM getHex m >>= \cs -> return $ sixteenBits $ T.pack cs where getHex c = case c of '_' -> hexRand otherwise -> return c where hexRand = randomRIO(0,15) >>= \r -> return $ intToDigit r -- | Generates a partial 'IPv6Addr' with n 'SixteenBits' partialRandAddr :: Int -> IO [IPv6AddrToken] partialRandAddr n = if n < 9 then do l <- replicateM n $ sixteenBitsArbToken "____" return $ intersperse Colon $ catMaybes l else return [] -- | Given a MAC address, returns the corresponding 'IPv6AddrToken' list, or an empty list. -- -- > macAddrToIPv6AddrTokens "fa:1d:58:cc:95:16" == [SixteenBits "fa1d",Colon,SixteenBits "58cc",Colon,SixteenBits "9516"] -- macAddrToIPv6AddrTokens :: T.Text -> [IPv6AddrToken] macAddrToIPv6AddrTokens mac = if T.length mac == 17 then do let p = snd $ trans (T.split (==':') mac,[]) if length p == 3 then intersperse Colon $ map (fromJust . maybeIPv6AddrToken) p else [] else [] where trans ([],l) = ([],l) trans (l1,l2) = do let s = splitAt 2 l1 trans (snd s,l2 ++ [T.concat $ fst s]) -- -- Functions based upon Network.Info to get local MAC and IPv6 addresses. -- networkInterfacesMacAddrList :: IO [(String,MAC)] networkInterfacesMacAddrList = getNetworkInterfaces >>= \n -> return $ map networkInterfacesMac n where networkInterfacesMac (NetworkInterface n _ _ m) = (n,m) -- | Given a valid name of a local network interface, returns 'Just' the list of -- tokens of the interface's IPv6 address, or 'Nothing'. getTokIPv6AddrOf :: String -> IO (Maybe [IPv6AddrToken]) getTokIPv6AddrOf s = do l <- networkInterfacesIPv6AddrList case lookup s l of Just a -> return $ maybeTokIPv6Addr $ T.pack $ show a Nothing -> return Nothing -- | Given a valid name of a local network interface, -- returns 'Just' the corresponding list of 'IPv6AddrToken' of the interface's MAC Address, -- or 'Nothing'. getTokMacAddrOf :: String -> IO (Maybe [IPv6AddrToken]) getTokMacAddrOf s = do l <- networkInterfacesMacAddrList case lookup s l of Just a -> return $ Just $ macAddrToIPv6AddrTokens $ T.pack $ show a Nothing -> return Nothing