Files
lneto/internet/pcap/capture_test.go
T

124 lines
3.6 KiB
Go

package pcap
import (
"math"
"math/rand"
"testing"
"github.com/soypat/lneto"
"github.com/soypat/lneto/ethernet"
"github.com/soypat/lneto/http/httpraw"
"github.com/soypat/lneto/internal/ltesto"
"github.com/soypat/lneto/ipv4"
"github.com/soypat/lneto/tcp"
)
func TestCap(t *testing.T) {
const mtu = 1500
const httpBody = "{200,ok}"
var buf [mtu]byte
var gen ltesto.PacketGen
rng := rand.New(rand.NewSource(1))
gen.RandomizeAddrs(rng)
pkt := gen.AppendRandomIPv4TCPPacket(buf[:0], rng, tcp.Segment{
SEQ: 100,
ACK: 200,
DATALEN: 256,
WND: 1024,
Flags: tcp.FlagFIN, //tcp.FlagSYN | tcp.FlagACK | tcp.FlagPSH,
})
var hdr httpraw.Header
hdr.SetStatus("200", "OK")
hdr.Set("Cookie", "ABC=123")
pkt, _ = hdr.AppendResponse(pkt)
pkt = append(pkt, httpBody...)
var pbreak PacketBreakdown
frames, err := pbreak.CaptureEthernet(nil, pkt, 0)
if err != nil {
t.Fatal(err)
}
// Ethernet+IPv4+TCP+HTTP = 4 frames
if len(frames) != 4 {
t.Errorf("want 4 frames, got %d", len(frames))
}
getClass := func(frame Frame, class FieldClass) uint64 {
idx, err := frame.FieldByClass(class)
if err != nil {
return 0xffff_ffff_ffff_ffff
}
v, _ := frame.FieldAsUint(idx, pkt)
return v
}
getName := func(frame Frame, name string) uint64 {
for i := range frame.Fields {
if frame.Fields[i].Name == name {
v, _ := frame.FieldAsUint(i, pkt)
return v
}
}
return math.MaxUint64
}
getClassData := func(frame Frame, class FieldClass) []byte {
idx, err := frame.FieldByClass(class)
if err != nil {
return nil
}
v, _ := frame.AppendField(nil, idx, pkt)
return v
}
efrm, _ := ethernet.NewFrame(pkt)
pefrm := frames[0]
pifrm := frames[1]
ptfrm := frames[2]
phfrm := frames[3]
gotEproto := ethernet.Type(getClass(pefrm, FieldClassProto))
if gotEproto != efrm.EtherTypeOrSize() {
t.Errorf("want %s ethernet type, got %s", efrm.EtherTypeOrSize().String(), gotEproto.String())
}
ifrm, _ := ipv4.NewFrame(efrm.Payload())
gotIproto := lneto.IPProto(getClass(pifrm, FieldClassProto))
if gotIproto != ifrm.Protocol() {
t.Errorf("want %s IP proto, got %s", ifrm.Protocol().String(), gotIproto.String())
}
gotToS := ipv4.ToS(getName(pifrm, "Type of Service"))
wantToS := ifrm.ToS()
if gotToS != wantToS {
t.Errorf("want %x IP ToS, got %x", wantToS, gotToS)
}
gotIflags := ipv4.Flags(getClass(pifrm, FieldClassFlags))
if gotIflags != ifrm.Flags() {
t.Errorf("want %x IP flags, got %x", ifrm.Flags(), gotIflags)
}
gotVersion := getClass(pifrm, FieldClassVersion)
wantVersion, _ := ifrm.VersionAndIHL()
if gotVersion != uint64(wantVersion) {
t.Errorf("want %d IP version, got %d", wantVersion, gotVersion)
}
tfrm, _ := tcp.NewFrame(ifrm.Payload())
gotTCPFlags := tcp.Flags(getClass(ptfrm, FieldClassFlags))
wantHeaderLen, wantTCPflags := tfrm.OffsetAndFlags()
if gotTCPFlags != wantTCPflags {
t.Errorf("want %s TCP flags, got %s", wantTCPflags.String(), gotTCPFlags.String())
}
wanDstPort := gen.DstTCP
wantSrcPort := gen.SrcTCP
gotSrcPort := uint16(getClass(ptfrm, FieldClassSrc))
gotDstPort := uint16(getClass(ptfrm, FieldClassDst))
if wantSrcPort != gotSrcPort {
t.Errorf("want %d TCP src port, got %d", wantSrcPort, gotSrcPort)
}
if wanDstPort != gotDstPort {
t.Errorf("want %d TCP dst port, got %d", wanDstPort, gotDstPort)
}
gotHeaderLen := getClass(ptfrm, FieldClassSize)
if gotHeaderLen != uint64(wantHeaderLen) {
t.Errorf("want %d TCP header length, got %d", wantHeaderLen, gotHeaderLen)
}
gotBody := getClassData(phfrm, FieldClassPayload)
if string(gotBody) != httpBody {
t.Errorf("want %q HTTP body, got %q", httpBody, gotBody)
}
}