route_bsd.mx raw

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