build(deps): bump github.com/vishvananda/netlink
Bumps [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink) from 1.2.1-beta.2 to 1.3.0. - [Release notes](https://github.com/vishvananda/netlink/releases) - [Commits](https://github.com/vishvananda/netlink/compare/v1.2.1-beta.2...v1.3.0) --- updated-dependencies: - dependency-name: github.com/vishvananda/netlink dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
		
							
								
								
									
										428
									
								
								vendor/github.com/vishvananda/netlink/route_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										428
									
								
								vendor/github.com/vishvananda/netlink/route_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -41,7 +41,6 @@ func (s Scope) String() string {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	FLAG_ONLINK    NextHopFlag = unix.RTNH_F_ONLINK
 | 
			
		||||
	FLAG_PERVASIVE NextHopFlag = unix.RTNH_F_PERVASIVE
 | 
			
		||||
@@ -274,6 +273,16 @@ type SEG6LocalEncap struct {
 | 
			
		||||
	In6Addr  net.IP
 | 
			
		||||
	Iif      int
 | 
			
		||||
	Oif      int
 | 
			
		||||
	bpf      bpfObj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *SEG6LocalEncap) SetProg(progFd int, progName string) error {
 | 
			
		||||
	if progFd <= 0 {
 | 
			
		||||
		return fmt.Errorf("seg6local bpf SetProg: invalid fd")
 | 
			
		||||
	}
 | 
			
		||||
	e.bpf.progFd = progFd
 | 
			
		||||
	e.bpf.progName = progName
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *SEG6LocalEncap) Type() int {
 | 
			
		||||
@@ -307,6 +316,22 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
 | 
			
		||||
		case nl.SEG6_LOCAL_OIF:
 | 
			
		||||
			e.Oif = int(native.Uint32(attr.Value[0:4]))
 | 
			
		||||
			e.Flags[nl.SEG6_LOCAL_OIF] = true
 | 
			
		||||
		case nl.SEG6_LOCAL_BPF:
 | 
			
		||||
			var bpfAttrs []syscall.NetlinkRouteAttr
 | 
			
		||||
			bpfAttrs, err = nl.ParseRouteAttr(attr.Value)
 | 
			
		||||
			bpfobj := bpfObj{}
 | 
			
		||||
			for _, bpfAttr := range bpfAttrs {
 | 
			
		||||
				switch bpfAttr.Attr.Type {
 | 
			
		||||
				case nl.LWT_BPF_PROG_FD:
 | 
			
		||||
					bpfobj.progFd = int(native.Uint32(bpfAttr.Value))
 | 
			
		||||
				case nl.LWT_BPF_PROG_NAME:
 | 
			
		||||
					bpfobj.progName = string(bpfAttr.Value)
 | 
			
		||||
				default:
 | 
			
		||||
					err = fmt.Errorf("seg6local bpf decode: unknown attribute: Type %d", bpfAttr.Attr)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			e.bpf = bpfobj
 | 
			
		||||
			e.Flags[nl.SEG6_LOCAL_BPF] = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
@@ -368,6 +393,16 @@ func (e *SEG6LocalEncap) Encode() ([]byte, error) {
 | 
			
		||||
		native.PutUint32(attr[4:], uint32(e.Oif))
 | 
			
		||||
		res = append(res, attr...)
 | 
			
		||||
	}
 | 
			
		||||
	if e.Flags[nl.SEG6_LOCAL_BPF] {
 | 
			
		||||
		attr := nl.NewRtAttr(nl.SEG6_LOCAL_BPF, []byte{})
 | 
			
		||||
		if e.bpf.progFd != 0 {
 | 
			
		||||
			attr.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(e.bpf.progFd)))
 | 
			
		||||
		}
 | 
			
		||||
		if e.bpf.progName != "" {
 | 
			
		||||
			attr.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(e.bpf.progName))
 | 
			
		||||
		}
 | 
			
		||||
		res = append(res, attr.Serialize()...)
 | 
			
		||||
	}
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
func (e *SEG6LocalEncap) String() string {
 | 
			
		||||
@@ -401,12 +436,15 @@ func (e *SEG6LocalEncap) String() string {
 | 
			
		||||
	}
 | 
			
		||||
	if e.Flags[nl.SEG6_LOCAL_SRH] {
 | 
			
		||||
		segs := make([]string, 0, len(e.Segments))
 | 
			
		||||
		//append segment backwards (from n to 0) since seg#0 is the last segment.
 | 
			
		||||
		// append segment backwards (from n to 0) since seg#0 is the last segment.
 | 
			
		||||
		for i := len(e.Segments); i > 0; i-- {
 | 
			
		||||
			segs = append(segs, e.Segments[i-1].String())
 | 
			
		||||
		}
 | 
			
		||||
		strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " ")))
 | 
			
		||||
	}
 | 
			
		||||
	if e.Flags[nl.SEG6_LOCAL_BPF] {
 | 
			
		||||
		strs = append(strs, fmt.Sprintf("bpf %s[%d]", e.bpf.progName, e.bpf.progFd))
 | 
			
		||||
	}
 | 
			
		||||
	return strings.Join(strs, " ")
 | 
			
		||||
}
 | 
			
		||||
func (e *SEG6LocalEncap) Equal(x Encap) bool {
 | 
			
		||||
@@ -438,7 +476,7 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool {
 | 
			
		||||
	if !e.InAddr.Equal(o.InAddr) || !e.In6Addr.Equal(o.In6Addr) {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif {
 | 
			
		||||
	if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif || e.bpf != o.bpf {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
@@ -590,6 +628,109 @@ func (e *BpfEncap) Equal(x Encap) bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IP6tnlEncap definition
 | 
			
		||||
type IP6tnlEncap struct {
 | 
			
		||||
	ID       uint64
 | 
			
		||||
	Dst      net.IP
 | 
			
		||||
	Src      net.IP
 | 
			
		||||
	Hoplimit uint8
 | 
			
		||||
	TC       uint8
 | 
			
		||||
	Flags    uint16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *IP6tnlEncap) Type() int {
 | 
			
		||||
	return nl.LWTUNNEL_ENCAP_IP6
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *IP6tnlEncap) Decode(buf []byte) error {
 | 
			
		||||
	attrs, err := nl.ParseRouteAttr(buf)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	for _, attr := range attrs {
 | 
			
		||||
		switch attr.Attr.Type {
 | 
			
		||||
		case nl.LWTUNNEL_IP6_ID:
 | 
			
		||||
			e.ID = uint64(native.Uint64(attr.Value[0:4]))
 | 
			
		||||
		case nl.LWTUNNEL_IP6_DST:
 | 
			
		||||
			e.Dst = net.IP(attr.Value[:])
 | 
			
		||||
		case nl.LWTUNNEL_IP6_SRC:
 | 
			
		||||
			e.Src = net.IP(attr.Value[:])
 | 
			
		||||
		case nl.LWTUNNEL_IP6_HOPLIMIT:
 | 
			
		||||
			e.Hoplimit = attr.Value[0]
 | 
			
		||||
		case nl.LWTUNNEL_IP6_TC:
 | 
			
		||||
			// e.TC = attr.Value[0]
 | 
			
		||||
			err = fmt.Errorf("decoding TC in IP6tnlEncap is not supported")
 | 
			
		||||
		case nl.LWTUNNEL_IP6_FLAGS:
 | 
			
		||||
			// e.Flags = uint16(native.Uint16(attr.Value[0:2]))
 | 
			
		||||
			err = fmt.Errorf("decoding FLAG in IP6tnlEncap is not supported")
 | 
			
		||||
		case nl.LWTUNNEL_IP6_PAD:
 | 
			
		||||
			err = fmt.Errorf("decoding PAD in IP6tnlEncap is not supported")
 | 
			
		||||
		case nl.LWTUNNEL_IP6_OPTS:
 | 
			
		||||
			err = fmt.Errorf("decoding OPTS in IP6tnlEncap is not supported")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *IP6tnlEncap) Encode() ([]byte, error) {
 | 
			
		||||
 | 
			
		||||
	final := []byte{}
 | 
			
		||||
 | 
			
		||||
	resID := make([]byte, 12)
 | 
			
		||||
	native.PutUint16(resID, 12) //  2+2+8
 | 
			
		||||
	native.PutUint16(resID[2:], nl.LWTUNNEL_IP6_ID)
 | 
			
		||||
	native.PutUint64(resID[4:], 0)
 | 
			
		||||
	final = append(final, resID...)
 | 
			
		||||
 | 
			
		||||
	resDst := make([]byte, 4)
 | 
			
		||||
	native.PutUint16(resDst, 20) //  2+2+16
 | 
			
		||||
	native.PutUint16(resDst[2:], nl.LWTUNNEL_IP6_DST)
 | 
			
		||||
	resDst = append(resDst, e.Dst...)
 | 
			
		||||
	final = append(final, resDst...)
 | 
			
		||||
 | 
			
		||||
	resSrc := make([]byte, 4)
 | 
			
		||||
	native.PutUint16(resSrc, 20)
 | 
			
		||||
	native.PutUint16(resSrc[2:], nl.LWTUNNEL_IP6_SRC)
 | 
			
		||||
	resSrc = append(resSrc, e.Src...)
 | 
			
		||||
	final = append(final, resSrc...)
 | 
			
		||||
 | 
			
		||||
	// resTc := make([]byte, 5)
 | 
			
		||||
	// native.PutUint16(resTc, 5)
 | 
			
		||||
	// native.PutUint16(resTc[2:], nl.LWTUNNEL_IP6_TC)
 | 
			
		||||
	// resTc[4] = e.TC
 | 
			
		||||
	// final = append(final,resTc...)
 | 
			
		||||
 | 
			
		||||
	resHops := make([]byte, 5)
 | 
			
		||||
	native.PutUint16(resHops, 5)
 | 
			
		||||
	native.PutUint16(resHops[2:], nl.LWTUNNEL_IP6_HOPLIMIT)
 | 
			
		||||
	resHops[4] = e.Hoplimit
 | 
			
		||||
	final = append(final, resHops...)
 | 
			
		||||
 | 
			
		||||
	// resFlags := make([]byte, 6)
 | 
			
		||||
	// native.PutUint16(resFlags, 6)
 | 
			
		||||
	// native.PutUint16(resFlags[2:], nl.LWTUNNEL_IP6_FLAGS)
 | 
			
		||||
	// native.PutUint16(resFlags[4:], e.Flags)
 | 
			
		||||
	// final = append(final,resFlags...)
 | 
			
		||||
 | 
			
		||||
	return final, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *IP6tnlEncap) String() string {
 | 
			
		||||
	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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *IP6tnlEncap) Equal(x Encap) bool {
 | 
			
		||||
	o, ok := x.(*IP6tnlEncap)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Via struct {
 | 
			
		||||
	AddrFamily int
 | 
			
		||||
	Addr       net.IP
 | 
			
		||||
@@ -656,7 +797,8 @@ func RouteAdd(route *Route) error {
 | 
			
		||||
func (h *Handle) RouteAdd(route *Route) error {
 | 
			
		||||
	flags := unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK
 | 
			
		||||
	req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
 | 
			
		||||
	return h.routeHandle(route, req, nl.NewRtMsg())
 | 
			
		||||
	_, err := h.routeHandle(route, req, nl.NewRtMsg())
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteAppend will append a route to the system.
 | 
			
		||||
@@ -670,7 +812,8 @@ func RouteAppend(route *Route) error {
 | 
			
		||||
func (h *Handle) RouteAppend(route *Route) error {
 | 
			
		||||
	flags := unix.NLM_F_CREATE | unix.NLM_F_APPEND | unix.NLM_F_ACK
 | 
			
		||||
	req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
 | 
			
		||||
	return h.routeHandle(route, req, nl.NewRtMsg())
 | 
			
		||||
	_, err := h.routeHandle(route, req, nl.NewRtMsg())
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteAddEcmp will add a route to the system.
 | 
			
		||||
@@ -682,7 +825,23 @@ func RouteAddEcmp(route *Route) error {
 | 
			
		||||
func (h *Handle) RouteAddEcmp(route *Route) error {
 | 
			
		||||
	flags := unix.NLM_F_CREATE | unix.NLM_F_ACK
 | 
			
		||||
	req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
 | 
			
		||||
	return h.routeHandle(route, req, nl.NewRtMsg())
 | 
			
		||||
	_, err := h.routeHandle(route, req, nl.NewRtMsg())
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteChange will change an existing route in the system.
 | 
			
		||||
// Equivalent to: `ip route change $route`
 | 
			
		||||
func RouteChange(route *Route) error {
 | 
			
		||||
	return pkgHandle.RouteChange(route)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteChange will change an existing route in the system.
 | 
			
		||||
// Equivalent to: `ip route change $route`
 | 
			
		||||
func (h *Handle) RouteChange(route *Route) error {
 | 
			
		||||
	flags := unix.NLM_F_REPLACE | unix.NLM_F_ACK
 | 
			
		||||
	req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
 | 
			
		||||
	_, err := h.routeHandle(route, req, nl.NewRtMsg())
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteReplace will add a route to the system.
 | 
			
		||||
@@ -696,7 +855,8 @@ func RouteReplace(route *Route) error {
 | 
			
		||||
func (h *Handle) RouteReplace(route *Route) error {
 | 
			
		||||
	flags := unix.NLM_F_CREATE | unix.NLM_F_REPLACE | unix.NLM_F_ACK
 | 
			
		||||
	req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
 | 
			
		||||
	return h.routeHandle(route, req, nl.NewRtMsg())
 | 
			
		||||
	_, err := h.routeHandle(route, req, nl.NewRtMsg())
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteDel will delete a route from the system.
 | 
			
		||||
@@ -709,12 +869,27 @@ func RouteDel(route *Route) error {
 | 
			
		||||
// Equivalent to: `ip route del $route`
 | 
			
		||||
func (h *Handle) RouteDel(route *Route) error {
 | 
			
		||||
	req := h.newNetlinkRequest(unix.RTM_DELROUTE, unix.NLM_F_ACK)
 | 
			
		||||
	return h.routeHandle(route, req, nl.NewRtDelMsg())
 | 
			
		||||
	_, err := h.routeHandle(route, req, nl.NewRtDelMsg())
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
 | 
			
		||||
	if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil {
 | 
			
		||||
		return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
 | 
			
		||||
func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) ([][]byte, error) {
 | 
			
		||||
	if err := h.prepareRouteReq(route, req, msg); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return req.Execute(unix.NETLINK_ROUTE, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Handle) routeHandleIter(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg, f func(msg []byte) bool) error {
 | 
			
		||||
	if err := h.prepareRouteReq(route, req, msg); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return req.ExecuteIter(unix.NETLINK_ROUTE, 0, f)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
 | 
			
		||||
	if req.NlMsghdr.Type != unix.RTM_GETROUTE && (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil {
 | 
			
		||||
		return fmt.Errorf("either Dst.IP, Src.IP or Gw must be set")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	family := -1
 | 
			
		||||
@@ -968,19 +1143,21 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
 | 
			
		||||
 | 
			
		||||
	msg.Flags = uint32(route.Flags)
 | 
			
		||||
	msg.Scope = uint8(route.Scope)
 | 
			
		||||
	msg.Family = uint8(family)
 | 
			
		||||
	// only overwrite family if it was not set in msg
 | 
			
		||||
	if msg.Family == 0 {
 | 
			
		||||
		msg.Family = uint8(family)
 | 
			
		||||
	}
 | 
			
		||||
	req.AddData(msg)
 | 
			
		||||
	for _, attr := range rtAttrs {
 | 
			
		||||
		req.AddData(attr)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b := make([]byte, 4)
 | 
			
		||||
	native.PutUint32(b, uint32(route.LinkIndex))
 | 
			
		||||
 | 
			
		||||
	req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
 | 
			
		||||
 | 
			
		||||
	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
 | 
			
		||||
	return err
 | 
			
		||||
	if (req.NlMsghdr.Type != unix.RTM_GETROUTE) || (req.NlMsghdr.Type == unix.RTM_GETROUTE && route.LinkIndex > 0) {
 | 
			
		||||
		b := make([]byte, 4)
 | 
			
		||||
		native.PutUint32(b, uint32(route.LinkIndex))
 | 
			
		||||
		req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteList gets a list of routes in the system.
 | 
			
		||||
@@ -994,13 +1171,13 @@ func RouteList(link Link, family int) ([]Route, error) {
 | 
			
		||||
// Equivalent to: `ip route show`.
 | 
			
		||||
// The list can be filtered by link and ip family.
 | 
			
		||||
func (h *Handle) RouteList(link Link, family int) ([]Route, error) {
 | 
			
		||||
	var routeFilter *Route
 | 
			
		||||
	routeFilter := &Route{}
 | 
			
		||||
	if link != nil {
 | 
			
		||||
		routeFilter = &Route{
 | 
			
		||||
			LinkIndex: link.Attrs().Index,
 | 
			
		||||
		}
 | 
			
		||||
		routeFilter.LinkIndex = link.Attrs().Index
 | 
			
		||||
 | 
			
		||||
		return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
 | 
			
		||||
	}
 | 
			
		||||
	return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF)
 | 
			
		||||
	return h.RouteListFiltered(family, routeFilter, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
 | 
			
		||||
@@ -1012,68 +1189,94 @@ func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, e
 | 
			
		||||
// RouteListFiltered gets a list of routes in the system filtered with specified rules.
 | 
			
		||||
// All rules must be defined in RouteFilter struct
 | 
			
		||||
func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
 | 
			
		||||
	req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
 | 
			
		||||
	rtmsg := nl.NewRtMsg()
 | 
			
		||||
	rtmsg.Family = uint8(family)
 | 
			
		||||
	req.AddData(rtmsg)
 | 
			
		||||
 | 
			
		||||
	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
 | 
			
		||||
	var res []Route
 | 
			
		||||
	err := h.RouteListFilteredIter(family, filter, filterMask, func(route Route) (cont bool) {
 | 
			
		||||
		res = append(res, route)
 | 
			
		||||
		return true
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	var res []Route
 | 
			
		||||
	for _, m := range msgs {
 | 
			
		||||
// RouteListFilteredIter passes each route that matches the filter to the given iterator func.  Iteration continues
 | 
			
		||||
// until all routes are loaded or the func returns false.
 | 
			
		||||
func RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
 | 
			
		||||
	return pkgHandle.RouteListFilteredIter(family, filter, filterMask, f)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Handle) RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error {
 | 
			
		||||
	req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP)
 | 
			
		||||
	rtmsg := &nl.RtMsg{}
 | 
			
		||||
	rtmsg.Family = uint8(family)
 | 
			
		||||
 | 
			
		||||
	var parseErr error
 | 
			
		||||
	err := h.routeHandleIter(filter, req, rtmsg, func(m []byte) bool {
 | 
			
		||||
		msg := nl.DeserializeRtMsg(m)
 | 
			
		||||
		if family != FAMILY_ALL && msg.Family != uint8(family) {
 | 
			
		||||
			// Ignore routes not matching requested family
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		if msg.Flags&unix.RTM_F_CLONED != 0 {
 | 
			
		||||
			// Ignore cloned routes
 | 
			
		||||
			continue
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		if msg.Table != unix.RT_TABLE_MAIN {
 | 
			
		||||
			if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 {
 | 
			
		||||
			if filter == nil || filterMask&RT_FILTER_TABLE == 0 {
 | 
			
		||||
				// Ignore non-main tables
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		route, err := deserializeRoute(m)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
			parseErr = err
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		if filter != nil {
 | 
			
		||||
			switch {
 | 
			
		||||
			case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table:
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol:
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope:
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type:
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_REALM != 0 && route.Realm != filter.Realm:
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw):
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src):
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			case filterMask&RT_FILTER_DST != 0:
 | 
			
		||||
				if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) {
 | 
			
		||||
					if filter.Dst == nil {
 | 
			
		||||
						filter.Dst = genZeroIPNet(family)
 | 
			
		||||
					}
 | 
			
		||||
					if !ipNetEqual(route.Dst, filter.Dst) {
 | 
			
		||||
						continue
 | 
			
		||||
						return true
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit:
 | 
			
		||||
				continue
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		res = append(res, route)
 | 
			
		||||
		return f(route)
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return res, nil
 | 
			
		||||
	if parseErr != nil {
 | 
			
		||||
		return parseErr
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// deserializeRoute decodes a binary netlink message into a Route struct
 | 
			
		||||
@@ -1257,6 +1460,27 @@ func deserializeRoute(m []byte) (Route, error) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Same logic to generate "default" dst with iproute2 implementation
 | 
			
		||||
	if route.Dst == nil {
 | 
			
		||||
		var addLen int
 | 
			
		||||
		var ip net.IP
 | 
			
		||||
		switch msg.Family {
 | 
			
		||||
		case FAMILY_V4:
 | 
			
		||||
			addLen = net.IPv4len
 | 
			
		||||
			ip = net.IPv4zero
 | 
			
		||||
		case FAMILY_V6:
 | 
			
		||||
			addLen = net.IPv6len
 | 
			
		||||
			ip = net.IPv6zero
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if addLen != 0 {
 | 
			
		||||
			route.Dst = &net.IPNet{
 | 
			
		||||
				IP:   ip,
 | 
			
		||||
				Mask: net.CIDRMask(int(msg.Dst_len), 8*addLen),
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(encap.Value) != 0 && len(encapType.Value) != 0 {
 | 
			
		||||
		typ := int(native.Uint16(encapType.Value[0:2]))
 | 
			
		||||
		var e Encap
 | 
			
		||||
@@ -1291,10 +1515,14 @@ func deserializeRoute(m []byte) (Route, error) {
 | 
			
		||||
// RouteGetOptions contains a set of options to use with
 | 
			
		||||
// RouteGetWithOptions
 | 
			
		||||
type RouteGetOptions struct {
 | 
			
		||||
	Iif     string
 | 
			
		||||
	Oif     string
 | 
			
		||||
	VrfName string
 | 
			
		||||
	SrcAddr net.IP
 | 
			
		||||
	Iif      string
 | 
			
		||||
	IifIndex int
 | 
			
		||||
	Oif      string
 | 
			
		||||
	VrfName  string
 | 
			
		||||
	SrcAddr  net.IP
 | 
			
		||||
	UID      *uint32
 | 
			
		||||
	Mark     uint32
 | 
			
		||||
	FIBMatch bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteGetWithOptions gets a route to a specific destination from the host system.
 | 
			
		||||
@@ -1330,6 +1558,9 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
 | 
			
		||||
		msg.Src_len = bitlen
 | 
			
		||||
	}
 | 
			
		||||
	msg.Flags = unix.RTM_F_LOOKUP_TABLE
 | 
			
		||||
	if options != nil && options.FIBMatch {
 | 
			
		||||
		msg.Flags |= unix.RTM_F_FIB_MATCH
 | 
			
		||||
	}
 | 
			
		||||
	req.AddData(msg)
 | 
			
		||||
 | 
			
		||||
	rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData)
 | 
			
		||||
@@ -1337,7 +1568,7 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
 | 
			
		||||
 | 
			
		||||
	if options != nil {
 | 
			
		||||
		if options.VrfName != "" {
 | 
			
		||||
			link, err := LinkByName(options.VrfName)
 | 
			
		||||
			link, err := h.LinkByName(options.VrfName)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
@@ -1347,20 +1578,27 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
 | 
			
		||||
			req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		iifIndex := 0
 | 
			
		||||
		if len(options.Iif) > 0 {
 | 
			
		||||
			link, err := LinkByName(options.Iif)
 | 
			
		||||
			link, err := h.LinkByName(options.Iif)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			iifIndex = link.Attrs().Index
 | 
			
		||||
		} else if options.IifIndex > 0 {
 | 
			
		||||
			iifIndex = options.IifIndex
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if iifIndex > 0 {
 | 
			
		||||
			b := make([]byte, 4)
 | 
			
		||||
			native.PutUint32(b, uint32(link.Attrs().Index))
 | 
			
		||||
			native.PutUint32(b, uint32(iifIndex))
 | 
			
		||||
 | 
			
		||||
			req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(options.Oif) > 0 {
 | 
			
		||||
			link, err := LinkByName(options.Oif)
 | 
			
		||||
			link, err := h.LinkByName(options.Oif)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
@@ -1381,6 +1619,21 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
 | 
			
		||||
 | 
			
		||||
			req.AddData(nl.NewRtAttr(unix.RTA_SRC, srcAddr))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if options.UID != nil {
 | 
			
		||||
			uid := *options.UID
 | 
			
		||||
			b := make([]byte, 4)
 | 
			
		||||
			native.PutUint32(b, uid)
 | 
			
		||||
 | 
			
		||||
			req.AddData(nl.NewRtAttr(unix.RTA_UID, b))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if options.Mark > 0 {
 | 
			
		||||
			b := make([]byte, 4)
 | 
			
		||||
			native.PutUint32(b, options.Mark)
 | 
			
		||||
 | 
			
		||||
			req.AddData(nl.NewRtAttr(unix.RTA_MARK, b))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
 | 
			
		||||
@@ -1408,21 +1661,24 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) {
 | 
			
		||||
// RouteSubscribe takes a chan down which notifications will be sent
 | 
			
		||||
// when routes are added or deleted. Close the 'done' chan to stop subscription.
 | 
			
		||||
func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error {
 | 
			
		||||
	return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
 | 
			
		||||
	return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteSubscribeAt works like RouteSubscribe plus it allows the caller
 | 
			
		||||
// to choose the network namespace in which to subscribe (ns).
 | 
			
		||||
func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error {
 | 
			
		||||
	return routeSubscribeAt(ns, netns.None(), ch, done, nil, false)
 | 
			
		||||
	return routeSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteSubscribeOptions contains a set of options to use with
 | 
			
		||||
// RouteSubscribeWithOptions.
 | 
			
		||||
type RouteSubscribeOptions struct {
 | 
			
		||||
	Namespace     *netns.NsHandle
 | 
			
		||||
	ErrorCallback func(error)
 | 
			
		||||
	ListExisting  bool
 | 
			
		||||
	Namespace              *netns.NsHandle
 | 
			
		||||
	ErrorCallback          func(error)
 | 
			
		||||
	ListExisting           bool
 | 
			
		||||
	ReceiveBufferSize      int
 | 
			
		||||
	ReceiveBufferForceSize bool
 | 
			
		||||
	ReceiveTimeout         *unix.Timeval
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RouteSubscribeWithOptions work like RouteSubscribe but enable to
 | 
			
		||||
@@ -1433,14 +1689,27 @@ func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, opti
 | 
			
		||||
		none := netns.None()
 | 
			
		||||
		options.Namespace = &none
 | 
			
		||||
	}
 | 
			
		||||
	return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
 | 
			
		||||
	return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting,
 | 
			
		||||
		options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
 | 
			
		||||
func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool,
 | 
			
		||||
	rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error {
 | 
			
		||||
	s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_ROUTE, unix.RTNLGRP_IPV6_ROUTE)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if rcvTimeout != nil {
 | 
			
		||||
		if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if rcvbuf != 0 {
 | 
			
		||||
		err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if done != nil {
 | 
			
		||||
		go func() {
 | 
			
		||||
			<-done
 | 
			
		||||
@@ -1495,7 +1764,11 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
 | 
			
		||||
					}
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				ch <- RouteUpdate{Type: m.Header.Type, Route: route}
 | 
			
		||||
				ch <- RouteUpdate{
 | 
			
		||||
					Type:    m.Header.Type,
 | 
			
		||||
					NlFlags: m.Header.Flags & (unix.NLM_F_REPLACE | unix.NLM_F_EXCL | unix.NLM_F_CREATE | unix.NLM_F_APPEND),
 | 
			
		||||
					Route:   route,
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
@@ -1523,7 +1796,7 @@ func (p RouteProtocol) String() string {
 | 
			
		||||
		return "gated"
 | 
			
		||||
	case unix.RTPROT_ISIS:
 | 
			
		||||
		return "isis"
 | 
			
		||||
	//case unix.RTPROT_KEEPALIVED:
 | 
			
		||||
	// case unix.RTPROT_KEEPALIVED:
 | 
			
		||||
	//	return "keepalived"
 | 
			
		||||
	case unix.RTPROT_KERNEL:
 | 
			
		||||
		return "kernel"
 | 
			
		||||
@@ -1553,3 +1826,24 @@ func (p RouteProtocol) String() string {
 | 
			
		||||
		return strconv.Itoa(int(p))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// genZeroIPNet returns 0.0.0.0/0 or ::/0 for IPv4 or IPv6, otherwise nil
 | 
			
		||||
func genZeroIPNet(family int) *net.IPNet {
 | 
			
		||||
	var addLen int
 | 
			
		||||
	var ip net.IP
 | 
			
		||||
	switch family {
 | 
			
		||||
	case FAMILY_V4:
 | 
			
		||||
		addLen = net.IPv4len
 | 
			
		||||
		ip = net.IPv4zero
 | 
			
		||||
	case FAMILY_V6:
 | 
			
		||||
		addLen = net.IPv6len
 | 
			
		||||
		ip = net.IPv6zero
 | 
			
		||||
	}
 | 
			
		||||
	if addLen != 0 {
 | 
			
		||||
		return &net.IPNet{
 | 
			
		||||
			IP:   ip,
 | 
			
		||||
			Mask: net.CIDRMask(0, 8*addLen),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user