{-# LANGUAGE PackageImports #-} module Main where import Data.Binary.Get (runGet) import qualified Data.ByteString as BS import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as LZ import qualified Data.ByteString.Lazy.Char8 as L8 import Data.IORef import Data.List import Debug.Trace import Text.Printf import Text.Show.Pretty as PP import "network-house" Net.Packet import qualified "network-house" Net.IPv4 as IP4 import qualified "network-house" Net.IPv6 as IP6 import "network-house" Net.PacketParsing import "network-house" Net.UDP as UDP import "pcap" Network.Pcap import qualified Data.Serialize as S import qualified Network.Socket as HS import Control.Applicative import Crypto.Tox import Network.Tox.DHT.Transport as Tox import Data.BEncode as BE import Data.BEncode.Pretty -- import Data.IKE.Message -- traceM string = trace string $ return () bs2chunk :: BS.ByteString -> UArray Int Word8 bs2chunk bs = listArray (0,subtract 33 $ BS.length bs) $ drop 32 $ BS.unpack bs hex :: BS.ByteString -> String hex = concatMap (printf "%02x") . B.unpack hexlines :: BS.ByteString -> [String] hexlines bs = ss where xs = zip [0..] $ hex bs ls = groupBy (\(n,_) (m,_)-> n `div` 32 == m `div` 32) xs ss = map (map snd) ls parsePacket :: IORef Int -> PktHdr -> BS.ByteString -> IO () parsePacket cnt hdr buf = do print hdr let -- mb :: Maybe (BS.ByteString, Message Encrypted) mb = do udp <- doParse $ toInPack $ bs2chunk buf -- traceM $ "got udp: " ++ show udp -- traceM $ "got udp content: " ++ show (content udp) let plen = Net.Packet.len $ content udp bs <- fmap BS.pack . parseInPacket (bytes plen) $ content udp -- traceM $ "Got bs " ++ show bs let (checksum,blob) = BS.splitAt 2 bs -- extra 2 bytes in pcap capture, i'm assuming its a checksum -- (first4,truncated) = BS.splitAt 4 blob -- -- First 4 bytes being zero is how we distinguish between -- -- ESP and IKEv2 packets on port 4500. -- dta = if destPort udp /= Port 500 && first4==BS.pack [0,0,0,0] -- then truncated -- else blob dta = blob let d = BE.decode {- runGet getMessage $ LZ.fromStrict -} dta saddr = HS.SockAddrInet 0 0 -- TODO -- e = S.decode dta :: Either String (DHTMessage Encrypted8) e = case Tox.parseDHTAddr (dta,saddr) :: Either (DHTMessage Encrypted8,NodeInfo) (BS.ByteString,HS.SockAddr) of Left toxpkt -> Right toxpkt Right _ -> Left "tox parse fail" return $ (udp, bs, fmap Left d <|> fmap Right e) flip (maybe $ return ()) mb $ \(udp, bs,m) -> do putStrLn $ show udp mapM_ putStrLn $ hexlines bs -- putStrLn $ PP.ppShow m either putStrLn (L8.putStrLn . either showBEncode (L8.pack . show)) m modifyIORef' cnt (+1) main = do cnt <- newIORef 0 pcap <- openOffline "packets.pcap" loopResult <- loopBS pcap (-1) $ parsePacket cnt pktcnt <- readIORef cnt putStrLn $ "read "++show pktcnt ++" packets."