github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/src/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 // +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 messeage 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 func RouteRIB(facility, param int) ([]byte, error) { 180 mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)} 181 // Find size. 182 n := uintptr(0) 183 if err := sysctl(mib, nil, &n, nil, 0); err != nil { 184 return nil, err 185 } 186 if n == 0 { 187 return nil, nil 188 } 189 tab := make([]byte, n) 190 if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil { 191 return nil, err 192 } 193 return tab[:n], nil 194 } 195 196 // RoutingMessage represents a routing message. 197 type RoutingMessage interface { 198 sockaddr() ([]Sockaddr, error) 199 } 200 201 const anyMessageLen = int(unsafe.Sizeof(anyMessage{})) 202 203 type anyMessage struct { 204 Msglen uint16 205 Version uint8 206 Type uint8 207 } 208 209 // RouteMessage represents a routing message containing routing 210 // entries. 211 type RouteMessage struct { 212 Header RtMsghdr 213 Data []byte 214 } 215 216 func (m *RouteMessage) sockaddr() ([]Sockaddr, error) { 217 var sas [RTAX_MAX]Sockaddr 218 b := m.Data[:] 219 family := uint8(AF_UNSPEC) 220 for i := uint(0); i < RTAX_MAX && len(b) >= minRoutingSockaddrLen; i++ { 221 if m.Header.Addrs&(1<<i) == 0 { 222 continue 223 } 224 rsa := (*RawSockaddr)(unsafe.Pointer(&b[0])) 225 switch rsa.Family { 226 case AF_LINK: 227 sa, err := parseSockaddrLink(b) 228 if err != nil { 229 return nil, err 230 } 231 sas[i] = sa 232 b = b[rsaAlignOf(int(rsa.Len)):] 233 case AF_INET, AF_INET6: 234 sa, err := parseSockaddrInet(b, rsa.Family) 235 if err != nil { 236 return nil, err 237 } 238 sas[i] = sa 239 b = b[rsaAlignOf(int(rsa.Len)):] 240 family = rsa.Family 241 default: 242 sa, err := parseNetworkLayerAddr(b, family) 243 if err != nil { 244 return nil, err 245 } 246 sas[i] = sa 247 b = b[rsaAlignOf(int(b[0])):] 248 } 249 } 250 return sas[:], nil 251 } 252 253 // InterfaceMessage represents a routing message containing 254 // network interface entries. 255 type InterfaceMessage struct { 256 Header IfMsghdr 257 Data []byte 258 } 259 260 func (m *InterfaceMessage) sockaddr() ([]Sockaddr, error) { 261 var sas [RTAX_MAX]Sockaddr 262 if m.Header.Addrs&RTA_IFP == 0 { 263 return nil, nil 264 } 265 sa, err := parseSockaddrLink(m.Data[:]) 266 if err != nil { 267 return nil, err 268 } 269 sas[RTAX_IFP] = sa 270 return sas[:], nil 271 } 272 273 // InterfaceAddrMessage represents a routing message containing 274 // network interface address entries. 275 type InterfaceAddrMessage struct { 276 Header IfaMsghdr 277 Data []byte 278 } 279 280 func (m *InterfaceAddrMessage) sockaddr() ([]Sockaddr, error) { 281 var sas [RTAX_MAX]Sockaddr 282 b := m.Data[:] 283 family := uint8(AF_UNSPEC) 284 for i := uint(0); i < RTAX_MAX && len(b) >= minRoutingSockaddrLen; i++ { 285 if m.Header.Addrs&(1<<i) == 0 { 286 continue 287 } 288 rsa := (*RawSockaddr)(unsafe.Pointer(&b[0])) 289 switch rsa.Family { 290 case AF_LINK: 291 sa, err := parseSockaddrLink(b) 292 if err != nil { 293 return nil, err 294 } 295 sas[i] = sa 296 b = b[rsaAlignOf(int(rsa.Len)):] 297 case AF_INET, AF_INET6: 298 sa, err := parseSockaddrInet(b, rsa.Family) 299 if err != nil { 300 return nil, err 301 } 302 sas[i] = sa 303 b = b[rsaAlignOf(int(rsa.Len)):] 304 family = rsa.Family 305 default: 306 sa, err := parseNetworkLayerAddr(b, family) 307 if err != nil { 308 return nil, err 309 } 310 sas[i] = sa 311 b = b[rsaAlignOf(int(b[0])):] 312 } 313 } 314 return sas[:], nil 315 } 316 317 // ParseRoutingMessage parses b as routing messages and returns the 318 // slice containing the RoutingMessage interfaces. 319 func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) { 320 nmsgs, nskips := 0, 0 321 for len(b) >= anyMessageLen { 322 nmsgs++ 323 any := (*anyMessage)(unsafe.Pointer(&b[0])) 324 if any.Version != RTM_VERSION { 325 b = b[any.Msglen:] 326 continue 327 } 328 if m := any.toRoutingMessage(b); m == nil { 329 nskips++ 330 } else { 331 msgs = append(msgs, m) 332 } 333 b = b[any.Msglen:] 334 } 335 // We failed to parse any of the messages - version mismatch? 336 if nmsgs != len(msgs)+nskips { 337 return nil, EINVAL 338 } 339 return msgs, nil 340 } 341 342 // ParseRoutingMessage parses msg's payload as raw sockaddrs and 343 // returns the slice containing the Sockaddr interfaces. 344 func ParseRoutingSockaddr(msg RoutingMessage) ([]Sockaddr, error) { 345 sas, err := msg.sockaddr() 346 if err != nil { 347 return nil, err 348 } 349 return sas, nil 350 }