netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [libnetfilter_conntrack PATCH 0/3] support for IPv6 NAT
@ 2016-05-17 12:50 Arturo Borrero Gonzalez
  2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 1/3] src: add support for IPv6 to struct __nfct_nat Arturo Borrero Gonzalez
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Arturo Borrero Gonzalez @ 2016-05-17 12:50 UTC (permalink / raw)
  To: netfilter-devel; +Cc: fw

The following series implements support for IPv6 NAT, which
was lacking in this library and in conntrackd.

I will to follow-up with the conntrackd patches, but I would like
to get an early review on these 3 patches to know if I'm working in the
right direction.

Comments welcome.

---

Arturo Borrero Gonzalez (3):
      src: add support for IPv6 to struct __nfct_nat
      src: add support for IPv6 NAT
      qa: update test_api with IPv6 NAT


 include/internal/object.h                          |    2 
 .../libnetfilter_conntrack.h                       |    2 
 qa/test_api.c                                      |    2 
 src/conntrack/build.c                              |   69 +++++++++++++---
 src/conntrack/build_mnl.c                          |   65 +++++++++++++--
 src/conntrack/copy.c                               |   20 ++++-
 src/conntrack/getter.c                             |   16 +++-
 src/conntrack/objopt.c                             |   85 ++++++++++++++++----
 src/conntrack/setter.c                             |   20 ++++-
 9 files changed, 236 insertions(+), 45 deletions(-)

--

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [libnetfilter_conntrack PATCH 1/3] src: add support for IPv6 to struct __nfct_nat
  2016-05-17 12:50 [libnetfilter_conntrack PATCH 0/3] support for IPv6 NAT Arturo Borrero Gonzalez
@ 2016-05-17 12:50 ` Arturo Borrero Gonzalez
  2016-05-17 15:45   ` Pablo Neira Ayuso
  2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 2/3] src: add support for IPv6 NAT Arturo Borrero Gonzalez
  2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 3/3] qa: update test_api with " Arturo Borrero Gonzalez
  2 siblings, 1 reply; 6+ messages in thread
From: Arturo Borrero Gonzalez @ 2016-05-17 12:50 UTC (permalink / raw)
  To: netfilter-devel; +Cc: fw

The conntrackd daemon lacks support for syncing IPv6 NATed connections.

This patch prepares the ground to give support to such operations:
 * replace uint32_t with union __nfct_address in struct __nfct_nat.
 * update all users of the former uint32_t to support the new struct

A follow-up patch gives support to actually manage the IPv6 NAT.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
 include/internal/object.h |    2 +
 src/conntrack/build.c     |   35 ++++++++++++++++---------
 src/conntrack/build_mnl.c |   31 +++++++++++++++-------
 src/conntrack/copy.c      |    4 +--
 src/conntrack/getter.c    |    4 +--
 src/conntrack/objopt.c    |   63 ++++++++++++++++++++++++++++++++++-----------
 src/conntrack/setter.c    |    4 +--
 7 files changed, 98 insertions(+), 45 deletions(-)

diff --git a/include/internal/object.h b/include/internal/object.h
index ffbcb1f..bb14dc8 100644
--- a/include/internal/object.h
+++ b/include/internal/object.h
@@ -144,7 +144,7 @@ struct __nfct_counters {
 };
 
 struct __nfct_nat {
-	uint32_t 		min_ip, max_ip;
+	union __nfct_address	min_ip, max_ip;
 	union __nfct_l4_src 	l4min, l4max;
 };
 
diff --git a/src/conntrack/build.c b/src/conntrack/build.c
index 01bdefb..10d51fe 100644
--- a/src/conntrack/build.c
+++ b/src/conntrack/build.c
@@ -275,20 +275,30 @@ static void __build_protonat(struct nfnlhdr *req,
 
 static void __build_nat(struct nfnlhdr *req,
 			size_t size,
-			const struct __nfct_nat *nat)
+			const struct __nfct_nat *nat,
+			uint8_t l3protonum)
 {
-	nfnl_addattr_l(&req->nlh, size, CTA_NAT_MINIP,
-		       &nat->min_ip, sizeof(uint32_t));
+	switch (l3protonum) {
+	case AF_INET:
+		nfnl_addattr_l(&req->nlh, size, CTA_NAT_MINIP,
+			       &nat->min_ip.v4, sizeof(uint32_t));
+		break;
+	case AF_INET6:
+		break;
+	default:
+		break;
+	}
 }
 
 static void __build_snat(struct nfnlhdr *req,
 			 size_t size,
-			 const struct nf_conntrack *ct)
+			 const struct nf_conntrack *ct,
+			 uint8_t l3protonum)
 {
 	struct nfattr *nest;
 
 	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
-	__build_nat(req, size, &ct->snat);
+	__build_nat(req, size, &ct->snat, l3protonum);
 	__build_protonat(req, size, ct, &ct->snat);
 	nfnl_nest_end(&req->nlh, nest);
 }
@@ -300,7 +310,7 @@ static void __build_snat_ipv4(struct nfnlhdr *req,
 	struct nfattr *nest;
 
 	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
-	__build_nat(req, size, &ct->snat);
+	__build_nat(req, size, &ct->snat, AF_INET);
 	nfnl_nest_end(&req->nlh, nest);
 }
 
@@ -317,12 +327,13 @@ static void __build_snat_port(struct nfnlhdr *req,
 
 static void __build_dnat(struct nfnlhdr *req,
 			 size_t size,
-			 const struct nf_conntrack *ct)
+			 const struct nf_conntrack *ct,
+			 uint8_t l3protonum)
 {
 	struct nfattr *nest;
 
 	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
-	__build_nat(req, size, &ct->dnat);
+	__build_nat(req, size, &ct->dnat, l3protonum);
 	__build_protonat(req, size, ct, &ct->dnat);
 	nfnl_nest_end(&req->nlh, nest);
 }
@@ -334,7 +345,7 @@ static void __build_dnat_ipv4(struct nfnlhdr *req,
 	struct nfattr *nest;
 
 	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
-	__build_nat(req, size, &ct->dnat);
+	__build_nat(req, size, &ct->dnat, AF_INET);
 	nfnl_nest_end(&req->nlh, nest);
 }
 
@@ -514,9 +525,9 @@ int __build_conntrack(struct nfnl_subsys_handle *ssh,
 
 	__build_protoinfo(req, size, ct);
 
-	if (test_bit(ATTR_SNAT_IPV4, ct->head.set) && 
+	if (test_bit(ATTR_SNAT_IPV4, ct->head.set) &&
 	    test_bit(ATTR_SNAT_PORT, ct->head.set))
-		__build_snat(req, size, ct);
+		__build_snat(req, size, ct, AF_INET);
 	else if (test_bit(ATTR_SNAT_IPV4, ct->head.set))
 		__build_snat_ipv4(req, size, ct);
 	else if (test_bit(ATTR_SNAT_PORT, ct->head.set))
@@ -524,7 +535,7 @@ int __build_conntrack(struct nfnl_subsys_handle *ssh,
 
 	if (test_bit(ATTR_DNAT_IPV4, ct->head.set) &&
 	    test_bit(ATTR_DNAT_PORT, ct->head.set))
-		__build_dnat(req, size, ct);
+		__build_dnat(req, size, ct, AF_INET);
 	else if (test_bit(ATTR_DNAT_IPV4, ct->head.set))
 		__build_dnat_ipv4(req, size, ct);
 	else if (test_bit(ATTR_DNAT_PORT, ct->head.set))
diff --git a/src/conntrack/build_mnl.c b/src/conntrack/build_mnl.c
index 8ed0690..961b824 100644
--- a/src/conntrack/build_mnl.c
+++ b/src/conntrack/build_mnl.c
@@ -264,19 +264,29 @@ nfct_build_protonat(struct nlmsghdr *nlh, const struct nf_conntrack *ct,
 }
 
 static int
-nfct_build_nat(struct nlmsghdr *nlh, const struct __nfct_nat *nat)
+nfct_build_nat(struct nlmsghdr *nlh, const struct __nfct_nat *nat,
+	       uint8_t l3protonum)
 {
-	mnl_attr_put_u32(nlh, CTA_NAT_MINIP, nat->min_ip);
+	switch (l3protonum) {
+	case AF_INET:
+		mnl_attr_put_u32(nlh, CTA_NAT_MINIP, nat->min_ip.v4);
+		break;
+	case AF_INET6:
+		break;
+	default:
+		break;
+	}
 	return 0;
 }
 
 static int
-nfct_build_snat(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
+nfct_build_snat(struct nlmsghdr *nlh, const struct nf_conntrack *ct,
+		uint8_t l3protonum)
 {
 	struct nlattr *nest;
 
 	nest = mnl_attr_nest_start(nlh, CTA_NAT_SRC);
-	nfct_build_nat(nlh, &ct->snat);
+	nfct_build_nat(nlh, &ct->snat, l3protonum);
 	nfct_build_protonat(nlh, ct, &ct->snat);
 	mnl_attr_nest_end(nlh, nest);
 	return 0;
@@ -288,7 +298,7 @@ nfct_build_snat_ipv4(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 	struct nlattr *nest;
 
 	nest = mnl_attr_nest_start(nlh, CTA_NAT_SRC);
-	nfct_build_nat(nlh, &ct->snat);
+	nfct_build_nat(nlh, &ct->snat, AF_INET);
 	mnl_attr_nest_end(nlh, nest);
 	return 0;
 }
@@ -305,12 +315,13 @@ nfct_build_snat_port(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 }
 
 static int
-nfct_build_dnat(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
+nfct_build_dnat(struct nlmsghdr *nlh, const struct nf_conntrack *ct,
+		uint8_t l3protonum)
 {
 	struct nlattr *nest;
 
 	nest = mnl_attr_nest_start(nlh, CTA_NAT_DST);
-	nfct_build_nat(nlh, &ct->dnat);
+	nfct_build_nat(nlh, &ct->dnat, l3protonum);
 	nfct_build_protonat(nlh, ct, &ct->dnat);
 	mnl_attr_nest_end(nlh, nest);
 	return 0;
@@ -322,7 +333,7 @@ nfct_build_dnat_ipv4(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 	struct nlattr *nest;
 
 	nest = mnl_attr_nest_start(nlh, CTA_NAT_DST);
-	nfct_build_nat(nlh, &ct->dnat);
+	nfct_build_nat(nlh, &ct->dnat, AF_INET);
 	mnl_attr_nest_end(nlh, nest);
 	return 0;
 }
@@ -498,7 +509,7 @@ nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 
 	if (test_bit(ATTR_SNAT_IPV4, ct->head.set) &&
 	    test_bit(ATTR_SNAT_PORT, ct->head.set)) {
-		nfct_build_snat(nlh, ct);
+		nfct_build_snat(nlh, ct, AF_INET);
 	} else if (test_bit(ATTR_SNAT_IPV4, ct->head.set)) {
 		nfct_build_snat_ipv4(nlh, ct);
 	} else if (test_bit(ATTR_SNAT_PORT, ct->head.set)) {
@@ -507,7 +518,7 @@ nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 
 	if (test_bit(ATTR_DNAT_IPV4, ct->head.set) &&
 	    test_bit(ATTR_DNAT_PORT, ct->head.set)) {
-		nfct_build_dnat(nlh, ct);
+		nfct_build_dnat(nlh, ct, AF_INET);
 	} else if (test_bit(ATTR_DNAT_IPV4, ct->head.set)) {
 		nfct_build_dnat_ipv4(nlh, ct);
 	} else if (test_bit(ATTR_DNAT_PORT, ct->head.set)) {
diff --git a/src/conntrack/copy.c b/src/conntrack/copy.c
index 249e7e0..eac977b 100644
--- a/src/conntrack/copy.c
+++ b/src/conntrack/copy.c
@@ -287,13 +287,13 @@ static void copy_attr_dccp_handshake_seq(struct nf_conntrack *dest,
 static void copy_attr_snat_ipv4(struct nf_conntrack *dest,
 				const struct nf_conntrack *orig)
 {
-	dest->snat.min_ip = orig->snat.min_ip;
+	dest->snat.min_ip.v4 = orig->snat.min_ip.v4;
 }
 
 static void copy_attr_dnat_ipv4(struct nf_conntrack *dest,
 				const struct nf_conntrack *orig)
 {
-	dest->dnat.min_ip = orig->dnat.min_ip;
+	dest->dnat.min_ip.v4 = orig->dnat.min_ip.v4;
 }
 
 static void copy_attr_snat_port(struct nf_conntrack *dest,
diff --git a/src/conntrack/getter.c b/src/conntrack/getter.c
index ef4ec1d..20dd905 100644
--- a/src/conntrack/getter.c
+++ b/src/conntrack/getter.c
@@ -206,12 +206,12 @@ static const void *get_attr_sctp_vtag_repl(const struct nf_conntrack *ct)
 
 static const void *get_attr_snat_ipv4(const struct nf_conntrack *ct)
 {
-	return &ct->snat.min_ip;
+	return &ct->snat.min_ip.v4;
 }
 
 static const void *get_attr_dnat_ipv4(const struct nf_conntrack *ct)
 {
-	return &ct->dnat.min_ip;
+	return &ct->dnat.min_ip.v4;
 }
 
 static const void *get_attr_snat_port(const struct nf_conntrack *ct)
diff --git a/src/conntrack/objopt.c b/src/conntrack/objopt.c
index 5898746..3756bbe 100644
--- a/src/conntrack/objopt.c
+++ b/src/conntrack/objopt.c
@@ -52,18 +52,33 @@ static void __autocomplete(struct nf_conntrack *ct, int dir)
 
 static void setobjopt_undo_snat(struct nf_conntrack *ct)
 {
-	ct->snat.min_ip = ct->repl.dst.v4;
-	ct->snat.max_ip = ct->snat.min_ip;
-	ct->repl.dst.v4 = ct->head.orig.src.v4;
-	set_bit(ATTR_SNAT_IPV4, ct->head.set);
+	switch (ct->head.orig.l3protonum) {
+	case AF_INET:
+		ct->snat.min_ip.v4 = ct->repl.dst.v4;
+		ct->snat.max_ip.v4 = ct->snat.min_ip.v4;
+		ct->repl.dst.v4 = ct->head.orig.src.v4;
+		set_bit(ATTR_SNAT_IPV4, ct->head.set);
+		break;
+	case AF_INET6:
+		break;
+	default:
+		break;
+	}
 }
 
 static void setobjopt_undo_dnat(struct nf_conntrack *ct)
 {
-	ct->dnat.min_ip = ct->repl.src.v4;
-	ct->dnat.max_ip = ct->dnat.min_ip;
-	ct->repl.src.v4 = ct->head.orig.dst.v4;
-	set_bit(ATTR_DNAT_IPV4, ct->head.set);
+	switch (ct->head.orig.l3protonum) {
+	case AF_INET:
+		ct->dnat.min_ip.v4 = ct->repl.src.v4;
+		ct->dnat.max_ip.v4 = ct->dnat.min_ip.v4;
+		ct->repl.src.v4 = ct->head.orig.dst.v4;
+		set_bit(ATTR_DNAT_IPV4, ct->head.set);
+	case AF_INET6:
+		break;
+	default:
+		break;
+	}
 }
 
 static void setobjopt_undo_spat(struct nf_conntrack *ct)
@@ -114,18 +129,34 @@ int __setobjopt(struct nf_conntrack *ct, unsigned int option)
 
 static int getobjopt_is_snat(const struct nf_conntrack *ct)
 {
-	return ((test_bit(ATTR_STATUS, ct->head.set) ?
-		ct->status & IPS_SRC_NAT_DONE : 1) &&
-		ct->repl.dst.v4 != 
-		ct->head.orig.src.v4);
+	if (!(test_bit(ATTR_STATUS, ct->head.set) ?
+		ct->status & IPS_SRC_NAT_DONE : 1))
+		return 0;
+
+	switch (ct->head.orig.l3protonum) {
+	case AF_INET:
+		return ct->repl.dst.v4 != ct->head.orig.src.v4;
+	case AF_INET6:
+		return 0;
+	default:
+		return 0;
+	}
 }
 
 static int getobjopt_is_dnat(const struct nf_conntrack *ct)
 {
-	return ((test_bit(ATTR_STATUS, ct->head.set) ?
-		ct->status & IPS_DST_NAT_DONE : 1) &&
-		ct->repl.src.v4 !=
-		ct->head.orig.dst.v4);
+	if (!(test_bit(ATTR_STATUS, ct->head.set) ?
+		ct->status & IPS_DST_NAT_DONE : 1))
+		return 0;
+
+	switch (ct->head.orig.l3protonum) {
+	case AF_INET:
+		return ct->repl.src.v4 != ct->head.orig.dst.v4;
+	case AF_INET6:
+		return 0;
+	default:
+		return 0;
+	}
 }
 
 static int getobjopt_is_spat(const struct nf_conntrack *ct)
diff --git a/src/conntrack/setter.c b/src/conntrack/setter.c
index a212461..e103646 100644
--- a/src/conntrack/setter.c
+++ b/src/conntrack/setter.c
@@ -237,13 +237,13 @@ set_attr_sctp_vtag_repl(struct nf_conntrack *ct, const void *value, size_t len)
 static void
 set_attr_snat_ipv4(struct nf_conntrack *ct, const void *value, size_t len)
 {
-	ct->snat.min_ip = ct->snat.max_ip = *((uint32_t *) value);
+	ct->snat.min_ip.v4 = ct->snat.max_ip.v4 = *((uint32_t *) value);
 }
 
 static void
 set_attr_dnat_ipv4(struct nf_conntrack *ct, const void *value, size_t len)
 {
-	ct->dnat.min_ip = ct->dnat.max_ip = *((uint32_t *) value);
+	ct->dnat.min_ip.v4 = ct->dnat.max_ip.v4 = *((uint32_t *) value);
 }
 
 static void


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [libnetfilter_conntrack PATCH 2/3] src: add support for IPv6 NAT
  2016-05-17 12:50 [libnetfilter_conntrack PATCH 0/3] support for IPv6 NAT Arturo Borrero Gonzalez
  2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 1/3] src: add support for IPv6 to struct __nfct_nat Arturo Borrero Gonzalez
@ 2016-05-17 12:50 ` Arturo Borrero Gonzalez
  2016-05-17 15:38   ` Pablo Neira Ayuso
  2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 3/3] qa: update test_api with " Arturo Borrero Gonzalez
  2 siblings, 1 reply; 6+ messages in thread
From: Arturo Borrero Gonzalez @ 2016-05-17 12:50 UTC (permalink / raw)
  To: netfilter-devel; +Cc: fw

The conntrackd daemon lacks support for syncing IPv6 NATed connections.

This patch adds support for managing the IPv6 part of struct __nfct_nat,
also updating the corresponsing symbols.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
 .../libnetfilter_conntrack.h                       |    2 +
 src/conntrack/build.c                              |   34 ++++++++++++++++++++
 src/conntrack/build_mnl.c                          |   34 ++++++++++++++++++++
 src/conntrack/copy.c                               |   16 +++++++++
 src/conntrack/getter.c                             |   12 +++++++
 src/conntrack/objopt.c                             |   26 ++++++++++++++-
 src/conntrack/setter.c                             |   16 +++++++++
 7 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
index 22af622..6cba578 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
@@ -138,6 +138,8 @@ enum nf_conntrack_attr {
 	ATTR_CONNLABELS_MASK,			/* variable length */
 	ATTR_ORIG_ZONE,				/* u16 bits */
 	ATTR_REPL_ZONE,				/* u16 bits */
+	ATTR_SNAT_IPV6,				/* u128 bits */
+	ATTR_DNAT_IPV6,				/* u128 bits */
 	ATTR_MAX
 };
 
diff --git a/src/conntrack/build.c b/src/conntrack/build.c
index 10d51fe..0b15230 100644
--- a/src/conntrack/build.c
+++ b/src/conntrack/build.c
@@ -284,6 +284,8 @@ static void __build_nat(struct nfnlhdr *req,
 			       &nat->min_ip.v4, sizeof(uint32_t));
 		break;
 	case AF_INET6:
+		nfnl_addattr_l(&req->nlh, size, CTA_NAT_MINIP,
+			       &nat->min_ip.v6, sizeof(struct in6_addr));
 		break;
 	default:
 		break;
@@ -314,6 +316,17 @@ static void __build_snat_ipv4(struct nfnlhdr *req,
 	nfnl_nest_end(&req->nlh, nest);
 }
 
+static void __build_snat_ipv6(struct nfnlhdr *req,
+			      size_t size,
+			      const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+	__build_nat(req, size, &ct->snat, AF_INET6);
+	nfnl_nest_end(&req->nlh, nest);
+}
+
 static void __build_snat_port(struct nfnlhdr *req,
 			      size_t size,
 			      const struct nf_conntrack *ct)
@@ -349,6 +362,17 @@ static void __build_dnat_ipv4(struct nfnlhdr *req,
 	nfnl_nest_end(&req->nlh, nest);
 }
 
+static void __build_dnat_ipv6(struct nfnlhdr *req,
+			      size_t size,
+			      const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
+	__build_nat(req, size, &ct->dnat, AF_INET6);
+	nfnl_nest_end(&req->nlh, nest);
+}
+
 static void __build_dnat_port(struct nfnlhdr *req,
 			      size_t size,
 			      const struct nf_conntrack *ct)
@@ -528,16 +552,26 @@ int __build_conntrack(struct nfnl_subsys_handle *ssh,
 	if (test_bit(ATTR_SNAT_IPV4, ct->head.set) &&
 	    test_bit(ATTR_SNAT_PORT, ct->head.set))
 		__build_snat(req, size, ct, AF_INET);
+	else if (test_bit(ATTR_SNAT_IPV6, ct->head.set) &&
+		 test_bit(ATTR_SNAT_PORT, ct->head.set))
+		__build_snat(req, size, ct, AF_INET6);
 	else if (test_bit(ATTR_SNAT_IPV4, ct->head.set))
 		__build_snat_ipv4(req, size, ct);
+	else if (test_bit(ATTR_SNAT_IPV6, ct->head.set))
+		__build_snat_ipv6(req, size, ct);
 	else if (test_bit(ATTR_SNAT_PORT, ct->head.set))
 		__build_snat_port(req, size, ct);
 
 	if (test_bit(ATTR_DNAT_IPV4, ct->head.set) &&
 	    test_bit(ATTR_DNAT_PORT, ct->head.set))
 		__build_dnat(req, size, ct, AF_INET);
+	else if (test_bit(ATTR_DNAT_IPV6, ct->head.set) &&
+		 test_bit(ATTR_DNAT_PORT, ct->head.set))
+		__build_dnat(req, size, ct, AF_INET6);
 	else if (test_bit(ATTR_DNAT_IPV4, ct->head.set))
 		__build_dnat_ipv4(req, size, ct);
+	else if (test_bit(ATTR_DNAT_IPV6, ct->head.set))
+		__build_dnat_ipv6(req, size, ct);
 	else if (test_bit(ATTR_DNAT_PORT, ct->head.set))
 		__build_dnat_port(req, size, ct);
 
diff --git a/src/conntrack/build_mnl.c b/src/conntrack/build_mnl.c
index 961b824..2118bf3 100644
--- a/src/conntrack/build_mnl.c
+++ b/src/conntrack/build_mnl.c
@@ -272,6 +272,8 @@ nfct_build_nat(struct nlmsghdr *nlh, const struct __nfct_nat *nat,
 		mnl_attr_put_u32(nlh, CTA_NAT_MINIP, nat->min_ip.v4);
 		break;
 	case AF_INET6:
+		mnl_attr_put(nlh, CTA_NAT_V6_MINIP, sizeof(struct in6_addr),
+			     &nat->min_ip.v6);
 		break;
 	default:
 		break;
@@ -304,6 +306,17 @@ nfct_build_snat_ipv4(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 }
 
 static int
+nfct_build_snat_ipv6(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
+{
+	struct nlattr *nest;
+
+	nest = mnl_attr_nest_start(nlh, CTA_NAT_SRC);
+	nfct_build_nat(nlh, &ct->snat, AF_INET6);
+	mnl_attr_nest_end(nlh, nest);
+	return 0;
+}
+
+static int
 nfct_build_snat_port(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 {
 	struct nlattr *nest;
@@ -339,6 +352,17 @@ nfct_build_dnat_ipv4(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 }
 
 static int
+nfct_build_dnat_ipv6(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
+{
+	struct nlattr *nest;
+
+	nest = mnl_attr_nest_start(nlh, CTA_NAT_DST);
+	nfct_build_nat(nlh, &ct->dnat, AF_INET6);
+	mnl_attr_nest_end(nlh, nest);
+	return 0;
+}
+
+static int
 nfct_build_dnat_port(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 {
 	struct nlattr *nest;
@@ -510,8 +534,13 @@ nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 	if (test_bit(ATTR_SNAT_IPV4, ct->head.set) &&
 	    test_bit(ATTR_SNAT_PORT, ct->head.set)) {
 		nfct_build_snat(nlh, ct, AF_INET);
+	} else if (test_bit(ATTR_SNAT_IPV6, ct->head.set) &&
+		   test_bit(ATTR_SNAT_PORT, ct->head.set)) {
+		nfct_build_snat(nlh, ct, AF_INET6);
 	} else if (test_bit(ATTR_SNAT_IPV4, ct->head.set)) {
 		nfct_build_snat_ipv4(nlh, ct);
+	} else if (test_bit(ATTR_SNAT_IPV6, ct->head.set)) {
+		nfct_build_snat_ipv6(nlh, ct);
 	} else if (test_bit(ATTR_SNAT_PORT, ct->head.set)) {
 		nfct_build_snat_port(nlh, ct);
 	}
@@ -519,8 +548,13 @@ nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
 	if (test_bit(ATTR_DNAT_IPV4, ct->head.set) &&
 	    test_bit(ATTR_DNAT_PORT, ct->head.set)) {
 		nfct_build_dnat(nlh, ct, AF_INET);
+	} else if (test_bit(ATTR_DNAT_IPV6, ct->head.set) &&
+		   test_bit(ATTR_DNAT_PORT, ct->head.set)) {
+		nfct_build_dnat(nlh, ct, AF_INET6);
 	} else if (test_bit(ATTR_DNAT_IPV4, ct->head.set)) {
 		nfct_build_dnat_ipv4(nlh, ct);
+	} else if (test_bit(ATTR_DNAT_IPV6, ct->head.set)) {
+		nfct_build_dnat_ipv6(nlh, ct);
 	} else if (test_bit(ATTR_DNAT_PORT, ct->head.set)) {
 		nfct_build_dnat_port(nlh, ct);
 	}
diff --git a/src/conntrack/copy.c b/src/conntrack/copy.c
index eac977b..e6e4f7a 100644
--- a/src/conntrack/copy.c
+++ b/src/conntrack/copy.c
@@ -296,6 +296,20 @@ static void copy_attr_dnat_ipv4(struct nf_conntrack *dest,
 	dest->dnat.min_ip.v4 = orig->dnat.min_ip.v4;
 }
 
+static void copy_attr_snat_ipv6(struct nf_conntrack *dest,
+				const struct nf_conntrack *orig)
+{
+	memcpy(&dest->snat.min_ip.v6, &orig->snat.min_ip.v6,
+	       sizeof(struct in6_addr));
+}
+
+static void copy_attr_dnat_ipv6(struct nf_conntrack *dest,
+				const struct nf_conntrack *orig)
+{
+	memcpy(&dest->dnat.min_ip.v6, &orig->dnat.min_ip.v6,
+	       sizeof(struct in6_addr));
+}
+
 static void copy_attr_snat_port(struct nf_conntrack *dest,
 				const struct nf_conntrack *orig)
 {
@@ -555,6 +569,8 @@ const copy_attr copy_attr_array[ATTR_MAX] = {
 	[ATTR_HELPER_INFO]		= copy_attr_help_info,
 	[ATTR_CONNLABELS]		= copy_attr_connlabels,
 	[ATTR_CONNLABELS_MASK]		= copy_attr_connlabels_mask,
+	[ATTR_SNAT_IPV6]		= copy_attr_snat_ipv6,
+	[ATTR_DNAT_IPV6]		= copy_attr_dnat_ipv6,
 };
 
 /* this is used by nfct_copy() with the NFCT_CP_OVERRIDE flag set. */
diff --git a/src/conntrack/getter.c b/src/conntrack/getter.c
index 20dd905..e818a05 100644
--- a/src/conntrack/getter.c
+++ b/src/conntrack/getter.c
@@ -214,6 +214,16 @@ static const void *get_attr_dnat_ipv4(const struct nf_conntrack *ct)
 	return &ct->dnat.min_ip.v4;
 }
 
+static const void *get_attr_snat_ipv6(const struct nf_conntrack *ct)
+{
+	return &ct->snat.min_ip.v6;
+}
+
+static const void *get_attr_dnat_ipv6(const struct nf_conntrack *ct)
+{
+	return &ct->dnat.min_ip.v6;
+}
+
 static const void *get_attr_snat_port(const struct nf_conntrack *ct)
 {
 	return &ct->snat.l4min.all;
@@ -430,4 +440,6 @@ const get_attr get_attr_array[ATTR_MAX] = {
 	[ATTR_HELPER_INFO]		= get_attr_helper_info,
 	[ATTR_CONNLABELS]		= get_attr_connlabels,
 	[ATTR_CONNLABELS_MASK]		= get_attr_connlabels_mask,
+	[ATTR_SNAT_IPV6]		= get_attr_snat_ipv6,
+	[ATTR_DNAT_IPV6]		= get_attr_dnat_ipv6,
 };
diff --git a/src/conntrack/objopt.c b/src/conntrack/objopt.c
index 3756bbe..d9e1e0d 100644
--- a/src/conntrack/objopt.c
+++ b/src/conntrack/objopt.c
@@ -60,6 +60,13 @@ static void setobjopt_undo_snat(struct nf_conntrack *ct)
 		set_bit(ATTR_SNAT_IPV4, ct->head.set);
 		break;
 	case AF_INET6:
+		memcpy(&ct->snat.min_ip.v6, &ct->repl.dst.v6,
+		       sizeof(struct in6_addr));
+		memcpy(&ct->snat.max_ip.v6, &ct->snat.min_ip.v6,
+		       sizeof(struct in6_addr));
+		memcpy(&ct->repl.dst.v6, &ct->head.orig.src.v6,
+		       sizeof(struct in6_addr));
+		set_bit(ATTR_SNAT_IPV6, ct->head.set);
 		break;
 	default:
 		break;
@@ -75,6 +82,13 @@ static void setobjopt_undo_dnat(struct nf_conntrack *ct)
 		ct->repl.src.v4 = ct->head.orig.dst.v4;
 		set_bit(ATTR_DNAT_IPV4, ct->head.set);
 	case AF_INET6:
+		memcpy(&ct->dnat.min_ip.v6, &ct->repl.src.v6,
+		       sizeof(struct in6_addr));
+		memcpy(&ct->dnat.max_ip.v6, &ct->dnat.min_ip.v6,
+		       sizeof(struct in6_addr));
+		memcpy(&ct->repl.src.v6, &ct->head.orig.dst.v6,
+		       sizeof(struct in6_addr));
+		set_bit(ATTR_DNAT_IPV6, ct->head.set);
 		break;
 	default:
 		break;
@@ -137,7 +151,11 @@ static int getobjopt_is_snat(const struct nf_conntrack *ct)
 	case AF_INET:
 		return ct->repl.dst.v4 != ct->head.orig.src.v4;
 	case AF_INET6:
-		return 0;
+		if (memcmp(&ct->repl.dst.v6, &ct->head.orig.src.v6,
+			   sizeof(struct in6_addr)) != 0)
+			return 1;
+		else
+			return 0;
 	default:
 		return 0;
 	}
@@ -153,7 +171,11 @@ static int getobjopt_is_dnat(const struct nf_conntrack *ct)
 	case AF_INET:
 		return ct->repl.src.v4 != ct->head.orig.dst.v4;
 	case AF_INET6:
-		return 0;
+		if (memcmp(&ct->repl.src.v6, &ct->head.orig.dst.v6,
+			   sizeof(struct in6_addr)) != 0)
+			return 1;
+		else
+			return 0;
 	default:
 		return 0;
 	}
diff --git a/src/conntrack/setter.c b/src/conntrack/setter.c
index e103646..75ab09e 100644
--- a/src/conntrack/setter.c
+++ b/src/conntrack/setter.c
@@ -247,6 +247,20 @@ set_attr_dnat_ipv4(struct nf_conntrack *ct, const void *value, size_t len)
 }
 
 static void
+set_attr_snat_ipv6(struct nf_conntrack *ct, const void *value, size_t len)
+{
+	memcpy(&ct->snat.min_ip.v6, value, sizeof(struct in6_addr));
+	memcpy(&ct->snat.max_ip.v6, value, sizeof(struct in6_addr));
+}
+
+static void
+set_attr_dnat_ipv6(struct nf_conntrack *ct, const void *value, size_t len)
+{
+	memcpy(&ct->dnat.min_ip.v6, value, sizeof(struct in6_addr));
+	memcpy(&ct->dnat.max_ip.v6, value, sizeof(struct in6_addr));
+}
+
+static void
 set_attr_snat_port(struct nf_conntrack *ct, const void *value, size_t len)
 {
 	ct->snat.l4min.all = ct->snat.l4max.all = *((uint16_t *) value);
@@ -527,4 +541,6 @@ const set_attr set_attr_array[ATTR_MAX] = {
 	[ATTR_HELPER_INFO]	= set_attr_helper_info,
 	[ATTR_CONNLABELS]	= set_attr_connlabels,
 	[ATTR_CONNLABELS_MASK]	= set_attr_connlabels_mask,
+	[ATTR_SNAT_IPV6]	= set_attr_snat_ipv6,
+	[ATTR_DNAT_IPV6]	= set_attr_dnat_ipv6,
 };


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [libnetfilter_conntrack PATCH 3/3] qa: update test_api with IPv6 NAT
  2016-05-17 12:50 [libnetfilter_conntrack PATCH 0/3] support for IPv6 NAT Arturo Borrero Gonzalez
  2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 1/3] src: add support for IPv6 to struct __nfct_nat Arturo Borrero Gonzalez
  2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 2/3] src: add support for IPv6 NAT Arturo Borrero Gonzalez
@ 2016-05-17 12:50 ` Arturo Borrero Gonzalez
  2 siblings, 0 replies; 6+ messages in thread
From: Arturo Borrero Gonzalez @ 2016-05-17 12:50 UTC (permalink / raw)
  To: netfilter-devel; +Cc: fw

Comparators are not implemented.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
 qa/test_api.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/qa/test_api.c b/qa/test_api.c
index 3742357..b96ecf7 100644
--- a/qa/test_api.c
+++ b/qa/test_api.c
@@ -178,6 +178,8 @@ static int test_nfct_cmp_api_single(struct nf_conntrack *ct1,
 	/* FIXME: not implemented comparators: */
 	case ATTR_SNAT_IPV4:
 	case ATTR_DNAT_IPV4:
+	case ATTR_SNAT_IPV6:
+	case ATTR_DNAT_IPV6:
 	case ATTR_SNAT_PORT:
 	case ATTR_DNAT_PORT:
 


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [libnetfilter_conntrack PATCH 2/3] src: add support for IPv6 NAT
  2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 2/3] src: add support for IPv6 NAT Arturo Borrero Gonzalez
@ 2016-05-17 15:38   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2016-05-17 15:38 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel, fw

On Tue, May 17, 2016 at 02:50:37PM +0200, Arturo Borrero Gonzalez wrote:
> The conntrackd daemon lacks support for syncing IPv6 NATed connections.
> 
> This patch adds support for managing the IPv6 part of struct __nfct_nat,
> also updating the corresponsing symbols.
> 
> Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
> ---
>  .../libnetfilter_conntrack.h                       |    2 +
>  src/conntrack/build.c                              |   34 ++++++++++++++++++++
>  src/conntrack/build_mnl.c                          |   34 ++++++++++++++++++++
>  src/conntrack/copy.c                               |   16 +++++++++
>  src/conntrack/getter.c                             |   12 +++++++
>  src/conntrack/objopt.c                             |   26 ++++++++++++++-
>  src/conntrack/setter.c                             |   16 +++++++++
>  7 files changed, 138 insertions(+), 2 deletions(-)
> 
> diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
> index 22af622..6cba578 100644
> --- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h
> +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
> @@ -138,6 +138,8 @@ enum nf_conntrack_attr {
>  	ATTR_CONNLABELS_MASK,			/* variable length */
>  	ATTR_ORIG_ZONE,				/* u16 bits */
>  	ATTR_REPL_ZONE,				/* u16 bits */
> +	ATTR_SNAT_IPV6,				/* u128 bits */
> +	ATTR_DNAT_IPV6,				/* u128 bits */
>  	ATTR_MAX
>  };
>  
> diff --git a/src/conntrack/build.c b/src/conntrack/build.c
> index 10d51fe..0b15230 100644
> --- a/src/conntrack/build.c
> +++ b/src/conntrack/build.c
> @@ -284,6 +284,8 @@ static void __build_nat(struct nfnlhdr *req,
>  			       &nat->min_ip.v4, sizeof(uint32_t));
>  		break;
>  	case AF_INET6:
> +		nfnl_addattr_l(&req->nlh, size, CTA_NAT_MINIP,
> +			       &nat->min_ip.v6, sizeof(struct in6_addr));

This should be CTA_NAT_V6_MINIP instead of CTA_NAT_MINIP.

enum ctattr_nat {
        CTA_NAT_UNSPEC,
        CTA_NAT_V4_MINIP,
#define CTA_NAT_MINIP CTA_NAT_V4_MINIP
        CTA_NAT_V4_MAXIP,
#define CTA_NAT_MAXIP CTA_NAT_V4_MAXIP
        CTA_NAT_PROTO,
        CTA_NAT_V6_MINIP,
        CTA_NAT_V6_MAXIP,
        __CTA_NAT_MAX
};
#define CTA_NAT_MAX (__CTA_NAT_MAX - 1)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [libnetfilter_conntrack PATCH 1/3] src: add support for IPv6 to struct __nfct_nat
  2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 1/3] src: add support for IPv6 to struct __nfct_nat Arturo Borrero Gonzalez
@ 2016-05-17 15:45   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2016-05-17 15:45 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel, fw

On Tue, May 17, 2016 at 02:50:32PM +0200, Arturo Borrero Gonzalez wrote:
> @@ -114,18 +129,34 @@ int __setobjopt(struct nf_conntrack *ct, unsigned int option)
>  
>  static int getobjopt_is_snat(const struct nf_conntrack *ct)
>  {
> -	return ((test_bit(ATTR_STATUS, ct->head.set) ?
> -		ct->status & IPS_SRC_NAT_DONE : 1) &&
> -		ct->repl.dst.v4 != 
> -		ct->head.orig.src.v4);
> +	if (!(test_bit(ATTR_STATUS, ct->head.set) ?
> +		ct->status & IPS_SRC_NAT_DONE : 1))
> +		return 0;

Better untangle this code:

        if (!test_bit(ATTR_STATUS, ct->head.set))
                return 0;

        if (!(ct->status & IPS_SRC_NAT_DONE))
                return 0;

        switch (ct->head.orig.l3protonum) {
        case AF_INET:
                return ct->repl.dst.v4 != ct->head.orig.src.v4;
        default:
                return 0;
        }

> +	switch (ct->head.orig.l3protonum) {
> +	case AF_INET:
> +		return ct->repl.dst.v4 != ct->head.orig.src.v4;
> +	case AF_INET6:
> +		return 0;

It is a bit strange to me that you add in this patch all these:

        case AF_INET6:
                return 0;

I'd rather see you adding this in 2/3 when you implement IPv6 support.

> +	default:
> +		return 0;
> +	}
>  }
>  

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-05-17 15:45 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-17 12:50 [libnetfilter_conntrack PATCH 0/3] support for IPv6 NAT Arturo Borrero Gonzalez
2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 1/3] src: add support for IPv6 to struct __nfct_nat Arturo Borrero Gonzalez
2016-05-17 15:45   ` Pablo Neira Ayuso
2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 2/3] src: add support for IPv6 NAT Arturo Borrero Gonzalez
2016-05-17 15:38   ` Pablo Neira Ayuso
2016-05-17 12:50 ` [libnetfilter_conntrack PATCH 3/3] qa: update test_api with " Arturo Borrero Gonzalez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).