Re: [PATCH net-next-2.6 0/5] XFRM,IPv6: Removal of RH2/HAO from IPsec-protected MIPv6 traffic

Previous thread: Re: [PATCH net-next-2.6 0/5] XFRM,IPv6: Removal of RH2/HAO from IPsec-protected MIPv6 traffic by David Miller on Friday, September 24, 2010 - 12:01 pm. (2 messages)

Next thread: [PATCH] ipv6: add a missing unregister_pernet_subsys call by Neil Horman on Friday, September 24, 2010 - 12:55 pm. (2 messages)
From: Arnaud Ebalard
Date: Friday, September 24, 2010 - 12:18 pm

Hi,

First off, patches for discussion are in following emails. They are
*against current linux-2.6* (on which they were tested) but will be
rebased against net-next-2.6 for next round.

Simply put, the patches provides the ability to remove annoying Routing
Header Type 2 and Destination Options Header with Home Address Option
from IPsec-protected MIPv6 signaling traffic, changing on-wire format
from:


    MN  ------------ IPv6() / HAO / ESP(BU) ----------> HA
    MN  <----------- IPv6() / RH2 / ESP(BA) ----------- HA

to 

    MN  ------------ IPv6() / ESP(BU) --------------> HA
    MN  <----------- IPv6() / ESP(BA) --------------- HA


This is an *self-contained* part of a set of additional enhancements for
Mobile IPv6 when used w/ IPsec and IKE specified in IRO draft [1]. Once 
available, this can also be extended to IPsec-protected route optimized
communications between MN and CN/MN.

Among the operational benefits of the feature is the ability to run in
networks in which (dumb) firewalls drop Routing Headers (Cisco PIX
firewalls are known to do that by default and w/o ways of correcting the
issue). Anonimity is another.

Basically, RH2/HAO are only *explicit* containers for the Home Address
(HoA), which is obviously available in the IPsec stack (transport mode
SA protecting traffic use the HoA). This means that the info is
available on both sides and there is no real need to carry it explictly.

From an implementation standpoint, some changes are required to allow
finding the SA when the addresses are not expected ones and remap them
if asked to do so (or act as usual if not). Then, most of the other
changes are basically simple versions of what can be found at the moment
for RH2 and HAO in DestOpt handling. Unlike what happens with RH2/HAO,
packets structure is never modified.

I rely on the feature on my MN (my laptop) and HA for 2 kernel versions
to provide me with connectivity (v4 networks are handled using
m6t [1]). Patches for UMIP [2] are available and ...
From: Arnaud Ebalard
Date: Friday, September 24, 2010 - 12:21 pm

In the new IPsec architecture [RFC4301], "for an SA used to carry
unicast traffic, the Security Parameters Index (SPI) by itself
suffices to specify an SA".  Section 4.1 of [RFC4301] provides
additional guidance on the topic.

In the old IPsec architecture [RFC2401], a SA "is uniquely identified
by a triple consisting of a Security Parameter Index (SPI), an IP
Destination Address and a security protocol (AH or ESP) identifier".

If an IPsec stack only supports the behavior mandated by the old
IPsec architecture, SAD lookup on inbound packets require the use of
both the SPI and the destination address of the SA.

For inbound IPsec traffic, IRO remapping rules may exist on the MN to
remap the destination address (CoA) into the HoA.  In that case, by
design, the address found in the destination address field of the
packet (CoA) does not match the one in the SA (HoA).

At the moment, Linux XFRM stack includes the address when computing
the hash to perform state lookup by SPI. This patch changes XFRM
state hash computation to prevent destination address to be
used. This will later allow finding states for packets w/ mangled
destination addresses.

Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
---
 net/xfrm/xfrm_hash.h  |   21 +--------------------
 net/xfrm/xfrm_state.c |   20 ++++++++------------
 2 files changed, 9 insertions(+), 32 deletions(-)

diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h
index 8e69533..19eeee7 100644
--- a/net/xfrm/xfrm_hash.h
+++ b/net/xfrm/xfrm_hash.h
@@ -4,16 +4,6 @@
 #include <linux/xfrm.h>
 #include <linux/socket.h>
 
-static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr)
-{
-	return ntohl(addr->a4);
-}
-
-static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr)
-{
-	return ntohl(addr->a6[2] ^ addr->a6[3]);
-}
-
 static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr)
 {
 	u32 sum = (__force u32)daddr->a4 + (__force u32)saddr->a4;
@@ -60,18 +50,9 @@ static ...
From: Arnaud Ebalard
Date: Friday, September 24, 2010 - 12:22 pm

This patch introduces IRO recv sockopts, in order for userland processes
(e.g. UMIP) to access on-wire source or destination addresses found in
incoming (IPsec-protected) packets as they were before remapping by IRO.
The socket options are respectively IPV6_RECVIROSRC and IPV6_RECVIRODST.

Basically, the two recv socket options are similar in their purpose to
their generic RH2/HAO counterparts defined in RFC 3542 (IPV6_RECVIROSRC
<->  IPV6_RECVDSTOPTS, IPV6_RECVIRODST <-> IPV6_RECVRTHDR). They differ
on the following aspects:

 - IRO reporting sockopts only work on incoming IPsec-protected packets
   Userspace will never get IRO remapped address report for common
   (non protected) packets.
 - The receiver gets the original source/desination address (IRO
   remapping) from its IPsec stack.
 - as IRO sockopts only deal with addresses, no specific structure is
   defined, i.e. struct in6_addr is used to pass info.

As we only interact with IPsec protected packets, struct sec_path is
used to carry information (addresses) for incoming packets that have
undergone remapping process.

Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
---
 include/linux/in6.h      |    7 +++++++
 include/linux/ipv6.h     |    4 +++-
 include/net/xfrm.h       |    5 +++++
 net/ipv6/datagram.c      |   18 ++++++++++++++++++
 net/ipv6/ipv6_sockglue.c |   26 ++++++++++++++++++++++++++
 5 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/include/linux/in6.h b/include/linux/in6.h
index c4bf46f..52a98ab 100644
--- a/include/linux/in6.h
+++ b/include/linux/in6.h
@@ -283,4 +283,11 @@ struct in6_flowlabel_req {
  * MRT6_PIM			208
  * (reserved)			209
  */
+
+/* IRO (IPsec Route Optimization) sockopts */
+#define IPV6_RECVIROSRC         74
+#define IPV6_IROSRC		75
+#define IPV6_RECVIRODST         76
+#define IPV6_IRODST		77
+
 #endif
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index e62683b..55289ee 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ ...
From: Arnaud Ebalard
Date: Friday, September 24, 2010 - 12:24 pm

Add IRO source and destination remapping XFRM types and associated
input/output handlers. This allows userland to install such states
in order to support remapping of source or destination address
of packet. They basically work like existing RH2 and HAO ones; the
main difference is that output handlers do not expand the packet by
adding an extension header: they simply change the source or
destination in place. Input handlers are almost the same as RH2/HAO
version in their behavior, but they are triggered differently. RH2
and HAO handlers are triggered based on structures found in the
packet. On input, IRO states (and associated handlers) are looked
up when processing an IPsec-protected packet, when there is an
address mismatch.

Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
---
 include/net/xfrm.h       |    2 +
 net/ipv6/mip6.c          |  140 ++++++++++++++++++++++++++++++++++++++++++++++
 net/ipv6/xfrm6_mode_ro.c |   11 +++-
 net/xfrm/xfrm_user.c     |    2 +
 4 files changed, 154 insertions(+), 1 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index f35bade..7ac6abe 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -35,6 +35,8 @@
 #define XFRM_PROTO_IPV6		41
 #define XFRM_PROTO_ROUTING	IPPROTO_ROUTING
 #define XFRM_PROTO_DSTOPTS	IPPROTO_DSTOPTS
+#define XFRM_PROTO_IRO_SRC      127
+#define XFRM_PROTO_IRO_DST      128
 
 #define XFRM_ALIGN8(len)	(((len) + 7) & ~7)
 #define MODULE_ALIAS_XFRM_MODE(family, encap) \
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index d6e9599..b52c651 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -477,6 +477,130 @@ static const struct xfrm_type mip6_rthdr_type =
 	.hdr_offset	= mip6_rthdr_offset,
 };
 
+/* IRO equivalent of mip6_destopt_input(): handles incoming packet with a
+ * source address different from the one expected in the SA: check that
+ * received source address is indeed the CoA we expected (or any address
+ * if the state references the unspecified address '::') */
+static ...
From: Arnaud Ebalard
Date: Friday, September 24, 2010 - 12:25 pm

Add a hook in xfrm_input() to allow IRO remapping to occur when
an incoming packet matching an existing SA (based on SPI) with
an unexpected destination or source address is received.
Because IRO does not consume additional bits in a packet (that's
the point), there is no way to demultiplex based on something
like nh or spi. Instead, IRO input handlers (for source and
destination address remapping) are called upon address mismatch
during IPsec processing.
For that to work, we rely on the fact that SPI values generated
locally are no more linked to destination address (first patch
of the set) and we postpone a bit the expected address check in
xfrm_input() (inside xfrm_state_lookup() against daddr param) by
introducing xfrm_input_addr_check() helper.

Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
---
 include/net/xfrm.h     |    3 ++
 net/ipv4/xfrm4_input.c |   12 +++++++++
 net/ipv6/xfrm6_input.c |   65 +++++++++++++++++++++++++++++++++++++++++++++++-
 net/xfrm/xfrm_input.c  |   25 ++++++++++++++++--
 net/xfrm/xfrm_state.c  |    2 +-
 5 files changed, 102 insertions(+), 5 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 7ac6abe..61a0562 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -623,6 +623,7 @@ struct xfrm_spi_skb_cb {
 		struct inet6_skb_parm h6;
 	} header;
 
+	unsigned int saddroff;
 	unsigned int daddroff;
 	unsigned int family;
 };
@@ -1405,6 +1406,7 @@ extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
 			   int encap_type);
 extern int xfrm4_transport_finish(struct sk_buff *skb, int async);
 extern int xfrm4_rcv(struct sk_buff *skb);
+extern int xfrm4_input_addr_check(struct sk_buff *skb, struct xfrm_state *x);
 
 static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
 {
@@ -1423,6 +1425,7 @@ extern int xfrm6_transport_finish(struct sk_buff *skb, int async);
 extern int xfrm6_rcv(struct sk_buff *skb);
 extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t ...
From: Arnaud Ebalard
Date: Friday, September 24, 2010 - 12:26 pm

This provides the ability to remap src/dst address using IRO
via ancillary data passed to sockets. This is the IRO equivalent
of what is done for RH2/HAO (i.e. IPV6_RTHDR/IPV6_DSTOPTS).
This is used by UMIP during BA emission when acting as a Home
Agent.

Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
---
 include/net/ipv6.h       |    4 ++++
 net/ipv6/datagram.c      |   20 ++++++++++++++++++++
 net/ipv6/exthdrs.c       |   19 +++++++++++++------
 net/ipv6/ip6_flowlabel.c |    7 +++++++
 net/ipv6/ip6_output.c    |   22 ++++++++++++++++++++++
 net/ipv6/raw.c           |    3 ++-
 6 files changed, 68 insertions(+), 7 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 1f84124..9dbc4f7 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -188,6 +188,10 @@ struct ipv6_txoptions {
 	struct ipv6_rt_hdr	*srcrt;	/* Routing Header */
 	struct ipv6_opt_hdr	*dst1opt;
 
+	/* XXX protect those via some ifdef e.g. CONFIG_XFRM_SUB_POLICY ? */
+	struct in6_addr         *iro_src;
+	struct in6_addr         *iro_dst;
+
 	/* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */
 };
 
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 2952c9e..0ac7adf 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -757,6 +757,26 @@ int datagram_send_ctl(struct net *net,
 			}
 			break;
 
+#ifdef CONFIG_XFRM_SUB_POLICY
+		case IPV6_IROSRC:
+		case IPV6_IRODST:
+			if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_addr))) {
+				err = -EINVAL;
+				goto exit_f;
+			}
+
+			if (!capable(CAP_NET_RAW)) {
+				err = -EPERM;
+				goto exit_f;
+			}
+
+			if (cmsg->cmsg_type == IPV6_IROSRC)
+				opt->iro_src = (struct in6_addr *)CMSG_DATA(cmsg);
+			else
+				opt->iro_dst = (struct in6_addr *)CMSG_DATA(cmsg);
+			break;
+#endif
+
 		case IPV6_2292RTHDR:
 		case IPV6_RTHDR:
 			if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_rt_hdr))) {
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 262f105..e480b06 100644
--- ...
From: David Miller
Date: Monday, September 27, 2010 - 9:25 pm

Please resubmit this after you've done some more exhaustive
build testing:

---
net/ipv6/xfrm6_input.c: In function ‘xfrm6_input_addr_check’:
net/ipv6/xfrm6_input.c:173: error: implicit declaration of function ‘ipv6_chk_home_addr’
net/ipv6/xfrm6_input.c:179: error: ‘struct sec_path’ has no member named ‘irodst’
net/ipv6/xfrm6_input.c:202: error: ‘struct sec_path’ has no member named ‘irosrc’
---
davem@sunset:~/src/GIT/net-next-2.6$ egrep XFRM .config
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_XFRM_MIGRATE=y
# CONFIG_XFRM_STATISTICS is not set
CONFIG_XFRM_IPCOMP=y
CONFIG_INET_XFRM_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_XFRM_MODE_TRANSPORT=m
CONFIG_INET6_XFRM_MODE_TUNNEL=m
CONFIG_INET6_XFRM_MODE_BEET=m
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
davem@sunset:~/src/GIT/net-next-2.6$ 
From: Arnaud Ebalard
Date: Tuesday, September 28, 2010 - 8:53 am

Hi David,


I spent some time on it today. An updated version follows. 
--

Previous thread: Re: [PATCH net-next-2.6 0/5] XFRM,IPv6: Removal of RH2/HAO from IPsec-protected MIPv6 traffic by David Miller on Friday, September 24, 2010 - 12:01 pm. (2 messages)

Next thread: [PATCH] ipv6: add a missing unregister_pernet_subsys call by Neil Horman on Friday, September 24, 2010 - 12:55 pm. (2 messages)