1
2
3
4
5
6
7 package route
8
9 import (
10 "runtime"
11 "syscall"
12 )
13
14
15 type Addr interface {
16
17 Family() int
18 }
19
20
21 type LinkAddr struct {
22 Index int
23 Name string
24 Addr []byte
25 }
26
27
28 func (a *LinkAddr) Family() int { return syscall.AF_LINK }
29
30 func (a *LinkAddr) lenAndSpace() (int, int) {
31 l := 8 + len(a.Name) + len(a.Addr)
32 return l, roundup(l)
33 }
34
35 func (a *LinkAddr) marshal(b []byte) (int, error) {
36 l, ll := a.lenAndSpace()
37 if len(b) < ll {
38 return 0, errShortBuffer
39 }
40 nlen, alen := len(a.Name), len(a.Addr)
41 if nlen > 255 || alen > 255 {
42 return 0, errInvalidAddr
43 }
44 b[0] = byte(l)
45 b[1] = syscall.AF_LINK
46 if a.Index > 0 {
47 nativeEndian.PutUint16(b[2:4], uint16(a.Index))
48 }
49 data := b[8:]
50 if nlen > 0 {
51 b[5] = byte(nlen)
52 copy(data[:nlen], a.Name)
53 data = data[nlen:]
54 }
55 if alen > 0 {
56 b[6] = byte(alen)
57 copy(data[:alen], a.Addr)
58 data = data[alen:]
59 }
60 return ll, nil
61 }
62
63 func parseLinkAddr(b []byte) (Addr, error) {
64 if len(b) < 8 {
65 return nil, errInvalidAddr
66 }
67 _, a, err := parseKernelLinkAddr(syscall.AF_LINK, b[4:])
68 if err != nil {
69 return nil, err
70 }
71 a.(*LinkAddr).Index = int(nativeEndian.Uint16(b[2:4]))
72 return a, nil
73 }
74
75
76
77 func parseKernelLinkAddr(_ int, b []byte) (int, Addr, error) {
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
94 if nlen == 0xff {
95 nlen = 0
96 }
97 if alen == 0xff {
98 alen = 0
99 }
100 if slen == 0xff {
101 slen = 0
102 }
103 l := 4 + nlen + alen + slen
104 if len(b) < l {
105 return 0, nil, errInvalidAddr
106 }
107 data := b[4:]
108 var name string
109 var addr []byte
110 if nlen > 0 {
111 name = string(data[:nlen])
112 data = data[nlen:]
113 }
114 if alen > 0 {
115 addr = data[:alen]
116 data = data[alen:]
117 }
118 return l, &LinkAddr{Name: name, Addr: addr}, nil
119 }
120
121
122 type Inet4Addr struct {
123 IP [4]byte
124 }
125
126
127 func (a *Inet4Addr) Family() int { return syscall.AF_INET }
128
129 func (a *Inet4Addr) lenAndSpace() (int, int) {
130 return sizeofSockaddrInet, roundup(sizeofSockaddrInet)
131 }
132
133 func (a *Inet4Addr) marshal(b []byte) (int, error) {
134 l, ll := a.lenAndSpace()
135 if len(b) < ll {
136 return 0, errShortBuffer
137 }
138 b[0] = byte(l)
139 b[1] = syscall.AF_INET
140 copy(b[4:8], a.IP[:])
141 return ll, nil
142 }
143
144
145 type Inet6Addr struct {
146 IP [16]byte
147 ZoneID int
148 }
149
150
151 func (a *Inet6Addr) Family() int { return syscall.AF_INET6 }
152
153 func (a *Inet6Addr) lenAndSpace() (int, int) {
154 return sizeofSockaddrInet6, roundup(sizeofSockaddrInet6)
155 }
156
157 func (a *Inet6Addr) marshal(b []byte) (int, error) {
158 l, ll := a.lenAndSpace()
159 if len(b) < ll {
160 return 0, errShortBuffer
161 }
162 b[0] = byte(l)
163 b[1] = syscall.AF_INET6
164 copy(b[8:24], a.IP[:])
165 if a.ZoneID > 0 {
166 nativeEndian.PutUint32(b[24:28], uint32(a.ZoneID))
167 }
168 return ll, nil
169 }
170
171
172 func parseInetAddr(af int, b []byte) (Addr, error) {
173 const (
174 off4 = 4
175 off6 = 8
176 )
177 switch af {
178 case syscall.AF_INET:
179 if len(b) < (off4+1) || len(b) < int(b[0]) || b[0] == 0 {
180 return nil, errInvalidAddr
181 }
182 sockAddrLen := int(b[0])
183 a := &Inet4Addr{}
184 n := off4 + 4
185 if sockAddrLen < n {
186 n = sockAddrLen
187 }
188 copy(a.IP[:], b[off4:n])
189 return a, nil
190 case syscall.AF_INET6:
191 if len(b) < (off6+1) || len(b) < int(b[0]) || b[0] == 0 {
192 return nil, errInvalidAddr
193 }
194 sockAddrLen := int(b[0])
195 n := off6 + 16
196 if sockAddrLen < n {
197 n = sockAddrLen
198 }
199 a := &Inet6Addr{}
200 if sockAddrLen == sizeofSockaddrInet6 {
201 a.ZoneID = int(nativeEndian.Uint32(b[24:28]))
202 }
203 copy(a.IP[:], b[off6:n])
204 if a.IP[0] == 0xfe && a.IP[1]&0xc0 == 0x80 || a.IP[0] == 0xff && (a.IP[1]&0x0f == 0x01 || a.IP[1]&0x0f == 0x02) {
205
206
207
208
209 id := int(bigEndian.Uint16(a.IP[2:4]))
210 if id != 0 {
211 a.ZoneID = id
212 a.IP[2], a.IP[3] = 0, 0
213 }
214 }
215 return a, nil
216 default:
217 return nil, errInvalidAddr
218 }
219 }
220
221
222
223 func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 l := int(b[0])
244 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
245
246
247 if l == 0 || len(b) > roundup(l) {
248 l = roundup(l)
249 }
250 } else {
251 l = roundup(l)
252 }
253 if len(b) < l {
254 return 0, nil, errInvalidAddr
255 }
256
257
258 const (
259 off4 = 4
260 off6 = 8
261 )
262 switch {
263 case b[0] == sizeofSockaddrInet6:
264 a := &Inet6Addr{}
265 copy(a.IP[:], b[off6:off6+16])
266 return int(b[0]), a, nil
267 case af == syscall.AF_INET6:
268 a := &Inet6Addr{}
269 if l-1 < off6 {
270 copy(a.IP[:], b[1:l])
271 } else {
272 copy(a.IP[:], b[l-off6:l])
273 }
274 return int(b[0]), a, nil
275 case b[0] == sizeofSockaddrInet:
276 a := &Inet4Addr{}
277 copy(a.IP[:], b[off4:off4+4])
278 return int(b[0]), a, nil
279 default:
280 a := &Inet4Addr{}
281 if l-1 < off4 {
282 copy(a.IP[:], b[1:l])
283 } else {
284 copy(a.IP[:], b[l-off4:l])
285 }
286 return int(b[0]), a, nil
287 }
288 }
289
290
291
292 type DefaultAddr struct {
293 af int
294 Raw []byte
295 }
296
297
298 func (a *DefaultAddr) Family() int { return a.af }
299
300 func (a *DefaultAddr) lenAndSpace() (int, int) {
301 l := len(a.Raw)
302 return l, roundup(l)
303 }
304
305 func (a *DefaultAddr) marshal(b []byte) (int, error) {
306 l, ll := a.lenAndSpace()
307 if len(b) < ll {
308 return 0, errShortBuffer
309 }
310 if l > 255 {
311 return 0, errInvalidAddr
312 }
313 b[1] = byte(l)
314 copy(b[:l], a.Raw)
315 return ll, nil
316 }
317
318 func parseDefaultAddr(b []byte) (Addr, error) {
319 if len(b) < 2 || len(b) < int(b[0]) {
320 return nil, errInvalidAddr
321 }
322 a := &DefaultAddr{af: int(b[1]), Raw: b[:b[0]]}
323 return a, nil
324 }
325
326 func addrsSpace(as []Addr) int {
327 var l int
328 for _, a := range as {
329 switch a := a.(type) {
330 case *LinkAddr:
331 _, ll := a.lenAndSpace()
332 l += ll
333 case *Inet4Addr:
334 _, ll := a.lenAndSpace()
335 l += ll
336 case *Inet6Addr:
337 _, ll := a.lenAndSpace()
338 l += ll
339 case *DefaultAddr:
340 _, ll := a.lenAndSpace()
341 l += ll
342 }
343 }
344 return l
345 }
346
347
348
349 func marshalAddrs(b []byte, as []Addr) (uint, error) {
350 var attrs uint
351 for i, a := range as {
352 switch a := a.(type) {
353 case *LinkAddr:
354 l, err := a.marshal(b)
355 if err != nil {
356 return 0, err
357 }
358 b = b[l:]
359 attrs |= 1 << uint(i)
360 case *Inet4Addr:
361 l, err := a.marshal(b)
362 if err != nil {
363 return 0, err
364 }
365 b = b[l:]
366 attrs |= 1 << uint(i)
367 case *Inet6Addr:
368 l, err := a.marshal(b)
369 if err != nil {
370 return 0, err
371 }
372 b = b[l:]
373 attrs |= 1 << uint(i)
374 case *DefaultAddr:
375 l, err := a.marshal(b)
376 if err != nil {
377 return 0, err
378 }
379 b = b[l:]
380 attrs |= 1 << uint(i)
381 }
382 }
383 return attrs, nil
384 }
385
386 func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ([]Addr, error) {
387 var as [syscall.RTAX_MAX]Addr
388 af := int(syscall.AF_UNSPEC)
389 for i := uint(0); i < syscall.RTAX_MAX && len(b) >= roundup(0); i++ {
390 if attrs&(1<<i) == 0 {
391 continue
392 }
393 if i <= syscall.RTAX_BRD {
394 switch b[1] {
395 case syscall.AF_LINK:
396 a, err := parseLinkAddr(b)
397 if err != nil {
398 return nil, err
399 }
400 as[i] = a
401 l := roundup(int(b[0]))
402 if len(b) < l {
403 return nil, errMessageTooShort
404 }
405 b = b[l:]
406 case syscall.AF_INET, syscall.AF_INET6:
407
408
409 if b[0] > 0 {
410 af = int(b[1])
411 a, err := parseInetAddr(af, b)
412 if err != nil {
413 return nil, err
414 }
415 as[i] = a
416 }
417 l := roundup(int(b[0]))
418 if len(b) < l {
419 return nil, errMessageTooShort
420 }
421 b = b[l:]
422 default:
423 l, a, err := fn(af, b)
424 if err != nil {
425 return nil, err
426 }
427 as[i] = a
428 ll := roundup(l)
429 if len(b) < ll {
430 b = b[l:]
431 } else {
432 b = b[ll:]
433 }
434 }
435 } else {
436 a, err := parseDefaultAddr(b)
437 if err != nil {
438 return nil, err
439 }
440 as[i] = a
441 l := roundup(int(b[0]))
442 if len(b) < l {
443 return nil, errMessageTooShort
444 }
445 b = b[l:]
446 }
447 }
448
449
450
451
452 return as[:], nil
453 }
454
View as plain text