|
|
7d290b |
From c1874130f845e526de76d116639c044cb30fcc9a Mon Sep 17 00:00:00 2001
|
|
|
7d290b |
From: Neil Wilson <neil@aldur.co.uk>
|
|
|
7d290b |
Date: Thu, 16 Mar 2017 11:49:03 +0000
|
|
|
7d290b |
Subject: [PATCH] conntrack: Support IPv6 NAT
|
|
|
7d290b |
|
|
|
7d290b |
Refactor and improve nat support to allow conntrack to manage IPv6
|
|
|
7d290b |
NAT entries.
|
|
|
7d290b |
|
|
|
7d290b |
Refactor and improve conntrack nat tests to include IPv6 NAT.
|
|
|
7d290b |
|
|
|
7d290b |
Signed-off-by: Neil Wilson <neil@aldur.co.uk>
|
|
|
7d290b |
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
|
|
7d290b |
(cherry picked from commit 29b390a2122143997a651e6b25d7496e62ead2a1)
|
|
|
7d290b |
---
|
|
|
7d290b |
src/conntrack.c | 213 ++++++++++++++++++++---------
|
|
|
7d290b |
tests/conntrack/testsuite/00create | 6 +
|
|
|
7d290b |
tests/conntrack/testsuite/03nat | 8 ++
|
|
|
7d290b |
tests/conntrack/testsuite/07nat6 | 56 ++++++++
|
|
|
7d290b |
4 files changed, 216 insertions(+), 67 deletions(-)
|
|
|
7d290b |
create mode 100644 tests/conntrack/testsuite/07nat6
|
|
|
7d290b |
|
|
|
7d290b |
diff --git a/src/conntrack.c b/src/conntrack.c
|
|
|
7d290b |
index ff030fe54e103..cbf03c7be8834 100644
|
|
|
7d290b |
--- a/src/conntrack.c
|
|
|
7d290b |
+++ b/src/conntrack.c
|
|
|
7d290b |
@@ -43,6 +43,8 @@
|
|
|
7d290b |
#include <stdio.h>
|
|
|
7d290b |
#include <getopt.h>
|
|
|
7d290b |
#include <stdlib.h>
|
|
|
7d290b |
+#include <ctype.h>
|
|
|
7d290b |
+#include <limits.h>
|
|
|
7d290b |
#include <stdarg.h>
|
|
|
7d290b |
#include <errno.h>
|
|
|
7d290b |
#include <unistd.h>
|
|
|
7d290b |
@@ -437,6 +439,9 @@ static const int opt2type[] = {
|
|
|
7d290b |
static const int opt2maskopt[] = {
|
|
|
7d290b |
['s'] = '{',
|
|
|
7d290b |
['d'] = '}',
|
|
|
7d290b |
+ ['g'] = 0,
|
|
|
7d290b |
+ ['j'] = 0,
|
|
|
7d290b |
+ ['n'] = 0,
|
|
|
7d290b |
['r'] = 0, /* no netmask */
|
|
|
7d290b |
['q'] = 0, /* support yet */
|
|
|
7d290b |
['{'] = 0,
|
|
|
7d290b |
@@ -448,6 +453,8 @@ static const int opt2maskopt[] = {
|
|
|
7d290b |
static const int opt2family_attr[][2] = {
|
|
|
7d290b |
['s'] = { ATTR_ORIG_IPV4_SRC, ATTR_ORIG_IPV6_SRC },
|
|
|
7d290b |
['d'] = { ATTR_ORIG_IPV4_DST, ATTR_ORIG_IPV6_DST },
|
|
|
7d290b |
+ ['g'] = { ATTR_DNAT_IPV4, ATTR_DNAT_IPV6 },
|
|
|
7d290b |
+ ['n'] = { ATTR_SNAT_IPV4, ATTR_SNAT_IPV6 },
|
|
|
7d290b |
['r'] = { ATTR_REPL_IPV4_SRC, ATTR_REPL_IPV6_SRC },
|
|
|
7d290b |
['q'] = { ATTR_REPL_IPV4_DST, ATTR_REPL_IPV6_DST },
|
|
|
7d290b |
['{'] = { ATTR_ORIG_IPV4_SRC, ATTR_ORIG_IPV6_SRC },
|
|
|
7d290b |
@@ -459,6 +466,8 @@ static const int opt2family_attr[][2] = {
|
|
|
7d290b |
static const int opt2attr[] = {
|
|
|
7d290b |
['s'] = ATTR_ORIG_L3PROTO,
|
|
|
7d290b |
['d'] = ATTR_ORIG_L3PROTO,
|
|
|
7d290b |
+ ['g'] = ATTR_ORIG_L3PROTO,
|
|
|
7d290b |
+ ['n'] = ATTR_ORIG_L3PROTO,
|
|
|
7d290b |
['r'] = ATTR_REPL_L3PROTO,
|
|
|
7d290b |
['q'] = ATTR_REPL_L3PROTO,
|
|
|
7d290b |
['{'] = ATTR_ORIG_L3PROTO,
|
|
|
7d290b |
@@ -1094,58 +1103,85 @@ parse_addr(const char *cp, union ct_address *address, int *mask)
|
|
|
7d290b |
return family;
|
|
|
7d290b |
}
|
|
|
7d290b |
|
|
|
7d290b |
-static void
|
|
|
7d290b |
-nat_parse(char *arg, struct nf_conntrack *obj, int type)
|
|
|
7d290b |
+static bool
|
|
|
7d290b |
+valid_port(char *cursor)
|
|
|
7d290b |
{
|
|
|
7d290b |
- char *colon, *error;
|
|
|
7d290b |
- union ct_address parse;
|
|
|
7d290b |
+ const char *str = cursor;
|
|
|
7d290b |
+ /* Missing port number */
|
|
|
7d290b |
+ if (!*str)
|
|
|
7d290b |
+ return false;
|
|
|
7d290b |
|
|
|
7d290b |
- colon = strchr(arg, ':');
|
|
|
7d290b |
+ /* Must be entirely digits - no spaces or +/- */
|
|
|
7d290b |
+ while (*cursor) {
|
|
|
7d290b |
+ if (!isdigit(*cursor))
|
|
|
7d290b |
+ return false;
|
|
|
7d290b |
+ else
|
|
|
7d290b |
+ ++cursor;
|
|
|
7d290b |
+ }
|
|
|
7d290b |
|
|
|
7d290b |
- if (colon) {
|
|
|
7d290b |
- uint16_t port;
|
|
|
7d290b |
+ /* Must be in range */
|
|
|
7d290b |
+ errno = 0;
|
|
|
7d290b |
+ long port = strtol(str, NULL, 10);
|
|
|
7d290b |
|
|
|
7d290b |
- *colon = '\0';
|
|
|
7d290b |
+ if ((errno == ERANGE && (port == LONG_MAX || port == LONG_MIN))
|
|
|
7d290b |
+ || (errno != 0 && port == 0) || (port > USHRT_MAX))
|
|
|
7d290b |
+ return false;
|
|
|
7d290b |
|
|
|
7d290b |
- port = (uint16_t)atoi(colon+1);
|
|
|
7d290b |
- if (port == 0) {
|
|
|
7d290b |
- if (strlen(colon+1) == 0) {
|
|
|
7d290b |
- exit_error(PARAMETER_PROBLEM,
|
|
|
7d290b |
- "No port specified after `:'");
|
|
|
7d290b |
- } else {
|
|
|
7d290b |
- exit_error(PARAMETER_PROBLEM,
|
|
|
7d290b |
- "Port `%s' not valid", colon+1);
|
|
|
7d290b |
- }
|
|
|
7d290b |
- }
|
|
|
7d290b |
+ return true;
|
|
|
7d290b |
+}
|
|
|
7d290b |
+
|
|
|
7d290b |
+static void
|
|
|
7d290b |
+split_address_and_port(const char *arg, char **address, char **port_str)
|
|
|
7d290b |
+{
|
|
|
7d290b |
+ char *cursor = strchr(arg, '[');
|
|
|
7d290b |
+
|
|
|
7d290b |
+ if (cursor) {
|
|
|
7d290b |
+ /* IPv6 address with port*/
|
|
|
7d290b |
+ char *start = cursor + 1;
|
|
|
7d290b |
|
|
|
7d290b |
- error = strchr(colon+1, ':');
|
|
|
7d290b |
- if (error)
|
|
|
7d290b |
+ cursor = strchr(start, ']');
|
|
|
7d290b |
+ if (start == cursor) {
|
|
|
7d290b |
+ exit_error(PARAMETER_PROBLEM,
|
|
|
7d290b |
+ "No IPv6 address specified");
|
|
|
7d290b |
+ } else if (!cursor) {
|
|
|
7d290b |
exit_error(PARAMETER_PROBLEM,
|
|
|
7d290b |
- "Invalid port:port syntax");
|
|
|
7d290b |
-
|
|
|
7d290b |
- if (type == CT_OPT_SRC_NAT)
|
|
|
7d290b |
- nfct_set_attr_u16(tmpl.ct, ATTR_SNAT_PORT, ntohs(port));
|
|
|
7d290b |
- else if (type == CT_OPT_DST_NAT)
|
|
|
7d290b |
- nfct_set_attr_u16(tmpl.ct, ATTR_DNAT_PORT, ntohs(port));
|
|
|
7d290b |
- else if (type == CT_OPT_ANY_NAT) {
|
|
|
7d290b |
- nfct_set_attr_u16(tmpl.ct, ATTR_SNAT_PORT, ntohs(port));
|
|
|
7d290b |
- nfct_set_attr_u16(tmpl.ct, ATTR_DNAT_PORT, ntohs(port));
|
|
|
7d290b |
+ "No closing ']' around IPv6 address");
|
|
|
7d290b |
}
|
|
|
7d290b |
- }
|
|
|
7d290b |
+ size_t len = cursor - start;
|
|
|
7d290b |
|
|
|
7d290b |
- if (parse_addr(arg, &parse, NULL) == AF_UNSPEC) {
|
|
|
7d290b |
- if (strlen(arg) == 0) {
|
|
|
7d290b |
- exit_error(PARAMETER_PROBLEM, "No IP specified");
|
|
|
7d290b |
+ cursor = strchr(cursor, ':');
|
|
|
7d290b |
+ if (cursor) {
|
|
|
7d290b |
+ /* Copy address only if there is a port */
|
|
|
7d290b |
+ *address = strndup(start, len);
|
|
|
7d290b |
+ }
|
|
|
7d290b |
+ } else {
|
|
|
7d290b |
+ cursor = strchr(arg, ':');
|
|
|
7d290b |
+ if (cursor && !strchr(cursor + 1, ':')) {
|
|
|
7d290b |
+ /* IPv4 address with port */
|
|
|
7d290b |
+ *address = strndup(arg, cursor - arg);
|
|
|
7d290b |
} else {
|
|
|
7d290b |
+ /* v6 address */
|
|
|
7d290b |
+ cursor = NULL;
|
|
|
7d290b |
+ }
|
|
|
7d290b |
+ }
|
|
|
7d290b |
+ if (cursor) {
|
|
|
7d290b |
+ /* Parse port entry */
|
|
|
7d290b |
+ cursor++;
|
|
|
7d290b |
+ if (strlen(cursor) == 0) {
|
|
|
7d290b |
exit_error(PARAMETER_PROBLEM,
|
|
|
7d290b |
- "Invalid IP address `%s'", arg);
|
|
|
7d290b |
+ "No port specified after `:'");
|
|
|
7d290b |
}
|
|
|
7d290b |
+ if (!valid_port(cursor)) {
|
|
|
7d290b |
+ exit_error(PARAMETER_PROBLEM,
|
|
|
7d290b |
+ "Invalid port `%s'", cursor);
|
|
|
7d290b |
+ }
|
|
|
7d290b |
+ *port_str = strdup(cursor);
|
|
|
7d290b |
+ } else {
|
|
|
7d290b |
+ /* No port colon or more than one colon (ipv6)
|
|
|
7d290b |
+ * assume arg is straight IP address and no port
|
|
|
7d290b |
+ */
|
|
|
7d290b |
+ *address = strdup(arg);
|
|
|
7d290b |
}
|
|
|
7d290b |
-
|
|
|
7d290b |
- if (type == CT_OPT_SRC_NAT || type == CT_OPT_ANY_NAT)
|
|
|
7d290b |
- nfct_set_attr_u32(tmpl.ct, ATTR_SNAT_IPV4, parse.v4);
|
|
|
7d290b |
- else if (type == CT_OPT_DST_NAT || type == CT_OPT_ANY_NAT)
|
|
|
7d290b |
- nfct_set_attr_u32(tmpl.ct, ATTR_DNAT_IPV4, parse.v4);
|
|
|
7d290b |
}
|
|
|
7d290b |
|
|
|
7d290b |
static void
|
|
|
7d290b |
@@ -1289,7 +1325,7 @@ nfct_ip6_net_cmp(const union ct_address *addr, const struct ct_network *net)
|
|
|
7d290b |
|
|
|
7d290b |
static int
|
|
|
7d290b |
nfct_ip_net_cmp(int family, const union ct_address *addr,
|
|
|
7d290b |
- const struct ct_network *net)
|
|
|
7d290b |
+ const struct ct_network *net)
|
|
|
7d290b |
{
|
|
|
7d290b |
switch(family) {
|
|
|
7d290b |
case AF_INET:
|
|
|
7d290b |
@@ -2128,6 +2164,7 @@ static void merge_bitmasks(struct nfct_bitmask **current,
|
|
|
7d290b |
nfct_bitmask_destroy(src);
|
|
|
7d290b |
}
|
|
|
7d290b |
|
|
|
7d290b |
+
|
|
|
7d290b |
static void
|
|
|
7d290b |
nfct_build_netmask(uint32_t *dst, int b, int n)
|
|
|
7d290b |
{
|
|
|
7d290b |
@@ -2147,10 +2184,9 @@ nfct_build_netmask(uint32_t *dst, int b, int n)
|
|
|
7d290b |
}
|
|
|
7d290b |
|
|
|
7d290b |
static void
|
|
|
7d290b |
-nfct_set_addr_opt(int opt, struct nf_conntrack *ct, union ct_address *ad,
|
|
|
7d290b |
- int l3protonum)
|
|
|
7d290b |
+nfct_set_addr_only(const int opt, struct nf_conntrack *ct, union ct_address *ad,
|
|
|
7d290b |
+ const int l3protonum)
|
|
|
7d290b |
{
|
|
|
7d290b |
- options |= opt2type[opt];
|
|
|
7d290b |
switch (l3protonum) {
|
|
|
7d290b |
case AF_INET:
|
|
|
7d290b |
nfct_set_attr_u32(ct,
|
|
|
7d290b |
@@ -2163,24 +2199,33 @@ nfct_set_addr_opt(int opt, struct nf_conntrack *ct, union ct_address *ad,
|
|
|
7d290b |
&ad->v6);
|
|
|
7d290b |
break;
|
|
|
7d290b |
}
|
|
|
7d290b |
+}
|
|
|
7d290b |
+
|
|
|
7d290b |
+static void
|
|
|
7d290b |
+nfct_set_addr_opt(const int opt, struct nf_conntrack *ct, union ct_address *ad,
|
|
|
7d290b |
+ const int l3protonum)
|
|
|
7d290b |
+{
|
|
|
7d290b |
+ options |= opt2type[opt];
|
|
|
7d290b |
+ nfct_set_addr_only(opt, ct, ad, l3protonum);
|
|
|
7d290b |
nfct_set_attr_u8(ct, opt2attr[opt], l3protonum);
|
|
|
7d290b |
}
|
|
|
7d290b |
|
|
|
7d290b |
static void
|
|
|
7d290b |
-nfct_parse_addr_from_opt(int opt, struct nf_conntrack *ct,
|
|
|
7d290b |
- struct nf_conntrack *ctmask,
|
|
|
7d290b |
- union ct_address *ad, int *family)
|
|
|
7d290b |
+nfct_parse_addr_from_opt(const int opt, const char *arg,
|
|
|
7d290b |
+ struct nf_conntrack *ct,
|
|
|
7d290b |
+ struct nf_conntrack *ctmask,
|
|
|
7d290b |
+ union ct_address *ad, int *family)
|
|
|
7d290b |
{
|
|
|
7d290b |
- int l3protonum, mask, maskopt;
|
|
|
7d290b |
+ int mask, maskopt;
|
|
|
7d290b |
|
|
|
7d290b |
- l3protonum = parse_addr(optarg, ad, &mask);
|
|
|
7d290b |
+ const int l3protonum = parse_addr(arg, ad, &mask);
|
|
|
7d290b |
if (l3protonum == AF_UNSPEC) {
|
|
|
7d290b |
exit_error(PARAMETER_PROBLEM,
|
|
|
7d290b |
- "Invalid IP address `%s'", optarg);
|
|
|
7d290b |
+ "Invalid IP address `%s'", arg);
|
|
|
7d290b |
}
|
|
|
7d290b |
set_family(family, l3protonum);
|
|
|
7d290b |
maskopt = opt2maskopt[opt];
|
|
|
7d290b |
- if (!maskopt && mask != -1) {
|
|
|
7d290b |
+ if (mask != -1 && !maskopt) {
|
|
|
7d290b |
exit_error(PARAMETER_PROBLEM,
|
|
|
7d290b |
"CIDR notation unavailable"
|
|
|
7d290b |
" for `--%s'", get_long_opt(opt));
|
|
|
7d290b |
@@ -2192,7 +2237,7 @@ nfct_parse_addr_from_opt(int opt, struct nf_conntrack *ct,
|
|
|
7d290b |
nfct_set_addr_opt(opt, ct, ad, l3protonum);
|
|
|
7d290b |
|
|
|
7d290b |
/* bail if we don't have a netmask to set*/
|
|
|
7d290b |
- if (!maskopt || mask == -1 || ctmask == NULL)
|
|
|
7d290b |
+ if (mask == -1 || !maskopt || ctmask == NULL)
|
|
|
7d290b |
return;
|
|
|
7d290b |
|
|
|
7d290b |
switch(l3protonum) {
|
|
|
7d290b |
@@ -2211,6 +2256,24 @@ nfct_parse_addr_from_opt(int opt, struct nf_conntrack *ct,
|
|
|
7d290b |
nfct_set_addr_opt(maskopt, ctmask, ad, l3protonum);
|
|
|
7d290b |
}
|
|
|
7d290b |
|
|
|
7d290b |
+static void
|
|
|
7d290b |
+nfct_set_nat_details(const int opt, struct nf_conntrack *ct,
|
|
|
7d290b |
+ union ct_address *ad, const char *port_str,
|
|
|
7d290b |
+ const int family)
|
|
|
7d290b |
+{
|
|
|
7d290b |
+ const int type = opt2type[opt];
|
|
|
7d290b |
+
|
|
|
7d290b |
+ nfct_set_addr_only(opt, ct, ad, family);
|
|
|
7d290b |
+ if (port_str && type == CT_OPT_SRC_NAT) {
|
|
|
7d290b |
+ nfct_set_attr_u16(ct, ATTR_SNAT_PORT,
|
|
|
7d290b |
+ ntohs((uint16_t)atoi(port_str)));
|
|
|
7d290b |
+ } else if (port_str && type == CT_OPT_DST_NAT) {
|
|
|
7d290b |
+ nfct_set_attr_u16(ct, ATTR_DNAT_PORT,
|
|
|
7d290b |
+ ntohs((uint16_t)atoi(port_str)));
|
|
|
7d290b |
+ }
|
|
|
7d290b |
+
|
|
|
7d290b |
+}
|
|
|
7d290b |
+
|
|
|
7d290b |
int main(int argc, char *argv[])
|
|
|
7d290b |
{
|
|
|
7d290b |
int c, cmd;
|
|
|
7d290b |
@@ -2289,17 +2352,18 @@ int main(int argc, char *argv[])
|
|
|
7d290b |
case 'd':
|
|
|
7d290b |
case 'r':
|
|
|
7d290b |
case 'q':
|
|
|
7d290b |
- nfct_parse_addr_from_opt(c, tmpl.ct, tmpl.mask,
|
|
|
7d290b |
- &ad, &family);
|
|
|
7d290b |
+ nfct_parse_addr_from_opt(c, optarg, tmpl.ct,
|
|
|
7d290b |
+ tmpl.mask, &ad, &family);
|
|
|
7d290b |
break;
|
|
|
7d290b |
case '[':
|
|
|
7d290b |
case ']':
|
|
|
7d290b |
- nfct_parse_addr_from_opt(c, tmpl.exptuple, tmpl.mask,
|
|
|
7d290b |
- &ad, &family);
|
|
|
7d290b |
+ nfct_parse_addr_from_opt(c, optarg, tmpl.exptuple,
|
|
|
7d290b |
+ tmpl.mask, &ad, &family);
|
|
|
7d290b |
break;
|
|
|
7d290b |
case '{':
|
|
|
7d290b |
case '}':
|
|
|
7d290b |
- nfct_parse_addr_from_opt(c, tmpl.mask, NULL, &ad, &family);
|
|
|
7d290b |
+ nfct_parse_addr_from_opt(c, optarg, tmpl.mask,
|
|
|
7d290b |
+ NULL, &ad, &family);
|
|
|
7d290b |
break;
|
|
|
7d290b |
case 'p':
|
|
|
7d290b |
options |= CT_OPT_PROTO;
|
|
|
7d290b |
@@ -2341,19 +2405,34 @@ int main(int argc, char *argv[])
|
|
|
7d290b |
break;
|
|
|
7d290b |
case 'n':
|
|
|
7d290b |
case 'g':
|
|
|
7d290b |
- case 'j': {
|
|
|
7d290b |
- char *tmp = NULL;
|
|
|
7d290b |
-
|
|
|
7d290b |
+ case 'j':
|
|
|
7d290b |
options |= opt2type[c];
|
|
|
7d290b |
-
|
|
|
7d290b |
- tmp = get_optional_arg(argc, argv);
|
|
|
7d290b |
- if (tmp == NULL)
|
|
|
7d290b |
- continue;
|
|
|
7d290b |
-
|
|
|
7d290b |
- set_family(&family, AF_INET);
|
|
|
7d290b |
- nat_parse(tmp, tmpl.ct, opt2type[c]);
|
|
|
7d290b |
+ char *optional_arg = get_optional_arg(argc, argv);
|
|
|
7d290b |
+
|
|
|
7d290b |
+ if (optional_arg) {
|
|
|
7d290b |
+ char *port_str = NULL;
|
|
|
7d290b |
+ char *nat_address = NULL;
|
|
|
7d290b |
+
|
|
|
7d290b |
+ split_address_and_port(optional_arg,
|
|
|
7d290b |
+ &nat_address,
|
|
|
7d290b |
+ &port_str);
|
|
|
7d290b |
+ nfct_parse_addr_from_opt(c, nat_address,
|
|
|
7d290b |
+ tmpl.ct, NULL,
|
|
|
7d290b |
+ &ad, &family);
|
|
|
7d290b |
+ if (c == 'j') {
|
|
|
7d290b |
+ /* Set details on both src and dst
|
|
|
7d290b |
+ * with any-nat
|
|
|
7d290b |
+ */
|
|
|
7d290b |
+ nfct_set_nat_details('g', tmpl.ct, &ad,
|
|
|
7d290b |
+ port_str, family);
|
|
|
7d290b |
+ nfct_set_nat_details('n', tmpl.ct, &ad,
|
|
|
7d290b |
+ port_str, family);
|
|
|
7d290b |
+ } else {
|
|
|
7d290b |
+ nfct_set_nat_details(c, tmpl.ct, &ad,
|
|
|
7d290b |
+ port_str, family);
|
|
|
7d290b |
+ }
|
|
|
7d290b |
+ }
|
|
|
7d290b |
break;
|
|
|
7d290b |
- }
|
|
|
7d290b |
case 'w':
|
|
|
7d290b |
case '(':
|
|
|
7d290b |
case ')':
|
|
|
7d290b |
diff --git a/tests/conntrack/testsuite/00create b/tests/conntrack/testsuite/00create
|
|
|
7d290b |
index 40e2c1952940c..afe4342e9b00d 100644
|
|
|
7d290b |
--- a/tests/conntrack/testsuite/00create
|
|
|
7d290b |
+++ b/tests/conntrack/testsuite/00create
|
|
|
7d290b |
@@ -18,3 +18,9 @@
|
|
|
7d290b |
-I -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 --state LISTEN -u SEEN_REPLY -t 50 ; OK
|
|
|
7d290b |
# delete reverse
|
|
|
7d290b |
-D -r 2.2.2.2 -q 1.1.1.1 -p tcp --reply-port-src 11 --reply-port-dst 21 ; OK
|
|
|
7d290b |
+# create a v6 conntrack
|
|
|
7d290b |
+-I -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
|
|
|
7d290b |
+# delete v6 conntrack
|
|
|
7d290b |
+-D -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p tcp --sport 10 --dport 20 ; OK
|
|
|
7d290b |
+# mismatched address family
|
|
|
7d290b |
+-I -s 2001:DB8::1.1.1.1 -d 2.2.2.2 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
|
|
|
7d290b |
diff --git a/tests/conntrack/testsuite/03nat b/tests/conntrack/testsuite/03nat
|
|
|
7d290b |
index f94e8ffeb2f9f..014feb8e6e3ab 100644
|
|
|
7d290b |
--- a/tests/conntrack/testsuite/03nat
|
|
|
7d290b |
+++ b/tests/conntrack/testsuite/03nat
|
|
|
7d290b |
@@ -36,5 +36,13 @@
|
|
|
7d290b |
-L --dst-nat 3.3.3.3:81 ; OK
|
|
|
7d290b |
# show
|
|
|
7d290b |
-L --dst-nat 1.1.1.1:80 ; OK
|
|
|
7d290b |
+# badport
|
|
|
7d290b |
+-L --dst-nat 1.1.1.1: ; BAD
|
|
|
7d290b |
+# badport
|
|
|
7d290b |
+-L --dst-nat 1.1.1.1::; BAD
|
|
|
7d290b |
+# badport
|
|
|
7d290b |
+-L --dst-nat 1.1.1.1:80:80; BAD
|
|
|
7d290b |
+# badport
|
|
|
7d290b |
+-L --dst-nat 1.1.1.1:65536; BAD
|
|
|
7d290b |
# delete
|
|
|
7d290b |
-D -s 1.1.1.1 ; OK
|
|
|
7d290b |
diff --git a/tests/conntrack/testsuite/07nat6 b/tests/conntrack/testsuite/07nat6
|
|
|
7d290b |
new file mode 100644
|
|
|
7d290b |
index 0000000000000..8cecd8e9bdd88
|
|
|
7d290b |
--- /dev/null
|
|
|
7d290b |
+++ b/tests/conntrack/testsuite/07nat6
|
|
|
7d290b |
@@ -0,0 +1,56 @@
|
|
|
7d290b |
+# create dummy
|
|
|
7d290b |
+-I -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 --dst-nat 2001:DB8::3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --dst-nat ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --dst-nat 2001:DB8::3.3.3.3 ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --src-nat ; OK
|
|
|
7d290b |
+# delete
|
|
|
7d290b |
+-D -s 2001:DB8::1.1.1.1 ; OK
|
|
|
7d290b |
+# create dummy again
|
|
|
7d290b |
+-I -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 --src-nat 2001:DB8::3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --src-nat ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --src-nat 2001:DB8::3.3.3.3 ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --dst-nat ; OK
|
|
|
7d290b |
+# show any-nat
|
|
|
7d290b |
+-L --any-nat ; OK
|
|
|
7d290b |
+# delete
|
|
|
7d290b |
+-D -s 2001:DB8::1.1.1.1 ; OK
|
|
|
7d290b |
+# bad combination
|
|
|
7d290b |
+-L --dst-nat --any-nat ; BAD
|
|
|
7d290b |
+# bad combination
|
|
|
7d290b |
+-L --src-nat --any-nat ; BAD
|
|
|
7d290b |
+# bad combination
|
|
|
7d290b |
+-L --src-nat --dst-nat --any-nat ; BAD
|
|
|
7d290b |
+# create
|
|
|
7d290b |
+-I -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 --dst-nat [2001:DB8::3.3.3.3]:80 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --dst-nat [2001:DB8::3.3.3.3]:80 ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --any-nat [2001:DB8::3.3.3.3]:80 ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --dst-nat [2001:DB8::3.3.3.3]:81 ; OK
|
|
|
7d290b |
+# show
|
|
|
7d290b |
+-L --dst-nat [2001:DB8::1.1.1.1]:80 ; OK
|
|
|
7d290b |
+# noport
|
|
|
7d290b |
+-L --dst-nat [2001:DB8::1.1.1.1]: ; BAD
|
|
|
7d290b |
+# badport
|
|
|
7d290b |
+-L --dst-nat [2001:DB8::1.1.1.1]:: ; BAD
|
|
|
7d290b |
+# badport
|
|
|
7d290b |
+-L --dst-nat [2001:DB8::1.1.1.1]:80:80 ; BAD
|
|
|
7d290b |
+# badport
|
|
|
7d290b |
+-L --dst-nat [2001:DB8::1.1.1.1]:65536 ; BAD
|
|
|
7d290b |
+# delete
|
|
|
7d290b |
+-D -s 2001:DB8::1.1.1.1 ; OK
|
|
|
7d290b |
+# mismatched address family
|
|
|
7d290b |
+-I -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 --dst-nat 3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
|
|
|
7d290b |
+# mismatched address family
|
|
|
7d290b |
+-I -s 1.1.1.1 -d 2.2.2.2 --dst-nat 2001:DB8::3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
|
|
|
7d290b |
+# create - brackets only for ports in nat
|
|
|
7d290b |
+-I -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 --dst-nat [2001:DB8::3.3.3.3] -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
|
|
|
7d290b |
+# create - brackets rejected elsewhere
|
|
|
7d290b |
+-I -s [2001:DB8::1.1.1.1] -d 2001:DB8::2.2.2.2 --dst-nat 2001:DB8::3.3.3.3 -p tcp --sport 10 --dport 20 --state LISTEN -u SEEN_REPLY -t 50 ; BAD
|
|
|
7d290b |
--
|
|
|
7d290b |
2.21.0
|
|
|
7d290b |
|