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