diff options
Diffstat (limited to 'net/ipv4/xfrm4_policy.c')
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 8f50eae47d03..eabcd27b1767 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -21,6 +21,25 @@ static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) | |||
21 | return __ip_route_output_key((struct rtable**)dst, fl); | 21 | return __ip_route_output_key((struct rtable**)dst, fl); |
22 | } | 22 | } |
23 | 23 | ||
24 | static int xfrm4_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) | ||
25 | { | ||
26 | struct rtable *rt; | ||
27 | struct flowi fl_tunnel = { | ||
28 | .nl_u = { | ||
29 | .ip4_u = { | ||
30 | .daddr = daddr->a4, | ||
31 | }, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | if (!xfrm4_dst_lookup((struct xfrm_dst **)&rt, &fl_tunnel)) { | ||
36 | saddr->a4 = rt->rt_src; | ||
37 | dst_release(&rt->u.dst); | ||
38 | return 0; | ||
39 | } | ||
40 | return -EHOSTUNREACH; | ||
41 | } | ||
42 | |||
24 | static struct dst_entry * | 43 | static struct dst_entry * |
25 | __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | 44 | __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) |
26 | { | 45 | { |
@@ -33,7 +52,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | |||
33 | xdst->u.rt.fl.fl4_dst == fl->fl4_dst && | 52 | xdst->u.rt.fl.fl4_dst == fl->fl4_dst && |
34 | xdst->u.rt.fl.fl4_src == fl->fl4_src && | 53 | xdst->u.rt.fl.fl4_src == fl->fl4_src && |
35 | xdst->u.rt.fl.fl4_tos == fl->fl4_tos && | 54 | xdst->u.rt.fl.fl4_tos == fl->fl4_tos && |
36 | xfrm_bundle_ok(xdst, fl, AF_INET)) { | 55 | xfrm_bundle_ok(xdst, fl, AF_INET, 0)) { |
37 | dst_clone(dst); | 56 | dst_clone(dst); |
38 | break; | 57 | break; |
39 | } | 58 | } |
@@ -93,10 +112,11 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
93 | 112 | ||
94 | xdst = (struct xfrm_dst *)dst1; | 113 | xdst = (struct xfrm_dst *)dst1; |
95 | xdst->route = &rt->u.dst; | 114 | xdst->route = &rt->u.dst; |
115 | xdst->genid = xfrm[i]->genid; | ||
96 | 116 | ||
97 | dst1->next = dst_prev; | 117 | dst1->next = dst_prev; |
98 | dst_prev = dst1; | 118 | dst_prev = dst1; |
99 | if (xfrm[i]->props.mode) { | 119 | if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { |
100 | remote = xfrm[i]->id.daddr.a4; | 120 | remote = xfrm[i]->id.daddr.a4; |
101 | local = xfrm[i]->props.saddr.a4; | 121 | local = xfrm[i]->props.saddr.a4; |
102 | tunnel = 1; | 122 | tunnel = 1; |
@@ -135,6 +155,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
135 | dst_prev->flags |= DST_HOST; | 155 | dst_prev->flags |= DST_HOST; |
136 | dst_prev->lastuse = jiffies; | 156 | dst_prev->lastuse = jiffies; |
137 | dst_prev->header_len = header_len; | 157 | dst_prev->header_len = header_len; |
158 | dst_prev->nfheader_len = 0; | ||
138 | dst_prev->trailer_len = trailer_len; | 159 | dst_prev->trailer_len = trailer_len; |
139 | memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics)); | 160 | memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics)); |
140 | 161 | ||
@@ -296,6 +317,7 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { | |||
296 | .family = AF_INET, | 317 | .family = AF_INET, |
297 | .dst_ops = &xfrm4_dst_ops, | 318 | .dst_ops = &xfrm4_dst_ops, |
298 | .dst_lookup = xfrm4_dst_lookup, | 319 | .dst_lookup = xfrm4_dst_lookup, |
320 | .get_saddr = xfrm4_get_saddr, | ||
299 | .find_bundle = __xfrm4_find_bundle, | 321 | .find_bundle = __xfrm4_find_bundle, |
300 | .bundle_create = __xfrm4_bundle_create, | 322 | .bundle_create = __xfrm4_bundle_create, |
301 | .decode_session = _decode_session4, | 323 | .decode_session = _decode_session4, |