summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-10-25 17:14:26 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2012-10-25 17:14:26 +0200
commit9d284c1c67188dfa8a4c7a6e36eb9a10bd9c15e2 (patch)
tree21c1bdb785a2b5779c772cc8fafbc043e16babbb
parent3e6fa55d5e28c93f417afeae7a7d4f349ddffcf4 (diff)
parent8d8896a3833292d091ee5a028f3461083bb956bd (diff)
Merge branch 'next' branch that contains new features scheduled for
Linux kernel 3.7
-rw-r--r--extensions/GNUmakefile.in2
-rw-r--r--extensions/libip6t_DNAT.c247
-rw-r--r--extensions/libip6t_DNPT.c71
-rw-r--r--extensions/libip6t_MASQUERADE.c150
-rw-r--r--extensions/libip6t_MASQUERADE.man30
-rw-r--r--extensions/libip6t_NETMAP.c93
-rw-r--r--extensions/libip6t_REDIRECT.c151
-rw-r--r--extensions/libip6t_SNAT.c247
-rw-r--r--extensions/libip6t_SNPT.c71
-rw-r--r--extensions/libipt_DNAT.c36
-rw-r--r--extensions/libipt_MASQUERADE.c32
-rw-r--r--extensions/libipt_NETMAP.c18
-rw-r--r--extensions/libipt_REDIRECT.c34
-rw-r--r--extensions/libipt_SAME.c21
-rw-r--r--extensions/libipt_SNAT.c36
-rw-r--r--extensions/libxt_time.c20
-rw-r--r--extensions/libxt_time.man12
-rw-r--r--include/linux/netfilter/nf_conntrack_tuple_common.h27
-rw-r--r--include/linux/netfilter/nf_nat.h33
-rw-r--r--include/linux/netfilter/xt_time.h1
-rw-r--r--include/linux/netfilter_ipv4/ipt_SAME.h2
-rw-r--r--include/linux/netfilter_ipv6/ip6t_NPT.h16
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h114
-rw-r--r--include/net/netfilter/nf_nat.h55
24 files changed, 1262 insertions, 257 deletions
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index 1cef239c..e71e3ff9 100644
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -101,10 +101,10 @@ libxt_state.so: libxt_conntrack.so
ln -fs $< $@
# Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD
+ip6t_NETMAP_LIBADD = -lip6tc
xt_RATEEST_LIBADD = -lm
xt_statistic_LIBADD = -lm
-
#
# Static bits
#
diff --git a/extensions/libip6t_DNAT.c b/extensions/libip6t_DNAT.c
new file mode 100644
index 00000000..a5969c36
--- /dev/null
+++ b/extensions/libip6t_DNAT.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Rusty Russell's IPv4 DNAT target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <iptables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/nf_nat.h>
+
+enum {
+ O_TO_DEST = 0,
+ O_RANDOM,
+ O_PERSISTENT,
+ O_X_TO_DEST,
+ F_TO_DEST = 1 << O_TO_DEST,
+ F_RANDOM = 1 << O_RANDOM,
+ F_X_TO_DEST = 1 << O_X_TO_DEST,
+};
+
+static void DNAT_help(void)
+{
+ printf(
+"DNAT target options:\n"
+" --to-dest [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
+" Address to map source to.\n"
+"[--random] [--persistent]\n");
+}
+
+static const struct xt_option_entry DNAT_opts[] = {
+ {.name = "to-dest", .id = O_TO_DEST, .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,
+};
+
+/* Ranges expected in network order. */
+static void
+parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
+{
+ char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
+ const struct in6_addr *ip;
+
+ arg = strdup(orig_arg);
+ if (arg == NULL)
+ xtables_error(RESOURCE_PROBLEM, "strdup");
+
+ start = strchr(arg, '[');
+ if (start == NULL)
+ start = arg;
+ else {
+ start++;
+ end = strchr(start, ']');
+ if (end == NULL)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid address format");
+
+ *end = '\0';
+ colon = strchr(end + 1, ':');
+ }
+
+ if (colon) {
+ int port;
+
+ if (!portok)
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
+
+ range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+
+ port = atoi(colon+1);
+ if (port <= 0 || port > 65535)
+ xtables_error(PARAMETER_PROBLEM,
+ "Port `%s' not valid\n", colon+1);
+
+ error = strchr(colon+1, ':');
+ if (error)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid port:port syntax - use dash\n");
+
+ dash = strchr(colon, '-');
+ if (!dash) {
+ range->min_proto.tcp.port
+ = range->max_proto.tcp.port
+ = htons(port);
+ } else {
+ int maxport;
+
+ maxport = atoi(dash + 1);
+ if (maxport <= 0 || maxport > 65535)
+ xtables_error(PARAMETER_PROBLEM,
+ "Port `%s' not valid\n", dash+1);
+ if (maxport < port)
+ /* People are stupid. */
+ xtables_error(PARAMETER_PROBLEM,
+ "Port range `%s' funky\n", colon+1);
+ range->min_proto.tcp.port = htons(port);
+ range->max_proto.tcp.port = htons(maxport);
+ }
+ /* Starts with a colon? No IP info...*/
+ if (colon == arg) {
+ free(arg);
+ return;
+ }
+ *colon = '\0';
+ }
+
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
+ dash = strchr(start, '-');
+ if (colon && dash && dash > colon)
+ dash = NULL;
+
+ if (dash)
+ *dash = '\0';
+
+ ip = xtables_numeric_to_ip6addr(start);
+ if (!ip)
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+ start);
+ range->min_addr.in6 = *ip;
+ if (dash) {
+ ip = xtables_numeric_to_ip6addr(dash + 1);
+ if (!ip)
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+ dash+1);
+ range->max_addr.in6 = *ip;
+ } else
+ range->max_addr = range->min_addr;
+
+ free(arg);
+ return;
+}
+
+static void DNAT_parse(struct xt_option_call *cb)
+{
+ const struct ip6t_entry *entry = cb->xt_entry;
+ struct nf_nat_range *range = cb->data;
+ int portok;
+
+ if (entry->ipv6.proto == IPPROTO_TCP ||
+ entry->ipv6.proto == IPPROTO_UDP ||
+ entry->ipv6.proto == IPPROTO_SCTP ||
+ entry->ipv6.proto == IPPROTO_DCCP ||
+ entry->ipv6.proto == IPPROTO_ICMP)
+ portok = 1;
+ else
+ portok = 0;
+
+ 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-source not supported");
+ }
+ parse_to(cb->arg, portok, range);
+ break;
+ case O_PERSISTENT:
+ range->flags |= NF_NAT_RANGE_PERSISTENT;
+ break;
+ }
+}
+
+static void DNAT_fcheck(struct xt_fcheck_call *cb)
+{
+ static const unsigned int f = F_TO_DEST | F_RANDOM;
+ struct nf_nat_range *mr = cb->data;
+
+ if ((cb->xflags & f) == f)
+ mr->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+}
+
+static void print_range(const struct nf_nat_range *range)
+{
+ if (range->flags & NF_NAT_RANGE_MAP_IPS) {
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
+ printf("[");
+ printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6));
+ if (memcmp(&range->min_addr, &range->max_addr,
+ sizeof(range->min_addr)))
+ printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6));
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
+ printf("]");
+ }
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(":");
+ printf("%hu", ntohs(range->min_proto.tcp.port));
+ if (range->max_proto.tcp.port != range->min_proto.tcp.port)
+ printf("-%hu", ntohs(range->max_proto.tcp.port));
+ }
+}
+
+static void DNAT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ printf(" to:");
+ print_range(range);
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" random");
+ if (range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" persistent");
+}
+
+static void DNAT_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ printf(" --to-source ");
+ print_range(range);
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" --random");
+ if (range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" --persistent");
+}
+
+static struct xtables_target snat_tg_reg = {
+ .name = "DNAT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = DNAT_help,
+ .x6_parse = DNAT_parse,
+ .x6_fcheck = DNAT_fcheck,
+ .print = DNAT_print,
+ .save = DNAT_save,
+ .x6_options = DNAT_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&snat_tg_reg);
+}
diff --git a/extensions/libip6t_DNPT.c b/extensions/libip6t_DNPT.c
new file mode 100644
index 00000000..9e4dc5cf
--- /dev/null
+++ b/extensions/libip6t_DNPT.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <xtables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_NPT.h>
+
+enum {
+ O_SRC_PFX = 1 << 0,
+ O_DST_PFX = 1 << 1,
+};
+
+static const struct xt_option_entry SNPT_options[] = {
+ { .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND },
+ { .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND },
+ { }
+};
+
+static void SNPT_help(void)
+{
+ printf("SNPT target options:"
+ "\n"
+ " --src-pfx prefix/length\n"
+ " --dst-pfx prefix/length\n"
+ "\n");
+}
+
+static void SNPT_parse(struct xt_option_call *cb)
+{
+ struct ip6t_npt_tginfo *npt = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRC_PFX:
+ npt->src_pfx = cb->val.haddr;
+ npt->src_pfx_len = cb->val.hlen;
+ break;
+ case O_DST_PFX:
+ npt->dst_pfx = cb->val.haddr;
+ npt->dst_pfx_len = cb->val.hlen;
+ break;
+ }
+}
+
+static void SNPT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct ip6t_npt_tginfo *npt = (const void *)target->data;
+
+ printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
+ npt->src_pfx_len);
+ printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
+ npt->dst_pfx_len);
+}
+
+static struct xtables_target snpt_tg_reg = {
+ .name = "DNPT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)),
+ .userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment),
+ .help = SNPT_help,
+ .x6_parse = SNPT_parse,
+ .print = SNPT_print,
+ .x6_options = SNPT_options,
+};
+
+void _init(void)
+{
+ xtables_register_target(&snpt_tg_reg);
+}
diff --git a/extensions/libip6t_MASQUERADE.c b/extensions/libip6t_MASQUERADE.c
new file mode 100644
index 00000000..eb9213ef
--- /dev/null
+++ b/extensions/libip6t_MASQUERADE.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Rusty Russell's IPv4 MASQUERADE target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/nf_nat.h>
+
+enum {
+ O_TO_PORTS = 0,
+ O_RANDOM,
+};
+
+static void MASQUERADE_help(void)
+{
+ printf(
+"MASQUERADE target options:\n"
+" --to-ports <port>[-<port>]\n"
+" Port (range) to map to.\n"
+" --random\n"
+" Randomize source port.\n");
+}
+
+static const struct xt_option_entry MASQUERADE_opts[] = {
+ {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+
+/* Parses ports */
+static void
+parse_ports(const char *arg, struct nf_nat_range *r)
+{
+ char *end;
+ unsigned int port, maxport;
+
+ r->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+
+ if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
+
+ switch (*end) {
+ case '\0':
+ r->min_proto.tcp.port
+ = r->max_proto.tcp.port
+ = htons(port);
+ return;
+ case '-':
+ if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX))
+ break;
+
+ if (maxport < port)
+ break;
+
+ r->min_proto.tcp.port = htons(port);
+ r->max_proto.tcp.port = htons(maxport);
+ return;
+ default:
+ break;
+ }
+ xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
+}
+
+static void MASQUERADE_parse(struct xt_option_call *cb)
+{
+ const struct ip6t_entry *entry = cb->xt_entry;
+ struct nf_nat_range *r = cb->data;
+ int portok;
+
+ if (entry->ipv6.proto == IPPROTO_TCP ||
+ entry->ipv6.proto == IPPROTO_UDP ||
+ entry->ipv6.proto == IPPROTO_SCTP ||
+ entry->ipv6.proto == IPPROTO_DCCP ||
+ entry->ipv6.proto == IPPROTO_ICMP)
+ portok = 1;
+ else
+ portok = 0;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_PORTS:
+ if (!portok)
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
+ parse_ports(cb->arg, r);
+ break;
+ case O_RANDOM:
+ r->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ break;
+ }
+}
+
+static void
+MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *r = (const void *)target->data;
+
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(" masq ports: ");
+ printf("%hu", ntohs(r->min_proto.tcp.port));
+ if (r->max_proto.tcp.port != r->min_proto.tcp.port)
+ printf("-%hu", ntohs(r->max_proto.tcp.port));
+ }
+
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" random");
+}
+
+static void
+MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct nf_nat_range *r = (const void *)target->data;
+
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(" --to-ports %hu", ntohs(r->min_proto.tcp.port));
+ if (r->max_proto.tcp.port != r->min_proto.tcp.port)
+ printf("-%hu", ntohs(r->max_proto.tcp.port));
+ }
+
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" --random");
+}
+
+static struct xtables_target masquerade_tg_reg = {
+ .name = "MASQUERADE",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = MASQUERADE_help,
+ .x6_parse = MASQUERADE_parse,
+ .print = MASQUERADE_print,
+ .save = MASQUERADE_save,
+ .x6_options = MASQUERADE_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&masquerade_tg_reg);
+}
diff --git a/extensions/libip6t_MASQUERADE.man b/extensions/libip6t_MASQUERADE.man
new file mode 100644
index 00000000..c63d826b
--- /dev/null
+++ b/extensions/libip6t_MASQUERADE.man
@@ -0,0 +1,30 @@
+This target is only valid in the
+.B nat
+table, in the
+.B POSTROUTING
+chain. It should only be used with dynamically assigned IPv6 (dialup)
+connections: if you have a static IP address, you should use the SNAT
+target. Masquerading is equivalent to specifying a mapping to the IP
+address of the interface the packet is going out, but also has the
+effect that connections are
+.I forgotten
+when the interface goes down. This is the correct behavior when the
+next dialup is unlikely to have the same interface address (and hence
+any established connections are lost anyway).
+.TP
+\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP]
+This specifies a range of source ports to use, overriding the default
+.B SNAT
+source port-selection heuristics (see above). This is only valid
+if the rule also specifies
+\fB\-p tcp\fP
+or
+\fB\-p udp\fP.
+.TP
+\fB\-\-random\fP
+Randomize source port mapping
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized.
+.RS
+.PP
diff --git a/extensions/libip6t_NETMAP.c b/extensions/libip6t_NETMAP.c
new file mode 100644
index 00000000..d14dece3
--- /dev/null
+++ b/extensions/libip6t_NETMAP.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <libiptc/libip6tc.h>
+#include <linux/netfilter/nf_nat.h>
+
+#define MODULENAME "NETMAP"
+
+enum {
+ O_TO = 0,
+};
+
+static const struct xt_option_entry NETMAP_opts[] = {
+ {.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND},
+ XTOPT_TABLEEND,
+};
+
+static void NETMAP_help(void)
+{
+ printf(MODULENAME" target options:\n"
+ " --%s address[/mask]\n"
+ " Network address to map to.\n\n",
+ NETMAP_opts[0].name);
+}
+
+static void NETMAP_parse(struct xt_option_call *cb)
+{
+ struct nf_nat_range *range = cb->data;
+ unsigned int i;
+
+ xtables_option_parse(cb);
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
+ for (i = 0; i < 4; i++) {
+ range->min_addr.ip6[i] = cb->val.haddr.ip6[i] &
+ cb->val.hmask.ip6[i];
+ range->max_addr.ip6[i] = range->min_addr.ip6[i] |
+ ~cb->val.hmask.ip6[i];
+ }
+}
+
+static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *r = (const void *)target->data;
+ struct in6_addr a;
+ unsigned int i;
+ int bits;
+
+ a = r->min_addr.in6;
+ printf("%s", xtables_ip6addr_to_numeric(&a));
+ for (i = 0; i < 4; i++)
+ a.s6_addr32[i] = ~(r->min_addr.ip6[i] ^ r->max_addr.ip6[i]);
+ bits = ipv6_prefix_length(&a);
+ if (bits < 0)
+ printf("/%s", xtables_ip6addr_to_numeric(&a));
+ else
+ printf("/%d", bits);
+}
+
+static void NETMAP_save(const void *ip, const struct xt_entry_target *target)
+{
+ printf(" --%s ", NETMAP_opts[0].name);
+ NETMAP_print(ip, target, 0);
+}
+
+static struct xtables_target netmap_tg_reg = {
+ .name = MODULENAME,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = NETMAP_help,
+ .x6_parse = NETMAP_parse,
+ .print = NETMAP_print,
+ .save = NETMAP_save,
+ .x6_options = NETMAP_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&netmap_tg_reg);
+}
diff --git a/extensions/libip6t_REDIRECT.c b/extensions/libip6t_REDIRECT.c
new file mode 100644
index 00000000..1724aa67
--- /dev/null
+++ b/extensions/libip6t_REDIRECT.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/nf_nat.h>
+
+enum {
+ O_TO_PORTS = 0,
+ O_RANDOM,
+ F_TO_PORTS = 1 << O_TO_PORTS,
+ F_RANDOM = 1 << O_RANDOM,
+};
+
+static void REDIRECT_help(void)
+{
+ printf(
+"REDIRECT target options:\n"
+" --to-ports <port>[-<port>]\n"
+" Port (range) to map to.\n"
+" [--random]\n");
+}
+
+static const struct xt_option_entry REDIRECT_opts[] = {
+ {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+
+/* Parses ports */
+static void
+parse_ports(const char *arg, struct nf_nat_range *range)
+{
+ char *end = "";
+ unsigned int port, maxport;
+
+ range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+
+ if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) &&
+ (port = xtables_service_to_port(arg, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg);
+
+ switch (*end) {
+ case '\0':
+ range->min_proto.tcp.port
+ = range->max_proto.tcp.port
+ = htons(port);
+ return;
+ case '-':
+ if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) &&
+ (maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1)
+ break;
+
+ if (maxport < port)
+ break;
+
+ range->min_proto.tcp.port = htons(port);
+ range->max_proto.tcp.port = htons(maxport);
+ return;
+ default:
+ break;
+ }
+ xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg);
+}
+
+static void REDIRECT_parse(struct xt_option_call *cb)
+{
+ const struct ip6t_entry *entry = cb->xt_entry;
+ struct nf_nat_range *range = (void *)(*cb->target)->data;
+ int portok;
+
+ if (entry->ipv6.proto == IPPROTO_TCP
+ || entry->ipv6.proto == IPPROTO_UDP
+ || entry->ipv6.proto == IPPROTO_SCTP
+ || entry->ipv6.proto == IPPROTO_DCCP
+ || entry->ipv6.proto == IPPROTO_ICMP)
+ portok = 1;
+ else
+ portok = 0;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_PORTS:
+ if (!portok)
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
+ parse_ports(cb->arg, range);
+ if (cb->xflags & F_RANDOM)
+ range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ break;
+ case O_RANDOM:
+ if (cb->xflags & F_TO_PORTS)
+ range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ break;
+ }
+}
+
+static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(" redir ports ");
+ printf("%hu", ntohs(range->min_proto.tcp.port));
+ if (range->max_proto.tcp.port != range->min_proto.tcp.port)
+ printf("-%hu", ntohs(range->max_proto.tcp.port));
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" random");
+ }
+}
+
+static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(" --to-ports ");
+ printf("%hu", ntohs(range->min_proto.tcp.port));
+ if (range->max_proto.tcp.port != range->min_proto.tcp.port)
+ printf("-%hu", ntohs(range->max_proto.tcp.port));
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" --random");
+ }
+}
+
+static struct xtables_target redirect_tg_reg = {
+ .name = "REDIRECT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = REDIRECT_help,
+ .x6_parse = REDIRECT_parse,
+ .print = REDIRECT_print,
+ .save = REDIRECT_save,
+ .x6_options = REDIRECT_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&redirect_tg_reg);
+}
diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c
new file mode 100644
index 00000000..307be70e
--- /dev/null
+++ b/extensions/libip6t_SNAT.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * Based on Rusty Russell's IPv4 SNAT target. Development of IPv6 NAT
+ * funded by Astaro.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <iptables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/nf_nat.h>
+
+enum {
+ O_TO_SRC = 0,
+ O_RANDOM,
+ O_PERSISTENT,
+ O_X_TO_SRC,
+ F_TO_SRC = 1 << O_TO_SRC,
+ F_RANDOM = 1 << O_RANDOM,
+ F_X_TO_SRC = 1 << O_X_TO_SRC,
+};
+
+static void SNAT_help(void)
+{
+ printf(
+"SNAT target options:\n"
+" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
+" Address to map source to.\n"
+"[--random] [--persistent]\n");
+}
+
+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,
+};
+
+/* Ranges expected in network order. */
+static void
+parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
+{
+ char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
+ const struct in6_addr *ip;
+
+ arg = strdup(orig_arg);
+ if (arg == NULL)
+ xtables_error(RESOURCE_PROBLEM, "strdup");
+
+ start = strchr(arg, '[');
+ if (start == NULL)
+ start = arg;
+ else {
+ start++;
+ end = strchr(start, ']');
+ if (end == NULL)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid address format");
+
+ *end = '\0';
+ colon = strchr(end + 1, ':');
+ }
+
+ if (colon) {
+ int port;
+
+ if (!portok)
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
+
+ range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+
+ port = atoi(colon+1);
+ if (port <= 0 || port > 65535)
+ xtables_error(PARAMETER_PROBLEM,
+ "Port `%s' not valid\n", colon+1);
+
+ error = strchr(colon+1, ':');
+ if (error)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid port:port syntax - use dash\n");
+
+ dash = strchr(colon, '-');
+ if (!dash) {
+ range->min_proto.tcp.port
+ = range->max_proto.tcp.port
+ = htons(port);
+ } else {
+ int maxport;
+
+ maxport = atoi(dash + 1);
+ if (maxport <= 0 || maxport > 65535)
+ xtables_error(PARAMETER_PROBLEM,
+ "Port `%s' not valid\n", dash+1);
+ if (maxport < port)
+ /* People are stupid. */
+ xtables_error(PARAMETER_PROBLEM,
+ "Port range `%s' funky\n", colon+1);
+ range->min_proto.tcp.port = htons(port);
+ range->max_proto.tcp.port = htons(maxport);
+ }
+ /* Starts with a colon? No IP info...*/
+ if (colon == arg) {
+ free(arg);
+ return;
+ }
+ *colon = '\0';
+ }
+
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
+ dash = strchr(start, '-');
+ if (colon && dash && dash > colon)
+ dash = NULL;
+
+ if (dash)
+ *dash = '\0';
+
+ ip = xtables_numeric_to_ip6addr(start);
+ if (!ip)
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+ start);
+ range->min_addr.in6 = *ip;
+ if (dash) {
+ ip = xtables_numeric_to_ip6addr(dash + 1);
+ if (!ip)
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+ dash+1);
+ range->max_addr.in6 = *ip;
+ } else
+ range->max_addr = range->min_addr;
+
+ free(arg);
+ return;
+}
+
+static void SNAT_parse(struct xt_option_call *cb)
+{
+ const struct ip6t_entry *entry = cb->xt_entry;
+ struct nf_nat_range *range = cb->data;
+ int portok;
+
+ if (entry->ipv6.proto == IPPROTO_TCP ||
+ entry->ipv6.proto == IPPROTO_UDP ||
+ entry->ipv6.proto == IPPROTO_SCTP ||
+ entry->ipv6.proto == IPPROTO_DCCP ||
+ entry->ipv6.proto == IPPROTO_ICMP)
+ portok = 1;
+ else
+ portok = 0;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_SRC:
+ if (cb->xflags & F_X_TO_SRC) {
+ if (!kernel_version)
+ get_kernel_version();
+ if (kernel_version > LINUX_VERSION(2, 6, 10))
+ xtables_error(PARAMETER_PROBLEM,
+ "SNAT: Multiple --to-source not supported");
+ }
+ parse_to(cb->arg, portok, range);
+ break;
+ case O_PERSISTENT:
+ range->flags |= NF_NAT_RANGE_PERSISTENT;
+ break;
+ }
+}
+
+static void SNAT_fcheck(struct xt_fcheck_call *cb)
+{
+ static const unsigned int f = F_TO_SRC | F_RANDOM;
+ struct nf_nat_range *range = cb->data;
+
+ if ((cb->xflags & f) == f)
+ range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+}
+
+static void print_range(const struct nf_nat_range *range)
+{
+ if (range->flags & NF_NAT_RANGE_MAP_IPS) {
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
+ printf("[");
+ printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6));
+ if (memcmp(&range->min_addr, &range->max_addr,
+ sizeof(range->min_addr)))
+ printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6));
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
+ printf("]");
+ }
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ printf(":");
+ printf("%hu", ntohs(range->min_proto.tcp.port));
+ if (range->max_proto.tcp.port != range->min_proto.tcp.port)
+ printf("-%hu", ntohs(range->max_proto.tcp.port));
+ }
+}
+
+static void SNAT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ printf(" to:");
+ print_range(range);
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" random");
+ if (range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" persistent");
+}
+
+static void SNAT_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct nf_nat_range *range = (const void *)target->data;
+
+ printf(" --to-source ");
+ print_range(range);
+ if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
+ printf(" --random");
+ if (range->flags & NF_NAT_RANGE_PERSISTENT)
+ printf(" --persistent");
+}
+
+static struct xtables_target snat_tg_reg = {
+ .name = "SNAT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = SNAT_help,
+ .x6_parse = SNAT_parse,
+ .x6_fcheck = SNAT_fcheck,
+ .print = SNAT_print,
+ .save = SNAT_save,
+ .x6_options = SNAT_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&snat_tg_reg);
+}
diff --git a/extensions/libip6t_SNPT.c b/extensions/libip6t_SNPT.c
new file mode 100644
index 00000000..26a86c56
--- /dev/null
+++ b/extensions/libip6t_SNPT.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <xtables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_NPT.h>
+
+enum {
+ O_SRC_PFX = 1 << 0,
+ O_DST_PFX = 1 << 1,
+};
+
+static const struct xt_option_entry SNPT_options[] = {
+ { .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND },
+ { .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_MAND },
+ { }
+};
+
+static void SNPT_help(void)
+{
+ printf("SNPT target options:"
+ "\n"
+ " --src-pfx prefix/length\n"
+ " --dst-pfx prefix/length\n"
+ "\n");
+}
+
+static void SNPT_parse(struct xt_option_call *cb)
+{
+ struct ip6t_npt_tginfo *npt = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRC_PFX:
+ npt->src_pfx = cb->val.haddr;
+ npt->src_pfx_len = cb->val.hlen;
+ break;
+ case O_DST_PFX:
+ npt->dst_pfx = cb->val.haddr;
+ npt->dst_pfx_len = cb->val.hlen;
+ break;
+ }
+}
+
+static void SNPT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct ip6t_npt_tginfo *npt = (const void *)target->data;
+
+ printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
+ npt->src_pfx_len);
+ printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
+ npt->dst_pfx_len);
+}
+
+static struct xtables_target snpt_tg_reg = {
+ .name = "SNPT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)),
+ .userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment),
+ .help = SNPT_help,
+ .x6_parse = SNPT_parse,
+ .print = SNPT_print,
+ .x6_options = SNPT_options,
+};
+
+void _init(void)
+{
+ xtables_register_target(&snpt_tg_reg);
+}
diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c
index 466c9def..ff187999 100644
--- a/extensions/libipt_DNAT.c
+++ b/extensions/libipt_DNAT.c
@@ -6,7 +6,7 @@
#include <iptables.h> /* get_kernel_version */
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
enum {
O_TO_DEST = 0,
@@ -23,7 +23,7 @@ enum {
struct ipt_natinfo
{
struct xt_entry_target t;
- struct nf_nat_multi_range mr;
+ struct nf_nat_ipv4_multi_range_compat mr;
};
static void DNAT_help(void)
@@ -44,7 +44,7 @@ static const struct xt_option_entry DNAT_opts[] = {
};
static struct ipt_natinfo *
-append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
+append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range)
{
unsigned int size;
@@ -66,7 +66,7 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
static struct xt_entry_target *
parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
{
- struct nf_nat_range range;
+ struct nf_nat_ipv4_range range;
char *arg, *colon, *dash, *error;
const struct in_addr *ip;
@@ -83,7 +83,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 |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
port = atoi(colon+1);
if (port <= 0 || port > 65535)
@@ -122,7 +122,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
*colon = '\0';
}
- range.flags |= IP_NAT_RANGE_MAP_IPS;
+ range.flags |= NF_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
if (colon && dash && dash > colon)
dash = NULL;
@@ -177,7 +177,7 @@ static void DNAT_parse(struct xt_option_call *cb)
cb->xflags |= F_X_TO_DEST;
break;
case O_PERSISTENT:
- info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT;
+ info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT;
break;
}
}
@@ -185,15 +185,15 @@ static void DNAT_parse(struct xt_option_call *cb)
static void DNAT_fcheck(struct xt_fcheck_call *cb)
{
static const unsigned int f = F_TO_DEST | F_RANDOM;
- struct nf_nat_multi_range *mr = cb->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
if ((cb->xflags & f) == f)
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
}
-static void print_range(const struct nf_nat_range *r)
+static void print_range(const struct nf_nat_ipv4_range *r)
{
- if (r->flags & IP_NAT_RANGE_MAP_IPS) {
+ if (r->flags & NF_NAT_RANGE_MAP_IPS) {
struct in_addr a;
a.s_addr = r->min_ip;
@@ -203,7 +203,7 @@ static void print_range(const struct nf_nat_range *r)
printf("-%s", xtables_ipaddr_to_numeric(&a));
}
}
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(":");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
@@ -220,9 +220,9 @@ static void DNAT_print(const void *ip, const struct xt_entry_target *target,
printf(" to:");
for (i = 0; i < info->mr.rangesize; i++) {
print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
- if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" persistent");
}
}
@@ -235,9 +235,9 @@ static void DNAT_save(const void *ip, const struct xt_entry_target *target)
for (i = 0; i < info->mr.rangesize; i++) {
printf(" --to-destination ");
print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
- if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" --persistent");
}
}
@@ -246,8 +246,8 @@ static struct xtables_target dnat_tg_reg = {
.name = "DNAT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = DNAT_help,
.x6_parse = DNAT_parse,
.x6_fcheck = DNAT_fcheck,
diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c
index 7ba42dfd..ea074454 100644
--- a/extensions/libipt_MASQUERADE.c
+++ b/extensions/libipt_MASQUERADE.c
@@ -6,7 +6,7 @@
#include <xtables.h>
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
enum {
O_TO_PORTS = 0,
@@ -31,7 +31,7 @@ static const struct xt_option_entry MASQUERADE_opts[] = {
static void MASQUERADE_init(struct xt_entry_target *t)
{
- struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
@@ -39,12 +39,12 @@ static void MASQUERADE_init(struct xt_entry_target *t)
/* Parses ports */
static void
-parse_ports(const char *arg, struct nf_nat_multi_range *mr)
+parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr)
{
char *end;
unsigned int port, maxport;
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
@@ -75,7 +75,7 @@ static void MASQUERADE_parse(struct xt_option_call *cb)
{
const struct ipt_entry *entry = cb->xt_entry;
int portok;
- struct nf_nat_multi_range *mr = cb->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
if (entry->ip.proto == IPPROTO_TCP
|| entry->ip.proto == IPPROTO_UDP
@@ -95,7 +95,7 @@ static void MASQUERADE_parse(struct xt_option_call *cb)
parse_ports(cb->arg, mr);
break;
case O_RANDOM:
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
}
}
@@ -104,33 +104,33 @@ static void
MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(" masq ports: ");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
}
- if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
}
static void
MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(" --to-ports %hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
}
- if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
}
@@ -138,8 +138,8 @@ static struct xtables_target masquerade_tg_reg = {
.name = "MASQUERADE",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = MASQUERADE_help,
.init = MASQUERADE_init,
.x6_parse = MASQUERADE_parse,
diff --git a/extensions/libipt_NETMAP.c b/extensions/libipt_NETMAP.c
index 5c4471a9..dee7b01b 100644
--- a/extensions/libipt_NETMAP.c
+++ b/extensions/libipt_NETMAP.c
@@ -7,7 +7,7 @@
#include <stdlib.h>
#include <getopt.h>
#include <xtables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
#define MODULENAME "NETMAP"
@@ -45,7 +45,7 @@ netmask2bits(uint32_t netmask)
static void NETMAP_init(struct xt_entry_target *t)
{
- struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
@@ -53,11 +53,11 @@ static void NETMAP_init(struct xt_entry_target *t)
static void NETMAP_parse(struct xt_option_call *cb)
{
- struct nf_nat_multi_range *mr = cb->data;
- struct nf_nat_range *range = &mr->range[0];
+ struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
+ struct nf_nat_ipv4_range *range = &mr->range[0];
xtables_option_parse(cb);
- range->flags |= IP_NAT_RANGE_MAP_IPS;
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip;
range->max_ip = range->min_ip | ~cb->val.hmask.ip;
}
@@ -65,8 +65,8 @@ static void NETMAP_parse(struct xt_option_call *cb)
static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
struct in_addr a;
int bits;
@@ -90,8 +90,8 @@ static struct xtables_target netmap_tg_reg = {
.name = MODULENAME,
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = NETMAP_help,
.init = NETMAP_init,
.x6_parse = NETMAP_parse,
diff --git a/extensions/libipt_REDIRECT.c b/extensions/libipt_REDIRECT.c
index e67360a0..610a9499 100644
--- a/extensions/libipt_REDIRECT.c
+++ b/extensions/libipt_REDIRECT.c
@@ -4,7 +4,7 @@
#include <xtables.h>
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
enum {
O_TO_PORTS = 0,
@@ -30,7 +30,7 @@ static const struct xt_option_entry REDIRECT_opts[] = {
static void REDIRECT_init(struct xt_entry_target *t)
{
- struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
@@ -38,12 +38,12 @@ static void REDIRECT_init(struct xt_entry_target *t)
/* Parses ports */
static void
-parse_ports(const char *arg, struct nf_nat_multi_range *mr)
+parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr)
{
char *end = "";
unsigned int port, maxport;
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) &&
(port = xtables_service_to_port(arg, NULL)) == (unsigned)-1)
@@ -75,7 +75,7 @@ parse_ports(const char *arg, struct nf_nat_multi_range *mr)
static void REDIRECT_parse(struct xt_option_call *cb)
{
const struct ipt_entry *entry = cb->xt_entry;
- struct nf_nat_multi_range *mr = (void *)(*cb->target)->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = (void *)(*cb->target)->data;
int portok;
if (entry->ip.proto == IPPROTO_TCP
@@ -95,11 +95,11 @@ static void REDIRECT_parse(struct xt_option_call *cb)
"Need TCP, UDP, SCTP or DCCP with port specification");
parse_ports(cb->arg, mr);
if (cb->xflags & F_RANDOM)
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
case O_RANDOM:
if (cb->xflags & F_TO_PORTS)
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
}
}
@@ -107,30 +107,30 @@ static void REDIRECT_parse(struct xt_option_call *cb)
static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(" redir ports ");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
- if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
}
}
static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
{
- const struct nf_nat_multi_range *mr = (const void *)target->data;
- const struct nf_nat_range *r = &mr->range[0];
+ const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
+ const struct nf_nat_ipv4_range *r = &mr->range[0];
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(" --to-ports ");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
- if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
}
}
@@ -139,8 +139,8 @@ static struct xtables_target redirect_tg_reg = {
.name = "REDIRECT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = REDIRECT_help,
.init = REDIRECT_init,
.x6_parse = REDIRECT_parse,
diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c
index e603ef64..5d5bf630 100644
--- a/extensions/libipt_SAME.c
+++ b/extensions/libipt_SAME.c
@@ -2,7 +2,7 @@
#include <string.h>
#include <stdlib.h>
#include <xtables.h>
-#include <net/netfilter/nf_nat.h>
+#include <linux/netfilter/nf_nat.h>
#include <linux/netfilter_ipv4/ipt_SAME.h>
enum {
@@ -37,7 +37,7 @@ static const struct xt_option_entry SAME_opts[] = {
};
/* Parses range of IPs */
-static void parse_to(const char *orig_arg, struct nf_nat_range *range)
+static void parse_to(const char *orig_arg, struct nf_nat_ipv4_range *range)
{
char *dash, *arg;
const struct in_addr *ip;
@@ -45,7 +45,7 @@ static void parse_to(const char *orig_arg, struct nf_nat_range *range)
arg = strdup(orig_arg);
if (arg == NULL)
xtables_error(RESOURCE_PROBLEM, "strdup");
- range->flags |= IP_NAT_RANGE_MAP_IPS;
+ range->flags |= NF_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
if (dash)
@@ -74,6 +74,7 @@ static void parse_to(const char *orig_arg, struct nf_nat_range *range)
static void SAME_parse(struct xt_option_call *cb)
{
struct ipt_same_info *mr = cb->data;
+ unsigned int count;
xtables_option_parse(cb);
switch (cb->entry->id) {
@@ -89,6 +90,10 @@ static void SAME_parse(struct xt_option_call *cb)
case O_NODST:
mr->info |= IPT_SAME_NODST;
break;
+ case O_RANDOM:
+ for (count=0; count < mr->rangesize; count++)
+ mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ break;
}
}
@@ -100,7 +105,7 @@ static void SAME_fcheck(struct xt_fcheck_call *cb)
if ((cb->xflags & f) == f)
for (count = 0; count < mr->rangesize; ++count)
- mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
}
static void SAME_print(const void *ip, const struct xt_entry_target *target,
@@ -113,7 +118,7 @@ static void SAME_print(const void *ip, const struct xt_entry_target *target,
printf(" same:");
for (count = 0; count < mr->rangesize; count++) {
- const struct nf_nat_range *r = &mr->range[count];
+ const struct nf_nat_ipv4_range *r = &mr->range[count];
struct in_addr a;
a.s_addr = r->min_ip;
@@ -123,7 +128,7 @@ static void SAME_print(const void *ip, const struct xt_entry_target *target,
if (r->min_ip != r->max_ip)
printf("-%s", xtables_ipaddr_to_numeric(&a));
- if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
random_selection = 1;
}
@@ -141,7 +146,7 @@ static void SAME_save(const void *ip, const struct xt_entry_target *target)
int random_selection = 0;
for (count = 0; count < mr->rangesize; count++) {
- const struct nf_nat_range *r = &mr->range[count];
+ const struct nf_nat_ipv4_range *r = &mr->range[count];
struct in_addr a;
a.s_addr = r->min_ip;
@@ -150,7 +155,7 @@ static void SAME_save(const void *ip, const struct xt_entry_target *target)
if (r->min_ip != r->max_ip)
printf("-%s", xtables_ipaddr_to_numeric(&a));
- if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
random_selection = 1;
}
diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c
index c8cb26df..1a24f3d8 100644
--- a/extensions/libipt_SNAT.c
+++ b/extensions/libipt_SNAT.c
@@ -6,7 +6,7 @@
#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>
+#include <linux/netfilter/nf_nat.h>
enum {
O_TO_SRC = 0,
@@ -23,7 +23,7 @@ enum {
struct ipt_natinfo
{
struct xt_entry_target t;
- struct nf_nat_multi_range mr;
+ struct nf_nat_ipv4_multi_range_compat mr;
};
static void SNAT_help(void)
@@ -44,7 +44,7 @@ static const struct xt_option_entry SNAT_opts[] = {
};
static struct ipt_natinfo *
-append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
+append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range)
{
unsigned int size;
@@ -66,7 +66,7 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
static struct xt_entry_target *
parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
{
- struct nf_nat_range range;
+ struct nf_nat_ipv4_range range;
char *arg, *colon, *dash, *error;
const struct in_addr *ip;
@@ -83,7 +83,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 |= IP_NAT_RANGE_PROTO_SPECIFIED;
+ range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
port = atoi(colon+1);
if (port <= 0 || port > 65535)
@@ -122,7 +122,7 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
*colon = '\0';
}
- range.flags |= IP_NAT_RANGE_MAP_IPS;
+ range.flags |= NF_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
if (colon && dash && dash > colon)
dash = NULL;
@@ -177,7 +177,7 @@ static void SNAT_parse(struct xt_option_call *cb)
cb->xflags |= F_X_TO_SRC;
break;
case O_PERSISTENT:
- info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT;
+ info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT;
break;
}
}
@@ -185,15 +185,15 @@ static void SNAT_parse(struct xt_option_call *cb)
static void SNAT_fcheck(struct xt_fcheck_call *cb)
{
static const unsigned int f = F_TO_SRC | F_RANDOM;
- struct nf_nat_multi_range *mr = cb->data;
+ struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
if ((cb->xflags & f) == f)
- mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
}
-static void print_range(const struct nf_nat_range *r)
+static void print_range(const struct nf_nat_ipv4_range *r)
{
- if (r->flags & IP_NAT_RANGE_MAP_IPS) {
+ if (r->flags & NF_NAT_RANGE_MAP_IPS) {
struct in_addr a;
a.s_addr = r->min_ip;
@@ -203,7 +203,7 @@ static void print_range(const struct nf_nat_range *r)
printf("-%s", xtables_ipaddr_to_numeric(&a));
}
}
- if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+ if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
printf(":");
printf("%hu", ntohs(r->min.tcp.port));
if (r->max.tcp.port != r->min.tcp.port)
@@ -220,9 +220,9 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target,
printf(" to:");
for (i = 0; i < info->mr.rangesize; i++) {
print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
- if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" persistent");
}
}
@@ -235,9 +235,9 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target)
for (i = 0; i < info->mr.rangesize; i++) {
printf(" --to-source ");
print_range(&info->mr.range[i]);
- if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
- if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" --persistent");
}
}
@@ -246,8 +246,8 @@ static struct xtables_target snat_tg_reg = {
.name = "SNAT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
.help = SNAT_help,
.x6_parse = SNAT_parse,
.x6_fcheck = SNAT_fcheck,
diff --git a/extensions/libxt_time.c b/extensions/libxt_time.c
index 44c05b8f..9c5bda88 100644
--- a/extensions/libxt_time.c
+++ b/extensions/libxt_time.c
@@ -22,6 +22,7 @@ enum {
O_DATE_STOP,
O_TIME_START,
O_TIME_STOP,
+ O_TIME_CONTIGUOUS,
O_MONTHDAYS,
O_WEEKDAYS,
O_LOCAL_TZ,
@@ -30,6 +31,7 @@ enum {
F_LOCAL_TZ = 1 << O_LOCAL_TZ,
F_UTC = 1 << O_UTC,
F_KERNEL_TZ = 1 << O_KERNEL_TZ,
+ F_TIME_CONTIGUOUS = 1 << O_TIME_CONTIGUOUS,
};
static const char *const week_days[] = {
@@ -41,6 +43,7 @@ static const struct xt_option_entry time_opts[] = {
{.name = "datestop", .id = O_DATE_STOP, .type = XTTYPE_STRING},
{.name = "timestart", .id = O_TIME_START, .type = XTTYPE_STRING},
{.name = "timestop", .id = O_TIME_STOP, .type = XTTYPE_STRING},
+ {.name = "contiguous", .id = O_TIME_CONTIGUOUS, .type = XTTYPE_NONE},
{.name = "weekdays", .id = O_WEEKDAYS, .type = XTTYPE_STRING,
.flags = XTOPT_INVERT},
{.name = "monthdays", .id = O_MONTHDAYS, .type = XTTYPE_STRING,
@@ -273,6 +276,9 @@ static void time_parse(struct xt_option_call *cb)
case O_TIME_STOP:
info->daytime_stop = time_parse_minutes(cb->arg);
break;
+ case O_TIME_CONTIGUOUS:
+ info->flags |= XT_TIME_CONTIGUOUS;
+ break;
case O_LOCAL_TZ:
fprintf(stderr, "WARNING: --localtz is being replaced by "
"--kerneltz, since \"local\" is ambiguous. Note the "
@@ -403,6 +409,8 @@ static void time_print(const void *ip, const struct xt_entry_match *match,
}
if (!(info->flags & XT_TIME_LOCAL_TZ))
printf(" UTC");
+ if (info->flags & XT_TIME_CONTIGUOUS)
+ printf(" contiguous");
}
static void time_save(const void *ip, const struct xt_entry_match *match)
@@ -429,6 +437,17 @@ static void time_save(const void *ip, const struct xt_entry_match *match)
time_print_date(info->date_stop, "--datestop");
if (info->flags & XT_TIME_LOCAL_TZ)
printf(" --kerneltz");
+ if (info->flags & XT_TIME_CONTIGUOUS)
+ printf(" --contiguous");
+}
+
+static void time_check(struct xt_fcheck_call *cb)
+{
+ const struct xt_time_info *info = (const void *) cb->data;
+ if ((cb->xflags & F_TIME_CONTIGUOUS) &&
+ info->daytime_start < info->daytime_stop)
+ xtables_error(PARAMETER_PROBLEM,
+ "time: --contiguous only makes sense when stoptime is smaller than starttime");
}
static struct xtables_match time_match = {
@@ -442,6 +461,7 @@ static struct xtables_match time_match = {
.print = time_print,
.save = time_save,
.x6_parse = time_parse,
+ .x6_fcheck = time_check,
.x6_options = time_opts,
};
diff --git a/extensions/libxt_time.man b/extensions/libxt_time.man
index 1d677b94..4c0cae06 100644
--- a/extensions/libxt_time.man
+++ b/extensions/libxt_time.man
@@ -30,6 +30,10 @@ Only match on the given weekdays. Possible values are \fBMon\fP, \fBTue\fP,
to \fB7\fP, respectively. You may also use two-character variants (\fBMo\fP,
\fBTu\fP, etc.).
.TP
+\fB\-\-contiguous\fP
+When \fB\-\-timestop\fP is smaller than \fB\-\-timestart\fP value, match
+this as a single time period instead distinct intervals. See EXAMPLES.
+.TP
\fB\-\-kerneltz\fP
Use the kernel timezone instead of UTC to determine whether a packet meets the
time regulations.
@@ -84,3 +88,11 @@ The fourth Friday in the month:
(Note that this exploits a certain mathematical property. It is not possible to
say "fourth Thursday OR fourth Friday" in one rule. It is possible with
multiple rules, though.)
+.PP
+Matching across days might not do what is expected. For instance,
+.IP
+\-m time \-\-weekdays Mo \-\-timestart 23:00 \-\-timestop 01:00
+Will match Monday, for one hour from midnight to 1 a.m., and then
+again for another hour from 23:00 onwards. If this is unwanted, e.g. if you
+would like 'match for two hours from Montay 23:00 onwards' you need to also specify
+the \-\-contiguous option in the example above.
diff --git a/include/linux/netfilter/nf_conntrack_tuple_common.h b/include/linux/netfilter/nf_conntrack_tuple_common.h
index 2ea22b01..2f6bbc5b 100644
--- a/include/linux/netfilter/nf_conntrack_tuple_common.h
+++ b/include/linux/netfilter/nf_conntrack_tuple_common.h
@@ -7,6 +7,33 @@ enum ip_conntrack_dir {
IP_CT_DIR_MAX
};
+/* The protocol-specific manipulable parts of the tuple: always in
+ * network order
+ */
+union nf_conntrack_man_proto {
+ /* Add other protocols here. */
+ __be16 all;
+
+ struct {
+ __be16 port;
+ } tcp;
+ struct {
+ __be16 port;
+ } udp;
+ struct {
+ __be16 id;
+ } icmp;
+ struct {
+ __be16 port;
+ } dccp;
+ struct {
+ __be16 port;
+ } sctp;
+ struct {
+ __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
+ } gre;
+};
+
#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
#endif /* _NF_CONNTRACK_TUPLE_COMMON_H */
diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h
new file mode 100644
index 00000000..bf0cc373
--- /dev/null
+++ b/include/linux/netfilter/nf_nat.h
@@ -0,0 +1,33 @@
+#ifndef _NETFILTER_NF_NAT_H
+#define _NETFILTER_NF_NAT_H
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+
+#define NF_NAT_RANGE_MAP_IPS 1
+#define NF_NAT_RANGE_PROTO_SPECIFIED 2
+#define NF_NAT_RANGE_PROTO_RANDOM 4
+#define NF_NAT_RANGE_PERSISTENT 8
+
+struct nf_nat_ipv4_range {
+ unsigned int flags;
+ __be32 min_ip;
+ __be32 max_ip;
+ union nf_conntrack_man_proto min;
+ union nf_conntrack_man_proto max;
+};
+
+struct nf_nat_ipv4_multi_range_compat {
+ unsigned int rangesize;
+ struct nf_nat_ipv4_range range[1];
+};
+
+struct nf_nat_range {
+ unsigned int flags;
+ union nf_inet_addr min_addr;
+ union nf_inet_addr max_addr;
+ union nf_conntrack_man_proto min_proto;
+ union nf_conntrack_man_proto max_proto;
+};
+
+#endif /* _NETFILTER_NF_NAT_H */
diff --git a/include/linux/netfilter/xt_time.h b/include/linux/netfilter/xt_time.h
index 7c37fac5..a21d5bf8 100644
--- a/include/linux/netfilter/xt_time.h
+++ b/include/linux/netfilter/xt_time.h
@@ -16,6 +16,7 @@ struct xt_time_info {
enum {
/* Match against local time (instead of UTC) */
XT_TIME_LOCAL_TZ = 1 << 0,
+ XT_TIME_CONTIGUOUS = 1 << 1,
/* Shortcuts */
XT_TIME_ALL_MONTHDAYS = 0xFFFFFFFE,
diff --git a/include/linux/netfilter_ipv4/ipt_SAME.h b/include/linux/netfilter_ipv4/ipt_SAME.h
index 5bca7826..a8551671 100644
--- a/include/linux/netfilter_ipv4/ipt_SAME.h
+++ b/include/linux/netfilter_ipv4/ipt_SAME.h
@@ -14,7 +14,7 @@ struct ipt_same_info {
__u32 *iparray;
/* hangs off end. */
- struct nf_nat_range range[IPT_SAME_MAX_RANGE];
+ struct nf_nat_ipv4_range range[IPT_SAME_MAX_RANGE];
};
#endif /*_IPT_SAME_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_NPT.h b/include/linux/netfilter_ipv6/ip6t_NPT.h
new file mode 100644
index 00000000..f7633554
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_NPT.h
@@ -0,0 +1,16 @@
+#ifndef __NETFILTER_IP6T_NPT
+#define __NETFILTER_IP6T_NPT
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+
+struct ip6t_npt_tginfo {
+ union nf_inet_addr src_pfx;
+ union nf_inet_addr dst_pfx;
+ __u8 src_pfx_len;
+ __u8 dst_pfx_len;
+ /* Used internally by the kernel */
+ __sum16 adjustment;
+};
+
+#endif /* __NETFILTER_IP6T_NPT */
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
deleted file mode 100644
index c40e0b40..00000000
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* This file was manually copied from the Linux kernel source
- * and manually stripped from __KERNEL__ sections and unused functions.
- */
-
-/*
- * Definitions and Declarations for tuple.
- *
- * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
- * - generalize L3 protocol dependent part.
- *
- * Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h
- */
-
-#ifndef _NF_CONNTRACK_TUPLE_H
-#define _NF_CONNTRACK_TUPLE_H
-
-#include <linux/netfilter/x_tables.h>
-#include <linux/netfilter/nf_conntrack_tuple_common.h>
-
-/* A `tuple' is a structure containing the information to uniquely
- identify a connection. ie. if two packets have the same tuple, they
- are in the same connection; if not, they are not.
-
- We divide the structure along "manipulatable" and
- "non-manipulatable" lines, for the benefit of the NAT code.
-*/
-
-#define NF_CT_TUPLE_L3SIZE ARRAY_SIZE(((union nf_inet_addr *)NULL)->all)
-
-/* The protocol-specific manipulable parts of the tuple: always in
- network order! */
-union nf_conntrack_man_proto
-{
- /* Add other protocols here. */
- __be16 all;
-
- struct {
- __be16 port;
- } tcp;
- struct {
- __be16 port;
- } udp;
- struct {
- __be16 id;
- } icmp;
- struct {
- __be16 port;
- } dccp;
- struct {
- __be16 port;
- } sctp;
- struct {
- __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
- } gre;
-};
-
-/* The manipulable part of the tuple. */
-struct nf_conntrack_man
-{
- union nf_inet_addr u3;
- union nf_conntrack_man_proto u;
- /* Layer 3 protocol */
- u_int16_t l3num;
-};
-
-/* This contains the information to distinguish a connection. */
-struct nf_conntrack_tuple
-{
- struct nf_conntrack_man src;
-
- /* These are the parts of the tuple which are fixed. */
- struct {
- union nf_inet_addr u3;
- union {
- /* Add other protocols here. */
- __be16 all;
-
- struct {
- __be16 port;
- } tcp;
- struct {
- __be16 port;
- } udp;
- struct {
- u_int8_t type, code;
- } icmp;
- struct {
- __be16 port;
- } dccp;
- struct {
- __be16 port;
- } sctp;
- struct {
- __be16 key;
- } gre;
- } u;
-
- /* The protocol. */
- u_int8_t protonum;
-
- /* The direction (for tuplehash) */
- u_int8_t dir;
- } dst;
-};
-
-struct nf_conntrack_tuple_mask
-{
- struct {
- union nf_inet_addr u3;
- union nf_conntrack_man_proto u;
- } src;
-};
-
-#endif /* _NF_CONNTRACK_TUPLE_H */
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
deleted file mode 100644
index c3e2060c..00000000
--- a/include/net/netfilter/nf_nat.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _NF_NAT_H
-#define _NF_NAT_H
-#include <linux/netfilter_ipv4.h>
-#include <net/netfilter/nf_conntrack_tuple.h>
-
-#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16
-
-enum nf_nat_manip_type
-{
- IP_NAT_MANIP_SRC,
- IP_NAT_MANIP_DST
-};
-
-/* SRC manip occurs POST_ROUTING or LOCAL_IN */
-#define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \
- (hooknum) != NF_INET_LOCAL_IN)
-
-#define IP_NAT_RANGE_MAP_IPS 1
-#define IP_NAT_RANGE_PROTO_SPECIFIED 2
-#define IP_NAT_RANGE_PROTO_RANDOM 4
-#define IP_NAT_RANGE_PERSISTENT 8
-
-/* NAT sequence number modifications */
-struct nf_nat_seq {
- /* position of the last TCP sequence number modification (if any) */
- u_int32_t correction_pos;
-
- /* sequence number offset before and after last modification */
- int16_t offset_before, offset_after;
-};
-
-/* Single range specification. */
-struct nf_nat_range
-{
- /* Set to OR of flags above. */
- unsigned int flags;
-
- /* Inclusive: network order. */
- __be32 min_ip, max_ip;
-
- /* Inclusive: network order */
- union nf_conntrack_man_proto min, max;
-};
-
-/* For backwards compat: don't use in modern code. */
-struct nf_nat_multi_range_compat
-{
- unsigned int rangesize; /* Must be 1. */
-
- /* hangs off end. */
- struct nf_nat_range range[1];
-};
-
-#define nf_nat_multi_range nf_nat_multi_range_compat
-#endif