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 switch af {
174 case syscall.AF_INET:
175 if len(b) < sizeofSockaddrInet {
176 return nil, errInvalidAddr
177 }
178 a := &Inet4Addr{}
179 copy(a.IP[:], b[4:8])
180 return a, nil
181 case syscall.AF_INET6:
182 if len(b) < sizeofSockaddrInet6 {
183 return nil, errInvalidAddr
184 }
185 a := &Inet6Addr{ZoneID: int(nativeEndian.Uint32(b[24:28]))}
186 copy(a.IP[:], b[8:24])
187 if a.IP[0] == 0xfe && a.IP[1]&0xc0 == 0x80 || a.IP[0] == 0xff && (a.IP[1]&0x0f == 0x01 || a.IP[1]&0x0f == 0x02) {
188
189
190
191
192 id := int(bigEndian.Uint16(a.IP[2:4]))
193 if id != 0 {
194 a.ZoneID = id
195 a.IP[2], a.IP[3] = 0, 0
196 }
197 }
198 return a, nil
199 default:
200 return nil, errInvalidAddr
201 }
202 }
203
204
205
206 func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226 l := int(b[0])
227 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
228
229
230 if l == 0 || len(b) > roundup(l) {
231 l = roundup(l)
232 }
233 } else {
234 l = roundup(l)
235 }
236 if len(b) < l {
237 return 0, nil, errInvalidAddr
238 }
239
240
241 const (
242 off4 = 4
243 off6 = 8
244 )
245 switch {
246 case b[0] == sizeofSockaddrInet6:
247 a := &Inet6Addr{}
248 copy(a.IP[:], b[off6:off6+16])
249 return int(b[0]), a, nil
250 case af == syscall.AF_INET6:
251 a := &Inet6Addr{}
252 if l-1 < off6 {
253 copy(a.IP[:], b[1:l])
254 } else {
255 copy(a.IP[:], b[l-off6:l])
256 }
257 return int(b[0]), a, nil
258 case b[0] == sizeofSockaddrInet:
259 a := &Inet4Addr{}
260 copy(a.IP[:], b[off4:off4+4])
261 return int(b[0]), a, nil
262 default:
263 a := &Inet4Addr{}
264 if l-1 < off4 {
265 copy(a.IP[:], b[1:l])
266 } else {
267 copy(a.IP[:], b[l-off4:l])
268 }
269 return int(b[0]), a, nil
270 }
271 }
272
273
274
275 type DefaultAddr struct {
276 af int
277 Raw []byte
278 }
279
280
281 func (a *DefaultAddr) Family() int { return a.af }
282
283 func (a *DefaultAddr) lenAndSpace() (int, int) {
284 l := len(a.Raw)
285 return l, roundup(l)
286 }
287
288 func (a *DefaultAddr) marshal(b []byte) (int, error) {
289 l, ll := a.lenAndSpace()
290 if len(b) < ll {
291 return 0, errShortBuffer
292 }
293 if l > 255 {
294 return 0, errInvalidAddr
295 }
296 b[1] = byte(l)
297 copy(b[:l], a.Raw)
298 return ll, nil
299 }
300
301 func parseDefaultAddr(b []byte) (Addr, error) {
302 if len(b) < 2 || len(b) < int(b[0]) {
303 return nil, errInvalidAddr
304 }
305 a := &DefaultAddr{af: int(b[1]), Raw: b[:b[0]]}
306 return a, nil
307 }
308
309 func addrsSpace(as []Addr) int {
310 var l int
311 for _, a := range as {
312 switch a := a.(type) {
313 case *LinkAddr:
314 _, ll := a.lenAndSpace()
315 l += ll
316 case *Inet4Addr:
317 _, ll := a.lenAndSpace()
318 l += ll
319 case *Inet6Addr:
320 _, ll := a.lenAndSpace()
321 l += ll
322 case *DefaultAddr:
323 _, ll := a.lenAndSpace()
324 l += ll
325 }
326 }
327 return l
328 }
329
330
331
332 func marshalAddrs(b []byte, as []Addr) (uint, error) {
333 var attrs uint
334 for i, a := range as {
335 switch a := a.(type) {
336 case *LinkAddr:
337 l, err := a.marshal(b)
338 if err != nil {
339 return 0, err
340 }
341 b = b[l:]
342 attrs |= 1 << uint(i)
343 case *Inet4Addr:
344 l, err := a.marshal(b)
345 if err != nil {
346 return 0, err
347 }
348 b = b[l:]
349 attrs |= 1 << uint(i)
350 case *Inet6Addr:
351 l, err := a.marshal(b)
352 if err != nil {
353 return 0, err
354 }
355 b = b[l:]
356 attrs |= 1 << uint(i)
357 case *DefaultAddr:
358 l, err := a.marshal(b)
359 if err != nil {
360 return 0, err
361 }
362 b = b[l:]
363 attrs |= 1 << uint(i)
364 }
365 }
366 return attrs, nil
367 }
368
369 func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ([]Addr, error) {
370 var as [syscall.RTAX_MAX]Addr
371 af := int(syscall.AF_UNSPEC)
372 for i := uint(0); i < syscall.RTAX_MAX && len(b) >= roundup(0); i++ {
373 if attrs&(1<<i) == 0 {
374 continue
375 }
376 if i <= syscall.RTAX_BRD {
377 switch b[1] {
378 case syscall.AF_LINK:
379 a, err := parseLinkAddr(b)
380 if err != nil {
381 return nil, err
382 }
383 as[i] = a
384 l := roundup(int(b[0]))
385 if len(b) < l {
386 return nil, errMessageTooShort
387 }
388 b = b[l:]
389 case syscall.AF_INET, syscall.AF_INET6:
390 af = int(b[1])
391 a, err := parseInetAddr(af, b)
392 if err != nil {
393 return nil, err
394 }
395 as[i] = a
396 l := roundup(int(b[0]))
397 if len(b) < l {
398 return nil, errMessageTooShort
399 }
400 b = b[l:]
401 default:
402 l, a, err := fn(af, b)
403 if err != nil {
404 return nil, err
405 }
406 as[i] = a
407 ll := roundup(l)
408 if len(b) < ll {
409 b = b[l:]
410 } else {
411 b = b[ll:]
412 }
413 }
414 } else {
415 a, err := parseDefaultAddr(b)
416 if err != nil {
417 return nil, err
418 }
419 as[i] = a
420 l := roundup(int(b[0]))
421 if len(b) < l {
422 return nil, errMessageTooShort
423 }
424 b = b[l:]
425 }
426 }
427
428
429
430
431 return as[:], nil
432 }
433
View as plain text