summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorJan Engelhardt <jengelh@medozas.de>2011-05-08 19:07:28 +0200
committerJan Engelhardt <jengelh@medozas.de>2011-05-09 17:11:42 +0200
commit9f4a637ee5856e8f260e3f3867782ed5584e00f9 (patch)
tree2a81154460b8831b1e1cfc1c7a141a68f39bf89f /extensions
parentf875e84427de17b34ecb69a56d87161571ffab76 (diff)
libipt_SNAT: use guided option parser
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libipt_SNAT.c88
1 files changed, 39 insertions, 49 deletions
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 <stdbool.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <iptables.h>
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
#include <net/netfilter/nf_nat.h>
-#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)