OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / lif / link.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 "unsafe"
10
11 // A Link represents logical data link information.
12 //
13 // It also represents base information for logical network interface.
14 // On Solaris, each logical network interface represents network layer
15 // adjacency information and the interface has a only single network
16 // address or address pair for tunneling. It's usual that multiple
17 // logical network interfaces share the same logical data link.
18 type Link struct {
19         Name  string // name, equivalent to IP interface name
20         Index int    // index, equivalent to IP interface index
21         Type  int    // type
22         Flags int    // flags
23         MTU   int    // maximum transmission unit, basically link MTU but may differ between IP address families
24         Addr  []byte // address
25 }
26
27 func (ll *Link) fetch(s uintptr) {
28         var lifr lifreq
29         for i := 0; i < len(ll.Name); i++ {
30                 lifr.Name[i] = int8(ll.Name[i])
31         }
32         ioc := int64(sysSIOCGLIFINDEX)
33         if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
34                 ll.Index = int(nativeEndian.Uint32(lifr.Lifru[:4]))
35         }
36         ioc = int64(sysSIOCGLIFFLAGS)
37         if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
38                 ll.Flags = int(nativeEndian.Uint64(lifr.Lifru[:8]))
39         }
40         ioc = int64(sysSIOCGLIFMTU)
41         if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
42                 ll.MTU = int(nativeEndian.Uint32(lifr.Lifru[:4]))
43         }
44         switch ll.Type {
45         case sysIFT_IPV4, sysIFT_IPV6, sysIFT_6TO4:
46         default:
47                 ioc = int64(sysSIOCGLIFHWADDR)
48                 if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
49                         ll.Addr, _ = parseLinkAddr(lifr.Lifru[4:])
50                 }
51         }
52 }
53
54 // Links returns a list of logical data links.
55 //
56 // The provided af must be an address family and name must be a data
57 // link name. The zero value of af or name means a wildcard.
58 func Links(af int, name string) ([]Link, error) {
59         eps, err := newEndpoints(af)
60         if len(eps) == 0 {
61                 return nil, err
62         }
63         defer func() {
64                 for _, ep := range eps {
65                         ep.close()
66                 }
67         }()
68         return links(eps, name)
69 }
70
71 func links(eps []endpoint, name string) ([]Link, error) {
72         var lls []Link
73         lifn := lifnum{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
74         lifc := lifconf{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
75         for _, ep := range eps {
76                 lifn.Family = uint16(ep.af)
77                 ioc := int64(sysSIOCGLIFNUM)
78                 if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifn)); err != nil {
79                         continue
80                 }
81                 if lifn.Count == 0 {
82                         continue
83                 }
84                 b := make([]byte, lifn.Count*sizeofLifreq)
85                 lifc.Family = uint16(ep.af)
86                 lifc.Len = lifn.Count * sizeofLifreq
87                 if len(lifc.Lifcu) == 8 {
88                         nativeEndian.PutUint64(lifc.Lifcu[:], uint64(uintptr(unsafe.Pointer(&b[0]))))
89                 } else {
90                         nativeEndian.PutUint32(lifc.Lifcu[:], uint32(uintptr(unsafe.Pointer(&b[0]))))
91                 }
92                 ioc = int64(sysSIOCGLIFCONF)
93                 if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifc)); err != nil {
94                         continue
95                 }
96                 nb := make([]byte, 32) // see LIFNAMSIZ in net/if.h
97                 for i := 0; i < int(lifn.Count); i++ {
98                         lifr := (*lifreq)(unsafe.Pointer(&b[i*sizeofLifreq]))
99                         for i := 0; i < 32; i++ {
100                                 if lifr.Name[i] == 0 {
101                                         nb = nb[:i]
102                                         break
103                                 }
104                                 nb[i] = byte(lifr.Name[i])
105                         }
106                         llname := string(nb)
107                         nb = nb[:32]
108                         if isDupLink(lls, llname) || name != "" && name != llname {
109                                 continue
110                         }
111                         ll := Link{Name: llname, Type: int(lifr.Type)}
112                         ll.fetch(ep.s)
113                         lls = append(lls, ll)
114                 }
115         }
116         return lls, nil
117 }
118
119 func isDupLink(lls []Link, name string) bool {
120         for _, ll := range lls {
121                 if ll.Name == name {
122                         return true
123                 }
124         }
125         return false
126 }