1
1
mirror of https://github.com/wader/fq.git synced 2024-12-24 13:52:02 +03:00
fq/format/pcap/pcap.go
Mattias Wadman 2b2320d411 pcap,flows: fuzz: Handle broken packets more nicely
Still need to understand how gopacket is suppose to handle broken things
2021-12-09 14:19:17 +01:00

106 lines
2.7 KiB
Go

package pcap
// https://wiki.wireshark.org/Development/LibpcapFileFormat
// TODO: tshark seems to not support sll2 in pcap, confusing
import (
"github.com/wader/fq/format"
"github.com/wader/fq/format/inet/flowsdecoder"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/scalar"
)
var pcapEther8023Format decode.Group
var pcapSLLPacket decode.Group
var pcapSLL2Packet decode.Group
var pcapTCPStreamFormat decode.Group
var pcapIPv4PacketFormat decode.Group
const (
bigEndian = 0xa1b2c3d4
littleEndian = 0xd4c3b2a1
)
var endianMap = scalar.UToSymStr{
bigEndian: "big_endian",
littleEndian: "little_endian",
}
func init() {
registry.MustRegister(decode.Format{
Name: format.PCAP,
Description: "PCAP packet capture",
Groups: []string{format.PROBE},
Dependencies: []decode.Dependency{
{Names: []string{format.ETHER8023_FRAME}, Group: &pcapEther8023Format},
{Names: []string{format.SLL_PACKET}, Group: &pcapSLLPacket},
{Names: []string{format.SLL2_PACKET}, Group: &pcapSLL2Packet},
{Names: []string{format.TCP_STREAM}, Group: &pcapTCPStreamFormat},
{Names: []string{format.IPV4_PACKET}, Group: &pcapIPv4PacketFormat},
},
DecodeFn: decodePcap,
})
}
func decodePcap(d *decode.D, in interface{}) interface{} {
endian := d.FieldU32("magic", d.AssertU(bigEndian, littleEndian), endianMap, scalar.Hex)
switch endian {
case bigEndian:
d.Endian = decode.BigEndian
case littleEndian:
d.Endian = decode.LittleEndian
default:
d.Fatalf("unknown endian %d", endian)
}
d.FieldU16("version_major")
d.FieldU16("version_minor")
d.FieldS32("thiszone")
d.FieldU32("sigfigs")
spanLen := d.FieldU32("snaplen")
linkType := int(d.FieldU32("network", format.LinkTypeMap))
fd := flowsdecoder.New()
d.FieldArray("packets", func(d *decode.D) {
for !d.End() {
d.FieldStruct("packet", func(d *decode.D) {
d.FieldU32("ts_sec")
d.FieldU32("ts_usec")
inclLen := d.FieldU32("incl_len")
origLen := d.FieldU32("orig_len")
if inclLen > spanLen {
d.Errorf("incl_len %d > snaplen %d", inclLen, spanLen)
}
if inclLen > origLen {
d.Errorf("incl_len %d > orig_len %d", inclLen, origLen)
}
bb := d.BitBufRange(d.Pos(), int64(inclLen)*8)
bs, err := bb.Bytes()
if err != nil {
// TODO:
d.IOPanic(err, "BitBufRange: inclLen")
}
if fn, ok := linkToDecodeFn[linkType]; ok {
// TODO: report decode errors
_ = fn(fd, bs)
}
if g, ok := linkToFormat[linkType]; ok {
d.FieldFormatLen("packet", int64(inclLen)*8, *g, nil)
} else {
d.FieldRawLen("packet", int64(inclLen)*8)
}
})
}
})
fd.Flush()
fieldFlows(d, fd, pcapTCPStreamFormat, pcapIPv4PacketFormat)
return nil
}