From d44b87fd4d3f58c8574fe61a18e330007f972529 Mon Sep 17 00:00:00 2001 From: Damien Tournoud Date: Thu, 21 Jul 2022 13:55:47 -0700 Subject: [PATCH] ipset: Add support for IPv6 --- ipset_linux.go | 32 +++++++++++++++++---- ipset_linux_test.go | 70 +++++++++++++++++++++++++++++++++++---------- nl/ipset_linux.go | 5 ++++ 3 files changed, 87 insertions(+), 20 deletions(-) diff --git a/ipset_linux.go b/ipset_linux.go index 0627b3d..94177e3 100644 --- a/ipset_linux.go +++ b/ipset_linux.go @@ -67,6 +67,7 @@ type IpsetCreateOptions struct { Comments bool Skbinfo bool + Family uint8 Revision uint8 IPFrom net.IP IPTo net.IP @@ -158,7 +159,10 @@ func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOption data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_FROM|int(nl.NLA_F_NET_BYTEORDER), buf[:2])) data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_TO|int(nl.NLA_F_NET_BYTEORDER), buf[2:])) default: - family = unix.AF_INET + family = options.Family + if family == 0 { + family = unix.AF_INET + } } req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(family))) @@ -249,6 +253,18 @@ func (h *Handle) IpsetDel(setname string, entry *IPSetEntry) error { return h.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry) } +func encodeIP(ip net.IP) (*nl.RtAttr, error) { + typ := int(nl.NLA_F_NET_BYTEORDER) + if ip4 := ip.To4(); ip4 != nil { + typ |= nl.IPSET_ATTR_IPADDR_IPV4 + ip = ip4 + } else { + typ |= nl.IPSET_ATTR_IPADDR_IPV6 + } + + return nl.NewRtAttr(typ, ip), nil +} + func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error { req := h.newIpsetRequest(nlCmd) req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname))) @@ -268,7 +284,10 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error } if entry.IP != nil { - nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP) + nestedData, err := encodeIP(entry.IP) + if err != nil { + return err + } data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NESTED), nestedData.Serialize())) } @@ -281,7 +300,10 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error } if entry.IP2 != nil { - nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP2) + nestedData, err := encodeIP(entry.IP2) + if err != nil { + return err + } data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP2|int(nl.NLA_F_NESTED), nestedData.Serialize())) } @@ -479,7 +501,7 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) { case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED: for attr := range nl.ParseAttributes(attr.Value) { switch attr.Type { - case nl.IPSET_ATTR_IP: + case nl.IPSET_ATTR_IPADDR_IPV4, nl.IPSET_ATTR_IPADDR_IPV6: entry.IP = net.IP(attr.Value) default: log.Printf("unknown nested ADT attribute from kernel: %+v", attr) @@ -488,7 +510,7 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) { case nl.IPSET_ATTR_IP2 | nl.NLA_F_NESTED: for attr := range nl.ParseAttributes(attr.Value) { switch attr.Type { - case nl.IPSET_ATTR_IP: + case nl.IPSET_ATTR_IPADDR_IPV4, nl.IPSET_ATTR_IPADDR_IPV6: entry.IP2 = net.IP(attr.Value) default: log.Printf("unknown nested ADT attribute from kernel: %+v", attr) diff --git a/ipset_linux_test.go b/ipset_linux_test.go index b0d06e4..fa9877b 100644 --- a/ipset_linux_test.go +++ b/ipset_linux_test.go @@ -145,7 +145,7 @@ func TestIpsetCreateListAddDelDestroy(t *testing.T) { err = IpsetAdd("my-test-ipset-1", &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.99").To4(), + IP: net.ParseIP("10.99.99.99"), Replace: false, }) @@ -173,7 +173,7 @@ func TestIpsetCreateListAddDelDestroy(t *testing.T) { err = IpsetDel("my-test-ipset-1", &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.99").To4(), + IP: net.ParseIP("10.99.99.99"), }) if err != nil { t.Fatal(err) @@ -224,7 +224,7 @@ func TestIpsetCreateListAddDelDestroyWithTestCases(t *testing.T) { }, entry: &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.99").To4(), + IP: net.ParseIP("10.99.99.99"), Replace: false, }, }, @@ -241,7 +241,7 @@ func TestIpsetCreateListAddDelDestroyWithTestCases(t *testing.T) { }, entry: &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.0").To4(), + IP: net.ParseIP("10.99.99.0"), CIDR: 24, Replace: false, }, @@ -259,9 +259,9 @@ func TestIpsetCreateListAddDelDestroyWithTestCases(t *testing.T) { }, entry: &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.0").To4(), + IP: net.ParseIP("10.99.99.0"), CIDR: 24, - IP2: net.ParseIP("10.99.0.0").To4(), + IP2: net.ParseIP("10.99.0.0"), CIDR2: 24, Replace: false, }, @@ -279,8 +279,8 @@ func TestIpsetCreateListAddDelDestroyWithTestCases(t *testing.T) { }, entry: &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.0").To4(), - IP2: net.ParseIP("10.99.0.0").To4(), + IP: net.ParseIP("10.99.99.0"), + IP2: net.ParseIP("10.99.0.0"), Replace: false, }, }, @@ -297,7 +297,7 @@ func TestIpsetCreateListAddDelDestroyWithTestCases(t *testing.T) { }, entry: &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.1").To4(), + IP: net.ParseIP("10.99.99.1"), Protocol: &protocalTCP, Port: &port, Replace: false, @@ -316,9 +316,9 @@ func TestIpsetCreateListAddDelDestroyWithTestCases(t *testing.T) { }, entry: &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.0").To4(), + IP: net.ParseIP("10.99.99.0"), CIDR: 24, - IP2: net.ParseIP("10.99.0.0").To4(), + IP2: net.ParseIP("10.99.0.0"), CIDR2: 24, Protocol: &protocalTCP, Port: &port, @@ -355,7 +355,7 @@ func TestIpsetCreateListAddDelDestroyWithTestCases(t *testing.T) { }, entry: &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.0").To4(), + IP: net.ParseIP("10.99.99.0"), CIDR: 24, IFace: "eth0", Replace: false, @@ -374,11 +374,51 @@ func TestIpsetCreateListAddDelDestroyWithTestCases(t *testing.T) { }, entry: &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.0").To4(), + IP: net.ParseIP("10.99.99.0"), Mark: &timeout, Replace: false, }, }, + { + desc: "Type-hash:net6", + setname: "my-test-ipset-11", + typename: "hash:net", + options: IpsetCreateOptions{ + Replace: true, + Timeout: &timeout, + Counters: false, + Comments: true, + Skbinfo: true, + Family: unix.AF_INET6, + }, + entry: &IPSetEntry{ + Comment: "test comment", + IP: net.ParseIP("::1"), + CIDR: 128, + Replace: false, + }, + }, + { + desc: "Type-hash:net6:net6", + setname: "my-test-ipset-11", + typename: "hash:net,net", + options: IpsetCreateOptions{ + Replace: true, + Timeout: &timeout, + Counters: false, + Comments: true, + Skbinfo: true, + Family: unix.AF_INET6, + }, + entry: &IPSetEntry{ + Comment: "test comment", + IP: net.ParseIP("::1"), + CIDR: 128, + IP2: net.ParseIP("::2"), + CIDR2: 128, + Replace: false, + }, + }, } for _, tC := range testCases { @@ -528,7 +568,7 @@ func TestIpsetBitmapCreateListWithTestCases(t *testing.T) { }, entry: &IPSetEntry{ Comment: "test comment", - IP: net.ParseIP("10.99.99.0").To4(), + IP: net.ParseIP("10.99.99.0"), CIDR: 26, Mark: &timeout, Replace: false, @@ -593,7 +633,7 @@ func TestIpsetSwap(t *testing.T) { }() err = IpsetAdd(ipset1, &IPSetEntry{ - IP: net.ParseIP("10.99.99.99").To4(), + IP: net.ParseIP("10.99.99.99"), }) if err != nil { t.Fatal(err) diff --git a/nl/ipset_linux.go b/nl/ipset_linux.go index a60b4b0..89dd009 100644 --- a/nl/ipset_linux.go +++ b/nl/ipset_linux.go @@ -88,6 +88,11 @@ const ( SET_ATTR_CREATE_MAX ) +const ( + IPSET_ATTR_IPADDR_IPV4 = 1 + IPSET_ATTR_IPADDR_IPV6 = 2 +) + /* ADT specific attributes */ const ( IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + iota + 1