golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/route/address.go (about)

     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 route
     8  
     9  import (
    10  	"runtime"
    11  	"syscall"
    12  )
    13  
    14  // An Addr represents an address associated with packet routing.
    15  type Addr interface {
    16  	// Family returns an address family.
    17  	Family() int
    18  }
    19  
    20  // A LinkAddr represents a link-layer address.
    21  type LinkAddr struct {
    22  	Index int    // interface index when attached
    23  	Name  string // interface name when attached
    24  	Addr  []byte // link-layer address when attached
    25  }
    26  
    27  // Family implements the Family method of Addr interface.
    28  func (a *LinkAddr) Family() int { return syscall.AF_LINK }
    29  
    30  func (a *LinkAddr) lenAndSpace() (int, int) {
    31  	l := 8 + len(a.Name) + len(a.Addr)
    32  	return l, roundup(l)
    33  }
    34  
    35  func (a *LinkAddr) marshal(b []byte) (int, error) {
    36  	l, ll := a.lenAndSpace()
    37  	if len(b) < ll {
    38  		return 0, errShortBuffer
    39  	}
    40  	nlen, alen := len(a.Name), len(a.Addr)
    41  	if nlen > 255 || alen > 255 {
    42  		return 0, errInvalidAddr
    43  	}
    44  	b[0] = byte(l)
    45  	b[1] = syscall.AF_LINK
    46  	if a.Index > 0 {
    47  		nativeEndian.PutUint16(b[2:4], uint16(a.Index))
    48  	}
    49  	data := b[8:]
    50  	if nlen > 0 {
    51  		b[5] = byte(nlen)
    52  		copy(data[:nlen], a.Name)
    53  		data = data[nlen:]
    54  	}
    55  	if alen > 0 {
    56  		b[6] = byte(alen)
    57  		copy(data[:alen], a.Addr)
    58  		data = data[alen:]
    59  	}
    60  	return ll, nil
    61  }
    62  
    63  func parseLinkAddr(b []byte) (Addr, error) {
    64  	if len(b) < 8 {
    65  		return nil, errInvalidAddr
    66  	}
    67  	_, a, err := parseKernelLinkAddr(syscall.AF_LINK, b[4:])
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	a.(*LinkAddr).Index = int(nativeEndian.Uint16(b[2:4]))
    72  	return a, nil
    73  }
    74  
    75  // parseKernelLinkAddr parses b as a link-layer address in
    76  // conventional BSD kernel form.
    77  func parseKernelLinkAddr(_ int, b []byte) (int, Addr, error) {
    78  	// The encoding looks like the following:
    79  	// +----------------------------+
    80  	// | Type             (1 octet) |
    81  	// +----------------------------+
    82  	// | Name length      (1 octet) |
    83  	// +----------------------------+
    84  	// | Address length   (1 octet) |
    85  	// +----------------------------+
    86  	// | Selector length  (1 octet) |
    87  	// +----------------------------+
    88  	// | Data            (variable) |
    89  	// +----------------------------+
    90  	//
    91  	// On some platforms, all-bit-one of length field means "don't
    92  	// care".
    93  	nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
    94  	if nlen == 0xff {
    95  		nlen = 0
    96  	}
    97  	if alen == 0xff {
    98  		alen = 0
    99  	}
   100  	if slen == 0xff {
   101  		slen = 0
   102  	}
   103  	l := 4 + nlen + alen + slen
   104  	if len(b) < l {
   105  		return 0, nil, errInvalidAddr
   106  	}
   107  	data := b[4:]
   108  	var name string
   109  	var addr []byte
   110  	if nlen > 0 {
   111  		name = string(data[:nlen])
   112  		data = data[nlen:]
   113  	}
   114  	if alen > 0 {
   115  		addr = data[:alen]
   116  		data = data[alen:]
   117  	}
   118  	return l, &LinkAddr{Name: name, Addr: addr}, nil
   119  }
   120  
   121  // An Inet4Addr represents an internet address for IPv4.
   122  type Inet4Addr struct {
   123  	IP [4]byte // IP address
   124  }
   125  
   126  // Family implements the Family method of Addr interface.
   127  func (a *Inet4Addr) Family() int { return syscall.AF_INET }
   128  
   129  func (a *Inet4Addr) lenAndSpace() (int, int) {
   130  	return sizeofSockaddrInet, roundup(sizeofSockaddrInet)
   131  }
   132  
   133  func (a *Inet4Addr) marshal(b []byte) (int, error) {
   134  	l, ll := a.lenAndSpace()
   135  	if len(b) < ll {
   136  		return 0, errShortBuffer
   137  	}
   138  	b[0] = byte(l)
   139  	b[1] = syscall.AF_INET
   140  	copy(b[4:8], a.IP[:])
   141  	return ll, nil
   142  }
   143  
   144  // An Inet6Addr represents an internet address for IPv6.
   145  type Inet6Addr struct {
   146  	IP     [16]byte // IP address
   147  	ZoneID int      // zone identifier
   148  }
   149  
   150  // Family implements the Family method of Addr interface.
   151  func (a *Inet6Addr) Family() int { return syscall.AF_INET6 }
   152  
   153  func (a *Inet6Addr) lenAndSpace() (int, int) {
   154  	return sizeofSockaddrInet6, roundup(sizeofSockaddrInet6)
   155  }
   156  
   157  func (a *Inet6Addr) marshal(b []byte) (int, error) {
   158  	l, ll := a.lenAndSpace()
   159  	if len(b) < ll {
   160  		return 0, errShortBuffer
   161  	}
   162  	b[0] = byte(l)
   163  	b[1] = syscall.AF_INET6
   164  	copy(b[8:24], a.IP[:])
   165  	if a.ZoneID > 0 {
   166  		nativeEndian.PutUint32(b[24:28], uint32(a.ZoneID))
   167  	}
   168  	return ll, nil
   169  }
   170  
   171  // parseInetAddr parses b as an internet address for IPv4 or IPv6.
   172  func parseInetAddr(af int, b []byte) (Addr, error) {
   173  	switch af {
   174  	case syscall.AF_INET:
   175  		if len(b) < sizeofSockaddrInet {
   176  			return nil, errInvalidAddr
   177  		}
   178  		a := &Inet4Addr{}
   179  		copy(a.IP[:], b[4:8])
   180  		return a, nil
   181  	case syscall.AF_INET6:
   182  		if len(b) < sizeofSockaddrInet6 {
   183  			return nil, errInvalidAddr
   184  		}
   185  		a := &Inet6Addr{ZoneID: int(nativeEndian.Uint32(b[24:28]))}
   186  		copy(a.IP[:], b[8:24])
   187  		if a.IP[0] == 0xfe && a.IP[1]&0xc0 == 0x80 || a.IP[0] == 0xff && (a.IP[1]&0x0f == 0x01 || a.IP[1]&0x0f == 0x02) {
   188  			// KAME based IPv6 protocol stack usually
   189  			// embeds the interface index in the
   190  			// interface-local or link-local address as
   191  			// the kernel-internal form.
   192  			id := int(bigEndian.Uint16(a.IP[2:4]))
   193  			if id != 0 {
   194  				a.ZoneID = id
   195  				a.IP[2], a.IP[3] = 0, 0
   196  			}
   197  		}
   198  		return a, nil
   199  	default:
   200  		return nil, errInvalidAddr
   201  	}
   202  }
   203  
   204  // parseKernelInetAddr parses b as an internet address in conventional
   205  // BSD kernel form.
   206  func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
   207  	// The encoding looks similar to the NLRI encoding.
   208  	// +----------------------------+
   209  	// | Length           (1 octet) |
   210  	// +----------------------------+
   211  	// | Address prefix  (variable) |
   212  	// +----------------------------+
   213  	//
   214  	// The differences between the kernel form and the NLRI
   215  	// encoding are:
   216  	//
   217  	// - The length field of the kernel form indicates the prefix
   218  	//   length in bytes, not in bits
   219  	//
   220  	// - In the kernel form, zero value of the length field
   221  	//   doesn't mean 0.0.0.0/0 or ::/0
   222  	//
   223  	// - The kernel form appends leading bytes to the prefix field
   224  	//   to make the <length, prefix> tuple to be conformed with
   225  	//   the routing message boundary
   226  	l := int(b[0])
   227  	if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
   228  		// On Darwin, an address in the kernel form is also
   229  		// used as a message filler.
   230  		if l == 0 || len(b) > roundup(l) {
   231  			l = roundup(l)
   232  		}
   233  	} else {
   234  		l = roundup(l)
   235  	}
   236  	if len(b) < l {
   237  		return 0, nil, errInvalidAddr
   238  	}
   239  	// Don't reorder case expressions.
   240  	// The case expressions for IPv6 must come first.
   241  	const (
   242  		off4 = 4 // offset of in_addr
   243  		off6 = 8 // offset of in6_addr
   244  	)
   245  	switch {
   246  	case b[0] == sizeofSockaddrInet6:
   247  		a := &Inet6Addr{}
   248  		copy(a.IP[:], b[off6:off6+16])
   249  		return int(b[0]), a, nil
   250  	case af == syscall.AF_INET6:
   251  		a := &Inet6Addr{}
   252  		if l-1 < off6 {
   253  			copy(a.IP[:], b[1:l])
   254  		} else {
   255  			copy(a.IP[:], b[l-off6:l])
   256  		}
   257  		return int(b[0]), a, nil
   258  	case b[0] == sizeofSockaddrInet:
   259  		a := &Inet4Addr{}
   260  		copy(a.IP[:], b[off4:off4+4])
   261  		return int(b[0]), a, nil
   262  	default: // an old fashion, AF_UNSPEC or unknown means AF_INET
   263  		a := &Inet4Addr{}
   264  		if l-1 < off4 {
   265  			copy(a.IP[:], b[1:l])
   266  		} else {
   267  			copy(a.IP[:], b[l-off4:l])
   268  		}
   269  		return int(b[0]), a, nil
   270  	}
   271  }
   272  
   273  // A DefaultAddr represents an address of various operating
   274  // system-specific features.
   275  type DefaultAddr struct {
   276  	af  int
   277  	Raw []byte // raw format of address
   278  }
   279  
   280  // Family implements the Family method of Addr interface.
   281  func (a *DefaultAddr) Family() int { return a.af }
   282  
   283  func (a *DefaultAddr) lenAndSpace() (int, int) {
   284  	l := len(a.Raw)
   285  	return l, roundup(l)
   286  }
   287  
   288  func (a *DefaultAddr) marshal(b []byte) (int, error) {
   289  	l, ll := a.lenAndSpace()
   290  	if len(b) < ll {
   291  		return 0, errShortBuffer
   292  	}
   293  	if l > 255 {
   294  		return 0, errInvalidAddr
   295  	}
   296  	b[1] = byte(l)
   297  	copy(b[:l], a.Raw)
   298  	return ll, nil
   299  }
   300  
   301  func parseDefaultAddr(b []byte) (Addr, error) {
   302  	if len(b) < 2 || len(b) < int(b[0]) {
   303  		return nil, errInvalidAddr
   304  	}
   305  	a := &DefaultAddr{af: int(b[1]), Raw: b[:b[0]]}
   306  	return a, nil
   307  }
   308  
   309  func addrsSpace(as []Addr) int {
   310  	var l int
   311  	for _, a := range as {
   312  		switch a := a.(type) {
   313  		case *LinkAddr:
   314  			_, ll := a.lenAndSpace()
   315  			l += ll
   316  		case *Inet4Addr:
   317  			_, ll := a.lenAndSpace()
   318  			l += ll
   319  		case *Inet6Addr:
   320  			_, ll := a.lenAndSpace()
   321  			l += ll
   322  		case *DefaultAddr:
   323  			_, ll := a.lenAndSpace()
   324  			l += ll
   325  		}
   326  	}
   327  	return l
   328  }
   329  
   330  // marshalAddrs marshals as and returns a bitmap indicating which
   331  // address is stored in b.
   332  func marshalAddrs(b []byte, as []Addr) (uint, error) {
   333  	var attrs uint
   334  	for i, a := range as {
   335  		switch a := a.(type) {
   336  		case *LinkAddr:
   337  			l, err := a.marshal(b)
   338  			if err != nil {
   339  				return 0, err
   340  			}
   341  			b = b[l:]
   342  			attrs |= 1 << uint(i)
   343  		case *Inet4Addr:
   344  			l, err := a.marshal(b)
   345  			if err != nil {
   346  				return 0, err
   347  			}
   348  			b = b[l:]
   349  			attrs |= 1 << uint(i)
   350  		case *Inet6Addr:
   351  			l, err := a.marshal(b)
   352  			if err != nil {
   353  				return 0, err
   354  			}
   355  			b = b[l:]
   356  			attrs |= 1 << uint(i)
   357  		case *DefaultAddr:
   358  			l, err := a.marshal(b)
   359  			if err != nil {
   360  				return 0, err
   361  			}
   362  			b = b[l:]
   363  			attrs |= 1 << uint(i)
   364  		}
   365  	}
   366  	return attrs, nil
   367  }
   368  
   369  func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ([]Addr, error) {
   370  	var as [syscall.RTAX_MAX]Addr
   371  	af := int(syscall.AF_UNSPEC)
   372  	for i := uint(0); i < syscall.RTAX_MAX && len(b) >= roundup(0); i++ {
   373  		if attrs&(1<<i) == 0 {
   374  			continue
   375  		}
   376  		if i <= syscall.RTAX_BRD {
   377  			switch b[1] {
   378  			case syscall.AF_LINK:
   379  				a, err := parseLinkAddr(b)
   380  				if err != nil {
   381  					return nil, err
   382  				}
   383  				as[i] = a
   384  				l := roundup(int(b[0]))
   385  				if len(b) < l {
   386  					return nil, errMessageTooShort
   387  				}
   388  				b = b[l:]
   389  			case syscall.AF_INET, syscall.AF_INET6:
   390  				af = int(b[1])
   391  				a, err := parseInetAddr(af, b)
   392  				if err != nil {
   393  					return nil, err
   394  				}
   395  				as[i] = a
   396  				l := roundup(int(b[0]))
   397  				if len(b) < l {
   398  					return nil, errMessageTooShort
   399  				}
   400  				b = b[l:]
   401  			default:
   402  				l, a, err := fn(af, b)
   403  				if err != nil {
   404  					return nil, err
   405  				}
   406  				as[i] = a
   407  				ll := roundup(l)
   408  				if len(b) < ll {
   409  					b = b[l:]
   410  				} else {
   411  					b = b[ll:]
   412  				}
   413  			}
   414  		} else {
   415  			a, err := parseDefaultAddr(b)
   416  			if err != nil {
   417  				return nil, err
   418  			}
   419  			as[i] = a
   420  			l := roundup(int(b[0]))
   421  			if len(b) < l {
   422  				return nil, errMessageTooShort
   423  			}
   424  			b = b[l:]
   425  		}
   426  	}
   427  	// The only remaining bytes in b should be alignment.
   428  	// However, under some circumstances DragonFly BSD appears to put
   429  	// more addresses in the message than are indicated in the address
   430  	// bitmask, so don't check for this.
   431  	return as[:], nil
   432  }