{-# LINE 1 "src/Network/Icmp/Marshal.hsc" #-}
{-# language DataKinds #-}




module Network.Icmp.Marshal
  ( pokeIcmpHeader
  , peekIcmpHeaderSequenceNumber
  , peekIcmpHeaderPayload
  , peekIcmpHeaderType
  , sizeOfIcmpHeader
  ) where

import Data.Word (Word32,Word16,Word8)
import GHC.Exts (RealWorld)

import Data.Primitive (MutableByteArray)
import Data.Primitive (readByteArray,writeByteArray)

-- The linux kernel (version 4.19.9) defines icmphdr as:
--
-- struct icmphdr {
--   __u8		type;
--   __u8		code;
--   __sum16	checksum;
--   union {
-- 	struct {
-- 		__be16	id;
-- 		__be16	sequence;
-- 	} echo;
-- 	__be32	gateway;
-- 	struct {
-- 		__be16	__unused;
-- 		__be16	mtu;
-- 	} frag;
-- 	__u8	reserved[4];
--   } un;
-- };

sizeOfIcmpHeader :: Int
sizeOfIcmpHeader = (8)
{-# LINE 42 "src/Network/Icmp/Marshal.hsc" #-}

-- This sets the type to ICMP_ECHO and the sequence number to
-- user-specified values. The sequence number is supposed to be
-- in network byte order, but this does not actually matter.
-- If it is mangled on the way out, it will also be
-- mangled when we receive it.
--
-- Why is the identifier (un.echo.id) missing? Linux overwrites
-- the identifier regardless of what the user puts there. This
-- makes sense since the operating system wants to make it as
-- easy as possible to hand the reply to the right process.
pokeIcmpHeader ::
     MutableByteArray RealWorld
  -> Word16 -- sequence number
  -> Word32 -- payload, we use this as a bigger sequence number
  -> IO ()
pokeIcmpHeader ptr sequenceNumber payload = do
  (\hsc_arr -> writeByteArray hsc_arr 0) ptr (8 :: Word8)
{-# LINE 60 "src/Network/Icmp/Marshal.hsc" #-}
  (\hsc_arr -> writeByteArray hsc_arr 3) ptr sequenceNumber
{-# LINE 61 "src/Network/Icmp/Marshal.hsc" #-}
  writeByteArray ptr 2 payload
{-# LINE 62 "src/Network/Icmp/Marshal.hsc" #-}

peekIcmpHeaderType :: MutableByteArray RealWorld -> IO Word8
peekIcmpHeaderType ptr = do
  (\hsc_arr -> readByteArray hsc_arr 0) ptr
{-# LINE 66 "src/Network/Icmp/Marshal.hsc" #-}

peekIcmpHeaderSequenceNumber :: MutableByteArray RealWorld -> IO Word16
peekIcmpHeaderSequenceNumber ptr = do
  (\hsc_arr -> readByteArray hsc_arr 3) ptr
{-# LINE 70 "src/Network/Icmp/Marshal.hsc" #-}

peekIcmpHeaderPayload :: MutableByteArray RealWorld -> IO Word32
peekIcmpHeaderPayload ptr = do
  readByteArray ptr 2
{-# LINE 74 "src/Network/Icmp/Marshal.hsc" #-}