netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* guided option parser, run 6
@ 2011-05-09 19:54 Jan Engelhardt
  2011-05-09 19:54 ` [PATCH 01/17] libxtables: support for XTTYPE_PLENMASK Jan Engelhardt
                   ` (17 more replies)
  0 siblings, 18 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:54 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel


The following changes since commit c29f7ef7cb5a31620060ef721d3c65b343eb537a:

  Merge branch 'opts' of git://dev.medozas.de/iptables (2011-05-09 20:23:21 +0200)

are available in the git repository at:

  git://dev.medozas.de/iptables opts

Jan Engelhardt (17):
      libxtables: support for XTTYPE_PLENMASK
      libxt_connlimit: use guided option parser
      libxt_recent: use guided option parser
      libxtables: do not overlay addr and mask parts, and cleanup
      libxtables: flag invalid uses of XTOPT_PUT
      libxtables: XTTYPE_PLEN support
      libxt_hashlimit: use guided option parser
      libxtables: XTTYPE_HOSTMASK support
      libxt_policy: use guided option parser
      libxt_owner: use guided option parser
      libxt_osf: use guided option parser
      libxt_multiport: use guided option parser
      libipt_NETMAP: use guided option parser
      libxt_limit: use guided option parser
      libxtables: XTTYPE_PROTOCOL support
      libxt_ipvs: use guided option parser
      libxt_conntrack: use guided option parser

 extensions/libipt_NETMAP.c   |  106 +------
 extensions/libxt_TEE.c       |    2 +-
 extensions/libxt_TPROXY.c    |    6 +-
 extensions/libxt_connlimit.c |  176 ++++-------
 extensions/libxt_conntrack.c |  670 ++++++++++++++----------------------------
 extensions/libxt_hashlimit.c |  419 ++++++++------------------
 extensions/libxt_ipvs.c      |  208 ++++---------
 extensions/libxt_limit.c     |   53 ++--
 extensions/libxt_multiport.c |  178 +++++-------
 extensions/libxt_osf.c       |   97 ++-----
 extensions/libxt_owner.c     |  288 ++++++++-----------
 extensions/libxt_policy.c    |  269 +++++------------
 extensions/libxt_recent.c    |  186 +++++-------
 include/xtables.h.in         |   28 ++-
 xtoptions.c                  |  147 +++++++++-
 15 files changed, 1050 insertions(+), 1783 deletions(-)

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

* [PATCH 01/17] libxtables: support for XTTYPE_PLENMASK
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
@ 2011-05-09 19:54 ` Jan Engelhardt
  2011-05-09 19:54 ` [PATCH 02/17] libxt_connlimit: use guided option parser Jan Engelhardt
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:54 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 include/xtables.h.in |    4 +++-
 xtoptions.c          |   43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletions(-)

diff --git a/include/xtables.h.in b/include/xtables.h.in
index 47f797b..a760755 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -59,6 +59,7 @@ struct in_addr;
  * %XTTYPE_PORT_NE:	16-bit port name or number, stored as network-endian
  * %XTTYPE_PORTRC:	colon-separated port range (names acceptable)
  * %XTTYPE_PORTRC_NE:	same as %XTTYPE_PORTRC, stored in network-endian
+ * %XTTYPE_PLENMASK:	prefix len stored as union nf_inet_addr
  */
 enum xt_option_type {
 	XTTYPE_NONE,
@@ -80,6 +81,7 @@ enum xt_option_type {
 	XTTYPE_PORT_NE,
 	XTTYPE_PORTRC,
 	XTTYPE_PORTRC_NE,
+	XTTYPE_PLENMASK,
 };
 
 /**
@@ -139,7 +141,7 @@ struct xt_option_call {
 		uint32_t u32, u32_range[2];
 		uint64_t u64, u64_range[2];
 		double dbl;
-		union nf_inet_addr inetaddr;
+		union nf_inet_addr inetaddr, inetmask;
 		struct {
 			uint8_t tos_value, tos_mask;
 		};
diff --git a/xtoptions.c b/xtoptions.c
index 86498a9..2bd66f9 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -561,6 +561,47 @@ static void xtopt_parse_mport(struct xt_option_call *cb)
 	free(lo_arg);
 }
 
+static void xtopt_parse_plenmask(struct xt_option_call *cb)
+{
+	const struct xt_option_entry *entry = cb->entry;
+	uint32_t *mask = cb->val.inetmask.all;
+	unsigned int prefix_len = 128;
+	uint8_t max = 128;
+
+	if (afinfo->family == NFPROTO_IPV6)
+		max = 128;
+	else if (afinfo->family == NFPROTO_IPV4)
+		max = 32;
+
+	if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, max))
+		xt_params->exit_err(PARAMETER_PROBLEM,
+			"%s: bad value for option \"--%s\", "
+			"or out of range (%u-%u).\n",
+			cb->ext_name, entry->name, 0, max);
+
+	memset(mask, 0xFF, sizeof(union nf_inet_addr));
+	if (prefix_len == 0) {
+		mask[0] = mask[1] = mask[2] = mask[3] = 0;
+	} else if (prefix_len <= 32) {
+		mask[0] <<= 32 - prefix_len;
+		mask[1] = mask[2] = mask[3] = 0;
+	} else if (prefix_len <= 64) {
+		mask[1] <<= 32 - (prefix_len - 32);
+		mask[2] = mask[3] = 0;
+	} else if (prefix_len <= 96) {
+		mask[2] <<= 32 - (prefix_len - 64);
+		mask[3] = 0;
+	} else if (prefix_len <= 128) {
+		mask[3] <<= 32 - (prefix_len - 96);
+	}
+	mask[0] = htonl(mask[0]);
+	mask[1] = htonl(mask[1]);
+	mask[2] = htonl(mask[2]);
+	mask[3] = htonl(mask[3]);
+	if (entry->flags & XTOPT_PUT)
+		memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr));
+}
+
 static void (*const xtopt_subparse[])(struct xt_option_call *) = {
 	[XTTYPE_UINT8]       = xtopt_parse_int,
 	[XTTYPE_UINT16]      = xtopt_parse_int,
@@ -580,6 +621,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
 	[XTTYPE_PORT_NE]     = xtopt_parse_port,
 	[XTTYPE_PORTRC]      = xtopt_parse_mport,
 	[XTTYPE_PORTRC_NE]   = xtopt_parse_mport,
+	[XTTYPE_PLENMASK]    = xtopt_parse_plenmask,
 };
 
 static const size_t xtopt_psize[] = {
@@ -599,6 +641,7 @@ static const size_t xtopt_psize[] = {
 	[XTTYPE_PORT_NE]     = sizeof(uint16_t),
 	[XTTYPE_PORTRC]      = sizeof(uint16_t[2]),
 	[XTTYPE_PORTRC_NE]   = sizeof(uint16_t[2]),
+	[XTTYPE_PLENMASK]    = sizeof(union nf_inet_addr),
 };
 
 /**
-- 
1.7.1


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

* [PATCH 02/17] libxt_connlimit: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
  2011-05-09 19:54 ` [PATCH 01/17] libxtables: support for XTTYPE_PLENMASK Jan Engelhardt
@ 2011-05-09 19:54 ` Jan Engelhardt
  2011-05-09 19:54 ` [PATCH 03/17] libxt_recent: " Jan Engelhardt
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:54 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_connlimit.c |  176 +++++++++++++++--------------------------
 1 files changed, 65 insertions(+), 111 deletions(-)

diff --git a/extensions/libxt_connlimit.c b/extensions/libxt_connlimit.c
index badf68c..a569f86 100644
--- a/extensions/libxt_connlimit.c
+++ b/extensions/libxt_connlimit.c
@@ -1,18 +1,20 @@
-/* Shared library add-on to iptables to add connection limit support. */
-#include <stdbool.h>
 #include <stdio.h>
 #include <netdb.h>
 #include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <getopt.h>
 #include <xtables.h>
 #include <linux/netfilter/xt_connlimit.h>
 
 enum {
-	FL_LIMIT = 1 << 0,
-	FL_MASK  = 1 << 1,
-	FL_ADDR  = 1 << 2,
+	O_UPTO = 0,
+	O_ABOVE,
+	O_MASK,
+	O_SADDR,
+	O_DADDR,
+	F_UPTO  = 1 << O_UPTO,
+	F_ABOVE = 1 << O_ABOVE,
+	F_MASK  = 1 << O_MASK,
+	F_SADDR = 1 << O_SADDR,
+	F_DADDR = 1 << O_DADDR,
 };
 
 static void connlimit_help(void)
@@ -26,14 +28,23 @@ static void connlimit_help(void)
 "  --connlimit-daddr      select destination addresses for grouping\n");
 }
 
-static const struct option connlimit_opts[] = {
-	{.name = "connlimit-upto",  .has_arg = true, .val = 'U'},
-	{.name = "connlimit-above", .has_arg = true, .val = 'A'},
-	{.name = "connlimit-mask",  .has_arg = true, .val = 'M'},
-	{.name = "connlimit-saddr", .has_arg = false, .val = 's'},
-	{.name = "connlimit-daddr", .has_arg = false, .val = 'd'},
-	XT_GETOPT_TABLEEND,
+#define s struct xt_connlimit_info
+static const struct xt_option_entry connlimit_opts[] = {
+	{.name = "connlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_INVERT | XTOPT_PUT,
+	 XTOPT_POINTER(s, limit)},
+	{.name = "connlimit-above", .id = O_ABOVE, .excl = F_UPTO,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_INVERT | XTOPT_PUT,
+	 XTOPT_POINTER(s, limit)},
+	{.name = "connlimit-mask", .id = O_MASK, .type = XTTYPE_PLENMASK,
+	 .flags = XTOPT_PUT, XTOPT_POINTER(s, mask)},
+	{.name = "connlimit-saddr", .id = O_SADDR, .excl = F_DADDR,
+	 .type = XTTYPE_NONE},
+	{.name = "connlimit-daddr", .id = O_DADDR, .excl = F_SADDR,
+	 .type = XTTYPE_NONE},
+	XTOPT_TABLEEND,
 };
+#undef s
 
 static void connlimit_init(struct xt_entry_match *match)
 {
@@ -43,111 +54,54 @@ static void connlimit_init(struct xt_entry_match *match)
 	memset(info->v6_mask, 0xFF, sizeof(info->v6_mask));
 }
 
-static void prefix_to_netmask(uint32_t *mask, unsigned int prefix_len)
+static void connlimit_parse(struct xt_option_call *cb, uint8_t family)
 {
-	if (prefix_len == 0) {
-		mask[0] = mask[1] = mask[2] = mask[3] = 0;
-	} else if (prefix_len <= 32) {
-		mask[0] <<= 32 - prefix_len;
-		mask[1] = mask[2] = mask[3] = 0;
-	} else if (prefix_len <= 64) {
-		mask[1] <<= 32 - (prefix_len - 32);
-		mask[2] = mask[3] = 0;
-	} else if (prefix_len <= 96) {
-		mask[2] <<= 32 - (prefix_len - 64);
-		mask[3] = 0;
-	} else if (prefix_len <= 128) {
-		mask[3] <<= 32 - (prefix_len - 96);
-	}
-	mask[0] = htonl(mask[0]);
-	mask[1] = htonl(mask[1]);
-	mask[2] = htonl(mask[2]);
-	mask[3] = htonl(mask[3]);
-}
-
-static int
-connlimit_parse(int c, char **argv, int invert, unsigned int *flags,
-                struct xt_entry_match **match, unsigned int family)
-{
-	struct xt_connlimit_info *info = (void *)(*match)->data;
-	const unsigned int revision = (*match)->u.user.revision;
-	char *err;
-	int i;
+	struct xt_connlimit_info *info = cb->data;
+	const unsigned int revision = (*cb->match)->u.user.revision;
 
-	switch (c) {
-	case 'A': /* --connlimit-above */
-		xtables_param_act(XTF_ONLY_ONCE, "connlimit",
-			"--connlimit-{upto,above}", *flags & FL_LIMIT);
-		*flags |= FL_LIMIT;
-		if (invert)
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_ABOVE:
+		if (cb->invert)
 			info->flags |= XT_CONNLIMIT_INVERT;
-		info->limit = strtoul(optarg, NULL, 0);
-		return true;
-	case 'U': /* --connlimit-upto */
-		xtables_param_act(XTF_ONLY_ONCE, "connlimit",
-			"--connlimit-{upto,above}", *flags & FL_LIMIT);
-		*flags |= FL_LIMIT;
-		if (!invert)
+		break;
+	case O_UPTO:
+		if (!cb->invert)
 			info->flags |= XT_CONNLIMIT_INVERT;
-		info->limit = strtoul(optarg, NULL, 0);
-		return true;
-	case 'M': /* --connlimit-mask */
-		xtables_param_act(XTF_NO_INVERT, "connlimit",
-			"--connlimit-mask", invert);
-		xtables_param_act(XTF_ONLY_ONCE, "connlimit",
-			"--connlimit-mask", *flags & FL_MASK);
-		*flags |= FL_MASK;
-		i = strtoul(optarg, &err, 0);
-		if (family == NFPROTO_IPV6) {
-			if (i > 128 || *err != '\0')
-				xtables_error(PARAMETER_PROBLEM,
-					"--connlimit-mask must be between "
-					"0 and 128");
-			prefix_to_netmask(info->v6_mask, i);
-		} else {
-			if (i > 32 || *err != '\0')
-				xtables_error(PARAMETER_PROBLEM,
-					"--connlimit-mask must be between "
-					"0 and 32");
-			if (i == 0)
-				info->v4_mask = 0;
-			else
-				info->v4_mask = htonl(0xFFFFFFFF << (32 - i));
-		}
-		return true;
-	case 's': /* --connlimit-saddr */
+		break;
+	case O_SADDR:
+		if (revision < 1)
+			xtables_error(PARAMETER_PROBLEM,
+				"xt_connlimit.0 does not support "
+				"--connlimit-daddr");
 		info->flags &= ~XT_CONNLIMIT_DADDR;
-		return true;
-	case 'd': /* --connlimit-daddr */
+		break;
+	case O_DADDR:
 		if (revision < 1)
 			xtables_error(PARAMETER_PROBLEM,
 				"xt_connlimit.0 does not support "
 				"--connlimit-daddr");
 		info->flags |= XT_CONNLIMIT_DADDR;
-		return true;
+		break;
 	}
-	return false;
 }
 
-static int connlimit_parse4(int c, char **argv, int invert,
-                            unsigned int *flags, const void *entry,
-                            struct xt_entry_match **match)
+static void connlimit_parse4(struct xt_option_call *cb)
 {
-	return connlimit_parse(c, argv, invert, flags, match, NFPROTO_IPV4);
+	return connlimit_parse(cb, NFPROTO_IPV4);
 }
 
-static int connlimit_parse6(int c, char **argv, int invert,
-                            unsigned int *flags, const void *entry,
-                            struct xt_entry_match **match)
+static void connlimit_parse6(struct xt_option_call *cb)
 {
-	return connlimit_parse(c, argv, invert, flags, match, NFPROTO_IPV6);
+	return connlimit_parse(cb, NFPROTO_IPV6);
 }
 
-static void connlimit_check(unsigned int flags)
+static void connlimit_check(struct xt_fcheck_call *cb)
 {
-	if (!(flags & 0x1))
+	if ((cb->xflags & (F_UPTO | F_ABOVE)) == 0)
 		xtables_error(PARAMETER_PROBLEM,
-			"You must specify \"--connlimit-above\"");
+			"You must specify \"--connlimit-above\" or "
+			"\"--connlimit-upto\".");
 }
 
 static unsigned int count_bits4(uint32_t mask)
@@ -239,11 +193,11 @@ static struct xtables_match connlimit_mt_reg[] = {
 		.userspacesize = offsetof(struct xt_connlimit_info, data),
 		.help          = connlimit_help,
 		.init          = connlimit_init,
-		.parse         = connlimit_parse4,
-		.final_check   = connlimit_check,
+		.x6_parse      = connlimit_parse4,
+		.x6_fcheck     = connlimit_check,
 		.print         = connlimit_print4,
 		.save          = connlimit_save4,
-		.extra_opts    = connlimit_opts,
+		.x6_options    = connlimit_opts,
 	},
 	{
 		.name          = "connlimit",
@@ -254,11 +208,11 @@ static struct xtables_match connlimit_mt_reg[] = {
 		.userspacesize = offsetof(struct xt_connlimit_info, data),
 		.help          = connlimit_help,
 		.init          = connlimit_init,
-		.parse         = connlimit_parse6,
-		.final_check   = connlimit_check,
+		.x6_parse      = connlimit_parse6,
+		.x6_fcheck     = connlimit_check,
 		.print         = connlimit_print6,
 		.save          = connlimit_save6,
-		.extra_opts    = connlimit_opts,
+		.x6_options    = connlimit_opts,
 	},
 	{
 		.name          = "connlimit",
@@ -269,11 +223,11 @@ static struct xtables_match connlimit_mt_reg[] = {
 		.userspacesize = offsetof(struct xt_connlimit_info, data),
 		.help          = connlimit_help,
 		.init          = connlimit_init,
-		.parse         = connlimit_parse4,
-		.final_check   = connlimit_check,
+		.x6_parse      = connlimit_parse4,
+		.x6_fcheck     = connlimit_check,
 		.print         = connlimit_print4,
 		.save          = connlimit_save4,
-		.extra_opts    = connlimit_opts,
+		.x6_options    = connlimit_opts,
 	},
 	{
 		.name          = "connlimit",
@@ -284,11 +238,11 @@ static struct xtables_match connlimit_mt_reg[] = {
 		.userspacesize = offsetof(struct xt_connlimit_info, data),
 		.help          = connlimit_help,
 		.init          = connlimit_init,
-		.parse         = connlimit_parse6,
-		.final_check   = connlimit_check,
+		.x6_parse      = connlimit_parse6,
+		.x6_fcheck     = connlimit_check,
 		.print         = connlimit_print6,
 		.save          = connlimit_save6,
-		.extra_opts    = connlimit_opts,
+		.x6_options    = connlimit_opts,
 	},
 };
 
-- 
1.7.1


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

* [PATCH 03/17] libxt_recent: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
  2011-05-09 19:54 ` [PATCH 01/17] libxtables: support for XTTYPE_PLENMASK Jan Engelhardt
  2011-05-09 19:54 ` [PATCH 02/17] libxt_connlimit: use guided option parser Jan Engelhardt
@ 2011-05-09 19:54 ` Jan Engelhardt
  2011-05-09 19:54 ` [PATCH 04/17] libxtables: do not overlay addr and mask parts, and cleanup Jan Engelhardt
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:54 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_recent.c |  186 +++++++++++++++++++--------------------------
 1 files changed, 79 insertions(+), 107 deletions(-)

diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c
index f8a5a18..1e1a111 100644
--- a/extensions/libxt_recent.c
+++ b/extensions/libxt_recent.c
@@ -1,27 +1,50 @@
-/* Shared library add-on to iptables to add recent matching support. */
 #include <stdbool.h>
 #include <stdio.h>
-#include <netdb.h>
 #include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
 #include <xtables.h>
 #include <linux/netfilter/xt_recent.h>
 
-static const struct option recent_opts[] = {
-	{.name = "set",      .has_arg = false, .val = 201},
-	{.name = "rcheck",   .has_arg = false, .val = 202},
-	{.name = "update",   .has_arg = false, .val = 203},
-	{.name = "seconds",  .has_arg = true,  .val = 204},
-	{.name = "hitcount", .has_arg = true,  .val = 205},
-	{.name = "remove",   .has_arg = false, .val = 206},
-	{.name = "rttl",     .has_arg = false, .val = 207},
-	{.name = "name",     .has_arg = true,  .val = 208},
-	{.name = "rsource",  .has_arg = false, .val = 209},
-	{.name = "rdest",    .has_arg = false, .val = 210},
-	XT_GETOPT_TABLEEND,
+enum {
+	O_SET = 0,
+	O_RCHECK,
+	O_UPDATE,
+	O_REMOVE,
+	O_SECONDS,
+	O_HITCOUNT,
+	O_RTTL,
+	O_NAME,
+	O_RSOURCE,
+	O_RDEST,
+	F_SET    = 1 << O_SET,
+	F_RCHECK = 1 << O_RCHECK,
+	F_UPDATE = 1 << O_UPDATE,
+	F_REMOVE = 1 << O_REMOVE,
+	F_ANY_OP = F_SET | F_RCHECK | F_UPDATE | F_REMOVE,
+};
+
+#define s struct xt_recent_mtinfo
+static const struct xt_option_entry recent_opts[] = {
+	{.name = "set", .id = O_SET, .type = XTTYPE_NONE,
+	 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+	{.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE,
+	 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+	{.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE,
+	 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+	{.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE,
+	 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
+	{.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)},
+	{.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)},
+	{.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE,
+	 .excl = F_SET | F_REMOVE},
+	{.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
+	 .flags = XTOPT_PUT, XTOPT_POINTER(s, name)},
+	{.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE},
+	{.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE},
+	XTOPT_TABLEEND,
 };
+#undef s
 
 static void recent_help(void)
 {
@@ -59,101 +82,50 @@ static void recent_init(struct xt_entry_match *match)
 	info->side = XT_RECENT_SOURCE;
 }
 
-#define RECENT_CMDS \
-	(XT_RECENT_SET | XT_RECENT_CHECK | \
-	XT_RECENT_UPDATE | XT_RECENT_REMOVE)
-
-static int recent_parse(int c, char **argv, int invert, unsigned int *flags,
-                        const void *entry, struct xt_entry_match **match)
+static void recent_parse(struct xt_option_call *cb)
 {
-	struct xt_recent_mtinfo *info = (void *)(*match)->data;
-
-	switch (c) {
-		case 201:
-			if (*flags & RECENT_CMDS)
-				xtables_error(PARAMETER_PROBLEM,
-					"recent: only one of `--set', `--rcheck' "
-					"`--update' or `--remove' may be set");
-			xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-			info->check_set |= XT_RECENT_SET;
-			if (invert) info->invert = 1;
-			*flags |= XT_RECENT_SET;
-			break;
-
-		case 202:
-			if (*flags & RECENT_CMDS)
-				xtables_error(PARAMETER_PROBLEM,
-					"recent: only one of `--set', `--rcheck' "
-					"`--update' or `--remove' may be set");
-			xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-			info->check_set |= XT_RECENT_CHECK;
-			if(invert) info->invert = 1;
-			*flags |= XT_RECENT_CHECK;
-			break;
-
-		case 203:
-			if (*flags & RECENT_CMDS)
-				xtables_error(PARAMETER_PROBLEM,
-					"recent: only one of `--set', `--rcheck' "
-					"`--update' or `--remove' may be set");
-			xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-			info->check_set |= XT_RECENT_UPDATE;
-			if (invert) info->invert = 1;
-			*flags |= XT_RECENT_UPDATE;
-			break;
-
-		case 204:
-			info->seconds = atoi(optarg);
-			break;
-
-		case 205:
-			info->hit_count = atoi(optarg);
-			break;
-
-		case 206:
-			if (*flags & RECENT_CMDS)
-				xtables_error(PARAMETER_PROBLEM,
-					"recent: only one of `--set', `--rcheck' "
-					"`--update' or `--remove' may be set");
-			xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-			info->check_set |= XT_RECENT_REMOVE;
-			if (invert) info->invert = 1;
-			*flags |= XT_RECENT_REMOVE;
-			break;
-
-		case 207:
-			info->check_set |= XT_RECENT_TTL;
-			*flags |= XT_RECENT_TTL;
-			break;
-
-		case 208:
-			strncpy(info->name,optarg, XT_RECENT_NAME_LEN);
-			info->name[XT_RECENT_NAME_LEN-1] = '\0';
-			break;
-
-		case 209:
-			info->side = XT_RECENT_SOURCE;
-			break;
-
-		case 210:
-			info->side = XT_RECENT_DEST;
-			break;
+	struct xt_recent_mtinfo *info = cb->data;
+
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_SET:
+		info->check_set |= XT_RECENT_SET;
+		if (cb->invert)
+			info->invert = true;
+		break;
+	case O_RCHECK:
+		info->check_set |= XT_RECENT_CHECK;
+		if (cb->invert)
+			info->invert = true;
+		break;
+	case O_UPDATE:
+		info->check_set |= XT_RECENT_UPDATE;
+		if (cb->invert)
+			info->invert = true;
+		break;
+	case O_REMOVE:
+		info->check_set |= XT_RECENT_REMOVE;
+		if (cb->invert)
+			info->invert = true;
+		break;
+	case O_RTTL:
+		info->check_set |= XT_RECENT_TTL;
+		break;
+	case O_RSOURCE:
+		info->side = XT_RECENT_SOURCE;
+		break;
+	case O_RDEST:
+		info->side = XT_RECENT_DEST;
+		break;
 	}
-
-	return 1;
 }
 
-static void recent_check(unsigned int flags)
+static void recent_check(struct xt_fcheck_call *cb)
 {
-	if (!(flags & RECENT_CMDS))
+	if (!(cb->xflags & F_ANY_OP))
 		xtables_error(PARAMETER_PROBLEM,
 			"recent: you must specify one of `--set', `--rcheck' "
 			"`--update' or `--remove'");
-	if ((flags & XT_RECENT_TTL) &&
-	    (flags & (XT_RECENT_SET | XT_RECENT_REMOVE)))
-		xtables_error(PARAMETER_PROBLEM,
-		           "recent: --rttl may only be used with --rcheck or "
-		           "--update");
 }
 
 static void recent_print(const void *ip, const struct xt_entry_match *match,
@@ -218,11 +190,11 @@ static struct xtables_match recent_mt_reg = {
 	.userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
 	.help          = recent_help,
 	.init          = recent_init,
-	.parse         = recent_parse,
-	.final_check   = recent_check,
+	.x6_parse      = recent_parse,
+	.x6_fcheck     = recent_check,
 	.print         = recent_print,
 	.save          = recent_save,
-	.extra_opts    = recent_opts,
+	.x6_options    = recent_opts,
 };
 
 void _init(void)
-- 
1.7.1


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

* [PATCH 04/17] libxtables: do not overlay addr and mask parts, and cleanup
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (2 preceding siblings ...)
  2011-05-09 19:54 ` [PATCH 03/17] libxt_recent: " Jan Engelhardt
@ 2011-05-09 19:54 ` Jan Engelhardt
  2011-05-09 19:54 ` [PATCH 05/17] libxtables: flag invalid uses of XTOPT_PUT Jan Engelhardt
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:54 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

XTTYPE_HOSTMASK will require that what has now become haddr,
hmask/hlen are not overlays of another. Thus relax the structure and
always set all members of the {haddr, hmask, hlen} triplet now for all
types that touch any of the members.

Add some more comments and clean out ONEHOST.
---
 extensions/libxt_TEE.c    |    2 +-
 extensions/libxt_TPROXY.c |    6 ++--
 include/xtables.h.in      |   17 +++++++++++---
 xtoptions.c               |   50 +++++++++++++++++++++++++++-----------------
 4 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/extensions/libxt_TEE.c b/extensions/libxt_TEE.c
index fd9a1b2..c89e580 100644
--- a/extensions/libxt_TEE.c
+++ b/extensions/libxt_TEE.c
@@ -31,7 +31,7 @@ enum {
 
 #define s struct xt_tee_tginfo
 static const struct xt_option_entry tee_tg_opts[] = {
-	{.name = "gateway", .id = O_GATEWAY, .type = XTTYPE_ONEHOST,
+	{.name = "gateway", .id = O_GATEWAY, .type = XTTYPE_HOST,
 	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, gw)},
 	{.name = "oif", .id = O_OIF, .type = XTTYPE_STRING,
 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, oif)},
diff --git a/extensions/libxt_TPROXY.c b/extensions/libxt_TPROXY.c
index 5264ea7..61646c9 100644
--- a/extensions/libxt_TPROXY.c
+++ b/extensions/libxt_TPROXY.c
@@ -22,7 +22,7 @@ enum {
 static const struct xt_option_entry tproxy_tg0_opts[] = {
 	{.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE,
 	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)},
-	{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_ONEHOST},
+	{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST},
 	{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
 	XTOPT_TABLEEND,
 };
@@ -31,7 +31,7 @@ static const struct xt_option_entry tproxy_tg0_opts[] = {
 static const struct xt_option_entry tproxy_tg1_opts[] = {
 	{.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE,
 	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)},
-	{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_ONEHOST,
+	{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST,
 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, laddr)},
 	{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
 	XTOPT_TABLEEND,
@@ -129,7 +129,7 @@ static void tproxy_tg0_parse(struct xt_option_call *cb)
 		info->mark_mask  = cb->val.mask;
 		break;
 	case P_ADDR:
-		info->laddr = cb->val.inetaddr.ip;
+		info->laddr = cb->val.haddr.ip;
 		break;
 	}
 }
diff --git a/include/xtables.h.in b/include/xtables.h.in
index a760755..c9ad523 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -46,6 +46,12 @@ struct in_addr;
 #define XTOPT_TABLEEND {.name = NULL}
 
 /**
+ * Select the format the input has to conform to, as well as the target type
+ * (area pointed to with XTOPT_POINTER). Note that the storing is not always
+ * uniform. @cb->val will be populated with as much as there is space, i.e.
+ * exactly 2 items for ranges, but the target area can receive more values
+ * (e.g. in case of ranges), or less values (e.g. %XTTYPE_HOSTMASK).
+ *
  * %XTTYPE_NONE:	option takes no argument
  * %XTTYPE_UINT*:	standard integer
  * %XTTYPE_UINT*RC:	colon-separated range of standard integers
@@ -54,12 +60,12 @@ struct in_addr;
  * %XTTYPE_TOSMASK:	8-bit TOS value with optional mask
  * %XTTYPE_MARKMASK32:	32-bit mark with optional mask
  * %XTTYPE_SYSLOGLEVEL:	syslog level by name or number
- * %XTTYPE_ONEHOST:	one host or address (union nf_inet_addr)
+ * %XTTYPE_HOST:	one host or address (ptr: union nf_inet_addr)
  * %XTTYPE_PORT:	16-bit port name or number
  * %XTTYPE_PORT_NE:	16-bit port name or number, stored as network-endian
  * %XTTYPE_PORTRC:	colon-separated port range (names acceptable)
  * %XTTYPE_PORTRC_NE:	same as %XTTYPE_PORTRC, stored in network-endian
- * %XTTYPE_PLENMASK:	prefix len stored as union nf_inet_addr
+ * %XTTYPE_PLENMASK:	prefix length (ptr: union nf_inet_addr)
  */
 enum xt_option_type {
 	XTTYPE_NONE,
@@ -76,7 +82,7 @@ enum xt_option_type {
 	XTTYPE_TOSMASK,
 	XTTYPE_MARKMASK32,
 	XTTYPE_SYSLOGLEVEL,
-	XTTYPE_ONEHOST,
+	XTTYPE_HOST,
 	XTTYPE_PORT,
 	XTTYPE_PORT_NE,
 	XTTYPE_PORTRC,
@@ -141,7 +147,10 @@ struct xt_option_call {
 		uint32_t u32, u32_range[2];
 		uint64_t u64, u64_range[2];
 		double dbl;
-		union nf_inet_addr inetaddr, inetmask;
+		struct {
+			union nf_inet_addr haddr, hmask;
+			uint8_t hlen;
+		};
 		struct {
 			uint8_t tos_value, tos_mask;
 		};
diff --git a/xtoptions.c b/xtoptions.c
index 2bd66f9..f8031bb 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -419,9 +419,11 @@ static socklen_t xtables_sa_hostlen(unsigned int afproto)
 }
 
 /**
- * Accepts: a hostname (DNS), or a single inetaddr.
+ * Accepts: a hostname (DNS), or a single inetaddr - without any mask. The
+ * result is stored in @cb->val.haddr. Additionally, @cb->val.hmask and
+ * @cb->val.hlen are set for completeness to the appropriate values.
  */
-static void xtopt_parse_onehost(struct xt_option_call *cb)
+static void xtopt_parse_host(struct xt_option_call *cb)
 {
 	struct addrinfo hints = {.ai_family = afinfo->family};
 	unsigned int adcount = 0;
@@ -433,16 +435,19 @@ static void xtopt_parse_onehost(struct xt_option_call *cb)
 		xt_params->exit_err(PARAMETER_PROBLEM,
 			"getaddrinfo: %s\n", gai_strerror(ret));
 
+	memset(&cb->val.hmask, 0xFF, sizeof(cb->val.hmask));
+	cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
+
 	for (p = res; p != NULL; p = p->ai_next) {
 		if (adcount == 0) {
-			memset(&cb->val.inetaddr, 0, sizeof(cb->val.inetaddr));
-			memcpy(&cb->val.inetaddr,
+			memset(&cb->val.haddr, 0, sizeof(cb->val.haddr));
+			memcpy(&cb->val.haddr,
 			       xtables_sa_host(p->ai_addr, p->ai_family),
 			       xtables_sa_hostlen(p->ai_family));
 			++adcount;
 			continue;
 		}
-		if (memcmp(&cb->val.inetaddr,
+		if (memcmp(&cb->val.haddr,
 		    xtables_sa_host(p->ai_addr, p->ai_family),
 		    xtables_sa_hostlen(p->ai_family)) != 0)
 			xt_params->exit_err(PARAMETER_PROBLEM,
@@ -453,8 +458,8 @@ static void xtopt_parse_onehost(struct xt_option_call *cb)
 	freeaddrinfo(res);
 	if (cb->entry->flags & XTOPT_PUT)
 		/* Validation in xtables_option_metavalidate */
-		memcpy(XTOPT_MKPTR(cb), &cb->val.inetaddr,
-		       sizeof(cb->val.inetaddr));
+		memcpy(XTOPT_MKPTR(cb), &cb->val.haddr,
+		       sizeof(cb->val.haddr));
 }
 
 /**
@@ -488,7 +493,8 @@ static int xtables_getportbyname(const char *name)
 }
 
 /**
- * Validate and parse a port specification and put the result into @cb.
+ * Validate and parse a port specification and put the result into
+ * @cb->val.port.
  */
 static void xtopt_parse_port(struct xt_option_call *cb)
 {
@@ -561,25 +567,27 @@ static void xtopt_parse_mport(struct xt_option_call *cb)
 	free(lo_arg);
 }
 
+/**
+ * Parse an integer and ensure it is within the address family's prefix length
+ * limits. The result is stored in @cb->val.hmask and @cb->val.hlen. If
+ * %XTOPT_PUT is used, hmask will be copied to the pointed-to area.
+ */
 static void xtopt_parse_plenmask(struct xt_option_call *cb)
 {
 	const struct xt_option_entry *entry = cb->entry;
-	uint32_t *mask = cb->val.inetmask.all;
+	uint32_t *mask = cb->val.hmask.all;
 	unsigned int prefix_len = 128;
-	uint8_t max = 128;
 
-	if (afinfo->family == NFPROTO_IPV6)
-		max = 128;
-	else if (afinfo->family == NFPROTO_IPV4)
-		max = 32;
-
-	if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, max))
+	cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
+	if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen))
 		xt_params->exit_err(PARAMETER_PROBLEM,
 			"%s: bad value for option \"--%s\", "
 			"or out of range (%u-%u).\n",
-			cb->ext_name, entry->name, 0, max);
+			cb->ext_name, entry->name, 0, cb->val.hlen);
 
+	cb->val.hlen = prefix_len;
 	memset(mask, 0xFF, sizeof(union nf_inet_addr));
+	/* This shifting is AF-independent. */
 	if (prefix_len == 0) {
 		mask[0] = mask[1] = mask[2] = mask[3] = 0;
 	} else if (prefix_len <= 32) {
@@ -616,7 +624,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
 	[XTTYPE_TOSMASK]     = xtopt_parse_tosmask,
 	[XTTYPE_MARKMASK32]  = xtopt_parse_markmask,
 	[XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel,
-	[XTTYPE_ONEHOST]     = xtopt_parse_onehost,
+	[XTTYPE_HOST]        = xtopt_parse_host,
 	[XTTYPE_PORT]        = xtopt_parse_port,
 	[XTTYPE_PORT_NE]     = xtopt_parse_port,
 	[XTTYPE_PORTRC]      = xtopt_parse_mport,
@@ -625,6 +633,10 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
 };
 
 static const size_t xtopt_psize[] = {
+	/*
+	 * All types not listed here, and thus essentially being initialized to
+	 * zero have zero on purpose.
+	 */
 	[XTTYPE_UINT8]       = sizeof(uint8_t),
 	[XTTYPE_UINT16]      = sizeof(uint16_t),
 	[XTTYPE_UINT32]      = sizeof(uint32_t),
@@ -636,7 +648,7 @@ static const size_t xtopt_psize[] = {
 	[XTTYPE_DOUBLE]      = sizeof(double),
 	[XTTYPE_STRING]      = -1,
 	[XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
-	[XTTYPE_ONEHOST]     = sizeof(union nf_inet_addr),
+	[XTTYPE_HOST]        = sizeof(union nf_inet_addr),
 	[XTTYPE_PORT]        = sizeof(uint16_t),
 	[XTTYPE_PORT_NE]     = sizeof(uint16_t),
 	[XTTYPE_PORTRC]      = sizeof(uint16_t[2]),
-- 
1.7.1


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

* [PATCH 05/17] libxtables: flag invalid uses of XTOPT_PUT
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (3 preceding siblings ...)
  2011-05-09 19:54 ` [PATCH 04/17] libxtables: do not overlay addr and mask parts, and cleanup Jan Engelhardt
@ 2011-05-09 19:54 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 06/17] libxtables: XTTYPE_PLEN support Jan Engelhardt
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:54 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 xtoptions.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/xtoptions.c b/xtoptions.c
index f8031bb..29d05d5 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -708,7 +708,8 @@ void xtables_option_metavalidate(const char *name,
 				name, entry->id);
 		if (!(entry->flags & XTOPT_PUT))
 			continue;
-		if (entry->type >= ARRAY_SIZE(xtopt_psize))
+		if (entry->type >= ARRAY_SIZE(xtopt_psize) ||
+		    xtopt_psize[entry->type] == 0)
 			xt_params->exit_err(OTHER_PROBLEM,
 				"%s: entry type of option \"--%s\" cannot be "
 				"combined with XTOPT_PUT\n",
-- 
1.7.1


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

* [PATCH 06/17] libxtables: XTTYPE_PLEN support
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (4 preceding siblings ...)
  2011-05-09 19:54 ` [PATCH 05/17] libxtables: flag invalid uses of XTOPT_PUT Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 07/17] libxt_hashlimit: use guided option parser Jan Engelhardt
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 include/xtables.h.in |    2 ++
 xtoptions.c          |   41 +++++++++++++++++++++++++++--------------
 2 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/include/xtables.h.in b/include/xtables.h.in
index c9ad523..9bb4235 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -65,6 +65,7 @@ struct in_addr;
  * %XTTYPE_PORT_NE:	16-bit port name or number, stored as network-endian
  * %XTTYPE_PORTRC:	colon-separated port range (names acceptable)
  * %XTTYPE_PORTRC_NE:	same as %XTTYPE_PORTRC, stored in network-endian
+ * %XTTYPE_PLEN:	prefix length
  * %XTTYPE_PLENMASK:	prefix length (ptr: union nf_inet_addr)
  */
 enum xt_option_type {
@@ -87,6 +88,7 @@ enum xt_option_type {
 	XTTYPE_PORT_NE,
 	XTTYPE_PORTRC,
 	XTTYPE_PORTRC_NE,
+	XTTYPE_PLEN,
 	XTTYPE_PLENMASK,
 };
 
diff --git a/xtoptions.c b/xtoptions.c
index 29d05d5..3cc2e0c 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -569,14 +569,12 @@ static void xtopt_parse_mport(struct xt_option_call *cb)
 
 /**
  * Parse an integer and ensure it is within the address family's prefix length
- * limits. The result is stored in @cb->val.hmask and @cb->val.hlen. If
- * %XTOPT_PUT is used, hmask will be copied to the pointed-to area.
+ * limits. The result is stored in @cb->val.hlen.
  */
-static void xtopt_parse_plenmask(struct xt_option_call *cb)
+static void xtopt_parse_plen(struct xt_option_call *cb)
 {
 	const struct xt_option_entry *entry = cb->entry;
-	uint32_t *mask = cb->val.hmask.all;
-	unsigned int prefix_len = 128;
+	unsigned int prefix_len = 128; /* happiness is a warm gcc */
 
 	cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
 	if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen))
@@ -586,21 +584,35 @@ static void xtopt_parse_plenmask(struct xt_option_call *cb)
 			cb->ext_name, entry->name, 0, cb->val.hlen);
 
 	cb->val.hlen = prefix_len;
+}
+
+/**
+ * Reuse xtopt_parse_plen for testing the integer. Afterwards convert this to
+ * a bitmask, and make it available through @cb->val.hmask (hlen remains
+ * valid). If %XTOPT_PUT is used, hmask will be copied to the target area.
+ */
+static void xtopt_parse_plenmask(struct xt_option_call *cb)
+{
+	const struct xt_option_entry *entry = cb->entry;
+	uint32_t *mask = cb->val.hmask.all;
+
+	xtopt_parse_plen(cb);
+
 	memset(mask, 0xFF, sizeof(union nf_inet_addr));
 	/* This shifting is AF-independent. */
-	if (prefix_len == 0) {
+	if (cb->val.hlen == 0) {
 		mask[0] = mask[1] = mask[2] = mask[3] = 0;
-	} else if (prefix_len <= 32) {
-		mask[0] <<= 32 - prefix_len;
+	} else if (cb->val.hlen <= 32) {
+		mask[0] <<= 32 - cb->val.hlen;
 		mask[1] = mask[2] = mask[3] = 0;
-	} else if (prefix_len <= 64) {
-		mask[1] <<= 32 - (prefix_len - 32);
+	} else if (cb->val.hlen <= 64) {
+		mask[1] <<= 32 - (cb->val.hlen - 32);
 		mask[2] = mask[3] = 0;
-	} else if (prefix_len <= 96) {
-		mask[2] <<= 32 - (prefix_len - 64);
+	} else if (cb->val.hlen <= 96) {
+		mask[2] <<= 32 - (cb->val.hlen - 64);
 		mask[3] = 0;
-	} else if (prefix_len <= 128) {
-		mask[3] <<= 32 - (prefix_len - 96);
+	} else if (cb->val.hlen <= 128) {
+		mask[3] <<= 32 - (cb->val.hlen - 96);
 	}
 	mask[0] = htonl(mask[0]);
 	mask[1] = htonl(mask[1]);
@@ -629,6 +641,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
 	[XTTYPE_PORT_NE]     = xtopt_parse_port,
 	[XTTYPE_PORTRC]      = xtopt_parse_mport,
 	[XTTYPE_PORTRC_NE]   = xtopt_parse_mport,
+	[XTTYPE_PLEN]        = xtopt_parse_plen,
 	[XTTYPE_PLENMASK]    = xtopt_parse_plenmask,
 };
 
-- 
1.7.1


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

* [PATCH 07/17] libxt_hashlimit: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (5 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 06/17] libxtables: XTTYPE_PLEN support Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 08/17] libxtables: XTTYPE_HOSTMASK support Jan Engelhardt
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_hashlimit.c |  419 +++++++++++++-----------------------------
 1 files changed, 129 insertions(+), 290 deletions(-)

diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c
index cd057c5..e683f9a 100644
--- a/extensions/libxt_hashlimit.c
+++ b/extensions/libxt_hashlimit.c
@@ -15,9 +15,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <getopt.h>
 #include <xtables.h>
-#include <stddef.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_hashlimit.h>
 
@@ -45,6 +43,23 @@ static void hashlimit_help(void)
 XT_HASHLIMIT_BURST);
 }
 
+enum {
+	O_UPTO = 0,
+	O_ABOVE,
+	O_LIMIT,
+	O_MODE,
+	O_SRCMASK,
+	O_DSTMASK,
+	O_NAME,
+	O_BURST,
+	O_HTABLE_SIZE,
+	O_HTABLE_MAX,
+	O_HTABLE_GCINT,
+	O_HTABLE_EXPIRE,
+	F_UPTO  = 1 << O_UPTO,
+	F_ABOVE = 1 << O_ABOVE,
+};
+
 static void hashlimit_mt_help(void)
 {
 	printf(
@@ -66,33 +81,64 @@ static void hashlimit_mt_help(void)
 "\n", XT_HASHLIMIT_BURST);
 }
 
-static const struct option hashlimit_opts[] = {
-	{.name = "hashlimit",                   .has_arg = true, .val = '%'},
-	{.name = "hashlimit-burst",             .has_arg = true, .val = '$'},
-	{.name = "hashlimit-htable-size",       .has_arg = true, .val = '&'},
-	{.name = "hashlimit-htable-max",        .has_arg = true, .val = '*'},
-	{.name = "hashlimit-htable-gcinterval", .has_arg = true, .val = '('},
-	{.name = "hashlimit-htable-expire",     .has_arg = true, .val = ')'},
-	{.name = "hashlimit-mode",              .has_arg = true, .val = '_'},
-	{.name = "hashlimit-name",              .has_arg = true, .val = '"'},
-	XT_GETOPT_TABLEEND,
+#define s struct xt_hashlimit_info
+static const struct xt_option_entry hashlimit_opts[] = {
+	{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
+	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
+	{.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
+	 .min = 1, .max = 10000, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.burst)},
+	{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.size)},
+	{.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.max)},
+	{.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.gc_interval)},
+	{.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.expire)},
+	{.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING,
+	 .flags = XTOPT_MAND},
+	{.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
+	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
+	XTOPT_TABLEEND,
 };
-
-static const struct option hashlimit_mt_opts[] = {
-	{.name = "hashlimit-upto",              .has_arg = true, .val = '%'},
-	{.name = "hashlimit-above",             .has_arg = true, .val = '^'},
-	{.name = "hashlimit",                   .has_arg = true, .val = '%'},
-	{.name = "hashlimit-srcmask",           .has_arg = true, .val = '<'},
-	{.name = "hashlimit-dstmask",           .has_arg = true, .val = '>'},
-	{.name = "hashlimit-burst",             .has_arg = true, .val = '$'},
-	{.name = "hashlimit-htable-size",       .has_arg = true, .val = '&'},
-	{.name = "hashlimit-htable-max",        .has_arg = true, .val = '*'},
-	{.name = "hashlimit-htable-gcinterval", .has_arg = true, .val = '('},
-	{.name = "hashlimit-htable-expire",     .has_arg = true, .val = ')'},
-	{.name = "hashlimit-mode",              .has_arg = true, .val = '_'},
-	{.name = "hashlimit-name",              .has_arg = true, .val = '"'},
-	XT_GETOPT_TABLEEND,
+#undef s
+
+#define s struct xt_hashlimit_mtinfo1
+static const struct xt_option_entry hashlimit_mt_opts[] = {
+	{.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
+	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
+	{.name = "hashlimit-above", .id = O_ABOVE, .excl = F_UPTO,
+	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
+	{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
+	 .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */
+	{.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN},
+	{.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN},
+	{.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
+	 .min = 1, .max = 10000, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.burst)},
+	{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.size)},
+	{.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.max)},
+	{.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.gc_interval)},
+	{.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
+	 .type = XTTYPE_UINT32, .flags = XTOPT_PUT,
+	 XTOPT_POINTER(s, cfg.expire)},
+	{.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING},
+	{.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
+	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
+	XTOPT_TABLEEND,
 };
+#undef s
 
 static
 int parse_rate(const char *rate, uint32_t *val)
@@ -165,7 +211,7 @@ static void hashlimit_mt6_init(struct xt_entry_match *match)
 }
 
 /* Parse a 'mode' parameter into the required bitmask */
-static int parse_mode(uint32_t *mode, char *option_arg)
+static int parse_mode(uint32_t *mode, const char *option_arg)
 {
 	char *tok;
 	char *arg = strdup(option_arg);
@@ -193,280 +239,73 @@ static int parse_mode(uint32_t *mode, char *option_arg)
 	return 0;
 }
 
-enum {
-	PARAM_LIMIT      = 1 << 0,
-	PARAM_BURST      = 1 << 1,
-	PARAM_MODE       = 1 << 2,
-	PARAM_NAME       = 1 << 3,
-	PARAM_SIZE       = 1 << 4,
-	PARAM_MAX        = 1 << 5,
-	PARAM_GCINTERVAL = 1 << 6,
-	PARAM_EXPIRE     = 1 << 7,
-	PARAM_SRCMASK    = 1 << 8,
-	PARAM_DSTMASK    = 1 << 9,
-};
-
-static int
-hashlimit_parse(int c, char **argv, int invert, unsigned int *flags,
-                const void *entry, struct xt_entry_match **match)
+static void hashlimit_parse(struct xt_option_call *cb)
 {
-	struct xt_hashlimit_info *r = 
-			(struct xt_hashlimit_info *)(*match)->data;
-	unsigned int num;
-
-	switch(c) {
-	case '%':
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit",
-		          *flags & PARAM_LIMIT);
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (!parse_rate(optarg, &r->cfg.avg))
-			xtables_error(PARAMETER_PROBLEM,
-				   "bad rate `%s'", optarg);
-		*flags |= PARAM_LIMIT;
-		break;
+	struct xt_hashlimit_info *info = cb->data;
 
-	case '$':
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-burst",
-		          *flags & PARAM_BURST);
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (!xtables_strtoui(optarg, NULL, &num, 0, 10000))
-			xtables_error(PARAMETER_PROBLEM,
-				   "bad --hashlimit-burst `%s'", optarg);
-		r->cfg.burst = num;
-		*flags |= PARAM_BURST;
-		break;
-	case '&':
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size",
-		          *flags & PARAM_SIZE);
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_error(PARAMETER_PROBLEM,
-				"bad --hashlimit-htable-size: `%s'", optarg);
-		r->cfg.size = num;
-		*flags |= PARAM_SIZE;
-		break;
-	case '*':
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max",
-		          *flags & PARAM_MAX);
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_error(PARAMETER_PROBLEM,
-				"bad --hashlimit-htable-max: `%s'", optarg);
-		r->cfg.max = num;
-		*flags |= PARAM_MAX;
-		break;
-	case '(':
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
-		          "--hashlimit-htable-gcinterval",
-		          *flags & PARAM_GCINTERVAL);
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_error(PARAMETER_PROBLEM,
-				"bad --hashlimit-htable-gcinterval: `%s'", 
-				optarg);
-		/* FIXME: not HZ dependent!! */
-		r->cfg.gc_interval = num;
-		*flags |= PARAM_GCINTERVAL;
-		break;
-	case ')':
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
-		          "--hashlimit-htable-expire", *flags & PARAM_EXPIRE);
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_error(PARAMETER_PROBLEM,
-				"bad --hashlimit-htable-expire: `%s'", optarg);
-		/* FIXME: not HZ dependent */
-		r->cfg.expire = num;
-		*flags |= PARAM_EXPIRE;
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_UPTO:
+		if (cb->invert)
+			info->cfg.mode |= XT_HASHLIMIT_INVERT;
+		if (!parse_rate(cb->arg, &info->cfg.avg))
+			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+			          "--hashlimit-upto", cb->arg);
 		break;
-	case '_':
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-mode",
-		          *flags & PARAM_MODE);
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (parse_mode(&r->cfg.mode, optarg) < 0)
-			xtables_error(PARAMETER_PROBLEM,
-				   "bad --hashlimit-mode: `%s'\n", optarg);
-		*flags |= PARAM_MODE;
+	case O_ABOVE:
+		if (!cb->invert)
+			info->cfg.mode |= XT_HASHLIMIT_INVERT;
+		if (!parse_rate(cb->arg, &info->cfg.avg))
+			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+			          "--hashlimit-above", cb->arg);
 		break;
-	case '"':
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-name",
-		          *flags & PARAM_NAME);
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (strlen(optarg) == 0)
-			xtables_error(PARAMETER_PROBLEM, "Zero-length name?");
-		strncpy(r->name, optarg, sizeof(r->name));
-		*flags |= PARAM_NAME;
+	case O_MODE:
+		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
+			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+			          "--hashlimit-mode", cb->arg);
 		break;
 	}
-
-	if (invert)
-		xtables_error(PARAMETER_PROBLEM,
-			   "hashlimit does not support invert");
-
-	return 1;
 }
 
-static int
-hashlimit_mt_parse(struct xt_hashlimit_mtinfo1 *info, unsigned int *flags,
-                   int c, int invert, unsigned int maxmask)
+static void hashlimit_mt_parse(struct xt_option_call *cb)
 {
-	unsigned int num;
+	struct xt_hashlimit_mtinfo1 *info = cb->data;
 
-	switch(c) {
-	case '%': /* --hashlimit / --hashlimit-below */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-upto",
-		          *flags & PARAM_LIMIT);
-		if (invert)
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_UPTO:
+		if (cb->invert)
 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
-		if (!parse_rate(optarg, &info->cfg.avg))
+		if (!parse_rate(cb->arg, &info->cfg.avg))
 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-upto", optarg);
-		*flags |= PARAM_LIMIT;
-		return true;
-
-	case '^': /* --hashlimit-above == !--hashlimit-below */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-above",
-		          *flags & PARAM_LIMIT);
-		if (!invert)
+			          "--hashlimit-upto", cb->arg);
+		break;
+	case O_ABOVE:
+		if (!cb->invert)
 			info->cfg.mode |= XT_HASHLIMIT_INVERT;
-		if (!parse_rate(optarg, &info->cfg.avg))
-			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-above", optarg);
-		*flags |= PARAM_LIMIT;
-		return true;
-
-	case '$': /* --hashlimit-burst */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-burst",
-		          *flags & PARAM_BURST);
-		if (!xtables_strtoui(optarg, NULL, &num, 0, 10000))
+		if (!parse_rate(cb->arg, &info->cfg.avg))
 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-burst", optarg);
-		info->cfg.burst = num;
-		*flags |= PARAM_BURST;
-		return true;
-
-	case '&': /* --hashlimit-htable-size */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size",
-		          *flags & PARAM_SIZE);
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-htable-size", optarg);
-		info->cfg.size = num;
-		*flags |= PARAM_SIZE;
-		return true;
-
-	case '*': /* --hashlimit-htable-max */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max",
-		          *flags & PARAM_MAX);
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-htable-max", optarg);
-		info->cfg.max = num;
-		*flags |= PARAM_MAX;
-		return true;
-
-	case '(': /* --hashlimit-htable-gcinterval */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
-		          "--hashlimit-htable-gcinterval",
-		          *flags & PARAM_GCINTERVAL);
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-htable-gcinterval", optarg);
-		/* FIXME: not HZ dependent!! */
-		info->cfg.gc_interval = num;
-		*flags |= PARAM_GCINTERVAL;
-		return true;
-
-	case ')': /* --hashlimit-htable-expire */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
-		          "--hashlimit-htable-expire", *flags & PARAM_EXPIRE);
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-htable-expire", optarg);
-		/* FIXME: not HZ dependent */
-		info->cfg.expire = num;
-		*flags |= PARAM_EXPIRE;
-		return true;
-
-	case '_':
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-mode",
-		          *flags & PARAM_MODE);
-		if (parse_mode(&info->cfg.mode, optarg) < 0)
-			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-mode", optarg);
-		*flags |= PARAM_MODE;
-		return true;
-
-	case '"': /* --hashlimit-name */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-name",
-		          *flags & PARAM_NAME);
-		if (strlen(optarg) == 0)
-			xtables_error(PARAMETER_PROBLEM, "Zero-length name?");
-		strncpy(info->name, optarg, sizeof(info->name));
-		info->name[sizeof(info->name)-1] = '\0';
-		*flags |= PARAM_NAME;
-		return true;
-
-	case '<': /* --hashlimit-srcmask */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-srcmask",
-		          *flags & PARAM_SRCMASK);
-		if (!xtables_strtoui(optarg, NULL, &num, 0, maxmask))
-			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-srcmask", optarg);
-		info->cfg.srcmask = num;
-		*flags |= PARAM_SRCMASK;
-		return true;
-
-	case '>': /* --hashlimit-dstmask */
-		xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-dstmask",
-		          *flags & PARAM_DSTMASK);
-		if (!xtables_strtoui(optarg, NULL, &num, 0, maxmask))
+			          "--hashlimit-above", cb->arg);
+		break;
+	case O_MODE:
+		if (parse_mode(&info->cfg.mode, cb->arg) < 0)
 			xtables_param_act(XTF_BAD_VALUE, "hashlimit",
-			          "--hashlimit-dstmask", optarg);
-		info->cfg.dstmask = num;
-		*flags |= PARAM_DSTMASK;
-		return true;
+			          "--hashlimit-mode", cb->arg);
+		break;
+	case O_SRCMASK:
+		info->cfg.srcmask = cb->val.hlen;
+		break;
+	case O_DSTMASK:
+		info->cfg.dstmask = cb->val.hlen;
+		break;
 	}
-	return false;
-}
-
-static int
-hashlimit_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
-                    const void *entry, struct xt_entry_match **match)
-{
-	return hashlimit_mt_parse((void *)(*match)->data,
-	       flags, c, invert, 32);
-}
-
-static int
-hashlimit_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
-                    const void *entry, struct xt_entry_match **match)
-{
-	return hashlimit_mt_parse((void *)(*match)->data,
-	       flags, c, invert, 128);
 }
 
-static void hashlimit_check(unsigned int flags)
+static void hashlimit_check(struct xt_fcheck_call *cb)
 {
-	if (!(flags & PARAM_LIMIT))
+	if (!(cb->xflags & (F_UPTO | F_ABOVE)))
 		xtables_error(PARAMETER_PROBLEM,
 				"You have to specify --hashlimit");
-	if (!(flags & PARAM_MODE))
-		xtables_error(PARAMETER_PROBLEM,
-				"You have to specify --hashlimit-mode");
-	if (!(flags & PARAM_NAME))
-		xtables_error(PARAMETER_PROBLEM,
-				"You have to specify --hashlimit-name");
-}
-
-static void hashlimit_mt_check(unsigned int flags)
-{
-	if (!(flags & PARAM_LIMIT))
-		xtables_error(PARAMETER_PROBLEM, "You have to specify "
-		           "--hashlimit-upto or --hashlimit-above");
-	if (!(flags & PARAM_NAME))
-		xtables_error(PARAMETER_PROBLEM,
-		           "You have to specify --hashlimit-name");
 }
 
 static const struct rates
@@ -664,11 +503,11 @@ static struct xtables_match hashlimit_mt_reg[] = {
 		.userspacesize = offsetof(struct xt_hashlimit_info, hinfo),
 		.help          = hashlimit_help,
 		.init          = hashlimit_init,
-		.parse         = hashlimit_parse,
-		.final_check   = hashlimit_check,
+		.x6_parse      = hashlimit_parse,
+		.x6_fcheck     = hashlimit_check,
 		.print         = hashlimit_print,
 		.save          = hashlimit_save,
-		.extra_opts    = hashlimit_opts,
+		.x6_options    = hashlimit_mt_opts,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -679,11 +518,11 @@ static struct xtables_match hashlimit_mt_reg[] = {
 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
 		.help          = hashlimit_mt_help,
 		.init          = hashlimit_mt4_init,
-		.parse         = hashlimit_mt4_parse,
-		.final_check   = hashlimit_mt_check,
+		.x6_parse      = hashlimit_mt_parse,
+		.x6_fcheck     = hashlimit_check,
 		.print         = hashlimit_mt4_print,
 		.save          = hashlimit_mt4_save,
-		.extra_opts    = hashlimit_mt_opts,
+		.x6_options    = hashlimit_mt_opts,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -694,11 +533,11 @@ static struct xtables_match hashlimit_mt_reg[] = {
 		.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
 		.help          = hashlimit_mt_help,
 		.init          = hashlimit_mt6_init,
-		.parse         = hashlimit_mt6_parse,
-		.final_check   = hashlimit_mt_check,
+		.x6_parse      = hashlimit_mt_parse,
+		.x6_fcheck     = hashlimit_check,
 		.print         = hashlimit_mt6_print,
 		.save          = hashlimit_mt6_save,
-		.extra_opts    = hashlimit_mt_opts,
+		.x6_options    = hashlimit_mt_opts,
 	},
 };
 
-- 
1.7.1


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

* [PATCH 08/17] libxtables: XTTYPE_HOSTMASK support
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (6 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 07/17] libxt_hashlimit: use guided option parser Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 09/17] libxt_policy: use guided option parser Jan Engelhardt
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 include/xtables.h.in |    3 +++
 xtoptions.c          |   29 +++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/include/xtables.h.in b/include/xtables.h.in
index 9bb4235..caaec2f 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -61,6 +61,8 @@ struct in_addr;
  * %XTTYPE_MARKMASK32:	32-bit mark with optional mask
  * %XTTYPE_SYSLOGLEVEL:	syslog level by name or number
  * %XTTYPE_HOST:	one host or address (ptr: union nf_inet_addr)
+ * %XTTYPE_HOSTMASK:	one host or address, with an optional prefix length
+ * 			(ptr: union nf_inet_addr; only host portion is stored)
  * %XTTYPE_PORT:	16-bit port name or number
  * %XTTYPE_PORT_NE:	16-bit port name or number, stored as network-endian
  * %XTTYPE_PORTRC:	colon-separated port range (names acceptable)
@@ -84,6 +86,7 @@ enum xt_option_type {
 	XTTYPE_MARKMASK32,
 	XTTYPE_SYSLOGLEVEL,
 	XTTYPE_HOST,
+	XTTYPE_HOSTMASK,
 	XTTYPE_PORT,
 	XTTYPE_PORT_NE,
 	XTTYPE_PORTRC,
diff --git a/xtoptions.c b/xtoptions.c
index 3cc2e0c..36f90e4 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -622,6 +622,33 @@ static void xtopt_parse_plenmask(struct xt_option_call *cb)
 		memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr));
 }
 
+static void xtopt_parse_hostmask(struct xt_option_call *cb)
+{
+	const char *orig_arg = cb->arg;
+	char *work, *p;
+
+	if (strchr(cb->arg, '/') == NULL) {
+		xtopt_parse_host(cb);
+		return;
+	}
+	work = strdup(orig_arg);
+	if (work == NULL)
+		xt_params->exit_err(PARAMETER_PROBLEM, "strdup");
+	p = strchr(work, '/'); /* by def this can't be NULL now */
+	*p++ = '\0';
+	/*
+	 * Because xtopt_parse_host and xtopt_parse_plenmask would store
+	 * different things in the same target area, XTTYPE_HOSTMASK must
+	 * disallow XTOPT_PUT, which it does by forcing its absence,
+	 * cf. not being listed in xtopt_psize.
+	 */
+	cb->arg = work;
+	xtopt_parse_host(cb);
+	cb->arg = p;
+	xtopt_parse_plenmask(cb);
+	cb->arg = orig_arg;
+}
+
 static void (*const xtopt_subparse[])(struct xt_option_call *) = {
 	[XTTYPE_UINT8]       = xtopt_parse_int,
 	[XTTYPE_UINT16]      = xtopt_parse_int,
@@ -637,6 +664,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
 	[XTTYPE_MARKMASK32]  = xtopt_parse_markmask,
 	[XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel,
 	[XTTYPE_HOST]        = xtopt_parse_host,
+	[XTTYPE_HOSTMASK]    = xtopt_parse_hostmask,
 	[XTTYPE_PORT]        = xtopt_parse_port,
 	[XTTYPE_PORT_NE]     = xtopt_parse_port,
 	[XTTYPE_PORTRC]      = xtopt_parse_mport,
@@ -662,6 +690,7 @@ static const size_t xtopt_psize[] = {
 	[XTTYPE_STRING]      = -1,
 	[XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
 	[XTTYPE_HOST]        = sizeof(union nf_inet_addr),
+	[XTTYPE_HOSTMASK]    = sizeof(union nf_inet_addr),
 	[XTTYPE_PORT]        = sizeof(uint16_t),
 	[XTTYPE_PORT_NE]     = sizeof(uint16_t),
 	[XTTYPE_PORTRC]      = sizeof(uint16_t[2]),
-- 
1.7.1


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

* [PATCH 09/17] libxt_policy: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (7 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 08/17] libxtables: XTTYPE_HOSTMASK support Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 10/17] libxt_owner: " Jan Engelhardt
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_policy.c |  269 ++++++++++++---------------------------------
 1 files changed, 73 insertions(+), 196 deletions(-)

diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c
index 16e8c53..a514246 100644
--- a/extensions/libxt_policy.c
+++ b/extensions/libxt_policy.c
@@ -1,25 +1,23 @@
-/* Shared library add-on to iptables to add policy support. */
 #include <stdbool.h>
+#include <stdint.h>
 #include <stdio.h>
-#include <netdb.h>
 #include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
 #include <netdb.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 #include <xtables.h>
-
 #include <linux/netfilter/xt_policy.h>
 
-/*
- * HACK: global pointer to current matchinfo for making
- * final checks and adjustments in final_check.
- */
-static struct xt_policy_info *policy_info;
+enum {
+	O_DIRECTION = 0,
+	O_POLICY,
+	O_STRICT,
+	O_REQID,
+	O_SPI,
+	O_PROTO,
+	O_MODE,
+	O_TUNNELSRC,
+	O_TUNNELDST,
+	O_NEXT
+};
 
 static void policy_help(void)
 {
@@ -39,62 +37,22 @@ static void policy_help(void)
 "  --next 			begin next element in policy\n");
 }
 
-static const struct option policy_opts[] =
-{
-	{
-		.name		= "dir",
-		.has_arg	= true,
-		.val		= '1',
-	},
-	{
-		.name		= "pol",
-		.has_arg	= true,
-		.val		= '2',
-	},
-	{
-		.name		= "strict",
-		.has_arg	= false,
-		.val		= '3'
-	},
-	{
-		.name		= "reqid",
-		.has_arg	= true,
-		.val		= '4',
-	},
-	{
-		.name		= "spi",
-		.has_arg	= true,
-		.val		= '5'
-	},
-	{
-		.name		= "tunnel-src",
-		.has_arg	= true,
-		.val		= '6'
-	},
-	{
-		.name		= "tunnel-dst",
-		.has_arg	= true,
-		.val		= '7'
-	},
-	{
-		.name		= "proto",
-		.has_arg	= true,
-		.val		= '8'
-	},
-	{
-		.name		= "mode",
-		.has_arg	= true,
-		.val		= '9'
-	},
-	{
-		.name		= "next",
-		.has_arg	= false,
-		.val		= 'a'
-	},
-	XT_GETOPT_TABLEEND,
+static const struct xt_option_entry policy_opts[] = {
+	{.name = "dir", .id = O_DIRECTION, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "pol", .id = O_POLICY, .type = XTTYPE_STRING},
+	{.name = "strict", .id = O_STRICT, .type = XTTYPE_NONE},
+	{.name = "reqid", .id = O_REQID, .type = XTTYPE_UINT32},
+	{.name = "spi", .id = O_SPI, .type = XTTYPE_UINT32},
+	{.name = "tunnel-src", .id = O_TUNNELSRC, .type = XTTYPE_HOSTMASK},
+	{.name = "tunnel-dst", .id = O_TUNNELDST, .type = XTTYPE_HOSTMASK},
+	{.name = "proto", .id = O_PROTO, .type = XTTYPE_STRING},
+	{.name = "mode", .id = O_MODE, .type = XTTYPE_STRING},
+	{.name = "next", .id = O_NEXT, .type = XTTYPE_NONE},
+	XTOPT_TABLEEND,
 };
 
-static int parse_direction(char *s)
+static int parse_direction(const char *s)
 {
 	if (strcmp(s, "in") == 0)
 		return XT_POLICY_MATCH_IN;
@@ -103,7 +61,7 @@ static int parse_direction(char *s)
 	xtables_error(PARAMETER_PROBLEM, "policy_match: invalid dir \"%s\"", s);
 }
 
-static int parse_policy(char *s)
+static int parse_policy(const char *s)
 {
 	if (strcmp(s, "none") == 0)
 		return XT_POLICY_MATCH_NONE;
@@ -112,7 +70,7 @@ static int parse_policy(char *s)
 	xtables_error(PARAMETER_PROBLEM, "policy match: invalid policy \"%s\"", s);
 }
 
-static int parse_mode(char *s)
+static int parse_mode(const char *s)
 {
 	if (strcmp(s, "transport") == 0)
 		return XT_POLICY_MODE_TRANSPORT;
@@ -121,176 +79,95 @@ static int parse_mode(char *s)
 	xtables_error(PARAMETER_PROBLEM, "policy match: invalid mode \"%s\"", s);
 }
 
-static int policy_parse(int c, char **argv, int invert, unsigned int *flags,
-                        struct xt_policy_info *info, uint8_t family)
+static void policy_parse(struct xt_option_call *cb)
 {
+	struct xt_policy_info *info = cb->data;
 	struct xt_policy_elem *e = &info->pol[info->len];
-	struct in_addr *addr = NULL, mask;
-	struct in6_addr *addr6 = NULL, mask6;
-	unsigned int naddr = 0, num;
-	int mode;
-
-	xtables_check_inverse(optarg, &invert, &optind, 0, argv);
 
-	switch (c) {
-	case '1':
-		if (info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT))
-			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: double --dir option");
-		if (invert)
-			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: can't invert --dir option");
-
-		info->flags |= parse_direction(optarg);
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_DIRECTION:
+		info->flags |= parse_direction(cb->arg);
 		break;
-	case '2':
-		if (invert)
-			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: can't invert --policy option");
-
-		info->flags |= parse_policy(optarg);
+	case O_POLICY:
+		info->flags |= parse_policy(cb->arg);
 		break;
-	case '3':
-		if (info->flags & XT_POLICY_MATCH_STRICT)
-			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: double --strict option");
-
-		if (invert)
-			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: can't invert --strict option");
-
+	case O_STRICT:
 		info->flags |= XT_POLICY_MATCH_STRICT;
 		break;
-	case '4':
+	case O_REQID:
 		if (e->match.reqid)
 			xtables_error(PARAMETER_PROBLEM,
 			           "policy match: double --reqid option");
-
 		e->match.reqid = 1;
-		e->invert.reqid = invert;
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg);
-		e->reqid = num;
+		e->invert.reqid = cb->invert;
+		e->reqid = cb->val.u32;
 		break;
-	case '5':
+	case O_SPI:
 		if (e->match.spi)
 			xtables_error(PARAMETER_PROBLEM,
 			           "policy match: double --spi option");
-
 		e->match.spi = 1;
-		e->invert.spi = invert;
-		if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg);
-		e->spi = num;
+		e->invert.spi = cb->invert;
+		e->spi = cb->val.u32;
 		break;
-	case '6':
+	case O_TUNNELSRC:
 		if (e->match.saddr)
 			xtables_error(PARAMETER_PROBLEM,
 			           "policy match: double --tunnel-src option");
 
-		if (family == NFPROTO_IPV6)
-			xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr);
-		else
-			xtables_ipparse_any(optarg, &addr, &mask, &naddr);
-		if (naddr > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: name resolves to multiple IPs");
-
 		e->match.saddr = 1;
-		e->invert.saddr = invert;
-		if (family == NFPROTO_IPV6) {
-			memcpy(&e->saddr.a6, addr6, sizeof(*addr6));
-			memcpy(&e->smask.a6, &mask6, sizeof(mask6));
-		} else {
-			e->saddr.a4 = addr[0];
-			e->smask.a4 = mask;
-		}
+		e->invert.saddr = cb->invert;
+		memcpy(&e->saddr, &cb->val.haddr, sizeof(cb->val.haddr));
+		memcpy(&e->smask, &cb->val.hmask, sizeof(cb->val.hmask));
                 break;
-	case '7':
+	case O_TUNNELDST:
 		if (e->match.daddr)
 			xtables_error(PARAMETER_PROBLEM,
 			           "policy match: double --tunnel-dst option");
-
-		if (family == NFPROTO_IPV6)
-			xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr);
-		else
-			xtables_ipparse_any(optarg, &addr, &mask, &naddr);
-		if (naddr > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: name resolves to multiple IPs");
-
 		e->match.daddr = 1;
-		e->invert.daddr = invert;
-		if (family == NFPROTO_IPV6) {
-			memcpy(&e->daddr.a6, addr6, sizeof(*addr6));
-			memcpy(&e->dmask.a6, &mask6, sizeof(mask6));
-		} else {
-			e->daddr.a4 = addr[0];
-			e->dmask.a4 = mask;
-		}
+		e->invert.daddr = cb->invert;
+		memcpy(&e->daddr, &cb->val.haddr, sizeof(cb->val.haddr));
+		memcpy(&e->dmask, &cb->val.hmask, sizeof(cb->val.hmask));
 		break;
-	case '8':
+	case O_PROTO:
 		if (e->match.proto)
 			xtables_error(PARAMETER_PROBLEM,
 			           "policy match: double --proto option");
-
-		e->proto = xtables_parse_protocol(optarg);
+		e->proto = xtables_parse_protocol(cb->arg);
 		if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
 		    e->proto != IPPROTO_COMP)
 			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: protocol must ah/esp/ipcomp");
+			           "policy match: protocol must be ah/esp/ipcomp");
 		e->match.proto = 1;
-		e->invert.proto = invert;
+		e->invert.proto = cb->invert;
 		break;
-	case '9':
+	case O_MODE:
 		if (e->match.mode)
 			xtables_error(PARAMETER_PROBLEM,
 			           "policy match: double --mode option");
-
-		mode = parse_mode(optarg);
 		e->match.mode = 1;
-		e->invert.mode = invert;
-		e->mode = mode;
+		e->invert.mode = cb->invert;
+		e->mode = parse_mode(cb->arg);
 		break;
-	case 'a':
-		if (invert)
-			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: can't invert --next option");
-
+	case O_NEXT:
 		if (++info->len == XT_POLICY_MAX_ELEM)
 			xtables_error(PARAMETER_PROBLEM,
 			           "policy match: maximum policy depth reached");
 		break;
 	}
-
-	policy_info = info;
-	return 1;
-}
-
-static int policy4_parse(int c, char **argv, int invert, unsigned int *flags,
-                         const void *entry, struct xt_entry_match **match)
-{
-	return policy_parse(c, argv, invert, flags, (void *)(*match)->data,
-	       NFPROTO_IPV4);
 }
 
-static int policy6_parse(int c, char **argv, int invert, unsigned int *flags,
-                        const void *entry, struct xt_entry_match **match)
+static void policy_check(struct xt_fcheck_call *cb)
 {
-	return policy_parse(c, argv, invert, flags, (void *)(*match)->data,
-	       NFPROTO_IPV6);
-}
-
-static void policy_check(unsigned int flags)
-{
-	struct xt_policy_info *info = policy_info;
-	struct xt_policy_elem *e;
+	struct xt_policy_info *info = cb->data;
+	const struct xt_policy_elem *e;
 	int i;
 
-	if (info == NULL)
-		xtables_error(PARAMETER_PROBLEM,
-		           "policy match: no parameters given");
-
+	/*
+	 * The old "no parameters given" check is carried out
+	 * by testing for --dir.
+	 */
 	if (!(info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT)))
 		xtables_error(PARAMETER_PROBLEM,
 		           "policy match: neither --dir in nor --dir out specified");
@@ -487,11 +364,11 @@ static struct xtables_match policy_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_policy_info)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)),
 		.help          = policy_help,
-		.parse         = policy4_parse,
-		.final_check   = policy_check,
+		.x6_parse      = policy_parse,
+		.x6_fcheck     = policy_check,
 		.print         = policy4_print,
 		.save          = policy4_save,
-		.extra_opts    = policy_opts,
+		.x6_options    = policy_opts,
 	},
 	{
 		.name          = "policy",
@@ -500,11 +377,11 @@ static struct xtables_match policy_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_policy_info)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)),
 		.help          = policy_help,
-		.parse         = policy6_parse,
-		.final_check   = policy_check,
+		.x6_parse      = policy_parse,
+		.x6_fcheck     = policy_check,
 		.print         = policy6_print,
 		.save          = policy6_save,
-		.extra_opts    = policy_opts,
+		.x6_options    = policy_opts,
 	},
 };
 
-- 
1.7.1


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

* [PATCH 10/17] libxt_owner: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (8 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 09/17] libxt_policy: use guided option parser Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 11/17] libxt_osf: " Jan Engelhardt
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_owner.c |  288 +++++++++++++++++++---------------------------
 1 files changed, 117 insertions(+), 171 deletions(-)

diff --git a/extensions/libxt_owner.c b/extensions/libxt_owner.c
index f930cf4..b60f907 100644
--- a/extensions/libxt_owner.c
+++ b/extensions/libxt_owner.c
@@ -4,16 +4,11 @@
  *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
  *	Jan Engelhardt <jengelh@computergmbh.de>
  */
-#include <getopt.h>
 #include <grp.h>
-#include <netdb.h>
 #include <pwd.h>
 #include <stdbool.h>
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <limits.h>
-
 #include <xtables.h>
 #include <linux/netfilter/xt_owner.h>
 
@@ -55,12 +50,12 @@ struct ip6t_owner_info {
  */
 
 enum {
-	FLAG_UID_OWNER     = 1 << 0,
-	FLAG_GID_OWNER     = 1 << 1,
-	FLAG_SOCKET_EXISTS = 1 << 2,
-	FLAG_PID_OWNER     = 1 << 3,
-	FLAG_SID_OWNER     = 1 << 4,
-	FLAG_COMM          = 1 << 5,
+	O_USER = 0,
+	O_GROUP,
+	O_SOCK_EXISTS,
+	O_PROCESS,
+	O_SESSION,
+	O_COMM,
 };
 
 static void owner_mt_help_v0(void)
@@ -95,170 +90,134 @@ static void owner_mt_help(void)
 "[!] --socket-exists                  Match if socket exists\n");
 }
 
-static const struct option owner_mt_opts_v0[] = {
-	{.name = "uid-owner", .has_arg = true, .val = 'u'},
-	{.name = "gid-owner", .has_arg = true, .val = 'g'},
-	{.name = "pid-owner", .has_arg = true, .val = 'p'},
-	{.name = "sid-owner", .has_arg = true, .val = 's'},
-	{.name = "cmd-owner", .has_arg = true, .val = 'c'},
-	XT_GETOPT_TABLEEND,
+#define s struct ipt_owner_info
+static const struct xt_option_entry owner_mt_opts_v0[] = {
+	{.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "pid-owner", .id = O_PROCESS, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, pid),
+	 .max = INT_MAX},
+	{.name = "sid-owner", .id = O_SESSION, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, sid),
+	 .max = INT_MAX},
+	{.name = "cmd-owner", .id = O_COMM, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, comm)},
+	XTOPT_TABLEEND,
 };
-
-static const struct option owner_mt6_opts_v0[] = {
-	{.name = "uid-owner", .has_arg = true, .val = 'u'},
-	{.name = "gid-owner", .has_arg = true, .val = 'g'},
-	{.name = "pid-owner", .has_arg = true, .val = 'p'},
-	{.name = "sid-owner", .has_arg = true, .val = 's'},
-	XT_GETOPT_TABLEEND,
+#undef s
+
+#define s struct ip6t_owner_info
+static const struct xt_option_entry owner_mt6_opts_v0[] = {
+	{.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "pid-owner", .id = O_PROCESS, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, pid),
+	 .max = INT_MAX},
+	{.name = "sid-owner", .id = O_SESSION, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, sid),
+	 .max = INT_MAX},
+	XTOPT_TABLEEND,
 };
+#undef s
 
-static const struct option owner_mt_opts[] = {
-	{.name = "uid-owner",     .has_arg = true,  .val = 'u'},
-	{.name = "gid-owner",     .has_arg = true,  .val = 'g'},
-	{.name = "socket-exists", .has_arg = false, .val = 'k'},
-	XT_GETOPT_TABLEEND,
+static const struct xt_option_entry owner_mt_opts[] = {
+	{.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING},
+	{.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING},
+	{.name = "socket-exists", .id = O_SOCK_EXISTS, .type = XTTYPE_NONE},
+	XTOPT_TABLEEND,
 };
 
-static int
-owner_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags,
-                  const void *entry, struct xt_entry_match **match)
+static void owner_mt_parse_v0(struct xt_option_call *cb)
 {
-	struct ipt_owner_info *info = (void *)(*match)->data;
+	struct ipt_owner_info *info = cb->data;
 	struct passwd *pwd;
 	struct group *grp;
 	unsigned int id;
 
-	switch (c) {
-	case 'u':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner", *flags & FLAG_UID_OWNER);
-		if ((pwd = getpwnam(optarg)) != NULL)
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_USER:
+		if ((pwd = getpwnam(cb->arg)) != NULL)
 			id = pwd->pw_uid;
-		else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
-			xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", optarg);
-		if (invert)
+		else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
+			xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", cb->arg);
+		if (cb->invert)
 			info->invert |= IPT_OWNER_UID;
 		info->match |= IPT_OWNER_UID;
 		info->uid    = id;
-		*flags      |= FLAG_UID_OWNER;
-		return true;
-
-	case 'g':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner", *flags & FLAG_GID_OWNER);
-		if ((grp = getgrnam(optarg)) != NULL)
+		break;
+	case O_GROUP:
+		if ((grp = getgrnam(cb->arg)) != NULL)
 			id = grp->gr_gid;
-		else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
-			xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", optarg);
-		if (invert)
+		else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
+			xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", cb->arg);
+		if (cb->invert)
 			info->invert |= IPT_OWNER_GID;
 		info->match |= IPT_OWNER_GID;
 		info->gid    = id;
-		*flags      |= FLAG_GID_OWNER;
-		return true;
-
-	case 'p':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--pid-owner", *flags & FLAG_PID_OWNER);
-		if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "owner", "--pid-owner", optarg);
-		if (invert)
+		break;
+	case O_PROCESS:
+		if (cb->invert)
 			info->invert |= IPT_OWNER_PID;
 		info->match |= IPT_OWNER_PID;
-		info->pid    = id;
-		*flags      |= FLAG_PID_OWNER;
-		return true;
-
-	case 's':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--sid-owner", *flags & FLAG_SID_OWNER);
-		if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "owner", "--sid-value", optarg);
-		if (invert)
+		break;
+	case O_SESSION:
+		if (cb->invert)
 			info->invert |= IPT_OWNER_SID;
 		info->match |= IPT_OWNER_SID;
-		info->sid    = id;
-		*flags      |= FLAG_SID_OWNER;
-		return true;
-
-	case 'c':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--cmd-owner", *flags & FLAG_COMM);
-		if (strlen(optarg) > sizeof(info->comm))
-			xtables_error(PARAMETER_PROBLEM, "owner match: command "
-			           "\"%s\" too long, max. %zu characters",
-			           optarg, sizeof(info->comm));
-
-		info->comm[sizeof(info->comm)-1] = '\0';
-		strncpy(info->comm, optarg, sizeof(info->comm));
-
-		if (invert)
+		break;
+	case O_COMM:
+		if (cb->invert)
 			info->invert |= IPT_OWNER_COMM;
 		info->match |= IPT_OWNER_COMM;
-		*flags      |= FLAG_COMM;
-		return true;
+		break;
 	}
-	return false;
 }
 
-static int
-owner_mt6_parse_v0(int c, char **argv, int invert, unsigned int *flags,
-                   const void *entry, struct xt_entry_match **match)
+static void owner_mt6_parse_v0(struct xt_option_call *cb)
 {
-	struct ip6t_owner_info *info = (void *)(*match)->data;
+	struct ip6t_owner_info *info = cb->data;
 	struct passwd *pwd;
 	struct group *grp;
 	unsigned int id;
 
-	switch (c) {
-	case 'u':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner",
-		          *flags & FLAG_UID_OWNER);
-		if ((pwd = getpwnam(optarg)) != NULL)
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_USER:
+		if ((pwd = getpwnam(cb->arg)) != NULL)
 			id = pwd->pw_uid;
-		else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
-			xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", optarg);
-		if (invert)
+		else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
+			xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", cb->arg);
+		if (cb->invert)
 			info->invert |= IP6T_OWNER_UID;
 		info->match |= IP6T_OWNER_UID;
 		info->uid    = id;
-		*flags      |= FLAG_UID_OWNER;
-		return true;
-
-	case 'g':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner",
-		          *flags & FLAG_GID_OWNER);
-		if ((grp = getgrnam(optarg)) != NULL)
+		break;
+	case O_GROUP:
+		if ((grp = getgrnam(cb->arg)) != NULL)
 			id = grp->gr_gid;
-		else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
-			xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", optarg);
-		if (invert)
+		else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
+			xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", cb->arg);
+		if (cb->invert)
 			info->invert |= IP6T_OWNER_GID;
 		info->match |= IP6T_OWNER_GID;
 		info->gid    = id;
-		*flags      |= FLAG_GID_OWNER;
-		return true;
-
-	case 'p':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--pid-owner",
-		          *flags & FLAG_PID_OWNER);
-		if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "owner", "--pid-owner", optarg);
-		if (invert)
+		break;
+	case O_PROCESS:
+		if (cb->invert)
 			info->invert |= IP6T_OWNER_PID;
 		info->match |= IP6T_OWNER_PID;
-		info->pid    = id;
-		*flags      |= FLAG_PID_OWNER;
-		return true;
-
-	case 's':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--sid-owner",
-		          *flags & FLAG_SID_OWNER);
-		if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "owner", "--sid-owner", optarg);
-		if (invert)
+		break;
+	case O_SESSION:
+		if (cb->invert)
 			info->invert |= IP6T_OWNER_SID;
 		info->match |= IP6T_OWNER_SID;
-		info->sid    = id;
-		*flags      |= FLAG_SID_OWNER;
-		return true;
+		break;
 	}
-	return false;
 }
 
 static void owner_parse_range(const char *s, unsigned int *from,
@@ -277,61 +236,48 @@ static void owner_parse_range(const char *s, unsigned int *from,
 		xtables_param_act(XTF_BAD_VALUE, "owner", opt, s);
 }
 
-static int owner_mt_parse(int c, char **argv, int invert, unsigned int *flags,
-                          const void *entry, struct xt_entry_match **match)
+static void owner_mt_parse(struct xt_option_call *cb)
 {
-	struct xt_owner_match_info *info = (void *)(*match)->data;
+	struct xt_owner_match_info *info = cb->data;
 	struct passwd *pwd;
 	struct group *grp;
 	unsigned int from, to;
 
-	switch (c) {
-	case 'u':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner",
-		          *flags & FLAG_UID_OWNER);
-		if ((pwd = getpwnam(optarg)) != NULL)
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_USER:
+		if ((pwd = getpwnam(cb->arg)) != NULL)
 			from = to = pwd->pw_uid;
 		else
-			owner_parse_range(optarg, &from, &to, "--uid-owner");
-		if (invert)
+			owner_parse_range(cb->arg, &from, &to, "--uid-owner");
+		if (cb->invert)
 			info->invert |= XT_OWNER_UID;
 		info->match  |= XT_OWNER_UID;
 		info->uid_min = from;
 		info->uid_max = to;
-		*flags       |= FLAG_UID_OWNER;
-		return true;
-
-	case 'g':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner",
-		          *flags & FLAG_GID_OWNER);
-		if ((grp = getgrnam(optarg)) != NULL)
+		break;
+	case O_GROUP:
+		if ((grp = getgrnam(cb->arg)) != NULL)
 			from = to = grp->gr_gid;
 		else
-			owner_parse_range(optarg, &from, &to, "--gid-owner");
-		if (invert)
+			owner_parse_range(cb->arg, &from, &to, "--gid-owner");
+		if (cb->invert)
 			info->invert |= XT_OWNER_GID;
 		info->match  |= XT_OWNER_GID;
 		info->gid_min = from;
 		info->gid_max = to;
-		*flags      |= FLAG_GID_OWNER;
-		return true;
-
-	case 'k':
-		xtables_param_act(XTF_ONLY_ONCE, "owner", "--socket-exists",
-		          *flags & FLAG_SOCKET_EXISTS);
-		if (invert)
+		break;
+	case O_SOCK_EXISTS:
+		if (cb->invert)
 			info->invert |= XT_OWNER_SOCKET;
 		info->match |= XT_OWNER_SOCKET;
-		*flags |= FLAG_SOCKET_EXISTS;
-		return true;
-
+		break;
 	}
-	return false;
 }
 
-static void owner_mt_check(unsigned int flags)
+static void owner_mt_check(struct xt_fcheck_call *cb)
 {
-	if (flags == 0)
+	if (cb->xflags == 0)
 		xtables_error(PARAMETER_PROBLEM, "owner: At least one of "
 		           "--uid-owner, --gid-owner or --socket-exists "
 		           "is required");
@@ -552,11 +498,11 @@ static struct xtables_match owner_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct ipt_owner_info)),
 		.userspacesize = XT_ALIGN(sizeof(struct ipt_owner_info)),
 		.help          = owner_mt_help_v0,
-		.parse         = owner_mt_parse_v0,
-		.final_check   = owner_mt_check,
+		.x6_parse      = owner_mt_parse_v0,
+		.x6_fcheck     = owner_mt_check,
 		.print         = owner_mt_print_v0,
 		.save          = owner_mt_save_v0,
-		.extra_opts    = owner_mt_opts_v0,
+		.x6_options    = owner_mt_opts_v0,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -566,11 +512,11 @@ static struct xtables_match owner_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct ip6t_owner_info)),
 		.userspacesize = XT_ALIGN(sizeof(struct ip6t_owner_info)),
 		.help          = owner_mt6_help_v0,
-		.parse         = owner_mt6_parse_v0,
-		.final_check   = owner_mt_check,
+		.x6_parse      = owner_mt6_parse_v0,
+		.x6_fcheck     = owner_mt_check,
 		.print         = owner_mt6_print_v0,
 		.save          = owner_mt6_save_v0,
-		.extra_opts    = owner_mt6_opts_v0,
+		.x6_options    = owner_mt6_opts_v0,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -580,11 +526,11 @@ static struct xtables_match owner_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_owner_match_info)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_owner_match_info)),
 		.help          = owner_mt_help,
-		.parse         = owner_mt_parse,
-		.final_check   = owner_mt_check,
+		.x6_parse      = owner_mt_parse,
+		.x6_fcheck     = owner_mt_check,
 		.print         = owner_mt_print,
 		.save          = owner_mt_save,
-		.extra_opts    = owner_mt_opts,
+		.x6_options    = owner_mt_opts,
 	},
 };
 
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 11/17] libxt_osf: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (9 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 10/17] libxt_owner: " Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 12/17] libxt_multiport: " Jan Engelhardt
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_osf.c |   97 ++++++++++++++---------------------------------
 1 files changed, 29 insertions(+), 68 deletions(-)

diff --git a/extensions/libxt_osf.c b/extensions/libxt_osf.c
index 20acfea..88274a0 100644
--- a/extensions/libxt_osf.c
+++ b/extensions/libxt_osf.c
@@ -20,23 +20,19 @@
 /*
  * xtables interface for OS fingerprint matching module.
  */
-#include <stdbool.h>
 #include <stdio.h>
-#include <netdb.h>
 #include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-
-#include <linux/types.h>
-
 #include <xtables.h>
-
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
-
 #include <linux/netfilter/xt_osf.h>
 
+enum {
+	O_GENRE = 0,
+	O_TTL,
+	O_LOGLEVEL,
+};
+
 static void osf_help(void)
 {
 	printf("OS fingerprint match options:\n"
@@ -52,71 +48,37 @@ static void osf_help(void)
 		);
 }
 
-
-static const struct option osf_opts[] = {
-	{.name = "genre", .has_arg = true, .val = '1'},
-	{.name = "ttl",   .has_arg = true, .val = '2'},
-	{.name = "log",   .has_arg = true, .val = '3'},
-	XT_GETOPT_TABLEEND,
+#define s struct xt_osf_info
+static const struct xt_option_entry osf_opts[] = {
+	{.name = "genre", .id = O_GENRE, .type = XTTYPE_STRING,
+	 .flags = XTOPT_MAND | XTOPT_INVERT | XTOPT_PUT,
+	 XTOPT_POINTER(s, genre)},
+	{.name = "ttl", .id = O_TTL, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_PUT, XTOPT_POINTER(s, ttl), .min = 0, .max = 2},
+	{.name = "log", .id = O_LOGLEVEL, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_PUT, XTOPT_POINTER(s, loglevel), .min = 0, .max = 2},
+	XTOPT_TABLEEND,
 };
+#undef s
 
-
-static void osf_parse_string(const char *s, struct xt_osf_info *info)
+static void osf_parse(struct xt_option_call *cb)
 {
-	if (strlen(s) < MAXGENRELEN)
-		strcpy(info->genre, s);
-	else
-		xtables_error(PARAMETER_PROBLEM,
-			      "Genre string too long `%s' [%zd], max=%d",
-			      s, strlen(s), MAXGENRELEN);
-}
-
-static int osf_parse(int c, char **argv, int invert, unsigned int *flags,
-      			const void *entry,
-      			struct xt_entry_match **match)
-{
-	struct xt_osf_info *info = (struct xt_osf_info *)(*match)->data;
+	struct xt_osf_info *info = cb->data;
 
-	switch(c) {
-		case '1': /* --genre */
-			if (*flags & XT_OSF_GENRE)
-				xtables_error(PARAMETER_PROBLEM,
-					      "Can't specify multiple genre parameter");
-			xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-			osf_parse_string(argv[optind-1], info);
-			if (invert)
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+		case O_GENRE:
+			if (cb->invert)
 				info->flags |= XT_OSF_INVERT;
-			info->len=strlen(info->genre);
-			*flags |= XT_OSF_GENRE;
+			info->len = strlen(info->genre);
 			break;
-		case '2': /* --ttl */
-			if (*flags & XT_OSF_TTL)
-				xtables_error(PARAMETER_PROBLEM,
-					      "Can't specify multiple ttl parameter");
-			*flags |= XT_OSF_TTL;
+		case O_TTL:
 			info->flags |= XT_OSF_TTL;
-			if (!xtables_strtoui(argv[optind-1], NULL, &info->ttl, 0, 2))
-				xtables_error(PARAMETER_PROBLEM, "TTL parameter is too big");
 			break;
-		case '3': /* --log */
-			if (*flags & XT_OSF_LOG)
-				xtables_error(PARAMETER_PROBLEM,
-					      "Can't specify multiple log parameter");
-			*flags |= XT_OSF_LOG;
-			if (!xtables_strtoui(argv[optind-1], NULL, &info->loglevel, 0, 2))
-				xtables_error(PARAMETER_PROBLEM, "Log level parameter is too big");
+		case O_LOGLEVEL:
 			info->flags |= XT_OSF_LOG;
 			break;
 	}
-
-	return 1;
-}
-
-static void osf_final_check(unsigned int flags)
-{
-	if (!(flags & XT_OSF_GENRE))
-		xtables_error(PARAMETER_PROBLEM,
-			      "OS fingerprint match: You must specify `--genre'");
 }
 
 static void osf_print(const void *ip, const struct xt_entry_match *match, int numeric)
@@ -139,12 +101,11 @@ static struct xtables_match osf_match = {
 	.size		= XT_ALIGN(sizeof(struct xt_osf_info)),
 	.userspacesize	= XT_ALIGN(sizeof(struct xt_osf_info)),
 	.help		= osf_help,
-	.parse		= osf_parse,
+	.x6_parse	= osf_parse,
 	.print		= osf_print,
-	.final_check	= osf_final_check,
 	.save		= osf_save,
-	.extra_opts	= osf_opts,
-	.family		= NFPROTO_IPV4
+	.x6_options	= osf_opts,
+	.family		= NFPROTO_IPV4,
 };
 
 void _init(void)
-- 
1.7.1


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

* [PATCH 12/17] libxt_multiport: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (10 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 11/17] libxt_osf: " Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 13/17] libipt_NETMAP: " Jan Engelhardt
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_multiport.c |  178 +++++++++++++++++-------------------------
 include/xtables.h.in         |    2 +
 xtoptions.c                  |    2 +
 3 files changed, 77 insertions(+), 105 deletions(-)

diff --git a/extensions/libxt_multiport.c b/extensions/libxt_multiport.c
index 7fa537e..03af5a9 100644
--- a/extensions/libxt_multiport.c
+++ b/extensions/libxt_multiport.c
@@ -1,19 +1,23 @@
-/* Shared library add-on to iptables to add multiple TCP port support. */
-#include <stdbool.h>
 #include <stdio.h>
 #include <netdb.h>
 #include <string.h>
 #include <stdlib.h>
-#include <getopt.h>
-
 #include <xtables.h>
-#include <libiptc/libiptc.h>
-#include <libiptc/libip6tc.h>
 #include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter/xt_multiport.h>
 
+enum {
+	O_SOURCE_PORTS = 0,
+	O_DEST_PORTS,
+	O_SD_PORTS,
+	F_SOURCE_PORTS = 1 << O_SOURCE_PORTS,
+	F_DEST_PORTS   = 1 << O_DEST_PORTS,
+	F_SD_PORTS     = 1 << O_SD_PORTS,
+	F_ANY          = F_SOURCE_PORTS | F_DEST_PORTS | F_SD_PORTS,
+};
+
 /* Function which prints out usage message. */
 static void multiport_help(void)
 {
@@ -44,13 +48,18 @@ static void multiport_help_v1(void)
 "				match both source and destination port(s)\n");
 }
 
-static const struct option multiport_opts[] = {
-	{.name = "source-ports",      .has_arg = true, .val = '1'},
-	{.name = "sports",            .has_arg = true, .val = '1'}, /* synonym */
-	{.name = "destination-ports", .has_arg = true, .val = '2'},
-	{.name = "dports",            .has_arg = true, .val = '2'}, /* synonym */
-	{.name = "ports",             .has_arg = true, .val = '3'},
-	XT_GETOPT_TABLEEND,
+static const struct xt_option_entry multiport_opts[] = {
+	{.name = "source-ports", .id = O_SOURCE_PORTS, .type = XTTYPE_STRING,
+	 .excl = F_ANY, .flags = XTOPT_INVERT},
+	{.name = "sports", .id = O_SOURCE_PORTS, .type = XTTYPE_STRING,
+	 .excl = F_ANY, .flags = XTOPT_INVERT},
+	{.name = "destination-ports", .id = O_DEST_PORTS,
+	 .type = XTTYPE_STRING, .excl = F_ANY, .flags = XTOPT_INVERT},
+	{.name = "dports", .id = O_DEST_PORTS, .type = XTTYPE_STRING,
+	 .excl = F_ANY, .flags = XTOPT_INVERT},
+	{.name = "ports", .id = O_SD_PORTS, .type = XTTYPE_STRING,
+	 .excl = F_ANY, .flags = XTOPT_INVERT},
+	XTOPT_TABLEEND,
 };
 
 static const char *
@@ -152,136 +161,97 @@ check_proto(uint16_t pnum, uint8_t invflags)
 			   "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
 }
 
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-__multiport_parse(int c, char **argv, int invert, unsigned int *flags,
-                  struct xt_entry_match **match, uint16_t pnum,
-                  uint8_t invflags)
+static void __multiport_parse(struct xt_option_call *cb, uint16_t pnum,
+			      uint8_t invflags)
 {
 	const char *proto;
-	struct xt_multiport *multiinfo
-		= (struct xt_multiport *)(*match)->data;
+	struct xt_multiport *multiinfo = cb->data;
 
-	switch (c) {
-	case '1':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_SOURCE_PORTS:
 		proto = check_proto(pnum, invflags);
-		multiinfo->count = parse_multi_ports(optarg,
+		multiinfo->count = parse_multi_ports(cb->arg,
 						     multiinfo->ports, proto);
 		multiinfo->flags = XT_MULTIPORT_SOURCE;
 		break;
-
-	case '2':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+	case O_DEST_PORTS:
 		proto = check_proto(pnum, invflags);
-		multiinfo->count = parse_multi_ports(optarg,
+		multiinfo->count = parse_multi_ports(cb->arg,
 						     multiinfo->ports, proto);
 		multiinfo->flags = XT_MULTIPORT_DESTINATION;
 		break;
-
-	case '3':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+	case O_SD_PORTS:
 		proto = check_proto(pnum, invflags);
-		multiinfo->count = parse_multi_ports(optarg,
+		multiinfo->count = parse_multi_ports(cb->arg,
 						     multiinfo->ports, proto);
 		multiinfo->flags = XT_MULTIPORT_EITHER;
 		break;
 	}
-
-	if (invert)
+	if (cb->invert)
 		xtables_error(PARAMETER_PROBLEM,
-			   "multiport does not support invert");
-
-	if (*flags)
-		xtables_error(PARAMETER_PROBLEM,
-			   "multiport can only have one option");
-	*flags = 1;
-	return 1;
+			   "multiport.0 does not support invert");
 }
 
-static int
-multiport_parse(int c, char **argv, int invert, unsigned int *flags,
-                const void *e, struct xt_entry_match **match)
+static void multiport_parse(struct xt_option_call *cb)
 {
-	const struct ipt_entry *entry = e;
-	return __multiport_parse(c, argv, invert, flags, match,
+	const struct ipt_entry *entry = cb->xt_entry;
+	return __multiport_parse(cb,
 	       entry->ip.proto, entry->ip.invflags);
 }
 
-static int
-multiport_parse6(int c, char **argv, int invert, unsigned int *flags,
-                 const void *e, struct xt_entry_match **match)
+static void multiport_parse6(struct xt_option_call *cb)
 {
-	const struct ip6t_entry *entry = e;
-	return __multiport_parse(c, argv, invert, flags, match,
+	const struct ip6t_entry *entry = cb->xt_entry;
+	return __multiport_parse(cb,
 	       entry->ipv6.proto, entry->ipv6.invflags);
 }
 
-static int
-__multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
-                     struct xt_entry_match **match, uint16_t pnum,
-                     uint8_t invflags)
+static void __multiport_parse_v1(struct xt_option_call *cb, uint16_t pnum,
+				 uint8_t invflags)
 {
 	const char *proto;
-	struct xt_multiport_v1 *multiinfo
-		= (struct xt_multiport_v1 *)(*match)->data;
+	struct xt_multiport_v1 *multiinfo = cb->data;
 
-	switch (c) {
-	case '1':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_SOURCE_PORTS:
 		proto = check_proto(pnum, invflags);
-		parse_multi_ports_v1(optarg, multiinfo, proto);
+		parse_multi_ports_v1(cb->arg, multiinfo, proto);
 		multiinfo->flags = XT_MULTIPORT_SOURCE;
 		break;
-
-	case '2':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+	case O_DEST_PORTS:
 		proto = check_proto(pnum, invflags);
-		parse_multi_ports_v1(optarg, multiinfo, proto);
+		parse_multi_ports_v1(cb->arg, multiinfo, proto);
 		multiinfo->flags = XT_MULTIPORT_DESTINATION;
 		break;
-
-	case '3':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+	case O_SD_PORTS:
 		proto = check_proto(pnum, invflags);
-		parse_multi_ports_v1(optarg, multiinfo, proto);
+		parse_multi_ports_v1(cb->arg, multiinfo, proto);
 		multiinfo->flags = XT_MULTIPORT_EITHER;
 		break;
 	}
-
-	if (invert)
+	if (cb->invert)
 		multiinfo->invert = 1;
-
-	if (*flags)
-		xtables_error(PARAMETER_PROBLEM,
-			   "multiport can only have one option");
-	*flags = 1;
-	return 1;
 }
 
-static int
-multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
-                   const void *e, struct xt_entry_match **match)
+static void multiport_parse_v1(struct xt_option_call *cb)
 {
-	const struct ipt_entry *entry = e;
-	return __multiport_parse_v1(c, argv, invert, flags, match,
+	const struct ipt_entry *entry = cb->xt_entry;
+	return __multiport_parse_v1(cb,
 	       entry->ip.proto, entry->ip.invflags);
 }
 
-static int
-multiport_parse6_v1(int c, char **argv, int invert, unsigned int *flags,
-                    const void *e, struct xt_entry_match **match)
+static void multiport_parse6_v1(struct xt_option_call *cb)
 {
-	const struct ip6t_entry *entry = e;
-	return __multiport_parse_v1(c, argv, invert, flags, match,
+	const struct ip6t_entry *entry = cb->xt_entry;
+	return __multiport_parse_v1(cb,
 	       entry->ipv6.proto, entry->ipv6.invflags);
 }
 
-/* Final check; must specify something. */
-static void multiport_check(unsigned int flags)
+static void multiport_check(struct xt_fcheck_call *cb)
 {
-	if (!flags)
+	if (cb->xflags == 0)
 		xtables_error(PARAMETER_PROBLEM, "multiport expection an option");
 }
 
@@ -307,7 +277,6 @@ print_port(uint16_t port, uint8_t protocol, int numeric)
 		printf("%s", service);
 }
 
-/* Prints out the matchinfo. */
 static void
 __multiport_print(const struct xt_entry_match *match, int numeric,
                   uint16_t proto)
@@ -410,7 +379,6 @@ static void multiport_print6_v1(const void *ip_void,
 	__multiport_print_v1(match, numeric, ip->proto);
 }
 
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
 static void __multiport_save(const struct xt_entry_match *match,
                              uint16_t proto)
 {
@@ -509,11 +477,11 @@ static struct xtables_match multiport_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_multiport)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
 		.help          = multiport_help,
-		.parse         = multiport_parse,
-		.final_check   = multiport_check,
+		.x6_parse      = multiport_parse,
+		.x6_fcheck     = multiport_check,
 		.print         = multiport_print,
 		.save          = multiport_save,
-		.extra_opts    = multiport_opts,
+		.x6_options    = multiport_opts,
 	},
 	{
 		.family        = NFPROTO_IPV6,
@@ -523,11 +491,11 @@ static struct xtables_match multiport_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_multiport)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
 		.help          = multiport_help,
-		.parse         = multiport_parse6,
-		.final_check   = multiport_check,
+		.x6_parse      = multiport_parse6,
+		.x6_fcheck     = multiport_check,
 		.print         = multiport_print6,
 		.save          = multiport_save6,
-		.extra_opts    = multiport_opts,
+		.x6_options    = multiport_opts,
 	},
 	{
 		.family        = NFPROTO_IPV4,
@@ -537,11 +505,11 @@ static struct xtables_match multiport_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_multiport_v1)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
 		.help          = multiport_help_v1,
-		.parse         = multiport_parse_v1,
-		.final_check   = multiport_check,
+		.x6_parse      = multiport_parse_v1,
+		.x6_fcheck     = multiport_check,
 		.print         = multiport_print_v1,
 		.save          = multiport_save_v1,
-		.extra_opts    = multiport_opts,
+		.x6_options    = multiport_opts,
 	},
 	{
 		.family        = NFPROTO_IPV6,
@@ -551,11 +519,11 @@ static struct xtables_match multiport_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_multiport_v1)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
 		.help          = multiport_help_v1,
-		.parse         = multiport_parse6_v1,
-		.final_check   = multiport_check,
+		.x6_parse      = multiport_parse6_v1,
+		.x6_fcheck     = multiport_check,
 		.print         = multiport_print6_v1,
 		.save          = multiport_save6_v1,
-		.extra_opts    = multiport_opts,
+		.x6_options    = multiport_opts,
 	},
 };
 
diff --git a/include/xtables.h.in b/include/xtables.h.in
index caaec2f..50aa414 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -163,10 +163,12 @@ struct xt_option_call {
 			uint32_t mark, mask;
 		};
 	} val;
+	/* Wished for a world where the ones below were gone: */
 	union {
 		struct xt_entry_match **match;
 		struct xt_entry_target **target;
 	};
+	void *xt_entry;
 };
 
 /**
diff --git a/xtoptions.c b/xtoptions.c
index 36f90e4..413de1b 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -808,6 +808,7 @@ void xtables_option_tpcall(unsigned int c, char **argv, bool invert,
 	cb.data     = t->t->data;
 	cb.xflags   = t->tflags;
 	cb.target   = &t->t;
+	cb.xt_entry = fw;
 	t->x6_parse(&cb);
 	t->tflags = cb.xflags;
 }
@@ -842,6 +843,7 @@ void xtables_option_mpcall(unsigned int c, char **argv, bool invert,
 	cb.data     = m->m->data;
 	cb.xflags   = m->mflags;
 	cb.match    = &m->m;
+	cb.xt_entry = fw;
 	m->x6_parse(&cb);
 	m->mflags = cb.xflags;
 }
-- 
1.7.1


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

* [PATCH 13/17] libipt_NETMAP: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (11 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 12/17] libxt_multiport: " Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 14/17] libxt_limit: " Jan Engelhardt
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libipt_NETMAP.c |  106 +++++++-------------------------------------
 1 files changed, 16 insertions(+), 90 deletions(-)

diff --git a/extensions/libipt_NETMAP.c b/extensions/libipt_NETMAP.c
index 0e85dec..5c4471a 100644
--- a/extensions/libipt_NETMAP.c
+++ b/extensions/libipt_NETMAP.c
@@ -1,7 +1,6 @@
 /* Shared library add-on to iptables to add static NAT support.
    Author: Svenning Soerensen <svenning@post5.tele.dk>
 */
-#include <stdbool.h>
 #include <stdio.h>
 #include <netdb.h>
 #include <string.h>
@@ -12,9 +11,14 @@
 
 #define MODULENAME "NETMAP"
 
-static const struct option NETMAP_opts[] = {
-	{.name = "to", .has_arg = true, .val = '1'},
-	XT_GETOPT_TABLEEND,
+enum {
+	O_TO = 0,
+};
+
+static const struct xt_option_entry NETMAP_opts[] = {
+	{.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK,
+	 .flags = XTOPT_MAND},
+	XTOPT_TABLEEND,
 };
 
 static void NETMAP_help(void)
@@ -25,18 +29,6 @@ static void NETMAP_help(void)
 	       NETMAP_opts[0].name);
 }
 
-static uint32_t
-bits2netmask(int bits)
-{
-	uint32_t netmask, bm;
-
-	if (bits >= 32 || bits < 0)
-		return(~0);
-	for (netmask = 0, bm = 0x80000000; bits; bits--, bm >>= 1)
-		netmask |= bm;
-	return htonl(netmask);
-}
-
 static int
 netmask2bits(uint32_t netmask)
 {
@@ -57,82 +49,17 @@ static void NETMAP_init(struct xt_entry_target *t)
 
 	/* Actually, it's 0, but it's ignored at the moment. */
 	mr->rangesize = 1;
-
 }
 
-/* Parses network address */
-static void
-parse_to(char *arg, struct nf_nat_range *range)
+static void NETMAP_parse(struct xt_option_call *cb)
 {
-	char *slash;
-	const struct in_addr *ip;
-	uint32_t netmask;
-	unsigned int bits;
+	struct nf_nat_multi_range *mr = cb->data;
+	struct nf_nat_range *range = &mr->range[0];
 
+	xtables_option_parse(cb);
 	range->flags |= IP_NAT_RANGE_MAP_IPS;
-	slash = strchr(arg, '/');
-	if (slash)
-		*slash = '\0';
-
-	ip = xtables_numeric_to_ipaddr(arg);
-	if (!ip)
-		xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
-			   arg);
-	range->min_ip = ip->s_addr;
-	if (slash) {
-		if (strchr(slash+1, '.')) {
-			ip = xtables_numeric_to_ipmask(slash+1);
-			if (!ip)
-				xtables_error(PARAMETER_PROBLEM, "Bad netmask \"%s\"\n",
-					   slash+1);
-			netmask = ip->s_addr;
-		}
-		else {
-			if (!xtables_strtoui(slash+1, NULL, &bits, 0, 32))
-				xtables_error(PARAMETER_PROBLEM, "Bad netmask \"%s\"\n",
-					   slash+1);
-			netmask = bits2netmask(bits);
-		}
-		/* Don't allow /0 (/1 is probably insane, too) */
-		if (netmask == 0)
-			xtables_error(PARAMETER_PROBLEM, "Netmask needed\n");
-	}
-	else
-		netmask = ~0;
-
-	if (range->min_ip & ~netmask) {
-		if (slash)
-			*slash = '/';
-		xtables_error(PARAMETER_PROBLEM, "Bad network address \"%s\"\n",
-			   arg);
-	}
-	range->max_ip = range->min_ip | ~netmask;
-}
-
-static int NETMAP_parse(int c, char **argv, int invert, unsigned int *flags,
-                        const void *entry, struct xt_entry_target **target)
-{
-	struct nf_nat_multi_range *mr
-		= (struct nf_nat_multi_range *)(*target)->data;
-
-	switch (c) {
-	case '1':
-		if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
-			xtables_error(PARAMETER_PROBLEM,
-				   "Unexpected `!' after --%s", NETMAP_opts[0].name);
-
-		parse_to(optarg, &mr->range[0]);
-		*flags = 1;
-		return 1;
-	}
-	return 0;
-}
-
-static void NETMAP_check(unsigned int flags)
-{
-	if (!flags)
-		xtables_error(PARAMETER_PROBLEM,
-			   MODULENAME" needs --%s", NETMAP_opts[0].name);
+	range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip;
+	range->max_ip = range->min_ip | ~cb->val.hmask.ip;
 }
 
 static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
@@ -167,11 +94,10 @@ static struct xtables_target netmap_tg_reg = {
 	.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_multi_range)),
 	.help		= NETMAP_help,
 	.init		= NETMAP_init,
-	.parse		= NETMAP_parse,
-	.final_check	= NETMAP_check,
+	.x6_parse	= NETMAP_parse,
 	.print		= NETMAP_print,
 	.save		= NETMAP_save,
-	.extra_opts	= NETMAP_opts,
+	.x6_options	= NETMAP_opts,
 };
 
 void _init(void)
-- 
1.7.1


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

* [PATCH 14/17] libxt_limit: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (12 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 13/17] libipt_NETMAP: " Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 15/17] libxtables: XTTYPE_PROTOCOL support Jan Engelhardt
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_limit.c |   53 ++++++++++++++++++---------------------------
 1 files changed, 21 insertions(+), 32 deletions(-)

diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c
index c4ba58b..b15b02f 100644
--- a/extensions/libxt_limit.c
+++ b/extensions/libxt_limit.c
@@ -3,20 +3,21 @@
  * Jérôme de Vivie   <devivie@info.enserb.u-bordeaux.fr>
  * Hervé Eychenne    <rv@wallfire.org>
  */
-#include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <getopt.h>
 #include <xtables.h>
-#include <stddef.h>
 #include <linux/netfilter/x_tables.h>
-/* For 64bit kernel / 32bit userspace */
 #include <linux/netfilter/xt_limit.h>
 
 #define XT_LIMIT_AVG	"3/hour"
 #define XT_LIMIT_BURST	5
 
+enum {
+	O_LIMIT = 0,
+	O_BURST,
+};
+
 static void limit_help(void)
 {
 	printf(
@@ -28,10 +29,12 @@ static void limit_help(void)
 XT_LIMIT_BURST);
 }
 
-static const struct option limit_opts[] = {
-	{.name = "limit",       .has_arg = true, .val = '%'},
-	{.name = "limit-burst", .has_arg = true, .val = '$'},
-	XT_GETOPT_TABLEEND,
+static const struct xt_option_entry limit_opts[] = {
+	{.name = "limit", .id = O_LIMIT, .type = XTTYPE_STRING},
+	{.name = "limit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_rateinfo, burst),
+	 .min = 0, .max = 10000},
+	XTOPT_TABLEEND,
 };
 
 static
@@ -85,35 +88,21 @@ static void limit_init(struct xt_entry_match *m)
 			   "Sorry: burst too large for that avg rate.\n");
 */
 
-static int
-limit_parse(int c, char **argv, int invert, unsigned int *flags,
-            const void *entry, struct xt_entry_match **match)
+static void limit_parse(struct xt_option_call *cb)
 {
-	struct xt_rateinfo *r = (struct xt_rateinfo *)(*match)->data;
-	unsigned int num;
-
-	switch(c) {
-	case '%':
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (!parse_rate(optarg, &r->avg))
-			xtables_error(PARAMETER_PROBLEM,
-				   "bad rate `%s'", optarg);
-		break;
+	struct xt_rateinfo *r = cb->data;
 
-	case '$':
-		if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
-		if (!xtables_strtoui(optarg, NULL, &num, 0, 10000))
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_LIMIT:
+		if (!parse_rate(cb->arg, &r->avg))
 			xtables_error(PARAMETER_PROBLEM,
-				   "bad --limit-burst `%s'", optarg);
-		r->burst = num;
+				   "bad rate \"%s\"'", cb->arg);
 		break;
 	}
-
-	if (invert)
+	if (cb->invert)
 		xtables_error(PARAMETER_PROBLEM,
 			   "limit does not support invert");
-
-	return 1;
 }
 
 static const struct rates
@@ -162,10 +151,10 @@ static struct xtables_match limit_match = {
 	.userspacesize	= offsetof(struct xt_rateinfo, prev),
 	.help		= limit_help,
 	.init		= limit_init,
-	.parse		= limit_parse,
+	.x6_parse	= limit_parse,
 	.print		= limit_print,
 	.save		= limit_save,
-	.extra_opts	= limit_opts,
+	.x6_options	= limit_opts,
 };
 
 void _init(void)
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 15/17] libxtables: XTTYPE_PROTOCOL support
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (13 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 14/17] libxt_limit: " Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 19:55 ` [PATCH 16/17] libxt_ipvs: use guided option parser Jan Engelhardt
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 include/xtables.h.in |    4 +++-
 xtoptions.c          |   25 +++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletions(-)

diff --git a/include/xtables.h.in b/include/xtables.h.in
index 50aa414..c3996a0 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -63,6 +63,7 @@ struct in_addr;
  * %XTTYPE_HOST:	one host or address (ptr: union nf_inet_addr)
  * %XTTYPE_HOSTMASK:	one host or address, with an optional prefix length
  * 			(ptr: union nf_inet_addr; only host portion is stored)
+ * %XTTYPE_PROTOCOL:	protocol number/name from /etc/protocols (ptr: uint8_t)
  * %XTTYPE_PORT:	16-bit port name or number
  * %XTTYPE_PORT_NE:	16-bit port name or number, stored as network-endian
  * %XTTYPE_PORTRC:	colon-separated port range (names acceptable)
@@ -87,6 +88,7 @@ enum xt_option_type {
 	XTTYPE_SYSLOGLEVEL,
 	XTTYPE_HOST,
 	XTTYPE_HOSTMASK,
+	XTTYPE_PROTOCOL,
 	XTTYPE_PORT,
 	XTTYPE_PORT_NE,
 	XTTYPE_PORTRC,
@@ -147,7 +149,7 @@ struct xt_option_call {
 	bool invert;
 	uint8_t nvals;
 	union {
-		uint8_t u8, u8_range[2], syslog_level;
+		uint8_t u8, u8_range[2], syslog_level, protocol;
 		uint16_t u16, u16_range[2], port, port_range[2];
 		uint32_t u32, u32_range[2];
 		uint64_t u64, u64_range[2];
diff --git a/xtoptions.c b/xtoptions.c
index 413de1b..70370ed 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -493,6 +493,29 @@ static int xtables_getportbyname(const char *name)
 }
 
 /**
+ * Validate and parse a protocol specification (number or name) by use of
+ * /etc/protocols and put the result into @cb->val.protocol.
+ */
+static void xtopt_parse_protocol(struct xt_option_call *cb)
+{
+	const struct protoent *entry;
+	unsigned int value = -1;
+
+	if (xtables_strtoui(cb->arg, NULL, &value, 0, UINT8_MAX)) {
+		cb->val.protocol = value;
+		return;
+	}
+	entry = getprotobyname(cb->arg);
+	if (entry == NULL)
+		xt_params->exit_err(PARAMETER_PROBLEM,
+			"Protocol \"%s\" does not resolve to anything.\n",
+			cb->arg);
+	cb->val.protocol = entry->p_proto;
+	if (cb->entry->flags & XTOPT_PUT)
+		*(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol;
+}
+
+/**
  * Validate and parse a port specification and put the result into
  * @cb->val.port.
  */
@@ -665,6 +688,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
 	[XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel,
 	[XTTYPE_HOST]        = xtopt_parse_host,
 	[XTTYPE_HOSTMASK]    = xtopt_parse_hostmask,
+	[XTTYPE_PROTOCOL]    = xtopt_parse_protocol,
 	[XTTYPE_PORT]        = xtopt_parse_port,
 	[XTTYPE_PORT_NE]     = xtopt_parse_port,
 	[XTTYPE_PORTRC]      = xtopt_parse_mport,
@@ -691,6 +715,7 @@ static const size_t xtopt_psize[] = {
 	[XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
 	[XTTYPE_HOST]        = sizeof(union nf_inet_addr),
 	[XTTYPE_HOSTMASK]    = sizeof(union nf_inet_addr),
+	[XTTYPE_PROTOCOL]    = sizeof(uint8_t),
 	[XTTYPE_PORT]        = sizeof(uint16_t),
 	[XTTYPE_PORT_NE]     = sizeof(uint16_t),
 	[XTTYPE_PORTRC]      = sizeof(uint16_t[2]),
-- 
1.7.1


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

* [PATCH 16/17] libxt_ipvs: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (14 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 15/17] libxtables: XTTYPE_PROTOCOL support Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-09 23:15   ` Simon Horman
  2011-05-09 19:55 ` [PATCH 17/17] libxt_conntrack: " Jan Engelhardt
  2011-05-11 11:45 ` guided option parser, run 6 Patrick McHardy
  17 siblings, 1 reply; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_ipvs.c |  208 +++++++++++++++--------------------------------
 1 files changed, 65 insertions(+), 143 deletions(-)

diff --git a/extensions/libxt_ipvs.c b/extensions/libxt_ipvs.c
index 89303a1..88d235f 100644
--- a/extensions/libxt_ipvs.c
+++ b/extensions/libxt_ipvs.c
@@ -5,31 +5,43 @@
  *
  * Author: Hannes Eder <heder@google.com>
  */
-#include <sys/types.h>
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <getopt.h>
-#include <netdb.h>
 #include <stdbool.h>
-#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <xtables.h>
 #include <linux/ip_vs.h>
 #include <linux/netfilter/xt_ipvs.h>
 
-static const struct option ipvs_mt_opts[] = {
-	{ .name = "ipvs",     .has_arg = false, .val = '0' },
-	{ .name = "vproto",   .has_arg = true,  .val = '1' },
-	{ .name = "vaddr",    .has_arg = true,  .val = '2' },
-	{ .name = "vport",    .has_arg = true,  .val = '3' },
-	{ .name = "vdir",     .has_arg = true,  .val = '4' },
-	{ .name = "vmethod",  .has_arg = true,  .val = '5' },
-	{ .name = "vportctl", .has_arg = true,  .val = '6' },
-	XT_GETOPT_TABLEEND,
+enum {
+	/* For xt_ipvs: make sure this matches up with %XT_IPVS_*'s order */
+	O_IPVS = 0,
+	O_VPROTO,
+	O_VADDR,
+	O_VPORT,
+	O_VDIR,
+	O_VMETHOD,
+	O_VPORTCTL,
 };
 
+#define s struct xt_ipvs_mtinfo
+static const struct xt_option_entry ipvs_mt_opts[] = {
+	{.name = "ipvs", .id = O_IPVS, .type = XTTYPE_NONE,
+	 .flags = XTOPT_INVERT},
+	{.name = "vproto", .id = O_VPROTO, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, l4proto)},
+	{.name = "vaddr", .id = O_VADDR, .type = XTTYPE_HOSTMASK,
+	 .flags = XTOPT_INVERT},
+	{.name = "vport", .id = O_VPORT, .type = XTTYPE_PORT,
+	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vport)},
+	{.name = "vdir", .id = O_VDIR, .type = XTTYPE_STRING},
+	{.name = "vmethod", .id = O_VMETHOD, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "vportctl", .id = O_VPORTCTL, .type = XTTYPE_PORT,
+	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vportctl)},
+	XTOPT_TABLEEND,
+};
+#undef s
+
 static void ipvs_mt_help(void)
 {
 	printf(
@@ -49,152 +61,62 @@ static void ipvs_mt_help(void)
 		);
 }
 
-static void ipvs_mt_parse_addr_and_mask(const char *arg,
-					union nf_inet_addr *address,
-					union nf_inet_addr *mask,
-					unsigned int family)
-{
-	struct in_addr *addr = NULL;
-	struct in6_addr *addr6 = NULL;
-	unsigned int naddrs = 0;
-
-	if (family == NFPROTO_IPV4) {
-		xtables_ipparse_any(arg, &addr, &mask->in, &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-				      "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&address->in, addr, sizeof(*addr));
-	} else if (family == NFPROTO_IPV6) {
-		xtables_ip6parse_any(arg, &addr6, &mask->in6, &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-				      "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&address->in6, addr6, sizeof(*addr6));
-	} else {
-		/* Hu? */
-		assert(false);
-	}
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int ipvs_mt_parse(int c, char **argv, int invert, unsigned int *flags,
-			 const void *entry, struct xt_entry_match **match,
-			 unsigned int family)
+static void ipvs_mt_parse(struct xt_option_call *cb)
 {
-	struct xt_ipvs_mtinfo *data = (void *)(*match)->data;
-	char *p = NULL;
-	uint8_t op = 0;
-
-	if ('0' <= c && c <= '6') {
-		static const int ops[] = {
-			XT_IPVS_IPVS_PROPERTY,
-			XT_IPVS_PROTO,
-			XT_IPVS_VADDR,
-			XT_IPVS_VPORT,
-			XT_IPVS_DIR,
-			XT_IPVS_METHOD,
-			XT_IPVS_VPORTCTL
-		};
-		op = ops[c - '0'];
-	} else
-		return 0;
-
-	if (*flags & op & XT_IPVS_ONCE_MASK)
-		goto multiple_use;
-
-	switch (c) {
-	case '0': /* --ipvs */
-		/* Nothing to do here. */
-		break;
+	struct xt_ipvs_mtinfo *data = cb->data;
 
-	case '1': /* --vproto */
-		/* Canonicalize into lower case */
-		for (p = optarg; *p != '\0'; ++p)
-			*p = tolower(*p);
-
-		data->l4proto = xtables_parse_protocol(optarg);
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_VPROTO:
+		data->l4proto = cb->val.protocol;
 		break;
-
-	case '2': /* --vaddr */
-		ipvs_mt_parse_addr_and_mask(optarg, &data->vaddr,
-					    &data->vmask, family);
+	case O_VADDR:
+		memcpy(&data->vaddr, &cb->val.haddr, sizeof(cb->val.haddr));
+		memcpy(&data->vmask, &cb->val.hmask, sizeof(cb->val.hmask));
 		break;
-
-	case '3': /* --vport */
-		data->vport = htons(xtables_parse_port(optarg, "tcp"));
-		break;
-
-	case '4': /* --vdir */
-		xtables_param_act(XTF_NO_INVERT, "ipvs", "--vdir", invert);
-		if (strcasecmp(optarg, "ORIGINAL") == 0) {
+	case O_VDIR:
+		if (strcasecmp(cb->arg, "ORIGINAL") == 0) {
 			data->bitmask |= XT_IPVS_DIR;
 			data->invert   &= ~XT_IPVS_DIR;
-		} else if (strcasecmp(optarg, "REPLY") == 0) {
+		} else if (strcasecmp(cb->arg, "REPLY") == 0) {
 			data->bitmask |= XT_IPVS_DIR;
 			data->invert  |= XT_IPVS_DIR;
 		} else {
 			xtables_param_act(XTF_BAD_VALUE,
-					  "ipvs", "--vdir", optarg);
+					  "ipvs", "--vdir", cb->arg);
 		}
 		break;
-
-	case '5': /* --vmethod */
-		if (strcasecmp(optarg, "GATE") == 0)
+	case O_VMETHOD:
+		if (strcasecmp(cb->arg, "GATE") == 0)
 			data->fwd_method = IP_VS_CONN_F_DROUTE;
-		else if (strcasecmp(optarg, "IPIP") == 0)
+		else if (strcasecmp(cb->arg, "IPIP") == 0)
 			data->fwd_method = IP_VS_CONN_F_TUNNEL;
-		else if (strcasecmp(optarg, "MASQ") == 0)
+		else if (strcasecmp(cb->arg, "MASQ") == 0)
 			data->fwd_method = IP_VS_CONN_F_MASQ;
 		else
 			xtables_param_act(XTF_BAD_VALUE,
-					  "ipvs", "--vmethod", optarg);
-		break;
-
-	case '6': /* --vportctl */
-		data->vportctl = htons(xtables_parse_port(optarg, "tcp"));
+					  "ipvs", "--vmethod", cb->arg);
 		break;
 	}
-
-	if (op & XT_IPVS_ONCE_MASK) {
-		if (data->invert & XT_IPVS_IPVS_PROPERTY)
-			xtables_error(PARAMETER_PROBLEM,
-				      "! --ipvs cannot be together with"
-				      " other options");
-		data->bitmask |= XT_IPVS_IPVS_PROPERTY;
-	}
-
-	data->bitmask |= op;
-	if (invert)
-		data->invert |= op;
-	*flags |= op;
-	return 1;
-
-multiple_use:
-	xtables_error(PARAMETER_PROBLEM,
-		      "multiple use of the same IPVS option is not allowed");
+	data->bitmask |= 1 << cb->entry->id;
+	if (cb->invert)
+		data->invert |= 1 << cb->entry->id;
 }
 
-static int ipvs_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
-			  const void *entry, struct xt_entry_match **match)
+static void ipvs_mt_check(struct xt_fcheck_call *cb)
 {
-	return ipvs_mt_parse(c, argv, invert, flags, entry, match,
-			     NFPROTO_IPV4);
-}
-
-static int ipvs_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
-			  const void *entry, struct xt_entry_match **match)
-{
-	return ipvs_mt_parse(c, argv, invert, flags, entry, match,
-			     NFPROTO_IPV6);
-}
+	struct xt_ipvs_mtinfo *info = cb->data;
 
-static void ipvs_mt_check(unsigned int flags)
-{
-	if (flags == 0)
+	if (cb->xflags == 0)
 		xtables_error(PARAMETER_PROBLEM,
 			      "IPVS: At least one option is required");
+	if (info->bitmask & XT_IPVS_ONCE_MASK) {
+		if (info->invert & XT_IPVS_IPVS_PROPERTY)
+			xtables_error(PARAMETER_PROBLEM,
+				      "! --ipvs cannot be together with"
+				      " other options");
+		info->bitmask |= XT_IPVS_IPVS_PROPERTY;
+	}
 }
 
 /* Shamelessly copied from libxt_conntrack.c */
@@ -332,11 +254,11 @@ static struct xtables_match ipvs_matches_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),
 		.help          = ipvs_mt_help,
-		.parse         = ipvs_mt4_parse,
-		.final_check   = ipvs_mt_check,
+		.x6_parse      = ipvs_mt_parse,
+		.x6_fcheck     = ipvs_mt_check,
 		.print         = ipvs_mt4_print,
 		.save          = ipvs_mt4_save,
-		.extra_opts    = ipvs_mt_opts,
+		.x6_options    = ipvs_mt_opts,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -346,11 +268,11 @@ static struct xtables_match ipvs_matches_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),
 		.help          = ipvs_mt_help,
-		.parse         = ipvs_mt6_parse,
-		.final_check   = ipvs_mt_check,
+		.x6_parse      = ipvs_mt_parse,
+		.x6_fcheck     = ipvs_mt_check,
 		.print         = ipvs_mt6_print,
 		.save          = ipvs_mt6_save,
-		.extra_opts    = ipvs_mt_opts,
+		.x6_options    = ipvs_mt_opts,
 	},
 };
 
-- 
1.7.1


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

* [PATCH 17/17] libxt_conntrack: use guided option parser
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (15 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 16/17] libxt_ipvs: use guided option parser Jan Engelhardt
@ 2011-05-09 19:55 ` Jan Engelhardt
  2011-05-11 11:45 ` guided option parser, run 6 Patrick McHardy
  17 siblings, 0 replies; 20+ messages in thread
From: Jan Engelhardt @ 2011-05-09 19:55 UTC (permalink / raw)
  To: kaber; +Cc: netfilter-devel

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
 extensions/libxt_conntrack.c |  670 ++++++++++++++----------------------------
 1 files changed, 219 insertions(+), 451 deletions(-)

diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
index 8312d04..2fb3644 100644
--- a/extensions/libxt_conntrack.c
+++ b/extensions/libxt_conntrack.c
@@ -6,21 +6,14 @@
  *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
  *	Jan Engelhardt <jengelh@computergmbh.de>
  */
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <getopt.h>
-#include <netdb.h>
 #include <stdbool.h>
-#include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <xtables.h>
-#include <linux/netfilter.h>
 #include <linux/netfilter/xt_conntrack.h>
 #include <linux/netfilter/nf_conntrack_common.h>
-#include <arpa/inet.h>
 
 struct ip_conntrack_old_tuple {
 	struct {
@@ -55,6 +48,22 @@ struct xt_conntrack_info {
 	uint8_t invflags;
 };
 
+enum {
+	O_CTSTATE = 0,
+	O_CTPROTO,
+	O_CTORIGSRC,
+	O_CTORIGDST,
+	O_CTREPLSRC,
+	O_CTREPLDST,
+	O_CTORIGSRCPORT,
+	O_CTORIGDSTPORT,
+	O_CTREPLSRCPORT,
+	O_CTREPLDSTPORT,
+	O_CTSTATUS,
+	O_CTEXPIRE,
+	O_CTDIR,
+};
+
 static void conntrack_mt_help(void)
 {
 	printf(
@@ -79,34 +88,59 @@ static void conntrack_mt_help(void)
 "    --ctdir {ORIGINAL|REPLY}   Flow direction of packet\n");
 }
 
-static const struct option conntrack_mt_opts_v0[] = {
-	{.name = "ctstate",   .has_arg = true, .val = '1'},
-	{.name = "ctproto",   .has_arg = true, .val = '2'},
-	{.name = "ctorigsrc", .has_arg = true, .val = '3'},
-	{.name = "ctorigdst", .has_arg = true, .val = '4'},
-	{.name = "ctreplsrc", .has_arg = true, .val = '5'},
-	{.name = "ctrepldst", .has_arg = true, .val = '6'},
-	{.name = "ctstatus",  .has_arg = true, .val = '7'},
-	{.name = "ctexpire",  .has_arg = true, .val = '8'},
-	XT_GETOPT_TABLEEND,
+#define s struct xt_conntrack_info /* for v0 */
+static const struct xt_option_entry conntrack_mt_opts_v0[] = {
+	{.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOST,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOST,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctreplsrc", .id = O_CTREPLSRC, .type = XTTYPE_HOST,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctrepldst", .id = O_CTREPLDST, .type = XTTYPE_HOST,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctstatus", .id = O_CTSTATUS, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctexpire", .id = O_CTEXPIRE, .type = XTTYPE_UINT32RC,
+	 .flags = XTOPT_INVERT},
+	XTOPT_TABLEEND,
 };
-
-static const struct option conntrack_mt_opts[] = {
-	{.name = "ctstate",       .has_arg = true, .val = '1'},
-	{.name = "ctproto",       .has_arg = true, .val = '2'},
-	{.name = "ctorigsrc",     .has_arg = true, .val = '3'},
-	{.name = "ctorigdst",     .has_arg = true, .val = '4'},
-	{.name = "ctreplsrc",     .has_arg = true, .val = '5'},
-	{.name = "ctrepldst",     .has_arg = true, .val = '6'},
-	{.name = "ctstatus",      .has_arg = true, .val = '7'},
-	{.name = "ctexpire",      .has_arg = true, .val = '8'},
-	{.name = "ctorigsrcport", .has_arg = true, .val = 'a'},
-	{.name = "ctorigdstport", .has_arg = true, .val = 'b'},
-	{.name = "ctreplsrcport", .has_arg = true, .val = 'c'},
-	{.name = "ctrepldstport", .has_arg = true, .val = 'd'},
-	{.name = "ctdir",         .has_arg = true, .val = 'e'},
-	{.name = NULL},
+#undef s
+
+#define s struct xt_conntrack_mtinfo3 /* for v1-v3 */
+/* We exploit the fact that v1-v3 share the same layout */
+static const struct xt_option_entry conntrack_mt_opts[] = {
+	{.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOSTMASK,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOSTMASK,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctreplsrc", .id = O_CTREPLSRC, .type = XTTYPE_HOSTMASK,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctrepldst", .id = O_CTREPLDST, .type = XTTYPE_HOSTMASK,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctstatus", .id = O_CTSTATUS, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctexpire", .id = O_CTEXPIRE, .type = XTTYPE_UINT32RC,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctorigsrcport", .id = O_CTORIGSRCPORT, .type = XTTYPE_PORTRC,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctorigdstport", .id = O_CTORIGDSTPORT, .type = XTTYPE_PORTRC,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctreplsrcport", .id = O_CTREPLSRCPORT, .type = XTTYPE_PORTRC,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctrepldstport", .id = O_CTREPLDSTPORT, .type = XTTYPE_PORTRC,
+	 .flags = XTOPT_INVERT},
+	{.name = "ctdir", .id = O_CTDIR, .type = XTTYPE_STRING},
+	XTOPT_TABLEEND,
 };
+#undef s
 
 static int
 parse_state(const char *state, size_t len, struct xt_conntrack_info *sinfo)
@@ -320,39 +354,21 @@ conntrack_ps_expires(struct xt_conntrack_mtinfo3 *info, const char *s)
 	info->expires_max = max;
 }
 
-static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
-                           const void *entry, struct xt_entry_match **match)
+static void conntrack_parse(struct xt_option_call *cb)
 {
-	struct xt_conntrack_info *sinfo = (void *)(*match)->data;
-	char *protocol = NULL;
-	unsigned int naddrs = 0;
-	struct in_addr *addrs = NULL;
+	struct xt_conntrack_info *sinfo = cb->data;
 
-
-	switch (c) {
-	case '1':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
-		parse_states(optarg, sinfo);
-		if (invert) {
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_CTSTATE:
+		parse_states(cb->arg, sinfo);
+		if (cb->invert)
 			sinfo->invflags |= XT_CONNTRACK_STATE;
-		}
-		sinfo->flags |= XT_CONNTRACK_STATE;
 		break;
-
-	case '2':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
-		if(invert)
+	case O_CTPROTO:
+		if (cb->invert)
 			sinfo->invflags |= XT_CONNTRACK_PROTO;
-
-		/* Canonicalize into lower case */
-		for (protocol = optarg; *protocol; protocol++)
-			*protocol = tolower(*protocol);
-
-		protocol = optarg;
-		sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum =
-			xtables_parse_protocol(protocol);
+		sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = cb->val.protocol;
 
 		if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
 		    && (sinfo->invflags & XT_INV_PROTO))
@@ -361,390 +377,151 @@ static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
 
 		sinfo->flags |= XT_CONNTRACK_PROTO;
 		break;
-
-	case '3':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
-		if (invert)
+	case O_CTORIGSRC:
+		if (cb->invert)
 			sinfo->invflags |= XT_CONNTRACK_ORIGSRC;
-
-		xtables_ipparse_any(optarg, &addrs,
-					&sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
-					&naddrs);
-		if(naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-				"multiple IP addresses not allowed");
-
-		if(naddrs == 1) {
-			sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
-		}
-
+		sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = cb->val.haddr.ip;
 		sinfo->flags |= XT_CONNTRACK_ORIGSRC;
 		break;
-
-	case '4':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
-		if (invert)
+	case O_CTORIGDST:
+		if (cb->invert)
 			sinfo->invflags |= XT_CONNTRACK_ORIGDST;
-
-		xtables_ipparse_any(optarg, &addrs,
-					&sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
-					&naddrs);
-		if(naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-				"multiple IP addresses not allowed");
-
-		if(naddrs == 1) {
-			sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
-		}
-
+		sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = cb->val.haddr.ip;
 		sinfo->flags |= XT_CONNTRACK_ORIGDST;
 		break;
-
-	case '5':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
-		if (invert)
+	case O_CTREPLSRC:
+		if (cb->invert)
 			sinfo->invflags |= XT_CONNTRACK_REPLSRC;
-
-		xtables_ipparse_any(optarg, &addrs,
-					&sinfo->sipmsk[IP_CT_DIR_REPLY],
-					&naddrs);
-		if(naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-				"multiple IP addresses not allowed");
-
-		if(naddrs == 1) {
-			sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
-		}
-
+		sinfo->tuple[IP_CT_DIR_REPLY].src.ip = cb->val.haddr.ip;
 		sinfo->flags |= XT_CONNTRACK_REPLSRC;
 		break;
-
-	case '6':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
-		if (invert)
+	case O_CTREPLDST:
+		if (cb->invert)
 			sinfo->invflags |= XT_CONNTRACK_REPLDST;
-
-		xtables_ipparse_any(optarg, &addrs,
-					&sinfo->dipmsk[IP_CT_DIR_REPLY],
-					&naddrs);
-		if(naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-				"multiple IP addresses not allowed");
-
-		if(naddrs == 1) {
-			sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
-		}
-
+		sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = cb->val.haddr.ip;
 		sinfo->flags |= XT_CONNTRACK_REPLDST;
 		break;
-
-	case '7':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
-		parse_statuses(optarg, sinfo);
-		if (invert) {
+	case O_CTSTATUS:
+		parse_statuses(cb->arg, sinfo);
+		if (cb->invert)
 			sinfo->invflags |= XT_CONNTRACK_STATUS;
-		}
 		sinfo->flags |= XT_CONNTRACK_STATUS;
 		break;
-
-	case '8':
-		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
-
-		parse_expires(optarg, sinfo);
-		if (invert) {
+	case O_CTEXPIRE:
+		parse_expires(cb->arg, sinfo);
+		if (cb->invert)
 			sinfo->invflags |= XT_CONNTRACK_EXPIRES;
-		}
 		sinfo->flags |= XT_CONNTRACK_EXPIRES;
 		break;
 	}
-
-	*flags = sinfo->flags;
-	return 1;
 }
 
-static void
-ct_parse_ports(const char *param, const char *str,
-	       u_int16_t *port_low, u_int16_t *port_high)
+static void conntrack_mt_parse(struct xt_option_call *cb, uint8_t rev)
 {
-	unsigned int port;
-	char *buf, *cp;
+	struct xt_conntrack_mtinfo3 *info = cb->data;
 
-	buf = strdup(str);
-	cp = strchr(buf, ':');
-	if (cp != NULL)
-		*cp = '\0';
-
-	if (!xtables_strtoui(buf, NULL, &port, 0, UINT16_MAX))
-		xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf);
-
-	if (port_high == NULL) {
-		/* revision 0-2 do not support ranges */
-		if (cp != NULL)
-			xtables_error(PARAMETER_PROBLEM, "conntrack: "
-				      "port ranges not supported");
-
-		*port_low = htons(port);
-	} else {
-		*port_low = port;
-
-		if (cp != NULL) {
-			if (!xtables_strtoui(cp + 1, NULL, &port, 0, UINT16_MAX))
-				xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf);
-
-			*port_high = port;
-			if (*port_low > *port_high)
-				xtables_error(PARAMETER_PROBLEM,
-					      "invalid portrange (min > max)");
-		} else
-			*port_high = port;
-	}
-
-	free(buf);
-}
-
-
-static int
-conntrack_mt_parse(int c, bool invert, unsigned int *flags,
-                   struct xt_conntrack_mtinfo3 *info, bool v3)
-{
-	char *p;
-
-	switch (c) {
-	case '1': /* --ctstate */
-		conntrack_ps_states(info, optarg);
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_CTSTATE:
+		conntrack_ps_states(info, cb->arg);
 		info->match_flags |= XT_CONNTRACK_STATE;
-		if (invert)
+		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_STATE;
 		break;
-
-	case '2': /* --ctproto */
-		/* Canonicalize into lower case */
-		for (p = optarg; *p != '\0'; ++p)
-			*p = tolower(*p);
-		info->l4proto = xtables_parse_protocol(optarg);
-
+	case O_CTPROTO:
+		info->l4proto = cb->val.protocol;
 		if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO))
 			xtables_error(PARAMETER_PROBLEM, "conntrack: rule would "
 			           "never match protocol");
 
 		info->match_flags |= XT_CONNTRACK_PROTO;
-		if (invert)
+		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_PROTO;
 		break;
-
-	case '7': /* --ctstatus */
-		conntrack_ps_statuses(info, optarg);
+	case O_CTORIGSRC:
+		info->origsrc_addr = cb->val.haddr;
+		info->origsrc_mask = cb->val.hmask;
+		info->match_flags |= XT_CONNTRACK_ORIGSRC;
+		if (cb->invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGSRC;
+		break;
+	case O_CTORIGDST:
+		info->origdst_addr = cb->val.haddr;
+		info->origdst_mask = cb->val.hmask;
+		info->match_flags |= XT_CONNTRACK_ORIGDST;
+		if (cb->invert)
+			info->invert_flags |= XT_CONNTRACK_ORIGDST;
+		break;
+	case O_CTREPLSRC:
+		info->replsrc_addr = cb->val.haddr;
+		info->replsrc_mask = cb->val.hmask;
+		info->match_flags |= XT_CONNTRACK_REPLSRC;
+		if (cb->invert)
+			info->invert_flags |= XT_CONNTRACK_REPLSRC;
+		break;
+	case O_CTREPLDST:
+		info->repldst_addr = cb->val.haddr;
+		info->repldst_mask = cb->val.hmask;
+		info->match_flags |= XT_CONNTRACK_REPLDST;
+		if (cb->invert)
+			info->invert_flags |= XT_CONNTRACK_REPLDST;
+		break;
+	case O_CTSTATUS:
+		conntrack_ps_statuses(info, cb->arg);
 		info->match_flags |= XT_CONNTRACK_STATUS;
-		if (invert)
+		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_STATUS;
 		break;
-
-	case '8': /* --ctexpire */
-		conntrack_ps_expires(info, optarg);
+	case O_CTEXPIRE:
+		conntrack_ps_expires(info, cb->arg);
 		info->match_flags |= XT_CONNTRACK_EXPIRES;
-		if (invert)
+		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_EXPIRES;
 		break;
-
-	case 'a': /* --ctorigsrcport */
-		ct_parse_ports("--ctorigsrcport", optarg,
-			       &info->origsrc_port,
-			       v3 ? &info->origsrc_port_high : NULL);
-
+	case O_CTORIGSRCPORT:
+		info->origsrc_port = cb->val.port_range[0];
+		info->origsrc_port = (cb->nvals == 2) ? cb->val.port_range[1] :
+		                     cb->val.port_range[0];
 		info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT;
-		if (invert)
+		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT;
 		break;
-
-	case 'b': /* --ctorigdstport */
-		ct_parse_ports("--ctorigdstport", optarg,
-			       &info->origdst_port,
-			       v3 ? &info->origdst_port_high : NULL);
-
+	case O_CTORIGDSTPORT:
+		info->origdst_port = cb->val.port_range[0];
+		info->origdst_port = (cb->nvals == 2) ? cb->val.port_range[1] :
+		                     cb->val.port_range[0];
 		info->match_flags |= XT_CONNTRACK_ORIGDST_PORT;
-		if (invert)
+		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT;
 		break;
-
-	case 'c': /* --ctreplsrcport */
-		ct_parse_ports("--ctreplsrcport", optarg,
-			       &info->replsrc_port,
-			       v3 ? &info->replsrc_port_high : NULL);
-
+	case O_CTREPLSRCPORT:
+		info->replsrc_port = cb->val.port_range[0];
+		info->replsrc_port = (cb->nvals == 2) ? cb->val.port_range[1] :
+		                     cb->val.port_range[0];
 		info->match_flags |= XT_CONNTRACK_REPLSRC_PORT;
-		if (invert)
+		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT;
 		break;
-
-	case 'd': /* --ctrepldstport */
-		ct_parse_ports("--ctrepldstport", optarg,
-			       &info->repldst_port,
-			       v3 ? &info->repldst_port_high : NULL);
-
+	case O_CTREPLDSTPORT:
+		info->repldst_port = cb->val.port_range[0];
+		info->repldst_port = (cb->nvals == 2) ? cb->val.port_range[1] :
+		                     cb->val.port_range[0];
 		info->match_flags |= XT_CONNTRACK_REPLDST_PORT;
-		if (invert)
+		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_REPLDST_PORT;
 		break;
-
-	case 'e': /* --ctdir */
-		xtables_param_act(XTF_NO_INVERT, "conntrack", "--ctdir", invert);
-		if (strcasecmp(optarg, "ORIGINAL") == 0) {
+	case O_CTDIR:
+		if (strcasecmp(cb->arg, "ORIGINAL") == 0) {
 			info->match_flags  |= XT_CONNTRACK_DIRECTION;
 			info->invert_flags &= ~XT_CONNTRACK_DIRECTION;
-		} else if (strcasecmp(optarg, "REPLY") == 0) {
+		} else if (strcasecmp(cb->arg, "REPLY") == 0) {
 			info->match_flags  |= XT_CONNTRACK_DIRECTION;
 			info->invert_flags |= XT_CONNTRACK_DIRECTION;
 		} else {
-			xtables_param_act(XTF_BAD_VALUE, "conntrack", "--ctdir", optarg);
+			xtables_param_act(XTF_BAD_VALUE, "conntrack", "--ctdir", cb->arg);
 		}
 		break;
 	}
-
-	*flags = info->match_flags;
-	return true;
-}
-
-static int
-conntrack_mt4_parse(int c, bool invert, unsigned int *flags,
-                    struct xt_conntrack_mtinfo3 *info, bool v3)
-{
-	struct in_addr *addr = NULL;
-	unsigned int naddrs = 0;
-
-	switch (c) {
-	case '3': /* --ctorigsrc */
-		xtables_ipparse_any(optarg, &addr, &info->origsrc_mask.in,
-		                        &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->origsrc_addr.in, addr, sizeof(*addr));
-		info->match_flags |= XT_CONNTRACK_ORIGSRC;
-		if (invert)
-			info->invert_flags |= XT_CONNTRACK_ORIGSRC;
-		break;
-
-	case '4': /* --ctorigdst */
-		xtables_ipparse_any(optarg, &addr, &info->origdst_mask.in,
-		                        &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
-		info->match_flags |= XT_CONNTRACK_ORIGDST;
-		if (invert)
-			info->invert_flags |= XT_CONNTRACK_ORIGDST;
-		break;
-
-	case '5': /* --ctreplsrc */
-		xtables_ipparse_any(optarg, &addr, &info->replsrc_mask.in,
-		                        &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
-		info->match_flags |= XT_CONNTRACK_REPLSRC;
-		if (invert)
-			info->invert_flags |= XT_CONNTRACK_REPLSRC;
-		break;
-
-	case '6': /* --ctrepldst */
-		xtables_ipparse_any(optarg, &addr, &info->repldst_mask.in,
-		                        &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
-		info->match_flags |= XT_CONNTRACK_REPLDST;
-		if (invert)
-			info->invert_flags |= XT_CONNTRACK_REPLDST;
-		break;
-
-
-	default:
-		return conntrack_mt_parse(c, invert, flags, info, v3);
-	}
-
-	*flags = info->match_flags;
-	return true;
-}
-
-static int
-conntrack_mt6_parse(int c, bool invert, unsigned int *flags,
-                    struct xt_conntrack_mtinfo3 *info, bool v3)
-{
-	struct in6_addr *addr = NULL;
-	unsigned int naddrs = 0;
-
-	switch (c) {
-	case '3': /* --ctorigsrc */
-		xtables_ip6parse_any(optarg, &addr,
-		                         &info->origsrc_mask.in6, &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->origsrc_addr.in6, addr, sizeof(*addr));
-		info->match_flags |= XT_CONNTRACK_ORIGSRC;
-		if (invert)
-			info->invert_flags |= XT_CONNTRACK_ORIGSRC;
-		break;
-
-	case '4': /* --ctorigdst */
-		xtables_ip6parse_any(optarg, &addr,
-		                         &info->origdst_mask.in6, &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
-		info->match_flags |= XT_CONNTRACK_ORIGDST;
-		if (invert)
-			info->invert_flags |= XT_CONNTRACK_ORIGDST;
-		break;
-
-	case '5': /* --ctreplsrc */
-		xtables_ip6parse_any(optarg, &addr,
-		                         &info->replsrc_mask.in6, &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
-		info->match_flags |= XT_CONNTRACK_REPLSRC;
-		if (invert)
-			info->invert_flags |= XT_CONNTRACK_REPLSRC;
-		break;
-
-	case '6': /* --ctrepldst */
-		xtables_ip6parse_any(optarg, &addr,
-		                         &info->repldst_mask.in6, &naddrs);
-		if (naddrs > 1)
-			xtables_error(PARAMETER_PROBLEM,
-			           "multiple IP addresses not allowed");
-		if (naddrs == 1)
-			memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
-		info->match_flags |= XT_CONNTRACK_REPLDST;
-		if (invert)
-			info->invert_flags |= XT_CONNTRACK_REPLDST;
-		break;
-
-
-	default:
-		return conntrack_mt_parse(c, invert, flags, info, v3);
-	}
-
-	*flags = info->match_flags;
-	return true;
 }
 
 #define cinfo_transform(r, l) \
@@ -754,65 +531,56 @@ conntrack_mt6_parse(int c, bool invert, unsigned int *flags,
 		(r)->status_mask = (l)->status_mask; \
 	} while (false);
 
-static int
-conntrack1_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
-                     const void *entry, struct xt_entry_match **match)
+static void conntrack1_mt_parse(struct xt_option_call *cb)
 {
-	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+	struct xt_conntrack_mtinfo1 *info = cb->data;
 	struct xt_conntrack_mtinfo3 up;
 
+	memset(&up, 0, sizeof(up));
 	cinfo_transform(&up, info);
-	if (!conntrack_mt4_parse(c, invert, flags, &up, false))
-		return false;
-	cinfo_transform(info, &up);
-	return true;
-}
-
-static int
-conntrack1_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
-                     const void *entry, struct xt_entry_match **match)
-{
-	struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
-	struct xt_conntrack_mtinfo3 up;
-
-	cinfo_transform(&up, info);
-	if (!conntrack_mt6_parse(c, invert, flags, &up, false))
-		return false;
+	cb->data = &up;
+	conntrack_mt_parse(cb, 3);
+	if (up.origsrc_port != up.origsrc_port_high ||
+	    up.origdst_port != up.origdst_port_high ||
+	    up.replsrc_port != up.replsrc_port_high ||
+	    up.repldst_port != up.repldst_port_high)
+		xtables_error(PARAMETER_PROBLEM,
+			"connlimit rev 1 does not support port ranges");
 	cinfo_transform(info, &up);
-	return true;
+	cb->data = info;
 }
 
-static int
-conntrack2_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
-                     const void *entry, struct xt_entry_match **match)
+static void conntrack2_mt_parse(struct xt_option_call *cb)
 {
-	return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, false);
-}
+#define cinfo2_transform(r, l) \
+		memcpy((r), (l), offsetof(typeof(*(l)), sizeof(*info));
 
-static int
-conntrack2_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
-                     const void *entry, struct xt_entry_match **match)
-{
-	return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, false);
-}
+	struct xt_conntrack_mtinfo2 *info = cb->data;
+	struct xt_conntrack_mtinfo3 up;
 
-static int
-conntrack3_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
-                     const void *entry, struct xt_entry_match **match)
-{
-	return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, true);
+	memset(&up, 0, sizeof(up));
+	memcpy(&up, info, sizeof(*info));
+	cb->data = &up;
+	conntrack_mt_parse(cb, 3);
+	if (up.origsrc_port != up.origsrc_port_high ||
+	    up.origdst_port != up.origdst_port_high ||
+	    up.replsrc_port != up.replsrc_port_high ||
+	    up.repldst_port != up.repldst_port_high)
+		xtables_error(PARAMETER_PROBLEM,
+			"connlimit rev 2 does not support port ranges");
+	memcpy(info, &up, sizeof(*info));
+	cb->data = info;
+#undef cinfo2_transform
 }
 
-static int
-conntrack3_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
-                     const void *entry, struct xt_entry_match **match)
+static void conntrack3_mt_parse(struct xt_option_call *cb)
 {
-	return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, true);
+	conntrack_mt_parse(cb, 3);
 }
 
-static void conntrack_mt_check(unsigned int flags)
+static void conntrack_mt_check(struct xt_fcheck_call *cb)
 {
-	if (flags == 0)
+	if (cb->xflags == 0)
 		xtables_error(PARAMETER_PROBLEM, "conntrack: At least one option "
 		           "is required");
 }
@@ -1259,11 +1027,11 @@ static struct xtables_match conntrack_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_conntrack_info)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_info)),
 		.help          = conntrack_mt_help,
-		.parse         = conntrack_parse,
-		.final_check   = conntrack_mt_check,
+		.x6_parse      = conntrack_parse,
+		.x6_fcheck     = conntrack_mt_check,
 		.print         = conntrack_print,
 		.save          = conntrack_save,
-		.extra_opts    = conntrack_mt_opts_v0,
+		.x6_options    = conntrack_mt_opts_v0,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -1273,11 +1041,11 @@ static struct xtables_match conntrack_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
 		.help          = conntrack_mt_help,
-		.parse         = conntrack1_mt4_parse,
-		.final_check   = conntrack_mt_check,
+		.x6_parse      = conntrack1_mt_parse,
+		.x6_fcheck     = conntrack_mt_check,
 		.print         = conntrack1_mt4_print,
 		.save          = conntrack1_mt4_save,
-		.extra_opts    = conntrack_mt_opts,
+		.x6_options    = conntrack_mt_opts,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -1287,11 +1055,11 @@ static struct xtables_match conntrack_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
 		.help          = conntrack_mt_help,
-		.parse         = conntrack1_mt6_parse,
-		.final_check   = conntrack_mt_check,
+		.x6_parse      = conntrack1_mt_parse,
+		.x6_fcheck     = conntrack_mt_check,
 		.print         = conntrack1_mt6_print,
 		.save          = conntrack1_mt6_save,
-		.extra_opts    = conntrack_mt_opts,
+		.x6_options    = conntrack_mt_opts,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -1301,11 +1069,11 @@ static struct xtables_match conntrack_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
 		.help          = conntrack_mt_help,
-		.parse         = conntrack2_mt4_parse,
-		.final_check   = conntrack_mt_check,
+		.x6_parse      = conntrack2_mt_parse,
+		.x6_fcheck     = conntrack_mt_check,
 		.print         = conntrack2_mt_print,
 		.save          = conntrack2_mt_save,
-		.extra_opts    = conntrack_mt_opts,
+		.x6_options    = conntrack_mt_opts,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -1315,11 +1083,11 @@ static struct xtables_match conntrack_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
 		.help          = conntrack_mt_help,
-		.parse         = conntrack2_mt6_parse,
-		.final_check   = conntrack_mt_check,
+		.x6_parse      = conntrack2_mt_parse,
+		.x6_fcheck     = conntrack_mt_check,
 		.print         = conntrack2_mt6_print,
 		.save          = conntrack2_mt6_save,
-		.extra_opts    = conntrack_mt_opts,
+		.x6_options    = conntrack_mt_opts,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -1329,11 +1097,11 @@ static struct xtables_match conntrack_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
 		.help          = conntrack_mt_help,
-		.parse         = conntrack3_mt4_parse,
-		.final_check   = conntrack_mt_check,
+		.x6_parse      = conntrack3_mt_parse,
+		.x6_fcheck     = conntrack_mt_check,
 		.print         = conntrack3_mt_print,
 		.save          = conntrack3_mt_save,
-		.extra_opts    = conntrack_mt_opts,
+		.x6_options    = conntrack_mt_opts,
 	},
 	{
 		.version       = XTABLES_VERSION,
@@ -1343,11 +1111,11 @@ static struct xtables_match conntrack_mt_reg[] = {
 		.size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
 		.userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
 		.help          = conntrack_mt_help,
-		.parse         = conntrack3_mt6_parse,
-		.final_check   = conntrack_mt_check,
+		.x6_parse      = conntrack3_mt_parse,
+		.x6_fcheck     = conntrack_mt_check,
 		.print         = conntrack3_mt6_print,
 		.save          = conntrack3_mt6_save,
-		.extra_opts    = conntrack_mt_opts,
+		.x6_options    = conntrack_mt_opts,
 	},
 };
 
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 16/17] libxt_ipvs: use guided option parser
  2011-05-09 19:55 ` [PATCH 16/17] libxt_ipvs: use guided option parser Jan Engelhardt
@ 2011-05-09 23:15   ` Simon Horman
  0 siblings, 0 replies; 20+ messages in thread
From: Simon Horman @ 2011-05-09 23:15 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: kaber, netfilter-devel

On Mon, May 09, 2011 at 09:55:10PM +0200, Jan Engelhardt wrote:
> Signed-off-by: Jan Engelhardt <jengelh@medozas.de>

Acked-by: Simon Horman <horms@verge.net.au>

> ---
>  extensions/libxt_ipvs.c |  208 +++++++++++++++--------------------------------
>  1 files changed, 65 insertions(+), 143 deletions(-)

Nice diffstat :-)

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

* Re: guided option parser, run 6
  2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
                   ` (16 preceding siblings ...)
  2011-05-09 19:55 ` [PATCH 17/17] libxt_conntrack: " Jan Engelhardt
@ 2011-05-11 11:45 ` Patrick McHardy
  17 siblings, 0 replies; 20+ messages in thread
From: Patrick McHardy @ 2011-05-11 11:45 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netfilter-devel

Am 09.05.2011 21:54, schrieb Jan Engelhardt:
> The following changes since commit c29f7ef7cb5a31620060ef721d3c65b343eb537a:
> 
>   Merge branch 'opts' of git://dev.medozas.de/iptables (2011-05-09 20:23:21 +0200)
> 
> are available in the git repository at:
> 
>   git://dev.medozas.de/iptables opts
> 
> Jan Engelhardt (17):
>       libxtables: support for XTTYPE_PLENMASK
>       libxt_connlimit: use guided option parser
>       libxt_recent: use guided option parser
>       libxtables: do not overlay addr and mask parts, and cleanup
>       libxtables: flag invalid uses of XTOPT_PUT
>       libxtables: XTTYPE_PLEN support
>       libxt_hashlimit: use guided option parser
>       libxtables: XTTYPE_HOSTMASK support
>       libxt_policy: use guided option parser
>       libxt_owner: use guided option parser
>       libxt_osf: use guided option parser
>       libxt_multiport: use guided option parser
>       libipt_NETMAP: use guided option parser
>       libxt_limit: use guided option parser
>       libxtables: XTTYPE_PROTOCOL support
>       libxt_ipvs: use guided option parser
>       libxt_conntrack: use guided option parser

Also pulled, thanks a lot Jan.

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

end of thread, other threads:[~2011-05-11 16:00 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-09 19:54 guided option parser, run 6 Jan Engelhardt
2011-05-09 19:54 ` [PATCH 01/17] libxtables: support for XTTYPE_PLENMASK Jan Engelhardt
2011-05-09 19:54 ` [PATCH 02/17] libxt_connlimit: use guided option parser Jan Engelhardt
2011-05-09 19:54 ` [PATCH 03/17] libxt_recent: " Jan Engelhardt
2011-05-09 19:54 ` [PATCH 04/17] libxtables: do not overlay addr and mask parts, and cleanup Jan Engelhardt
2011-05-09 19:54 ` [PATCH 05/17] libxtables: flag invalid uses of XTOPT_PUT Jan Engelhardt
2011-05-09 19:55 ` [PATCH 06/17] libxtables: XTTYPE_PLEN support Jan Engelhardt
2011-05-09 19:55 ` [PATCH 07/17] libxt_hashlimit: use guided option parser Jan Engelhardt
2011-05-09 19:55 ` [PATCH 08/17] libxtables: XTTYPE_HOSTMASK support Jan Engelhardt
2011-05-09 19:55 ` [PATCH 09/17] libxt_policy: use guided option parser Jan Engelhardt
2011-05-09 19:55 ` [PATCH 10/17] libxt_owner: " Jan Engelhardt
2011-05-09 19:55 ` [PATCH 11/17] libxt_osf: " Jan Engelhardt
2011-05-09 19:55 ` [PATCH 12/17] libxt_multiport: " Jan Engelhardt
2011-05-09 19:55 ` [PATCH 13/17] libipt_NETMAP: " Jan Engelhardt
2011-05-09 19:55 ` [PATCH 14/17] libxt_limit: " Jan Engelhardt
2011-05-09 19:55 ` [PATCH 15/17] libxtables: XTTYPE_PROTOCOL support Jan Engelhardt
2011-05-09 19:55 ` [PATCH 16/17] libxt_ipvs: use guided option parser Jan Engelhardt
2011-05-09 23:15   ` Simon Horman
2011-05-09 19:55 ` [PATCH 17/17] libxt_conntrack: " Jan Engelhardt
2011-05-11 11:45 ` guided option parser, run 6 Patrick McHardy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).