forked from cloudflare/cbpfc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkernel_test.go
78 lines (67 loc) · 1.9 KB
/
kernel_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package cbpfc
import (
"bytes"
"net"
"testing"
"time"
"unsafe"
"golang.org/x/net/bpf"
"golang.org/x/sys/unix"
)
// kernelBackend is a backend that runs cBPF in the kernel
func kernelBackend(tb testing.TB, insns []bpf.Instruction, in []byte) result {
filter, err := bpf.Assemble(insns)
if err != nil {
tb.Fatal(err)
}
// Use a unix socket to test the filter
// This doesn't risk interfering with any other network traffic, doesn't require / add special
// headers (as would be the case if we used UDP for example) that the XDP tests don't deal with,
// and doesn't require any special permissions
read, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Name: "", Net: "unixgram"})
if err != nil {
tb.Fatal(err)
}
defer read.Close()
readConn, err := read.SyscallConn()
if err != nil {
tb.Fatal(err)
}
err = readConn.Control(func(fd uintptr) {
err := unix.SetsockoptSockFprog(int(fd), unix.SOL_SOCKET, unix.SO_ATTACH_FILTER, &unix.SockFprog{
Len: uint16(len(filter)),
Filter: (*unix.SockFilter)(unsafe.Pointer(&filter[0])),
})
if err != nil {
tb.Fatal(err)
}
})
if err != nil {
tb.Fatal(err)
}
write, err := net.Dial("unixgram", read.LocalAddr().String())
if err != nil {
tb.Fatal(err)
}
defer write.Close()
if _, err := write.Write(in); err != nil {
tb.Fatal(err)
}
read.SetDeadline(time.Now().Add(50 * time.Millisecond))
// SocketFilters only allow matching packets through
// If the packet does not match, the only signal we have is the absence of a packet
var out [1500]byte
n, err := read.Read(out[:])
if err != nil {
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
return noMatch
}
tb.Fatal(err)
}
// Sanity check we received the right packet
// Received packet is truncated to the SocketFilter's return value
if !bytes.Equal(in[:n], out[:n]) {
tb.Fatalf("Received unexpected packet:\nSent: %v\nGot: %v\n", in, out[:n])
}
return match
}