github.com/vishvananda/netlink@v1.3.0/route_linux.go (about) 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 // RtAttr is shared so it is in netlink_linux.go 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 // SEG6 definitions 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 // Get Length(l) & Type(typ) : 2 + 2 bytes 208 l := native.Uint16(buf) 209 if len(buf) < int(l) { 210 return fmt.Errorf("lack of bytes") 211 } 212 buf = buf[:l] // make sure buf size upper limit is Length 213 typ := native.Uint16(buf[2:]) 214 // LWTUNNEL_ENCAP_SEG6 has only one attr type SEG6_IPTUNNEL_SRH 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 // append segment backwards (from n to 0) since seg#0 is the last segment. 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 // SEG6LocalEncap definitions 267 type SEG6LocalEncap struct { 268 Flags [nl.SEG6_LOCAL_MAX]bool 269 Action int 270 Segments []net.IP // from SRH in seg6_local_lwt 271 Table int // table id for End.T and End.DT6 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) // length 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 // append segment backwards (from n to 0) since seg#0 is the last segment. 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 // compare all arrays first 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 // compare values 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 // Encap BPF definitions 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 // SetProg adds a bpf function to the route via netlink RTA_ENCAP. The fd must be a bpf 496 // program loaded with bpf(type=BPF_PROG_TYPE_LWT_*) matching the direction the program should 497 // be applied to (LWT_BPF_IN, LWT_BPF_OUT, LWT_BPF_XMIT). 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 // SetXmitHeadroom sets the xmit headroom (LWT_BPF_MAX_HEADROOM) via netlink RTA_ENCAP. 511 // maximum headroom is LWT_BPF_MAX_HEADROOM 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 // nl.LWT_BPF_UNSPEC 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 // IP6tnlEncap definition 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 // e.TC = attr.Value[0] 662 err = fmt.Errorf("decoding TC in IP6tnlEncap is not supported") 663 case nl.LWTUNNEL_IP6_FLAGS: 664 // e.Flags = uint16(native.Uint16(attr.Value[0:2])) 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) // 2+2+8 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) // 2+2+16 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 // resTc := make([]byte, 5) 698 // native.PutUint16(resTc, 5) 699 // native.PutUint16(resTc[2:], nl.LWTUNNEL_IP6_TC) 700 // resTc[4] = e.TC 701 // final = append(final,resTc...) 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 // resFlags := make([]byte, 6) 710 // native.PutUint16(resFlags, 6) 711 // native.PutUint16(resFlags[2:], nl.LWTUNNEL_IP6_FLAGS) 712 // native.PutUint16(resFlags[4:], e.Flags) 713 // final = append(final,resFlags...) 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 // RouteAdd will add a route to the system. 790 // Equivalent to: `ip route add $route` 791 func RouteAdd(route *Route) error { 792 return pkgHandle.RouteAdd(route) 793 } 794 795 // RouteAdd will add a route to the system. 796 // Equivalent to: `ip route add $route` 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 // RouteAppend will append a route to the system. 805 // Equivalent to: `ip route append $route` 806 func RouteAppend(route *Route) error { 807 return pkgHandle.RouteAppend(route) 808 } 809 810 // RouteAppend will append a route to the system. 811 // Equivalent to: `ip route append $route` 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 // RouteAddEcmp will add a route to the system. 820 func RouteAddEcmp(route *Route) error { 821 return pkgHandle.RouteAddEcmp(route) 822 } 823 824 // RouteAddEcmp will add a route to the system. 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 // RouteChange will change an existing route in the system. 833 // Equivalent to: `ip route change $route` 834 func RouteChange(route *Route) error { 835 return pkgHandle.RouteChange(route) 836 } 837 838 // RouteChange will change an existing route in the system. 839 // Equivalent to: `ip route change $route` 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 // RouteReplace will add a route to the system. 848 // Equivalent to: `ip route replace $route` 849 func RouteReplace(route *Route) error { 850 return pkgHandle.RouteReplace(route) 851 } 852 853 // RouteReplace will add a route to the system. 854 // Equivalent to: `ip route replace $route` 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 // RouteDel will delete a route from the system. 863 // Equivalent to: `ip route del $route` 864 func RouteDel(route *Route) error { 865 return pkgHandle.RouteDel(route) 866 } 867 868 // RouteDel will delete a route from the system. 869 // Equivalent to: `ip route del $route` 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 // The commonly used src ip for routes is actually PREFSRC 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 // only overwrite family if it was not set in msg 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 // RouteList gets a list of routes in the system. 1164 // Equivalent to: `ip route show`. 1165 // The list can be filtered by link and ip family. 1166 func RouteList(link Link, family int) ([]Route, error) { 1167 return pkgHandle.RouteList(link, family) 1168 } 1169 1170 // RouteList gets a list of routes in the system. 1171 // Equivalent to: `ip route show`. 1172 // The list can be filtered by link and ip family. 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 // RouteListFiltered gets a list of routes in the system filtered with specified rules. 1184 // All rules must be defined in RouteFilter struct 1185 func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { 1186 return pkgHandle.RouteListFiltered(family, filter, filterMask) 1187 } 1188 1189 // RouteListFiltered gets a list of routes in the system filtered with specified rules. 1190 // All rules must be defined in RouteFilter struct 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 // RouteListFilteredIter passes each route that matches the filter to the given iterator func. Iteration continues 1204 // until all routes are loaded or the func returns false. 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 // Ignore routes not matching requested family 1219 return true 1220 } 1221 if msg.Flags&unix.RTM_F_CLONED != 0 { 1222 // Ignore cloned routes 1223 return true 1224 } 1225 if msg.Table != unix.RT_TABLE_MAIN { 1226 if filter == nil || filterMask&RT_FILTER_TABLE == 0 { 1227 // Ignore non-main tables 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 // deserializeRoute decodes a binary netlink message into a Route struct 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 // Same logic to generate "default" dst with iproute2 implementation 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 // RouteGetOptions contains a set of options to use with 1516 // RouteGetWithOptions 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 // RouteGetWithOptions gets a route to a specific destination from the host system. 1529 // Equivalent to: 'ip route get <> vrf <VrfName>'. 1530 func RouteGetWithOptions(destination net.IP, options *RouteGetOptions) ([]Route, error) { 1531 return pkgHandle.RouteGetWithOptions(destination, options) 1532 } 1533 1534 // RouteGet gets a route to a specific destination from the host system. 1535 // Equivalent to: 'ip route get'. 1536 func RouteGet(destination net.IP) ([]Route, error) { 1537 return pkgHandle.RouteGet(destination) 1538 } 1539 1540 // RouteGetWithOptions gets a route to a specific destination from the host system. 1541 // Equivalent to: 'ip route get <> vrf <VrfName>'. 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 // RouteGet gets a route to a specific destination from the host system. 1656 // Equivalent to: 'ip route get'. 1657 func (h *Handle) RouteGet(destination net.IP) ([]Route, error) { 1658 return h.RouteGetWithOptions(destination, nil) 1659 } 1660 1661 // RouteSubscribe takes a chan down which notifications will be sent 1662 // when routes are added or deleted. Close the 'done' chan to stop subscription. 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 // RouteSubscribeAt works like RouteSubscribe plus it allows the caller 1668 // to choose the network namespace in which to subscribe (ns). 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 // RouteSubscribeOptions contains a set of options to use with 1674 // RouteSubscribeWithOptions. 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 // RouteSubscribeWithOptions work like RouteSubscribe but enable to 1685 // provide additional options to modify the behavior. Currently, the 1686 // namespace can be provided as well as an error callback. 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 // case unix.RTPROT_KEEPALIVED: 1800 // return "keepalived" 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 // genZeroIPNet returns 0.0.0.0/0 or ::/0 for IPv4 or IPv6, otherwise nil 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 }