From 6dd8bdacfe82ed178c5d6538685f02eb996a3c76 Mon Sep 17 00:00:00 2001 From: Kristian Evensen Date: Thu, 26 Sep 2019 12:06:45 +0200 Subject: ipset: Add wildcard support to net,iface The net,iface equal functions currently compares the full interface names. In several cases, wildcard (or prefix) matching is useful. For example, when converting a large iptables rule-set to make use of ipset, I was able to significantly reduce the number of set elements by making use of wildcard matching. Wildcard matching is enabled by adding "wildcard" when adding an element to a set. Internally, this causes the IPSET_FLAG_IFACE_WILDCARD-flag to be set. When this flag is set, only the initial part of the interface name is used for comparison. Wildcard matching is done per element and not per set, as there are many cases where mixing wildcard and non-wildcard elements are useful. This means that is up to the user to handle (avoid) overlapping interface names. Signed-off-by: Kristian Evensen Signed-off-by: Jozsef Kadlecsik --- lib/ipset_hash_netiface.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) (limited to 'lib/ipset_hash_netiface.c') diff --git a/lib/ipset_hash_netiface.c b/lib/ipset_hash_netiface.c index a709816..6755782 100644 --- a/lib/ipset_hash_netiface.c +++ b/lib/ipset_hash_netiface.c @@ -619,6 +619,100 @@ static struct ipset_type ipset_hash_netiface6 = { " Adding/deleting multiple elements with IPv4 is supported.", .description = "skbinfo support", }; +/* interface wildcard support */ +static struct ipset_type ipset_hash_netiface7 = { + .name = "hash:net,iface", + .alias = { "netifacehash", NULL }, + .revision = 7, + .family = NFPROTO_IPSET_IPV46, + .dimension = IPSET_DIM_TWO, + .elem = { + [IPSET_DIM_ONE - 1] = { + .parse = ipset_parse_ip4_net6, + .print = ipset_print_ip, + .opt = IPSET_OPT_IP + }, + [IPSET_DIM_TWO - 1] = { + .parse = ipset_parse_iface, + .print = ipset_print_iface, + .opt = IPSET_OPT_IFACE + }, + }, + .cmd = { + [IPSET_CREATE] = { + .args = { + IPSET_ARG_FAMILY, + /* Aliases */ + IPSET_ARG_INET, + IPSET_ARG_INET6, + IPSET_ARG_HASHSIZE, + IPSET_ARG_MAXELEM, + IPSET_ARG_TIMEOUT, + IPSET_ARG_COUNTERS, + IPSET_ARG_COMMENT, + IPSET_ARG_FORCEADD, + IPSET_ARG_SKBINFO, + IPSET_ARG_NONE, + }, + .need = 0, + .full = 0, + .help = "", + }, + [IPSET_ADD] = { + .args = { + IPSET_ARG_TIMEOUT, + IPSET_ARG_NOMATCH, + IPSET_ARG_IFACE_WILDCARD, + IPSET_ARG_PACKETS, + IPSET_ARG_BYTES, + IPSET_ARG_ADT_COMMENT, + IPSET_ARG_SKBMARK, + IPSET_ARG_SKBPRIO, + IPSET_ARG_SKBQUEUE, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IFACE), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IFACE) + | IPSET_FLAG(IPSET_OPT_PHYSDEV), + .help = "IP[/CIDR]|FROM-TO,[physdev:]IFACE", + }, + [IPSET_DEL] = { + .args = { + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IFACE), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IP_TO) + | IPSET_FLAG(IPSET_OPT_IFACE) + | IPSET_FLAG(IPSET_OPT_PHYSDEV), + .help = "IP[/CIDR]|FROM-TO,[physdev:]IFACE", + }, + [IPSET_TEST] = { + .args = { + IPSET_ARG_NOMATCH, + IPSET_ARG_NONE, + }, + .need = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_IFACE), + .full = IPSET_FLAG(IPSET_OPT_IP) + | IPSET_FLAG(IPSET_OPT_CIDR) + | IPSET_FLAG(IPSET_OPT_IFACE) + | IPSET_FLAG(IPSET_OPT_PHYSDEV), + .help = "IP[/CIDR],[physdev:]IFACE", + }, + }, + .usage = "where depending on the INET family\n" + " IP is a valid IPv4 or IPv6 address (or hostname),\n" + " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" + " Adding/deleting multiple elements with IPv4 is supported.", + .description = "skbinfo and wildcard support", +}; void _init(void); void _init(void) @@ -630,4 +724,5 @@ void _init(void) ipset_type_add(&ipset_hash_netiface4); ipset_type_add(&ipset_hash_netiface5); ipset_type_add(&ipset_hash_netiface6); + ipset_type_add(&ipset_hash_netiface7); } -- cgit v1.2.3