From 9f4a637ee5856e8f260e3f3867782ed5584e00f9 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 8 May 2011 19:07:28 +0200 Subject: libipt_SNAT: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libipt_SNAT.c | 88 +++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 49 deletions(-) (limited to 'extensions/libipt_SNAT.c') diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c index 532770da..97769e68 100644 --- a/extensions/libipt_SNAT.c +++ b/extensions/libipt_SNAT.c @@ -1,18 +1,20 @@ -/* Shared library add-on to iptables to add source-NAT support. */ -#include #include #include #include #include -#include #include #include #include /* INT_MAX in ip_tables.h */ #include #include -#define IPT_SNAT_OPT_SOURCE 0x01 -#define IPT_SNAT_OPT_RANDOM 0x02 +enum { + O_TO_SRC = 0, + O_RANDOM, + O_PERSISTENT, + F_TO_SRC = 1 << O_TO_SRC, + F_RANDOM = 1 << O_RANDOM, +}; /* Source NAT data consists of a multi-range, indicating where to map to. */ @@ -31,11 +33,12 @@ static void SNAT_help(void) "[--random] [--persistent]\n"); } -static const struct option SNAT_opts[] = { - {.name = "to-source", .has_arg = true, .val = '1'}, - {.name = "random", .has_arg = false, .val = '2'}, - {.name = "persistent", .has_arg = false, .val = '3'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry SNAT_opts[] = { + {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_MULTI}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; static struct ipt_natinfo * @@ -59,12 +62,15 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range) /* Ranges expected in network order. */ static struct xt_entry_target * -parse_to(char *arg, int portok, struct ipt_natinfo *info) +parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info) { struct nf_nat_range range; - char *colon, *dash, *error; + char *arg, *colon, *dash, *error; const struct in_addr *ip; + arg = strdup(orig_arg); + if (arg == NULL) + xtables_error(RESOURCE_PROBLEM, "strdup"); memset(&range, 0, sizeof(range)); colon = strchr(arg, ':'); @@ -107,8 +113,10 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info) range.max.tcp.port = htons(maxport); } /* Starts with a colon? No IP info...*/ - if (colon == arg) + if (colon == arg) { + free(arg); return &(append_range(info, &range)->t); + } *colon = '\0'; } @@ -134,14 +142,14 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info) } else range.max_ip = range.min_ip; + free(arg); return &(append_range(info, &range)->t); } -static int SNAT_parse(int c, char **argv, int invert, unsigned int *flags, - const void *e, struct xt_entry_target **target) +static void SNAT_parse(struct xt_option_call *cb) { - const struct ipt_entry *entry = e; - struct ipt_natinfo *info = (void *)*target; + const struct ipt_entry *entry = cb->xt_entry; + struct ipt_natinfo *info = (void *)(*cb->target); int portok; if (entry->ip.proto == IPPROTO_TCP @@ -153,46 +161,29 @@ static int SNAT_parse(int c, char **argv, int invert, unsigned int *flags, else portok = 0; - switch (c) { - case '1': - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --to-source"); - - if (*flags & IPT_SNAT_OPT_SOURCE) { + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_TO_SRC: + if (cb->xflags & F_TO_SRC) { if (!kernel_version) get_kernel_version(); if (kernel_version > LINUX_VERSION(2, 6, 10)) xtables_error(PARAMETER_PROBLEM, "Multiple --to-source not supported"); } - *target = parse_to(optarg, portok, info); + *cb->target = parse_to(cb->arg, portok, info); /* WTF do we need this for?? */ - if (*flags & IPT_SNAT_OPT_RANDOM) + if (cb->xflags & F_RANDOM) info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; - *flags |= IPT_SNAT_OPT_SOURCE; - return 1; - - case '2': - if (*flags & IPT_SNAT_OPT_SOURCE) { + break; + case O_RANDOM: + if (cb->xflags & F_TO_SRC) info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM; - *flags |= IPT_SNAT_OPT_RANDOM; - } else - *flags |= IPT_SNAT_OPT_RANDOM; - return 1; - - case '3': + break; + case O_PERSISTENT: info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT; - return 1; + break; } - return 0; -} - -static void SNAT_check(unsigned int flags) -{ - if (!(flags & IPT_SNAT_OPT_SOURCE)) - xtables_error(PARAMETER_PROBLEM, - "You must specify --to-source"); } static void print_range(const struct nf_nat_range *r) @@ -253,11 +244,10 @@ static struct xtables_target snat_tg_reg = { .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)), .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), .help = SNAT_help, - .parse = SNAT_parse, - .final_check = SNAT_check, + .x6_parse = SNAT_parse, .print = SNAT_print, .save = SNAT_save, - .extra_opts = SNAT_opts, + .x6_options = SNAT_opts, }; void _init(void) -- cgit v1.2.3