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