{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE OverloadedStrings #-} module HaskellWorks.Data.Network.Ip.Ip ( IpBlock(..) , isCanonical , canonicalise , firstIpAddress , lastIpAddress ) where import Control.Monad import Data.Word import GHC.Generics import HaskellWorks.Data.Bits.BitWise import HaskellWorks.Data.Network.Ip.Validity import Text.Read import qualified HaskellWorks.Data.Network.Ip.Ipv4 as V4 import qualified HaskellWorks.Data.Network.Ip.Ipv6 as V6 data IpBlock v = IpBlockV4 (V4.IpBlock v) | IpBlockV6 (V6.IpBlock v) deriving (Eq, Ord, Generic) instance Show (IpBlock v) where showsPrec _ (IpBlockV4 a) = shows a showsPrec _ (IpBlockV6 a) = shows a instance Read (IpBlock Unaligned) where readsPrec _ s = case readMaybe s :: Maybe (V4.IpBlock Unaligned) of Just ip -> [(IpBlockV4 ip, "")] Nothing -> case readMaybe s :: Maybe (V6.IpBlock Unaligned) of Just ipv6 -> [(IpBlockV6 ipv6, "")] Nothing -> [] isCanonical :: IpBlock v -> Bool isCanonical (IpBlockV4 b) = V4.isCanonical b isCanonical (IpBlockV6 b) = V6.isCanonical b canonicalise :: IpBlock Unaligned -> Maybe (IpBlock Canonical) canonicalise (IpBlockV4 (V4.IpBlock a m)) = mfilter isCanonical (Just $ IpBlockV4 (V4.IpBlock a m)) canonicalise (IpBlockV6 (V6.IpBlock a m)) = mfilter isCanonical (Just $ IpBlockV6 (V6.IpBlock a m)) firstIpAddress :: IpBlock Canonical -> (Word32, Word32, Word32, Word32) firstIpAddress (IpBlockV4 v4Block) = firstIpAddress (IpBlockV6 (V6.fromV4 v4Block)) -- firstIpAddress (IpBlockV6 (V6.IpBlock ip _)) = V6.words ip firstIpAddress (IpBlockV6 (V6.IpBlock (V6.IpAddress ip) _)) = ip lastIpAddress :: IpBlock Canonical -> (Word32, Word32, Word32, Word32) lastIpAddress (IpBlockV4 ib) = (0, 0, 0xFFFF, V4.word (V4.lastIpAddress ib)) lastIpAddress (IpBlockV6 (V6.IpBlock (V6.IpAddress ip) (V6.IpNetMask msk))) = let (w1, w2, w3, w4) = ip lt = V6.masksIp $ fromIntegral msk w1' = w1 .|. (lt !! 0) w2' = w2 .|. (lt !! 1) w3' = w3 .|. (lt !! 2) w4' = w4 .|. (lt !! 3) in (w1', w2', w3', w4')