Parsing Packets with House

Now that I have the Haskell libpcap binding working, I want to be able to parse the packets that I capture. How feasible would it be to use the modules in House (programatica/hOp/kernel/Net) standalone? For example, here is a capture of a packet showing the 14-byte ethernet header followed by the IP packet which in this case is an ICMP echo request. I assume I can somehow use Net.Ethernet, Net.IPv4 and Net.ICMP to parse the packet? Dominic. [0,16,220,204,93,240,0,48,5,177,121,178,8,0, 69,0,0,84,104,184,0,0,255,1,9,54,192,168,100,55,192,168,100,50, 8,0,136,151,164,247,0,0, 68,120,161,81, 0,0,249,163,8,9,10,11,12,13,14,15,16,17,18,19, 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35, 36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51, 52,53,54,55]

Dominic Steinitz wrote:
Now that I have the Haskell libpcap binding working, I want to be able to parse the packets that I capture. How feasible would it be to use the modules in House (programatica/hOp/kernel/Net) standalone?
For example, here is a capture of a packet showing the 14-byte ethernet header followed by the IP packet which in this case is an ICMP echo request. I assume I can somehow use Net.Ethernet, Net.IPv4 and Net.ICMP to parse the packet?
Yes, that is possible. I enclose a sample session with ghci. (Sorry about the long lines.) What is missing is perhaps a data type that can hold different types of packets and a parser/prettyprinter for that type. Thomas H ------------------------------------------------------------------------ % ghci -fglasgow-exts -fallow-undecidable-instances ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.4.2, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base-1.0 ... linking ... done. Prelude> :l Net.Ethernet Net.IPv4 Net.ICMP Compiling Monad.Util ( ./Monad/Util.hs, interpreted ) Compiling Net.Interface ( ./Net/Interface.hs, interpreted ) Compiling Net.Concurrent ( ./Net/Concurrent.hs, interpreted ) Compiling Kernel.Bits ( ./Kernel/Bits.hs, interpreted ) Compiling Net.Utils ( ./Net/Utils.hs, interpreted ) Compiling Net.Packet ( ./Net/Packet.hs, interpreted ) Compiling Net.PacketParsing ( ./Net/PacketParsing.hs, interpreted ) Compiling Net.ICMP ( ./Net/ICMP.hs, interpreted ) Compiling Net.IPv4 ( ./Net/IPv4.hs, interpreted ) Compiling Net.Ethernet ( ./Net/Ethernet.hs, interpreted ) Ok, modules loaded: Net.Ethernet, Net.IPv4, Net.ICMP, Net.PacketParsing, Net.Packet, Net.Utils, Kernel.Bits, Net.Concurrent, Net.Interface, Monad.Util. *Net.Ethernet> let p = toInPack (listArray (0,length bytes-1) bytes); bytes = [0,16,220,204,93,240,0,48,5,177,121,178,8,0,69,0,0,84,104,184,0,0,255,1,9,54,192,168,100,55,192,168,100,50,8,0,136,151,164,247,0,0,68,120,161,81,0,0,249,163,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55] Loading package mtl-1.0 ... linking ... done. *Net.Ethernet> doParse p::Maybe (Net.Ethernet.Packet (Net.IPv4.Packet Net.ICMP.Packet)) Just (Packet {dest = 00:10:dc:cc:5d:f0, source = 00:30:05:b1:79:b2, packType = IPv4, content = Packet {version = 4, headerLen = 5, tos = TOS {precedence = Routine, lowDelay = False, highThrough = False, highReal = False}, totalLen = 84, identifier = 26808, flags = Flags {don'tFrag = False, moreFrags = False}, fragOff = 0, timeToLive = 255, protocol = ICMP, headerCheck = 2358, source = 192.168.100.55, dest = 192.168.100.50, options = [], content = EchoRequest (Echo {ident = 42231, seqNum = 0, echoData = array (0,55) [(0,68),(1,120),(2,161),(3,81),(4,0),(5,0),(6,249),(7,163),(8,8),(9,9),(10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19),(20,20),(21,21),(22,22),(23,23),(24,24),(25,25),(26,26),(27,27),(28,28),(29,29),(30,30),(31,31),(32,32),(33,33),(34,34),(35,35),(36,36),(37,37),(38,38),(39,39),(40,40),(41,41),(42,42),(43,43),(44,44),(45,45),(46,46),(47,47),(48,48),(49,49),(50,50),(51,51),(52,52),(53,53),(54,54),(55,55)]})}}) *Net.Ethernet> doParse p::Maybe (Net.Ethernet.Packet InPacket) Just (Packet {dest = 00:10:dc:cc:5d:f0, source = 00:30:05:b1:79:b2, packType = IPv4, content = <<84 bytes>>}) *Net.Ethernet>

Dominic Steinitz wrote:
Thomas Hallgren wrote:
% ghci -fglasgow-exts -fallow-undecidable-instances
That's excellent. One question: what's the reason for undecidable instances?
It's needed for some of the instance declarations in Net.Concurrent. But that stuff is not used for packet parsing, it just happens to be imported. For the example, you can omit it if you comment out the import of Net.Concurrent and the definition of doReq in Net.Utils. Thomas H

Hello Thomas, Sunday, May 28, 2006, 11:09:56 AM, you wrote:
% ghci -fglasgow-exts -fallow-undecidable-instances
It's needed for some of the instance declarations in Net.Concurrent. But
just two cents - imho it's better to include such flags in source file itself: {-# OPTIONS_GHC -cpp -fglasgow-exts -fallow-undecidable-instances #-} -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
participants (3)
-
Bulat Ziganshin
-
Dominic Steinitz
-
Thomas Hallgren