module Hans.Message.Arp where
import Hans.Address (Address(addrSize))
import Hans.Utils (chunk)
import Control.Applicative (Applicative(..),(<$>))
import Data.Serialize.Get (Get,runGet,getWord8,getWord16be)
import Data.Serialize.Put (Putter,runPut,putWord16be,putWord8)
import Data.Word (Word16)
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
data ArpPacket hw p = ArpPacket
{ arpHwType :: !Word16
, arpPType :: !Word16
, arpOper :: ArpOper
, arpSHA :: hw
, arpSPA :: p
, arpTHA :: hw
, arpTPA :: p
} deriving (Show)
parseArpPacket :: Get hw -> Get p
-> S.ByteString -> Either String (ArpPacket hw p)
parseArpPacket getHw getP = runGet $
ArpPacket
<$> getWord16be
<*> getWord16be
<* getWord8
<* getWord8
<*> parseArpOper
<*> getHw
<*> getP
<*> getHw
<*> getP
renderArpPacket :: (Address hw, Address p)
=> Putter hw -> Putter p
-> ArpPacket hw p -> L.ByteString
renderArpPacket putHw putP arp = chunk $ runPut $ do
putWord16be (arpHwType arp)
putWord16be (arpPType arp)
putWord8 (addrSize (arpSHA arp))
putWord8 (addrSize (arpSPA arp))
renderArpOper (arpOper arp)
putHw (arpSHA arp)
putP (arpSPA arp)
putHw (arpTHA arp)
putP (arpTPA arp)
data ArpOper
= ArpRequest
| ArpReply
deriving (Show,Eq)
parseArpOper :: Get ArpOper
parseArpOper = do
b <- getWord16be
case b of
0x1 -> return ArpRequest
0x2 -> return ArpReply
_ -> fail "invalid Arp opcode"
renderArpOper :: Putter ArpOper
renderArpOper op = case op of
ArpRequest -> putWord16be 0x1
ArpReply -> putWord16be 0x2