#networking #haskell #libpcap
#сеть #haskell #libpcap
Вопрос:
Я пытаюсь декодировать файл 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
Я хочу, чтобы время возвращалось в hdrсекундах p [время для захвата] в том же формате, что и в wireshark [Дата: месяц: год, час: минута: Сек], и данные возвращались переменной q в формате Ascii.Пожалуйста, скажите мне, как это сделать.
На самом деле я пытался проанализировать файл pcap, чтобы отобразить его содержимое почти аналогично wireshark без библиотеки libpcap [чисто в haskell, открыв файл pcap в двоичном формате и прочитав байт за байтом], но я не смог продвинуться дальше. Не могли бы некоторые, пожалуйста, поместить карту руководства для этого проекта, например, что читать, как подойти, что угодно, что, по вашему мнению, было бы полезно.
Редактировать: я начал писать это приложение, но чего-то не хватает. Я прочитал этот файл http://www.viste.com/Linux/Server/WireShark/libpcapformat.pdf и в нем говорится , что первые 24 байта являются глобальными заголовками , после чего каждый пакет содержит локальный заголовок pcap . Что я пытаюсь сделать, так это сначала попытаться получить байты данных в каждом пакете, прочитав третье поле incl_len в локальном заголовке, но мой код ведет себя не так, как он предполагает. Мой тестовый файл libcap.
--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
С уважением
Мукеш Тивари
Ответ №1:
Я хочу, чтобы время возвращалось на hdrСекунды p [время для захвата] в том же формате, что и в wireshark [ Дата: месяц: год Час: Мин: Сек]
Ну, вы можете использовать time
пакет и преобразовать это в UTCTime
. Это делает тривиальным извлечение месяца, дня, года и т. Д. Посмотрите на haddock пакета time для получения дополнительной информации.
let epoch = pcapEpochTimeThatYouFindInOnlineDocumentation
diff <- hdrDiffTime p
let date = addUTCTime (realToFrac diff) epoch
Из того, что я могу сказать, привязки Haskell не предоставляют эпоху, но как только вы обнаружите, что это должно быть хорошо. Я бы отправил по электронной почте исправление сопровождающему, чтобы добавить диалог непосредственно в UTCTime.
и возврат данных переменной q в формате Ascii
Ну, q — это просто промежуточное значение, и вы можете получить Char
s из Int
s, используя toEnum
:
print (toEnum (fromIntegral q) :: Char)
Что касается выполнения этого в чистом Haskell, я думаю, вам нужно немного отступить назад и узнать больше о Haskell как языке, возможно, из учебника, такого как learnyouahaskell. Если вы полны решимости продвигаться вперед, ознакомьтесь с бинарным пакетом, который был упомянут в списке рассылки как библиотека выбора для их непубличной библиотеки pcap Haskell.
Ответ №2:
Вы можете использовать Data.Time
модуль для преобразования времени на основе эпохи UNIX, возвращаемого by hdrSeconds
, в LocalTime
объект, который затем может быть отформатирован в строку 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
Ответ №3:
Существует библиотека Haskell для чтения файлов pcap, которая выполняет синтаксический анализ заголовка файла и заголовков записей пакетов, поэтому вам не нужно делать это самостоятельно. Однако вы все еще самостоятельно анализируете пакетные данные.