summaryrefslogtreecommitdiffstats
path: root/extensions/libipt_DNAT.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2022-01-08 13:15:20 +0100
committerPhil Sutter <phil@nwl.cc>2022-01-17 15:16:21 +0100
commit30b178b9bf11e75cd5ff7310ce0f5d9c9ace3b7a (patch)
tree22c084309bbfee0f03584db7a9be05cd00b72a83 /extensions/libipt_DNAT.c
parent7ee5b97095365383629b9c7c78ba93e09e1051d2 (diff)
extensions: *NAT: Kill multiple IPv4 range support
It is the year of the great revolution, nobody cares about kernel versions below 2.6.11 anymore. Time to get rid of the cruft. While being at it, drop the explicit duplicate argument check and instead just remove XTOPT_MULTI flag from the respective xt_option_entry. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'extensions/libipt_DNAT.c')
-rw-r--r--extensions/libipt_DNAT.c138
1 files changed, 47 insertions, 91 deletions
diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c
index 5b33fd23..eefa95eb 100644
--- a/extensions/libipt_DNAT.c
+++ b/extensions/libipt_DNAT.c
@@ -18,14 +18,6 @@ enum {
F_X_TO_DEST = 1 << O_X_TO_DEST,
};
-/* Dest NAT data consists of a multi-range, indicating where to map
- to. */
-struct ipt_natinfo
-{
- struct xt_entry_target t;
- struct nf_nat_ipv4_multi_range_compat mr;
-};
-
static void DNAT_help(void)
{
printf(
@@ -46,41 +38,20 @@ static void DNAT_help_v2(void)
static const struct xt_option_entry DNAT_opts[] = {
{.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING,
- .flags = XTOPT_MAND | XTOPT_MULTI},
+ .flags = XTOPT_MAND},
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
-static struct ipt_natinfo *
-append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range)
-{
- unsigned int size;
-
- /* One rangesize already in struct ipt_natinfo */
- size = XT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range));
-
- info = realloc(info, size);
- if (!info)
- xtables_error(OTHER_PROBLEM, "Out of memory\n");
-
- info->t.u.target_size = size;
- info->mr.range[info->mr.rangesize] = *range;
- info->mr.rangesize++;
-
- return info;
-}
-
/* Ranges expected in network order. */
-static struct xt_entry_target *
-parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
+static void
+parse_to(const char *orig_arg, int portok, struct nf_nat_ipv4_range *range)
{
- struct nf_nat_ipv4_range range;
char *arg, *colon, *dash, *error;
const struct in_addr *ip;
arg = xtables_strdup(orig_arg);
- memset(&range, 0, sizeof(range));
colon = strchr(arg, ':');
if (colon) {
@@ -90,7 +61,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
xtables_error(PARAMETER_PROBLEM,
"Need TCP, UDP, SCTP or DCCP with port specification");
- range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+ range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
port = atoi(colon+1);
if (port <= 0 || port > 65535)
@@ -104,8 +75,8 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
dash = strchr(colon, '-');
if (!dash) {
- range.min.tcp.port
- = range.max.tcp.port
+ range->min.tcp.port
+ = range->max.tcp.port
= htons(port);
} else {
int maxport;
@@ -118,18 +89,18 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
/* People are stupid. */
xtables_error(PARAMETER_PROBLEM,
"Port range `%s' funky\n", colon+1);
- range.min.tcp.port = htons(port);
- range.max.tcp.port = htons(maxport);
+ range->min.tcp.port = htons(port);
+ range->max.tcp.port = htons(maxport);
}
/* Starts with a colon? No IP info...*/
if (colon == arg) {
free(arg);
- return &(append_range(info, &range)->t);
+ return;
}
*colon = '\0';
}
- range.flags |= NF_NAT_RANGE_MAP_IPS;
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
if (colon && dash && dash > colon)
dash = NULL;
@@ -141,24 +112,24 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
if (!ip)
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
arg);
- range.min_ip = ip->s_addr;
+ range->min_ip = ip->s_addr;
if (dash) {
ip = xtables_numeric_to_ipaddr(dash+1);
if (!ip)
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
dash+1);
- range.max_ip = ip->s_addr;
+ range->max_ip = ip->s_addr;
} else
- range.max_ip = range.min_ip;
+ range->max_ip = range->min_ip;
free(arg);
- return &(append_range(info, &range)->t);
+ return;
}
static void DNAT_parse(struct xt_option_call *cb)
{
+ struct nf_nat_ipv4_multi_range_compat *mr = (void *)cb->data;
const struct ipt_entry *entry = cb->xt_entry;
- struct ipt_natinfo *info = (void *)(*cb->target);
int portok;
if (entry->ip.proto == IPPROTO_TCP
@@ -173,18 +144,11 @@ static void DNAT_parse(struct xt_option_call *cb)
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_TO_DEST:
- if (cb->xflags & F_X_TO_DEST) {
- if (!kernel_version)
- get_kernel_version();
- if (kernel_version > LINUX_VERSION(2, 6, 10))
- xtables_error(PARAMETER_PROBLEM,
- "DNAT: Multiple --to-destination not supported");
- }
- *cb->target = parse_to(cb->arg, portok, info);
+ parse_to(cb->arg, portok, mr->range);
cb->xflags |= F_X_TO_DEST;
break;
case O_PERSISTENT:
- info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT;
+ mr->range->flags |= NF_NAT_RANGE_PERSISTENT;
break;
}
}
@@ -196,6 +160,8 @@ static void DNAT_fcheck(struct xt_fcheck_call *cb)
if ((cb->xflags & f) == f)
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
+
+ mr->rangesize = 1;
}
static void print_range(const struct nf_nat_ipv4_range *r)
@@ -221,32 +187,28 @@ static void print_range(const struct nf_nat_ipv4_range *r)
static void DNAT_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
- const struct ipt_natinfo *info = (const void *)target;
- unsigned int i = 0;
+ const struct nf_nat_ipv4_multi_range_compat *mr =
+ (const void *)target->data;
printf(" to:");
- for (i = 0; i < info->mr.rangesize; i++) {
- print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" random");
- if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
- printf(" persistent");
- }
+ print_range(mr->range);
+ if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" random");
+ if (mr->range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" persistent");
}
static void DNAT_save(const void *ip, const struct xt_entry_target *target)
{
- const struct ipt_natinfo *info = (const void *)target;
- unsigned int i = 0;
-
- for (i = 0; i < info->mr.rangesize; i++) {
- printf(" --to-destination ");
- print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" --random");
- if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
- printf(" --persistent");
- }
+ const struct nf_nat_ipv4_multi_range_compat *mr =
+ (const void *)target->data;
+
+ printf(" --to-destination ");
+ print_range(mr->range);
+ if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" --random");
+ if (mr->range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" --persistent");
}
static void print_range_xlate(const struct nf_nat_ipv4_range *r,
@@ -272,23 +234,21 @@ static void print_range_xlate(const struct nf_nat_ipv4_range *r,
static int DNAT_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
- const struct ipt_natinfo *info = (const void *)params->target;
- unsigned int i = 0;
+ const struct nf_nat_ipv4_multi_range_compat *mr =
+ (const void *)params->target->data;
bool sep_need = false;
const char *sep = " ";
- for (i = 0; i < info->mr.rangesize; i++) {
- xt_xlate_add(xl, "dnat to ");
- print_range_xlate(&info->mr.range[i], xl);
- if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) {
- xt_xlate_add(xl, " random");
- sep_need = true;
- }
- if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) {
- if (sep_need)
- sep = ",";
- xt_xlate_add(xl, "%spersistent", sep);
- }
+ xt_xlate_add(xl, "dnat to ");
+ print_range_xlate(mr->range, xl);
+ if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM) {
+ xt_xlate_add(xl, " random");
+ sep_need = true;
+ }
+ if (mr->range->flags & NF_NAT_RANGE_PERSISTENT) {
+ if (sep_need)
+ sep = ",";
+ xt_xlate_add(xl, "%spersistent", sep);
}
return 1;
@@ -406,10 +366,6 @@ static void DNAT_parse_v2(struct xt_option_call *cb)
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_TO_DEST:
- if (cb->xflags & F_X_TO_DEST) {
- xtables_error(PARAMETER_PROBLEM,
- "DNAT: Multiple --to-destination not supported");
- }
parse_to_v2(cb->arg, portok, range);
cb->xflags |= F_X_TO_DEST;
break;