1 package netlink
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "fmt"
7 "net"
8 "strconv"
9 "strings"
10 "syscall"
11
12 "github.com/vishvananda/netlink/nl"
13 "github.com/vishvananda/netns"
14 "golang.org/x/sys/unix"
15 )
16
17
18
19 const (
20 SCOPE_UNIVERSE Scope = unix.RT_SCOPE_UNIVERSE
21 SCOPE_SITE Scope = unix.RT_SCOPE_SITE
22 SCOPE_LINK Scope = unix.RT_SCOPE_LINK
23 SCOPE_HOST Scope = unix.RT_SCOPE_HOST
24 SCOPE_NOWHERE Scope = unix.RT_SCOPE_NOWHERE
25 )
26
27 func (s Scope) String() string {
28 switch s {
29 case SCOPE_UNIVERSE:
30 return "universe"
31 case SCOPE_SITE:
32 return "site"
33 case SCOPE_LINK:
34 return "link"
35 case SCOPE_HOST:
36 return "host"
37 case SCOPE_NOWHERE:
38 return "nowhere"
39 default:
40 return "unknown"
41 }
42 }
43
44 const (
45 FLAG_ONLINK NextHopFlag = unix.RTNH_F_ONLINK
46 FLAG_PERVASIVE NextHopFlag = unix.RTNH_F_PERVASIVE
47 )
48
49 var testFlags = []flagString{
50 {f: FLAG_ONLINK, s: "onlink"},
51 {f: FLAG_PERVASIVE, s: "pervasive"},
52 }
53
54 func listFlags(flag int) []string {
55 var flags []string
56 for _, tf := range testFlags {
57 if flag&int(tf.f) != 0 {
58 flags = append(flags, tf.s)
59 }
60 }
61 return flags
62 }
63
64 func (r *Route) ListFlags() []string {
65 return listFlags(r.Flags)
66 }
67
68 func (n *NexthopInfo) ListFlags() []string {
69 return listFlags(n.Flags)
70 }
71
72 type MPLSDestination struct {
73 Labels []int
74 }
75
76 func (d *MPLSDestination) Family() int {
77 return nl.FAMILY_MPLS
78 }
79
80 func (d *MPLSDestination) Decode(buf []byte) error {
81 d.Labels = nl.DecodeMPLSStack(buf)
82 return nil
83 }
84
85 func (d *MPLSDestination) Encode() ([]byte, error) {
86 return nl.EncodeMPLSStack(d.Labels...), nil
87 }
88
89 func (d *MPLSDestination) String() string {
90 s := make([]string, 0, len(d.Labels))
91 for _, l := range d.Labels {
92 s = append(s, fmt.Sprintf("%d", l))
93 }
94 return strings.Join(s, "/")
95 }
96
97 func (d *MPLSDestination) Equal(x Destination) bool {
98 o, ok := x.(*MPLSDestination)
99 if !ok {
100 return false
101 }
102 if d == nil && o == nil {
103 return true
104 }
105 if d == nil || o == nil {
106 return false
107 }
108 if d.Labels == nil && o.Labels == nil {
109 return true
110 }
111 if d.Labels == nil || o.Labels == nil {
112 return false
113 }
114 if len(d.Labels) != len(o.Labels) {
115 return false
116 }
117 for i := range d.Labels {
118 if d.Labels[i] != o.Labels[i] {
119 return false
120 }
121 }
122 return true
123 }
124
125 type MPLSEncap struct {
126 Labels []int
127 }
128
129 func (e *MPLSEncap) Type() int {
130 return nl.LWTUNNEL_ENCAP_MPLS
131 }
132
133 func (e *MPLSEncap) Decode(buf []byte) error {
134 if len(buf) < 4 {
135 return fmt.Errorf("lack of bytes")
136 }
137 l := native.Uint16(buf)
138 if len(buf) < int(l) {
139 return fmt.Errorf("lack of bytes")
140 }
141 buf = buf[:l]
142 typ := native.Uint16(buf[2:])
143 if typ != nl.MPLS_IPTUNNEL_DST {
144 return fmt.Errorf("unknown MPLS Encap Type: %d", typ)
145 }
146 e.Labels = nl.DecodeMPLSStack(buf[4:])
147 return nil
148 }
149
150 func (e *MPLSEncap) Encode() ([]byte, error) {
151 s := nl.EncodeMPLSStack(e.Labels...)
152 hdr := make([]byte, 4)
153 native.PutUint16(hdr, uint16(len(s)+4))
154 native.PutUint16(hdr[2:], nl.MPLS_IPTUNNEL_DST)
155 return append(hdr, s...), nil
156 }
157
158 func (e *MPLSEncap) String() string {
159 s := make([]string, 0, len(e.Labels))
160 for _, l := range e.Labels {
161 s = append(s, fmt.Sprintf("%d", l))
162 }
163 return strings.Join(s, "/")
164 }
165
166 func (e *MPLSEncap) Equal(x Encap) bool {
167 o, ok := x.(*MPLSEncap)
168 if !ok {
169 return false
170 }
171 if e == nil && o == nil {
172 return true
173 }
174 if e == nil || o == nil {
175 return false
176 }
177 if e.Labels == nil && o.Labels == nil {
178 return true
179 }
180 if e.Labels == nil || o.Labels == nil {
181 return false
182 }
183 if len(e.Labels) != len(o.Labels) {
184 return false
185 }
186 for i := range e.Labels {
187 if e.Labels[i] != o.Labels[i] {
188 return false
189 }
190 }
191 return true
192 }
193
194
195 type SEG6Encap struct {
196 Mode int
197 Segments []net.IP
198 }
199
200 func (e *SEG6Encap) Type() int {
201 return nl.LWTUNNEL_ENCAP_SEG6
202 }
203 func (e *SEG6Encap) Decode(buf []byte) error {
204 if len(buf) < 4 {
205 return fmt.Errorf("lack of bytes")
206 }
207
208 l := native.Uint16(buf)
209 if len(buf) < int(l) {
210 return fmt.Errorf("lack of bytes")
211 }
212 buf = buf[:l]
213 typ := native.Uint16(buf[2:])
214
215 if typ != nl.SEG6_IPTUNNEL_SRH {
216 return fmt.Errorf("unknown SEG6 Type: %d", typ)
217 }
218
219 var err error
220 e.Mode, e.Segments, err = nl.DecodeSEG6Encap(buf[4:])
221
222 return err
223 }
224 func (e *SEG6Encap) Encode() ([]byte, error) {
225 s, err := nl.EncodeSEG6Encap(e.Mode, e.Segments)
226 hdr := make([]byte, 4)
227 native.PutUint16(hdr, uint16(len(s)+4))
228 native.PutUint16(hdr[2:], nl.SEG6_IPTUNNEL_SRH)
229 return append(hdr, s...), err
230 }
231 func (e *SEG6Encap) String() string {
232 segs := make([]string, 0, len(e.Segments))
233
234 for i := len(e.Segments); i > 0; i-- {
235 segs = append(segs, e.Segments[i-1].String())
236 }
237 str := fmt.Sprintf("mode %s segs %d [ %s ]", nl.SEG6EncapModeString(e.Mode),
238 len(e.Segments), strings.Join(segs, " "))
239 return str
240 }
241 func (e *SEG6Encap) Equal(x Encap) bool {
242 o, ok := x.(*SEG6Encap)
243 if !ok {
244 return false
245 }
246 if e == o {
247 return true
248 }
249 if e == nil || o == nil {
250 return false
251 }
252 if e.Mode != o.Mode {
253 return false
254 }
255 if len(e.Segments) != len(o.Segments) {
256 return false
257 }
258 for i := range e.Segments {
259 if !e.Segments[i].Equal(o.Segments[i]) {
260 return false
261 }
262 }
263 return true
264 }
265
266
267 type SEG6LocalEncap struct {
268 Flags [nl.SEG6_LOCAL_MAX]bool
269 Action int
270 Segments []net.IP
271 Table int
272 InAddr net.IP
273 In6Addr net.IP
274 Iif int
275 Oif int
276 bpf bpfObj
277 }
278
279 func (e *SEG6LocalEncap) SetProg(progFd int, progName string) error {
280 if progFd <= 0 {
281 return fmt.Errorf("seg6local bpf SetProg: invalid fd")
282 }
283 e.bpf.progFd = progFd
284 e.bpf.progName = progName
285 return nil
286 }
287
288 func (e *SEG6LocalEncap) Type() int {
289 return nl.LWTUNNEL_ENCAP_SEG6_LOCAL
290 }
291 func (e *SEG6LocalEncap) Decode(buf []byte) error {
292 attrs, err := nl.ParseRouteAttr(buf)
293 if err != nil {
294 return err
295 }
296 for _, attr := range attrs {
297 switch attr.Attr.Type {
298 case nl.SEG6_LOCAL_ACTION:
299 e.Action = int(native.Uint32(attr.Value[0:4]))
300 e.Flags[nl.SEG6_LOCAL_ACTION] = true
301 case nl.SEG6_LOCAL_SRH:
302 e.Segments, err = nl.DecodeSEG6Srh(attr.Value[:])
303 e.Flags[nl.SEG6_LOCAL_SRH] = true
304 case nl.SEG6_LOCAL_TABLE:
305 e.Table = int(native.Uint32(attr.Value[0:4]))
306 e.Flags[nl.SEG6_LOCAL_TABLE] = true
307 case nl.SEG6_LOCAL_NH4:
308 e.InAddr = net.IP(attr.Value[0:4])
309 e.Flags[nl.SEG6_LOCAL_NH4] = true
310 case nl.SEG6_LOCAL_NH6:
311 e.In6Addr = net.IP(attr.Value[0:16])
312 e.Flags[nl.SEG6_LOCAL_NH6] = true
313 case nl.SEG6_LOCAL_IIF:
314 e.Iif = int(native.Uint32(attr.Value[0:4]))
315 e.Flags[nl.SEG6_LOCAL_IIF] = true
316 case nl.SEG6_LOCAL_OIF:
317 e.Oif = int(native.Uint32(attr.Value[0:4]))
318 e.Flags[nl.SEG6_LOCAL_OIF] = true
319 case nl.SEG6_LOCAL_BPF:
320 var bpfAttrs []syscall.NetlinkRouteAttr
321 bpfAttrs, err = nl.ParseRouteAttr(attr.Value)
322 bpfobj := bpfObj{}
323 for _, bpfAttr := range bpfAttrs {
324 switch bpfAttr.Attr.Type {
325 case nl.LWT_BPF_PROG_FD:
326 bpfobj.progFd = int(native.Uint32(bpfAttr.Value))
327 case nl.LWT_BPF_PROG_NAME:
328 bpfobj.progName = string(bpfAttr.Value)
329 default:
330 err = fmt.Errorf("seg6local bpf decode: unknown attribute: Type %d", bpfAttr.Attr)
331 }
332 }
333 e.bpf = bpfobj
334 e.Flags[nl.SEG6_LOCAL_BPF] = true
335 }
336 }
337 return err
338 }
339 func (e *SEG6LocalEncap) Encode() ([]byte, error) {
340 var err error
341 res := make([]byte, 8)
342 native.PutUint16(res, 8)
343 native.PutUint16(res[2:], nl.SEG6_LOCAL_ACTION)
344 native.PutUint32(res[4:], uint32(e.Action))
345 if e.Flags[nl.SEG6_LOCAL_SRH] {
346 srh, err := nl.EncodeSEG6Srh(e.Segments)
347 if err != nil {
348 return nil, err
349 }
350 attr := make([]byte, 4)
351 native.PutUint16(attr, uint16(len(srh)+4))
352 native.PutUint16(attr[2:], nl.SEG6_LOCAL_SRH)
353 attr = append(attr, srh...)
354 res = append(res, attr...)
355 }
356 if e.Flags[nl.SEG6_LOCAL_TABLE] {
357 attr := make([]byte, 8)
358 native.PutUint16(attr, 8)
359 native.PutUint16(attr[2:], nl.SEG6_LOCAL_TABLE)
360 native.PutUint32(attr[4:], uint32(e.Table))
361 res = append(res, attr...)
362 }
363 if e.Flags[nl.SEG6_LOCAL_NH4] {
364 attr := make([]byte, 4)
365 native.PutUint16(attr, 8)
366 native.PutUint16(attr[2:], nl.SEG6_LOCAL_NH4)
367 ipv4 := e.InAddr.To4()
368 if ipv4 == nil {
369 err = fmt.Errorf("SEG6_LOCAL_NH4 has invalid IPv4 address")
370 return nil, err
371 }
372 attr = append(attr, ipv4...)
373 res = append(res, attr...)
374 }
375 if e.Flags[nl.SEG6_LOCAL_NH6] {
376 attr := make([]byte, 4)
377 native.PutUint16(attr, 20)
378 native.PutUint16(attr[2:], nl.SEG6_LOCAL_NH6)
379 attr = append(attr, e.In6Addr...)
380 res = append(res, attr...)
381 }
382 if e.Flags[nl.SEG6_LOCAL_IIF] {
383 attr := make([]byte, 8)
384 native.PutUint16(attr, 8)
385 native.PutUint16(attr[2:], nl.SEG6_LOCAL_IIF)
386 native.PutUint32(attr[4:], uint32(e.Iif))
387 res = append(res, attr...)
388 }
389 if e.Flags[nl.SEG6_LOCAL_OIF] {
390 attr := make([]byte, 8)
391 native.PutUint16(attr, 8)
392 native.PutUint16(attr[2:], nl.SEG6_LOCAL_OIF)
393 native.PutUint32(attr[4:], uint32(e.Oif))
394 res = append(res, attr...)
395 }
396 if e.Flags[nl.SEG6_LOCAL_BPF] {
397 attr := nl.NewRtAttr(nl.SEG6_LOCAL_BPF, []byte{})
398 if e.bpf.progFd != 0 {
399 attr.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(e.bpf.progFd)))
400 }
401 if e.bpf.progName != "" {
402 attr.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(e.bpf.progName))
403 }
404 res = append(res, attr.Serialize()...)
405 }
406 return res, err
407 }
408 func (e *SEG6LocalEncap) String() string {
409 strs := make([]string, 0, nl.SEG6_LOCAL_MAX)
410 strs = append(strs, fmt.Sprintf("action %s", nl.SEG6LocalActionString(e.Action)))
411
412 if e.Flags[nl.SEG6_LOCAL_TABLE] {
413 strs = append(strs, fmt.Sprintf("table %d", e.Table))
414 }
415 if e.Flags[nl.SEG6_LOCAL_NH4] {
416 strs = append(strs, fmt.Sprintf("nh4 %s", e.InAddr))
417 }
418 if e.Flags[nl.SEG6_LOCAL_NH6] {
419 strs = append(strs, fmt.Sprintf("nh6 %s", e.In6Addr))
420 }
421 if e.Flags[nl.SEG6_LOCAL_IIF] {
422 link, err := LinkByIndex(e.Iif)
423 if err != nil {
424 strs = append(strs, fmt.Sprintf("iif %d", e.Iif))
425 } else {
426 strs = append(strs, fmt.Sprintf("iif %s", link.Attrs().Name))
427 }
428 }
429 if e.Flags[nl.SEG6_LOCAL_OIF] {
430 link, err := LinkByIndex(e.Oif)
431 if err != nil {
432 strs = append(strs, fmt.Sprintf("oif %d", e.Oif))
433 } else {
434 strs = append(strs, fmt.Sprintf("oif %s", link.Attrs().Name))
435 }
436 }
437 if e.Flags[nl.SEG6_LOCAL_SRH] {
438 segs := make([]string, 0, len(e.Segments))
439
440 for i := len(e.Segments); i > 0; i-- {
441 segs = append(segs, e.Segments[i-1].String())
442 }
443 strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " ")))
444 }
445 if e.Flags[nl.SEG6_LOCAL_BPF] {
446 strs = append(strs, fmt.Sprintf("bpf %s[%d]", e.bpf.progName, e.bpf.progFd))
447 }
448 return strings.Join(strs, " ")
449 }
450 func (e *SEG6LocalEncap) Equal(x Encap) bool {
451 o, ok := x.(*SEG6LocalEncap)
452 if !ok {
453 return false
454 }
455 if e == o {
456 return true
457 }
458 if e == nil || o == nil {
459 return false
460 }
461
462 for i := range e.Flags {
463 if e.Flags[i] != o.Flags[i] {
464 return false
465 }
466 }
467 if len(e.Segments) != len(o.Segments) {
468 return false
469 }
470 for i := range e.Segments {
471 if !e.Segments[i].Equal(o.Segments[i]) {
472 return false
473 }
474 }
475
476 if !e.InAddr.Equal(o.InAddr) || !e.In6Addr.Equal(o.In6Addr) {
477 return false
478 }
479 if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif || e.bpf != o.bpf {
480 return false
481 }
482 return true
483 }
484
485
486 type bpfObj struct {
487 progFd int
488 progName string
489 }
490 type BpfEncap struct {
491 progs [nl.LWT_BPF_MAX]bpfObj
492 headroom int
493 }
494
495
496
497
498 func (e *BpfEncap) SetProg(mode, progFd int, progName string) error {
499 if progFd <= 0 {
500 return fmt.Errorf("lwt bpf SetProg: invalid fd")
501 }
502 if mode <= nl.LWT_BPF_UNSPEC || mode >= nl.LWT_BPF_XMIT_HEADROOM {
503 return fmt.Errorf("lwt bpf SetProg:invalid mode")
504 }
505 e.progs[mode].progFd = progFd
506 e.progs[mode].progName = fmt.Sprintf("%s[fd:%d]", progName, progFd)
507 return nil
508 }
509
510
511
512 func (e *BpfEncap) SetXmitHeadroom(headroom int) error {
513 if headroom > nl.LWT_BPF_MAX_HEADROOM || headroom < 0 {
514 return fmt.Errorf("invalid headroom size. range is 0 - %d", nl.LWT_BPF_MAX_HEADROOM)
515 }
516 e.headroom = headroom
517 return nil
518 }
519
520 func (e *BpfEncap) Type() int {
521 return nl.LWTUNNEL_ENCAP_BPF
522 }
523 func (e *BpfEncap) Decode(buf []byte) error {
524 if len(buf) < 4 {
525 return fmt.Errorf("lwt bpf decode: lack of bytes")
526 }
527 native := nl.NativeEndian()
528 attrs, err := nl.ParseRouteAttr(buf)
529 if err != nil {
530 return fmt.Errorf("lwt bpf decode: failed parsing attribute. err: %v", err)
531 }
532 for _, attr := range attrs {
533 if int(attr.Attr.Type) < 1 {
534
535 continue
536 }
537 if int(attr.Attr.Type) > nl.LWT_BPF_MAX {
538 return fmt.Errorf("lwt bpf decode: received unknown attribute type: %d", attr.Attr.Type)
539 }
540 switch int(attr.Attr.Type) {
541 case nl.LWT_BPF_MAX_HEADROOM:
542 e.headroom = int(native.Uint32(attr.Value))
543 default:
544 bpfO := bpfObj{}
545 parsedAttrs, err := nl.ParseRouteAttr(attr.Value)
546 if err != nil {
547 return fmt.Errorf("lwt bpf decode: failed parsing route attribute")
548 }
549 for _, parsedAttr := range parsedAttrs {
550 switch int(parsedAttr.Attr.Type) {
551 case nl.LWT_BPF_PROG_FD:
552 bpfO.progFd = int(native.Uint32(parsedAttr.Value))
553 case nl.LWT_BPF_PROG_NAME:
554 bpfO.progName = string(parsedAttr.Value)
555 default:
556 return fmt.Errorf("lwt bpf decode: received unknown attribute: type: %d, len: %d", parsedAttr.Attr.Type, parsedAttr.Attr.Len)
557 }
558 }
559 e.progs[attr.Attr.Type] = bpfO
560 }
561 }
562 return nil
563 }
564
565 func (e *BpfEncap) Encode() ([]byte, error) {
566 buf := make([]byte, 0)
567 native = nl.NativeEndian()
568 for index, attr := range e.progs {
569 nlMsg := nl.NewRtAttr(index, []byte{})
570 if attr.progFd != 0 {
571 nlMsg.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(attr.progFd)))
572 }
573 if attr.progName != "" {
574 nlMsg.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(attr.progName))
575 }
576 if nlMsg.Len() > 4 {
577 buf = append(buf, nlMsg.Serialize()...)
578 }
579 }
580 if len(buf) <= 4 {
581 return nil, fmt.Errorf("lwt bpf encode: bpf obj definitions returned empty buffer")
582 }
583 if e.headroom > 0 {
584 hRoom := nl.NewRtAttr(nl.LWT_BPF_XMIT_HEADROOM, nl.Uint32Attr(uint32(e.headroom)))
585 buf = append(buf, hRoom.Serialize()...)
586 }
587 return buf, nil
588 }
589
590 func (e *BpfEncap) String() string {
591 progs := make([]string, 0)
592 for index, obj := range e.progs {
593 empty := bpfObj{}
594 switch index {
595 case nl.LWT_BPF_IN:
596 if obj != empty {
597 progs = append(progs, fmt.Sprintf("in: %s", obj.progName))
598 }
599 case nl.LWT_BPF_OUT:
600 if obj != empty {
601 progs = append(progs, fmt.Sprintf("out: %s", obj.progName))
602 }
603 case nl.LWT_BPF_XMIT:
604 if obj != empty {
605 progs = append(progs, fmt.Sprintf("xmit: %s", obj.progName))
606 }
607 }
608 }
609 if e.headroom > 0 {
610 progs = append(progs, fmt.Sprintf("xmit headroom: %d", e.headroom))
611 }
612 return strings.Join(progs, " ")
613 }
614
615 func (e *BpfEncap) Equal(x Encap) bool {
616 o, ok := x.(*BpfEncap)
617 if !ok {
618 return false
619 }
620 if e.headroom != o.headroom {
621 return false
622 }
623 for i := range o.progs {
624 if o.progs[i] != e.progs[i] {
625 return false
626 }
627 }
628 return true
629 }
630
631
632 type IP6tnlEncap struct {
633 ID uint64
634 Dst net.IP
635 Src net.IP
636 Hoplimit uint8
637 TC uint8
638 Flags uint16
639 }
640
641 func (e *IP6tnlEncap) Type() int {
642 return nl.LWTUNNEL_ENCAP_IP6
643 }
644
645 func (e *IP6tnlEncap) Decode(buf []byte) error {
646 attrs, err := nl.ParseRouteAttr(buf)
647 if err != nil {
648 return err
649 }
650 for _, attr := range attrs {
651 switch attr.Attr.Type {
652 case nl.LWTUNNEL_IP6_ID:
653 e.ID = uint64(native.Uint64(attr.Value[0:4]))
654 case nl.LWTUNNEL_IP6_DST:
655 e.Dst = net.IP(attr.Value[:])
656 case nl.LWTUNNEL_IP6_SRC:
657 e.Src = net.IP(attr.Value[:])
658 case nl.LWTUNNEL_IP6_HOPLIMIT:
659 e.Hoplimit = attr.Value[0]
660 case nl.LWTUNNEL_IP6_TC:
661
662 err = fmt.Errorf("decoding TC in IP6tnlEncap is not supported")
663 case nl.LWTUNNEL_IP6_FLAGS:
664
665 err = fmt.Errorf("decoding FLAG in IP6tnlEncap is not supported")
666 case nl.LWTUNNEL_IP6_PAD:
667 err = fmt.Errorf("decoding PAD in IP6tnlEncap is not supported")
668 case nl.LWTUNNEL_IP6_OPTS:
669 err = fmt.Errorf("decoding OPTS in IP6tnlEncap is not supported")
670 }
671 }
672 return err
673 }
674
675 func (e *IP6tnlEncap) Encode() ([]byte, error) {
676
677 final := []byte{}
678
679 resID := make([]byte, 12)
680 native.PutUint16(resID, 12)
681 native.PutUint16(resID[2:], nl.LWTUNNEL_IP6_ID)
682 native.PutUint64(resID[4:], 0)
683 final = append(final, resID...)
684
685 resDst := make([]byte, 4)
686 native.PutUint16(resDst, 20)
687 native.PutUint16(resDst[2:], nl.LWTUNNEL_IP6_DST)
688 resDst = append(resDst, e.Dst...)
689 final = append(final, resDst...)
690
691 resSrc := make([]byte, 4)
692 native.PutUint16(resSrc, 20)
693 native.PutUint16(resSrc[2:], nl.LWTUNNEL_IP6_SRC)
694 resSrc = append(resSrc, e.Src...)
695 final = append(final, resSrc...)
696
697
698
699
700
701
702
703 resHops := make([]byte, 5)
704 native.PutUint16(resHops, 5)
705 native.PutUint16(resHops[2:], nl.LWTUNNEL_IP6_HOPLIMIT)
706 resHops[4] = e.Hoplimit
707 final = append(final, resHops...)
708
709
710
711
712
713
714
715 return final, nil
716 }
717
718 func (e *IP6tnlEncap) String() string {
719 return fmt.Sprintf("id %d src %s dst %s hoplimit %d tc %d flags 0x%.4x", e.ID, e.Src, e.Dst, e.Hoplimit, e.TC, e.Flags)
720 }
721
722 func (e *IP6tnlEncap) Equal(x Encap) bool {
723 o, ok := x.(*IP6tnlEncap)
724 if !ok {
725 return false
726 }
727
728 if e.ID != o.ID || e.Flags != o.Flags || e.Hoplimit != o.Hoplimit || e.Src.Equal(o.Src) || e.Dst.Equal(o.Dst) || e.TC != o.TC {
729 return false
730 }
731 return true
732 }
733
734 type Via struct {
735 AddrFamily int
736 Addr net.IP
737 }
738
739 func (v *Via) Equal(x Destination) bool {
740 o, ok := x.(*Via)
741 if !ok {
742 return false
743 }
744 if v.AddrFamily == x.Family() && v.Addr.Equal(o.Addr) {
745 return true
746 }
747 return false
748 }
749
750 func (v *Via) String() string {
751 return fmt.Sprintf("Family: %d, Address: %s", v.AddrFamily, v.Addr.String())
752 }
753
754 func (v *Via) Family() int {
755 return v.AddrFamily
756 }
757
758 func (v *Via) Encode() ([]byte, error) {
759 buf := &bytes.Buffer{}
760 err := binary.Write(buf, native, uint16(v.AddrFamily))
761 if err != nil {
762 return nil, err
763 }
764 err = binary.Write(buf, native, v.Addr)
765 if err != nil {
766 return nil, err
767 }
768 return buf.Bytes(), nil
769 }
770
771 func (v *Via) Decode(b []byte) error {
772 if len(b) < 6 {
773 return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b))
774 }
775 v.AddrFamily = int(native.Uint16(b[0:2]))
776 if v.AddrFamily == nl.FAMILY_V4 {
777 v.Addr = net.IP(b[2:6])
778 return nil
779 } else if v.AddrFamily == nl.FAMILY_V6 {
780 if len(b) < 18 {
781 return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b))
782 }
783 v.Addr = net.IP(b[2:])
784 return nil
785 }
786 return fmt.Errorf("decoding failed: address family %d unknown", v.AddrFamily)
787 }
788
789
790
791 func RouteAdd(route *Route) error {
792 return pkgHandle.RouteAdd(route)
793 }
794
795
796
797 func (h *Handle) RouteAdd(route *Route) error {
798 flags := unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK
799 req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
800 _, err := h.routeHandle(route, req, nl.NewRtMsg())
801 return err
802 }
803
804
805
806 func RouteAppend(route *Route) error {
807 return pkgHandle.RouteAppend(route)
808 }
809
810
811
812 func (h *Handle) RouteAppend(route *Route) error {
813 flags := unix.NLM_F_CREATE | unix.NLM_F_APPEND | unix.NLM_F_ACK
814 req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
815 _, err := h.routeHandle(route, req, nl.NewRtMsg())
816 return err
817 }
818
819
820 func RouteAddEcmp(route *Route) error {
821 return pkgHandle.RouteAddEcmp(route)
822 }
823
824
825 func (h *Handle) RouteAddEcmp(route *Route) error {
826 flags := unix.NLM_F_CREATE | unix.NLM_F_ACK
827 req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
828 _, err := h.routeHandle(route, req, nl.NewRtMsg())
829 return err
830 }
831
832
833
834 func RouteChange(route *Route) error {
835 return pkgHandle.RouteChange(route)
836 }
837
838
839
840 func (h *Handle) RouteChange(route *Route) error {
841 flags := unix.NLM_F_REPLACE | unix.NLM_F_ACK
842 req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
843 _, err := h.routeHandle(route, req, nl.NewRtMsg())
844 return err
845 }
846
847
848
849 func RouteReplace(route *Route) error {
850 return pkgHandle.RouteReplace(route)
851 }
852
853
854
855 func (h *Handle) RouteReplace(route *Route) error {
856 flags := unix.NLM_F_CREATE | unix.NLM_F_REPLACE | unix.NLM_F_ACK
857 req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
858 _, err := h.routeHandle(route, req, nl.NewRtMsg())
859 return err
860 }
861
862
863
864 func RouteDel(route *Route) error {
865 return pkgHandle.RouteDel(route)
866 }
867
868
869
870 func (h *Handle) RouteDel(route *Route) error {
871 req := h.newNetlinkRequest(unix.RTM_DELROUTE, unix.NLM_F_ACK)
872 _, err := h.routeHandle(route, req, nl.NewRtDelMsg())
873 return err
874 }
875
876 func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) ([][]byte, error) {
877 if err := h.prepareRouteReq(route, req, msg); err != nil {
878 return nil, err
879 }
880 return req.Execute(unix.NETLINK_ROUTE, 0)
881 }
882
883 func (h *Handle) routeHandleIter(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg, f func(msg []byte) bool) error {
884 if err := h.prepareRouteReq(route, req, msg); err != nil {
885 return err
886 }
887 return req.ExecuteIter(unix.NETLINK_ROUTE, 0, f)
888 }
889
890 func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
891 if req.NlMsghdr.Type != unix.RTM_GETROUTE && (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil {
892 return fmt.Errorf("either Dst.IP, Src.IP or Gw must be set")
893 }
894
895 family := -1
896 var rtAttrs []*nl.RtAttr
897
898 if route.Dst != nil && route.Dst.IP != nil {
899 dstLen, _ := route.Dst.Mask.Size()
900 msg.Dst_len = uint8(dstLen)
901 dstFamily := nl.GetIPFamily(route.Dst.IP)
902 family = dstFamily
903 var dstData []byte
904 if dstFamily == FAMILY_V4 {
905 dstData = route.Dst.IP.To4()
906 } else {
907 dstData = route.Dst.IP.To16()
908 }
909 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData))
910 } else if route.MPLSDst != nil {
911 family = nl.FAMILY_MPLS
912 msg.Dst_len = uint8(20)
913 msg.Type = unix.RTN_UNICAST
914 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, nl.EncodeMPLSStack(*route.MPLSDst)))
915 }
916
917 if route.NewDst != nil {
918 if family != -1 && family != route.NewDst.Family() {
919 return fmt.Errorf("new destination and destination are not the same address family")
920 }
921 buf, err := route.NewDst.Encode()
922 if err != nil {
923 return err
924 }
925 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_NEWDST, buf))
926 }
927
928 if route.Encap != nil {
929 buf := make([]byte, 2)
930 native.PutUint16(buf, uint16(route.Encap.Type()))
931 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
932 buf, err := route.Encap.Encode()
933 if err != nil {
934 return err
935 }
936 switch route.Encap.Type() {
937 case nl.LWTUNNEL_ENCAP_BPF:
938 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP|unix.NLA_F_NESTED, buf))
939 default:
940 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf))
941 }
942
943 }
944
945 if route.Src != nil {
946 srcFamily := nl.GetIPFamily(route.Src)
947 if family != -1 && family != srcFamily {
948 return fmt.Errorf("source and destination ip are not the same IP family")
949 }
950 family = srcFamily
951 var srcData []byte
952 if srcFamily == FAMILY_V4 {
953 srcData = route.Src.To4()
954 } else {
955 srcData = route.Src.To16()
956 }
957
958 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PREFSRC, srcData))
959 }
960
961 if route.Gw != nil {
962 gwFamily := nl.GetIPFamily(route.Gw)
963 if family != -1 && family != gwFamily {
964 return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
965 }
966 family = gwFamily
967 var gwData []byte
968 if gwFamily == FAMILY_V4 {
969 gwData = route.Gw.To4()
970 } else {
971 gwData = route.Gw.To16()
972 }
973 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_GATEWAY, gwData))
974 }
975
976 if route.Via != nil {
977 buf, err := route.Via.Encode()
978 if err != nil {
979 return fmt.Errorf("failed to encode RTA_VIA: %v", err)
980 }
981 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_VIA, buf))
982 }
983
984 if len(route.MultiPath) > 0 {
985 buf := []byte{}
986 for _, nh := range route.MultiPath {
987 rtnh := &nl.RtNexthop{
988 RtNexthop: unix.RtNexthop{
989 Hops: uint8(nh.Hops),
990 Ifindex: int32(nh.LinkIndex),
991 Flags: uint8(nh.Flags),
992 },
993 }
994 children := []nl.NetlinkRequestData{}
995 if nh.Gw != nil {
996 gwFamily := nl.GetIPFamily(nh.Gw)
997 if family != -1 && family != gwFamily {
998 return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
999 }
1000 if gwFamily == FAMILY_V4 {
1001 children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To4())))
1002 } else {
1003 children = append(children, nl.NewRtAttr(unix.RTA_GATEWAY, []byte(nh.Gw.To16())))
1004 }
1005 }
1006 if nh.NewDst != nil {
1007 if family != -1 && family != nh.NewDst.Family() {
1008 return fmt.Errorf("new destination and destination are not the same address family")
1009 }
1010 buf, err := nh.NewDst.Encode()
1011 if err != nil {
1012 return err
1013 }
1014 children = append(children, nl.NewRtAttr(unix.RTA_NEWDST, buf))
1015 }
1016 if nh.Encap != nil {
1017 buf := make([]byte, 2)
1018 native.PutUint16(buf, uint16(nh.Encap.Type()))
1019 children = append(children, nl.NewRtAttr(unix.RTA_ENCAP_TYPE, buf))
1020 buf, err := nh.Encap.Encode()
1021 if err != nil {
1022 return err
1023 }
1024 children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf))
1025 }
1026 if nh.Via != nil {
1027 buf, err := nh.Via.Encode()
1028 if err != nil {
1029 return err
1030 }
1031 children = append(children, nl.NewRtAttr(unix.RTA_VIA, buf))
1032 }
1033 rtnh.Children = children
1034 buf = append(buf, rtnh.Serialize()...)
1035 }
1036 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_MULTIPATH, buf))
1037 }
1038
1039 if route.Table > 0 {
1040 if route.Table >= 256 {
1041 msg.Table = unix.RT_TABLE_UNSPEC
1042 b := make([]byte, 4)
1043 native.PutUint32(b, uint32(route.Table))
1044 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_TABLE, b))
1045 } else {
1046 msg.Table = uint8(route.Table)
1047 }
1048 }
1049
1050 if route.Priority > 0 {
1051 b := make([]byte, 4)
1052 native.PutUint32(b, uint32(route.Priority))
1053 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b))
1054 }
1055 if route.Realm > 0 {
1056 b := make([]byte, 4)
1057 native.PutUint32(b, uint32(route.Realm))
1058 rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_FLOW, b))
1059 }
1060 if route.Tos > 0 {
1061 msg.Tos = uint8(route.Tos)
1062 }
1063 if route.Protocol > 0 {
1064 msg.Protocol = uint8(route.Protocol)
1065 }
1066 if route.Type > 0 {
1067 msg.Type = uint8(route.Type)
1068 }
1069
1070 var metrics []*nl.RtAttr
1071 if route.MTU > 0 {
1072 b := nl.Uint32Attr(uint32(route.MTU))
1073 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b))
1074 }
1075 if route.Window > 0 {
1076 b := nl.Uint32Attr(uint32(route.Window))
1077 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_WINDOW, b))
1078 }
1079 if route.Rtt > 0 {
1080 b := nl.Uint32Attr(uint32(route.Rtt))
1081 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTT, b))
1082 }
1083 if route.RttVar > 0 {
1084 b := nl.Uint32Attr(uint32(route.RttVar))
1085 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTTVAR, b))
1086 }
1087 if route.Ssthresh > 0 {
1088 b := nl.Uint32Attr(uint32(route.Ssthresh))
1089 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_SSTHRESH, b))
1090 }
1091 if route.Cwnd > 0 {
1092 b := nl.Uint32Attr(uint32(route.Cwnd))
1093 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_CWND, b))
1094 }
1095 if route.AdvMSS > 0 {
1096 b := nl.Uint32Attr(uint32(route.AdvMSS))
1097 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b))
1098 }
1099 if route.Reordering > 0 {
1100 b := nl.Uint32Attr(uint32(route.Reordering))
1101 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_REORDERING, b))
1102 }
1103 if route.Hoplimit > 0 {
1104 b := nl.Uint32Attr(uint32(route.Hoplimit))
1105 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_HOPLIMIT, b))
1106 }
1107 if route.InitCwnd > 0 {
1108 b := nl.Uint32Attr(uint32(route.InitCwnd))
1109 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_INITCWND, b))
1110 }
1111 if route.Features > 0 {
1112 b := nl.Uint32Attr(uint32(route.Features))
1113 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_FEATURES, b))
1114 }
1115 if route.RtoMin > 0 {
1116 b := nl.Uint32Attr(uint32(route.RtoMin))
1117 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTO_MIN, b))
1118 }
1119 if route.InitRwnd > 0 {
1120 b := nl.Uint32Attr(uint32(route.InitRwnd))
1121 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_INITRWND, b))
1122 }
1123 if route.QuickACK > 0 {
1124 b := nl.Uint32Attr(uint32(route.QuickACK))
1125 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_QUICKACK, b))
1126 }
1127 if route.Congctl != "" {
1128 b := nl.ZeroTerminated(route.Congctl)
1129 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_CC_ALGO, b))
1130 }
1131 if route.FastOpenNoCookie > 0 {
1132 b := nl.Uint32Attr(uint32(route.FastOpenNoCookie))
1133 metrics = append(metrics, nl.NewRtAttr(unix.RTAX_FASTOPEN_NO_COOKIE, b))
1134 }
1135
1136 if metrics != nil {
1137 attr := nl.NewRtAttr(unix.RTA_METRICS, nil)
1138 for _, metric := range metrics {
1139 attr.AddChild(metric)
1140 }
1141 rtAttrs = append(rtAttrs, attr)
1142 }
1143
1144 msg.Flags = uint32(route.Flags)
1145 msg.Scope = uint8(route.Scope)
1146
1147 if msg.Family == 0 {
1148 msg.Family = uint8(family)
1149 }
1150 req.AddData(msg)
1151 for _, attr := range rtAttrs {
1152 req.AddData(attr)
1153 }
1154
1155 if (req.NlMsghdr.Type != unix.RTM_GETROUTE) || (req.NlMsghdr.Type == unix.RTM_GETROUTE && route.LinkIndex > 0) {
1156 b := make([]byte, 4)
1157 native.PutUint32(b, uint32(route.LinkIndex))
1158 req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
1159 }
1160 return nil
1161 }
1162
1163
1164
1165
1166 func RouteList(link Link, family int) ([]Route, error) {
1167 return pkgHandle.RouteList(link, family)
1168 }
1169
1170
1171
1172
1173 func (h *Handle) RouteList(link Link, family int) ([]Route, error) {
1174 routeFilter := &Route{}
1175 if link != nil {
1176 routeFilter.LinkIndex = link.Attrs().Index
1177
1178 return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
1179 }
1180 return h.RouteListFiltered(family, routeFilter, 0)
1181 }
1182
1183
1184
1185 func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
1186 return pkgHandle.RouteListFiltered(family, filter, filterMask)
1187 }
1188
1189
1190
1191 func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
1192 var res []Route
1193 err := h.RouteListFilteredIter(family, filter, filterMask, func(route Route) (cont bool) {
1194 res = append(res, route)
1195 return true
1196 })
1197 if err != nil {
1198 return nil, err
1199 }
1200 return res, nil
1201 }
1202
1203
1204
1205 func RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
1206 return pkgHandle.RouteListFilteredIter(family, filter, filterMask, f)
1207 }
1208
1209 func (h *Handle) RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
1210 req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
1211 rtmsg := &nl.RtMsg{}
1212 rtmsg.Family = uint8(family)
1213
1214 var parseErr error
1215 err := h.routeHandleIter(filter, req, rtmsg, func(m []byte) bool {
1216 msg := nl.DeserializeRtMsg(m)
1217 if family != FAMILY_ALL && msg.Family != uint8(family) {
1218
1219 return true
1220 }
1221 if msg.Flags&unix.RTM_F_CLONED != 0 {
1222
1223 return true
1224 }
1225 if msg.Table != unix.RT_TABLE_MAIN {
1226 if filter == nil || filterMask&RT_FILTER_TABLE == 0 {
1227
1228 return true
1229 }
1230 }
1231 route, err := deserializeRoute(m)
1232 if err != nil {
1233 parseErr = err
1234 return false
1235 }
1236 if filter != nil {
1237 switch {
1238 case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table:
1239 return true
1240 case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
1241 return true
1242 case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope:
1243 return true
1244 case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type:
1245 return true
1246 case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
1247 return true
1248 case filterMask&RT_FILTER_REALM != 0 && route.Realm != filter.Realm:
1249 return true
1250 case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
1251 return true
1252 case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
1253 return true
1254 case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw):
1255 return true
1256 case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src):
1257 return true
1258 case filterMask&RT_FILTER_DST != 0:
1259 if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) {
1260 if filter.Dst == nil {
1261 filter.Dst = genZeroIPNet(family)
1262 }
1263 if !ipNetEqual(route.Dst, filter.Dst) {
1264 return true
1265 }
1266 }
1267 case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit:
1268 return true
1269 }
1270 }
1271 return f(route)
1272 })
1273 if err != nil {
1274 return err
1275 }
1276 if parseErr != nil {
1277 return parseErr
1278 }
1279 return nil
1280 }
1281
1282
1283 func deserializeRoute(m []byte) (Route, error) {
1284 msg := nl.DeserializeRtMsg(m)
1285 attrs, err := nl.ParseRouteAttr(m[msg.Len():])
1286 if err != nil {
1287 return Route{}, err
1288 }
1289 route := Route{
1290 Scope: Scope(msg.Scope),
1291 Protocol: RouteProtocol(int(msg.Protocol)),
1292 Table: int(msg.Table),
1293 Type: int(msg.Type),
1294 Tos: int(msg.Tos),
1295 Flags: int(msg.Flags),
1296 Family: int(msg.Family),
1297 }
1298
1299 var encap, encapType syscall.NetlinkRouteAttr
1300 for _, attr := range attrs {
1301 switch attr.Attr.Type {
1302 case unix.RTA_GATEWAY:
1303 route.Gw = net.IP(attr.Value)
1304 case unix.RTA_PREFSRC:
1305 route.Src = net.IP(attr.Value)
1306 case unix.RTA_DST:
1307 if msg.Family == nl.FAMILY_MPLS {
1308 stack := nl.DecodeMPLSStack(attr.Value)
1309 if len(stack) == 0 || len(stack) > 1 {
1310 return route, fmt.Errorf("invalid MPLS RTA_DST")
1311 }
1312 route.MPLSDst = &stack[0]
1313 } else {
1314 route.Dst = &net.IPNet{
1315 IP: attr.Value,
1316 Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
1317 }
1318 }
1319 case unix.RTA_OIF:
1320 route.LinkIndex = int(native.Uint32(attr.Value[0:4]))
1321 case unix.RTA_IIF:
1322 route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
1323 case unix.RTA_PRIORITY:
1324 route.Priority = int(native.Uint32(attr.Value[0:4]))
1325 case unix.RTA_FLOW:
1326 route.Realm = int(native.Uint32(attr.Value[0:4]))
1327 case unix.RTA_TABLE:
1328 route.Table = int(native.Uint32(attr.Value[0:4]))
1329 case unix.RTA_MULTIPATH:
1330 parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) {
1331 if len(value) < unix.SizeofRtNexthop {
1332 return nil, nil, fmt.Errorf("lack of bytes")
1333 }
1334 nh := nl.DeserializeRtNexthop(value)
1335 if len(value) < int(nh.RtNexthop.Len) {
1336 return nil, nil, fmt.Errorf("lack of bytes")
1337 }
1338 info := &NexthopInfo{
1339 LinkIndex: int(nh.RtNexthop.Ifindex),
1340 Hops: int(nh.RtNexthop.Hops),
1341 Flags: int(nh.RtNexthop.Flags),
1342 }
1343 attrs, err := nl.ParseRouteAttr(value[unix.SizeofRtNexthop:int(nh.RtNexthop.Len)])
1344 if err != nil {
1345 return nil, nil, err
1346 }
1347 var encap, encapType syscall.NetlinkRouteAttr
1348 for _, attr := range attrs {
1349 switch attr.Attr.Type {
1350 case unix.RTA_GATEWAY:
1351 info.Gw = net.IP(attr.Value)
1352 case unix.RTA_NEWDST:
1353 var d Destination
1354 switch msg.Family {
1355 case nl.FAMILY_MPLS:
1356 d = &MPLSDestination{}
1357 }
1358 if err := d.Decode(attr.Value); err != nil {
1359 return nil, nil, err
1360 }
1361 info.NewDst = d
1362 case unix.RTA_ENCAP_TYPE:
1363 encapType = attr
1364 case unix.RTA_ENCAP:
1365 encap = attr
1366 case unix.RTA_VIA:
1367 d := &Via{}
1368 if err := d.Decode(attr.Value); err != nil {
1369 return nil, nil, err
1370 }
1371 info.Via = d
1372 }
1373 }
1374
1375 if len(encap.Value) != 0 && len(encapType.Value) != 0 {
1376 typ := int(native.Uint16(encapType.Value[0:2]))
1377 var e Encap
1378 switch typ {
1379 case nl.LWTUNNEL_ENCAP_MPLS:
1380 e = &MPLSEncap{}
1381 if err := e.Decode(encap.Value); err != nil {
1382 return nil, nil, err
1383 }
1384 }
1385 info.Encap = e
1386 }
1387
1388 return info, value[int(nh.RtNexthop.Len):], nil
1389 }
1390 rest := attr.Value
1391 for len(rest) > 0 {
1392 info, buf, err := parseRtNexthop(rest)
1393 if err != nil {
1394 return route, err
1395 }
1396 route.MultiPath = append(route.MultiPath, info)
1397 rest = buf
1398 }
1399 case unix.RTA_NEWDST:
1400 var d Destination
1401 switch msg.Family {
1402 case nl.FAMILY_MPLS:
1403 d = &MPLSDestination{}
1404 }
1405 if err := d.Decode(attr.Value); err != nil {
1406 return route, err
1407 }
1408 route.NewDst = d
1409 case unix.RTA_VIA:
1410 v := &Via{}
1411 if err := v.Decode(attr.Value); err != nil {
1412 return route, err
1413 }
1414 route.Via = v
1415 case unix.RTA_ENCAP_TYPE:
1416 encapType = attr
1417 case unix.RTA_ENCAP:
1418 encap = attr
1419 case unix.RTA_METRICS:
1420 metrics, err := nl.ParseRouteAttr(attr.Value)
1421 if err != nil {
1422 return route, err
1423 }
1424 for _, metric := range metrics {
1425 switch metric.Attr.Type {
1426 case unix.RTAX_MTU:
1427 route.MTU = int(native.Uint32(metric.Value[0:4]))
1428 case unix.RTAX_WINDOW:
1429 route.Window = int(native.Uint32(metric.Value[0:4]))
1430 case unix.RTAX_RTT:
1431 route.Rtt = int(native.Uint32(metric.Value[0:4]))
1432 case unix.RTAX_RTTVAR:
1433 route.RttVar = int(native.Uint32(metric.Value[0:4]))
1434 case unix.RTAX_SSTHRESH:
1435 route.Ssthresh = int(native.Uint32(metric.Value[0:4]))
1436 case unix.RTAX_CWND:
1437 route.Cwnd = int(native.Uint32(metric.Value[0:4]))
1438 case unix.RTAX_ADVMSS:
1439 route.AdvMSS = int(native.Uint32(metric.Value[0:4]))
1440 case unix.RTAX_REORDERING:
1441 route.Reordering = int(native.Uint32(metric.Value[0:4]))
1442 case unix.RTAX_HOPLIMIT:
1443 route.Hoplimit = int(native.Uint32(metric.Value[0:4]))
1444 case unix.RTAX_INITCWND:
1445 route.InitCwnd = int(native.Uint32(metric.Value[0:4]))
1446 case unix.RTAX_FEATURES:
1447 route.Features = int(native.Uint32(metric.Value[0:4]))
1448 case unix.RTAX_RTO_MIN:
1449 route.RtoMin = int(native.Uint32(metric.Value[0:4]))
1450 case unix.RTAX_INITRWND:
1451 route.InitRwnd = int(native.Uint32(metric.Value[0:4]))
1452 case unix.RTAX_QUICKACK:
1453 route.QuickACK = int(native.Uint32(metric.Value[0:4]))
1454 case unix.RTAX_CC_ALGO:
1455 route.Congctl = nl.BytesToString(metric.Value)
1456 case unix.RTAX_FASTOPEN_NO_COOKIE:
1457 route.FastOpenNoCookie = int(native.Uint32(metric.Value[0:4]))
1458 }
1459 }
1460 }
1461 }
1462
1463
1464 if route.Dst == nil {
1465 var addLen int
1466 var ip net.IP
1467 switch msg.Family {
1468 case FAMILY_V4:
1469 addLen = net.IPv4len
1470 ip = net.IPv4zero
1471 case FAMILY_V6:
1472 addLen = net.IPv6len
1473 ip = net.IPv6zero
1474 }
1475
1476 if addLen != 0 {
1477 route.Dst = &net.IPNet{
1478 IP: ip,
1479 Mask: net.CIDRMask(int(msg.Dst_len), 8*addLen),
1480 }
1481 }
1482 }
1483
1484 if len(encap.Value) != 0 && len(encapType.Value) != 0 {
1485 typ := int(native.Uint16(encapType.Value[0:2]))
1486 var e Encap
1487 switch typ {
1488 case nl.LWTUNNEL_ENCAP_MPLS:
1489 e = &MPLSEncap{}
1490 if err := e.Decode(encap.Value); err != nil {
1491 return route, err
1492 }
1493 case nl.LWTUNNEL_ENCAP_SEG6:
1494 e = &SEG6Encap{}
1495 if err := e.Decode(encap.Value); err != nil {
1496 return route, err
1497 }
1498 case nl.LWTUNNEL_ENCAP_SEG6_LOCAL:
1499 e = &SEG6LocalEncap{}
1500 if err := e.Decode(encap.Value); err != nil {
1501 return route, err
1502 }
1503 case nl.LWTUNNEL_ENCAP_BPF:
1504 e = &BpfEncap{}
1505 if err := e.Decode(encap.Value); err != nil {
1506 return route, err
1507 }
1508 }
1509 route.Encap = e
1510 }
1511
1512 return route, nil
1513 }
1514
1515
1516
1517 type RouteGetOptions struct {
1518 Iif string
1519 IifIndex int
1520 Oif string
1521 VrfName string
1522 SrcAddr net.IP
1523 UID *uint32
1524 Mark uint32
1525 FIBMatch bool
1526 }
1527
1528
1529
1530 func RouteGetWithOptions(destination net.IP, options *RouteGetOptions) ([]Route, error) {
1531 return pkgHandle.RouteGetWithOptions(destination, options)
1532 }
1533
1534
1535
1536 func RouteGet(destination net.IP) ([]Route, error) {
1537 return pkgHandle.RouteGet(destination)
1538 }
1539
1540
1541
1542 func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOptions) ([]Route, error) {
1543 req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_REQUEST)
1544 family := nl.GetIPFamily(destination)
1545 var destinationData []byte
1546 var bitlen uint8
1547 if family == FAMILY_V4 {
1548 destinationData = destination.To4()
1549 bitlen = 32
1550 } else {
1551 destinationData = destination.To16()
1552 bitlen = 128
1553 }
1554 msg := &nl.RtMsg{}
1555 msg.Family = uint8(family)
1556 msg.Dst_len = bitlen
1557 if options != nil && options.SrcAddr != nil {
1558 msg.Src_len = bitlen
1559 }
1560 msg.Flags = unix.RTM_F_LOOKUP_TABLE
1561 if options != nil && options.FIBMatch {
1562 msg.Flags |= unix.RTM_F_FIB_MATCH
1563 }
1564 req.AddData(msg)
1565
1566 rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData)
1567 req.AddData(rtaDst)
1568
1569 if options != nil {
1570 if options.VrfName != "" {
1571 link, err := h.LinkByName(options.VrfName)
1572 if err != nil {
1573 return nil, err
1574 }
1575 b := make([]byte, 4)
1576 native.PutUint32(b, uint32(link.Attrs().Index))
1577
1578 req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
1579 }
1580
1581 iifIndex := 0
1582 if len(options.Iif) > 0 {
1583 link, err := h.LinkByName(options.Iif)
1584 if err != nil {
1585 return nil, err
1586 }
1587
1588 iifIndex = link.Attrs().Index
1589 } else if options.IifIndex > 0 {
1590 iifIndex = options.IifIndex
1591 }
1592
1593 if iifIndex > 0 {
1594 b := make([]byte, 4)
1595 native.PutUint32(b, uint32(iifIndex))
1596
1597 req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
1598 }
1599
1600 if len(options.Oif) > 0 {
1601 link, err := h.LinkByName(options.Oif)
1602 if err != nil {
1603 return nil, err
1604 }
1605
1606 b := make([]byte, 4)
1607 native.PutUint32(b, uint32(link.Attrs().Index))
1608
1609 req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
1610 }
1611
1612 if options.SrcAddr != nil {
1613 var srcAddr []byte
1614 if family == FAMILY_V4 {
1615 srcAddr = options.SrcAddr.To4()
1616 } else {
1617 srcAddr = options.SrcAddr.To16()
1618 }
1619
1620 req.AddData(nl.NewRtAttr(unix.RTA_SRC, srcAddr))
1621 }
1622
1623 if options.UID != nil {
1624 uid := *options.UID
1625 b := make([]byte, 4)
1626 native.PutUint32(b, uid)
1627
1628 req.AddData(nl.NewRtAttr(unix.RTA_UID, b))
1629 }
1630
1631 if options.Mark > 0 {
1632 b := make([]byte, 4)
1633 native.PutUint32(b, options.Mark)
1634
1635 req.AddData(nl.NewRtAttr(unix.RTA_MARK, b))
1636 }
1637 }
1638
1639 msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
1640 if err != nil {
1641 return nil, err
1642 }
1643
1644 var res []Route
1645 for _, m := range msgs {
1646 route, err := deserializeRoute(m)
1647 if err != nil {
1648 return nil, err
1649 }
1650 res = append(res, route)
1651 }
1652 return res, nil
1653 }
1654
1655
1656
1657 func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
1658 return h.RouteGetWithOptions(destination, nil)
1659 }
1660
1661
1662
1663 func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
1664 return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false)
1665 }
1666
1667
1668
1669 func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
1670 return routeSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
1671 }
1672
1673
1674
1675 type RouteSubscribeOptions struct {
1676 Namespace *netns.NsHandle
1677 ErrorCallback func(error)
1678 ListExisting bool
1679 ReceiveBufferSize int
1680 ReceiveBufferForceSize bool
1681 ReceiveTimeout *unix.Timeval
1682 }
1683
1684
1685
1686
1687 func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, options RouteSubscribeOptions) error {
1688 if options.Namespace == nil {
1689 none := netns.None()
1690 options.Namespace = &none
1691 }
1692 return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
1693 options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
1694 }
1695
1696 func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
1697 rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error {
1698 s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_ROUTE, unix.RTNLGRP_IPV6_ROUTE)
1699 if err != nil {
1700 return err
1701 }
1702 if rcvTimeout != nil {
1703 if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
1704 return err
1705 }
1706 }
1707 if rcvbuf != 0 {
1708 err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce)
1709 if err != nil {
1710 return err
1711 }
1712 }
1713 if done != nil {
1714 go func() {
1715 <-done
1716 s.Close()
1717 }()
1718 }
1719 if listExisting {
1720 req := pkgHandle.newNetlinkRequest(unix.RTM_GETROUTE,
1721 unix.NLM_F_DUMP)
1722 infmsg := nl.NewIfInfomsg(unix.AF_UNSPEC)
1723 req.AddData(infmsg)
1724 if err := s.Send(req); err != nil {
1725 return err
1726 }
1727 }
1728 go func() {
1729 defer close(ch)
1730 for {
1731 msgs, from, err := s.Receive()
1732 if err != nil {
1733 if cberr != nil {
1734 cberr(fmt.Errorf("Receive failed: %v",
1735 err))
1736 }
1737 return
1738 }
1739 if from.Pid != nl.PidKernel {
1740 if cberr != nil {
1741 cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
1742 }
1743 continue
1744 }
1745 for _, m := range msgs {
1746 if m.Header.Type == unix.NLMSG_DONE {
1747 continue
1748 }
1749 if m.Header.Type == unix.NLMSG_ERROR {
1750 error := int32(native.Uint32(m.Data[0:4]))
1751 if error == 0 {
1752 continue
1753 }
1754 if cberr != nil {
1755 cberr(fmt.Errorf("error message: %v",
1756 syscall.Errno(-error)))
1757 }
1758 continue
1759 }
1760 route, err := deserializeRoute(m.Data)
1761 if err != nil {
1762 if cberr != nil {
1763 cberr(err)
1764 }
1765 continue
1766 }
1767 ch <- RouteUpdate{
1768 Type: m.Header.Type,
1769 NlFlags: m.Header.Flags & (unix.NLM_F_REPLACE | unix.NLM_F_EXCL | unix.NLM_F_CREATE | unix.NLM_F_APPEND),
1770 Route: route,
1771 }
1772 }
1773 }
1774 }()
1775
1776 return nil
1777 }
1778
1779 func (p RouteProtocol) String() string {
1780 switch int(p) {
1781 case unix.RTPROT_BABEL:
1782 return "babel"
1783 case unix.RTPROT_BGP:
1784 return "bgp"
1785 case unix.RTPROT_BIRD:
1786 return "bird"
1787 case unix.RTPROT_BOOT:
1788 return "boot"
1789 case unix.RTPROT_DHCP:
1790 return "dhcp"
1791 case unix.RTPROT_DNROUTED:
1792 return "dnrouted"
1793 case unix.RTPROT_EIGRP:
1794 return "eigrp"
1795 case unix.RTPROT_GATED:
1796 return "gated"
1797 case unix.RTPROT_ISIS:
1798 return "isis"
1799
1800
1801 case unix.RTPROT_KERNEL:
1802 return "kernel"
1803 case unix.RTPROT_MROUTED:
1804 return "mrouted"
1805 case unix.RTPROT_MRT:
1806 return "mrt"
1807 case unix.RTPROT_NTK:
1808 return "ntk"
1809 case unix.RTPROT_OSPF:
1810 return "ospf"
1811 case unix.RTPROT_RA:
1812 return "ra"
1813 case unix.RTPROT_REDIRECT:
1814 return "redirect"
1815 case unix.RTPROT_RIP:
1816 return "rip"
1817 case unix.RTPROT_STATIC:
1818 return "static"
1819 case unix.RTPROT_UNSPEC:
1820 return "unspec"
1821 case unix.RTPROT_XORP:
1822 return "xorp"
1823 case unix.RTPROT_ZEBRA:
1824 return "zebra"
1825 default:
1826 return strconv.Itoa(int(p))
1827 }
1828 }
1829
1830
1831 func genZeroIPNet(family int) *net.IPNet {
1832 var addLen int
1833 var ip net.IP
1834 switch family {
1835 case FAMILY_V4:
1836 addLen = net.IPv4len
1837 ip = net.IPv4zero
1838 case FAMILY_V6:
1839 addLen = net.IPv6len
1840 ip = net.IPv6zero
1841 }
1842 if addLen != 0 {
1843 return &net.IPNet{
1844 IP: ip,
1845 Mask: net.CIDRMask(0, 8*addLen),
1846 }
1847 }
1848 return nil
1849 }
1850
View as plain text