github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/internal/x/net/lif/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  // +build solaris
     6  
     7  package lif
     8  
     9  import (
    10  	"errors"
    11  	"unsafe"
    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  // An Inet4Addr represents an internet address for IPv4.
    21  type Inet4Addr struct {
    22  	IP        [4]byte // IP address
    23  	PrefixLen int     // address prefix length
    24  }
    25  
    26  // Family implements the Family method of Addr interface.
    27  func (a *Inet4Addr) Family() int { return sysAF_INET }
    28  
    29  // An Inet6Addr represents an internet address for IPv6.
    30  type Inet6Addr struct {
    31  	IP        [16]byte // IP address
    32  	PrefixLen int      // address prefix length
    33  	ZoneID    int      // zone identifier
    34  }
    35  
    36  // Family implements the Family method of Addr interface.
    37  func (a *Inet6Addr) Family() int { return sysAF_INET6 }
    38  
    39  // Addrs returns a list of interface addresses.
    40  //
    41  // The provided af must be an address family and name must be a data
    42  // link name. The zero value of af or name means a wildcard.
    43  func Addrs(af int, name string) ([]Addr, error) {
    44  	eps, err := newEndpoints(af)
    45  	if len(eps) == 0 {
    46  		return nil, err
    47  	}
    48  	defer func() {
    49  		for _, ep := range eps {
    50  			ep.close()
    51  		}
    52  	}()
    53  	lls, err := links(eps, name)
    54  	if len(lls) == 0 {
    55  		return nil, err
    56  	}
    57  	var as []Addr
    58  	for _, ll := range lls {
    59  		var lifr lifreq
    60  		for i := 0; i < len(ll.Name); i++ {
    61  			lifr.Name[i] = int8(ll.Name[i])
    62  		}
    63  		for _, ep := range eps {
    64  			ioc := int64(sysSIOCGLIFADDR)
    65  			err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifr))
    66  			if err != nil {
    67  				continue
    68  			}
    69  			sa := (*sockaddrStorage)(unsafe.Pointer(&lifr.Lifru[0]))
    70  			l := int(nativeEndian.Uint32(lifr.Lifru1[:4]))
    71  			if l == 0 {
    72  				continue
    73  			}
    74  			switch sa.Family {
    75  			case sysAF_INET:
    76  				a := &Inet4Addr{PrefixLen: l}
    77  				copy(a.IP[:], lifr.Lifru[4:8])
    78  				as = append(as, a)
    79  			case sysAF_INET6:
    80  				a := &Inet6Addr{PrefixLen: l, ZoneID: int(nativeEndian.Uint32(lifr.Lifru[24:28]))}
    81  				copy(a.IP[:], lifr.Lifru[8:24])
    82  				as = append(as, a)
    83  			}
    84  		}
    85  	}
    86  	return as, nil
    87  }
    88  
    89  func parseLinkAddr(b []byte) ([]byte, error) {
    90  	nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
    91  	l := 4 + nlen + alen + slen
    92  	if len(b) < l {
    93  		return nil, errors.New("invalid address")
    94  	}
    95  	b = b[4:]
    96  	var addr []byte
    97  	if nlen > 0 {
    98  		b = b[nlen:]
    99  	}
   100  	if alen > 0 {
   101  		addr = make([]byte, alen)
   102  		copy(addr, b[:alen])
   103  	}
   104  	return addr, nil
   105  }