diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-11-13 21:37:28 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 14:53:42 -0800 |
commit | 66cdb3ca27323a92712d289fc5edc7841d74a139 (patch) | |
tree | 443c864e4cab413743c3ca755a50f8a5d0ec300d /net/ipv4/xfrm4_policy.c | |
parent | f04e7e8d7f175c05bbde3ae748bf2541da53721d (diff) |
[IPSEC]: Move flow construction into xfrm_dst_lookup
This patch moves the flow construction from the callers of
xfrm_dst_lookup into that function. It also changes xfrm_dst_lookup
so that it takes an xfrm state as its argument instead of explicit
addresses.
This removes any address-specific logic from the callers of
xfrm_dst_lookup which is needed to correctly support inter-family
transforms.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/xfrm4_policy.c')
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 80 |
1 files changed, 38 insertions, 42 deletions
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index d903c8bdffcd..cebc84731969 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -8,7 +8,8 @@ * */ -#include <linux/compiler.h> +#include <linux/err.h> +#include <linux/kernel.h> #include <linux/inetdevice.h> #include <net/dst.h> #include <net/xfrm.h> @@ -17,28 +18,44 @@ static struct dst_ops xfrm4_dst_ops; static struct xfrm_policy_afinfo xfrm4_policy_afinfo; -static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) +static struct dst_entry *xfrm4_dst_lookup(int tos, xfrm_address_t *saddr, + xfrm_address_t *daddr) { - return __ip_route_output_key((struct rtable**)dst, fl); -} - -static int xfrm4_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) -{ - struct rtable *rt; - struct flowi fl_tunnel = { + struct flowi fl = { .nl_u = { .ip4_u = { + .tos = tos, .daddr = daddr->a4, }, }, }; + struct dst_entry *dst; + struct rtable *rt; + int err; - if (!xfrm4_dst_lookup((struct xfrm_dst **)&rt, &fl_tunnel)) { - saddr->a4 = rt->rt_src; - dst_release(&rt->u.dst); - return 0; - } - return -EHOSTUNREACH; + if (saddr) + fl.fl4_src = saddr->a4; + + err = __ip_route_output_key(&rt, &fl); + dst = &rt->u.dst; + if (err) + dst = ERR_PTR(err); + return dst; +} + +static int xfrm4_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) +{ + struct dst_entry *dst; + struct rtable *rt; + + dst = xfrm4_dst_lookup(0, NULL, daddr); + if (IS_ERR(dst)) + return -EHOSTUNREACH; + + rt = (struct rtable *)dst; + saddr->a4 = rt->rt_src; + dst_release(dst); + return 0; } static struct dst_entry * @@ -73,15 +90,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int struct dst_entry *dst, *dst_prev; struct rtable *rt0 = (struct rtable*)(*dst_p); struct rtable *rt = rt0; - struct flowi fl_tunnel = { - .nl_u = { - .ip4_u = { - .saddr = fl->fl4_src, - .daddr = fl->fl4_dst, - .tos = fl->fl4_tos - } - } - }; + int tos = fl->fl4_tos; int i; int err; int header_len = 0; @@ -119,25 +128,12 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int trailer_len += xfrm[i]->props.trailer_len; if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { - unsigned short encap_family = xfrm[i]->props.family; - switch (encap_family) { - case AF_INET: - fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4; - fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4; - break; -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) - case AF_INET6: - ipv6_addr_copy(&fl_tunnel.fl6_dst, (struct in6_addr*)&xfrm[i]->id.daddr.a6); - ipv6_addr_copy(&fl_tunnel.fl6_src, (struct in6_addr*)&xfrm[i]->props.saddr.a6); - break; -#endif - default: - BUG_ON(1); - } - err = xfrm_dst_lookup((struct xfrm_dst **)&rt, - &fl_tunnel, encap_family); - if (err) + dst1 = xfrm_dst_lookup(xfrm[i], tos); + err = PTR_ERR(dst1); + if (IS_ERR(dst1)) goto error; + + rt = (struct rtable *)dst1; } else dst_hold(&rt->u.dst); } |