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