|  | // Copyright 2016 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // +build solaris | 
|  |  | 
|  | package lif | 
|  |  | 
|  | import ( | 
|  | "errors" | 
|  | "unsafe" | 
|  | ) | 
|  |  | 
|  | // An Addr represents an address associated with packet routing. | 
|  | type Addr interface { | 
|  | // Family returns an address family. | 
|  | Family() int | 
|  | } | 
|  |  | 
|  | // An Inet4Addr represents an internet address for IPv4. | 
|  | type Inet4Addr struct { | 
|  | IP        [4]byte // IP address | 
|  | PrefixLen int     // address prefix length | 
|  | } | 
|  |  | 
|  | // Family implements the Family method of Addr interface. | 
|  | func (a *Inet4Addr) Family() int { return sysAF_INET } | 
|  |  | 
|  | // An Inet6Addr represents an internet address for IPv6. | 
|  | type Inet6Addr struct { | 
|  | IP        [16]byte // IP address | 
|  | PrefixLen int      // address prefix length | 
|  | ZoneID    int      // zone identifier | 
|  | } | 
|  |  | 
|  | // Family implements the Family method of Addr interface. | 
|  | func (a *Inet6Addr) Family() int { return sysAF_INET6 } | 
|  |  | 
|  | // Addrs returns a list of interface addresses. | 
|  | // | 
|  | // The provided af must be an address family and name must be a data | 
|  | // link name. The zero value of af or name means a wildcard. | 
|  | func Addrs(af int, name string) ([]Addr, error) { | 
|  | eps, err := newEndpoints(af) | 
|  | if len(eps) == 0 { | 
|  | return nil, err | 
|  | } | 
|  | defer func() { | 
|  | for _, ep := range eps { | 
|  | ep.close() | 
|  | } | 
|  | }() | 
|  | lls, err := links(eps, name) | 
|  | if len(lls) == 0 { | 
|  | return nil, err | 
|  | } | 
|  | var as []Addr | 
|  | for _, ll := range lls { | 
|  | var lifr lifreq | 
|  | for i := 0; i < len(ll.Name); i++ { | 
|  | lifr.Name[i] = int8(ll.Name[i]) | 
|  | } | 
|  | for _, ep := range eps { | 
|  | ioc := int64(sysSIOCGLIFADDR) | 
|  | err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifr)) | 
|  | if err != nil { | 
|  | continue | 
|  | } | 
|  | sa := (*sockaddrStorage)(unsafe.Pointer(&lifr.Lifru[0])) | 
|  | l := int(littleEndian.Uint32(lifr.Lifru1[:4])) | 
|  | if l == 0 { | 
|  | continue | 
|  | } | 
|  | switch sa.Family { | 
|  | case sysAF_INET: | 
|  | a := &Inet4Addr{PrefixLen: l} | 
|  | copy(a.IP[:], lifr.Lifru[4:8]) | 
|  | as = append(as, a) | 
|  | case sysAF_INET6: | 
|  | a := &Inet6Addr{PrefixLen: l, ZoneID: int(littleEndian.Uint32(lifr.Lifru[24:28]))} | 
|  | copy(a.IP[:], lifr.Lifru[8:24]) | 
|  | as = append(as, a) | 
|  | } | 
|  | } | 
|  | } | 
|  | return as, nil | 
|  | } | 
|  |  | 
|  | func parseLinkAddr(b []byte) ([]byte, error) { | 
|  | nlen, alen, slen := int(b[1]), int(b[2]), int(b[3]) | 
|  | l := 4 + nlen + alen + slen | 
|  | if len(b) < l { | 
|  | return nil, errors.New("invalid address") | 
|  | } | 
|  | b = b[4:] | 
|  | var addr []byte | 
|  | if nlen > 0 { | 
|  | b = b[nlen:] | 
|  | } | 
|  | if alen > 0 { | 
|  | addr = make([]byte, alen) | 
|  | copy(addr, b[:alen]) | 
|  | } | 
|  | return addr, nil | 
|  | } |