All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] ipset: Extend netmask support for userspace
@ 2017-03-21 18:39 Josh Hunt
  2017-03-21 18:39 ` [PATCH 1/5] ipset: netmask: expand to support cidr and full mask Josh Hunt
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Josh Hunt @ 2017-03-21 18:39 UTC (permalink / raw)
  To: kadlec; +Cc: netfilter-devel, coreteam, Josh Hunt

These are the userspace changes to add the ability to specify a netmask
or wildcard mask for the set during creation instead of just a cidr
value.

Example usage:

Legacy behavior:
ipset create foo hash:ip family inet6 netmask 64

New netmask support (equivalent to legacy example):
ipset create foo hash:ip family inet6 netmask ffff:ffff:ffff:ffff::

New wildcard mask support:
ipset create foo hash:ip family inet6 netmask ffff:ffff:ffff:0:0:ffff:ffff:ffff

The 3 mask types are supported for ipv4 sets as well.

Josh Hunt (5):
  ipset: netmask: expand to support cidr and full mask
  ipset: hash:ip: add support for new netmask types
  ipset: hash:ipport: netmask support
  hash:ip: add new netmask support to man page
  hash:ip,port: add netmask support to man page

 include/libipset/data.h         |   5 +-
 include/libipset/linux_ip_set.h |   5 ++
 include/libipset/print.h        |   3 +
 lib/data.c                      |  25 +++++-
 lib/debug.c                     |   1 +
 lib/ipset_hash_ip.c             | 166 ++++++++++++++++++++++++++++++++++
 lib/ipset_hash_ipport.c         | 194 ++++++++++++++++++++++++++++++++++++++++
 lib/parse.c                     |  68 ++++++++++++--
 lib/print.c                     |  39 +++++++-
 lib/session.c                   |   8 ++
 src/ipset.8                     |  90 +++++++++++++++++--
 11 files changed, 583 insertions(+), 21 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] ipset: netmask: expand to support cidr and full mask
  2017-03-21 18:39 [PATCH 0/5] ipset: Extend netmask support for userspace Josh Hunt
@ 2017-03-21 18:39 ` Josh Hunt
  2017-03-27 20:08   ` Jozsef Kadlecsik
  2017-03-21 18:39 ` [PATCH 2/5] ipset: hash:ip: add support for new netmask types Josh Hunt
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Josh Hunt @ 2017-03-21 18:39 UTC (permalink / raw)
  To: kadlec; +Cc: netfilter-devel, coreteam, Josh Hunt

Convert netmask to store cidr and netmask.

Signed-off-by: Josh Hunt <johunt@akamai.com>
---
 include/libipset/data.h         |  5 ++-
 include/libipset/linux_ip_set.h |  5 +++
 include/libipset/print.h        |  3 ++
 lib/data.c                      | 25 +++++++++++++--
 lib/debug.c                     |  1 +
 lib/parse.c                     | 68 ++++++++++++++++++++++++++++++++++++-----
 lib/print.c                     | 39 +++++++++++++++++++++--
 lib/session.c                   |  8 +++++
 8 files changed, 141 insertions(+), 13 deletions(-)

diff --git a/include/libipset/data.h b/include/libipset/data.h
index ca21890..0314cfb 100644
--- a/include/libipset/data.h
+++ b/include/libipset/data.h
@@ -37,6 +37,7 @@ enum ipset_opt {
 	IPSET_OPT_RESIZE,
 	IPSET_OPT_SIZE,
 	IPSET_OPT_FORCEADD,
+	IPSET_OPT_NETMASK_MASK,
 	/* Create-specific options, filled out by the kernel */
 	IPSET_OPT_ELEMENTS,
 	IPSET_OPT_REFERENCES,
@@ -66,6 +67,7 @@ enum ipset_opt {
 	IPSET_OPT_SKBMARK,
 	IPSET_OPT_SKBPRIO,
 	IPSET_OPT_SKBQUEUE,
+	IPSET_OPT_NETMASK_FLAG,
 	/* Internal options */
 	IPSET_OPT_FLAGS = 48,	/* IPSET_FLAG_EXIST| */
 	IPSET_OPT_CADT_FLAGS,	/* IPSET_FLAG_BEFORE| */
@@ -101,7 +103,8 @@ enum ipset_opt {
 	| IPSET_FLAG(IPSET_OPT_COUNTERS)\
 	| IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)\
 	| IPSET_FLAG(IPSET_OPT_FORCEADD)\
-	| IPSET_FLAG(IPSET_OPT_SKBINFO))
+	| IPSET_FLAG(IPSET_OPT_SKBINFO)\
+	| IPSET_FLAG(IPSET_OPT_NETMASK_MASK))
 
 #define IPSET_ADT_FLAGS			\
 	(IPSET_FLAG(IPSET_OPT_IP)	\
diff --git a/include/libipset/linux_ip_set.h b/include/libipset/linux_ip_set.h
index def91b9..4f93886 100644
--- a/include/libipset/linux_ip_set.h
+++ b/include/libipset/linux_ip_set.h
@@ -84,6 +84,7 @@ enum {
 	IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO,	/* 9 */
 	IPSET_ATTR_MARK,	/* 10 */
 	IPSET_ATTR_MARKMASK,	/* 11 */
+	IPSET_ATTR_NETMASK_MASK,/* 12 */
 	/* Reserve empty slots */
 	IPSET_ATTR_CADT_MAX = 16,
 	/* Create-only specific attributes */
@@ -199,6 +200,8 @@ enum ipset_cadt_flags {
 	IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD),
 	IPSET_FLAG_BIT_WITH_SKBINFO = 6,
 	IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO),
+	IPSET_FLAG_BIT_WITH_NETMASK = 7,
+	IPSET_FLAG_WITH_NETMASK = (1 << IPSET_FLAG_BIT_WITH_NETMASK),
 	IPSET_FLAG_CADT_MAX	= 15,
 };
 
@@ -206,6 +209,8 @@ enum ipset_cadt_flags {
 enum ipset_create_flags {
 	IPSET_CREATE_FLAG_BIT_FORCEADD = 0,
 	IPSET_CREATE_FLAG_FORCEADD = (1 << IPSET_CREATE_FLAG_BIT_FORCEADD),
+	IPSET_CREATE_FLAG_BIT_NETMASK = 1,
+	IPSET_CREATE_FLAG_NETMASK = (1 << IPSET_CREATE_FLAG_BIT_NETMASK),
 	IPSET_CREATE_FLAG_BIT_MAX = 7,
 };
 
diff --git a/include/libipset/print.h b/include/libipset/print.h
index 2103ce1..f9e77d3 100644
--- a/include/libipset/print.h
+++ b/include/libipset/print.h
@@ -74,6 +74,9 @@ extern int ipset_print_flag(char *buf, unsigned int len,
 extern int ipset_print_elem(char *buf, unsigned int len,
 			    const struct ipset_data *data,
 			    enum ipset_opt opt, uint8_t env);
+extern int ipset_print_netmask(char *buf, unsigned int len,
+			    const struct ipset_data *data,
+			    enum ipset_opt opt, uint8_t env);
 
 #define ipset_print_portnum	ipset_print_number
 
diff --git a/lib/data.c b/lib/data.c
index 8372a2f..951a124 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -24,6 +24,11 @@
  * We always store the data in host order, *except* IP addresses.
  */
 
+struct ipset_netmask {
+	uint8_t cidr;
+	union nf_inet_addr mask;
+};
+
 struct ipset_data {
 	/* Option bits: which fields are set */
 	uint64_t bits;
@@ -51,7 +56,7 @@ struct ipset_data {
 		struct {
 			uint8_t probes;
 			uint8_t resize;
-			uint8_t netmask;
+			struct ipset_netmask netmask;
 			uint32_t hashsize;
 			uint32_t maxelem;
 			uint32_t markmask;
@@ -295,7 +300,13 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
 		data->create.markmask = *(const uint32_t *) value;
 		break;
 	case IPSET_OPT_NETMASK:
-		data->create.netmask = *(const uint8_t *) value;
+		data->create.netmask.cidr = *(const uint8_t *) value;
+		break;
+	case IPSET_OPT_NETMASK_MASK:
+		if (!(data->family == NFPROTO_IPV4 ||
+		      data->family == NFPROTO_IPV6))
+			return -1;
+		copy_addr(data->family, &data->create.netmask.mask, value);
 		break;
 	case IPSET_OPT_PROBES:
 		data->create.probes = *(const uint8_t *) value;
@@ -318,6 +329,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
 	case IPSET_OPT_SKBINFO:
 		cadt_flag_type_attr(data, opt, IPSET_FLAG_WITH_SKBINFO);
 		break;
+	case IPSET_OPT_NETMASK_FLAG:
+		cadt_flag_type_attr(data, opt, IPSET_FLAG_WITH_NETMASK);
+		break;
 	/* Create-specific options, filled out by the kernel */
 	case IPSET_OPT_ELEMENTS:
 		data->create.elements = *(const uint32_t *) value;
@@ -495,7 +509,9 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
 	case IPSET_OPT_MARKMASK:
 		return &data->create.markmask;
 	case IPSET_OPT_NETMASK:
-		return &data->create.netmask;
+		return &data->create.netmask.cidr;
+	case IPSET_OPT_NETMASK_MASK:
+		return &data->create.netmask.mask;
 	case IPSET_OPT_PROBES:
 		return &data->create.probes;
 	case IPSET_OPT_RESIZE:
@@ -558,6 +574,7 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
 	case IPSET_OPT_CREATE_COMMENT:
 	case IPSET_OPT_FORCEADD:
 	case IPSET_OPT_SKBINFO:
+	case IPSET_OPT_NETMASK_FLAG:
 		return &data->cadt_flags;
 	default:
 		return NULL;
@@ -581,6 +598,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
 	case IPSET_OPT_IP_TO:
 	case IPSET_OPT_IP2:
 	case IPSET_OPT_IP2_TO:
+	case IPSET_OPT_NETMASK_MASK:
 		return family == NFPROTO_IPV4 ? sizeof(uint32_t)
 					 : sizeof(struct in6_addr);
 	case IPSET_OPT_MARK:
@@ -623,6 +641,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
 	case IPSET_OPT_NOMATCH:
 	case IPSET_OPT_COUNTERS:
 	case IPSET_OPT_FORCEADD:
+	case IPSET_OPT_NETMASK_FLAG:
 		return sizeof(uint32_t);
 	case IPSET_OPT_ADT_COMMENT:
 		return IPSET_MAX_COMMENT_SIZE + 1;
diff --git a/lib/debug.c b/lib/debug.c
index 6f831ec..a32f709 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -40,6 +40,7 @@ static const struct ipset_attrname createattr2name[] = {
 	[IPSET_ATTR_MAXELEM]	= { .name = "MAXELEM" },
 	[IPSET_ATTR_MARKMASK]	= { .name = "MARKMASK" },
 	[IPSET_ATTR_NETMASK]	= { .name = "NETMASK" },
+	[IPSET_ATTR_NETMASK_MASK] = { .name = "NETMASK_MASK" },
 	[IPSET_ATTR_PROBES]	= { .name = "PROBES" },
 	[IPSET_ATTR_RESIZE]	= { .name = "RESIZE" },
 	[IPSET_ATTR_SIZE]	= { .name = "SIZE" },
diff --git a/lib/parse.c b/lib/parse.c
index 88d2888..5c41c37 100644
--- a/lib/parse.c
+++ b/lib/parse.c
@@ -1654,7 +1654,35 @@ ipset_parse_uint8(struct ipset_session *session,
 }
 
 /**
+ * ipset_cidr_to_mask - convert cidr value to mask stored in nf_inet_addr
+ * @addr: store resulting mask here
+ * @cidr: value to convert to mask
+ * @family: INET family type
+ *
+ * Parse cidr value and convert it into a mask stored in an nf_inet_addr.
+ */
+static void
+ipset_cidr_to_mask(union nf_inet_addr *addr, uint8_t cidr, uint8_t family)
+{
+	uint8_t i;
+	uint8_t addrsize = (family == NFPROTO_IPV4) ? 1 : 4;
+
+        for (i=0; i < addrsize; i++) {
+		if (!cidr) {
+			addr->all[i] = 0;
+		} else if (cidr >= 32) {
+			addr->all[i] = 0xffffffff;
+			cidr -= 32;
+		} else {
+			addr->all[i] = htonl(~((1 << (32 - cidr)) - 1));
+			break;
+		}
+	}
+}
+
+/**
  * ipset_parse_netmask - parse string as a CIDR netmask value
+ *			 or netmask value
  * @session: session structure
  * @opt: option kind of the data
  * @str: string to parse
@@ -1669,12 +1697,13 @@ int
 ipset_parse_netmask(struct ipset_session *session,
 		    enum ipset_opt opt, const char *str)
 {
-	uint8_t family, cidr;
+	uint8_t family, cidr = 0;
 	struct ipset_data *data;
 	int err = 0;
+	union nf_inet_addr netmask = {};
 
 	assert(session);
-	assert(opt == IPSET_OPT_NETMASK);
+	assert(opt == IPSET_OPT_NETMASK_MASK || opt == IPSET_OPT_NETMASK);
 	assert(str);
 
 	data = ipset_session_data(session);
@@ -1684,16 +1713,41 @@ ipset_parse_netmask(struct ipset_session *session,
 		ipset_data_set(data, IPSET_OPT_FAMILY, &family);
 	}
 
+	/* Try to parse input as CIDR first */
 	err = string_to_cidr(session, str, 1,
 			     family == NFPROTO_IPV4 ? 32 : 128,
 			     &cidr);
 
-	if (err)
-		return syntax_err("netmask is out of the inclusive range "
-				  "of 1-%u",
-				  family == NFPROTO_IPV4 ? 32 : 128);
+	if (opt == IPSET_OPT_NETMASK) {
+		if (err)
+			return syntax_err("netmask is out of the inclusive range "
+					  "of 1-%u",
+					  family == NFPROTO_IPV4 ? 32 : 128);
+
+		return ipset_data_set(data, opt, &cidr);
+	} else {
+
+		/* If that fails, attempt to parse as an IP addr */
+		if (err) {
+			/* Store mask value as input by user */
+			err = parse_ipaddr(session, opt, str, family);
+			if (err)
+				return err;
 
-	return ipset_data_set(data, opt, &cidr);
+			/* Check if it's a CIDR and store if it is */
+			netmask = *(const union nf_inet_addr *) ipset_data_get(data, IPSET_OPT_NETMASK_MASK);
+		} else {
+			ipset_cidr_to_mask(&netmask, cidr, family);
+
+			err = ipset_data_set(data, opt, &netmask);
+			if (err)
+				return err;
+		}
+
+		ipset_data_set(data, IPSET_OPT_NETMASK_FLAG, &family);
+
+		return ipset_data_set(data, IPSET_OPT_NETMASK, &cidr);
+	}
 }
 
 /**
diff --git a/lib/print.c b/lib/print.c
index 7dd229e..cc450c6 100644
--- a/lib/print.c
+++ b/lib/print.c
@@ -241,6 +241,39 @@ SNPRINTF_IP(32, 4)
 SNPRINTF_IP(128, 6)
 
 /**
+ * ipset_print_netmask - print netmask in either CIDR or address to string
+ * @buf: printing buffer
+ * @len: length of available buffer space
+ * @data: data blob
+ * @opt: the option kind
+ * @env: environment flags
+ *
+ * If the netmask can be represented as a CIDR print that, otherwise print
+ * the mask value.
+ *
+ * Return length of printed string or error size.
+ */
+int
+ipset_print_netmask(char *buf, unsigned int len,
+		    const struct ipset_data *data, enum ipset_opt opt,
+		    uint8_t env)
+{
+	uint8_t cidr;
+
+	assert(buf);
+	assert(len > 0);
+	assert(data);
+	assert(opt == IPSET_OPT_NETMASK_MASK);
+
+	cidr = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_NETMASK);
+
+	if (cidr)
+		return snprintf(buf, len, "%u", cidr);
+	else
+		return ipset_print_ip(buf, len, data, opt, env);
+}
+
+/**
  * ipset_print_ip - print IPv4|IPv6 address to string
  * @buf: printing buffer
  * @len: length of available buffer space
@@ -265,7 +298,7 @@ ipset_print_ip(char *buf, unsigned int len,
 	assert(buf);
 	assert(len > 0);
 	assert(data);
-	assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
+	assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2 || opt == IPSET_OPT_NETMASK_MASK);
 
 	D("len: %u", len);
 	family = ipset_data_family(data);
@@ -944,7 +977,6 @@ ipset_print_data(char *buf, unsigned int len,
 	case IPSET_OPT_HASHSIZE:
 	case IPSET_OPT_MAXELEM:
 	case IPSET_OPT_MARKMASK:
-	case IPSET_OPT_NETMASK:
 	case IPSET_OPT_PROBES:
 	case IPSET_OPT_RESIZE:
 	case IPSET_OPT_TIMEOUT:
@@ -953,6 +985,9 @@ ipset_print_data(char *buf, unsigned int len,
 	case IPSET_OPT_SIZE:
 		size = ipset_print_number(buf, len, data, opt, env);
 		break;
+	case IPSET_OPT_NETMASK_MASK:
+		size = ipset_print_netmask(buf, len, data, opt, env);
+		break;
 	default:
 		return -1;
 	}
diff --git a/lib/session.c b/lib/session.c
index 1bdaaa7..55eab83 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -414,6 +414,10 @@ static const struct ipset_attr_policy create_attrs[] = {
 		.type = MNL_TYPE_U32,
 		.opt = IPSET_OPT_MEMSIZE,
 	},
+	[IPSET_ATTR_NETMASK_MASK] = {
+		.type = MNL_TYPE_NESTED,
+		.opt = IPSET_OPT_NETMASK_MASK,
+	},
 };
 
 static const struct ipset_attr_policy adt_attrs[] = {
@@ -1494,6 +1498,10 @@ rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
 	if (attr->type == MNL_TYPE_NESTED) {
 		/* IP addresses */
 		struct nlattr *nested;
+
+		if (type == IPSET_ATTR_NETMASK_MASK)
+			family = ipset_data_family(session->data);
+
 		int atype = family == NFPROTO_IPV4 ? IPSET_ATTR_IPADDR_IPV4
 					      : IPSET_ATTR_IPADDR_IPV6;
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] ipset: hash:ip: add support for new netmask types
  2017-03-21 18:39 [PATCH 0/5] ipset: Extend netmask support for userspace Josh Hunt
  2017-03-21 18:39 ` [PATCH 1/5] ipset: netmask: expand to support cidr and full mask Josh Hunt
@ 2017-03-21 18:39 ` Josh Hunt
  2017-03-21 18:39 ` [PATCH 3/5] ipset: hash:ipport: netmask support Josh Hunt
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Josh Hunt @ 2017-03-21 18:39 UTC (permalink / raw)
  To: kadlec; +Cc: netfilter-devel, coreteam, Josh Hunt

Uses new netmask support added in previous commit to allow user to
specify cidr, netmask, or wildcard mask as arguments to the netmask
parameter at creation time.

Signed-off-by: Josh Hunt <johunt@akamai.com>
---
 lib/ipset_hash_ip.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/lib/ipset_hash_ip.c b/lib/ipset_hash_ip.c
index 2bff34f..36afc59 100644
--- a/lib/ipset_hash_ip.c
+++ b/lib/ipset_hash_ip.c
@@ -669,6 +669,171 @@ static struct ipset_type ipset_hash_ip4 = {
 	.description = "skbinfo support",
 };
 
+/* Parse commandline arguments */
+static const struct ipset_arg hash_ip_create_args5[] = {
+	{ .name = { "family", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_FAMILY,
+	  .parse = ipset_parse_family,		.print = ipset_print_family,
+	},
+	/* Alias: family inet */
+	{ .name = { "-4", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_FAMILY,
+	  .parse = ipset_parse_family,
+	},
+	/* Alias: family inet6 */
+	{ .name = { "-6", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_FAMILY,
+	  .parse = ipset_parse_family,
+	},
+	{ .name = { "hashsize", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_HASHSIZE,
+	  .parse = ipset_parse_uint32,		.print = ipset_print_number,
+	},
+	{ .name = { "maxelem", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_MAXELEM,
+	  .parse = ipset_parse_uint32,		.print = ipset_print_number,
+	},
+	{ .name = { "netmask", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_NETMASK_MASK,
+	  .parse = ipset_parse_netmask,		.print = ipset_print_netmask,
+	},
+	{ .name = { "timeout", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_TIMEOUT,
+	  .parse = ipset_parse_timeout,		.print = ipset_print_number,
+	},
+	{ .name = { "counters", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_COUNTERS,
+	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
+	},
+	{ .name = { "comment", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_CREATE_COMMENT,
+	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
+	},
+	{ .name = { "forceadd", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_FORCEADD,
+	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
+	},
+	{ .name = { "skbinfo", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_SKBINFO,
+	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
+	},
+	/* Ignored options: backward compatibilty */
+	{ .name = { "probes", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_PROBES,
+	  .parse = ipset_parse_ignored,		.print = ipset_print_number,
+	},
+	{ .name = { "resize", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_RESIZE,
+	  .parse = ipset_parse_ignored,		.print = ipset_print_number,
+	},
+	{ .name = { "gc", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_GC,
+	  .parse = ipset_parse_ignored,		.print = ipset_print_number,
+	},
+	{ },
+};
+
+static const struct ipset_arg hash_ip_add_args5[] = {
+	{ .name = { "timeout", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_TIMEOUT,
+	  .parse = ipset_parse_timeout,		.print = ipset_print_number,
+	},
+	{ .name = { "packets", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_PACKETS,
+	  .parse = ipset_parse_uint64,		.print = ipset_print_number,
+	},
+	{ .name = { "bytes", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_BYTES,
+	  .parse = ipset_parse_uint64,		.print = ipset_print_number,
+	},
+	{ .name = { "comment", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_ADT_COMMENT,
+	  .parse = ipset_parse_comment,		.print = ipset_print_comment,
+	},
+	{ .name = { "skbmark", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_SKBMARK,
+	  .parse = ipset_parse_skbmark,		.print = ipset_print_skbmark,
+	},
+	{ .name = { "skbprio", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_SKBPRIO,
+	  .parse = ipset_parse_skbprio,		.print = ipset_print_skbprio,
+	},
+	{ .name = { "skbqueue", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_SKBQUEUE,
+	  .parse = ipset_parse_uint16,		.print = ipset_print_number,
+	},
+	{ },
+};
+
+
+static const char hash_ip_usage5[] =
+"create SETNAME hash:ip\n"
+"		[family inet|inet6]\n"
+"               [hashsize VALUE] [maxelem VALUE]\n"
+"               [netmask CIDR or MASK] [timeout VALUE]\n"
+"               [counters] [comment] [forceadd] [skbinfo]\n"
+"add    SETNAME IP [timeout VALUE]\n"
+"               [packets VALUE] [bytes VALUE] [comment \"string\"]\n"
+"		[skbmark VALUE] [skbprio VALUE] [skbqueue VALUE]\n"
+"del    SETNAME IP\n"
+"test   SETNAME IP\n\n"
+"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 in IP/CIDR or FROM-TO form\n"
+"      is supported for IPv4.\n";
+
+static struct ipset_type ipset_hash_ip5 = {
+	.name = "hash:ip",
+	.alias = { "iphash", NULL },
+	.revision = 5,
+	.family = NFPROTO_IPSET_IPV46,
+	.dimension = IPSET_DIM_ONE,
+	.elem = {
+		[IPSET_DIM_ONE - 1] = {
+			.parse = ipset_parse_ip4_single6,
+			.print = ipset_print_ip,
+			.opt = IPSET_OPT_IP
+		},
+	},
+	.args = {
+		[IPSET_CREATE] = hash_ip_create_args5,
+		[IPSET_ADD] = hash_ip_add_args5,
+	},
+	.mandatory = {
+		[IPSET_CREATE] = 0,
+		[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
+		[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
+		[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
+	},
+	.full = {
+		[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
+			| IPSET_FLAG(IPSET_OPT_MAXELEM)
+			| IPSET_FLAG(IPSET_OPT_NETMASK)
+			| IPSET_FLAG(IPSET_OPT_TIMEOUT)
+			| IPSET_FLAG(IPSET_OPT_COUNTERS)
+			| IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)
+			| IPSET_FLAG(IPSET_OPT_FORCEADD)
+			| IPSET_FLAG(IPSET_OPT_SKBINFO)
+			| IPSET_FLAG(IPSET_OPT_NETMASK_MASK),
+		[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+			| IPSET_FLAG(IPSET_OPT_IP_TO)
+			| IPSET_FLAG(IPSET_OPT_TIMEOUT)
+			| IPSET_FLAG(IPSET_OPT_PACKETS)
+			| IPSET_FLAG(IPSET_OPT_BYTES)
+			| IPSET_FLAG(IPSET_OPT_ADT_COMMENT)
+			| IPSET_FLAG(IPSET_OPT_SKBMARK)
+			| IPSET_FLAG(IPSET_OPT_SKBPRIO)
+			| IPSET_FLAG(IPSET_OPT_SKBQUEUE),
+		[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+			| IPSET_FLAG(IPSET_OPT_IP_TO),
+		[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
+	},
+
+	.usage = hash_ip_usage5,
+	.description = "netmask wildcardmask support",
+};
+
 void _init(void);
 void _init(void)
 {
@@ -677,4 +842,5 @@ void _init(void)
 	ipset_type_add(&ipset_hash_ip2);
 	ipset_type_add(&ipset_hash_ip3);
 	ipset_type_add(&ipset_hash_ip4);
+	ipset_type_add(&ipset_hash_ip5);
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] ipset: hash:ipport: netmask support
  2017-03-21 18:39 [PATCH 0/5] ipset: Extend netmask support for userspace Josh Hunt
  2017-03-21 18:39 ` [PATCH 1/5] ipset: netmask: expand to support cidr and full mask Josh Hunt
  2017-03-21 18:39 ` [PATCH 2/5] ipset: hash:ip: add support for new netmask types Josh Hunt
@ 2017-03-21 18:39 ` Josh Hunt
  2017-03-27 20:12   ` Jozsef Kadlecsik
  2017-03-21 18:39 ` [PATCH 4/5] hash:ip: add new netmask support to man page Josh Hunt
  2017-03-21 18:39 ` [PATCH 5/5] hash:ip,port: add " Josh Hunt
  4 siblings, 1 reply; 8+ messages in thread
From: Josh Hunt @ 2017-03-21 18:39 UTC (permalink / raw)
  To: kadlec; +Cc: netfilter-devel, coreteam, Josh Hunt

Adds netmask support to hash:ipport sets.

Signed-off-by: Josh Hunt <johunt@akamai.com>
---
 lib/ipset_hash_ipport.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 194 insertions(+)

diff --git a/lib/ipset_hash_ipport.c b/lib/ipset_hash_ipport.c
index 2166922..a2cf79e 100644
--- a/lib/ipset_hash_ipport.c
+++ b/lib/ipset_hash_ipport.c
@@ -787,6 +787,199 @@ static struct ipset_type ipset_hash_ipport5 = {
 	.description = "skbinfo support",
 };
 
+/* Parse commandline arguments */
+static const struct ipset_arg hash_ipport_create_args6[] = {
+	{ .name = { "family", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_FAMILY,
+	  .parse = ipset_parse_family,		.print = ipset_print_family,
+	},
+	/* Alias: family inet */
+	{ .name = { "-4", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_FAMILY,
+	  .parse = ipset_parse_family,
+	},
+	/* Alias: family inet6 */
+	{ .name = { "-6", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_FAMILY,
+	  .parse = ipset_parse_family,
+	},
+	{ .name = { "hashsize", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_HASHSIZE,
+	  .parse = ipset_parse_uint32,		.print = ipset_print_number,
+	},
+	{ .name = { "maxelem", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_MAXELEM,
+	  .parse = ipset_parse_uint32,		.print = ipset_print_number,
+	},
+	{ .name = { "timeout", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_TIMEOUT,
+	  .parse = ipset_parse_timeout,		.print = ipset_print_number,
+	},
+	{ .name = { "counters", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_COUNTERS,
+	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
+	},
+	{ .name = { "comment", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_CREATE_COMMENT,
+	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
+	},
+	{ .name = { "forceadd", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_FORCEADD,
+	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
+	},
+	{ .name = { "skbinfo", NULL },
+	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_SKBINFO,
+	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
+	},
+	{ .name = { "netmask", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_NETMASK_MASK,
+	  .parse = ipset_parse_netmask,         .print = ipset_print_netmask,
+	},
+	/* Backward compatibility */
+	{ .name = { "probes", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_PROBES,
+	  .parse = ipset_parse_ignored,		.print = ipset_print_number,
+	},
+	{ .name = { "resize", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_RESIZE,
+	  .parse = ipset_parse_ignored,		.print = ipset_print_number,
+	},
+	{ .name = { "from", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_IP,
+	  .parse = ipset_parse_ignored,
+	},
+	{ .name = { "to", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_IP_TO,
+	  .parse = ipset_parse_ignored,
+	},
+	{ .name = { "network", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_IP,
+	  .parse = ipset_parse_ignored,
+	},
+	{ },
+};
+
+static const struct ipset_arg hash_ipport_add_args6[] = {
+	{ .name = { "timeout", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_TIMEOUT,
+	  .parse = ipset_parse_timeout,		.print = ipset_print_number,
+	},
+	{ .name = { "packets", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_PACKETS,
+	  .parse = ipset_parse_uint64,		.print = ipset_print_number,
+	},
+	{ .name = { "bytes", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_BYTES,
+	  .parse = ipset_parse_uint64,		.print = ipset_print_number,
+	},
+	{ .name = { "comment", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_ADT_COMMENT,
+	  .parse = ipset_parse_comment,		.print = ipset_print_comment,
+	},
+	{ .name = { "skbmark", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_SKBMARK,
+	  .parse = ipset_parse_skbmark,		.print = ipset_print_skbmark,
+	},
+	{ .name = { "skbprio", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_SKBPRIO,
+	  .parse = ipset_parse_skbprio,		.print = ipset_print_skbprio,
+	},
+	{ .name = { "skbqueue", NULL },
+	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_SKBQUEUE,
+	  .parse = ipset_parse_uint16,		.print = ipset_print_number,
+	},
+	{ },
+};
+
+static const char hash_ipport_usage6[] =
+"create SETNAME hash:ip,port\n"
+"		[family inet|inet6]\n"
+"               [hashsize VALUE] [maxelem VALUE]\n"
+"               [timeout VALUE] [counters] [comment]\n"
+"		[forceadd] [skbinfo] [netmask CIDR or MASK]\n"
+"add    SETNAME IP,PROTO:PORT [timeout VALUE]\n"
+"               [packets VALUE] [bytes VALUE] [comment \"string\"]\n"
+"		[skbmark VALUE] [skbprio VALUE] [skbqueue VALUE]\n"
+"del    SETNAME IP,PROTO:PORT\n"
+"test   SETNAME IP,PROTO:PORT\n\n"
+"where depending on the INET family\n"
+"      IP is a valid IPv4 or IPv6 address (or hostname).\n"
+"      Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
+"      is supported for IPv4.\n"
+"      Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
+"      port range is supported both for IPv4 and IPv6.\n";
+
+static struct ipset_type ipset_hash_ipport6 = {
+	.name = "hash:ip,port",
+	.alias = { "ipporthash", NULL },
+	.revision = 6,
+	.family = NFPROTO_IPSET_IPV46,
+	.dimension = IPSET_DIM_TWO,
+	.elem = {
+		[IPSET_DIM_ONE - 1] = {
+			.parse = ipset_parse_ip4_single6,
+			.print = ipset_print_ip,
+			.opt = IPSET_OPT_IP
+		},
+		[IPSET_DIM_TWO - 1] = {
+			.parse = ipset_parse_proto_port,
+			.print = ipset_print_proto_port,
+			.opt = IPSET_OPT_PORT
+		},
+	},
+	.args = {
+		[IPSET_CREATE] = hash_ipport_create_args6,
+		[IPSET_ADD] = hash_ipport_add_args6,
+	},
+	.mandatory = {
+		[IPSET_CREATE] = 0,
+		[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+			| IPSET_FLAG(IPSET_OPT_PROTO)
+			| IPSET_FLAG(IPSET_OPT_PORT),
+		[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+			| IPSET_FLAG(IPSET_OPT_PROTO)
+			| IPSET_FLAG(IPSET_OPT_PORT),
+		[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+			| IPSET_FLAG(IPSET_OPT_PROTO)
+			| IPSET_FLAG(IPSET_OPT_PORT),
+	},
+	.full = {
+		[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
+			| IPSET_FLAG(IPSET_OPT_MAXELEM)
+			| IPSET_FLAG(IPSET_OPT_TIMEOUT)
+			| IPSET_FLAG(IPSET_OPT_COUNTERS)
+			| IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)
+			| IPSET_FLAG(IPSET_OPT_FORCEADD)
+			| IPSET_FLAG(IPSET_OPT_SKBINFO)
+			| IPSET_FLAG(IPSET_OPT_NETMASK)
+			| IPSET_FLAG(IPSET_OPT_NETMASK_MASK),
+		[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+			| IPSET_FLAG(IPSET_OPT_IP_TO)
+			| IPSET_FLAG(IPSET_OPT_PORT)
+			| IPSET_FLAG(IPSET_OPT_PORT_TO)
+			| IPSET_FLAG(IPSET_OPT_PROTO)
+			| IPSET_FLAG(IPSET_OPT_TIMEOUT)
+			| IPSET_FLAG(IPSET_OPT_PACKETS)
+			| IPSET_FLAG(IPSET_OPT_BYTES)
+			| IPSET_FLAG(IPSET_OPT_ADT_COMMENT)
+			| IPSET_FLAG(IPSET_OPT_SKBMARK)
+			| IPSET_FLAG(IPSET_OPT_SKBPRIO)
+			| IPSET_FLAG(IPSET_OPT_SKBQUEUE),
+		[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+			| IPSET_FLAG(IPSET_OPT_IP_TO)
+			| IPSET_FLAG(IPSET_OPT_PORT)
+			| IPSET_FLAG(IPSET_OPT_PORT_TO)
+			| IPSET_FLAG(IPSET_OPT_PROTO),
+		[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+			| IPSET_FLAG(IPSET_OPT_PORT)
+			| IPSET_FLAG(IPSET_OPT_PROTO),
+	},
+
+	.usage = hash_ipport_usage6,
+	.usagefn = ipset_port_usage,
+	.description = "netmask support",
+};
+
 void _init(void);
 void _init(void)
 {
@@ -795,4 +988,5 @@ void _init(void)
 	ipset_type_add(&ipset_hash_ipport3);
 	ipset_type_add(&ipset_hash_ipport4);
 	ipset_type_add(&ipset_hash_ipport5);
+	ipset_type_add(&ipset_hash_ipport6);
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] hash:ip: add new netmask support to man page
  2017-03-21 18:39 [PATCH 0/5] ipset: Extend netmask support for userspace Josh Hunt
                   ` (2 preceding siblings ...)
  2017-03-21 18:39 ` [PATCH 3/5] ipset: hash:ipport: netmask support Josh Hunt
@ 2017-03-21 18:39 ` Josh Hunt
  2017-03-21 18:39 ` [PATCH 5/5] hash:ip,port: add " Josh Hunt
  4 siblings, 0 replies; 8+ messages in thread
From: Josh Hunt @ 2017-03-21 18:39 UTC (permalink / raw)
  To: kadlec; +Cc: netfilter-devel, coreteam, Josh Hunt

Updates hash:ip create options to list new mask param to netmask,
describe how it works, and provide examples.

Signed-off-by: Josh Hunt <johunt@akamai.com>
---
 src/ipset.8 | 43 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 36 insertions(+), 7 deletions(-)

diff --git a/src/ipset.8 b/src/ipset.8
index cd8c3ad..56cc9ea 100644
--- a/src/ipset.8
+++ b/src/ipset.8
@@ -504,7 +504,7 @@ The \fBhash:ip\fR set type uses a hash to store IP host addresses (default) or
 network addresses. Zero valued IP address cannot be stored in a \fBhash:ip\fR
 type of set.
 .PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBnetmask\fP { \fIcidr\fP | \fImask\fP } ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
 .PP
 \fIADD\-ENTRY\fR := \fIipaddr\fR
 .PP
@@ -516,12 +516,17 @@ type of set.
 .PP
 Optional \fBcreate\fR options:
 .TP 
-\fBnetmask\fP \fIcidr\fP
-When the optional \fBnetmask\fP parameter specified, network addresses will be 
-stored in the set instead of IP host addresses. The \fIcidr\fP prefix value must be
-between 1\-32 for IPv4 and between 1\-128 for IPv6. An IP address will be in the set
-if the network address, which is resulted by masking the address with the netmask,
-can be found in the set.
+\fBnetmask\fP { \fIcidr\fP | \fImask\fP }
+The optional \fBnetmask\fP parameter supports two different mask types: \fIcidr\fP,
+\fImask\fP.
+.TP
+\fIcidr\fP
+When the optional \fBnetmask\fP parameter is specified and a \fIcidr\fP argument is
+given, network addresses will be stored in the set instead of IP host addresses. The
+\fIcidr\fP prefix value must be between 1\-32 for IPv4 and between 1\-128 for IPv6.
+An IP address will be in the set if the network address, which is resulted by masking
+the address with the netmask, can be found in the set.
+.IP
 Examples:
 .IP 
 ipset create foo hash:ip netmask 30
@@ -529,6 +534,30 @@ ipset create foo hash:ip netmask 30
 ipset add foo 192.168.1.0/24
 .IP 
 ipset test foo 192.168.1.2
+.TP
+\fImask\fP
+A \fImask\fP argument to \fBnetmask\fP, like \fIcidr\fP, applies the defined mask
+against the address to be added to the set. The difference with \fImask\fP is that
+it can support conventional netmask values like 255.255.255.0 for IPv4 addresses, 
+but it can also support wildcard masks. Allowing the user to define a \fImask\fP
+of any bits to apply to the address. Wildcard masks prove to be very useful for
+IPv6 addressing.
+.IP
+Conventional Mask Examples:
+.IP
+ipset create foo hash:ip netmask 255.255.255.0
+.IP
+ipset add foo 192.168.1.2
+.IP
+ipset test foo 192.168.1.20
+.IP
+Wildcard Mask Examples:
+.IP
+ipset create foo hash:ip family inet6 netmask ffff:ffff:ffff:0:0:ffff::
+.IP
+ipset add foo 1:2:3:4:5:6:7:8
+.IP
+ipset test foo 1:2:3:a:b:6:c:d
 .SS hash:mac
 The \fBhash:mac\fR set type uses a hash to store MAC addresses. Zero valued MAC addresses cannot be stored in a \fBhash:mac\fR
 type of set.
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] hash:ip,port: add netmask support to man page
  2017-03-21 18:39 [PATCH 0/5] ipset: Extend netmask support for userspace Josh Hunt
                   ` (3 preceding siblings ...)
  2017-03-21 18:39 ` [PATCH 4/5] hash:ip: add new netmask support to man page Josh Hunt
@ 2017-03-21 18:39 ` Josh Hunt
  4 siblings, 0 replies; 8+ messages in thread
From: Josh Hunt @ 2017-03-21 18:39 UTC (permalink / raw)
  To: kadlec; +Cc: netfilter-devel, coreteam, Josh Hunt

Adds netmask to hash:ip,port create options, describe how it works, and
provide examples.

Signed-off-by: Josh Hunt <johunt@akamai.com>
---
 src/ipset.8 | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/src/ipset.8 b/src/ipset.8
index 56cc9ea..d0ca810 100644
--- a/src/ipset.8
+++ b/src/ipset.8
@@ -710,7 +710,7 @@ The \fBhash:ip,port\fR set type uses a hash to store IP address and port number
 The port number is interpreted together with a protocol (default TCP) and zero
 protocol number cannot be used.
 .PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
+\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBnetmask\fP { \fIcidr\fP | \fImask\fP } ] [ \fBtimeout\fR \fIvalue\fR ] [ \fBcounters\fP ] [ \fBcomment\fP ] [ \fBskbinfo\fP ]
 .PP
 \fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
 .PP
@@ -761,6 +761,51 @@ ipset add foo 192.168.1.1,udp:53
 ipset add foo 192.168.1.1,vrrp:0
 .IP 
 ipset test foo 192.168.1.1,80
+.TP
+Optional \fBcreate\fR options:
+.TP 
+\fBnetmask\fP { \fIcidr\fP | \fImask\fP }
+The optional \fBnetmask\fP parameter supports two different mask types: \fIcidr\fP,
+\fImask\fP.
+.TP
+\fIcidr\fP
+When the optional \fBnetmask\fP parameter is specified and a \fIcidr\fP argument is
+given, network addresses will be stored in the set instead of IP host addresses. The
+\fIcidr\fP prefix value must be between 1\-32 for IPv4 and between 1\-128 for IPv6.
+An IP address will be in the set if the network address, which is resulted by masking
+the address with the netmask, can be found in the set.
+.IP
+Examples:
+.IP 
+ipset create foo hash:ip,port netmask 30
+.IP 
+ipset add foo 192.168.1.0/24,80
+.IP 
+ipset test foo 192.168.1.2,80
+.TP
+\fImask\fP
+A \fImask\fP argument to \fBnetmask\fP, like \fIcidr\fP, applies the defined mask
+against the address to be added to the set. The difference with \fImask\fP is that
+it can support conventional netmask values like 255.255.255.0 for IPv4 addresses, 
+but it can also support wildcard masks. Allowing the user to define a \fImask\fP
+of any bits to apply to the address. Wildcard masks prove to be very useful for
+IPv6 addressing.
+.IP
+Conventional Mask Examples:
+.IP
+ipset create foo hash:ip,port netmask 255.255.255.0
+.IP
+ipset add foo 192.168.1.2,22
+.IP
+ipset test foo 192.168.1.20,22
+.IP
+Wildcard Mask Examples:
+.IP
+ipset create foo hash:ip,port family inet6 netmask ffff:ffff:ffff:0:0:ffff::
+.IP
+ipset add foo 1:2:3:4:5:6:7:8,udp:53
+.IP
+ipset test foo 1:2:3:a:b:6:c:d,udp:53
 .SS hash:net,port
 The \fBhash:net,port\fR set type uses a hash to store different sized IP network
 address and port pairs. The port number is interpreted together with a protocol
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/5] ipset: netmask: expand to support cidr and full mask
  2017-03-21 18:39 ` [PATCH 1/5] ipset: netmask: expand to support cidr and full mask Josh Hunt
@ 2017-03-27 20:08   ` Jozsef Kadlecsik
  0 siblings, 0 replies; 8+ messages in thread
From: Jozsef Kadlecsik @ 2017-03-27 20:08 UTC (permalink / raw)
  To: Josh Hunt; +Cc: netfilter-devel, coreteam

On Tue, 21 Mar 2017, Josh Hunt wrote:

> Convert netmask to store cidr and netmask.
> 
> Signed-off-by: Josh Hunt <johunt@akamai.com>
> ---
>  include/libipset/data.h         |  5 ++-
>  include/libipset/linux_ip_set.h |  5 +++
>  include/libipset/print.h        |  3 ++
>  lib/data.c                      | 25 +++++++++++++--
>  lib/debug.c                     |  1 +
>  lib/parse.c                     | 68 ++++++++++++++++++++++++++++++++++++-----
>  lib/print.c                     | 39 +++++++++++++++++++++--
>  lib/session.c                   |  8 +++++
>  8 files changed, 141 insertions(+), 13 deletions(-)
> 
> diff --git a/include/libipset/data.h b/include/libipset/data.h
> index ca21890..0314cfb 100644
> --- a/include/libipset/data.h
> +++ b/include/libipset/data.h
> @@ -37,6 +37,7 @@ enum ipset_opt {
>  	IPSET_OPT_RESIZE,
>  	IPSET_OPT_SIZE,
>  	IPSET_OPT_FORCEADD,
> +	IPSET_OPT_NETMASK_MASK,
>  	/* Create-specific options, filled out by the kernel */
>  	IPSET_OPT_ELEMENTS,
>  	IPSET_OPT_REFERENCES,
> @@ -66,6 +67,7 @@ enum ipset_opt {
>  	IPSET_OPT_SKBMARK,
>  	IPSET_OPT_SKBPRIO,
>  	IPSET_OPT_SKBQUEUE,
> +	IPSET_OPT_NETMASK_FLAG,
>  	/* Internal options */
>  	IPSET_OPT_FLAGS = 48,	/* IPSET_FLAG_EXIST| */
>  	IPSET_OPT_CADT_FLAGS,	/* IPSET_FLAG_BEFORE| */
> @@ -101,7 +103,8 @@ enum ipset_opt {
>  	| IPSET_FLAG(IPSET_OPT_COUNTERS)\
>  	| IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)\
>  	| IPSET_FLAG(IPSET_OPT_FORCEADD)\
> -	| IPSET_FLAG(IPSET_OPT_SKBINFO))
> +	| IPSET_FLAG(IPSET_OPT_SKBINFO)\
> +	| IPSET_FLAG(IPSET_OPT_NETMASK_MASK))
>  
>  #define IPSET_ADT_FLAGS			\
>  	(IPSET_FLAG(IPSET_OPT_IP)	\
> diff --git a/include/libipset/linux_ip_set.h b/include/libipset/linux_ip_set.h
> index def91b9..4f93886 100644
> --- a/include/libipset/linux_ip_set.h
> +++ b/include/libipset/linux_ip_set.h
> @@ -84,6 +84,7 @@ enum {
>  	IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO,	/* 9 */
>  	IPSET_ATTR_MARK,	/* 10 */
>  	IPSET_ATTR_MARKMASK,	/* 11 */
> +	IPSET_ATTR_NETMASK_MASK,/* 12 */
>  	/* Reserve empty slots */
>  	IPSET_ATTR_CADT_MAX = 16,
>  	/* Create-only specific attributes */
> @@ -199,6 +200,8 @@ enum ipset_cadt_flags {
>  	IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD),
>  	IPSET_FLAG_BIT_WITH_SKBINFO = 6,
>  	IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO),
> +	IPSET_FLAG_BIT_WITH_NETMASK = 7,
> +	IPSET_FLAG_WITH_NETMASK = (1 << IPSET_FLAG_BIT_WITH_NETMASK),
>  	IPSET_FLAG_CADT_MAX	= 15,
>  };
>  
> @@ -206,6 +209,8 @@ enum ipset_cadt_flags {
>  enum ipset_create_flags {
>  	IPSET_CREATE_FLAG_BIT_FORCEADD = 0,
>  	IPSET_CREATE_FLAG_FORCEADD = (1 << IPSET_CREATE_FLAG_BIT_FORCEADD),
> +	IPSET_CREATE_FLAG_BIT_NETMASK = 1,
> +	IPSET_CREATE_FLAG_NETMASK = (1 << IPSET_CREATE_FLAG_BIT_NETMASK),
>  	IPSET_CREATE_FLAG_BIT_MAX = 7,
>  };
>  
> diff --git a/include/libipset/print.h b/include/libipset/print.h
> index 2103ce1..f9e77d3 100644
> --- a/include/libipset/print.h
> +++ b/include/libipset/print.h
> @@ -74,6 +74,9 @@ extern int ipset_print_flag(char *buf, unsigned int len,
>  extern int ipset_print_elem(char *buf, unsigned int len,
>  			    const struct ipset_data *data,
>  			    enum ipset_opt opt, uint8_t env);
> +extern int ipset_print_netmask(char *buf, unsigned int len,
> +			    const struct ipset_data *data,
> +			    enum ipset_opt opt, uint8_t env);
>  
>  #define ipset_print_portnum	ipset_print_number
>  
> diff --git a/lib/data.c b/lib/data.c
> index 8372a2f..951a124 100644
> --- a/lib/data.c
> +++ b/lib/data.c
> @@ -24,6 +24,11 @@
>   * We always store the data in host order, *except* IP addresses.
>   */
>  
> +struct ipset_netmask {
> +	uint8_t cidr;
> +	union nf_inet_addr mask;
> +};
> +
>  struct ipset_data {
>  	/* Option bits: which fields are set */
>  	uint64_t bits;
> @@ -51,7 +56,7 @@ struct ipset_data {
>  		struct {
>  			uint8_t probes;
>  			uint8_t resize;
> -			uint8_t netmask;
> +			struct ipset_netmask netmask;
>  			uint32_t hashsize;
>  			uint32_t maxelem;
>  			uint32_t markmask;
> @@ -295,7 +300,13 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
>  		data->create.markmask = *(const uint32_t *) value;
>  		break;
>  	case IPSET_OPT_NETMASK:
> -		data->create.netmask = *(const uint8_t *) value;
> +		data->create.netmask.cidr = *(const uint8_t *) value;
> +		break;
> +	case IPSET_OPT_NETMASK_MASK:
> +		if (!(data->family == NFPROTO_IPV4 ||
> +		      data->family == NFPROTO_IPV6))
> +			return -1;
> +		copy_addr(data->family, &data->create.netmask.mask, value);
>  		break;
>  	case IPSET_OPT_PROBES:
>  		data->create.probes = *(const uint8_t *) value;
> @@ -318,6 +329,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
>  	case IPSET_OPT_SKBINFO:
>  		cadt_flag_type_attr(data, opt, IPSET_FLAG_WITH_SKBINFO);
>  		break;
> +	case IPSET_OPT_NETMASK_FLAG:
> +		cadt_flag_type_attr(data, opt, IPSET_FLAG_WITH_NETMASK);
> +		break;
>  	/* Create-specific options, filled out by the kernel */
>  	case IPSET_OPT_ELEMENTS:
>  		data->create.elements = *(const uint32_t *) value;
> @@ -495,7 +509,9 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
>  	case IPSET_OPT_MARKMASK:
>  		return &data->create.markmask;
>  	case IPSET_OPT_NETMASK:
> -		return &data->create.netmask;
> +		return &data->create.netmask.cidr;
> +	case IPSET_OPT_NETMASK_MASK:
> +		return &data->create.netmask.mask;
>  	case IPSET_OPT_PROBES:
>  		return &data->create.probes;
>  	case IPSET_OPT_RESIZE:
> @@ -558,6 +574,7 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
>  	case IPSET_OPT_CREATE_COMMENT:
>  	case IPSET_OPT_FORCEADD:
>  	case IPSET_OPT_SKBINFO:
> +	case IPSET_OPT_NETMASK_FLAG:
>  		return &data->cadt_flags;
>  	default:
>  		return NULL;
> @@ -581,6 +598,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
>  	case IPSET_OPT_IP_TO:
>  	case IPSET_OPT_IP2:
>  	case IPSET_OPT_IP2_TO:
> +	case IPSET_OPT_NETMASK_MASK:
>  		return family == NFPROTO_IPV4 ? sizeof(uint32_t)
>  					 : sizeof(struct in6_addr);
>  	case IPSET_OPT_MARK:
> @@ -623,6 +641,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
>  	case IPSET_OPT_NOMATCH:
>  	case IPSET_OPT_COUNTERS:
>  	case IPSET_OPT_FORCEADD:
> +	case IPSET_OPT_NETMASK_FLAG:
>  		return sizeof(uint32_t);
>  	case IPSET_OPT_ADT_COMMENT:
>  		return IPSET_MAX_COMMENT_SIZE + 1;
> diff --git a/lib/debug.c b/lib/debug.c
> index 6f831ec..a32f709 100644
> --- a/lib/debug.c
> +++ b/lib/debug.c
> @@ -40,6 +40,7 @@ static const struct ipset_attrname createattr2name[] = {
>  	[IPSET_ATTR_MAXELEM]	= { .name = "MAXELEM" },
>  	[IPSET_ATTR_MARKMASK]	= { .name = "MARKMASK" },
>  	[IPSET_ATTR_NETMASK]	= { .name = "NETMASK" },
> +	[IPSET_ATTR_NETMASK_MASK] = { .name = "NETMASK_MASK" },
>  	[IPSET_ATTR_PROBES]	= { .name = "PROBES" },
>  	[IPSET_ATTR_RESIZE]	= { .name = "RESIZE" },
>  	[IPSET_ATTR_SIZE]	= { .name = "SIZE" },
> diff --git a/lib/parse.c b/lib/parse.c
> index 88d2888..5c41c37 100644
> --- a/lib/parse.c
> +++ b/lib/parse.c
> @@ -1654,7 +1654,35 @@ ipset_parse_uint8(struct ipset_session *session,
>  }
>  
>  /**
> + * ipset_cidr_to_mask - convert cidr value to mask stored in nf_inet_addr
> + * @addr: store resulting mask here
> + * @cidr: value to convert to mask
> + * @family: INET family type
> + *
> + * Parse cidr value and convert it into a mask stored in an nf_inet_addr.
> + */
> +static void
> +ipset_cidr_to_mask(union nf_inet_addr *addr, uint8_t cidr, uint8_t family)
> +{
> +	uint8_t i;
> +	uint8_t addrsize = (family == NFPROTO_IPV4) ? 1 : 4;
> +
> +        for (i=0; i < addrsize; i++) {
> +		if (!cidr) {
> +			addr->all[i] = 0;
> +		} else if (cidr >= 32) {
> +			addr->all[i] = 0xffffffff;
> +			cidr -= 32;
> +		} else {
> +			addr->all[i] = htonl(~((1 << (32 - cidr)) - 1));
> +			break;
> +		}
> +	}
> +}

If either IPSET_ATTR_NETMASK or IPSET_ATTR_NETMASK_MASK is passed then
I think ipset_cidr_to_mask() is unnecessary.

> +/**
>   * ipset_parse_netmask - parse string as a CIDR netmask value
> + *			 or netmask value
>   * @session: session structure
>   * @opt: option kind of the data
>   * @str: string to parse
> @@ -1669,12 +1697,13 @@ int
>  ipset_parse_netmask(struct ipset_session *session,
>  		    enum ipset_opt opt, const char *str)
>  {
> -	uint8_t family, cidr;
> +	uint8_t family, cidr = 0;
>  	struct ipset_data *data;
>  	int err = 0;
> +	union nf_inet_addr netmask = {};
>  
>  	assert(session);
> -	assert(opt == IPSET_OPT_NETMASK);
> +	assert(opt == IPSET_OPT_NETMASK_MASK || opt == IPSET_OPT_NETMASK);
>  	assert(str);
>  
>  	data = ipset_session_data(session);
> @@ -1684,16 +1713,41 @@ ipset_parse_netmask(struct ipset_session *session,
>  		ipset_data_set(data, IPSET_OPT_FAMILY, &family);
>  	}
>  
> +	/* Try to parse input as CIDR first */
>  	err = string_to_cidr(session, str, 1,
>  			     family == NFPROTO_IPV4 ? 32 : 128,
>  			     &cidr);
>  
> -	if (err)
> -		return syntax_err("netmask is out of the inclusive range "
> -				  "of 1-%u",
> -				  family == NFPROTO_IPV4 ? 32 : 128);
> +	if (opt == IPSET_OPT_NETMASK) {
> +		if (err)
> +			return syntax_err("netmask is out of the inclusive range "
> +					  "of 1-%u",
> +					  family == NFPROTO_IPV4 ? 32 : 128);
> +
> +		return ipset_data_set(data, opt, &cidr);
> +	} else {
> +
> +		/* If that fails, attempt to parse as an IP addr */
> +		if (err) {
> +			/* Store mask value as input by user */
> +			err = parse_ipaddr(session, opt, str, family);
> +			if (err)
> +				return err;
>  
> -	return ipset_data_set(data, opt, &cidr);
> +			/* Check if it's a CIDR and store if it is */
> +			netmask = *(const union nf_inet_addr *) ipset_data_get(data, IPSET_OPT_NETMASK_MASK);
> +		} else {
> +			ipset_cidr_to_mask(&netmask, cidr, family);
> +
> +			err = ipset_data_set(data, opt, &netmask);
> +			if (err)
> +				return err;
> +		}
> +
> +		ipset_data_set(data, IPSET_OPT_NETMASK_FLAG, &family);
> +
> +		return ipset_data_set(data, IPSET_OPT_NETMASK, &cidr);
> +	}
>  }

The parser should work with IPSET_OPT_NETMASK only and depending on the 
value, it should set either IPSET_OPT_NETMASK (cidr is parsed) or
both IPSET_OPT_NETMASK_MASK (wildcard mask is passed) and  
IPSET_CREATE_FLAG_NETMASK.

>  /**
> diff --git a/lib/print.c b/lib/print.c
> index 7dd229e..cc450c6 100644
> --- a/lib/print.c
> +++ b/lib/print.c
> @@ -241,6 +241,39 @@ SNPRINTF_IP(32, 4)
>  SNPRINTF_IP(128, 6)
>  
>  /**
> + * ipset_print_netmask - print netmask in either CIDR or address to string
> + * @buf: printing buffer
> + * @len: length of available buffer space
> + * @data: data blob
> + * @opt: the option kind
> + * @env: environment flags
> + *
> + * If the netmask can be represented as a CIDR print that, otherwise print
> + * the mask value.
> + *
> + * Return length of printed string or error size.
> + */
> +int
> +ipset_print_netmask(char *buf, unsigned int len,
> +		    const struct ipset_data *data, enum ipset_opt opt,
> +		    uint8_t env)
> +{
> +	uint8_t cidr;
> +
> +	assert(buf);
> +	assert(len > 0);
> +	assert(data);
> +	assert(opt == IPSET_OPT_NETMASK_MASK);
> +
> +	cidr = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_NETMASK);
> +
> +	if (cidr)
> +		return snprintf(buf, len, "%u", cidr);
> +	else
> +		return ipset_print_ip(buf, len, data, opt, env);
> +}
> +
> +/**
>   * ipset_print_ip - print IPv4|IPv6 address to string
>   * @buf: printing buffer
>   * @len: length of available buffer space
> @@ -265,7 +298,7 @@ ipset_print_ip(char *buf, unsigned int len,
>  	assert(buf);
>  	assert(len > 0);
>  	assert(data);
> -	assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
> +	assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2 || opt == IPSET_OPT_NETMASK_MASK);
>  
>  	D("len: %u", len);
>  	family = ipset_data_family(data);
> @@ -944,7 +977,6 @@ ipset_print_data(char *buf, unsigned int len,
>  	case IPSET_OPT_HASHSIZE:
>  	case IPSET_OPT_MAXELEM:
>  	case IPSET_OPT_MARKMASK:
> -	case IPSET_OPT_NETMASK:
>  	case IPSET_OPT_PROBES:
>  	case IPSET_OPT_RESIZE:
>  	case IPSET_OPT_TIMEOUT:
> @@ -953,6 +985,9 @@ ipset_print_data(char *buf, unsigned int len,
>  	case IPSET_OPT_SIZE:
>  		size = ipset_print_number(buf, len, data, opt, env);
>  		break;
> +	case IPSET_OPT_NETMASK_MASK:
> +		size = ipset_print_netmask(buf, len, data, opt, env);
> +		break;
>  	default:
>  		return -1;
>  	}
> diff --git a/lib/session.c b/lib/session.c
> index 1bdaaa7..55eab83 100644
> --- a/lib/session.c
> +++ b/lib/session.c
> @@ -414,6 +414,10 @@ static const struct ipset_attr_policy create_attrs[] = {
>  		.type = MNL_TYPE_U32,
>  		.opt = IPSET_OPT_MEMSIZE,
>  	},
> +	[IPSET_ATTR_NETMASK_MASK] = {
> +		.type = MNL_TYPE_NESTED,
> +		.opt = IPSET_OPT_NETMASK_MASK,
> +	},
>  };
>  
>  static const struct ipset_attr_policy adt_attrs[] = {
> @@ -1494,6 +1498,10 @@ rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
>  	if (attr->type == MNL_TYPE_NESTED) {
>  		/* IP addresses */
>  		struct nlattr *nested;
> +
> +		if (type == IPSET_ATTR_NETMASK_MASK)
> +			family = ipset_data_family(session->data);
> +
>  		int atype = family == NFPROTO_IPV4 ? IPSET_ATTR_IPADDR_IPV4
>  					      : IPSET_ATTR_IPADDR_IPV6;
>  
> -- 
> 1.9.1

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlecsik.jozsef@wigner.mta.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : Wigner Research Centre for Physics, Hungarian Academy of Sciences
          H-1525 Budapest 114, POB. 49, Hungary

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/5] ipset: hash:ipport: netmask support
  2017-03-21 18:39 ` [PATCH 3/5] ipset: hash:ipport: netmask support Josh Hunt
@ 2017-03-27 20:12   ` Jozsef Kadlecsik
  0 siblings, 0 replies; 8+ messages in thread
From: Jozsef Kadlecsik @ 2017-03-27 20:12 UTC (permalink / raw)
  To: Josh Hunt; +Cc: netfilter-devel, coreteam

On Tue, 21 Mar 2017, Josh Hunt wrote:

> Adds netmask support to hash:ipport sets.
> 
> Signed-off-by: Josh Hunt <johunt@akamai.com>
> ---
>  lib/ipset_hash_ipport.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 194 insertions(+)
> 
> diff --git a/lib/ipset_hash_ipport.c b/lib/ipset_hash_ipport.c
> index 2166922..a2cf79e 100644
> --- a/lib/ipset_hash_ipport.c
> +++ b/lib/ipset_hash_ipport.c
> @@ -787,6 +787,199 @@ static struct ipset_type ipset_hash_ipport5 = {
>  	.description = "skbinfo support",
>  };
>  
> +/* Parse commandline arguments */
> +static const struct ipset_arg hash_ipport_create_args6[] = {
> +	{ .name = { "family", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_FAMILY,
> +	  .parse = ipset_parse_family,		.print = ipset_print_family,
> +	},
> +	/* Alias: family inet */
> +	{ .name = { "-4", NULL },
> +	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_FAMILY,
> +	  .parse = ipset_parse_family,
> +	},
> +	/* Alias: family inet6 */
> +	{ .name = { "-6", NULL },
> +	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_FAMILY,
> +	  .parse = ipset_parse_family,
> +	},
> +	{ .name = { "hashsize", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_HASHSIZE,
> +	  .parse = ipset_parse_uint32,		.print = ipset_print_number,
> +	},
> +	{ .name = { "maxelem", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_MAXELEM,
> +	  .parse = ipset_parse_uint32,		.print = ipset_print_number,
> +	},
> +	{ .name = { "timeout", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_TIMEOUT,
> +	  .parse = ipset_parse_timeout,		.print = ipset_print_number,
> +	},
> +	{ .name = { "counters", NULL },
> +	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_COUNTERS,
> +	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
> +	},
> +	{ .name = { "comment", NULL },
> +	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_CREATE_COMMENT,
> +	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
> +	},
> +	{ .name = { "forceadd", NULL },
> +	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_FORCEADD,
> +	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
> +	},
> +	{ .name = { "skbinfo", NULL },
> +	  .has_arg = IPSET_NO_ARG,		.opt = IPSET_OPT_SKBINFO,
> +	  .parse = ipset_parse_flag,		.print = ipset_print_flag,
> +	},
> +	{ .name = { "netmask", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_NETMASK_MASK,
> +	  .parse = ipset_parse_netmask,         .print = ipset_print_netmask,

With the modified parser you can use IPSET_OPT_NETMASK here - and the same 
comment for the hash:ip,port type.

> +	},
> +	/* Backward compatibility */
> +	{ .name = { "probes", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_PROBES,
> +	  .parse = ipset_parse_ignored,		.print = ipset_print_number,
> +	},
> +	{ .name = { "resize", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_RESIZE,
> +	  .parse = ipset_parse_ignored,		.print = ipset_print_number,
> +	},
> +	{ .name = { "from", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_IP,
> +	  .parse = ipset_parse_ignored,
> +	},
> +	{ .name = { "to", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_IP_TO,
> +	  .parse = ipset_parse_ignored,
> +	},
> +	{ .name = { "network", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_IP,
> +	  .parse = ipset_parse_ignored,
> +	},
> +	{ },
> +};
> +
> +static const struct ipset_arg hash_ipport_add_args6[] = {
> +	{ .name = { "timeout", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_TIMEOUT,
> +	  .parse = ipset_parse_timeout,		.print = ipset_print_number,
> +	},
> +	{ .name = { "packets", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_PACKETS,
> +	  .parse = ipset_parse_uint64,		.print = ipset_print_number,
> +	},
> +	{ .name = { "bytes", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_BYTES,
> +	  .parse = ipset_parse_uint64,		.print = ipset_print_number,
> +	},
> +	{ .name = { "comment", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_ADT_COMMENT,
> +	  .parse = ipset_parse_comment,		.print = ipset_print_comment,
> +	},
> +	{ .name = { "skbmark", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_SKBMARK,
> +	  .parse = ipset_parse_skbmark,		.print = ipset_print_skbmark,
> +	},
> +	{ .name = { "skbprio", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_SKBPRIO,
> +	  .parse = ipset_parse_skbprio,		.print = ipset_print_skbprio,
> +	},
> +	{ .name = { "skbqueue", NULL },
> +	  .has_arg = IPSET_MANDATORY_ARG,	.opt = IPSET_OPT_SKBQUEUE,
> +	  .parse = ipset_parse_uint16,		.print = ipset_print_number,
> +	},
> +	{ },
> +};
> +
> +static const char hash_ipport_usage6[] =
> +"create SETNAME hash:ip,port\n"
> +"		[family inet|inet6]\n"
> +"               [hashsize VALUE] [maxelem VALUE]\n"
> +"               [timeout VALUE] [counters] [comment]\n"
> +"		[forceadd] [skbinfo] [netmask CIDR or MASK]\n"
> +"add    SETNAME IP,PROTO:PORT [timeout VALUE]\n"
> +"               [packets VALUE] [bytes VALUE] [comment \"string\"]\n"
> +"		[skbmark VALUE] [skbprio VALUE] [skbqueue VALUE]\n"
> +"del    SETNAME IP,PROTO:PORT\n"
> +"test   SETNAME IP,PROTO:PORT\n\n"
> +"where depending on the INET family\n"
> +"      IP is a valid IPv4 or IPv6 address (or hostname).\n"
> +"      Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
> +"      is supported for IPv4.\n"
> +"      Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
> +"      port range is supported both for IPv4 and IPv6.\n";
> +
> +static struct ipset_type ipset_hash_ipport6 = {
> +	.name = "hash:ip,port",
> +	.alias = { "ipporthash", NULL },
> +	.revision = 6,
> +	.family = NFPROTO_IPSET_IPV46,
> +	.dimension = IPSET_DIM_TWO,
> +	.elem = {
> +		[IPSET_DIM_ONE - 1] = {
> +			.parse = ipset_parse_ip4_single6,
> +			.print = ipset_print_ip,
> +			.opt = IPSET_OPT_IP
> +		},
> +		[IPSET_DIM_TWO - 1] = {
> +			.parse = ipset_parse_proto_port,
> +			.print = ipset_print_proto_port,
> +			.opt = IPSET_OPT_PORT
> +		},
> +	},
> +	.args = {
> +		[IPSET_CREATE] = hash_ipport_create_args6,
> +		[IPSET_ADD] = hash_ipport_add_args6,
> +	},
> +	.mandatory = {
> +		[IPSET_CREATE] = 0,
> +		[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
> +			| IPSET_FLAG(IPSET_OPT_PROTO)
> +			| IPSET_FLAG(IPSET_OPT_PORT),
> +		[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
> +			| IPSET_FLAG(IPSET_OPT_PROTO)
> +			| IPSET_FLAG(IPSET_OPT_PORT),
> +		[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
> +			| IPSET_FLAG(IPSET_OPT_PROTO)
> +			| IPSET_FLAG(IPSET_OPT_PORT),
> +	},
> +	.full = {
> +		[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
> +			| IPSET_FLAG(IPSET_OPT_MAXELEM)
> +			| IPSET_FLAG(IPSET_OPT_TIMEOUT)
> +			| IPSET_FLAG(IPSET_OPT_COUNTERS)
> +			| IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)
> +			| IPSET_FLAG(IPSET_OPT_FORCEADD)
> +			| IPSET_FLAG(IPSET_OPT_SKBINFO)
> +			| IPSET_FLAG(IPSET_OPT_NETMASK)
> +			| IPSET_FLAG(IPSET_OPT_NETMASK_MASK),
> +		[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
> +			| IPSET_FLAG(IPSET_OPT_IP_TO)
> +			| IPSET_FLAG(IPSET_OPT_PORT)
> +			| IPSET_FLAG(IPSET_OPT_PORT_TO)
> +			| IPSET_FLAG(IPSET_OPT_PROTO)
> +			| IPSET_FLAG(IPSET_OPT_TIMEOUT)
> +			| IPSET_FLAG(IPSET_OPT_PACKETS)
> +			| IPSET_FLAG(IPSET_OPT_BYTES)
> +			| IPSET_FLAG(IPSET_OPT_ADT_COMMENT)
> +			| IPSET_FLAG(IPSET_OPT_SKBMARK)
> +			| IPSET_FLAG(IPSET_OPT_SKBPRIO)
> +			| IPSET_FLAG(IPSET_OPT_SKBQUEUE),
> +		[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
> +			| IPSET_FLAG(IPSET_OPT_IP_TO)
> +			| IPSET_FLAG(IPSET_OPT_PORT)
> +			| IPSET_FLAG(IPSET_OPT_PORT_TO)
> +			| IPSET_FLAG(IPSET_OPT_PROTO),
> +		[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
> +			| IPSET_FLAG(IPSET_OPT_PORT)
> +			| IPSET_FLAG(IPSET_OPT_PROTO),
> +	},
> +
> +	.usage = hash_ipport_usage6,
> +	.usagefn = ipset_port_usage,
> +	.description = "netmask support",
> +};
> +
>  void _init(void);
>  void _init(void)
>  {
> @@ -795,4 +988,5 @@ void _init(void)
>  	ipset_type_add(&ipset_hash_ipport3);
>  	ipset_type_add(&ipset_hash_ipport4);
>  	ipset_type_add(&ipset_hash_ipport5);
> +	ipset_type_add(&ipset_hash_ipport6);
>  }
> -- 
> 1.9.1

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlecsik.jozsef@wigner.mta.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : Wigner Research Centre for Physics, Hungarian Academy of Sciences
          H-1525 Budapest 114, POB. 49, Hungary

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-03-27 20:12 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-21 18:39 [PATCH 0/5] ipset: Extend netmask support for userspace Josh Hunt
2017-03-21 18:39 ` [PATCH 1/5] ipset: netmask: expand to support cidr and full mask Josh Hunt
2017-03-27 20:08   ` Jozsef Kadlecsik
2017-03-21 18:39 ` [PATCH 2/5] ipset: hash:ip: add support for new netmask types Josh Hunt
2017-03-21 18:39 ` [PATCH 3/5] ipset: hash:ipport: netmask support Josh Hunt
2017-03-27 20:12   ` Jozsef Kadlecsik
2017-03-21 18:39 ` [PATCH 4/5] hash:ip: add new netmask support to man page Josh Hunt
2017-03-21 18:39 ` [PATCH 5/5] hash:ip,port: add " Josh Hunt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.