    ------------------------------------------------------------------------------
    -- |
    --  Module      : Network.Pcap
    --  Copyright   : Bryan O'Sullivan 2007, Antiope Associates LLC 2004
    --  License     : BSD-style
    --  Maintainer  : bos@serpentine.com
    --  Stability   : experimental
    --  Portability : non-portable
    --
    -- The 'Network.Pcap' module is a high(ish) level binding to all of
    -- the functions in @libpcap@.  See <http://www.tcpdump.org> for more
    -- information.
    --
    -- This module is built on the lower-level 'Network.Pcap.Base' module,
    -- which is slightly more efficient.  Don\'t use 'Network.Pcap.Base'
    -- unless profiling data indicates that you need to.
    --
    -- Only a minimum of marshaling is done on received packets.  To
    -- convert captured packet data to a 'B.ByteString' (space efficient,
    -- and with /O(1)/ access to every byte in a captured packet), use
    -- 'toBS'.
    --
    -- Note that the 'SockAddr' exported here is not the @SockAddr@ from
    -- 'Network.Socket'. The @SockAddr@ from 'Network.Socket' corresponds
    -- to @struct sockaddr_in@ in BSD terminology. The 'SockAddr' record
    -- here is BSD's @struct sockaddr@. See W.R.Stevens, TCP Illustrated,
    -- volume 2, for further elucidation.
    --
    -- This binding should be portable across systems that can use the
    -- @libpcap@ from @tcpdump.org@. It does not yet work with Winpcap, a
    -- similar library for Windows, although adapting it should not prove
    -- difficult.
    --
    ------------------------------------------------------------------------------

    module Network.Pcap
        (
          -- * Types
          PcapHandle
        , DumpHandle
        , BpfProgram
        , Callback
        , CallbackBS
        , Direction(..)
        , Link(..)
        , Interface(..)
        , PcapAddr(..)
        , SockAddr(..)
        , Network(..)
        , PktHdr(..)
        , Statistics(..)

        -- * Device opening
        , openOffline               -- :: FilePath -> IO Pcap
        , openLive                  -- :: String -> Int -> Bool -> Int -> IO Pcap
        , openDead                  -- :: Int -> Int -> IO Pcap
        , openDump                  -- :: PcapHandle -> FilePath -> IO Pdump

        -- * Filter handling
        , setFilter                 -- :: PcapHandle -> String -> Bool -> Word32 -> IO ()
        , compileFilter             -- :: Int -> Int -> String -> Bool -> Word32 -> IO BpfProgram

        -- * Device utilities
        , lookupDev                 -- :: IO String
        , findAllDevs               -- :: IO [Interface]
        , lookupNet                 -- :: String -> IO Network

        -- * Interface control

        , setNonBlock               -- :: PcapHandle -> Bool -> IO ()
        , getNonBlock               -- :: PcapHandle -> IO Bool
        , setDirection

        -- * Link layer utilities
        , datalink                  -- :: PcapHandle -> IO Link
        , setDatalink               -- :: PcapHandle -> Link -> IO ()
        , listDatalinks             -- :: PcapHandle -> IO [Link]

        -- * Packet processing
        , dispatch                  -- :: PcapHandle -> Int -> Callback -> IO Int
        , loop                      -- :: PcapHandle -> Int -> Callback -> IO Int
        , next                      -- :: PcapHandle -> IO (PktHdr, Ptr Word8)
        , dump                      -- :: Ptr PcapDumpTag -> Ptr PktHdr -> Ptr Word8 -> IO ()

        -- ** 'B.ByteString' variants
        , dispatchBS                -- :: PcapHandle -> Int -> CallbackBS -> IO Int
        , loopBS                    -- :: PcapHandle -> Int -> CallbackBS -> IO Int
        , nextBS                    -- :: PcapHandle -> IO (PktHdr, B.ByteStringa)
        , dumpBS                    -- :: Ptr PcapDumpTag -> Ptr PktHdr -> B.ByteString -> IO ()

        -- * Sending packets
        , sendPacket
        , sendPacketBS

        -- * Conversion
        , toBS
        , hdrTime
        , hdrDiffTime

        -- * Miscellaneous
        , statistics                -- :: PcapHandle -> IO Statistics
        , version                   -- :: PcapHandle -> IO (Int, Int)
        , isSwapped                 -- :: PcapHandle -> IO Bool
        , snapshotLen               -- :: PcapHandle -> IO Int
        ) where

    #ifdef BYTESTRING_IN_BASE
    import qualified Data.ByteString.Base as B
    import qualified Data.ByteString.Base as BU
    #else
    import qualified Data.ByteString.Internal as B
    import qualified Data.ByteString.Unsafe as BU
    #endif
    import Data.Int (Int64)
    import Data.Time.Clock (DiffTime, picosecondsToDiffTime)
    import Data.Word (Word8, Word32)
    import Foreign.Ptr (Ptr, castPtr)
    import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)
    import qualified Network.Pcap.Base as P
    import Network.Pcap.Base (BpfProgram, Callback, Interface(..), Link(..),
                              Network(..), Direction(..),
                              PcapAddr(..), PktHdr(..), SockAddr(..), Statistics,
                              compileFilter, findAllDevs, lookupDev, lookupNet)

    -- | Packet capture handle.
    newtype PcapHandle = PcapHandle (ForeignPtr P.PcapTag)

    -- | Dump file handle.
    newtype DumpHandle = DumpHandle (ForeignPtr P.PcapDumpTag)

    -- | Callback using 'B.ByteString' for packet body.
    type CallbackBS = PktHdr -> B.ByteString -> IO ()

    --
    -- Open a device
    --

    -- | 'openOffline' opens a dump file for reading. The file format is
    -- the same as used by @tcpdump@ and Wireshark. The string @\"-\"@ is
    -- a synonym for @stdin@.
    --
    openOffline :: FilePath -- ^ name of dump file to read
                -> IO PcapHandle
    openOffline :: FilePath -> IO PcapHandle
    openOffline = (ForeignPtr PcapTag -> PcapHandle)
    -> IO (ForeignPtr PcapTag) -> IO PcapHandle
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ForeignPtr PcapTag -> PcapHandle
    PcapHandle (IO (ForeignPtr PcapTag) -> IO PcapHandle)
    -> (FilePath -> IO (ForeignPtr PcapTag))
    -> FilePath
    -> IO PcapHandle
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> IO (ForeignPtr PcapTag)
    P.openOffline

    -- | 'openLive' is used to get a 'PcapHandle' that can be used to look
    -- at packets on the network. The arguments are the device name, the
    -- snapshot length (in bytes), the promiscuity of the interface
    -- ('True' == promiscuous) and a timeout in microseconds.
    --
    -- The timeout allows the packet filter to delay while accumulating
    -- multiple packets, which is more efficient than reading packets one
    -- by one.  A timeout of zero will wait indefinitely for \"enough\"
    -- packets to arrive.
    --
    -- Using @\"any\"@ as the device name will capture packets from all
    -- interfaces.  On some systems, reading from the @\"any\"@ device is
    -- incompatible with setting the interfaces into promiscuous mode. In
    -- that case, only packets whose link layer addresses match those of
    -- the interfaces are captured.
    --
    openLive :: String              -- ^ device name
             -> Int                 -- ^ snapshot length
             -> Bool                -- ^ set interface to promiscuous mode?
             -> Int64               -- ^ timeout in microseconds
             -> IO PcapHandle
    openLive :: FilePath -> Int -> Bool -> Int64 -> IO PcapHandle
    openLive FilePath
    name Int
    snaplen Bool
    promisc Int64
    timeout =
        let timeout' :: Int
    timeout' | Int64
    timeout Int64 -> Int64 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int64
    0 = Int
    0
                     | Bool
    otherwise = Int64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int64
    timeout Int64 -> Int64 -> Int64
    forall a. Integral a => a -> a -> a
    `div` Int64
    1000)
        in ForeignPtr PcapTag -> PcapHandle
    PcapHandle (ForeignPtr PcapTag -> PcapHandle)
    -> IO (ForeignPtr PcapTag) -> IO PcapHandle
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` FilePath -> Int -> Bool -> Int -> IO (ForeignPtr PcapTag)
    P.openLive FilePath
    name Int
    snaplen Bool
    promisc Int
    timeout'

    -- | 'openDead' is used to get a 'PcapHandle' without opening a file
    -- or device. It is typically used to test packet filter compilation
    -- by 'setFilter'. The arguments are the link type and the snapshot
    -- length.
    --
    openDead :: Link                -- ^ datalink type
             -> Int                 -- ^ snapshot length
             -> IO PcapHandle
    openDead :: Link -> Int -> IO PcapHandle
    openDead Link
    link Int
    snaplen = ForeignPtr PcapTag -> PcapHandle
    PcapHandle (ForeignPtr PcapTag -> PcapHandle)
    -> IO (ForeignPtr PcapTag) -> IO PcapHandle
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` Link -> Int -> IO (ForeignPtr PcapTag)
    P.openDead Link
    link Int
    snaplen

    {-# INLINE withPcap #-}
    withPcap :: PcapHandle -> (Ptr P.PcapTag -> IO a) -> IO a
    withPcap :: forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap (PcapHandle ForeignPtr PcapTag
    hdl) = ForeignPtr PcapTag -> (Ptr PcapTag -> IO a) -> IO a
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr PcapTag
    hdl

    {-# INLINE withDump #-}
    withDump :: DumpHandle -> (Ptr P.PcapDumpTag -> IO a) -> IO a
    withDump :: forall a. DumpHandle -> (Ptr PcapDumpTag -> IO a) -> IO a
    withDump (DumpHandle ForeignPtr PcapDumpTag
    hdl) = ForeignPtr PcapDumpTag -> (Ptr PcapDumpTag -> IO a) -> IO a
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr PcapDumpTag
    hdl

    --
    -- Open a dump device
    --

    -- | 'openDump' opens a dump file for writing. This dump file is
    -- written to by the 'dump' function.
    openDump :: PcapHandle          -- ^ packet capture handle
             -> FilePath            -- ^ name of dump file to write to
             -> IO DumpHandle
    openDump :: PcapHandle -> FilePath -> IO DumpHandle
    openDump PcapHandle
    pch FilePath
    name = PcapHandle -> (Ptr PcapTag -> IO DumpHandle) -> IO DumpHandle
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO DumpHandle) -> IO DumpHandle)
    -> (Ptr PcapTag -> IO DumpHandle) -> IO DumpHandle
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl ->
        ForeignPtr PcapDumpTag -> DumpHandle
    DumpHandle (ForeignPtr PcapDumpTag -> DumpHandle)
    -> IO (ForeignPtr PcapDumpTag) -> IO DumpHandle
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` Ptr PcapTag -> FilePath -> IO (ForeignPtr PcapDumpTag)
    P.openDump Ptr PcapTag
    hdl FilePath
    name

    --
    -- Set the filter
    --

    -- | Set a filter on the specified packet capture handle. Valid filter
    -- strings are those accepted by @tcpdump@.
    setFilter :: PcapHandle         -- ^ handle on which to set filter
              -> String             -- ^ filter string
              -> Bool               -- ^ optimize?
              -> Word32             -- ^ IPv4 network mask
              -> IO ()
    setFilter :: PcapHandle -> FilePath -> Bool -> Word32 -> IO ()
    setFilter PcapHandle
    pch FilePath
    filt Bool
    opt Word32
    mask = PcapHandle -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO ()) -> IO ())
    -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl ->
        Ptr PcapTag -> FilePath -> Bool -> Word32 -> IO ()
    P.setFilter Ptr PcapTag
    hdl FilePath
    filt Bool
    opt Word32
    mask

    --
    -- Set or read the device mode (blocking/nonblocking)
    --

    -- | Set the given 'PcapHandle' into non-blocking mode if the second
    -- argument is 'True', otherwise put it in blocking mode. Note that
    -- the 'PcapHandle' must have been obtained from 'openLive'.
    --
    setNonBlock :: PcapHandle       -- ^ must have been obtained from 'openLive'
                -> Bool             -- ^ set\/unset blocking mode
                -> IO ()
    setNonBlock :: PcapHandle -> Bool -> IO ()
    setNonBlock PcapHandle
    pch Bool
    block = PcapHandle -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO ()) -> IO ())
    -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl -> Ptr PcapTag -> Bool -> IO ()
    P.setNonBlock Ptr PcapTag
    hdl Bool
    block

    -- | Return the blocking status of the 'PcapHandle'. 'True' indicates
    -- that the handle is non-blocking. Handles referring to dump files
    -- opened by 'openDump' always return 'False'.
    getNonBlock :: PcapHandle -> IO Bool
    getNonBlock :: PcapHandle -> IO Bool
    getNonBlock PcapHandle
    pch = PcapHandle -> (Ptr PcapTag -> IO Bool) -> IO Bool
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch Ptr PcapTag -> IO Bool
    P.getNonBlock

    -- | Specify the direction in which packets are to be captured.
    -- Complete functionality is not necessarily available on all
    -- platforms.
    setDirection :: PcapHandle -> Direction -> IO ()
    setDirection :: PcapHandle -> Direction -> IO ()
    setDirection PcapHandle
    pch Direction
    dir = PcapHandle -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO ()) -> IO ())
    -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl -> Ptr PcapTag -> Direction -> IO ()
    P.setDirection Ptr PcapTag
    hdl Direction
    dir

    {-# INLINE hdrTime #-}
    -- | Get the timestamp of a packet as a single quantity, in
    -- microseconds.
    hdrTime :: PktHdr -> Int64
    hdrTime :: PktHdr -> Int64
    hdrTime PktHdr
    pkt = Word32 -> Int64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (PktHdr -> Word32
    hdrSeconds PktHdr
    pkt) Int64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    * Int64
    1000000 Int64 -> Int64 -> Int64
    forall a. Num a => a -> a -> a
    +
                  Word32 -> Int64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (PktHdr -> Word32
    hdrUseconds PktHdr
    pkt)

    -- | Get the timestamp of a packet as a 'DiffTime'.
    hdrDiffTime :: PktHdr -> DiffTime
    hdrDiffTime :: PktHdr -> DiffTime
    hdrDiffTime PktHdr
    pkt = Integer -> DiffTime
    picosecondsToDiffTime (Int64 -> Integer
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (PktHdr -> Int64
    hdrTime PktHdr
    pkt) Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    1000000)

    --
    -- Reading packets
    --

    -- | Wrap a callback that expects a 'B.ByteString' so that it is
    -- usable as a regular 'Callback'.
    wrapBS :: CallbackBS -> Callback
    wrapBS :: CallbackBS -> Callback
    wrapBS CallbackBS
    f PktHdr
    hdr Ptr Word8
    ptr = do
      let len :: Word32
    len = PktHdr -> Word32
    hdrCaptureLength PktHdr
    hdr
      ByteString
    bs <- Int -> (Ptr Word8 -> IO ()) -> IO ByteString
    B.create (Word32 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word32
    len) ((Ptr Word8 -> IO ()) -> IO ByteString)
    -> (Ptr Word8 -> IO ()) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    p -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    B.memcpy Ptr Word8
    p Ptr Word8
    ptr (Word32 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word32
    len)
      CallbackBS
    f PktHdr
    hdr ByteString
    bs

    -- | Collect and process packets.
    --
    -- The count is the maximum number of packets to process before
    -- returning.  A count of -1 means process all of the packets received
    -- in one buffer (if a live capture) or all of the packets in a dump
    -- file (if offline).
    --
    -- The callback function is passed two arguments, a packet header
    -- record and a pointer to the packet data (@Ptr Word8@). THe header
    -- record contains the number of bytes captured, which can be used to
    -- marshal the data into a list, array, or 'B.ByteString' (using
    -- 'toBS').
    --
    dispatch :: PcapHandle
             -> Int                 -- ^ number of packets to process
             -> Callback            -- ^ packet processing function
             -> IO Int              -- ^ number of packets read
    dispatch :: PcapHandle -> Int -> Callback -> IO Int
    dispatch PcapHandle
    pch Int
    count Callback
    f = PcapHandle -> (Ptr PcapTag -> IO Int) -> IO Int
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO Int) -> IO Int)
    -> (Ptr PcapTag -> IO Int) -> IO Int
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl -> Ptr PcapTag -> Int -> Callback -> IO Int
    P.dispatch Ptr PcapTag
    hdl Int
    count Callback
    f

    -- | Variant of 'dispatch' for use with 'B.ByteString'.
    dispatchBS :: PcapHandle
               -> Int               -- ^ number of packets to process
               -> CallbackBS        -- ^ packet processing function
               -> IO Int            -- ^ number of packets read
    dispatchBS :: PcapHandle -> Int -> CallbackBS -> IO Int
    dispatchBS PcapHandle
    pch Int
    count CallbackBS
    f = PcapHandle -> (Ptr PcapTag -> IO Int) -> IO Int
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO Int) -> IO Int)
    -> (Ptr PcapTag -> IO Int) -> IO Int
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl -> Ptr PcapTag -> Int -> Callback -> IO Int
    P.dispatch Ptr PcapTag
    hdl Int
    count (CallbackBS -> Callback
    wrapBS CallbackBS
    f)

    -- | Similar to 'dispatch', but loop until the number of packets
    -- specified by the second argument are read. A negative value loops
    -- forever.
    --
    -- This function does not return when a live read timeout occurs. Use
    -- 'dispatch' instead if you want to specify a timeout.
    loop :: PcapHandle
         -> Int                     -- ^ number of packets to read (-1 == loop forever)
         -> Callback                -- ^ packet processing function
         -> IO Int                  -- ^ number of packets read
    loop :: PcapHandle -> Int -> Callback -> IO Int
    loop PcapHandle
    pch Int
    count Callback
    f = PcapHandle -> (Ptr PcapTag -> IO Int) -> IO Int
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO Int) -> IO Int)
    -> (Ptr PcapTag -> IO Int) -> IO Int
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl -> Ptr PcapTag -> Int -> Callback -> IO Int
    P.loop Ptr PcapTag
    hdl Int
    count Callback
    f

    -- | Variant of 'loop' for use with 'B.ByteString'.
    loopBS :: PcapHandle
           -> Int                   -- ^ number of packets to read (-1 == loop forever)
           -> CallbackBS            -- ^ packet processing function
           -> IO Int                -- ^ number of packets read
    loopBS :: PcapHandle -> Int -> CallbackBS -> IO Int
    loopBS PcapHandle
    pch Int
    count CallbackBS
    f = PcapHandle -> (Ptr PcapTag -> IO Int) -> IO Int
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO Int) -> IO Int)
    -> (Ptr PcapTag -> IO Int) -> IO Int
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl -> Ptr PcapTag -> Int -> Callback -> IO Int
    P.loop Ptr PcapTag
    hdl Int
    count (CallbackBS -> Callback
    wrapBS CallbackBS
    f)

    -- | Send a raw packet through the network interface.
    sendPacket :: PcapHandle
               -> Ptr Word8         -- ^ packet data (including link-level header)
               -> Int               -- ^ packet size
               -> IO ()
    sendPacket :: PcapHandle -> Ptr Word8 -> Int -> IO ()
    sendPacket PcapHandle
    pch Ptr Word8
    buf Int
    size = PcapHandle -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO ()) -> IO ())
    -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl -> Ptr PcapTag -> Ptr Word8 -> Int -> IO ()
    P.sendPacket Ptr PcapTag
    hdl Ptr Word8
    buf Int
    size

    -- | Variant of 'sendPacket' for use with 'B.ByteString'.
    sendPacketBS :: PcapHandle
                 -> B.ByteString    -- ^ packet data (including link-level header)
                 -> IO ()
    sendPacketBS :: PcapHandle -> ByteString -> IO ()
    sendPacketBS PcapHandle
    pch ByteString
    s = ByteString -> (CStringLen -> IO ()) -> IO ()
    forall a. ByteString -> (CStringLen -> IO a) -> IO a
    BU.unsafeUseAsCStringLen ByteString
    s ((CStringLen -> IO ()) -> IO ()) -> (CStringLen -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \(Ptr CChar
    buf, Int
    len) ->
        PcapHandle -> Ptr Word8 -> Int -> IO ()
    sendPacket PcapHandle
    pch (Ptr CChar -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr CChar
    buf) Int
    len

    -- | Represent a captured packet as a 'B.ByteString'.  Suitable for
    -- use as is with the result of 'next', or use @'curry' 'toBS'@ inside
    -- a 'Callback' with 'dispatch'.
    toBS :: (PktHdr, Ptr Word8) -> IO (PktHdr, B.ByteString)
    toBS :: (PktHdr, Ptr Word8) -> IO (PktHdr, ByteString)
    toBS (PktHdr
    hdr, Ptr Word8
    ptr) = do
        let len :: Word32
    len = PktHdr -> Word32
    hdrCaptureLength PktHdr
    hdr
        ByteString
    s <- Int -> (Ptr Word8 -> IO ()) -> IO ByteString
    B.create (Word32 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word32
    len) ((Ptr Word8 -> IO ()) -> IO ByteString)
    -> (Ptr Word8 -> IO ()) -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    p -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    B.memcpy Ptr Word8
    p Ptr Word8
    ptr (Word32 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word32
    len)
        (PktHdr, ByteString) -> IO (PktHdr, ByteString)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (PktHdr
    hdr, ByteString
    s)

    -- | Read the next packet (equivalent to calling 'dispatch' with a
    -- count of 1).
    next :: PcapHandle -> IO (PktHdr, Ptr Word8)
    next :: PcapHandle -> IO (PktHdr, Ptr Word8)
    next PcapHandle
    pch = PcapHandle
    -> (Ptr PcapTag -> IO (PktHdr, Ptr Word8))
    -> IO (PktHdr, Ptr Word8)
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch Ptr PcapTag -> IO (PktHdr, Ptr Word8)
    P.next

    nextBS :: PcapHandle -> IO (PktHdr, B.ByteString)
    nextBS :: PcapHandle -> IO (PktHdr, ByteString)
    nextBS PcapHandle
    pch = PcapHandle
    -> (Ptr PcapTag -> IO (PktHdr, Ptr Word8))
    -> IO (PktHdr, Ptr Word8)
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch Ptr PcapTag -> IO (PktHdr, Ptr Word8)
    P.next IO (PktHdr, Ptr Word8)
    -> ((PktHdr, Ptr Word8) -> IO (PktHdr, ByteString))
    -> IO (PktHdr, ByteString)
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (PktHdr, Ptr Word8) -> IO (PktHdr, ByteString)
    toBS

    -- | Write the packet data given by the second and third arguments to
    -- a dump file opened by 'openDead'. 'dump' is designed so it can be
    -- easily used as a default callback function by 'dispatch' or 'loop'.
    dump :: DumpHandle
         -> Ptr PktHdr              -- ^ packet header record
         -> Ptr Word8               -- ^ packet data
         -> IO ()
    dump :: DumpHandle -> Ptr PktHdr -> Ptr Word8 -> IO ()
    dump DumpHandle
    dh Ptr PktHdr
    hdr Ptr Word8
    pkt = DumpHandle -> (Ptr PcapDumpTag -> IO ()) -> IO ()
    forall a. DumpHandle -> (Ptr PcapDumpTag -> IO a) -> IO a
    withDump DumpHandle
    dh ((Ptr PcapDumpTag -> IO ()) -> IO ())
    -> (Ptr PcapDumpTag -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapDumpTag
    hdl -> Ptr PcapDumpTag -> Ptr PktHdr -> Ptr Word8 -> IO ()
    P.dump Ptr PcapDumpTag
    hdl Ptr PktHdr
    hdr Ptr Word8
    pkt

    dumpBS :: DumpHandle
           -> Ptr PktHdr            -- ^ packet header record
           -> B.ByteString          -- ^ packet data
           -> IO ()
    dumpBS :: DumpHandle -> Ptr PktHdr -> ByteString -> IO ()
    dumpBS DumpHandle
    dh Ptr PktHdr
    hdr ByteString
    s =
        DumpHandle -> (Ptr PcapDumpTag -> IO ()) -> IO ()
    forall a. DumpHandle -> (Ptr PcapDumpTag -> IO a) -> IO a
    withDump DumpHandle
    dh ((Ptr PcapDumpTag -> IO ()) -> IO ())
    -> (Ptr PcapDumpTag -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapDumpTag
    hdl ->
            ByteString -> (Ptr CChar -> IO ()) -> IO ()
    forall a. ByteString -> (Ptr CChar -> IO a) -> IO a
    BU.unsafeUseAsCString ByteString
    s ((Ptr CChar -> IO ()) -> IO ()) -> (Ptr CChar -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Ptr PcapDumpTag -> Ptr PktHdr -> Ptr Word8 -> IO ()
    P.dump Ptr PcapDumpTag
    hdl Ptr PktHdr
    hdr (Ptr Word8 -> IO ())
    -> (Ptr CChar -> Ptr Word8) -> Ptr CChar -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Ptr CChar -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr

    --
    -- Datalink manipulation
    --

    -- | Returns the datalink type associated with the given handle.
    datalink :: PcapHandle -> IO Link
    datalink :: PcapHandle -> IO Link
    datalink PcapHandle
    pch = PcapHandle -> (Ptr PcapTag -> IO Link) -> IO Link
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch Ptr PcapTag -> IO Link
    P.datalink

    -- | Sets the datalink type for the given handle.
    setDatalink :: PcapHandle -> Link -> IO ()
    setDatalink :: PcapHandle -> Link -> IO ()
    setDatalink PcapHandle
    pch Link
    link = PcapHandle -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch ((Ptr PcapTag -> IO ()) -> IO ())
    -> (Ptr PcapTag -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr PcapTag
    hdl -> Ptr PcapTag -> Link -> IO ()
    P.setDatalink Ptr PcapTag
    hdl Link
    link

    -- | List all the datalink types supported by the given
    -- handle. Entries from the resulting list are valid arguments to
    -- 'setDatalink'.
    listDatalinks :: PcapHandle -> IO [Link]
    listDatalinks :: PcapHandle -> IO [Link]
    listDatalinks PcapHandle
    pch = PcapHandle -> (Ptr PcapTag -> IO [Link]) -> IO [Link]
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch Ptr PcapTag -> IO [Link]
    P.listDatalinks

    -- | Returns the number of packets received, the number of packets
    -- dropped by the packet filter and the number of packets dropped by
    -- the interface (before processing by the packet filter).
    statistics :: PcapHandle -> IO Statistics
    statistics :: PcapHandle -> IO Statistics
    statistics PcapHandle
    pch = PcapHandle -> (Ptr PcapTag -> IO Statistics) -> IO Statistics
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch Ptr PcapTag -> IO Statistics
    P.statistics

    -- | Version of the library.  The returned pair consists of the major
    -- and minor version numbers.
    version :: PcapHandle -> IO (Int, Int)
    version :: PcapHandle -> IO (Int, Int)
    version PcapHandle
    pch = PcapHandle -> (Ptr PcapTag -> IO (Int, Int)) -> IO (Int, Int)
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch Ptr PcapTag -> IO (Int, Int)
    P.version

    -- | 'isSwapped' returns 'True' if the current dump file uses a
    -- different byte order than the one native to the system.
    isSwapped :: PcapHandle -> IO Bool
    isSwapped :: PcapHandle -> IO Bool
    isSwapped PcapHandle
    pch = PcapHandle -> (Ptr PcapTag -> IO Bool) -> IO Bool
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch Ptr PcapTag -> IO Bool
    P.isSwapped

    -- | The snapshot length that was used in the call to 'openLive'.
    snapshotLen :: PcapHandle -> IO Int
    snapshotLen :: PcapHandle -> IO Int
    snapshotLen PcapHandle
    pch = PcapHandle -> (Ptr PcapTag -> IO Int) -> IO Int
    forall a. PcapHandle -> (Ptr PcapTag -> IO a) -> IO a
    withPcap PcapHandle
    pch Ptr PcapTag -> IO Int
    P.snapshotLen