David S. Miller wrote:
From: Herbert Xu <[EMAIL PROTECTED]>
Date: Fri, 13 Jan 2006 08:06:00 +1100


The only reason I mentioned doing it in userspace is that it gives us
a little bit more flexibility since userspace can choose a different
method to pick the source address.


Note that userspace could override and do something with the zero
source address before the kernel ever gets to see it.

This behavior in the kernel is in line with how socket binding works,
and it's not a bad fallback in the case where we do see a zero tunnel
source addres which frankly has no other sane semantic than the one
Patrick has given to it.

The main point is that putting zero tunnel source address handling
into the kernel does not preclude at all userspace doing something
interesting with it as well.

Therefore I think Patrick's initial kernel patch makes a lot of sense.

Great, here is a properly signed off patch without the extra
hunks.
[XFRM]: IPsec tunnel wildcard address support

When the source address of a tunnel is given as 0.0.0.0 do a routing lookup
to get the real source address for the destination and fill that into the
acquire message. This allows to specify policies like this:

spdadd 172.16.128.13/32 172.16.0.0/20 any -P out ipsec
        esp/tunnel/0.0.0.0-x.x.x.x/require;
spdadd 172.16.0.0/20 172.16.128.13/32 any -P in ipsec
        esp/tunnel/x.x.x.x-0.0.0.0/require;

Signed-off-by: Patrick McHardy <[EMAIL PROTECTED]>

---
commit e1109d524e3ddbe9e4a4704c829ef1c286a1e944
tree 17e3a2059b601790a58cd1d5d3a6cb705754c314
parent b7ad9d284f47611352d759214af371a4b9475dc9
author Patrick McHardy <[EMAIL PROTECTED]> Thu, 12 Jan 2006 22:50:14 +0100
committer Patrick McHardy <[EMAIL PROTECTED]> Thu, 12 Jan 2006 22:50:14 +0100

 net/ipv4/xfrm4_state.c |   15 +++++++++++++++
 net/ipv6/xfrm6_state.c |   17 +++++++++++++++++
 2 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index d23e07f..dbabf81 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -42,6 +42,21 @@ __xfrm4_init_tempsel(struct xfrm_state *
        x->props.saddr = tmpl->saddr;
        if (x->props.saddr.a4 == 0)
                x->props.saddr.a4 = saddr->a4;
+       if (tmpl->mode && x->props.saddr.a4 == 0) {
+               struct rtable *rt;
+               struct flowi fl_tunnel = {
+                       .nl_u = {
+                               .ip4_u = {
+                                       .daddr = x->id.daddr.a4,
+                               }
+                       }
+               };
+               if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
+                                    &fl_tunnel, AF_INET)) {
+                       x->props.saddr.a4 = rt->rt_src;
+                       dst_release(&rt->u.dst);
+               }
+       }
        x->props.mode = tmpl->mode;
        x->props.reqid = tmpl->reqid;
        x->props.family = AF_INET;
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index bf0d0ab..a572302 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -15,6 +15,7 @@
 #include <linux/pfkeyv2.h>
 #include <linux/ipsec.h>
 #include <net/ipv6.h>
+#include <net/addrconf.h>
 
 static struct xfrm_state_afinfo xfrm6_state_afinfo;
 
@@ -41,6 +42,22 @@ __xfrm6_init_tempsel(struct xfrm_state *
        memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
        if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
                memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr));
+       if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) {
+               struct rt6_info *rt;
+               struct flowi fl_tunnel = {
+                       .nl_u = {
+                               .ip6_u = {
+                                       .daddr = *(struct in6_addr *)daddr,
+                               }
+                       }
+               };
+               if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
+                                    &fl_tunnel, AF_INET6)) {
+                       ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr,
+                                      (struct in6_addr *)&x->props.saddr);
+                       dst_release(&rt->u.dst);
+               }
+       }
        x->props.mode = tmpl->mode;
        x->props.reqid = tmpl->reqid;
        x->props.family = AF_INET6;

Reply via email to