github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/route/route_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 // +build darwin dragonfly freebsd netbsd openbsd 7 8 package route 9 10 import ( 11 "fmt" 12 "os/exec" 13 "runtime" 14 ) 15 16 func (m *RouteMessage) String() string { 17 return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[12:16]))) 18 } 19 20 func (m *InterfaceMessage) String() string { 21 var attrs addrAttrs 22 if runtime.GOOS == "openbsd" { 23 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16])) 24 } else { 25 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8])) 26 } 27 return fmt.Sprintf("%s", attrs) 28 } 29 30 func (m *InterfaceAddrMessage) String() string { 31 var attrs addrAttrs 32 if runtime.GOOS == "openbsd" { 33 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16])) 34 } else { 35 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8])) 36 } 37 return fmt.Sprintf("%s", attrs) 38 } 39 40 func (m *InterfaceMulticastAddrMessage) String() string { 41 return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[4:8]))) 42 } 43 44 func (m *InterfaceAnnounceMessage) String() string { 45 what := "<nil>" 46 switch m.What { 47 case 0: 48 what = "arrival" 49 case 1: 50 what = "departure" 51 } 52 return fmt.Sprintf("(%d %s %s)", m.Index, m.Name, what) 53 } 54 55 func (m *InterfaceMetrics) String() string { 56 return fmt.Sprintf("(type=%d mtu=%d)", m.Type, m.MTU) 57 } 58 59 func (m *RouteMetrics) String() string { 60 return fmt.Sprintf("(pmtu=%d)", m.PathMTU) 61 } 62 63 type addrAttrs uint 64 65 var addrAttrNames = [...]string{ 66 "dst", 67 "gateway", 68 "netmask", 69 "genmask", 70 "ifp", 71 "ifa", 72 "author", 73 "brd", 74 "df:mpls1-n:tag-o:src", // mpls1 for dragonfly, tag for netbsd, src for openbsd 75 "df:mpls2-o:srcmask", // mpls2 for dragonfly, srcmask for openbsd 76 "df:mpls3-o:label", // mpls3 for dragonfly, label for openbsd 77 "o:bfd", // bfd for openbsd 78 "o:dns", // dns for openbsd 79 "o:static", // static for openbsd 80 "o:search", // search for openbsd 81 } 82 83 func (attrs addrAttrs) String() string { 84 var s string 85 for i, name := range addrAttrNames { 86 if attrs&(1<<uint(i)) != 0 { 87 if s != "" { 88 s += "|" 89 } 90 s += name 91 } 92 } 93 if s == "" { 94 return "<nil>" 95 } 96 return s 97 } 98 99 type msgs []Message 100 101 func (ms msgs) validate() ([]string, error) { 102 var ss []string 103 for _, m := range ms { 104 switch m := m.(type) { 105 case *RouteMessage: 106 if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[12:16]))); err != nil { 107 return nil, err 108 } 109 sys := m.Sys() 110 if sys == nil { 111 return nil, fmt.Errorf("no sys for %s", m.String()) 112 } 113 ss = append(ss, m.String()+" "+syss(sys).String()+" "+addrs(m.Addrs).String()) 114 case *InterfaceMessage: 115 var attrs addrAttrs 116 if runtime.GOOS == "openbsd" { 117 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16])) 118 } else { 119 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8])) 120 } 121 if err := addrs(m.Addrs).match(attrs); err != nil { 122 return nil, err 123 } 124 sys := m.Sys() 125 if sys == nil { 126 return nil, fmt.Errorf("no sys for %s", m.String()) 127 } 128 ss = append(ss, m.String()+" "+syss(sys).String()+" "+addrs(m.Addrs).String()) 129 case *InterfaceAddrMessage: 130 var attrs addrAttrs 131 if runtime.GOOS == "openbsd" { 132 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16])) 133 } else { 134 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8])) 135 } 136 if err := addrs(m.Addrs).match(attrs); err != nil { 137 return nil, err 138 } 139 ss = append(ss, m.String()+" "+addrs(m.Addrs).String()) 140 case *InterfaceMulticastAddrMessage: 141 if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[4:8]))); err != nil { 142 return nil, err 143 } 144 ss = append(ss, m.String()+" "+addrs(m.Addrs).String()) 145 case *InterfaceAnnounceMessage: 146 ss = append(ss, m.String()) 147 default: 148 ss = append(ss, fmt.Sprintf("%+v", m)) 149 } 150 } 151 return ss, nil 152 } 153 154 type syss []Sys 155 156 func (sys syss) String() string { 157 var s string 158 for _, sy := range sys { 159 switch sy := sy.(type) { 160 case *InterfaceMetrics: 161 if len(s) > 0 { 162 s += " " 163 } 164 s += sy.String() 165 case *RouteMetrics: 166 if len(s) > 0 { 167 s += " " 168 } 169 s += sy.String() 170 } 171 } 172 return s 173 } 174 175 type addrFamily int 176 177 func (af addrFamily) String() string { 178 switch af { 179 case sysAF_UNSPEC: 180 return "unspec" 181 case sysAF_LINK: 182 return "link" 183 case sysAF_INET: 184 return "inet4" 185 case sysAF_INET6: 186 return "inet6" 187 default: 188 return fmt.Sprintf("%d", af) 189 } 190 } 191 192 const hexDigit = "0123456789abcdef" 193 194 type llAddr []byte 195 196 func (a llAddr) String() string { 197 if len(a) == 0 { 198 return "" 199 } 200 buf := make([]byte, 0, len(a)*3-1) 201 for i, b := range a { 202 if i > 0 { 203 buf = append(buf, ':') 204 } 205 buf = append(buf, hexDigit[b>>4]) 206 buf = append(buf, hexDigit[b&0xF]) 207 } 208 return string(buf) 209 } 210 211 type ipAddr []byte 212 213 func (a ipAddr) String() string { 214 if len(a) == 0 { 215 return "<nil>" 216 } 217 if len(a) == 4 { 218 return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3]) 219 } 220 if len(a) == 16 { 221 return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]) 222 } 223 s := make([]byte, len(a)*2) 224 for i, tn := range a { 225 s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf] 226 } 227 return string(s) 228 } 229 230 func (a *LinkAddr) String() string { 231 name := a.Name 232 if name == "" { 233 name = "<nil>" 234 } 235 lla := llAddr(a.Addr).String() 236 if lla == "" { 237 lla = "<nil>" 238 } 239 return fmt.Sprintf("(%v %d %s %s)", addrFamily(a.Family()), a.Index, name, lla) 240 } 241 242 func (a *Inet4Addr) String() string { 243 return fmt.Sprintf("(%v %v)", addrFamily(a.Family()), ipAddr(a.IP[:])) 244 } 245 246 func (a *Inet6Addr) String() string { 247 return fmt.Sprintf("(%v %v %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.ZoneID) 248 } 249 250 func (a *DefaultAddr) String() string { 251 return fmt.Sprintf("(%v %s)", addrFamily(a.Family()), ipAddr(a.Raw[2:]).String()) 252 } 253 254 type addrs []Addr 255 256 func (as addrs) String() string { 257 var s string 258 for _, a := range as { 259 if a == nil { 260 continue 261 } 262 if len(s) > 0 { 263 s += " " 264 } 265 switch a := a.(type) { 266 case *LinkAddr: 267 s += a.String() 268 case *Inet4Addr: 269 s += a.String() 270 case *Inet6Addr: 271 s += a.String() 272 case *DefaultAddr: 273 s += a.String() 274 } 275 } 276 if s == "" { 277 return "<nil>" 278 } 279 return s 280 } 281 282 func (as addrs) match(attrs addrAttrs) error { 283 var ts addrAttrs 284 af := sysAF_UNSPEC 285 for i := range as { 286 if as[i] != nil { 287 ts |= 1 << uint(i) 288 } 289 switch as[i].(type) { 290 case *Inet4Addr: 291 if af == sysAF_UNSPEC { 292 af = sysAF_INET 293 } 294 if af != sysAF_INET { 295 return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af)) 296 } 297 case *Inet6Addr: 298 if af == sysAF_UNSPEC { 299 af = sysAF_INET6 300 } 301 if af != sysAF_INET6 { 302 return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af)) 303 } 304 } 305 } 306 if ts != attrs && ts > attrs { 307 return fmt.Errorf("%v not included in %v", ts, attrs) 308 } 309 return nil 310 } 311 312 func fetchAndParseRIB(af int, typ RIBType) ([]Message, error) { 313 b, err := FetchRIB(af, typ, 0) 314 if err != nil { 315 return nil, fmt.Errorf("%v %d %v", addrFamily(af), typ, err) 316 } 317 ms, err := ParseRIB(typ, b) 318 if err != nil { 319 return nil, fmt.Errorf("%v %d %v", addrFamily(af), typ, err) 320 } 321 return ms, nil 322 } 323 324 // propVirtual is a proprietary virtual network interface. 325 type propVirtual struct { 326 name string 327 addr, mask string 328 setupCmds []*exec.Cmd 329 teardownCmds []*exec.Cmd 330 } 331 332 func (pv *propVirtual) setup() error { 333 for _, cmd := range pv.setupCmds { 334 if err := cmd.Run(); err != nil { 335 pv.teardown() 336 return err 337 } 338 } 339 return nil 340 } 341 342 func (pv *propVirtual) teardown() error { 343 for _, cmd := range pv.teardownCmds { 344 if err := cmd.Run(); err != nil { 345 return err 346 } 347 } 348 return nil 349 } 350 351 func (pv *propVirtual) configure(suffix int) error { 352 if runtime.GOOS == "openbsd" { 353 pv.name = fmt.Sprintf("vether%d", suffix) 354 } else { 355 pv.name = fmt.Sprintf("vlan%d", suffix) 356 } 357 xname, err := exec.LookPath("ifconfig") 358 if err != nil { 359 return err 360 } 361 pv.setupCmds = append(pv.setupCmds, &exec.Cmd{ 362 Path: xname, 363 Args: []string{"ifconfig", pv.name, "create"}, 364 }) 365 if runtime.GOOS == "netbsd" { 366 // NetBSD requires an underlying dot1Q-capable network 367 // interface. 368 pv.setupCmds = append(pv.setupCmds, &exec.Cmd{ 369 Path: xname, 370 Args: []string{"ifconfig", pv.name, "vlan", fmt.Sprintf("%d", suffix&0xfff), "vlanif", "wm0"}, 371 }) 372 } 373 pv.setupCmds = append(pv.setupCmds, &exec.Cmd{ 374 Path: xname, 375 Args: []string{"ifconfig", pv.name, "inet", pv.addr, "netmask", pv.mask}, 376 }) 377 pv.teardownCmds = append(pv.teardownCmds, &exec.Cmd{ 378 Path: xname, 379 Args: []string{"ifconfig", pv.name, "destroy"}, 380 }) 381 return nil 382 }