{-# LINE 1 "Network/Socket/Linux/Types.hsc" #-}
{-# LANGUAGE PatternSynonyms #-}



module Network.Socket.Linux.Types (
    -- * sockaddr_ll type
    SockAddrLl
    , sllPktType
    , physicalAddress
    , mkBindSockAddrLl
    , mkSendSockAddrLl
    , IfIndex
    , PhysicalAddress
    , PhysicalAddressBytes
    , addressLength
    , address
    , mkPhysicalAddress
    , macAddress

    -- * ProtocolId
    , ProtocolId(GeneralProtocolId, UnsupportedProtocolId
                ,ETH_P_LOOP,ETH_P_PUP,ETH_P_PUPAT,ETH_P_IP,ETH_P_X25,ETH_P_ARP
                ,ETH_P_BPQ,ETH_P_IEEEPUP,ETH_P_IEEEPUPAT,ETH_P_DEC,ETH_P_DNA_DL
                ,ETH_P_DNA_RC,ETH_P_DNA_RT,ETH_P_LAT,ETH_P_DIAG,ETH_P_CUST
                ,ETH_P_SCA,ETH_P_TEB,ETH_P_RARP,ETH_P_ATALK,ETH_P_AARP
                ,ETH_P_8021Q,ETH_P_IPX,ETH_P_IPV6,ETH_P_PAUSE,ETH_P_SLOW
                ,ETH_P_WCCP,ETH_P_PPP_DISC,ETH_P_PPP_SES,ETH_P_MPLS_UC
                ,ETH_P_MPLS_MC,ETH_P_ATMMPOA,ETH_P_ATMFATE,ETH_P_PAE,ETH_P_AOE
                ,ETH_P_TIPC,ETH_P_1588,ETH_P_FCOE,ETH_P_FIP,ETH_P_EDSA
                ,ETH_P_802_3,ETH_P_AX25,ETH_P_ALL,ETH_P_802_2,ETH_P_SNAP
                ,ETH_P_DDCMP,ETH_P_WAN_PPP,ETH_P_PPP_MP,ETH_P_LOCALTALK
                ,ETH_P_CAN,ETH_P_PPPTALK,ETH_P_TR_802_2,ETH_P_MOBITEX
                ,ETH_P_CONTROL,ETH_P_IRDA,ETH_P_ECONET,ETH_P_HDLC,ETH_P_ARCNET
                ,ETH_P_DSA,ETH_P_TRAILER,ETH_P_PHONET,ETH_P_IEEE802154)
    , isSupportedProtocolId
    , toProtocolNumber

    -- * PacketType
    , PacketType(GeneralPacketType, UnsupportedPacketType
                ,PACKET_HOST,PACKET_BROADCAST,PACKET_MULTICAST,PACKET_OTHERHOST
                ,PACKET_OUTGOING)
    , isSupportedPacketType
    ) where

import Data.Word
import Foreign.Ptr
import Foreign.C.Types
import Foreign.Storable
import Network.Socket.ReadShow
import Network.Socket (Family, packFamily, unpackFamily, ProtocolNumber)
import Network.Socket.Address (SocketAddress, peekSocketAddress, pokeSocketAddress, sizeOfSocketAddress)
import Text.Read (readPrec)

foreign import ccall unsafe "ntohs" ntohs :: Word16 -> Word16
foreign import ccall unsafe "htons" htons :: Word16 -> Word16
foreign import ccall unsafe "string.h" memset :: Ptr a -> CInt -> CSize -> IO ()

------------------------------------------------------------------------
-- | Ethernet Protocol IDs.
--
-- These are IEEE 802.3 protocol numbers (as defined in @\<linux/if_ether.h>@),
-- for use in 'SockAddrLl' addresses when working with packet sockets.
--
-- Some of the defined patterns may be unsupported on some systems:
-- see 'isSupportedProtocolId'.
newtype ProtocolId = ProtocolId { packProtocolId :: CUShort } deriving (Eq, Ord)

-- | Does one of the @ETH_@ constants correspond to a known Ethernet protocol id
-- on this system?
--
-- Just like for 'Network.Socket.isSupportedFamily', 'GeneralProtocolId' values
-- not equal to any of the named @ETH_xxxxx@ patterns or 'UnsupportedProtocolId' 
-- will return 'True' even when not known on this system.
isSupportedProtocolId :: ProtocolId -> Bool
isSupportedProtocolId f = case f of
    UnsupportedProtocolId -> False
    GeneralProtocolId _   -> True

pattern GeneralProtocolId  :: CUShort -> ProtocolId
pattern GeneralProtocolId n = ProtocolId n

{-# LINE 82 "Network/Socket/Linux/Types.hsc" #-}
{-# COMPLETE GeneralProtocolId #-}

{-# LINE 84 "Network/Socket/Linux/Types.hsc" #-}

-- | Convert 'CUShort' to 'ProtocolId'.
unpackProtocolId :: CUShort -> ProtocolId
unpackProtocolId = ProtocolId
{-# INLINE unpackProtocolId #-}

-- | Convert 'ProtocolId' to network byte order, for use with
-- 'Network.Socket.socket'
toProtocolNumber :: ProtocolId -> ProtocolNumber
toProtocolNumber = fromIntegral . htons . fromIntegral . packProtocolId

-- | Unsupported protocol id, equal to any other protocol ids that are not
-- supported on the system.
pattern UnsupportedProtocolId  :: ProtocolId
pattern UnsupportedProtocolId   = ProtocolId (-1)

-- | Ethernet Loopback packet
pattern ETH_P_LOOP             :: ProtocolId

{-# LINE 103 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_LOOP              = ProtocolId (96)
{-# LINE 104 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 107 "Network/Socket/Linux/Types.hsc" #-}

-- | Xerox PUP packet
pattern ETH_P_PUP              :: ProtocolId

{-# LINE 111 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_PUP               = ProtocolId (512)
{-# LINE 112 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 115 "Network/Socket/Linux/Types.hsc" #-}

-- | Xerox PUP Addr Trans packet
pattern ETH_P_PUPAT            :: ProtocolId

{-# LINE 119 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_PUPAT             = ProtocolId (513)
{-# LINE 120 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 123 "Network/Socket/Linux/Types.hsc" #-}

-- | Internet Protocol packet
pattern ETH_P_IP               :: ProtocolId

{-# LINE 127 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_IP                = ProtocolId (2048)
{-# LINE 128 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 131 "Network/Socket/Linux/Types.hsc" #-}

-- | CCITT X.25
pattern ETH_P_X25              :: ProtocolId

{-# LINE 135 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_X25               = ProtocolId (2053)
{-# LINE 136 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 139 "Network/Socket/Linux/Types.hsc" #-}

-- | Address Resolution packet
pattern ETH_P_ARP              :: ProtocolId

{-# LINE 143 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_ARP               = ProtocolId (2054)
{-# LINE 144 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 147 "Network/Socket/Linux/Types.hsc" #-}

-- | G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ]
pattern ETH_P_BPQ              :: ProtocolId

{-# LINE 151 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_BPQ               = ProtocolId (2303)
{-# LINE 152 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 155 "Network/Socket/Linux/Types.hsc" #-}

-- | Xerox IEEE802.3 PUP packet
pattern ETH_P_IEEEPUP          :: ProtocolId

{-# LINE 159 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_IEEEPUP           = ProtocolId (2560)
{-# LINE 160 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 163 "Network/Socket/Linux/Types.hsc" #-}

-- | Xerox IEEE802.3 PUP Addr Trans packet
pattern ETH_P_IEEEPUPAT        :: ProtocolId

{-# LINE 167 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_IEEEPUPAT         = ProtocolId (2561)
{-# LINE 168 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 171 "Network/Socket/Linux/Types.hsc" #-}

-- | DEC Assigned proto
pattern ETH_P_DEC              :: ProtocolId

{-# LINE 175 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_DEC               = ProtocolId (24576)
{-# LINE 176 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 179 "Network/Socket/Linux/Types.hsc" #-}

-- | DEC DNA Dump/Load
pattern ETH_P_DNA_DL           :: ProtocolId

{-# LINE 183 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_DNA_DL            = ProtocolId (24577)
{-# LINE 184 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 187 "Network/Socket/Linux/Types.hsc" #-}

-- | DEC DNA Remote Console
pattern ETH_P_DNA_RC           :: ProtocolId

{-# LINE 191 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_DNA_RC            = ProtocolId (24578)
{-# LINE 192 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 195 "Network/Socket/Linux/Types.hsc" #-}

-- | DEC DNA Routing
pattern ETH_P_DNA_RT           :: ProtocolId

{-# LINE 199 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_DNA_RT            = ProtocolId (24579)
{-# LINE 200 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 203 "Network/Socket/Linux/Types.hsc" #-}

-- | DEC LAT
pattern ETH_P_LAT              :: ProtocolId

{-# LINE 207 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_LAT               = ProtocolId (24580)
{-# LINE 208 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 211 "Network/Socket/Linux/Types.hsc" #-}

-- | DEC Diagnostics
pattern ETH_P_DIAG             :: ProtocolId

{-# LINE 215 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_DIAG              = ProtocolId (24581)
{-# LINE 216 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 219 "Network/Socket/Linux/Types.hsc" #-}

-- | DEC Customer use
pattern ETH_P_CUST             :: ProtocolId

{-# LINE 223 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_CUST              = ProtocolId (24582)
{-# LINE 224 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 227 "Network/Socket/Linux/Types.hsc" #-}

-- | DEC Systems Comms Arch
pattern ETH_P_SCA              :: ProtocolId

{-# LINE 231 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_SCA               = ProtocolId (24583)
{-# LINE 232 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 235 "Network/Socket/Linux/Types.hsc" #-}

-- | Trans Ether Bridging
pattern ETH_P_TEB              :: ProtocolId

{-# LINE 239 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_TEB               = ProtocolId (25944)
{-# LINE 240 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 243 "Network/Socket/Linux/Types.hsc" #-}

-- | Reverse Addr Res packet
pattern ETH_P_RARP             :: ProtocolId

{-# LINE 247 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_RARP              = ProtocolId (32821)
{-# LINE 248 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 251 "Network/Socket/Linux/Types.hsc" #-}

-- | Appletalk DDP
pattern ETH_P_ATALK            :: ProtocolId

{-# LINE 255 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_ATALK             = ProtocolId (32923)
{-# LINE 256 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 259 "Network/Socket/Linux/Types.hsc" #-}

-- | Appletalk AARP
pattern ETH_P_AARP             :: ProtocolId

{-# LINE 263 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_AARP              = ProtocolId (33011)
{-# LINE 264 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 267 "Network/Socket/Linux/Types.hsc" #-}

-- | 802\.1Q VLAN Extended Header
pattern ETH_P_8021Q            :: ProtocolId

{-# LINE 271 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_8021Q             = ProtocolId (33024)
{-# LINE 272 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 275 "Network/Socket/Linux/Types.hsc" #-}

-- | IPX over DIX
pattern ETH_P_IPX              :: ProtocolId

{-# LINE 279 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_IPX               = ProtocolId (33079)
{-# LINE 280 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 283 "Network/Socket/Linux/Types.hsc" #-}

-- | IPv6 over bluebook
pattern ETH_P_IPV6             :: ProtocolId

{-# LINE 287 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_IPV6              = ProtocolId (34525)
{-# LINE 288 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 291 "Network/Socket/Linux/Types.hsc" #-}

-- | IEEE Pause frames. See 802.3 31B
pattern ETH_P_PAUSE            :: ProtocolId

{-# LINE 295 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_PAUSE             = ProtocolId (34824)
{-# LINE 296 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 299 "Network/Socket/Linux/Types.hsc" #-}

-- | Slow Protocol. See 802.3ad 43B
pattern ETH_P_SLOW             :: ProtocolId

{-# LINE 303 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_SLOW              = ProtocolId (34825)
{-# LINE 304 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 307 "Network/Socket/Linux/Types.hsc" #-}

-- | Web-cache coordination protocol
pattern ETH_P_WCCP             :: ProtocolId

{-# LINE 311 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_WCCP              = ProtocolId (34878)
{-# LINE 312 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 315 "Network/Socket/Linux/Types.hsc" #-}

-- | PPPoE discovery messages
pattern ETH_P_PPP_DISC         :: ProtocolId

{-# LINE 319 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_PPP_DISC          = ProtocolId (34915)
{-# LINE 320 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 323 "Network/Socket/Linux/Types.hsc" #-}

-- | PPPoE session messages
pattern ETH_P_PPP_SES          :: ProtocolId

{-# LINE 327 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_PPP_SES           = ProtocolId (34916)
{-# LINE 328 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 331 "Network/Socket/Linux/Types.hsc" #-}

-- | MPLS Unicast traffic
pattern ETH_P_MPLS_UC          :: ProtocolId

{-# LINE 335 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_MPLS_UC           = ProtocolId (34887)
{-# LINE 336 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 339 "Network/Socket/Linux/Types.hsc" #-}

-- | MPLS Multicast traffic
pattern ETH_P_MPLS_MC          :: ProtocolId

{-# LINE 343 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_MPLS_MC           = ProtocolId (34888)
{-# LINE 344 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 347 "Network/Socket/Linux/Types.hsc" #-}

-- | MultiProtocol Over ATM
pattern ETH_P_ATMMPOA          :: ProtocolId

{-# LINE 351 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_ATMMPOA           = ProtocolId (34892)
{-# LINE 352 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 355 "Network/Socket/Linux/Types.hsc" #-}

-- | Frame-based ATM Transport
pattern ETH_P_ATMFATE          :: ProtocolId

{-# LINE 359 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_ATMFATE           = ProtocolId (34948)
{-# LINE 360 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 363 "Network/Socket/Linux/Types.hsc" #-}

-- | Port Access Entity (IEEE 802.1X)
pattern ETH_P_PAE              :: ProtocolId

{-# LINE 367 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_PAE               = ProtocolId (34958)
{-# LINE 368 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 371 "Network/Socket/Linux/Types.hsc" #-}

-- | ATA over Ethernet
pattern ETH_P_AOE              :: ProtocolId

{-# LINE 375 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_AOE               = ProtocolId (34978)
{-# LINE 376 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 379 "Network/Socket/Linux/Types.hsc" #-}

-- | TIPC
pattern ETH_P_TIPC             :: ProtocolId

{-# LINE 383 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_TIPC              = ProtocolId (35018)
{-# LINE 384 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 387 "Network/Socket/Linux/Types.hsc" #-}

-- | IEEE 1588 Timesync
pattern ETH_P_1588             :: ProtocolId

{-# LINE 391 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_1588              = ProtocolId (35063)
{-# LINE 392 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 395 "Network/Socket/Linux/Types.hsc" #-}

-- | Fibre Channel over Ethernet
pattern ETH_P_FCOE             :: ProtocolId

{-# LINE 399 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_FCOE              = ProtocolId (35078)
{-# LINE 400 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 403 "Network/Socket/Linux/Types.hsc" #-}

-- | FCoE Initialization Protocol
pattern ETH_P_FIP              :: ProtocolId

{-# LINE 407 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_FIP               = ProtocolId (35092)
{-# LINE 408 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 411 "Network/Socket/Linux/Types.hsc" #-}

-- | Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ]
pattern ETH_P_EDSA             :: ProtocolId

{-# LINE 415 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_EDSA              = ProtocolId (56026)
{-# LINE 416 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 419 "Network/Socket/Linux/Types.hsc" #-}

-- | Dummy type for 802.3 frames
pattern ETH_P_802_3            :: ProtocolId

{-# LINE 423 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_802_3             = ProtocolId (1)
{-# LINE 424 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 427 "Network/Socket/Linux/Types.hsc" #-}

-- | Dummy protocol id for AX\.25
pattern ETH_P_AX25             :: ProtocolId

{-# LINE 431 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_AX25              = ProtocolId (2)
{-# LINE 432 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 435 "Network/Socket/Linux/Types.hsc" #-}

-- | Every packet (be careful!!!)
pattern ETH_P_ALL              :: ProtocolId

{-# LINE 439 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_ALL               = ProtocolId (3)
{-# LINE 440 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 443 "Network/Socket/Linux/Types.hsc" #-}

-- | 802\.2 frames
pattern ETH_P_802_2            :: ProtocolId

{-# LINE 447 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_802_2             = ProtocolId (4)
{-# LINE 448 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 451 "Network/Socket/Linux/Types.hsc" #-}

-- | Internal only
pattern ETH_P_SNAP             :: ProtocolId

{-# LINE 455 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_SNAP              = ProtocolId (5)
{-# LINE 456 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 459 "Network/Socket/Linux/Types.hsc" #-}

-- | DEC DDCMP: Internal only
pattern ETH_P_DDCMP            :: ProtocolId

{-# LINE 463 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_DDCMP             = ProtocolId (6)
{-# LINE 464 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 467 "Network/Socket/Linux/Types.hsc" #-}

-- | Dummy type for WAN PPP frames
pattern ETH_P_WAN_PPP          :: ProtocolId

{-# LINE 471 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_WAN_PPP           = ProtocolId (7)
{-# LINE 472 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 475 "Network/Socket/Linux/Types.hsc" #-}

-- | Dummy type for PPP MP frames
pattern ETH_P_PPP_MP           :: ProtocolId

{-# LINE 479 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_PPP_MP            = ProtocolId (8)
{-# LINE 480 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 483 "Network/Socket/Linux/Types.hsc" #-}

-- | Localtalk pseudo type
pattern ETH_P_LOCALTALK        :: ProtocolId

{-# LINE 487 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_LOCALTALK         = ProtocolId (9)
{-# LINE 488 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 491 "Network/Socket/Linux/Types.hsc" #-}

-- | Controller Area Network
pattern ETH_P_CAN              :: ProtocolId

{-# LINE 495 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_CAN               = ProtocolId (12)
{-# LINE 496 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 499 "Network/Socket/Linux/Types.hsc" #-}

-- | Dummy type for Atalk over PPP
pattern ETH_P_PPPTALK          :: ProtocolId

{-# LINE 503 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_PPPTALK           = ProtocolId (16)
{-# LINE 504 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 507 "Network/Socket/Linux/Types.hsc" #-}

-- | 802\.2 frames
pattern ETH_P_TR_802_2         :: ProtocolId

{-# LINE 511 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_TR_802_2          = ProtocolId (17)
{-# LINE 512 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 515 "Network/Socket/Linux/Types.hsc" #-}

-- | Mobitex (kaz@cafe.net)
pattern ETH_P_MOBITEX          :: ProtocolId

{-# LINE 519 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_MOBITEX           = ProtocolId (21)
{-# LINE 520 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 523 "Network/Socket/Linux/Types.hsc" #-}

-- | Card specific control frames
pattern ETH_P_CONTROL          :: ProtocolId

{-# LINE 527 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_CONTROL           = ProtocolId (22)
{-# LINE 528 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 531 "Network/Socket/Linux/Types.hsc" #-}

-- | Linux-IrDA
pattern ETH_P_IRDA             :: ProtocolId

{-# LINE 535 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_IRDA              = ProtocolId (23)
{-# LINE 536 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 539 "Network/Socket/Linux/Types.hsc" #-}

-- | Acorn Econet
pattern ETH_P_ECONET           :: ProtocolId

{-# LINE 543 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_ECONET            = ProtocolId (24)
{-# LINE 544 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 547 "Network/Socket/Linux/Types.hsc" #-}

-- | HDLC frames
pattern ETH_P_HDLC             :: ProtocolId

{-# LINE 551 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_HDLC              = ProtocolId (25)
{-# LINE 552 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 555 "Network/Socket/Linux/Types.hsc" #-}

-- | 1A for ArcNet :-)
pattern ETH_P_ARCNET           :: ProtocolId

{-# LINE 559 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_ARCNET            = ProtocolId (26)
{-# LINE 560 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 563 "Network/Socket/Linux/Types.hsc" #-}

-- | Distributed Switch Arch.
pattern ETH_P_DSA              :: ProtocolId

{-# LINE 567 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_DSA               = ProtocolId (27)
{-# LINE 568 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 571 "Network/Socket/Linux/Types.hsc" #-}

-- | Trailer switch tagging
pattern ETH_P_TRAILER          :: ProtocolId

{-# LINE 575 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_TRAILER           = ProtocolId (28)
{-# LINE 576 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 579 "Network/Socket/Linux/Types.hsc" #-}

-- | Nokia Phonet frames
pattern ETH_P_PHONET           :: ProtocolId

{-# LINE 583 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_PHONET            = ProtocolId (245)
{-# LINE 584 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 587 "Network/Socket/Linux/Types.hsc" #-}

-- | IEEE802.15.4 frame
pattern ETH_P_IEEE802154       :: ProtocolId

{-# LINE 591 "Network/Socket/Linux/Types.hsc" #-}
pattern ETH_P_IEEE802154        = ProtocolId (246)
{-# LINE 592 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 595 "Network/Socket/Linux/Types.hsc" #-}

------------------------------------------------------------------------
-- | Packet Types.
--
-- Linux packet types as defined in @\<linux/if_packet.h>@, for use in
-- SockAddrLl addresses when working with packet sockets.
--
-- Some of the defined patterns may be unsupported on some systems:
-- see 'isSupportedPacketType'.
newtype PacketType = PacketType { packPacketType :: CUChar } deriving (Eq, Ord)

-- | Does one of the @PACKET_@ constants correspond to a known packet type
-- on this system?
--
-- Like for 'Network.Socket.isSupportedFamily', 'GeneralPacketType' values
-- not equal to any of the named @PACKET_@ patterns or 'UnsupportedPacketType'
-- will return 'True' even when not known on this system.
isSupportedPacketType :: PacketType -> Bool
isSupportedPacketType f = case f of
    UnsupportedPacketType -> False
    GeneralPacketType _   -> True

pattern GeneralPacketType :: CUChar -> PacketType
pattern GeneralPacketType n = PacketType n

{-# LINE 620 "Network/Socket/Linux/Types.hsc" #-}
{-# COMPLETE GeneralPacketType #-}

{-# LINE 622 "Network/Socket/Linux/Types.hsc" #-}

-- | Convert 'CUChar' to 'PacketType'.
unpackPacketType :: CUChar -> PacketType
unpackPacketType = PacketType
{-# INLINE unpackPacketType #-}

-- | Unsupported packet id, equal to any other packet ids that are not
-- supported on the system.
pattern UnsupportedPacketType  :: PacketType
pattern UnsupportedPacketType   = PacketType (-1)

-- | To us
pattern PACKET_HOST            :: PacketType

{-# LINE 636 "Network/Socket/Linux/Types.hsc" #-}
pattern PACKET_HOST             = PacketType (0)
{-# LINE 637 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 640 "Network/Socket/Linux/Types.hsc" #-}

-- | To all
pattern PACKET_BROADCAST       :: PacketType

{-# LINE 644 "Network/Socket/Linux/Types.hsc" #-}
pattern PACKET_BROADCAST        = PacketType (1)
{-# LINE 645 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 648 "Network/Socket/Linux/Types.hsc" #-}

-- | To group
pattern PACKET_MULTICAST       :: PacketType

{-# LINE 652 "Network/Socket/Linux/Types.hsc" #-}
pattern PACKET_MULTICAST        = PacketType (2)
{-# LINE 653 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 656 "Network/Socket/Linux/Types.hsc" #-}

-- | To someone else
pattern PACKET_OTHERHOST       :: PacketType

{-# LINE 660 "Network/Socket/Linux/Types.hsc" #-}
pattern PACKET_OTHERHOST        = PacketType (3)
{-# LINE 661 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 664 "Network/Socket/Linux/Types.hsc" #-}

-- | Outgoing of any type
pattern PACKET_OUTGOING        :: PacketType

{-# LINE 668 "Network/Socket/Linux/Types.hsc" #-}
pattern PACKET_OUTGOING         = PacketType (4)
{-# LINE 669 "Network/Socket/Linux/Types.hsc" #-}

{-# LINE 672 "Network/Socket/Linux/Types.hsc" #-}
------------------------------------------------------------------------
-- | A physical address consisting of up to eight bytes.
--
-- This type encapsulates the @sll_halen@ and @sll_addr@ fields of
-- @sockaddr_ll@ (as defined in @\<linux/if_packet.h>@).
data PhysicalAddress = PhysicalAddress { addressLength :: SllHaLen 
                                         -- ^ Get the length of the given 'PhysicalAddress'.
                                       , sllAddr :: SllAddr }
    deriving (Show, Eq)

-- | Up to eight bytes, for use with a 'PhysicalAddress'
type PhysicalAddressBytes = (Word8, Word8, Word8, Word8, Word8, Word8, Word8, Word8)

-- | Get the address bytes for the given 'PhysicalAddress'
address :: PhysicalAddress -> PhysicalAddressBytes
address addr = bytes where
                 (SllAddr bytes) = sllAddr addr

-- | Create a new 'PhysicalAddress' with the given length and bytes.
-- Note that 'addressLength' must be between 0 and 8
mkPhysicalAddress :: Int -> PhysicalAddressBytes -> Maybe PhysicalAddress
mkPhysicalAddress haLen addr
    | haLen >= 0 && haLen <= 8 = Just $ PhysicalAddress { addressLength = fromIntegral haLen
                                                        , sllAddr = SllAddr addr }
    | otherwise = Nothing

-- | Create a new 'PhysicalAddress' to represent the the given MAC address.
macAddress :: (Word8, Word8, Word8, Word8, Word8, Word8) -> PhysicalAddress
macAddress (a,b,c,d,e,f) = PhysicalAddress { addressLength = 6
                                           , sllAddr = SllAddr (a,b,c,d,e,f,0,0) }

emptyAddress :: PhysicalAddress
emptyAddress = PhysicalAddress { addressLength = 0, sllAddr = SllAddr (0,0,0,0,0,0,0,0) }

-- | A type representing the @sockaddr_ll@ struct defined in
-- @\<linux/if_ether.h>@.
--
-- This can be used by functions in "Network.Socket.Address" in order to
-- interact with packet sockets - see
-- [packet (7)](https://man7.org/linux/man-pages/man7/packet.7.html) for
-- details. Note that passing this type to 'Network.Socket.Address.connect' or
-- 'Network.Socket.Address.accept' is an error.
data SockAddrLl = SockAddrLl { sllFamily :: Family
                             , sllProtocol :: ProtocolId
                             , sllIfIndex :: SllIfIndex
                             , sllHaType :: SllHaType
                             , sllPktType :: PacketType -- ^ Get the type of a received packet
                             , physicalAddress :: PhysicalAddress -- ^ Get the 'PhysicalAddress' corresponding to the the @sll_halen@ and @sll_addr@ fields of a @sockaddr_ll@
                             }

-- | The index of a network interface
type IfIndex = Int

-- | Create a SockAddrLl for binding a packet socket to an interface.
mkBindSockAddrLl :: Family -> ProtocolId -> IfIndex -> SockAddrLl
mkBindSockAddrLl family protocol index =
    SockAddrLl { sllFamily = family
               , sllProtocol = protocol
               , sllIfIndex = fromIntegral index
               , sllHaType = 0
               , sllPktType = PacketType 0
               , physicalAddress = emptyAddress }

-- | Create a SockAddrLl for sending data to a specific address.
mkSendSockAddrLl :: Family -> ProtocolId -> IfIndex -> PhysicalAddress -> SockAddrLl
mkSendSockAddrLl family protocol index addr =
    SockAddrLl { sllFamily = family
               , sllProtocol = protocol
               , sllIfIndex = (fromIntegral index)
               , sllHaType = 0
               , sllPktType = (PacketType 0)
               , physicalAddress = addr }

instance SocketAddress SockAddrLl where
    sizeOfSocketAddress = sizeOfSockAddrLl
    peekSocketAddress   = peekSockAddrLl
    pokeSocketAddress   = pokeSockAddrLl

-- Internal representation of the bytes in a SockAddrLl, needed so we can create
-- an instance of Storable
newtype SllAddr = SllAddr (Word8, Word8, Word8, Word8, Word8, Word8, Word8, Word8) deriving (Show, Eq)

instance Storable SllAddr where
    sizeOf    _ = 8
    alignment _ = 0

    peek p = do
        a <- peekByteOff p 0
        b <- peekByteOff p 1
        c <- peekByteOff p 2
        d <- peekByteOff p 3
        e <- peekByteOff p 4
        f <- peekByteOff p 5
        g <- peekByteOff p 6
        h <- peekByteOff p 7
        return $ SllAddr (a, b, c, d, e, f, g, h)

    poke p (SllAddr (a, b, c, d, e, f, g, h)) = do
        pokeByteOff p 0 a
        pokeByteOff p 1 b
        pokeByteOff p 2 c
        pokeByteOff p 3 d
        pokeByteOff p 4 e
        pokeByteOff p 5 f
        pokeByteOff p 6 g
        pokeByteOff p 7 h

type SllIfIndex = CInt
type SllHaType = CUShort
type SllHaLen = CUChar

sizeOfSockAddrLl :: SockAddrLl -> Int
sizeOfSockAddrLl SockAddrLl{}  = 20
{-# LINE 785 "Network/Socket/Linux/Types.hsc" #-}

-- | Write the given 'SockAddrLl' to the given memory location.
pokeSockAddrLl :: Ptr a -> SockAddrLl -> IO ()
pokeSockAddrLl p addr = do
    memset p 0 (20)
{-# LINE 790 "Network/Socket/Linux/Types.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) p (packFamily . sllFamily $ addr)
{-# LINE 791 "Network/Socket/Linux/Types.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 2)) p (htons . fromIntegral . packProtocolId . sllProtocol $ addr)
{-# LINE 792 "Network/Socket/Linux/Types.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 4)) p $ sllIfIndex addr
{-# LINE 793 "Network/Socket/Linux/Types.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) p $ sllHaType addr
{-# LINE 794 "Network/Socket/Linux/Types.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 10)) p (packPacketType . sllPktType $ addr)
{-# LINE 795 "Network/Socket/Linux/Types.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 11)) p $ (addressLength . physicalAddress $ addr)
{-# LINE 796 "Network/Socket/Linux/Types.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 12)) p $ (sllAddr . physicalAddress $ addr)
{-# LINE 797 "Network/Socket/Linux/Types.hsc" #-}

-- | Read a 'SockAddrLl' from the given memory location
peekSockAddrLl:: Ptr SockAddrLl -> IO SockAddrLl
peekSockAddrLl p = do
    sllFamily <- unpackFamily <$> ((\hsc_ptr -> peekByteOff hsc_ptr 0)) p
{-# LINE 802 "Network/Socket/Linux/Types.hsc" #-}
    sllProtocol <- (unpackProtocolId . fromIntegral . ntohs) <$> ((\hsc_ptr -> peekByteOff hsc_ptr 2)) p
{-# LINE 803 "Network/Socket/Linux/Types.hsc" #-}
    sllIfIndex <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) p
{-# LINE 804 "Network/Socket/Linux/Types.hsc" #-}
    sllHaType <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) p
{-# LINE 805 "Network/Socket/Linux/Types.hsc" #-}
    sllPktType <- unpackPacketType <$> ((\hsc_ptr -> peekByteOff hsc_ptr 10)) p
{-# LINE 806 "Network/Socket/Linux/Types.hsc" #-}
    sllHaLen <- ((\hsc_ptr -> peekByteOff hsc_ptr 11)) p
{-# LINE 807 "Network/Socket/Linux/Types.hsc" #-}
    sllAddr <- ((\hsc_ptr -> peekByteOff hsc_ptr 12)) p
{-# LINE 808 "Network/Socket/Linux/Types.hsc" #-}
    return $ SockAddrLl sllFamily sllProtocol sllIfIndex sllHaType sllPktType (PhysicalAddress sllHaLen sllAddr)

------------------------------------------------------------------------
-- Read and Show instance for pattern-based integral newtypes

protocolIdBijection :: Bijection ProtocolId String
protocolIdBijection =
    [ (UnsupportedProtocolId, "UnsupportedProtocolId")
    , (ETH_P_LOOP, "ETH_P_LOOP")
    , (ETH_P_PUP, "ETH_P_PUP")
    , (ETH_P_PUPAT, "ETH_P_PUPAT")
    , (ETH_P_IP, "ETH_P_IP")
    , (ETH_P_X25, "ETH_P_X25")
    , (ETH_P_ARP, "ETH_P_ARP")
    , (ETH_P_BPQ, "ETH_P_BPQ")
    , (ETH_P_IEEEPUP, "ETH_P_IEEEPUP")
    , (ETH_P_IEEEPUPAT, "ETH_P_IEEEPUPAT")
    , (ETH_P_DEC, "ETH_P_DEC")
    , (ETH_P_DNA_DL, "ETH_P_DNA_DL")
    , (ETH_P_DNA_RC, "ETH_P_DNA_RC")
    , (ETH_P_DNA_RT, "ETH_P_DNA_RT")
    , (ETH_P_LAT, "ETH_P_LAT")
    , (ETH_P_DIAG, "ETH_P_DIAG")
    , (ETH_P_CUST, "ETH_P_CUST")
    , (ETH_P_SCA, "ETH_P_SCA")
    , (ETH_P_TEB, "ETH_P_TEB")
    , (ETH_P_RARP, "ETH_P_RARP")
    , (ETH_P_ATALK, "ETH_P_ATALK")
    , (ETH_P_AARP, "ETH_P_AARP")
    , (ETH_P_8021Q, "ETH_P_8021Q")
    , (ETH_P_IPX, "ETH_P_IPX")
    , (ETH_P_IPV6, "ETH_P_IPV6")
    , (ETH_P_PAUSE, "ETH_P_PAUSE")
    , (ETH_P_SLOW, "ETH_P_SLOW")
    , (ETH_P_WCCP, "ETH_P_WCCP")
    , (ETH_P_PPP_DISC, "ETH_P_PPP_DISC")
    , (ETH_P_PPP_SES, "ETH_P_PPP_SES")
    , (ETH_P_MPLS_UC, "ETH_P_MPLS_UC")
    , (ETH_P_MPLS_MC, "ETH_P_MPLS_MC")
    , (ETH_P_ATMMPOA, "ETH_P_ATMMPOA")
    , (ETH_P_ATMFATE, "ETH_P_ATMFATE")
    , (ETH_P_PAE, "ETH_P_PAE")
    , (ETH_P_AOE, "ETH_P_AOE")
    , (ETH_P_TIPC, "ETH_P_TIPC")
    , (ETH_P_1588, "ETH_P_1588")
    , (ETH_P_FCOE, "ETH_P_FCOE")
    , (ETH_P_FIP, "ETH_P_FIP")
    , (ETH_P_EDSA, "ETH_P_EDSA")
    , (ETH_P_802_3, "ETH_P_802_3")
    , (ETH_P_AX25, "ETH_P_AX25")
    , (ETH_P_ALL, "ETH_P_ALL")
    , (ETH_P_802_2, "ETH_P_802_2")
    , (ETH_P_SNAP, "ETH_P_SNAP")
    , (ETH_P_DDCMP, "ETH_P_DDCMP")
    , (ETH_P_WAN_PPP, "ETH_P_WAN_PPP")
    , (ETH_P_PPP_MP, "ETH_P_PPP_MP")
    , (ETH_P_LOCALTALK, "ETH_P_LOCALTALK")
    , (ETH_P_CAN, "ETH_P_CAN")
    , (ETH_P_PPPTALK, "ETH_P_PPPTALK")
    , (ETH_P_TR_802_2, "ETH_P_TR_802_2")
    , (ETH_P_MOBITEX, "ETH_P_MOBITEX")
    , (ETH_P_CONTROL, "ETH_P_CONTROL")
    , (ETH_P_IRDA, "ETH_P_IRDA")
    , (ETH_P_ECONET, "ETH_P_ECONET")
    , (ETH_P_HDLC, "ETH_P_HDLC")
    , (ETH_P_ARCNET, "ETH_P_ARCNET")
    , (ETH_P_DSA, "ETH_P_DSA")
    , (ETH_P_TRAILER, "ETH_P_TRAILER")
    , (ETH_P_PHONET, "ETH_P_PHONET")
    , (ETH_P_IEEE802154, "ETH_P_IEEE802154")]

instance Show ProtocolId where
    showsPrec = bijectiveShow protocolIdBijection def
      where
        gf = "GeneralProtocolId"
        def = defShow gf packProtocolId _showInt

instance Read ProtocolId where
    readPrec = bijectiveRead protocolIdBijection def
      where
        gf = "GeneralProtocolId"
        def = defRead gf unpackProtocolId _readInt

packetTypeBijection :: Bijection PacketType String
packetTypeBijection =
    [ (UnsupportedPacketType, "UnsupportedPacketType")
    , (PACKET_HOST, "PACKET_HOST")
    , (PACKET_BROADCAST, "PACKET_BROADCAST")
    , (PACKET_MULTICAST, "PACKET_MULTICAST")
    , (PACKET_OTHERHOST, "PACKET_OTHERHOST")
    , (PACKET_OUTGOING, "PACKET_OUTGOING")]

instance Show PacketType where
    showsPrec = bijectiveShow packetTypeBijection def
      where
        gf = "GeneralPacketType"
        def = defShow gf packPacketType _showInt

instance Read PacketType where
    readPrec = bijectiveRead packetTypeBijection def
      where
        gf = "GeneralPacketType"
        def = defRead gf unpackPacketType _readInt