Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Network interface identification for Linux | 5 // Network interface identification for Linux |
6 | 6 |
7 package net | 7 package net |
8 | 8 |
9 import ( | 9 import ( |
10 "os" | 10 "os" |
11 "syscall" | 11 "syscall" |
12 "unsafe" | 12 "unsafe" |
13 ) | 13 ) |
14 | 14 |
15 // If the ifindex is zero, interfaceTable returns mappings of all | 15 // If the ifindex is zero, interfaceTable returns mappings of all |
16 // network interfaces. Otherwise it returns a mapping of a specific | 16 // network interfaces. Otherwise it returns a mapping of a specific |
17 // interface. | 17 // interface. |
18 func interfaceTable(ifindex int) ([]Interface, error) { | 18 func interfaceTable(ifindex int) ([]Interface, error) { |
19 tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC) | 19 tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC) |
20 if err != nil { | 20 if err != nil { |
21 return nil, os.NewSyscallError("netlink rib", err) | 21 return nil, os.NewSyscallError("netlink rib", err) |
22 } | 22 } |
23 | |
24 msgs, err := syscall.ParseNetlinkMessage(tab) | 23 msgs, err := syscall.ParseNetlinkMessage(tab) |
25 if err != nil { | 24 if err != nil { |
26 return nil, os.NewSyscallError("netlink message", err) | 25 return nil, os.NewSyscallError("netlink message", err) |
27 } | 26 } |
28 | |
29 var ift []Interface | 27 var ift []Interface |
28 done: | |
30 for _, m := range msgs { | 29 for _, m := range msgs { |
31 switch m.Header.Type { | 30 switch m.Header.Type { |
32 case syscall.NLMSG_DONE: | 31 case syscall.NLMSG_DONE: |
33 » » » goto done | 32 » » » break done |
rsc
2013/02/19 15:20:31
done is weird label for a for loop. If you want to
mikio
2013/02/19 23:18:14
Done.
| |
34 case syscall.RTM_NEWLINK: | 33 case syscall.RTM_NEWLINK: |
35 ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0])) | 34 ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0])) |
36 if ifindex == 0 || ifindex == int(ifim.Index) { | 35 if ifindex == 0 || ifindex == int(ifim.Index) { |
37 attrs, err := syscall.ParseNetlinkRouteAttr(&m) | 36 attrs, err := syscall.ParseNetlinkRouteAttr(&m) |
38 if err != nil { | 37 if err != nil { |
39 return nil, os.NewSyscallError("netlink routeattr", err) | 38 return nil, os.NewSyscallError("netlink routeattr", err) |
40 } | 39 } |
41 ifi := newLink(ifim, attrs) | 40 ifi := newLink(ifim, attrs) |
42 ift = append(ift, ifi) | 41 ift = append(ift, ifi) |
43 } | 42 } |
44 } | 43 } |
45 } | 44 } |
46 done: | |
47 return ift, nil | 45 return ift, nil |
48 } | 46 } |
49 | 47 |
50 func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) Interfac e { | 48 func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) Interfac e { |
51 ifi := Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)} | 49 ifi := Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)} |
52 for _, a := range attrs { | 50 for _, a := range attrs { |
53 switch a.Attr.Type { | 51 switch a.Attr.Type { |
54 case syscall.IFLA_ADDRESS: | 52 case syscall.IFLA_ADDRESS: |
55 var nonzero bool | 53 var nonzero bool |
56 for _, b := range a.Value { | 54 for _, b := range a.Value { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
91 } | 89 } |
92 | 90 |
93 // If the ifindex is zero, interfaceAddrTable returns addresses | 91 // If the ifindex is zero, interfaceAddrTable returns addresses |
94 // for all network interfaces. Otherwise it returns addresses | 92 // for all network interfaces. Otherwise it returns addresses |
95 // for a specific interface. | 93 // for a specific interface. |
96 func interfaceAddrTable(ifindex int) ([]Addr, error) { | 94 func interfaceAddrTable(ifindex int) ([]Addr, error) { |
97 tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC) | 95 tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC) |
98 if err != nil { | 96 if err != nil { |
99 return nil, os.NewSyscallError("netlink rib", err) | 97 return nil, os.NewSyscallError("netlink rib", err) |
100 } | 98 } |
101 | |
102 msgs, err := syscall.ParseNetlinkMessage(tab) | 99 msgs, err := syscall.ParseNetlinkMessage(tab) |
103 if err != nil { | 100 if err != nil { |
104 return nil, os.NewSyscallError("netlink message", err) | 101 return nil, os.NewSyscallError("netlink message", err) |
105 } | 102 } |
106 | |
107 ifat, err := addrTable(msgs, ifindex) | 103 ifat, err := addrTable(msgs, ifindex) |
108 if err != nil { | 104 if err != nil { |
109 return nil, err | 105 return nil, err |
110 } | 106 } |
111 return ifat, nil | 107 return ifat, nil |
112 } | 108 } |
113 | 109 |
114 func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) { | 110 func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) { |
115 var ifat []Addr | 111 var ifat []Addr |
112 done: | |
116 for _, m := range msgs { | 113 for _, m := range msgs { |
117 switch m.Header.Type { | 114 switch m.Header.Type { |
118 case syscall.NLMSG_DONE: | 115 case syscall.NLMSG_DONE: |
119 » » » goto done | 116 » » » break done |
rsc
2013/02/19 15:20:31
Same.
mikio
2013/02/19 23:18:14
Done.
| |
120 case syscall.RTM_NEWADDR: | 117 case syscall.RTM_NEWADDR: |
121 ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0])) | 118 ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0])) |
122 if ifindex == 0 || ifindex == int(ifam.Index) { | 119 if ifindex == 0 || ifindex == int(ifam.Index) { |
123 attrs, err := syscall.ParseNetlinkRouteAttr(&m) | 120 attrs, err := syscall.ParseNetlinkRouteAttr(&m) |
124 if err != nil { | 121 if err != nil { |
125 return nil, os.NewSyscallError("netlink routeattr", err) | 122 return nil, os.NewSyscallError("netlink routeattr", err) |
126 } | 123 } |
127 » » » » ifat = append(ifat, newAddr(attrs, int(ifam.Fami ly), int(ifam.Prefixlen))) | 124 » » » » ifat = append(ifat, newAddr(ifam, attrs)) |
128 } | 125 } |
129 } | 126 } |
130 } | 127 } |
131 done: | |
132 return ifat, nil | 128 return ifat, nil |
133 } | 129 } |
134 | 130 |
135 func newAddr(attrs []syscall.NetlinkRouteAttr, family, pfxlen int) Addr { | 131 func newAddr(ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRouteAttr) Addr { |
136 ifa := &IPNet{} | 132 ifa := &IPNet{} |
137 for _, a := range attrs { | 133 for _, a := range attrs { |
138 switch a.Attr.Type { | 134 switch a.Attr.Type { |
139 case syscall.IFA_ADDRESS: | 135 case syscall.IFA_ADDRESS: |
140 » » » switch family { | 136 » » » switch ifam.Family { |
141 case syscall.AF_INET: | 137 case syscall.AF_INET: |
142 ifa.IP = IPv4(a.Value[0], a.Value[1], a.Value[2] , a.Value[3]) | 138 ifa.IP = IPv4(a.Value[0], a.Value[1], a.Value[2] , a.Value[3]) |
143 » » » » ifa.Mask = CIDRMask(pfxlen, 8*IPv4len) | 139 » » » » ifa.Mask = CIDRMask(int(ifam.Prefixlen), 8*IPv4l en) |
144 case syscall.AF_INET6: | 140 case syscall.AF_INET6: |
145 ifa.IP = make(IP, IPv6len) | 141 ifa.IP = make(IP, IPv6len) |
146 copy(ifa.IP, a.Value[:]) | 142 copy(ifa.IP, a.Value[:]) |
147 » » » » ifa.Mask = CIDRMask(pfxlen, 8*IPv6len) | 143 » » » » ifa.Mask = CIDRMask(int(ifam.Prefixlen), 8*IPv6l en) |
144 » » » » if ifam.Scope == syscall.RT_SCOPE_HOST || ifam.S cope == syscall.RT_SCOPE_LINK { | |
145 » » » » » ifa.Zone = zoneToString(int(ifam.Index)) | |
146 » » » » } | |
148 } | 147 } |
149 } | 148 } |
150 } | 149 } |
151 return ifa | 150 return ifa |
152 } | 151 } |
153 | 152 |
154 // If the ifindex is zero, interfaceMulticastAddrTable returns | 153 // If the ifindex is zero, interfaceMulticastAddrTable returns |
155 // addresses for all network interfaces. Otherwise it returns | 154 // addresses for all network interfaces. Otherwise it returns |
156 // addresses for a specific interface. | 155 // addresses for a specific interface. |
157 func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { | 156 func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { |
(...skipping 11 matching lines...) Expand all Loading... | |
169 ifmat6 := parseProcNetIGMP6("/proc/net/igmp6", ifi) | 168 ifmat6 := parseProcNetIGMP6("/proc/net/igmp6", ifi) |
170 return append(ifmat4, ifmat6...), nil | 169 return append(ifmat4, ifmat6...), nil |
171 } | 170 } |
172 | 171 |
173 func parseProcNetIGMP(path string, ifi *Interface) []Addr { | 172 func parseProcNetIGMP(path string, ifi *Interface) []Addr { |
174 fd, err := open(path) | 173 fd, err := open(path) |
175 if err != nil { | 174 if err != nil { |
176 return nil | 175 return nil |
177 } | 176 } |
178 defer fd.close() | 177 defer fd.close() |
179 | |
180 var ( | 178 var ( |
181 ifmat []Addr | 179 ifmat []Addr |
182 name string | 180 name string |
183 ) | 181 ) |
184 fd.readLine() // skip first line | 182 fd.readLine() // skip first line |
185 b := make([]byte, IPv4len) | 183 b := make([]byte, IPv4len) |
186 for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { | 184 for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { |
187 f := splitAtBytes(l, " :\r\t\n") | 185 f := splitAtBytes(l, " :\r\t\n") |
188 if len(f) < 4 { | 186 if len(f) < 4 { |
189 continue | 187 continue |
(...skipping 17 matching lines...) Expand all Loading... | |
207 } | 205 } |
208 return ifmat | 206 return ifmat |
209 } | 207 } |
210 | 208 |
211 func parseProcNetIGMP6(path string, ifi *Interface) []Addr { | 209 func parseProcNetIGMP6(path string, ifi *Interface) []Addr { |
212 fd, err := open(path) | 210 fd, err := open(path) |
213 if err != nil { | 211 if err != nil { |
214 return nil | 212 return nil |
215 } | 213 } |
216 defer fd.close() | 214 defer fd.close() |
217 | |
218 var ifmat []Addr | 215 var ifmat []Addr |
219 b := make([]byte, IPv6len) | 216 b := make([]byte, IPv6len) |
220 for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { | 217 for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { |
221 f := splitAtBytes(l, " \r\t\n") | 218 f := splitAtBytes(l, " \r\t\n") |
222 if len(f) < 6 { | 219 if len(f) < 6 { |
223 continue | 220 continue |
224 } | 221 } |
225 if ifi == nil || f[1] == ifi.Name { | 222 if ifi == nil || f[1] == ifi.Name { |
226 for i := 0; i+1 < len(f[2]); i += 2 { | 223 for i := 0; i+1 < len(f[2]); i += 2 { |
227 b[i/2], _ = xtoi2(f[2][i:i+2], 0) | 224 b[i/2], _ = xtoi2(f[2][i:i+2], 0) |
228 } | 225 } |
229 ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5] , b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}} | 226 ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5] , b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}} |
227 if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLink LocalMulticast() { | |
228 ifma.Zone = ifi.Name | |
229 } | |
230 ifmat = append(ifmat, ifma.toAddr()) | 230 ifmat = append(ifmat, ifma.toAddr()) |
231 } | 231 } |
232 } | 232 } |
233 return ifmat | 233 return ifmat |
234 } | 234 } |
OLD | NEW |