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  }