106 lines
2.4 KiB
Go
106 lines
2.4 KiB
Go
|
// 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
|
||
|
}
|