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
5//go:build darwin || dragonfly || freebsd || netbsd || openbsd
6// +build darwin dragonfly freebsd netbsd openbsd
7
8package route
9
10import (
11	"os"
12	"syscall"
13	"testing"
14	"time"
15)
16
17func TestFetchAndParseRIB(t *testing.T) {
18	for _, typ := range []RIBType{sysNET_RT_DUMP, sysNET_RT_IFLIST} {
19		var lastErr error
20		var ms []Message
21		for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
22			rs, err := fetchAndParseRIB(af, typ)
23			if err != nil {
24				lastErr = err
25				continue
26			}
27			ms = append(ms, rs...)
28		}
29		if len(ms) == 0 && lastErr != nil {
30			t.Error(typ, lastErr)
31			continue
32		}
33		ss, err := msgs(ms).validate()
34		if err != nil {
35			t.Error(typ, err)
36			continue
37		}
38		for _, s := range ss {
39			t.Log(typ, s)
40		}
41	}
42}
43
44var (
45	rtmonSock int
46	rtmonErr  error
47)
48
49func init() {
50	// We need to keep rtmonSock alive to avoid treading on
51	// recycled socket descriptors.
52	rtmonSock, rtmonErr = syscall.Socket(sysAF_ROUTE, sysSOCK_RAW, sysAF_UNSPEC)
53}
54
55// TestMonitorAndParseRIB leaks a worker goroutine and a socket
56// descriptor but that's intentional.
57func TestMonitorAndParseRIB(t *testing.T) {
58	if testing.Short() || os.Getuid() != 0 {
59		t.Skip("must be root")
60	}
61
62	if rtmonErr != nil {
63		t.Fatal(rtmonErr)
64	}
65
66	// We suppose that using an IPv4 link-local address and the
67	// dot1Q ID for Token Ring and FDDI doesn't harm anyone.
68	pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"}
69	if err := pv.configure(1002); err != nil {
70		t.Skip(err)
71	}
72	if err := pv.setup(); err != nil {
73		t.Skip(err)
74	}
75	pv.teardown()
76
77	go func() {
78		b := make([]byte, os.Getpagesize())
79		for {
80			// There's no easy way to unblock this read
81			// call because the routing message exchange
82			// over routing socket is a connectionless
83			// message-oriented protocol, no control plane
84			// for signaling connectivity, and we cannot
85			// use the net package of standard library due
86			// to the lack of support for routing socket
87			// and circular dependency.
88			n, err := syscall.Read(rtmonSock, b)
89			if err != nil {
90				return
91			}
92			ms, err := ParseRIB(0, b[:n])
93			if err != nil {
94				t.Error(err)
95				return
96			}
97			ss, err := msgs(ms).validate()
98			if err != nil {
99				t.Error(err)
100				return
101			}
102			for _, s := range ss {
103				t.Log(s)
104			}
105		}
106	}()
107
108	for _, vid := range []int{1002, 1003, 1004, 1005} {
109		pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"}
110		if err := pv.configure(vid); err != nil {
111			t.Fatal(err)
112		}
113		if err := pv.setup(); err != nil {
114			t.Fatal(err)
115		}
116		time.Sleep(200 * time.Millisecond)
117		if err := pv.teardown(); err != nil {
118			t.Fatal(err)
119		}
120		time.Sleep(200 * time.Millisecond)
121	}
122}
123
124func TestParseRIBWithFuzz(t *testing.T) {
125	for _, fuzz := range []string{
126		"0\x00\x05\x050000000000000000" +
127			"00000000000000000000" +
128			"00000000000000000000" +
129			"00000000000000000000" +
130			"0000000000000\x02000000" +
131			"00000000",
132		"\x02\x00\x05\f0000000000000000" +
133			"0\x0200000000000000",
134		"\x02\x00\x05\x100000000000000\x1200" +
135			"0\x00\xff\x00",
136		"\x02\x00\x05\f0000000000000000" +
137			"0\x12000\x00\x02\x0000",
138		"\x00\x00\x00\x01\x00",
139		"00000",
140	} {
141		for typ := RIBType(0); typ < 256; typ++ {
142			ParseRIB(typ, []byte(fuzz))
143		}
144	}
145}
146
147func TestRouteMessage(t *testing.T) {
148	s, err := syscall.Socket(sysAF_ROUTE, sysSOCK_RAW, sysAF_UNSPEC)
149	if err != nil {
150		t.Fatal(err)
151	}
152	defer syscall.Close(s)
153
154	var ms []RouteMessage
155	for _, af := range []int{sysAF_INET, sysAF_INET6} {
156		if _, err := fetchAndParseRIB(af, sysNET_RT_DUMP); err != nil {
157			t.Log(err)
158			continue
159		}
160		switch af {
161		case sysAF_INET:
162			ms = append(ms, []RouteMessage{
163				{
164					Type: sysRTM_GET,
165					Addrs: []Addr{
166						sysRTAX_DST:     &Inet4Addr{IP: [4]byte{127, 0, 0, 1}},
167						sysRTAX_GATEWAY: nil,
168						sysRTAX_NETMASK: nil,
169						sysRTAX_GENMASK: nil,
170						sysRTAX_IFP:     &LinkAddr{},
171						sysRTAX_IFA:     &Inet4Addr{},
172						sysRTAX_AUTHOR:  nil,
173						sysRTAX_BRD:     &Inet4Addr{},
174					},
175				},
176				{
177					Type: sysRTM_GET,
178					Addrs: []Addr{
179						sysRTAX_DST: &Inet4Addr{IP: [4]byte{127, 0, 0, 1}},
180					},
181				},
182			}...)
183		case sysAF_INET6:
184			ms = append(ms, []RouteMessage{
185				{
186					Type: sysRTM_GET,
187					Addrs: []Addr{
188						sysRTAX_DST:     &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}},
189						sysRTAX_GATEWAY: nil,
190						sysRTAX_NETMASK: nil,
191						sysRTAX_GENMASK: nil,
192						sysRTAX_IFP:     &LinkAddr{},
193						sysRTAX_IFA:     &Inet6Addr{},
194						sysRTAX_AUTHOR:  nil,
195						sysRTAX_BRD:     &Inet6Addr{},
196					},
197				},
198				{
199					Type: sysRTM_GET,
200					Addrs: []Addr{
201						sysRTAX_DST: &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}},
202					},
203				},
204			}...)
205		}
206	}
207	for i, m := range ms {
208		m.ID = uintptr(os.Getpid())
209		m.Seq = i + 1
210		wb, err := m.Marshal()
211		if err != nil {
212			t.Fatalf("%v: %v", m, err)
213		}
214		if _, err := syscall.Write(s, wb); err != nil {
215			t.Fatalf("%v: %v", m, err)
216		}
217		rb := make([]byte, os.Getpagesize())
218		n, err := syscall.Read(s, rb)
219		if err != nil {
220			t.Fatalf("%v: %v", m, err)
221		}
222		rms, err := ParseRIB(0, rb[:n])
223		if err != nil {
224			t.Fatalf("%v: %v", m, err)
225		}
226		for _, rm := range rms {
227			if rm, ok := rm.(*RouteMessage); ok && rm.Err != nil {
228				t.Errorf("%v: %v", m, rm.Err)
229			}
230		}
231		ss, err := msgs(rms).validate()
232		if err != nil {
233			t.Fatalf("%v: %v", m, err)
234		}
235		for _, s := range ss {
236			t.Log(s)
237		}
238	}
239}
240