When moving around with my notebook I got annoyed by having
to change the IPsec policies whenever I get a new address.
This patch handles a tunnel source of 0.0.0.0 as special case
and using routing to get the real source address for the
acquire message. I've tested with racoon and it works fine.

Any objections to this?

diff --git a/net/core/wireless.c b/net/core/wireless.c
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -78,6 +78,7 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>                        /* for __init */
 #include <linux/if_arp.h>              /* ARPHRD_ETHER */
+#include <linux/etherdevice.h>
 
 #include <linux/wireless.h>            /* Pretty obvious */
 #include <net/iw_handler.h>            /* New driver API */
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
--- 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/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
--- a/net/ipv6/netfilter/ip6t_mac.c
+++ b/net/ipv6/netfilter/ip6t_mac.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/if_ether.h>
+#include <linux/etherdevice.h>
 
 #include <linux/netfilter_ipv6/ip6t_mac.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
--- 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