[PATCH 02/17] libxt_connlimit: use guided option parser

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxx>
---
 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

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


[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux