Home | History | Annotate | Download | only in lif
      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 }
    106