From 97b14f3150ee9448401478684dbd268bf807bed1 Mon Sep 17 00:00:00 2001 From: nikiforo Date: Tue, 7 Dec 2021 21:01:26 +0300 Subject: [PATCH] pcapng - granulate IDB --- .../scala/fs2/protocols/pcap/LinkType.scala | 9 +++++++-- .../pcapng/InterfaceDescriptionBlock.scala | 19 ++++++++++++++++--- .../scala/fs2/protocols/PcapNgExample.scala | 3 ++- .../fs2/protocols/pcapng/BlockTest.scala | 9 +++++---- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/protocols/shared/src/main/scala/fs2/protocols/pcap/LinkType.scala b/protocols/shared/src/main/scala/fs2/protocols/pcap/LinkType.scala index 04ecd741a6..b6a14a6aed 100644 --- a/protocols/shared/src/main/scala/fs2/protocols/pcap/LinkType.scala +++ b/protocols/shared/src/main/scala/fs2/protocols/pcap/LinkType.scala @@ -41,14 +41,17 @@ object LinkType { case object MPEG2TS extends LinkType case class Unknown(value: Long) extends LinkType - def toLong(lt: LinkType): Long = lt match { + def fromInt(l: Int): LinkType = + fromLong(l) + + def toInt(lt: LinkType): Int = lt match { case Null => 0 case Ethernet => 1 case Raw => 101 case IPv4 => 228 case IPv6 => 229 case MPEG2TS => 243 - case Unknown(value) => value + case Unknown(value) => value.toInt // discuss? } def fromLong(l: Long): LinkType = l match { @@ -61,6 +64,8 @@ object LinkType { case other => Unknown(other) } + def toLong(lt: LinkType): Long = toInt(lt) + implicit def codec(implicit bo: ByteOrdering): Codec[LinkType] = guint32.xmap[LinkType](fromLong, toLong) } diff --git a/protocols/shared/src/main/scala/fs2/protocols/pcapng/InterfaceDescriptionBlock.scala b/protocols/shared/src/main/scala/fs2/protocols/pcapng/InterfaceDescriptionBlock.scala index 8ea113079a..2224082f60 100644 --- a/protocols/shared/src/main/scala/fs2/protocols/pcapng/InterfaceDescriptionBlock.scala +++ b/protocols/shared/src/main/scala/fs2/protocols/pcapng/InterfaceDescriptionBlock.scala @@ -22,17 +22,30 @@ package fs2.protocols package pcapng -import scodec.bits._ +import pcap._ import scodec.Codec +import scodec.bits._ import scodec.codecs._ -case class InterfaceDescriptionBlock(length: Length, bytes: ByteVector) extends BodyBlock +case class InterfaceDescriptionBlock( + length: Length, + linkType: LinkType, + snapLen: Long, + bytes: ByteVector +) extends BodyBlock object InterfaceDescriptionBlock { private def hexConstant(implicit ord: ByteOrdering) = orderDependent(hex"00000001", hex"01000000") + // format: off def codec(implicit ord: ByteOrdering): Codec[InterfaceDescriptionBlock] = - "IDB" | Block.ignoredCodec(hexConstant).as[InterfaceDescriptionBlock] + "IDB" | Block.codec(hexConstant) { length => + ("LinkType" | guint16.xmap[LinkType](LinkType.fromInt, LinkType.toInt)) :: + ("Reserved" | ignore(16)) :: + ("SnapLen" | guint32) :: + ("Block Bytes" | bytes(length.toLong.toInt - 20)) + }.dropUnits.as[InterfaceDescriptionBlock] + // format: on } diff --git a/protocols/shared/src/test/scala/fs2/protocols/PcapNgExample.scala b/protocols/shared/src/test/scala/fs2/protocols/PcapNgExample.scala index 2cbffaeb84..78279afb3d 100644 --- a/protocols/shared/src/test/scala/fs2/protocols/PcapNgExample.scala +++ b/protocols/shared/src/test/scala/fs2/protocols/PcapNgExample.scala @@ -27,11 +27,12 @@ import fs2.interop.scodec.StreamDecoder import fs2.io.file.{Files, Path} import fs2.protocols.pcapng.{BodyBlock, DummyBlock, SectionHeaderBlock} import scodec.Decoder +import cats.syntax.all._ object PcapNgExample extends IOApp.Simple { def run: IO[Unit] = - decode.compile.count.flatMap(IO.println) + decode.compile.toList.flatMap(_.traverse_(IO.println)) private def byteStream: Stream[IO, Byte] = Files[IO].readAll(Path("/Users/anikiforov/pcapng/many_interfaces.pcapng")) diff --git a/protocols/shared/src/test/scala/fs2/protocols/pcapng/BlockTest.scala b/protocols/shared/src/test/scala/fs2/protocols/pcapng/BlockTest.scala index 0b2c158935..a8d09c6bee 100644 --- a/protocols/shared/src/test/scala/fs2/protocols/pcapng/BlockTest.scala +++ b/protocols/shared/src/test/scala/fs2/protocols/pcapng/BlockTest.scala @@ -22,6 +22,7 @@ package fs2.protocols package pcapng +import fs2.protocols.pcap.LinkType.Ethernet import scodec.Attempt.Successful import scodec.DecodeResult import scodec.bits.ByteOrdering.LittleEndian @@ -92,10 +93,10 @@ private object BlockTest { object Interface { val header = hex"01000000" val length = hex"20000000" - val nonParsed = hex"01000000ffff0000090001000600000000000000" - val bytes = header ++ length ++ nonParsed ++ length - - val expected = InterfaceDescriptionBlock(Length(length), nonParsed) + val parsed = hex"01000000ffff0000" + val nonParsed = hex"090001000600000000000000" + val bytes = header ++ length ++ parsed ++ nonParsed ++ length + val expected = InterfaceDescriptionBlock(Length(length), Ethernet, 65535, nonParsed) } val enhancedHeader = hex"06000000"