...
1
2
3
4
5
6
7 package lif
8
9 import (
10 "errors"
11 "syscall"
12 "unsafe"
13 )
14
15
16 type Addr interface {
17
18 Family() int
19 }
20
21
22 type Inet4Addr struct {
23 IP [4]byte
24 PrefixLen int
25 }
26
27
28 func (a *Inet4Addr) Family() int { return syscall.AF_INET }
29
30
31 type Inet6Addr struct {
32 IP [16]byte
33 PrefixLen int
34 ZoneID int
35 }
36
37
38 func (a *Inet6Addr) Family() int { return syscall.AF_INET6 }
39
40
41
42
43
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 = make([]byte, alen)
103 copy(addr, b[:alen])
104 }
105 return addr, nil
106 }
107
View as plain text