diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-11-14 00:37:28 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:53:42 -0500 |
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 @@ | |||
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 @@ | |||
17 | static struct dst_ops xfrm4_dst_ops; | 18 | static struct dst_ops xfrm4_dst_ops; |
18 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo; | 19 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo; |
19 | 20 | ||
20 | static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) | 21 | static 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 | |||
25 | static 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 | |||
46 | static 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 | ||
44 | static struct dst_entry * | 61 | static 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 | } |