[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 <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Patrick McHardy and committed by David S. Miller ee51b1b6 7b11f69f

+32
+15
net/ipv4/xfrm4_state.c
··· 42 x->props.saddr = tmpl->saddr; 43 if (x->props.saddr.a4 == 0) 44 x->props.saddr.a4 = saddr->a4; 45 x->props.mode = tmpl->mode; 46 x->props.reqid = tmpl->reqid; 47 x->props.family = AF_INET;
··· 42 x->props.saddr = tmpl->saddr; 43 if (x->props.saddr.a4 == 0) 44 x->props.saddr.a4 = saddr->a4; 45 + if (tmpl->mode && x->props.saddr.a4 == 0) { 46 + struct rtable *rt; 47 + struct flowi fl_tunnel = { 48 + .nl_u = { 49 + .ip4_u = { 50 + .daddr = x->id.daddr.a4, 51 + } 52 + } 53 + }; 54 + if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, 55 + &fl_tunnel, AF_INET)) { 56 + x->props.saddr.a4 = rt->rt_src; 57 + dst_release(&rt->u.dst); 58 + } 59 + } 60 x->props.mode = tmpl->mode; 61 x->props.reqid = tmpl->reqid; 62 x->props.family = AF_INET;
+17
net/ipv6/xfrm6_state.c
··· 15 #include <linux/pfkeyv2.h> 16 #include <linux/ipsec.h> 17 #include <net/ipv6.h> 18 19 static struct xfrm_state_afinfo xfrm6_state_afinfo; 20 ··· 42 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); 43 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) 44 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); 45 x->props.mode = tmpl->mode; 46 x->props.reqid = tmpl->reqid; 47 x->props.family = AF_INET6;
··· 15 #include <linux/pfkeyv2.h> 16 #include <linux/ipsec.h> 17 #include <net/ipv6.h> 18 + #include <net/addrconf.h> 19 20 static struct xfrm_state_afinfo xfrm6_state_afinfo; 21 ··· 41 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); 42 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) 43 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); 44 + if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) { 45 + struct rt6_info *rt; 46 + struct flowi fl_tunnel = { 47 + .nl_u = { 48 + .ip6_u = { 49 + .daddr = *(struct in6_addr *)daddr, 50 + } 51 + } 52 + }; 53 + if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, 54 + &fl_tunnel, AF_INET6)) { 55 + ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr, 56 + (struct in6_addr *)&x->props.saddr); 57 + dst_release(&rt->u.dst); 58 + } 59 + } 60 x->props.mode = tmpl->mode; 61 x->props.reqid = tmpl->reqid; 62 x->props.family = AF_INET6;