address.mx raw

   1  // Copyright 2016 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 routebsd
   8  
   9  import (
  10  	"net/netip"
  11  	"runtime"
  12  	"syscall"
  13  )
  14  
  15  // An Addr represents an address associated with packet routing.
  16  type Addr interface {
  17  	// Family returns an address family.
  18  	Family() int
  19  }
  20  
  21  // A LinkAddr represents a link-layer address.
  22  type LinkAddr struct {
  23  	Index int    // interface index when attached
  24  	Name  []byte // interface name when attached
  25  	Addr  []byte // link-layer address when attached
  26  }
  27  
  28  // Family implements the Family method of Addr interface.
  29  func (a *LinkAddr) Family() int { return syscall.AF_LINK }
  30  
  31  func parseLinkAddr(b []byte) (Addr, error) {
  32  	if len(b) < 8 {
  33  		return nil, errInvalidAddr
  34  	}
  35  	_, a, err := parseKernelLinkAddr(syscall.AF_LINK, b[4:])
  36  	if err != nil {
  37  		return nil, err
  38  	}
  39  	a.(*LinkAddr).Index = int(nativeEndian.Uint16(b[2:4]))
  40  	return a, nil
  41  }
  42  
  43  // parseKernelLinkAddr parses b as a link-layer address in
  44  // conventional BSD kernel form.
  45  func parseKernelLinkAddr(_ int, b []byte) (int, Addr, error) {
  46  	// The encoding looks like the following:
  47  	// +----------------------------+
  48  	// | Type             (1 octet) |
  49  	// +----------------------------+
  50  	// | Name length      (1 octet) |
  51  	// +----------------------------+
  52  	// | Address length   (1 octet) |
  53  	// +----------------------------+
  54  	// | Selector length  (1 octet) |
  55  	// +----------------------------+
  56  	// | Data            (variable) |
  57  	// +----------------------------+
  58  	//
  59  	// On some platforms, all-bit-one of length field means "don't
  60  	// care".
  61  	nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
  62  	if nlen == 0xff {
  63  		nlen = 0
  64  	}
  65  	if alen == 0xff {
  66  		alen = 0
  67  	}
  68  	if slen == 0xff {
  69  		slen = 0
  70  	}
  71  	l := 4 + nlen + alen + slen
  72  	if len(b) < l {
  73  		return 0, nil, errInvalidAddr
  74  	}
  75  	data := b[4:]
  76  	var name []byte
  77  	var addr []byte
  78  	if nlen > 0 {
  79  		name = []byte(data[:nlen])
  80  		data = data[nlen:]
  81  	}
  82  	if alen > 0 {
  83  		addr = data[:alen]
  84  		data = data[alen:]
  85  	}
  86  	return l, &LinkAddr{Name: name, Addr: addr}, nil
  87  }
  88  
  89  // An InetAddr represent an internet address using IPv4 or IPv6.
  90  type InetAddr struct {
  91  	IP netip.Addr
  92  }
  93  
  94  func (a *InetAddr) Family() int {
  95  	if a.IP.Is4() {
  96  		return syscall.AF_INET
  97  	} else {
  98  		return syscall.AF_INET6
  99  	}
 100  }
 101  
 102  // parseInetAddr parses b as an internet address for IPv4 or IPv6.
 103  func parseInetAddr(af int, b []byte) (Addr, error) {
 104  	const (
 105  		off4    = 4  // offset of in_addr
 106  		off6    = 8  // offset of in6_addr
 107  		ipv4Len = 4  // length of IPv4 address in bytes
 108  		ipv6Len = 16 // length of IPv6 address in bytes
 109  	)
 110  	switch af {
 111  	case syscall.AF_INET:
 112  		if len(b) < (off4+1) || len(b) < int(b[0]) {
 113  			return nil, errInvalidAddr
 114  		}
 115  		sockAddrLen := int(b[0])
 116  		var ip [ipv4Len]byte
 117  		if sockAddrLen != 0 {
 118  			// Calculate how many bytes of the address to copy:
 119  			// either full IPv4 length or the available length.
 120  			n := off4 + ipv4Len
 121  			if sockAddrLen < n {
 122  				n = sockAddrLen
 123  			}
 124  			copy(ip[:], b[off4:n])
 125  		}
 126  		a := &InetAddr{
 127  			IP: netip.AddrFrom4(ip),
 128  		}
 129  		return a, nil
 130  	case syscall.AF_INET6:
 131  		if len(b) < (off6+1) || len(b) < int(b[0]) {
 132  			return nil, errInvalidAddr
 133  		}
 134  		var ip [ipv6Len]byte
 135  		sockAddrLen := int(b[0])
 136  		if sockAddrLen != 0 {
 137  			n := off6 + ipv6Len
 138  			if sockAddrLen < n {
 139  				n = sockAddrLen
 140  			}
 141  			copy(ip[:], b[off6:n])
 142  			if ip[0] == 0xfe && ip[1]&0xc0 == 0x80 || ip[0] == 0xff && (ip[1]&0x0f == 0x01 || ip[1]&0x0f == 0x02) {
 143  				// KAME based IPv6 protocol stack usually
 144  				// embeds the interface index in the
 145  				// interface-local or link-local address as
 146  				// the kernel-internal form.
 147  				id := int(bigEndian.Uint16(ip[2:4]))
 148  				if id != 0 {
 149  					ip[2], ip[3] = 0, 0
 150  				}
 151  			}
 152  		}
 153  		// The kernel can provide an integer zone ID.
 154  		// We ignore it.
 155  		a := &InetAddr{
 156  			IP: netip.AddrFrom16(ip),
 157  		}
 158  		return a, nil
 159  	default:
 160  		return nil, errInvalidAddr
 161  	}
 162  }
 163  
 164  // parseKernelInetAddr parses b as an internet address in conventional
 165  // BSD kernel form.
 166  func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
 167  	// The encoding looks similar to the NLRI encoding.
 168  	// +----------------------------+
 169  	// | Length           (1 octet) |
 170  	// +----------------------------+
 171  	// | Address prefix  (variable) |
 172  	// +----------------------------+
 173  	//
 174  	// The differences between the kernel form and the NLRI
 175  	// encoding are:
 176  	//
 177  	// - The length field of the kernel form indicates the prefix
 178  	//   length in bytes, not in bits
 179  	//
 180  	// - In the kernel form, zero value of the length field
 181  	//   doesn't mean 0.0.0.0/0 or ::/0
 182  	//
 183  	// - The kernel form appends leading bytes to the prefix field
 184  	//   to make the <length, prefix> tuple to be conformed with
 185  	//   the routing message boundary
 186  	l := int(b[0])
 187  	if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
 188  		// On Darwin, an address in the kernel form is also
 189  		// used as a message filler.
 190  		if l == 0 || len(b) > roundup(l) {
 191  			l = roundup(l)
 192  		}
 193  	} else {
 194  		l = roundup(l)
 195  	}
 196  	if len(b) < l {
 197  		return 0, nil, errInvalidAddr
 198  	}
 199  	// Don't reorder case expressions.
 200  	// The case expressions for IPv6 must come first.
 201  	const (
 202  		off4 = 4 // offset of in_addr
 203  		off6 = 8 // offset of in6_addr
 204  	)
 205  	switch {
 206  	case b[0] == syscall.SizeofSockaddrInet6:
 207  		a := &InetAddr{
 208  			IP: netip.AddrFrom16([16]byte(b[off6 : off6+16])),
 209  		}
 210  		return int(b[0]), a, nil
 211  	case af == syscall.AF_INET6:
 212  		var ab [16]byte
 213  		if l-1 < off6 {
 214  			copy(ab[:], b[1:l])
 215  		} else {
 216  			copy(ab[:], b[l-off6:l])
 217  		}
 218  		a := &InetAddr{
 219  			IP: netip.AddrFrom16(ab),
 220  		}
 221  		return int(b[0]), a, nil
 222  	case b[0] == syscall.SizeofSockaddrInet4:
 223  		a := &InetAddr{
 224  			IP: netip.AddrFrom4([4]byte(b[off4 : off4+4])),
 225  		}
 226  		return int(b[0]), a, nil
 227  	default: // an old fashion, AF_UNSPEC or unknown means AF_INET
 228  		var ab [4]byte
 229  		if l-1 < off4 {
 230  			copy(ab[:], b[1:l])
 231  		} else {
 232  			copy(ab[:], b[l-off4:l])
 233  		}
 234  		a := &InetAddr{
 235  			IP: netip.AddrFrom4(ab),
 236  		}
 237  		return int(b[0]), a, nil
 238  	}
 239  }
 240  
 241  func parseAddrs(attrs uint, b []byte) ([]Addr, error) {
 242  	var as [syscall.RTAX_MAX]Addr
 243  	af := int(syscall.AF_UNSPEC)
 244  	for i := uint(0); i < syscall.RTAX_MAX && len(b) >= roundup(0); i++ {
 245  		if attrs&(1<<i) == 0 {
 246  			continue
 247  		}
 248  		if i <= syscall.RTAX_BRD {
 249  			switch b[1] {
 250  			case syscall.AF_LINK:
 251  				a, err := parseLinkAddr(b)
 252  				if err != nil {
 253  					return nil, err
 254  				}
 255  				as[i] = a
 256  				l := roundup(int(b[0]))
 257  				if len(b) < l {
 258  					return nil, errMessageTooShort
 259  				}
 260  				b = b[l:]
 261  			case syscall.AF_INET, syscall.AF_INET6:
 262  				af = int(b[1])
 263  				a, err := parseInetAddr(af, b)
 264  				if err != nil {
 265  					return nil, err
 266  				}
 267  				as[i] = a
 268  				l := roundup(int(b[0]))
 269  				if len(b) < l {
 270  					return nil, errMessageTooShort
 271  				}
 272  				b = b[l:]
 273  			default:
 274  				l, a, err := parseKernelInetAddr(af, b)
 275  				if err != nil {
 276  					return nil, err
 277  				}
 278  				as[i] = a
 279  				ll := roundup(l)
 280  				if len(b) < ll {
 281  					b = b[l:]
 282  				} else {
 283  					b = b[ll:]
 284  				}
 285  			}
 286  		} else {
 287  			// Skip unknown addresses.
 288  			l := roundup(int(b[0]))
 289  			if len(b) < l {
 290  				return nil, errMessageTooShort
 291  			}
 292  			b = b[l:]
 293  		}
 294  	}
 295  	// The only remaining bytes in b should be alignment.
 296  	// However, under some circumstances DragonFly BSD appears to put
 297  	// more addresses in the message than are indicated in the address
 298  	// bitmask, so don't check for this.
 299  	return as[:], nil
 300  }
 301