Haskell中的Pcap文件解码

时间:2011-10-12 23:25:00

标签: networking haskell libpcap

我正在尝试解码pcap file并且除了几件事以外它的工作正常。

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 

我希望时间以hdrSeconds p [捕获时间]返回,格式与wireshark相同[日期:月份:年份时间:最小值:秒],数据以变量q返回Ascii格式。请告诉我该怎么做这个。
  实际上我试图解析pcap文件以几乎类似于wireshark的方式显示其内容而没有libpcap库[纯粹在haskell中打开二进制格式的pcap文件并逐字节读取]但我无法进一步。有些人可以把这个项目的指南地图放在一起,比如读什么,怎么接近,你觉得有什么用处。

编辑: 我开始编写这个应用程序但是有些东西丢失了。我读了这个文件http://www.viste.com/Linux/Server/WireShark/libpcapformat.pdf,它说前24个字节是全局标题,之后每个数据包都包含pcap本地标题。我想要做的是,首先尝试通过读取第三个来获取每个数据包中的数据字节 字段incl_len在本地标题中,但我的代码不像它假设的那样。我的测试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 


问候
Mukesh Tiwari

3 个答案:

答案 0 :(得分:2)

  

我希望时间以hdrSeconds p [捕获时间]以与wireshark相同的格式返回[日期:月份:年份时间:最小值:秒]

您可以使用time包并将其转换为UTCTime。这使得提取月,日,年等变得微不足道。查看time package的黑线鳕以获取更多信息。

let epoch = pcapEpochTimeThatYouFindInOnlineDocumentation
diff <- hdrDiffTime p
let date = addUTCTime (realToFrac diff) epoch

据我所知,Haskell绑定不提供时代,但一旦你发现这应该没问题。我会在维护者的补丁中发送电子邮件,直接向UTCTime添加转换。

  

以Ascii格式的变量q返回数据

好的q只是一个整体,您可以使用CharInt获取toEnum个:

print (toEnum (fromIntegral q) :: Char)

至于在纯粹的Haskell中这样做,我认为你需要退一步,了解更多关于Haskell作为一种语言,或许来自像learnyouahaskell这样的教诲。如果您决心继续前进,请阅读binary包,该包在邮件列表中被提及为非公共pcap Haskell库的首选库。

答案 1 :(得分:2)

您可以使用Data.Time模块将hdrSeconds返回的基于UNIX纪元的时间转换为LocalTime对象,然后可以将其格式化为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

答案 2 :(得分:0)

a Haskell library for reading pcap files,它可以解析文件头和数据包记录头,因此您不必自己动手。但是,您仍在自己解析数据包数据