aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c66
1 files changed, 36 insertions, 30 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 41a91d27d3ea..b1932a629ef8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1735,19 +1735,36 @@ error:
1735 return ERR_PTR(err); 1735 return ERR_PTR(err);
1736} 1736}
1737 1737
1738static 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 */
1743int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, 1760struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
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;
1749 struct xfrm_dst *xdst; 1766 struct xfrm_dst *xdst;
1750 struct dst_entry *dst, *dst_orig = *dst_p, *route; 1767 struct dst_entry *dst, *route;
1751 u16 family = dst_orig->ops->family; 1768 u16 family = dst_orig->ops->family;
1752 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); 1769 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
1753 int i, err, num_pols, num_xfrms = 0, drop_pols = 0; 1770 int i, err, num_pols, num_xfrms = 0, drop_pols = 0;
@@ -1829,9 +1846,10 @@ 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 return make_blackhole(net, family, dst_orig);
1833 } 1851 }
1834 if (flags & XFRM_LOOKUP_WAIT) { 1852 if (fl->flags & FLOWI_FLAG_CAN_SLEEP) {
1835 DECLARE_WAITQUEUE(wait, current); 1853 DECLARE_WAITQUEUE(wait, current);
1836 1854
1837 add_wait_queue(&net->xfrm.km_waitq, &wait); 1855 add_wait_queue(&net->xfrm.km_waitq, &wait);
@@ -1873,43 +1891,28 @@ no_transform:
1873 goto error; 1891 goto error;
1874 } else if (num_xfrms > 0) { 1892 } else if (num_xfrms > 0) {
1875 /* Flow transformed */ 1893 /* Flow transformed */
1876 *dst_p = dst;
1877 dst_release(dst_orig); 1894 dst_release(dst_orig);
1878 } else { 1895 } else {
1879 /* Flow passes untransformed */ 1896 /* Flow passes untransformed */
1880 dst_release(dst); 1897 dst_release(dst);
1898 dst = dst_orig;
1881 } 1899 }
1882ok: 1900ok:
1883 xfrm_pols_put(pols, drop_pols); 1901 xfrm_pols_put(pols, drop_pols);
1884 return 0; 1902 return dst;
1885 1903
1886nopol: 1904nopol:
1887 if (!(flags & XFRM_LOOKUP_ICMP)) 1905 if (!(flags & XFRM_LOOKUP_ICMP)) {
1906 dst = dst_orig;
1888 goto ok; 1907 goto ok;
1908 }
1889 err = -ENOENT; 1909 err = -ENOENT;
1890error: 1910error:
1891 dst_release(dst); 1911 dst_release(dst);
1892dropdst: 1912dropdst:
1893 dst_release(dst_orig); 1913 dst_release(dst_orig);
1894 *dst_p = NULL;
1895 xfrm_pols_put(pols, drop_pols); 1914 xfrm_pols_put(pols, drop_pols);
1896 return err; 1915 return ERR_PTR(err);
1897}
1898EXPORT_SYMBOL(__xfrm_lookup);
1899
1900int 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} 1916}
1914EXPORT_SYMBOL(xfrm_lookup); 1917EXPORT_SYMBOL(xfrm_lookup);
1915 1918
@@ -2169,7 +2172,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
2169 struct net *net = dev_net(skb->dev); 2172 struct net *net = dev_net(skb->dev);
2170 struct flowi fl; 2173 struct flowi fl;
2171 struct dst_entry *dst; 2174 struct dst_entry *dst;
2172 int res; 2175 int res = 0;
2173 2176
2174 if (xfrm_decode_session(skb, &fl, family) < 0) { 2177 if (xfrm_decode_session(skb, &fl, family) < 0) {
2175 XFRM_INC_STATS(net, LINUX_MIB_XFRMFWDHDRERROR); 2178 XFRM_INC_STATS(net, LINUX_MIB_XFRMFWDHDRERROR);
@@ -2177,9 +2180,12 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
2177 } 2180 }
2178 2181
2179 skb_dst_force(skb); 2182 skb_dst_force(skb);
2180 dst = skb_dst(skb);
2181 2183
2182 res = xfrm_lookup(net, &dst, &fl, NULL, 0) == 0; 2184 dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0);
2185 if (IS_ERR(dst)) {
2186 res = 1;
2187 dst = NULL;
2188 }
2183 skb_dst_set(skb, dst); 2189 skb_dst_set(skb, dst);
2184 return res; 2190 return res;
2185} 2191}