diff options
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index d0882e53b6fc..b8bab89616a0 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -29,6 +29,8 @@ | |||
29 | 29 | ||
30 | #include "xfrm_hash.h" | 30 | #include "xfrm_hash.h" |
31 | 31 | ||
32 | int sysctl_xfrm_larval_drop; | ||
33 | |||
32 | DEFINE_MUTEX(xfrm_cfg_mutex); | 34 | DEFINE_MUTEX(xfrm_cfg_mutex); |
33 | EXPORT_SYMBOL(xfrm_cfg_mutex); | 35 | EXPORT_SYMBOL(xfrm_cfg_mutex); |
34 | 36 | ||
@@ -1390,8 +1392,8 @@ static int stale_bundle(struct dst_entry *dst); | |||
1390 | * At the moment we eat a raw IP route. Mostly to speed up lookups | 1392 | * At the moment we eat a raw IP route. Mostly to speed up lookups |
1391 | * on interfaces with disabled IPsec. | 1393 | * on interfaces with disabled IPsec. |
1392 | */ | 1394 | */ |
1393 | int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, | 1395 | int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, |
1394 | struct sock *sk, int flags) | 1396 | struct sock *sk, int flags) |
1395 | { | 1397 | { |
1396 | struct xfrm_policy *policy; | 1398 | struct xfrm_policy *policy; |
1397 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; | 1399 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; |
@@ -1509,6 +1511,13 @@ restart: | |||
1509 | 1511 | ||
1510 | if (unlikely(nx<0)) { | 1512 | if (unlikely(nx<0)) { |
1511 | err = nx; | 1513 | err = nx; |
1514 | if (err == -EAGAIN && sysctl_xfrm_larval_drop) { | ||
1515 | /* EREMOTE tells the caller to generate | ||
1516 | * a one-shot blackhole route. | ||
1517 | */ | ||
1518 | xfrm_pol_put(policy); | ||
1519 | return -EREMOTE; | ||
1520 | } | ||
1512 | if (err == -EAGAIN && flags) { | 1521 | if (err == -EAGAIN && flags) { |
1513 | DECLARE_WAITQUEUE(wait, current); | 1522 | DECLARE_WAITQUEUE(wait, current); |
1514 | 1523 | ||
@@ -1598,6 +1607,21 @@ error: | |||
1598 | *dst_p = NULL; | 1607 | *dst_p = NULL; |
1599 | return err; | 1608 | return err; |
1600 | } | 1609 | } |
1610 | EXPORT_SYMBOL(__xfrm_lookup); | ||
1611 | |||
1612 | int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, | ||
1613 | struct sock *sk, int flags) | ||
1614 | { | ||
1615 | int err = __xfrm_lookup(dst_p, fl, sk, flags); | ||
1616 | |||
1617 | if (err == -EREMOTE) { | ||
1618 | dst_release(*dst_p); | ||
1619 | *dst_p = NULL; | ||
1620 | err = -EAGAIN; | ||
1621 | } | ||
1622 | |||
1623 | return err; | ||
1624 | } | ||
1601 | EXPORT_SYMBOL(xfrm_lookup); | 1625 | EXPORT_SYMBOL(xfrm_lookup); |
1602 | 1626 | ||
1603 | static inline int | 1627 | static inline int |