OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / lif / address.go
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 // +build solaris
6
7 package lif
8
9 import (
10         "errors"
11         "unsafe"
12 )
13
14 // An Addr represents an address associated with packet routing.
15 type Addr interface {
16         // Family returns an address family.
17         Family() int
18 }
19
20 // An Inet4Addr represents an internet address for IPv4.
21 type Inet4Addr struct {
22         IP        [4]byte // IP address
23         PrefixLen int     // address prefix length
24 }
25
26 // Family implements the Family method of Addr interface.
27 func (a *Inet4Addr) Family() int { return sysAF_INET }
28
29 // An Inet6Addr represents an internet address for IPv6.
30 type Inet6Addr struct {
31         IP        [16]byte // IP address
32         PrefixLen int      // address prefix length
33         ZoneID    int      // zone identifier
34 }
35
36 // Family implements the Family method of Addr interface.
37 func (a *Inet6Addr) Family() int { return sysAF_INET6 }
38
39 // Addrs returns a list of interface addresses.
40 //
41 // The provided af must be an address family and name must be a data
42 // link name. The zero value of af or name means a wildcard.
43 func Addrs(af int, name string) ([]Addr, error) {
44         eps, err := newEndpoints(af)
45         if len(eps) == 0 {
46                 return nil, err
47         }
48         defer func() {
49                 for _, ep := range eps {
50                         ep.close()
51                 }
52         }()
53         lls, err := links(eps, name)
54         if len(lls) == 0 {
55                 return nil, err
56         }
57         var as []Addr
58         for _, ll := range lls {
59                 var lifr lifreq
60                 for i := 0; i < len(ll.Name); i++ {
61                         lifr.Name[i] = int8(ll.Name[i])
62                 }
63                 for _, ep := range eps {
64                         ioc := int64(sysSIOCGLIFADDR)
65                         err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifr))
66                         if err != nil {
67                                 continue
68                         }
69                         sa := (*sockaddrStorage)(unsafe.Pointer(&lifr.Lifru[0]))
70                         l := int(nativeEndian.Uint32(lifr.Lifru1[:4]))
71                         if l == 0 {
72                                 continue
73                         }
74                         switch sa.Family {
75                         case sysAF_INET:
76                                 a := &Inet4Addr{PrefixLen: l}
77                                 copy(a.IP[:], lifr.Lifru[4:8])
78                                 as = append(as, a)
79                         case sysAF_INET6:
80                                 a := &Inet6Addr{PrefixLen: l, ZoneID: int(nativeEndian.Uint32(lifr.Lifru[24:28]))}
81                                 copy(a.IP[:], lifr.Lifru[8:24])
82                                 as = append(as, a)
83                         }
84                 }
85         }
86         return as, nil
87 }
88
89 func parseLinkAddr(b []byte) ([]byte, error) {
90         nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
91         l := 4 + nlen + alen + slen
92         if len(b) < l {
93                 return nil, errors.New("invalid address")
94         }
95         b = b[4:]
96         var addr []byte
97         if nlen > 0 {
98                 b = b[nlen:]
99         }
100         if alen > 0 {
101                 addr = make([]byte, alen)
102                 copy(addr, b[:alen])
103         }
104         return addr, nil
105 }