...

Source file src/pkg/syscall/route_bsd.go

     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 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	}
   365	

View as plain text