8cadff2b79
* CNI: bump to 1.0.1 This commit bumps the declared version of CNI in the Kilo manifests to 1.0.1. This is possible with no changes to the configuration lists because our simple configuration is not affected by any of the deprecations, and there was effectively no change between 0.4.0 and 1.0.0, other than the declaration of a stable API. Similarly, this commit also bumps the version of the CNI library and the plugins package. Bumping to CNI 1.0.0 will help ensure that Kilo stays compatible with container runtimes in the future. Signed-off-by: Lucas Servén Marín <lserven@gmail.com> * vendor: revendor Signed-off-by: Lucas Servén Marín <lserven@gmail.com>
297 lines
8.1 KiB
Go
297 lines
8.1 KiB
Go
package netlink
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/vishvananda/netlink/nl"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
const FibRuleInvert = 0x2
|
|
|
|
// RuleAdd adds a rule to the system.
|
|
// Equivalent to: ip rule add
|
|
func RuleAdd(rule *Rule) error {
|
|
return pkgHandle.RuleAdd(rule)
|
|
}
|
|
|
|
// RuleAdd adds a rule to the system.
|
|
// Equivalent to: ip rule add
|
|
func (h *Handle) RuleAdd(rule *Rule) error {
|
|
req := h.newNetlinkRequest(unix.RTM_NEWRULE, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
|
return ruleHandle(rule, req)
|
|
}
|
|
|
|
// RuleDel deletes a rule from the system.
|
|
// Equivalent to: ip rule del
|
|
func RuleDel(rule *Rule) error {
|
|
return pkgHandle.RuleDel(rule)
|
|
}
|
|
|
|
// RuleDel deletes a rule from the system.
|
|
// Equivalent to: ip rule del
|
|
func (h *Handle) RuleDel(rule *Rule) error {
|
|
req := h.newNetlinkRequest(unix.RTM_DELRULE, unix.NLM_F_ACK)
|
|
return ruleHandle(rule, req)
|
|
}
|
|
|
|
func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
|
|
msg := nl.NewRtMsg()
|
|
msg.Family = unix.AF_INET
|
|
msg.Protocol = unix.RTPROT_BOOT
|
|
msg.Scope = unix.RT_SCOPE_UNIVERSE
|
|
msg.Table = unix.RT_TABLE_UNSPEC
|
|
msg.Type = unix.RTN_UNSPEC
|
|
if req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 {
|
|
msg.Type = unix.RTN_UNICAST
|
|
}
|
|
if rule.Invert {
|
|
msg.Flags |= FibRuleInvert
|
|
}
|
|
if rule.Family != 0 {
|
|
msg.Family = uint8(rule.Family)
|
|
}
|
|
if rule.Table >= 0 && rule.Table < 256 {
|
|
msg.Table = uint8(rule.Table)
|
|
}
|
|
if rule.Tos != 0 {
|
|
msg.Tos = uint8(rule.Tos)
|
|
}
|
|
|
|
var dstFamily uint8
|
|
var rtAttrs []*nl.RtAttr
|
|
if rule.Dst != nil && rule.Dst.IP != nil {
|
|
dstLen, _ := rule.Dst.Mask.Size()
|
|
msg.Dst_len = uint8(dstLen)
|
|
msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP))
|
|
dstFamily = msg.Family
|
|
var dstData []byte
|
|
if msg.Family == unix.AF_INET {
|
|
dstData = rule.Dst.IP.To4()
|
|
} else {
|
|
dstData = rule.Dst.IP.To16()
|
|
}
|
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, dstData))
|
|
}
|
|
|
|
if rule.Src != nil && rule.Src.IP != nil {
|
|
msg.Family = uint8(nl.GetIPFamily(rule.Src.IP))
|
|
if dstFamily != 0 && dstFamily != msg.Family {
|
|
return fmt.Errorf("source and destination ip are not the same IP family")
|
|
}
|
|
srcLen, _ := rule.Src.Mask.Size()
|
|
msg.Src_len = uint8(srcLen)
|
|
var srcData []byte
|
|
if msg.Family == unix.AF_INET {
|
|
srcData = rule.Src.IP.To4()
|
|
} else {
|
|
srcData = rule.Src.IP.To16()
|
|
}
|
|
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_SRC, srcData))
|
|
}
|
|
|
|
req.AddData(msg)
|
|
for i := range rtAttrs {
|
|
req.AddData(rtAttrs[i])
|
|
}
|
|
|
|
native := nl.NativeEndian()
|
|
|
|
if rule.Priority >= 0 {
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(rule.Priority))
|
|
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
|
|
}
|
|
if rule.Mark >= 0 {
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(rule.Mark))
|
|
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
|
|
}
|
|
if rule.Mask >= 0 {
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(rule.Mask))
|
|
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
|
|
}
|
|
if rule.Flow >= 0 {
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(rule.Flow))
|
|
req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b))
|
|
}
|
|
if rule.TunID > 0 {
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(rule.TunID))
|
|
req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b))
|
|
}
|
|
if rule.Table >= 256 {
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(rule.Table))
|
|
req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b))
|
|
}
|
|
if msg.Table > 0 {
|
|
if rule.SuppressPrefixlen >= 0 {
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(rule.SuppressPrefixlen))
|
|
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b))
|
|
}
|
|
if rule.SuppressIfgroup >= 0 {
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(rule.SuppressIfgroup))
|
|
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b))
|
|
}
|
|
}
|
|
if rule.IifName != "" {
|
|
req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName+"\x00")))
|
|
}
|
|
if rule.OifName != "" {
|
|
req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName+"\x00")))
|
|
}
|
|
if rule.Goto >= 0 {
|
|
msg.Type = nl.FR_ACT_GOTO
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(rule.Goto))
|
|
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
|
|
}
|
|
|
|
if rule.Dport != nil {
|
|
b := rule.Dport.toRtAttrData()
|
|
req.AddData(nl.NewRtAttr(nl.FRA_DPORT_RANGE, b))
|
|
}
|
|
|
|
if rule.Sport != nil {
|
|
b := rule.Sport.toRtAttrData()
|
|
req.AddData(nl.NewRtAttr(nl.FRA_SPORT_RANGE, b))
|
|
}
|
|
|
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
|
return err
|
|
}
|
|
|
|
// RuleList lists rules in the system.
|
|
// Equivalent to: ip rule list
|
|
func RuleList(family int) ([]Rule, error) {
|
|
return pkgHandle.RuleList(family)
|
|
}
|
|
|
|
// RuleList lists rules in the system.
|
|
// Equivalent to: ip rule list
|
|
func (h *Handle) RuleList(family int) ([]Rule, error) {
|
|
return h.RuleListFiltered(family, nil, 0)
|
|
}
|
|
|
|
// RuleListFiltered gets a list of rules in the system filtered by the
|
|
// specified rule template `filter`.
|
|
// Equivalent to: ip rule list
|
|
func RuleListFiltered(family int, filter *Rule, filterMask uint64) ([]Rule, error) {
|
|
return pkgHandle.RuleListFiltered(family, filter, filterMask)
|
|
}
|
|
|
|
// RuleListFiltered lists rules in the system.
|
|
// Equivalent to: ip rule list
|
|
func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) ([]Rule, error) {
|
|
req := h.newNetlinkRequest(unix.RTM_GETRULE, unix.NLM_F_DUMP|unix.NLM_F_REQUEST)
|
|
msg := nl.NewIfInfomsg(family)
|
|
req.AddData(msg)
|
|
|
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWRULE)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
native := nl.NativeEndian()
|
|
var res = make([]Rule, 0)
|
|
for i := range msgs {
|
|
msg := nl.DeserializeRtMsg(msgs[i])
|
|
attrs, err := nl.ParseRouteAttr(msgs[i][msg.Len():])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rule := NewRule()
|
|
|
|
rule.Invert = msg.Flags&FibRuleInvert > 0
|
|
rule.Tos = uint(msg.Tos)
|
|
|
|
for j := range attrs {
|
|
switch attrs[j].Attr.Type {
|
|
case unix.RTA_TABLE:
|
|
rule.Table = int(native.Uint32(attrs[j].Value[0:4]))
|
|
case nl.FRA_SRC:
|
|
rule.Src = &net.IPNet{
|
|
IP: attrs[j].Value,
|
|
Mask: net.CIDRMask(int(msg.Src_len), 8*len(attrs[j].Value)),
|
|
}
|
|
case nl.FRA_DST:
|
|
rule.Dst = &net.IPNet{
|
|
IP: attrs[j].Value,
|
|
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)),
|
|
}
|
|
case nl.FRA_FWMARK:
|
|
rule.Mark = int(native.Uint32(attrs[j].Value[0:4]))
|
|
case nl.FRA_FWMASK:
|
|
rule.Mask = int(native.Uint32(attrs[j].Value[0:4]))
|
|
case nl.FRA_TUN_ID:
|
|
rule.TunID = uint(native.Uint64(attrs[j].Value[0:4]))
|
|
case nl.FRA_IIFNAME:
|
|
rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1])
|
|
case nl.FRA_OIFNAME:
|
|
rule.OifName = string(attrs[j].Value[:len(attrs[j].Value)-1])
|
|
case nl.FRA_SUPPRESS_PREFIXLEN:
|
|
i := native.Uint32(attrs[j].Value[0:4])
|
|
if i != 0xffffffff {
|
|
rule.SuppressPrefixlen = int(i)
|
|
}
|
|
case nl.FRA_SUPPRESS_IFGROUP:
|
|
i := native.Uint32(attrs[j].Value[0:4])
|
|
if i != 0xffffffff {
|
|
rule.SuppressIfgroup = int(i)
|
|
}
|
|
case nl.FRA_FLOW:
|
|
rule.Flow = int(native.Uint32(attrs[j].Value[0:4]))
|
|
case nl.FRA_GOTO:
|
|
rule.Goto = int(native.Uint32(attrs[j].Value[0:4]))
|
|
case nl.FRA_PRIORITY:
|
|
rule.Priority = int(native.Uint32(attrs[j].Value[0:4]))
|
|
case nl.FRA_DPORT_RANGE:
|
|
rule.Dport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4]))
|
|
case nl.FRA_SPORT_RANGE:
|
|
rule.Sport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4]))
|
|
}
|
|
}
|
|
|
|
if filter != nil {
|
|
switch {
|
|
case filterMask&RT_FILTER_SRC != 0 &&
|
|
(rule.Src == nil || rule.Src.String() != filter.Src.String()):
|
|
continue
|
|
case filterMask&RT_FILTER_DST != 0 &&
|
|
(rule.Dst == nil || rule.Dst.String() != filter.Dst.String()):
|
|
continue
|
|
case filterMask&RT_FILTER_TABLE != 0 &&
|
|
filter.Table != unix.RT_TABLE_UNSPEC && rule.Table != filter.Table:
|
|
continue
|
|
case filterMask&RT_FILTER_TOS != 0 && rule.Tos != filter.Tos:
|
|
continue
|
|
case filterMask&RT_FILTER_PRIORITY != 0 && rule.Priority != filter.Priority:
|
|
continue
|
|
case filterMask&RT_FILTER_MARK != 0 && rule.Mark != filter.Mark:
|
|
continue
|
|
case filterMask&RT_FILTER_MASK != 0 && rule.Mask != filter.Mask:
|
|
continue
|
|
}
|
|
}
|
|
|
|
res = append(res, *rule)
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func (pr *RulePortRange) toRtAttrData() []byte {
|
|
b := [][]byte{make([]byte, 2), make([]byte, 2)}
|
|
native.PutUint16(b[0], pr.Start)
|
|
native.PutUint16(b[1], pr.End)
|
|
return bytes.Join(b, []byte{})
|
|
}
|