Pcap file decoding in Haskell
I am trying to decode a pcap file and its working fine except couple of things.
import Network.Pcap
import System.IO
import Control.Monad
callfun f = do
( p , q ) <- next f
print $ hdrSeconds p
print $ hdrCaptureLength p
print $ hdrWireLength p
print q
when ( hdrWireLength p /= 0 ) $ callfun f
main = do
f <- openOffline "udp_lite_full_coverage_0.pcap"
callfun f
I want the time return by hdrSeconds p [ time to capture ] in same format as in wireshark [ Date : Month : Year Hour : Min : Sec ] and data return by variable q in Ascii format.Kindly tell me how to do this.
Actually i was trying to parse pcap file to display its content in almost similar manner to wireshark without libpcap library [ purely in haskell by opening the pcap file in binary format and read byte by byte ] but i could not get any further. Could some please put the guide map for this project like what to read , how to approach , any thing which you feel would be helpful .Edit: I started writing this application but there is some thing missing. I read this file http://www.viste.com/Linux/Server/WireShark/libpcapformat.pdf and it say that first 24 bytes are gl开发者_StackOverflow社区obal headers , after that every packet contains pcap local header . What i am trying to do is , first trying to get the bytes of data in each packet by reading the third field incl_len in local header but my code is not behaving as it suppose . My test libcap file.
--http://www.viste.com/Linux/Server/WireShark/libpcapformat.pdf
import Data.List
import qualified Data.ByteString.Lazy as BS
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Monad
import Text.Printf
import Data.Word
import Data.Char
import System.Time
import Numeric
import System.Environment
hexTodec :: BS.ByteString -> Integer
hexTodec lst = read $ "0x" ++ ( concatMap ( \x -> showHex x "" ) $ BS.unpack lst )
parseFile :: BS.ByteString -> Bool -> IO [ BS.ByteString ]
parseFile xs revflag
| BS.null xs = return []
| otherwise = do
let ind =if revflag then hexTodec . BS.reverse . BS.take 4 . BS.drop 8 $ xs
else hexTodec . BS.take 4 . BS.drop 8 $ xs
print ind
let ( x , ys ) = BS.splitAt ( fromIntegral ind ) xs
--BS.putStrLn $ x
tmp <- parseFile ys revflag
return $ x : tmp
main = do
[ file ] <- getArgs
contents <- BS.readFile file
let ( a , rest ) = BS.splitAt 24 contents --strip global header
let revflag = case BS.unpack $ BS.take 4 a of
[ 0xd4 , 0xc3 , 0xb2 , 0xa1 ] -> True
_ -> False
p <- parseFile rest revflag
print $ p !! 0
BS.putStr $ p !! 0
Regards
Mukesh Tiwari
I want the time return by hdrSeconds p [ time to capture ] in same format as in wireshark [ Date : Month : Year Hour : Min : Sec ]
Well you can use the time
package and convert this to a UTCTime
. This makes it trivial to extract month, day, year, etc. Look at the time package's haddock for more.
let epoch = pcapEpochTimeThatYouFindInOnlineDocumentation
diff <- hdrDiffTime p
let date = addUTCTime (realToFrac diff) epoch
From what I can tell the Haskell bindings don't provide the epoch, but once you find that this should be fine. I'd e-mail in a patch to the maintainer to add a converstion directly to UTCTime.
and data return by variable q in Ascii format
Well q is just an intergral and you can get Char
s from Int
s using toEnum
:
print (toEnum (fromIntegral q) :: Char)
As for doing this in pure Haskell, I think you need to step back a bit and learn more about Haskell as a language, perhaps from a tutuorial such as learnyouahaskell. If you are determined to forge ahead then read up on the binary package, which was mentioned on the mailing list as the library of choice for their non-public pcap Haskell library.
You can use the Data.Time
module to convert the UNIX epoch-based time returned by hdrSeconds
to a LocalTime
object that can then be formatted into a string with formatTime
.
import Data.Time.Clock.POSIX
import Data.Time.Format
import Data.Time.LocalTime
import System.Locale
import Data.Word (Word32)
data MockPCap = MockPCap { hdrSeconds :: Word32 }
toPosixTime :: Word32 -> POSIXTime
toPosixTime = fromIntegral
localHdrTime p = do tz <- getCurrentTimeZone
return $ utcToLocalTime tz $ posixSecondsToUTCTime $ toPosixTime $ hdrSeconds p
main = let p = MockPCap 1318464165 {-- Mock a PCap object --}
in do hTime <- localHdrTime p
print $ formatTime defaultTimeLocale "%c" hTime
There's a Haskell library for reading pcap files, which does the work of parsing the file header and packet record headers, so you don't have to do that on your own. You're still on your own parsing the packet data, however.
精彩评论