1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ipv4_test
6
7import (
8	"net"
9	"runtime"
10	"testing"
11	"time"
12
13	"golang.org/x/net/bpf"
14	"golang.org/x/net/ipv4"
15)
16
17func TestBPF(t *testing.T) {
18	if runtime.GOOS != "linux" {
19		t.Skipf("not supported on %s", runtime.GOOS)
20	}
21
22	l, err := net.ListenPacket("udp4", "127.0.0.1:0")
23	if err != nil {
24		t.Fatal(err)
25	}
26	defer l.Close()
27
28	p := ipv4.NewPacketConn(l)
29
30	// This filter accepts UDP packets whose first payload byte is
31	// even.
32	prog, err := bpf.Assemble([]bpf.Instruction{
33		// Load the first byte of the payload (skipping UDP header).
34		bpf.LoadAbsolute{Off: 8, Size: 1},
35		// Select LSB of the byte.
36		bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1},
37		// Byte is even?
38		bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1},
39		// Accept.
40		bpf.RetConstant{Val: 4096},
41		// Ignore.
42		bpf.RetConstant{Val: 0},
43	})
44	if err != nil {
45		t.Fatalf("compiling BPF: %s", err)
46	}
47
48	if err = p.SetBPF(prog); err != nil {
49		t.Fatalf("attaching filter to Conn: %s", err)
50	}
51
52	s, err := net.Dial("udp4", l.LocalAddr().String())
53	if err != nil {
54		t.Fatal(err)
55	}
56	defer s.Close()
57	go func() {
58		for i := byte(0); i < 10; i++ {
59			s.Write([]byte{i})
60		}
61	}()
62
63	l.SetDeadline(time.Now().Add(2 * time.Second))
64	seen := make([]bool, 5)
65	for {
66		var b [512]byte
67		n, _, err := l.ReadFrom(b[:])
68		if err != nil {
69			t.Fatalf("reading from listener: %s", err)
70		}
71		if n != 1 {
72			t.Fatalf("unexpected packet length, want 1, got %d", n)
73		}
74		if b[0] >= 10 {
75			t.Fatalf("unexpected byte, want 0-9, got %d", b[0])
76		}
77		if b[0]%2 != 0 {
78			t.Fatalf("got odd byte %d, wanted only even bytes", b[0])
79		}
80		seen[b[0]/2] = true
81
82		seenAll := true
83		for _, v := range seen {
84			if !v {
85				seenAll = false
86				break
87			}
88		}
89		if seenAll {
90			break
91		}
92	}
93}
94