Commit ee51b1b6 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[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: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7b11f69f
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -42,6 +42,21 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
	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;
+17 −0
Original line number Diff line number Diff line
@@ -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 *x, struct flowi *fl,
	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;