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 solaris
   6  
   7  package lif
   8  
   9  import (
  10  	"errors"
  11  	"syscall"
  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 syscall.AF_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 syscall.AF_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(syscall.SIOCGLIFADDR)
  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 syscall.AF_INET:
  77  				a := &Inet4Addr{PrefixLen: l}
  78  				copy(a.IP[:], lifr.Lifru[4:8])
  79  				as = append(as, a)
  80  			case syscall.AF_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 = []byte{:alen}
 103  		copy(addr, b[:alen])
 104  	}
 105  	return addr, nil
 106  }
 107