Source file
src/net/interface_linux.go
1
2
3
4
5 package net
6
7 import (
8 "os"
9 "syscall"
10 "unsafe"
11 )
12
13
14
15
16 func interfaceTable(ifindex int) ([]Interface, error) {
17 tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
18 if err != nil {
19 return nil, os.NewSyscallError("netlinkrib", err)
20 }
21 msgs, err := syscall.ParseNetlinkMessage(tab)
22 if err != nil {
23 return nil, os.NewSyscallError("parsenetlinkmessage", err)
24 }
25 var ift []Interface
26 loop:
27 for _, m := range msgs {
28 switch m.Header.Type {
29 case syscall.NLMSG_DONE:
30 break loop
31 case syscall.RTM_NEWLINK:
32 ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
33 if ifindex == 0 || ifindex == int(ifim.Index) {
34 attrs, err := syscall.ParseNetlinkRouteAttr(&m)
35 if err != nil {
36 return nil, os.NewSyscallError("parsenetlinkrouteattr", err)
37 }
38 ift = append(ift, *newLink(ifim, attrs))
39 if ifindex == int(ifim.Index) {
40 break loop
41 }
42 }
43 }
44 }
45 return ift, nil
46 }
47
48 const (
49
50
51 sysARPHardwareIPv4IPv4 = 768
52 sysARPHardwareIPv6IPv6 = 769
53 sysARPHardwareIPv6IPv4 = 776
54 sysARPHardwareGREIPv4 = 778
55 sysARPHardwareGREIPv6 = 823
56 )
57
58 func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) *Interface {
59 ifi := &Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)}
60 for _, a := range attrs {
61 switch a.Attr.Type {
62 case syscall.IFLA_ADDRESS:
63
64
65
66 switch len(a.Value) {
67 case IPv4len:
68 switch ifim.Type {
69 case sysARPHardwareIPv4IPv4, sysARPHardwareGREIPv4, sysARPHardwareIPv6IPv4:
70 continue
71 }
72 case IPv6len:
73 switch ifim.Type {
74 case sysARPHardwareIPv6IPv6, sysARPHardwareGREIPv6:
75 continue
76 }
77 }
78 var nonzero bool
79 for _, b := range a.Value {
80 if b != 0 {
81 nonzero = true
82 break
83 }
84 }
85 if nonzero {
86 ifi.HardwareAddr = a.Value[:]
87 }
88 case syscall.IFLA_IFNAME:
89 ifi.Name = string(a.Value[:len(a.Value)-1])
90 case syscall.IFLA_MTU:
91 ifi.MTU = int(*(*uint32)(unsafe.Pointer(&a.Value[:4][0])))
92 }
93 }
94 return ifi
95 }
96
97 func linkFlags(rawFlags uint32) Flags {
98 var f Flags
99 if rawFlags&syscall.IFF_UP != 0 {
100 f |= FlagUp
101 }
102 if rawFlags&syscall.IFF_RUNNING != 0 {
103 f |= FlagRunning
104 }
105 if rawFlags&syscall.IFF_BROADCAST != 0 {
106 f |= FlagBroadcast
107 }
108 if rawFlags&syscall.IFF_LOOPBACK != 0 {
109 f |= FlagLoopback
110 }
111 if rawFlags&syscall.IFF_POINTOPOINT != 0 {
112 f |= FlagPointToPoint
113 }
114 if rawFlags&syscall.IFF_MULTICAST != 0 {
115 f |= FlagMulticast
116 }
117 return f
118 }
119
120
121
122
123 func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
124 tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
125 if err != nil {
126 return nil, os.NewSyscallError("netlinkrib", err)
127 }
128 msgs, err := syscall.ParseNetlinkMessage(tab)
129 if err != nil {
130 return nil, os.NewSyscallError("parsenetlinkmessage", err)
131 }
132 ifat, err := addrTable(ifi, msgs)
133 if err != nil {
134 return nil, err
135 }
136 return ifat, nil
137 }
138
139 func addrTable(ifi *Interface, msgs []syscall.NetlinkMessage) ([]Addr, error) {
140 var ifat []Addr
141 loop:
142 for _, m := range msgs {
143 switch m.Header.Type {
144 case syscall.NLMSG_DONE:
145 break loop
146 case syscall.RTM_NEWADDR:
147 ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
148 if ifi == nil || ifi.Index == int(ifam.Index) {
149 attrs, err := syscall.ParseNetlinkRouteAttr(&m)
150 if err != nil {
151 return nil, os.NewSyscallError("parsenetlinkrouteattr", err)
152 }
153 ifa := newAddr(ifam, attrs)
154 if ifa != nil {
155 ifat = append(ifat, ifa)
156 }
157 }
158 }
159 }
160 return ifat, nil
161 }
162
163 func newAddr(ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRouteAttr) Addr {
164 var ipPointToPoint bool
165
166
167
168 for _, a := range attrs {
169 if a.Attr.Type == syscall.IFA_LOCAL {
170 ipPointToPoint = true
171 break
172 }
173 }
174 for _, a := range attrs {
175 if ipPointToPoint && a.Attr.Type == syscall.IFA_ADDRESS {
176 continue
177 }
178 switch ifam.Family {
179 case syscall.AF_INET:
180 return &IPNet{IP: IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3]), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv4len)}
181 case syscall.AF_INET6:
182 ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv6len)}
183 copy(ifa.IP, a.Value[:])
184 return ifa
185 }
186 }
187 return nil
188 }
189
190
191
192 func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
193 ifmat4 := parseProcNetIGMP("/proc/net/igmp", ifi)
194 ifmat6 := parseProcNetIGMP6("/proc/net/igmp6", ifi)
195 return append(ifmat4, ifmat6...), nil
196 }
197
198 func parseProcNetIGMP(path string, ifi *Interface) []Addr {
199 fd, err := open(path)
200 if err != nil {
201 return nil
202 }
203 defer fd.close()
204 var (
205 ifmat []Addr
206 name string
207 )
208 fd.readLine()
209 b := make([]byte, IPv4len)
210 for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
211 f := splitAtBytes(l, " :\r\t\n")
212 if len(f) < 4 {
213 continue
214 }
215 switch {
216 case l[0] != ' ' && l[0] != '\t':
217 name = f[1]
218 case len(f[0]) == 8:
219 if ifi == nil || name == ifi.Name {
220
221
222
223 for i := 0; i+1 < len(f[0]); i += 2 {
224 b[i/2], _ = xtoi2(f[0][i:i+2], 0)
225 }
226 i := *(*uint32)(unsafe.Pointer(&b[:4][0]))
227 ifma := &IPAddr{IP: IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i))}
228 ifmat = append(ifmat, ifma)
229 }
230 }
231 }
232 return ifmat
233 }
234
235 func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
236 fd, err := open(path)
237 if err != nil {
238 return nil
239 }
240 defer fd.close()
241 var ifmat []Addr
242 b := make([]byte, IPv6len)
243 for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
244 f := splitAtBytes(l, " \r\t\n")
245 if len(f) < 6 {
246 continue
247 }
248 if ifi == nil || f[1] == ifi.Name {
249 for i := 0; i+1 < len(f[2]); i += 2 {
250 b[i/2], _ = xtoi2(f[2][i:i+2], 0)
251 }
252 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]}}
253 ifmat = append(ifmat, ifma)
254 }
255 }
256 return ifmat
257 }
258
View as plain text