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