hpaste

recent | annotate | new

import Control.Monad.State
import Control.Concurrent
import System.Environment
import System.Process
import qualified Network.Pcap as PCap
import Text.Printf
import System.IO
import Data.List
import Data.Char
import Foreign

data PacketFmt = PacketFmt {
                   ascii       :: String,
                   hexadecimal :: [Word8]
                 }
 deriving (Eq,Show)

initPktFmt a h =
  PacketFmt {
    ascii       = a,
    hexadecimal = h
}


formatData :: PacketFmt -> IO ()
formatData pf = do
  let (x,x') = splitAt 10 a
      (y,y') = splitAt 10 h
  unless (x' == [] && y' == []) $ do
    mapM_ (printf "%02.2x ") (fmtHex y)
    printf "\t\t%s\n" x
    formatData (initPktFmt x' y')
  return ()
 where
  a = ascii pf
  h = hexadecimal pf
  fmtHex :: [Word8] -> [Int]
  fmtHex bytes = [ (read $ show y) | y <- bytes] :: [Int]

captcha :: PCap.PktHdr -> Ptr Word8 -> IO ()
captcha pkth datap = do
  a  <- peekArray (fromIntegral (PCap.caplen pkth)) datap
  s  <- return $ map (\x -> if (x >= 32 && x <= 126) then x else 46) a
  s' <- return $ map (\x -> chr (read $ show x)) s
  formatData (initPktFmt s' a)
  printf "\n"
  hFlush stdout

main = do
  a      <- getArgs
  devs   <- PCap.findAllDevs
  let x   = map (\i -> (PCap.ifName i)) devs
  net    <- PCap.lookupNet (x !! 0)
  spy    <- PCap.openLive (x !! 0) 512 True 100000

  withForeignPtr spy $ \ptr -> do
    -- set our filter, it must happen in this context as spy is
    -- a ForeignPtr, rather than a Ptr like we need for
    -- setFilter/loop
    if a == [] then return () else PCap.setFilter ptr (head a) False (PCap.netMask net)
    -- loop and capture
    PCap.loop ptr 5 captcha
    --print statistics
    s <- PCap.statistics ptr
    putStrLn ("Packets recieved: " ++ (show $ PCap.recv s))
    putStrLn ("Packets dropped: " ++ (show $ PCap.drop s))
    putStrLn ("Packets dropped by interface: " ++ (show $ PCap.ifdrop s))
  return ()