1 // Copyright 2012 Google, Inc. All rights reserved.
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
17 "github.com/google/gopacket"
18 "github.com/google/gopacket/layers"
21 func TestPcapNonexistentFile(t *testing.T) {
22 handle, err := OpenOffline("/path/to/nonexistent/file")
24 t.Error("No error returned for nonexistent file open")
26 t.Logf("Error returned for nonexistent file: %v", err)
29 t.Error("Non-nil handle returned for nonexistent file open")
33 func TestPcapFileRead(t *testing.T) {
34 invalidData := []byte{
35 0xAB, 0xAD, 0x1D, 0xEA,
38 invalidPcap, err := ioutil.TempFile("", "invalid.pcap")
42 defer os.Remove(invalidPcap.Name())
44 err = ioutil.WriteFile(invalidPcap.Name(), invalidData, 0644)
48 defer invalidPcap.Close()
50 for _, file := range []struct {
53 expectedLayers []gopacket.LayerType
56 {filename: "test_loopback.pcap",
58 expectedLayers: []gopacket.LayerType{
59 layers.LayerTypeLoopback,
64 {filename: "test_ethernet.pcap",
66 expectedLayers: []gopacket.LayerType{
67 layers.LayerTypeEthernet,
72 {filename: "test_dns.pcap",
74 expectedLayers: []gopacket.LayerType{
75 layers.LayerTypeEthernet,
81 {filename: invalidPcap.Name(),
83 err: "unknown file format",
86 t.Logf("\n\n\n\nProcessing file %s\n\n\n\n", file.filename)
88 packets := []gopacket.Packet{}
89 if handle, err := OpenOffline(file.filename); err != nil {
91 if err.Error() != file.err {
92 t.Errorf("expected message %q; got %q", file.err, err.Error())
99 t.Fatalf("Expected error, got none")
101 packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
102 for packet := range packetSource.Packets() {
103 packets = append(packets, packet)
106 if len(packets) != file.num {
107 t.Fatal("Incorrect number of packets, want", file.num, "got", len(packets))
109 for i, p := range packets {
111 for _, layertype := range file.expectedLayers {
112 if p.Layer(layertype) == nil {
113 t.Fatal("Packet", i, "has no layer type\n%s", layertype, p.Dump())
120 func TestBPF(t *testing.T) {
121 handle, err := OpenOffline("test_ethernet.pcap")
126 for _, expected := range []struct {
131 {"foobar", true, false},
132 {"tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)", false, true},
133 {"tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack", false, true},
134 {"udp", false, false},
136 data, ci, err := handle.ReadPacketData()
140 t.Log("Testing filter", expected.expr)
141 if bpf, err := handle.NewBPF(expected.expr); err != nil {
143 t.Error(err, "while compiling filter was unexpected")
145 } else if expected.Error {
146 t.Error("expected error but didn't see one")
147 } else if matches := bpf.Matches(ci, data); matches != expected.Result {
148 t.Error("Filter result was", matches, "but should be", expected.Result)
153 func TestBPFInstruction(t *testing.T) {
154 handle, err := OpenOffline("test_ethernet.pcap")
160 oversizedBpfInstructionBuffer := [MaxBpfInstructions + 1]BPFInstruction{}
162 for _, expected := range []struct {
164 BpfInstruction []BPFInstruction
168 // {"foobar", true, false},
169 {"foobar", []BPFInstruction{}, true, false},
171 // tcpdump -dd 'tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)'
172 {"tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)",
174 {0x28, 0, 0, 0x0000000c},
175 {0x15, 0, 9, 0x00000800},
176 {0x30, 0, 0, 0x00000017},
177 {0x15, 0, 7, 0x00000006},
178 {0x28, 0, 0, 0x00000014},
179 {0x45, 5, 0, 0x00001fff},
180 {0xb1, 0, 0, 0x0000000e},
181 {0x50, 0, 0, 0x0000001b},
182 {0x54, 0, 0, 0x00000012},
183 {0x15, 0, 1, 0x00000012},
184 {0x6, 0, 0, 0x0000ffff},
185 {0x6, 0, 0, 0x00000000},
188 // tcpdump -dd 'tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack'
189 {"tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack",
191 {0x28, 0, 0, 0x0000000c},
192 {0x15, 0, 9, 0x00000800},
193 {0x30, 0, 0, 0x00000017},
194 {0x15, 0, 7, 0x00000006},
195 {0x28, 0, 0, 0x00000014},
196 {0x45, 5, 0, 0x00001fff},
197 {0xb1, 0, 0, 0x0000000e},
198 {0x50, 0, 0, 0x0000001b},
199 {0x54, 0, 0, 0x00000012},
200 {0x15, 0, 1, 0x00000010},
201 {0x6, 0, 0, 0x0000ffff},
202 {0x6, 0, 0, 0x00000000},
208 {0x28, 0, 0, 0x0000000c},
209 {0x15, 0, 5, 0x000086dd},
210 {0x30, 0, 0, 0x00000014},
211 {0x15, 6, 0, 0x00000011},
212 {0x15, 0, 6, 0x0000002c},
213 {0x30, 0, 0, 0x00000036},
214 {0x15, 3, 4, 0x00000011},
215 {0x15, 0, 3, 0x00000800},
216 {0x30, 0, 0, 0x00000017},
217 {0x15, 0, 1, 0x00000011},
218 {0x6, 0, 0, 0x0000ffff},
219 {0x6, 0, 0, 0x00000000},
222 {"", oversizedBpfInstructionBuffer[:], true, false},
225 data, ci, err := handle.ReadPacketData()
230 t.Log("Testing BpfInstruction filter", cntr)
231 if bpf, err := handle.NewBPFInstructionFilter(expected.BpfInstruction); err != nil {
233 t.Error(err, "while compiling filter was unexpected")
235 } else if expected.Error {
236 t.Error("expected error but didn't see one")
237 } else if matches := bpf.Matches(ci, data); matches != expected.Result {
238 t.Error("Filter result was", matches, "but should be", expected.Result)
241 if expected.Filter != "" {
242 t.Log("Testing dead bpf filter", cntr)
243 if bpf, err := CompileBPFFilter(layers.LinkTypeEthernet, 65535, expected.Filter); err != nil {
245 t.Error(err, "while compiling filter was unexpected")
247 } else if expected.Error {
248 t.Error("expected error but didn't see one")
250 if len(bpf) != len(expected.BpfInstruction) {
251 t.Errorf("expected %d instructions, got %d", len(expected.BpfInstruction), len(bpf))
253 for i := 0; i < len(bpf); i++ {
254 if bpf[i] != expected.BpfInstruction[i] {
255 t.Errorf("expected instruction %d = %d, got %d", i, expected.BpfInstruction[i], bpf[i])
264 handle, err := OpenOffline("test_ethernet.pcap")
268 synack, err := handle.NewBPF("tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)")
272 syn, err := handle.NewBPF("tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn")
277 data, ci, err := handle.ReadPacketData()
283 case synack.Matches(ci, data):
284 fmt.Println("SYN/ACK packet")
285 case syn.Matches(ci, data):
286 fmt.Println("SYN packet")
288 fmt.Println("SYN flag not set")