diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-01 17:59:04 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-01 17:59:04 -0500 |
commit | 2774c131b1d19920b4587db1cfbd6f0750ad1f15 (patch) | |
tree | 3a0482c727cf4dcc046a211214f12459dcba8271 /net/xfrm | |
parent | 69ead7afdf6028184f713a77376ee26f8aaafdcd (diff) |
xfrm: Handle blackhole route creation via afinfo.
That way we don't have to potentially do this in every xfrm_lookup()
caller.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index f4c7467a614e..0248afa11cda 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -1735,14 +1735,31 @@ error: | |||
1735 | return ERR_PTR(err); | 1735 | return ERR_PTR(err); |
1736 | } | 1736 | } |
1737 | 1737 | ||
1738 | static struct dst_entry *make_blackhole(struct net *net, u16 family, | ||
1739 | struct dst_entry *dst_orig) | ||
1740 | { | ||
1741 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | ||
1742 | struct dst_entry *ret; | ||
1743 | |||
1744 | if (!afinfo) { | ||
1745 | dst_release(dst_orig); | ||
1746 | ret = ERR_PTR(-EINVAL); | ||
1747 | } else { | ||
1748 | ret = afinfo->blackhole_route(net, dst_orig); | ||
1749 | } | ||
1750 | xfrm_policy_put_afinfo(afinfo); | ||
1751 | |||
1752 | return ret; | ||
1753 | } | ||
1754 | |||
1738 | /* Main function: finds/creates a bundle for given flow. | 1755 | /* Main function: finds/creates a bundle for given flow. |
1739 | * | 1756 | * |
1740 | * At the moment we eat a raw IP route. Mostly to speed up lookups | 1757 | * At the moment we eat a raw IP route. Mostly to speed up lookups |
1741 | * on interfaces with disabled IPsec. | 1758 | * on interfaces with disabled IPsec. |
1742 | */ | 1759 | */ |
1743 | int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, | 1760 | int xfrm_lookup(struct net *net, struct dst_entry **dst_p, |
1744 | const struct flowi *fl, | 1761 | const struct flowi *fl, |
1745 | struct sock *sk, int flags) | 1762 | struct sock *sk, int flags) |
1746 | { | 1763 | { |
1747 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; | 1764 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; |
1748 | struct flow_cache_object *flo; | 1765 | struct flow_cache_object *flo; |
@@ -1829,7 +1846,12 @@ restart: | |||
1829 | dst_release(dst); | 1846 | dst_release(dst); |
1830 | xfrm_pols_put(pols, drop_pols); | 1847 | xfrm_pols_put(pols, drop_pols); |
1831 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); | 1848 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1832 | return -EREMOTE; | 1849 | |
1850 | dst = make_blackhole(net, family, dst_orig); | ||
1851 | if (IS_ERR(dst)) | ||
1852 | return PTR_ERR(dst); | ||
1853 | *dst_p = dst; | ||
1854 | return 0; | ||
1833 | } | 1855 | } |
1834 | if (fl->flags & FLOWI_FLAG_CAN_SLEEP) { | 1856 | if (fl->flags & FLOWI_FLAG_CAN_SLEEP) { |
1835 | DECLARE_WAITQUEUE(wait, current); | 1857 | DECLARE_WAITQUEUE(wait, current); |
@@ -1895,22 +1917,6 @@ dropdst: | |||
1895 | xfrm_pols_put(pols, drop_pols); | 1917 | xfrm_pols_put(pols, drop_pols); |
1896 | return err; | 1918 | return err; |
1897 | } | 1919 | } |
1898 | EXPORT_SYMBOL(__xfrm_lookup); | ||
1899 | |||
1900 | int xfrm_lookup(struct net *net, struct dst_entry **dst_p, | ||
1901 | const struct flowi *fl, | ||
1902 | struct sock *sk, int flags) | ||
1903 | { | ||
1904 | int err = __xfrm_lookup(net, dst_p, fl, sk, flags); | ||
1905 | |||
1906 | if (err == -EREMOTE) { | ||
1907 | dst_release(*dst_p); | ||
1908 | *dst_p = NULL; | ||
1909 | err = -EAGAIN; | ||
1910 | } | ||
1911 | |||
1912 | return err; | ||
1913 | } | ||
1914 | EXPORT_SYMBOL(xfrm_lookup); | 1920 | EXPORT_SYMBOL(xfrm_lookup); |
1915 | 1921 | ||
1916 | static inline int | 1922 | static inline int |