github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/syscall/route_bsd.go (about) 1 // Copyright 2011 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 syscall 8 9 import ( 10 "runtime" 11 "unsafe" 12 ) 13 14 var ( 15 freebsdConfArch string // "machine $arch" line in kern.conftxt on freebsd 16 minRoutingSockaddrLen = rsaAlignOf(0) 17 ) 18 19 // Round the length of a raw sockaddr up to align it properly. 20 func rsaAlignOf(salen int) int { 21 salign := sizeofPtr 22 if darwin64Bit { 23 // Darwin kernels require 32-bit aligned access to 24 // routing facilities. 25 salign = 4 26 } else if netbsd32Bit { 27 // NetBSD 6 and beyond kernels require 64-bit aligned 28 // access to routing facilities. 29 salign = 8 30 } else if runtime.GOOS == "freebsd" { 31 // In the case of kern.supported_archs="amd64 i386", 32 // we need to know the underlying kernel's 33 // architecture because the alignment for routing 34 // facilities are set at the build time of the kernel. 35 if freebsdConfArch == "amd64" { 36 salign = 8 37 } 38 } 39 if salen == 0 { 40 return salign 41 } 42 return (salen + salign - 1) & ^(salign - 1) 43 } 44 45 // parseSockaddrLink parses b as a datalink socket address. 46 func parseSockaddrLink(b []byte) (*SockaddrDatalink, error) { 47 if len(b) < 8 { 48 return nil, EINVAL 49 } 50 sa, _, err := parseLinkLayerAddr(b[4:]) 51 if err != nil { 52 return nil, err 53 } 54 rsa := (*RawSockaddrDatalink)(unsafe.Pointer(&b[0])) 55 sa.Len = rsa.Len 56 sa.Family = rsa.Family 57 sa.Index = rsa.Index 58 return sa, nil 59 } 60 61 // parseLinkLayerAddr parses b as a datalink socket address in 62 // conventional BSD kernel form. 63 func parseLinkLayerAddr(b []byte) (*SockaddrDatalink, int, error) { 64 // The encoding looks like the following: 65 // +----------------------------+ 66 // | Type (1 octet) | 67 // +----------------------------+ 68 // | Name length (1 octet) | 69 // +----------------------------+ 70 // | Address length (1 octet) | 71 // +----------------------------+ 72 // | Selector length (1 octet) | 73 // +----------------------------+ 74 // | Data (variable) | 75 // +----------------------------+ 76 type linkLayerAddr struct { 77 Type byte 78 Nlen byte 79 Alen byte 80 Slen byte 81 } 82 lla := (*linkLayerAddr)(unsafe.Pointer(&b[0])) 83 l := 4 + int(lla.Nlen) + int(lla.Alen) + int(lla.Slen) 84 if len(b) < l { 85 return nil, 0, EINVAL 86 } 87 b = b[4:] 88 sa := &SockaddrDatalink{Type: lla.Type, Nlen: lla.Nlen, Alen: lla.Alen, Slen: lla.Slen} 89 for i := 0; len(sa.Data) > i && i < l-4; i++ { 90 sa.Data[i] = int8(b[i]) 91 } 92 return sa, rsaAlignOf(l), nil 93 } 94 95 // parseSockaddrInet parses b as an internet socket address. 96 func parseSockaddrInet(b []byte, family byte) (Sockaddr, error) { 97 switch family { 98 case AF_INET: 99 if len(b) < SizeofSockaddrInet4 { 100 return nil, EINVAL 101 } 102 rsa := (*RawSockaddrAny)(unsafe.Pointer(&b[0])) 103 return anyToSockaddr(rsa) 104 case AF_INET6: 105 if len(b) < SizeofSockaddrInet6 { 106 return nil, EINVAL 107 } 108 rsa := (*RawSockaddrAny)(unsafe.Pointer(&b[0])) 109 return anyToSockaddr(rsa) 110 default: 111 return nil, EINVAL 112 } 113 } 114 115 const ( 116 offsetofInet4 = int(unsafe.Offsetof(RawSockaddrInet4{}.Addr)) 117 offsetofInet6 = int(unsafe.Offsetof(RawSockaddrInet6{}.Addr)) 118 ) 119 120 // parseNetworkLayerAddr parses b as an internet socket address in 121 // conventional BSD kernel form. 122 func parseNetworkLayerAddr(b []byte, family byte) (Sockaddr, error) { 123 // The encoding looks similar to the NLRI encoding. 124 // +----------------------------+ 125 // | Length (1 octet) | 126 // +----------------------------+ 127 // | Address prefix (variable) | 128 // +----------------------------+ 129 // 130 // The differences between the kernel form and the NLRI 131 // encoding are: 132 // 133 // - The length field of the kernel form indicates the prefix 134 // length in bytes, not in bits 135 // 136 // - In the kernel form, zero value of the length field 137 // doesn't mean 0.0.0.0/0 or ::/0 138 // 139 // - The kernel form appends leading bytes to the prefix field 140 // to make the <length, prefix> tuple to be conformed with 141 // the routing message boundary 142 l := int(rsaAlignOf(int(b[0]))) 143 if len(b) < l { 144 return nil, EINVAL 145 } 146 // Don't reorder case expressions. 147 // The case expressions for IPv6 must come first. 148 switch { 149 case b[0] == SizeofSockaddrInet6: 150 sa := &SockaddrInet6{} 151 copy(sa.Addr[:], b[offsetofInet6:]) 152 return sa, nil 153 case family == AF_INET6: 154 sa := &SockaddrInet6{} 155 if l-1 < offsetofInet6 { 156 copy(sa.Addr[:], b[1:l]) 157 } else { 158 copy(sa.Addr[:], b[l-offsetofInet6:l]) 159 } 160 return sa, nil 161 case b[0] == SizeofSockaddrInet4: 162 sa := &SockaddrInet4{} 163 copy(sa.Addr[:], b[offsetofInet4:]) 164 return sa, nil 165 default: // an old fashion, AF_UNSPEC or unknown means AF_INET 166 sa := &SockaddrInet4{} 167 if l-1 < offsetofInet4 { 168 copy(sa.Addr[:], b[1:l]) 169 } else { 170 copy(sa.Addr[:], b[l-offsetofInet4:l]) 171 } 172 return sa, nil 173 } 174 } 175 176 // RouteRIB returns routing information base, as known as RIB, 177 // which consists of network facility information, states and 178 // parameters. 179 // 180 // Deprecated: Use golang.org/x/net/route instead. 181 func RouteRIB(facility, param int) ([]byte, error) { 182 mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)} 183 // Find size. 184 n := uintptr(0) 185 if err := sysctl(mib, nil, &n, nil, 0); err != nil { 186 return nil, err 187 } 188 if n == 0 { 189 return nil, nil 190 } 191 tab := make([]byte, n) 192 if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil { 193 return nil, err 194 } 195 return tab[:n], nil 196 } 197 198 // RoutingMessage represents a routing message. 199 // 200 // Deprecated: Use golang.org/x/net/route instead. 201 type RoutingMessage interface { 202 sockaddr() ([]Sockaddr, error) 203 } 204 205 const anyMessageLen = int(unsafe.Sizeof(anyMessage{})) 206 207 type anyMessage struct { 208 Msglen uint16 209 Version uint8 210 Type uint8 211 } 212 213 // RouteMessage represents a routing message containing routing 214 // entries. 215 // 216 // Deprecated: Use golang.org/x/net/route instead. 217 type RouteMessage struct { 218 Header RtMsghdr 219 Data []byte 220 } 221 222 func (m *RouteMessage) sockaddr() ([]Sockaddr, error) { 223 var sas [RTAX_MAX]Sockaddr 224 b := m.Data[:] 225 family := uint8(AF_UNSPEC) 226 for i := uint(0); i < RTAX_MAX && len(b) >= minRoutingSockaddrLen; i++ { 227 if m.Header.Addrs&(1<<i) == 0 { 228 continue 229 } 230 rsa := (*RawSockaddr)(unsafe.Pointer(&b[0])) 231 switch rsa.Family { 232 case AF_LINK: 233 sa, err := parseSockaddrLink(b) 234 if err != nil { 235 return nil, err 236 } 237 sas[i] = sa 238 b = b[rsaAlignOf(int(rsa.Len)):] 239 case AF_INET, AF_INET6: 240 sa, err := parseSockaddrInet(b, rsa.Family) 241 if err != nil { 242 return nil, err 243 } 244 sas[i] = sa 245 b = b[rsaAlignOf(int(rsa.Len)):] 246 family = rsa.Family 247 default: 248 sa, err := parseNetworkLayerAddr(b, family) 249 if err != nil { 250 return nil, err 251 } 252 sas[i] = sa 253 b = b[rsaAlignOf(int(b[0])):] 254 } 255 } 256 return sas[:], nil 257 } 258 259 // InterfaceMessage represents a routing message containing 260 // network interface entries. 261 // 262 // Deprecated: Use golang.org/x/net/route instead. 263 type InterfaceMessage struct { 264 Header IfMsghdr 265 Data []byte 266 } 267 268 func (m *InterfaceMessage) sockaddr() ([]Sockaddr, error) { 269 var sas [RTAX_MAX]Sockaddr 270 if m.Header.Addrs&RTA_IFP == 0 { 271 return nil, nil 272 } 273 sa, err := parseSockaddrLink(m.Data[:]) 274 if err != nil { 275 return nil, err 276 } 277 sas[RTAX_IFP] = sa 278 return sas[:], nil 279 } 280 281 // InterfaceAddrMessage represents a routing message containing 282 // network interface address entries. 283 // 284 // Deprecated: Use golang.org/x/net/route instead. 285 type InterfaceAddrMessage struct { 286 Header IfaMsghdr 287 Data []byte 288 } 289 290 func (m *InterfaceAddrMessage) sockaddr() ([]Sockaddr, error) { 291 var sas [RTAX_MAX]Sockaddr 292 b := m.Data[:] 293 family := uint8(AF_UNSPEC) 294 for i := uint(0); i < RTAX_MAX && len(b) >= minRoutingSockaddrLen; i++ { 295 if m.Header.Addrs&(1<<i) == 0 { 296 continue 297 } 298 rsa := (*RawSockaddr)(unsafe.Pointer(&b[0])) 299 switch rsa.Family { 300 case AF_LINK: 301 sa, err := parseSockaddrLink(b) 302 if err != nil { 303 return nil, err 304 } 305 sas[i] = sa 306 b = b[rsaAlignOf(int(rsa.Len)):] 307 case AF_INET, AF_INET6: 308 sa, err := parseSockaddrInet(b, rsa.Family) 309 if err != nil { 310 return nil, err 311 } 312 sas[i] = sa 313 b = b[rsaAlignOf(int(rsa.Len)):] 314 family = rsa.Family 315 default: 316 sa, err := parseNetworkLayerAddr(b, family) 317 if err != nil { 318 return nil, err 319 } 320 sas[i] = sa 321 b = b[rsaAlignOf(int(b[0])):] 322 } 323 } 324 return sas[:], nil 325 } 326 327 // ParseRoutingMessage parses b as routing messages and returns the 328 // slice containing the RoutingMessage interfaces. 329 // 330 // Deprecated: Use golang.org/x/net/route instead. 331 func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) { 332 nmsgs, nskips := 0, 0 333 for len(b) >= anyMessageLen { 334 nmsgs++ 335 any := (*anyMessage)(unsafe.Pointer(&b[0])) 336 if any.Version != RTM_VERSION { 337 b = b[any.Msglen:] 338 continue 339 } 340 if m := any.toRoutingMessage(b); m == nil { 341 nskips++ 342 } else { 343 msgs = append(msgs, m) 344 } 345 b = b[any.Msglen:] 346 } 347 // We failed to parse any of the messages - version mismatch? 348 if nmsgs != len(msgs)+nskips { 349 return nil, EINVAL 350 } 351 return msgs, nil 352 } 353 354 // ParseRoutingSockaddr parses msg's payload as raw sockaddrs and 355 // returns the slice containing the Sockaddr interfaces. 356 // 357 // Deprecated: Use golang.org/x/net/route instead. 358 func ParseRoutingSockaddr(msg RoutingMessage) ([]Sockaddr, error) { 359 sas, err := msg.sockaddr() 360 if err != nil { 361 return nil, err 362 } 363 return sas, nil 364 }