| // 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. |
| |
| //go:build solaris |
| |
| package lif |
| |
| import ( |
| "errors" |
| "syscall" |
| "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 syscall.AF_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 syscall.AF_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(syscall.SIOCGLIFADDR) |
| err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifr)) |
| if err != nil { |
| continue |
| } |
| sa := (*sockaddrStorage)(unsafe.Pointer(&lifr.Lifru[0])) |
| l := int(nativeEndian.Uint32(lifr.Lifru1[:4])) |
| if l == 0 { |
| continue |
| } |
| switch sa.Family { |
| case syscall.AF_INET: |
| a := &Inet4Addr{PrefixLen: l} |
| copy(a.IP[:], lifr.Lifru[4:8]) |
| as = append(as, a) |
| case syscall.AF_INET6: |
| a := &Inet6Addr{PrefixLen: l, ZoneID: int(nativeEndian.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 |
| } |