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