build: update github.com/vishvananda/netlink to 1.3.0
This includes a breaking change:
acdc658b86
route.Dst is now a zero IPNet instead of nil
Signed-off-by: Etienne Champetier <e.champetier@ateme.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