[PATCH 12/17] libxt_multiport: 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_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

--
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