diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 7505674c9faa..fdde51f4271a 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -39,6 +39,11 @@ | |||
39 | #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) | 39 | #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) |
40 | #define XFRM_MAX_QUEUE_LEN 100 | 40 | #define XFRM_MAX_QUEUE_LEN 100 |
41 | 41 | ||
42 | struct xfrm_flo { | ||
43 | struct dst_entry *dst_orig; | ||
44 | u8 flags; | ||
45 | }; | ||
46 | |||
42 | static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); | 47 | static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); |
43 | static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] | 48 | static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] |
44 | __read_mostly; | 49 | __read_mostly; |
@@ -1877,13 +1882,14 @@ static int xdst_queue_output(struct sock *sk, struct sk_buff *skb) | |||
1877 | } | 1882 | } |
1878 | 1883 | ||
1879 | static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, | 1884 | static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, |
1880 | struct dst_entry *dst, | 1885 | struct xfrm_flo *xflo, |
1881 | const struct flowi *fl, | 1886 | const struct flowi *fl, |
1882 | int num_xfrms, | 1887 | int num_xfrms, |
1883 | u16 family) | 1888 | u16 family) |
1884 | { | 1889 | { |
1885 | int err; | 1890 | int err; |
1886 | struct net_device *dev; | 1891 | struct net_device *dev; |
1892 | struct dst_entry *dst; | ||
1887 | struct dst_entry *dst1; | 1893 | struct dst_entry *dst1; |
1888 | struct xfrm_dst *xdst; | 1894 | struct xfrm_dst *xdst; |
1889 | 1895 | ||
@@ -1891,9 +1897,12 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, | |||
1891 | if (IS_ERR(xdst)) | 1897 | if (IS_ERR(xdst)) |
1892 | return xdst; | 1898 | return xdst; |
1893 | 1899 | ||
1894 | if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0) | 1900 | if (!(xflo->flags & XFRM_LOOKUP_QUEUE) || |
1901 | net->xfrm.sysctl_larval_drop || | ||
1902 | num_xfrms <= 0) | ||
1895 | return xdst; | 1903 | return xdst; |
1896 | 1904 | ||
1905 | dst = xflo->dst_orig; | ||
1897 | dst1 = &xdst->u.dst; | 1906 | dst1 = &xdst->u.dst; |
1898 | dst_hold(dst); | 1907 | dst_hold(dst); |
1899 | xdst->route = dst; | 1908 | xdst->route = dst; |
@@ -1935,7 +1944,7 @@ static struct flow_cache_object * | |||
1935 | xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, | 1944 | xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, |
1936 | struct flow_cache_object *oldflo, void *ctx) | 1945 | struct flow_cache_object *oldflo, void *ctx) |
1937 | { | 1946 | { |
1938 | struct dst_entry *dst_orig = (struct dst_entry *)ctx; | 1947 | struct xfrm_flo *xflo = (struct xfrm_flo *)ctx; |
1939 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; | 1948 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; |
1940 | struct xfrm_dst *xdst, *new_xdst; | 1949 | struct xfrm_dst *xdst, *new_xdst; |
1941 | int num_pols = 0, num_xfrms = 0, i, err, pol_dead; | 1950 | int num_pols = 0, num_xfrms = 0, i, err, pol_dead; |
@@ -1976,7 +1985,8 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, | |||
1976 | goto make_dummy_bundle; | 1985 | goto make_dummy_bundle; |
1977 | } | 1986 | } |
1978 | 1987 | ||
1979 | new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, dst_orig); | 1988 | new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, |
1989 | xflo->dst_orig); | ||
1980 | if (IS_ERR(new_xdst)) { | 1990 | if (IS_ERR(new_xdst)) { |
1981 | err = PTR_ERR(new_xdst); | 1991 | err = PTR_ERR(new_xdst); |
1982 | if (err != -EAGAIN) | 1992 | if (err != -EAGAIN) |
@@ -2010,7 +2020,7 @@ make_dummy_bundle: | |||
2010 | /* We found policies, but there's no bundles to instantiate: | 2020 | /* We found policies, but there's no bundles to instantiate: |
2011 | * either because the policy blocks, has no transformations or | 2021 | * either because the policy blocks, has no transformations or |
2012 | * we could not build template (no xfrm_states).*/ | 2022 | * we could not build template (no xfrm_states).*/ |
2013 | xdst = xfrm_create_dummy_bundle(net, dst_orig, fl, num_xfrms, family); | 2023 | xdst = xfrm_create_dummy_bundle(net, xflo, fl, num_xfrms, family); |
2014 | if (IS_ERR(xdst)) { | 2024 | if (IS_ERR(xdst)) { |
2015 | xfrm_pols_put(pols, num_pols); | 2025 | xfrm_pols_put(pols, num_pols); |
2016 | return ERR_CAST(xdst); | 2026 | return ERR_CAST(xdst); |
@@ -2104,13 +2114,18 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, | |||
2104 | } | 2114 | } |
2105 | 2115 | ||
2106 | if (xdst == NULL) { | 2116 | if (xdst == NULL) { |
2117 | struct xfrm_flo xflo; | ||
2118 | |||
2119 | xflo.dst_orig = dst_orig; | ||
2120 | xflo.flags = flags; | ||
2121 | |||
2107 | /* To accelerate a bit... */ | 2122 | /* To accelerate a bit... */ |
2108 | if ((dst_orig->flags & DST_NOXFRM) || | 2123 | if ((dst_orig->flags & DST_NOXFRM) || |
2109 | !net->xfrm.policy_count[XFRM_POLICY_OUT]) | 2124 | !net->xfrm.policy_count[XFRM_POLICY_OUT]) |
2110 | goto nopol; | 2125 | goto nopol; |
2111 | 2126 | ||
2112 | flo = flow_cache_lookup(net, fl, family, dir, | 2127 | flo = flow_cache_lookup(net, fl, family, dir, |
2113 | xfrm_bundle_lookup, dst_orig); | 2128 | xfrm_bundle_lookup, &xflo); |
2114 | if (flo == NULL) | 2129 | if (flo == NULL) |
2115 | goto nopol; | 2130 | goto nopol; |
2116 | if (IS_ERR(flo)) { | 2131 | if (IS_ERR(flo)) { |
@@ -2202,7 +2217,8 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, | |||
2202 | const struct flowi *fl, | 2217 | const struct flowi *fl, |
2203 | struct sock *sk, int flags) | 2218 | struct sock *sk, int flags) |
2204 | { | 2219 | { |
2205 | struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, flags); | 2220 | struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, |
2221 | flags | XFRM_LOOKUP_QUEUE); | ||
2206 | 2222 | ||
2207 | if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE) | 2223 | if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE) |
2208 | return make_blackhole(net, dst_orig->ops->family, dst_orig); | 2224 | return make_blackhole(net, dst_orig->ops->family, dst_orig); |
@@ -2476,7 +2492,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | |||
2476 | 2492 | ||
2477 | skb_dst_force(skb); | 2493 | skb_dst_force(skb); |
2478 | 2494 | ||
2479 | dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0); | 2495 | dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, XFRM_LOOKUP_QUEUE); |
2480 | if (IS_ERR(dst)) { | 2496 | if (IS_ERR(dst)) { |
2481 | res = 0; | 2497 | res = 0; |
2482 | dst = NULL; | 2498 | dst = NULL; |