aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/xfrm4_policy.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-11-14 00:37:28 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:53:42 -0500
commit66cdb3ca27323a92712d289fc5edc7841d74a139 (patch)
tree443c864e4cab413743c3ca755a50f8a5d0ec300d /net/ipv4/xfrm4_policy.c
parentf04e7e8d7f175c05bbde3ae748bf2541da53721d (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.c80
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 @@
8 * 8 *
9 */ 9 */
10 10
11#include <linux/compiler.h> 11#include <linux/err.h>
12#include <linux/kernel.h>
12#include <linux/inetdevice.h> 13#include <linux/inetdevice.h>
13#include <net/dst.h> 14#include <net/dst.h>
14#include <net/xfrm.h> 15#include <net/xfrm.h>
@@ -17,28 +18,44 @@
17static struct dst_ops xfrm4_dst_ops; 18static struct dst_ops xfrm4_dst_ops;
18static struct xfrm_policy_afinfo xfrm4_policy_afinfo; 19static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
19 20
20static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) 21static struct dst_entry *xfrm4_dst_lookup(int tos, xfrm_address_t *saddr,
22 xfrm_address_t *daddr)
21{ 23{
22 return __ip_route_output_key((struct rtable**)dst, fl); 24 struct flowi fl = {
23}
24
25static int xfrm4_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
26{
27 struct rtable *rt;
28 struct flowi fl_tunnel = {
29 .nl_u = { 25 .nl_u = {
30 .ip4_u = { 26 .ip4_u = {
27 .tos = tos,
31 .daddr = daddr->a4, 28 .daddr = daddr->a4,
32 }, 29 },
33 }, 30 },
34 }; 31 };
32 struct dst_entry *dst;
33 struct rtable *rt;
34 int err;
35 35
36 if (!xfrm4_dst_lookup((struct xfrm_dst **)&rt, &fl_tunnel)) { 36 if (saddr)
37 saddr->a4 = rt->rt_src; 37 fl.fl4_src = saddr->a4;
38 dst_release(&rt->u.dst); 38
39 return 0; 39 err = __ip_route_output_key(&rt, &fl);
40 } 40 dst = &rt->u.dst;
41 return -EHOSTUNREACH; 41 if (err)
42 dst = ERR_PTR(err);
43 return dst;
44}
45
46static int xfrm4_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
47{
48 struct dst_entry *dst;
49 struct rtable *rt;
50
51 dst = xfrm4_dst_lookup(0, NULL, daddr);
52 if (IS_ERR(dst))
53 return -EHOSTUNREACH;
54
55 rt = (struct rtable *)dst;
56 saddr->a4 = rt->rt_src;
57 dst_release(dst);
58 return 0;
42} 59}
43 60
44static struct dst_entry * 61static struct dst_entry *
@@ -73,15 +90,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
73 struct dst_entry *dst, *dst_prev; 90 struct dst_entry *dst, *dst_prev;
74 struct rtable *rt0 = (struct rtable*)(*dst_p); 91 struct rtable *rt0 = (struct rtable*)(*dst_p);
75 struct rtable *rt = rt0; 92 struct rtable *rt = rt0;
76 struct flowi fl_tunnel = { 93 int tos = fl->fl4_tos;
77 .nl_u = {
78 .ip4_u = {
79 .saddr = fl->fl4_src,
80 .daddr = fl->fl4_dst,
81 .tos = fl->fl4_tos
82 }
83 }
84 };
85 int i; 94 int i;
86 int err; 95 int err;
87 int header_len = 0; 96 int header_len = 0;
@@ -119,25 +128,12 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
119 trailer_len += xfrm[i]->props.trailer_len; 128 trailer_len += xfrm[i]->props.trailer_len;
120 129
121 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { 130 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
122 unsigned short encap_family = xfrm[i]->props.family; 131 dst1 = xfrm_dst_lookup(xfrm[i], tos);
123 switch (encap_family) { 132 err = PTR_ERR(dst1);
124 case AF_INET: 133 if (IS_ERR(dst1))
125 fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4;
126 fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;
127 break;
128#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
129 case AF_INET6:
130 ipv6_addr_copy(&fl_tunnel.fl6_dst, (struct in6_addr*)&xfrm[i]->id.daddr.a6);
131 ipv6_addr_copy(&fl_tunnel.fl6_src, (struct in6_addr*)&xfrm[i]->props.saddr.a6);
132 break;
133#endif
134 default:
135 BUG_ON(1);
136 }
137 err = xfrm_dst_lookup((struct xfrm_dst **)&rt,
138 &fl_tunnel, encap_family);
139 if (err)
140 goto error; 134 goto error;
135
136 rt = (struct rtable *)dst1;
141 } else 137 } else
142 dst_hold(&rt->u.dst); 138 dst_hold(&rt->u.dst);
143 } 139 }