Source file src/internal/routebsd/address.go

     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  string // 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 string
    77  	var addr []byte
    78  	if nlen > 0 {
    79  		name = string(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  

View as plain text