diff options
-rw-r--r-- | include/net/xfrm.h | 19 | ||||
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 4 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 8 |
4 files changed, 28 insertions, 5 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 248874ecf8df..7f1630630dcf 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -869,6 +869,23 @@ xfrm_state_addr_check(struct xfrm_state *x, | |||
869 | return 0; | 869 | return 0; |
870 | } | 870 | } |
871 | 871 | ||
872 | static __inline__ int | ||
873 | xfrm_state_addr_flow_check(struct xfrm_state *x, struct flowi *fl, | ||
874 | unsigned short family) | ||
875 | { | ||
876 | switch (family) { | ||
877 | case AF_INET: | ||
878 | return __xfrm4_state_addr_check(x, | ||
879 | (xfrm_address_t *)&fl->fl4_dst, | ||
880 | (xfrm_address_t *)&fl->fl4_src); | ||
881 | case AF_INET6: | ||
882 | return __xfrm6_state_addr_check(x, | ||
883 | (xfrm_address_t *)&fl->fl6_dst, | ||
884 | (xfrm_address_t *)&fl->fl6_src); | ||
885 | } | ||
886 | return 0; | ||
887 | } | ||
888 | |||
872 | static inline int xfrm_state_kern(struct xfrm_state *x) | 889 | static inline int xfrm_state_kern(struct xfrm_state *x) |
873 | { | 890 | { |
874 | return atomic_read(&x->tunnel_users); | 891 | return atomic_read(&x->tunnel_users); |
@@ -1014,7 +1031,7 @@ extern void xfrm_policy_flush(void); | |||
1014 | extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); | 1031 | extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); |
1015 | extern int xfrm_flush_bundles(void); | 1032 | extern int xfrm_flush_bundles(void); |
1016 | extern void xfrm_flush_all_bundles(void); | 1033 | extern void xfrm_flush_all_bundles(void); |
1017 | extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family); | 1034 | extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family, int strict); |
1018 | extern void xfrm_init_pmtu(struct dst_entry *dst); | 1035 | extern void xfrm_init_pmtu(struct dst_entry *dst); |
1019 | 1036 | ||
1020 | extern wait_queue_head_t km_waitq; | 1037 | extern wait_queue_head_t km_waitq; |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index e517981ceadd..42d8ded0f96a 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -33,7 +33,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | |||
33 | xdst->u.rt.fl.fl4_dst == fl->fl4_dst && | 33 | xdst->u.rt.fl.fl4_dst == fl->fl4_dst && |
34 | xdst->u.rt.fl.fl4_src == fl->fl4_src && | 34 | xdst->u.rt.fl.fl4_src == fl->fl4_src && |
35 | xdst->u.rt.fl.fl4_tos == fl->fl4_tos && | 35 | xdst->u.rt.fl.fl4_tos == fl->fl4_tos && |
36 | xfrm_bundle_ok(xdst, fl, AF_INET)) { | 36 | xfrm_bundle_ok(xdst, fl, AF_INET, 0)) { |
37 | dst_clone(dst); | 37 | dst_clone(dst); |
38 | break; | 38 | break; |
39 | } | 39 | } |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index a3f68c8b737e..729b4748d6d3 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -50,7 +50,9 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | |||
50 | xdst->u.rt6.rt6i_src.plen); | 50 | xdst->u.rt6.rt6i_src.plen); |
51 | if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && | 51 | if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && |
52 | ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && | 52 | ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && |
53 | xfrm_bundle_ok(xdst, fl, AF_INET6)) { | 53 | xfrm_bundle_ok(xdst, fl, AF_INET6, |
54 | (xdst->u.rt6.rt6i_dst.plen != 128 || | ||
55 | xdst->u.rt6.rt6i_src.plen != 128))) { | ||
54 | dst_clone(dst); | 56 | dst_clone(dst); |
55 | break; | 57 | break; |
56 | } | 58 | } |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 56abb5c057d4..ad2a5cba1f5b 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -1167,7 +1167,7 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) | |||
1167 | 1167 | ||
1168 | static int stale_bundle(struct dst_entry *dst) | 1168 | static int stale_bundle(struct dst_entry *dst) |
1169 | { | 1169 | { |
1170 | return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC); | 1170 | return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0); |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) | 1173 | void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) |
@@ -1282,7 +1282,7 @@ EXPORT_SYMBOL(xfrm_init_pmtu); | |||
1282 | * still valid. | 1282 | * still valid. |
1283 | */ | 1283 | */ |
1284 | 1284 | ||
1285 | int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family) | 1285 | int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict) |
1286 | { | 1286 | { |
1287 | struct dst_entry *dst = &first->u.dst; | 1287 | struct dst_entry *dst = &first->u.dst; |
1288 | struct xfrm_dst *last; | 1288 | struct xfrm_dst *last; |
@@ -1304,6 +1304,10 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family) | |||
1304 | if (dst->xfrm->km.state != XFRM_STATE_VALID) | 1304 | if (dst->xfrm->km.state != XFRM_STATE_VALID) |
1305 | return 0; | 1305 | return 0; |
1306 | 1306 | ||
1307 | if (strict && fl && dst->xfrm->props.mode != XFRM_MODE_TUNNEL && | ||
1308 | !xfrm_state_addr_flow_check(dst->xfrm, fl, family)) | ||
1309 | return 0; | ||
1310 | |||
1307 | mtu = dst_mtu(dst->child); | 1311 | mtu = dst_mtu(dst->child); |
1308 | if (xdst->child_mtu_cached != mtu) { | 1312 | if (xdst->child_mtu_cached != mtu) { |
1309 | last = xdst; | 1313 | last = xdst; |