module Nettle.Ethernet.EthernetAddress (
EthernetAddress
, ethernetAddress
, ethernetAddress64
, unpack
, unpack64
, pack_32_16
, isReserved
, broadcastAddress
, getEthernetAddress
, getEthernetAddress2
, putEthernetAddress
, putEthernetAddress2
) where
import Data.Word
import Data.Bits
import Data.Binary
import Data.Binary.Put as P
import qualified Data.Binary.Strict.Get as Strict
import qualified Nettle.OpenFlow.StrictPut as Strict
import Data.Generics
import qualified Data.Binary.Get as Binary
import GHC.Base
import GHC.Word
newtype EthernetAddress = EthernetAddress Word64
deriving (Show,Read,Eq,Ord, Data, Typeable)
ethernetAddress64 :: Word64 -> EthernetAddress
ethernetAddress64 w64 = EthernetAddress (w64 `mod` 0x01000000000000)
ethernetAddress :: Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> EthernetAddress
ethernetAddress w1 w2 w3 w4 w5 w6
= let w64 = (shiftL (fromIntegral w1) 40) .|.
(shiftL (fromIntegral w2) 32) .|.
(shiftL (fromIntegral w3) 24) .|.
(shiftL (fromIntegral w4) 16) .|.
(shiftL (fromIntegral w5) 8) .|.
(fromIntegral w6)
in EthernetAddress w64
pack_32_16 :: Word32 -> Word16 -> Word64
pack_32_16 w32 w16
= (fromIntegral w32 `shiftL` 16) .|. fromIntegral w16
unpack :: EthernetAddress -> (Word8,Word8,Word8,Word8,Word8,Word8)
unpack (EthernetAddress w64) =
let a1 = fromIntegral (shiftR w64 40)
a2 = fromIntegral (shiftR w64 32 `mod` 0x0100)
a3 = fromIntegral (shiftR w64 24 `mod` 0x0100)
a4 = fromIntegral (shiftR w64 16 `mod` 0x0100)
a5 = fromIntegral (shiftR w64 8 `mod` 0x0100)
a6 = fromIntegral (w64 `mod` 0x0100)
in (a1,a2,a3,a4,a5,a6)
unpack64 :: EthernetAddress -> Word64
unpack64 (EthernetAddress e) = e
getEthernetAddress :: Strict.Get EthernetAddress
getEthernetAddress =
do w32 <- Strict.getWord32be
w16 <- Strict.getWord16be
return (EthernetAddress (pack_32_16 w32 w16))
getEthernetAddress2 :: Binary.Get EthernetAddress
getEthernetAddress2 =
do w32 <- Binary.getWord32be
w16 <- Binary.getWord16be
return (EthernetAddress (pack_32_16 w32 w16))
putEthernetAddress :: EthernetAddress -> Strict.Put
putEthernetAddress (EthernetAddress w64)
= Strict.putWord32be (fromIntegral (shiftR w64 16)) >>
Strict.putWord16be (fromIntegral (w64 `mod` 0x010000))
putEthernetAddress2 :: EthernetAddress -> P.Put
putEthernetAddress2 (EthernetAddress w64)
= P.putWord32be (fromIntegral (shiftR w64 16)) >>
P.putWord16be (fromIntegral (w64 `mod` 0x010000))
isReserved :: EthernetAddress -> Bool
isReserved e =
let (a1, a2, a3, a4, a5, a6) = unpack e
in
a1 == 0x01 &&
a2 == 0x80 &&
a3 == 0xc2 &&
a4 == 0 &&
((a5 .&. 0xf0) == 0)
broadcastAddress :: EthernetAddress
broadcastAddress = EthernetAddress 0xffffffffffff