github.com/vishvananda/netlink@v1.3.1/route_linux.go (about)

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