chore(netlink): define own types with minimal fields
- Allow to swap `github.com/vishvananda/netlink` - Allow to add build tags for each platform - One step closer to development on non-Linux platforms
This commit is contained in:
@@ -1,14 +1,40 @@
|
||||
package netlink
|
||||
|
||||
import "github.com/vishvananda/netlink"
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
type Addr = netlink.Addr
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
type Addr struct {
|
||||
Network netip.Prefix
|
||||
}
|
||||
|
||||
func (a Addr) String() string {
|
||||
return a.Network.String()
|
||||
}
|
||||
|
||||
func (n *NetLink) AddrList(link Link, family int) (
|
||||
addresses []Addr, err error) {
|
||||
return netlink.AddrList(link, family)
|
||||
netlinkLink := linkToNetlinkLink(&link)
|
||||
netlinkAddresses, err := netlink.AddrList(netlinkLink, family)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addresses = make([]Addr, len(netlinkAddresses))
|
||||
for i := range netlinkAddresses {
|
||||
addresses[i].Network = netIPNetToNetipPrefix(netlinkAddresses[i].IPNet)
|
||||
}
|
||||
|
||||
return addresses, nil
|
||||
}
|
||||
|
||||
func (n *NetLink) AddrReplace(link Link, addr *Addr) error {
|
||||
return netlink.AddrReplace(link, addr)
|
||||
func (n *NetLink) AddrReplace(link Link, addr Addr) error {
|
||||
netlinkLink := linkToNetlinkLink(&link)
|
||||
netlinkAddress := netlink.Addr{
|
||||
IPNet: netipPrefixToIPNet(addr.Network),
|
||||
}
|
||||
|
||||
return netlink.AddrReplace(netlinkLink, &netlinkAddress)
|
||||
}
|
||||
|
||||
62
internal/netlink/conversion.go
Normal file
62
internal/netlink/conversion.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
func netipPrefixToIPNet(prefix netip.Prefix) (ipNet *net.IPNet) {
|
||||
if !prefix.IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
prefixAddr := prefix.Addr().Unmap()
|
||||
ipMask := net.CIDRMask(prefix.Bits(), prefixAddr.BitLen())
|
||||
ip := netipAddrToNetIP(prefixAddr)
|
||||
|
||||
return &net.IPNet{
|
||||
IP: ip,
|
||||
Mask: ipMask,
|
||||
}
|
||||
}
|
||||
|
||||
func netIPNetToNetipPrefix(ipNet *net.IPNet) (prefix netip.Prefix) {
|
||||
if ipNet == nil || (len(ipNet.IP) != net.IPv4len && len(ipNet.IP) != net.IPv6len) {
|
||||
return prefix
|
||||
}
|
||||
|
||||
var ip netip.Addr
|
||||
if ipv4 := ipNet.IP.To4(); ipv4 != nil {
|
||||
ip = netip.AddrFrom4([4]byte(ipv4))
|
||||
} else {
|
||||
ip = netip.AddrFrom16([16]byte(ipNet.IP))
|
||||
}
|
||||
bits, _ := ipNet.Mask.Size()
|
||||
return netip.PrefixFrom(ip, bits)
|
||||
}
|
||||
|
||||
func netipAddrToNetIP(address netip.Addr) (ip net.IP) {
|
||||
switch {
|
||||
case !address.IsValid():
|
||||
return nil
|
||||
case address.Is4() || address.Is4In6():
|
||||
bytes := address.As4()
|
||||
return net.IP(bytes[:])
|
||||
default:
|
||||
bytes := address.As16()
|
||||
return net.IP(bytes[:])
|
||||
}
|
||||
}
|
||||
|
||||
func netIPToNetipAddress(ip net.IP) (address netip.Addr) {
|
||||
if len(ip) != net.IPv4len && len(ip) != net.IPv6len {
|
||||
return address // invalid
|
||||
}
|
||||
|
||||
address, ok := netip.AddrFromSlice(ip)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("converting %#v to netip.Addr failed", ip))
|
||||
}
|
||||
return address.Unmap()
|
||||
}
|
||||
146
internal/netlink/conversion_test.go
Normal file
146
internal/netlink/conversion_test.go
Normal file
@@ -0,0 +1,146 @@
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_netipPrefixToIPNet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
prefix netip.Prefix
|
||||
ipNet *net.IPNet
|
||||
}{
|
||||
"empty_prefix": {},
|
||||
"IPv4_prefix": {
|
||||
prefix: netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
|
||||
ipNet: &net.IPNet{
|
||||
IP: net.IP{1, 2, 3, 4},
|
||||
Mask: net.IPv4Mask(255, 255, 255, 0),
|
||||
},
|
||||
},
|
||||
"IPv4-in-IPv6_prefix": {
|
||||
prefix: netip.PrefixFrom(netip.AddrFrom16(
|
||||
[16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 1, 2, 3, 4}),
|
||||
24),
|
||||
ipNet: &net.IPNet{
|
||||
IP: net.IP{1, 2, 3, 4},
|
||||
Mask: net.IPv4Mask(255, 255, 255, 0),
|
||||
},
|
||||
},
|
||||
"IPv6_prefix": {
|
||||
prefix: netip.PrefixFrom(netip.IPv6Loopback(), 8),
|
||||
ipNet: &net.IPNet{
|
||||
IP: net.IPv6loopback,
|
||||
Mask: net.IPMask{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ipNet := netipPrefixToIPNet(testCase.prefix)
|
||||
|
||||
assert.Equal(t, testCase.ipNet, ipNet)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_netIPNetToNetipPrefix(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
ipNet *net.IPNet
|
||||
prefix netip.Prefix
|
||||
}{
|
||||
"empty ipnet": {},
|
||||
"custom sized IP in ipnet": {
|
||||
ipNet: &net.IPNet{
|
||||
IP: net.IP{1},
|
||||
},
|
||||
},
|
||||
"IPv4 ipnet": {
|
||||
ipNet: &net.IPNet{
|
||||
IP: net.IP{1, 2, 3, 4},
|
||||
Mask: net.IPMask{255, 255, 255, 0},
|
||||
},
|
||||
prefix: netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
|
||||
},
|
||||
"IPv4-in-IPv6 ipnet": {
|
||||
ipNet: &net.IPNet{
|
||||
IP: net.IPv4(1, 2, 3, 4),
|
||||
Mask: net.IPMask{255, 255, 255, 0},
|
||||
},
|
||||
prefix: netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
|
||||
},
|
||||
"IPv6 ipnet": {
|
||||
ipNet: &net.IPNet{
|
||||
IP: net.IPv6loopback,
|
||||
Mask: net.IPMask{0xff},
|
||||
},
|
||||
prefix: netip.PrefixFrom(netip.IPv6Loopback(), 8),
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
prefix := netIPNetToNetipPrefix(testCase.ipNet)
|
||||
|
||||
assert.Equal(t, testCase.prefix, prefix)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_netIPToNetipAddress(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
ip net.IP
|
||||
address netip.Addr
|
||||
panicMessage string
|
||||
}{
|
||||
"nil_ip": {},
|
||||
"ip_not_ipv4_or_ipv6": {
|
||||
ip: net.IP{1},
|
||||
},
|
||||
"IPv4": {
|
||||
ip: net.IPv4(1, 2, 3, 4),
|
||||
address: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||
},
|
||||
"IPv6": {
|
||||
ip: net.IPv6zero,
|
||||
address: netip.AddrFrom16([16]byte{}),
|
||||
},
|
||||
"IPv4 prefixed with 0xffff": {
|
||||
ip: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 1, 2, 3, 4},
|
||||
address: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if testCase.panicMessage != "" {
|
||||
assert.PanicsWithValue(t, testCase.panicMessage, func() {
|
||||
netIPToNetipAddress(testCase.ip)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
address := netIPToNetipAddress(testCase.ip)
|
||||
assert.Equal(t, testCase.address, address)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -6,20 +6,19 @@ import (
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
//nolint:revive
|
||||
const (
|
||||
FAMILY_ALL = netlink.FAMILY_ALL
|
||||
FAMILY_V4 = netlink.FAMILY_V4
|
||||
FAMILY_V6 = netlink.FAMILY_V6
|
||||
FamilyAll = 0
|
||||
FamilyV4 = 2
|
||||
FamilyV6 = 10
|
||||
)
|
||||
|
||||
func FamilyToString(family int) string {
|
||||
switch family {
|
||||
case FAMILY_ALL:
|
||||
return "all"
|
||||
case FAMILY_V4:
|
||||
case FamilyAll:
|
||||
return "all" //nolint:goconst
|
||||
case FamilyV4:
|
||||
return "v4"
|
||||
case FAMILY_V6:
|
||||
case FamilyV6:
|
||||
return "v6"
|
||||
default:
|
||||
return fmt.Sprint(family)
|
||||
|
||||
@@ -14,20 +14,21 @@ func (n *NetLink) IsIPv6Supported() (supported bool, err error) {
|
||||
|
||||
var totalRoutes uint
|
||||
for _, link := range links {
|
||||
routes, err := n.RouteList(link, netlink.FAMILY_V6)
|
||||
link := link
|
||||
routes, err := n.RouteList(&link, netlink.FAMILY_V6)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("listing IPv6 routes for link %s: %w",
|
||||
link.Attrs().Name, err)
|
||||
link.Name, err)
|
||||
}
|
||||
|
||||
// Check each route for IPv6 due to Podman bug listing IPv4 routes
|
||||
// as IPv6 routes at container start, see:
|
||||
// https://github.com/qdm12/gluetun/issues/1241#issuecomment-1333405949
|
||||
for _, route := range routes {
|
||||
sourceIsIPv6 := route.Src != nil && route.Src.To4() == nil
|
||||
destinationIsIPv6 := route.Dst != nil && route.Dst.IP.To4() == nil
|
||||
sourceIsIPv6 := route.Src.IsValid() && route.Src.Is6()
|
||||
destinationIsIPv6 := route.Dst.IsValid() && route.Dst.Addr().Is6()
|
||||
if sourceIsIPv6 || destinationIsIPv6 {
|
||||
n.debugLogger.Debugf("IPv6 is supported by link %s", link.Attrs().Name)
|
||||
n.debugLogger.Debugf("IPv6 is supported by link %s", link.Name)
|
||||
return true, nil
|
||||
}
|
||||
totalRoutes++
|
||||
|
||||
@@ -2,36 +2,117 @@ package netlink
|
||||
|
||||
import "github.com/vishvananda/netlink"
|
||||
|
||||
type (
|
||||
Link = netlink.Link
|
||||
Bridge = netlink.Bridge
|
||||
Wireguard = netlink.Wireguard
|
||||
)
|
||||
type Link struct {
|
||||
Type string
|
||||
Name string
|
||||
Index int
|
||||
EncapType string
|
||||
MTU uint16
|
||||
|
||||
NetNsID int
|
||||
TxQLen int
|
||||
}
|
||||
|
||||
func (n *NetLink) LinkList() (links []Link, err error) {
|
||||
return netlink.LinkList()
|
||||
netlinkLinks, err := netlink.LinkList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
links = make([]Link, len(netlinkLinks))
|
||||
for i := range netlinkLinks {
|
||||
links[i] = netlinkLinkToLink(netlinkLinks[i])
|
||||
}
|
||||
|
||||
return links, nil
|
||||
}
|
||||
|
||||
func (n *NetLink) LinkByName(name string) (link Link, err error) {
|
||||
return netlink.LinkByName(name)
|
||||
netlinkLink, err := netlink.LinkByName(name)
|
||||
if err != nil {
|
||||
return Link{}, err
|
||||
}
|
||||
|
||||
return netlinkLinkToLink(netlinkLink), nil
|
||||
}
|
||||
|
||||
func (n *NetLink) LinkByIndex(index int) (link Link, err error) {
|
||||
return netlink.LinkByIndex(index)
|
||||
netlinkLink, err := netlink.LinkByIndex(index)
|
||||
if err != nil {
|
||||
return Link{}, err
|
||||
}
|
||||
|
||||
return netlinkLinkToLink(netlinkLink), nil
|
||||
}
|
||||
|
||||
func (n *NetLink) LinkAdd(link Link) (err error) {
|
||||
return netlink.LinkAdd(link)
|
||||
func (n *NetLink) LinkAdd(link Link) (linkIndex int, err error) {
|
||||
netlinkLink := linkToNetlinkLink(&link)
|
||||
err = netlink.LinkAdd(netlinkLink)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return netlinkLink.Attrs().Index, nil
|
||||
}
|
||||
|
||||
func (n *NetLink) LinkDel(link Link) (err error) {
|
||||
return netlink.LinkDel(link)
|
||||
return netlink.LinkDel(linkToNetlinkLink(&link))
|
||||
}
|
||||
|
||||
func (n *NetLink) LinkSetUp(link Link) (err error) {
|
||||
return netlink.LinkSetUp(link)
|
||||
func (n *NetLink) LinkSetUp(link Link) (linkIndex int, err error) {
|
||||
netlinkLink := linkToNetlinkLink(&link)
|
||||
err = netlink.LinkSetUp(netlinkLink)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return netlinkLink.Attrs().Index, nil
|
||||
}
|
||||
|
||||
func (n *NetLink) LinkSetDown(link Link) (err error) {
|
||||
return netlink.LinkSetDown(link)
|
||||
return netlink.LinkSetDown(linkToNetlinkLink(&link))
|
||||
}
|
||||
|
||||
type netlinkLinkImpl struct {
|
||||
attrs *netlink.LinkAttrs
|
||||
linkType string
|
||||
}
|
||||
|
||||
func (n *netlinkLinkImpl) Attrs() *netlink.LinkAttrs {
|
||||
return n.attrs
|
||||
}
|
||||
|
||||
func (n *netlinkLinkImpl) Type() string {
|
||||
return n.linkType
|
||||
}
|
||||
|
||||
func netlinkLinkToLink(netlinkLink netlink.Link) Link {
|
||||
attributes := netlinkLink.Attrs()
|
||||
return Link{
|
||||
Type: netlinkLink.Type(),
|
||||
Name: attributes.Name,
|
||||
Index: attributes.Index,
|
||||
EncapType: attributes.EncapType,
|
||||
MTU: uint16(attributes.MTU),
|
||||
NetNsID: attributes.NetNsID,
|
||||
TxQLen: attributes.TxQLen,
|
||||
}
|
||||
}
|
||||
|
||||
// Warning: we must return `netlink.Link` and not `netlinkLinkImpl`
|
||||
// so that the vishvananda/netlink package can compare the returned
|
||||
// value against an untyped nil.
|
||||
func linkToNetlinkLink(link *Link) netlink.Link {
|
||||
if link == nil {
|
||||
return nil
|
||||
}
|
||||
return &netlinkLinkImpl{
|
||||
linkType: link.Type,
|
||||
attrs: &netlink.LinkAttrs{ // TODO get all original attributes
|
||||
Name: link.Name,
|
||||
Index: link.Index,
|
||||
EncapType: link.EncapType,
|
||||
MTU: int(link.MTU),
|
||||
NetNsID: link.NetNsID,
|
||||
TxQLen: link.TxQLen,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package netlink
|
||||
|
||||
import "github.com/vishvananda/netlink"
|
||||
|
||||
type LinkAttrs = netlink.LinkAttrs
|
||||
|
||||
func NewLinkAttrs() LinkAttrs {
|
||||
return netlink.NewLinkAttrs()
|
||||
}
|
||||
@@ -1,22 +1,74 @@
|
||||
package netlink
|
||||
|
||||
import "github.com/vishvananda/netlink"
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
type Route = netlink.Route
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func (n *NetLink) RouteList(link Link, family int) (
|
||||
type Route struct {
|
||||
LinkIndex int
|
||||
Dst netip.Prefix
|
||||
Src netip.Addr
|
||||
Gw netip.Addr
|
||||
Priority int
|
||||
Family int
|
||||
Table int
|
||||
Type int
|
||||
}
|
||||
|
||||
func (n *NetLink) RouteList(link *Link, family int) (
|
||||
routes []Route, err error) {
|
||||
return netlink.RouteList(link, family)
|
||||
netlinkLink := linkToNetlinkLink(link)
|
||||
netlinkRoutes, err := netlink.RouteList(netlinkLink, family)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
routes = make([]Route, len(netlinkRoutes))
|
||||
for i := range netlinkRoutes {
|
||||
routes[i] = netlinkRouteToRoute(netlinkRoutes[i])
|
||||
}
|
||||
return routes, nil
|
||||
}
|
||||
|
||||
func (n *NetLink) RouteAdd(route *Route) error {
|
||||
return netlink.RouteAdd(route)
|
||||
func (n *NetLink) RouteAdd(route Route) error {
|
||||
netlinkRoute := routeToNetlinkRoute(route)
|
||||
return netlink.RouteAdd(&netlinkRoute)
|
||||
}
|
||||
|
||||
func (n *NetLink) RouteDel(route *Route) error {
|
||||
return netlink.RouteDel(route)
|
||||
func (n *NetLink) RouteDel(route Route) error {
|
||||
netlinkRoute := routeToNetlinkRoute(route)
|
||||
return netlink.RouteDel(&netlinkRoute)
|
||||
}
|
||||
|
||||
func (n *NetLink) RouteReplace(route *Route) error {
|
||||
return netlink.RouteReplace(route)
|
||||
func (n *NetLink) RouteReplace(route Route) error {
|
||||
netlinkRoute := routeToNetlinkRoute(route)
|
||||
return netlink.RouteReplace(&netlinkRoute)
|
||||
}
|
||||
|
||||
func netlinkRouteToRoute(netlinkRoute netlink.Route) (route Route) {
|
||||
return Route{
|
||||
LinkIndex: netlinkRoute.LinkIndex,
|
||||
Dst: netIPNetToNetipPrefix(netlinkRoute.Dst),
|
||||
Src: netIPToNetipAddress(netlinkRoute.Src),
|
||||
Gw: netIPToNetipAddress(netlinkRoute.Gw),
|
||||
Priority: netlinkRoute.Priority,
|
||||
Family: netlinkRoute.Family,
|
||||
Table: netlinkRoute.Table,
|
||||
Type: netlinkRoute.Type,
|
||||
}
|
||||
}
|
||||
|
||||
func routeToNetlinkRoute(route Route) (netlinkRoute netlink.Route) {
|
||||
return netlink.Route{
|
||||
LinkIndex: route.LinkIndex,
|
||||
Dst: netipPrefixToIPNet(route.Dst),
|
||||
Src: netipAddrToNetIP(route.Src),
|
||||
Gw: netipAddrToNetIP(route.Gw),
|
||||
Priority: route.Priority,
|
||||
Family: route.Family,
|
||||
Table: route.Table,
|
||||
Type: route.Type,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,90 @@
|
||||
package netlink
|
||||
|
||||
import "github.com/vishvananda/netlink"
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
|
||||
type Rule = netlink.Rule
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func NewRule() *Rule {
|
||||
return netlink.NewRule()
|
||||
type Rule struct {
|
||||
Priority int
|
||||
Family int
|
||||
Table int
|
||||
Mark int
|
||||
Src netip.Prefix
|
||||
Dst netip.Prefix
|
||||
Invert bool
|
||||
}
|
||||
|
||||
func (r Rule) String() string {
|
||||
from := "all"
|
||||
if r.Src.IsValid() {
|
||||
from = r.Src.String()
|
||||
}
|
||||
|
||||
to := "all"
|
||||
if r.Dst.IsValid() {
|
||||
to = r.Dst.String()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("ip rule %d: from %s to %s table %d",
|
||||
r.Priority, from, to, r.Table)
|
||||
}
|
||||
|
||||
func NewRule() Rule {
|
||||
// defaults found from netlink.NewRule() for fields we use,
|
||||
// the rest of the defaults is set when converting from a `Rule`
|
||||
// to a `netlink.Rule`
|
||||
return Rule{
|
||||
Priority: -1,
|
||||
Mark: -1,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NetLink) RuleList(family int) (rules []Rule, err error) {
|
||||
return netlink.RuleList(family)
|
||||
netlinkRules, err := netlink.RuleList(family)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules = make([]Rule, len(netlinkRules))
|
||||
for i := range netlinkRules {
|
||||
rules[i] = netlinkRuleToRule(netlinkRules[i])
|
||||
}
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (n *NetLink) RuleAdd(rule *Rule) error {
|
||||
return netlink.RuleAdd(rule)
|
||||
func (n *NetLink) RuleAdd(rule Rule) error {
|
||||
netlinkRule := ruleToNetlinkRule(rule)
|
||||
return netlink.RuleAdd(&netlinkRule)
|
||||
}
|
||||
|
||||
func (n *NetLink) RuleDel(rule *Rule) error {
|
||||
return netlink.RuleDel(rule)
|
||||
func (n *NetLink) RuleDel(rule Rule) error {
|
||||
netlinkRule := ruleToNetlinkRule(rule)
|
||||
return netlink.RuleDel(&netlinkRule)
|
||||
}
|
||||
|
||||
func ruleToNetlinkRule(rule Rule) (netlinkRule netlink.Rule) {
|
||||
netlinkRule = *netlink.NewRule()
|
||||
netlinkRule.Priority = rule.Priority
|
||||
netlinkRule.Family = rule.Family
|
||||
netlinkRule.Table = rule.Table
|
||||
netlinkRule.Mark = rule.Mark
|
||||
netlinkRule.Src = netipPrefixToIPNet(rule.Src)
|
||||
netlinkRule.Dst = netipPrefixToIPNet(rule.Dst)
|
||||
netlinkRule.Invert = rule.Invert
|
||||
return netlinkRule
|
||||
}
|
||||
|
||||
func netlinkRuleToRule(netlinkRule netlink.Rule) (rule Rule) {
|
||||
return Rule{
|
||||
Priority: netlinkRule.Priority,
|
||||
Family: netlinkRule.Family,
|
||||
Table: netlinkRule.Table,
|
||||
Mark: netlinkRule.Mark,
|
||||
Src: netIPNetToNetipPrefix(netlinkRule.Src),
|
||||
Dst: netIPNetToNetipPrefix(netlinkRule.Dst),
|
||||
Invert: netlinkRule.Invert,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user