...
1
2
3
4
5
6
7
8 package packet_test
9
10 import (
11 "encoding/binary"
12 "errors"
13 "net"
14 "os"
15 "testing"
16 "time"
17
18 "github.com/mdlayher/packet"
19 "golang.org/x/sys/unix"
20 )
21
22 func TestConnListen(t *testing.T) {
23
24
25
26
27 c, ifi := testConn(t)
28 t.Logf("interface: %q, MTU: %d", ifi.Name, ifi.MTU)
29
30 if err := c.SetReadDeadline(time.Now().Add(30 * time.Second)); err != nil {
31 t.Fatalf("failed to set read deadline: %v", err)
32 }
33
34 b := make([]byte, ifi.MTU)
35 n, addr, err := c.ReadFrom(b)
36 if err != nil {
37 t.Fatalf("failed to read Ethernet frame: %v", err)
38 }
39
40
41 stats, err := c.Stats()
42 if err != nil {
43 t.Fatalf("failed to fetch stats: %v", err)
44 }
45 if stats.Packets == 0 {
46 t.Fatal("stats indicated 0 received packets")
47 }
48
49 t.Logf(" - packets: %d, drops: %d, freeze queue count: %d",
50 stats.Packets, stats.Drops, stats.FreezeQueueCount)
51
52
53
54
55
56 const header = 6 + 6 + 2
57 if n < header {
58 t.Fatalf("did not read a complete Ethernet frame from %v, only %d bytes read",
59 addr, n)
60 }
61
62
63 var (
64 dst = net.HardwareAddr(b[0:6])
65 src = net.HardwareAddr(b[6:12])
66 et = binary.BigEndian.Uint16(b[12:14])
67 )
68
69
70 var ets string
71 switch et {
72 case 0x0800:
73 ets = "IPv4"
74 case 0x0806:
75 ets = "ARP"
76 case 0x86dd:
77 ets = "IPv6"
78 default:
79 ets = "unknown"
80 }
81
82
83 t.Log("Ethernet frame:")
84 t.Logf(" - destination: %s", dst)
85 t.Logf(" - source: %s", src)
86 t.Logf(" - ethertype: %#04x (%s)", et, ets)
87 t.Logf(" - payload: %d bytes", n-header)
88 }
89
90
91
92 func testConn(t *testing.T) (*packet.Conn, *net.Interface) {
93 t.Helper()
94
95
96 ifi := testInterface(t)
97 c, err := packet.Listen(ifi, packet.Raw, unix.ETH_P_ALL, nil)
98 if err != nil {
99 if errors.Is(err, os.ErrPermission) {
100 t.Skipf("skipping, permission denied (try setting CAP_NET_RAW capability): %v", err)
101 }
102
103 t.Fatalf("failed to listen: %v", err)
104 }
105
106 t.Cleanup(func() { c.Close() })
107 return c, ifi
108 }
109
110
111 func testInterface(t *testing.T) *net.Interface {
112 ifis, err := net.Interfaces()
113 if err != nil {
114 t.Fatalf("failed to get network interfaces: %v", err)
115 }
116
117 if len(ifis) == 0 {
118 t.Skip("skipping, no network interfaces found")
119 }
120
121
122 var tried []string
123 for _, ifi := range ifis {
124 tried = append(tried, ifi.Name)
125
126
127 ok := true &&
128
129 len(ifi.HardwareAddr) == 6 &&
130
131 ifi.Flags&(net.FlagUp|net.FlagMulticast|net.FlagBroadcast) != 0
132
133 if ok {
134 return &ifi
135 }
136 }
137
138 t.Skipf("skipping, could not find a usable network interface, tried: %s", tried)
139 panic("unreachable")
140 }
141
View as plain text