diff options
Diffstat (limited to 'vendor/github.com/google/gopacket/pcap/pcap_test.go')
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/pcap_test.go | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/vendor/github.com/google/gopacket/pcap/pcap_test.go b/vendor/github.com/google/gopacket/pcap/pcap_test.go new file mode 100644 index 0000000..04f1812 --- /dev/null +++ b/vendor/github.com/google/gopacket/pcap/pcap_test.go @@ -0,0 +1,308 @@ +// Copyright 2012 Google, Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. + +package pcap + +import ( + "fmt" + "io" + "io/ioutil" + "log" + "os" + "testing" + + "github.com/google/gopacket" + "github.com/google/gopacket/layers" +) + +func TestPcapNonexistentFile(t *testing.T) { + handle, err := OpenOffline("/path/to/nonexistent/file") + if err == nil { + t.Error("No error returned for nonexistent file open") + } else { + t.Logf("Error returned for nonexistent file: %v", err) + } + if handle != nil { + t.Error("Non-nil handle returned for nonexistent file open") + } +} + +func TestPcapFileRead(t *testing.T) { + invalidData := []byte{ + 0xAB, 0xAD, 0x1D, 0xEA, + } + + invalidPcap, err := ioutil.TempFile("", "invalid.pcap") + if err != nil { + t.Fatal(err) + } + defer os.Remove(invalidPcap.Name()) + + err = ioutil.WriteFile(invalidPcap.Name(), invalidData, 0644) + if err != nil { + t.Fatal(err) + } + defer invalidPcap.Close() + + for _, file := range []struct { + filename string + num int + expectedLayers []gopacket.LayerType + err string + }{ + {filename: "test_loopback.pcap", + num: 24, + expectedLayers: []gopacket.LayerType{ + layers.LayerTypeLoopback, + layers.LayerTypeIPv6, + layers.LayerTypeTCP, + }, + }, + {filename: "test_ethernet.pcap", + num: 16, + expectedLayers: []gopacket.LayerType{ + layers.LayerTypeEthernet, + layers.LayerTypeIPv4, + layers.LayerTypeTCP, + }, + }, + {filename: "test_dns.pcap", + num: 10, + expectedLayers: []gopacket.LayerType{ + layers.LayerTypeEthernet, + layers.LayerTypeIPv4, + layers.LayerTypeUDP, + layers.LayerTypeDNS, + }, + }, + {filename: invalidPcap.Name(), + num: 0, + err: "unknown file format", + }, + } { + t.Logf("\n\n\n\nProcessing file %s\n\n\n\n", file.filename) + + packets := []gopacket.Packet{} + if handle, err := OpenOffline(file.filename); err != nil { + if file.err != "" { + if err.Error() != file.err { + t.Errorf("expected message %q; got %q", file.err, err.Error()) + } + } else { + t.Fatal(err) + } + } else { + if file.err != "" { + t.Fatalf("Expected error, got none") + } + packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) + for packet := range packetSource.Packets() { + packets = append(packets, packet) + } + } + if len(packets) != file.num { + t.Fatal("Incorrect number of packets, want", file.num, "got", len(packets)) + } + for i, p := range packets { + t.Log(p.Dump()) + for _, layertype := range file.expectedLayers { + if p.Layer(layertype) == nil { + t.Fatal("Packet", i, "has no layer type\n%s", layertype, p.Dump()) + } + } + } + } +} + +func TestBPF(t *testing.T) { + handle, err := OpenOffline("test_ethernet.pcap") + if err != nil { + t.Fatal(err) + } + + for _, expected := range []struct { + expr string + Error bool + Result bool + }{ + {"foobar", true, false}, + {"tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)", false, true}, + {"tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack", false, true}, + {"udp", false, false}, + } { + data, ci, err := handle.ReadPacketData() + if err != nil { + t.Fatal(err) + } + t.Log("Testing filter", expected.expr) + if bpf, err := handle.NewBPF(expected.expr); err != nil { + if !expected.Error { + t.Error(err, "while compiling filter was unexpected") + } + } else if expected.Error { + t.Error("expected error but didn't see one") + } else if matches := bpf.Matches(ci, data); matches != expected.Result { + t.Error("Filter result was", matches, "but should be", expected.Result) + } + } +} + +func TestBPFInstruction(t *testing.T) { + handle, err := OpenOffline("test_ethernet.pcap") + if err != nil { + t.Fatal(err) + } + + cntr := 0 + oversizedBpfInstructionBuffer := [MaxBpfInstructions + 1]BPFInstruction{} + + for _, expected := range []struct { + Filter string + BpfInstruction []BPFInstruction + Error bool + Result bool + }{ + // {"foobar", true, false}, + {"foobar", []BPFInstruction{}, true, false}, + + // tcpdump -dd 'tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)' + {"tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)", + []BPFInstruction{ + {0x28, 0, 0, 0x0000000c}, + {0x15, 0, 9, 0x00000800}, + {0x30, 0, 0, 0x00000017}, + {0x15, 0, 7, 0x00000006}, + {0x28, 0, 0, 0x00000014}, + {0x45, 5, 0, 0x00001fff}, + {0xb1, 0, 0, 0x0000000e}, + {0x50, 0, 0, 0x0000001b}, + {0x54, 0, 0, 0x00000012}, + {0x15, 0, 1, 0x00000012}, + {0x6, 0, 0, 0x0000ffff}, + {0x6, 0, 0, 0x00000000}, + }, false, true}, + + // tcpdump -dd 'tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack' + {"tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack", + []BPFInstruction{ + {0x28, 0, 0, 0x0000000c}, + {0x15, 0, 9, 0x00000800}, + {0x30, 0, 0, 0x00000017}, + {0x15, 0, 7, 0x00000006}, + {0x28, 0, 0, 0x00000014}, + {0x45, 5, 0, 0x00001fff}, + {0xb1, 0, 0, 0x0000000e}, + {0x50, 0, 0, 0x0000001b}, + {0x54, 0, 0, 0x00000012}, + {0x15, 0, 1, 0x00000010}, + {0x6, 0, 0, 0x0000ffff}, + {0x6, 0, 0, 0x00000000}, + }, false, true}, + + // tcpdump -dd 'udp' + {"udp", + []BPFInstruction{ + {0x28, 0, 0, 0x0000000c}, + {0x15, 0, 5, 0x000086dd}, + {0x30, 0, 0, 0x00000014}, + {0x15, 6, 0, 0x00000011}, + {0x15, 0, 6, 0x0000002c}, + {0x30, 0, 0, 0x00000036}, + {0x15, 3, 4, 0x00000011}, + {0x15, 0, 3, 0x00000800}, + {0x30, 0, 0, 0x00000017}, + {0x15, 0, 1, 0x00000011}, + {0x6, 0, 0, 0x0000ffff}, + {0x6, 0, 0, 0x00000000}, + }, false, false}, + + {"", oversizedBpfInstructionBuffer[:], true, false}, + } { + cntr++ + data, ci, err := handle.ReadPacketData() + if err != nil { + t.Fatal(err) + } + + t.Log("Testing BpfInstruction filter", cntr) + if bpf, err := handle.NewBPFInstructionFilter(expected.BpfInstruction); err != nil { + if !expected.Error { + t.Error(err, "while compiling filter was unexpected") + } + } else if expected.Error { + t.Error("expected error but didn't see one") + } else if matches := bpf.Matches(ci, data); matches != expected.Result { + t.Error("Filter result was", matches, "but should be", expected.Result) + } + + if expected.Filter != "" { + t.Log("Testing dead bpf filter", cntr) + if bpf, err := CompileBPFFilter(layers.LinkTypeEthernet, 65535, expected.Filter); err != nil { + if !expected.Error { + t.Error(err, "while compiling filter was unexpected") + } + } else if expected.Error { + t.Error("expected error but didn't see one") + } else { + if len(bpf) != len(expected.BpfInstruction) { + t.Errorf("expected %d instructions, got %d", len(expected.BpfInstruction), len(bpf)) + } + for i := 0; i < len(bpf); i++ { + if bpf[i] != expected.BpfInstruction[i] { + t.Errorf("expected instruction %d = %d, got %d", i, expected.BpfInstruction[i], bpf[i]) + } + } + } + } + } +} + +func ExampleBPF() { + handle, err := OpenOffline("test_ethernet.pcap") + if err != nil { + log.Fatal(err) + } + synack, err := handle.NewBPF("tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)") + if err != nil { + log.Fatal(err) + } + syn, err := handle.NewBPF("tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn") + if err != nil { + log.Fatal(err) + } + for { + data, ci, err := handle.ReadPacketData() + switch { + case err == io.EOF: + return + case err != nil: + log.Fatal(err) + case synack.Matches(ci, data): + fmt.Println("SYN/ACK packet") + case syn.Matches(ci, data): + fmt.Println("SYN packet") + default: + fmt.Println("SYN flag not set") + } + } + // Output: + // SYN packet + // SYN/ACK packet + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set + // SYN flag not set +} |