2011-10-12 52 views
1

我想解码一个pcap file及其工作正常,除了几件事。Haskell中的Pcap文件解码

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的[日期:月:年时:分:秒],并以ASCII format.Kindly可变Q数据告诉回报我如何做到这一点。
其实我试图解析pcap文件,以与wireshark几乎类似的方式显示其内容,而没有libpcap库[纯粹通过以二进制格式打开pcap文件并逐字节读取]在haskell中,但我无法得到任何进一步的信息。有些人可以把这个项目的指导地图放在什么地方阅读,如何处理,任何你认为会有帮助的东西。

编辑: 我开始写这个应用程序,但有一些东西丢失。我读这个文件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 


问候
穆克什·蒂瓦里

回答

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是只是一个可积,你可以从Int S使用toEnum得到Char S:

print (toEnum (fromIntegral q) :: Char) 

至于这样做在纯粹的Haskell中,我认为你需要退后一步,并更多地了解Haskell作为一种语言,可能来自于例如learnyouahaskell的tutuorial。如果您决心进取,那么请阅读binary软件包,该软件包在邮件列表中被提及为非公开pcap Haskell库的首选库。

2

可以使用Data.Time模块通过hdrSeconds返回,然后可以格式化成与formatTime一个字符串LocalTime对象的基于UNIX时代时间转换。

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