aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-01 17:59:04 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-01 17:59:04 -0500
commit2774c131b1d19920b4587db1cfbd6f0750ad1f15 (patch)
tree3a0482c727cf4dcc046a211214f12459dcba8271
parent69ead7afdf6028184f713a77376ee26f8aaafdcd (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>
-rw-r--r--include/net/dst.h8
-rw-r--r--include/net/ipv6.h4
-rw-r--r--include/net/route.h1
-rw-r--r--include/net/xfrm.h1
-rw-r--r--net/ipv4/route.c20
-rw-r--r--net/ipv4/xfrm4_policy.c1
-rw-r--r--net/ipv6/ip6_output.c32
-rw-r--r--net/ipv6/route.c3
-rw-r--r--net/ipv6/xfrm6_policy.c1
-rw-r--r--net/xfrm/xfrm_policy.c46
10 files changed, 50 insertions, 67 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index 15d67c8d3ce8..8948452132ad 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -432,17 +432,9 @@ static inline int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
432{ 432{
433 return 0; 433 return 0;
434} 434}
435static inline int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
436 const struct flowi *fl, struct sock *sk,
437 int flags)
438{
439 return 0;
440}
441#else 435#else
442extern int xfrm_lookup(struct net *net, struct dst_entry **dst_p, 436extern int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
443 const struct flowi *fl, struct sock *sk, int flags); 437 const struct flowi *fl, struct sock *sk, int flags);
444extern int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
445 const struct flowi *fl, struct sock *sk, int flags);
446#endif 438#endif
447#endif 439#endif
448 440
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 5d125c1293a9..d6d077d7f2cf 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -520,8 +520,8 @@ extern struct dst_entry * ip6_sk_dst_lookup_flow(struct sock *sk,
520 struct flowi *fl, 520 struct flowi *fl,
521 const struct in6_addr *final_dst, 521 const struct in6_addr *final_dst,
522 bool can_sleep); 522 bool can_sleep);
523extern struct dst_entry * ip6_dst_blackhole(struct net *net, 523extern struct dst_entry * ip6_blackhole_route(struct net *net,
524 struct dst_entry *orig_dst); 524 struct dst_entry *orig_dst);
525 525
526/* 526/*
527 * skb processing functions 527 * skb processing functions
diff --git a/include/net/route.h b/include/net/route.h
index 923e670586d4..707cfc8eccdc 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -121,6 +121,7 @@ extern void rt_cache_flush_batch(struct net *net);
121extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); 121extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp);
122extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); 122extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp);
123extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk); 123extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk);
124extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig);
124 125
125extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, 126extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src,
126 u8 tos, struct net_device *devin, bool noref); 127 u8 tos, struct net_device *devin, bool noref);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index efded23dc4ae..d5dcf3974636 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -280,6 +280,7 @@ struct xfrm_policy_afinfo {
280 int (*fill_dst)(struct xfrm_dst *xdst, 280 int (*fill_dst)(struct xfrm_dst *xdst,
281 struct net_device *dev, 281 struct net_device *dev,
282 const struct flowi *fl); 282 const struct flowi *fl);
283 struct dst_entry *(*blackhole_route)(struct net *net, struct dst_entry *orig);
283}; 284};
284 285
285extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); 286extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 23d205043d92..e24e4cf2a112 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2675,12 +2675,10 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
2675 .update_pmtu = ipv4_rt_blackhole_update_pmtu, 2675 .update_pmtu = ipv4_rt_blackhole_update_pmtu,
2676}; 2676};
2677 2677
2678 2678struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig)
2679static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi *flp)
2680{ 2679{
2681 struct rtable *ort = *rp; 2680 struct rtable *rt = dst_alloc(&ipv4_dst_blackhole_ops, 1);
2682 struct rtable *rt = (struct rtable *) 2681 struct rtable *ort = (struct rtable *) dst_orig;
2683 dst_alloc(&ipv4_dst_blackhole_ops, 1);
2684 2682
2685 if (rt) { 2683 if (rt) {
2686 struct dst_entry *new = &rt->dst; 2684 struct dst_entry *new = &rt->dst;
@@ -2714,9 +2712,9 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi
2714 dst_free(new); 2712 dst_free(new);
2715 } 2713 }
2716 2714
2717 dst_release(&(*rp)->dst); 2715 dst_release(dst_orig);
2718 *rp = rt; 2716
2719 return rt ? 0 : -ENOMEM; 2717 return rt ? &rt->dst : ERR_PTR(-ENOMEM);
2720} 2718}
2721 2719
2722int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp, 2720int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp,
@@ -2732,11 +2730,7 @@ int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp,
2732 flp->fl4_src = (*rp)->rt_src; 2730 flp->fl4_src = (*rp)->rt_src;
2733 if (!flp->fl4_dst) 2731 if (!flp->fl4_dst)
2734 flp->fl4_dst = (*rp)->rt_dst; 2732 flp->fl4_dst = (*rp)->rt_dst;
2735 err = __xfrm_lookup(net, (struct dst_entry **)rp, flp, sk, 0); 2733 return xfrm_lookup(net, (struct dst_entry **)rp, flp, sk, 0);
2736 if (err == -EREMOTE)
2737 err = ipv4_dst_blackhole(net, rp, flp);
2738
2739 return err;
2740 } 2734 }
2741 2735
2742 return 0; 2736 return 0;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 63aa88efdcef..5f0f058dc376 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -234,6 +234,7 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
234 .get_tos = xfrm4_get_tos, 234 .get_tos = xfrm4_get_tos,
235 .init_path = xfrm4_init_path, 235 .init_path = xfrm4_init_path,
236 .fill_dst = xfrm4_fill_dst, 236 .fill_dst = xfrm4_fill_dst,
237 .blackhole_route = ipv4_blackhole_route,
237}; 238};
238 239
239#ifdef CONFIG_SYSCTL 240#ifdef CONFIG_SYSCTL
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index ac16f3b2a029..35a4ad90a0f5 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1025,18 +1025,12 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi *fl,
1025 return ERR_PTR(err); 1025 return ERR_PTR(err);
1026 if (final_dst) 1026 if (final_dst)
1027 ipv6_addr_copy(&fl->fl6_dst, final_dst); 1027 ipv6_addr_copy(&fl->fl6_dst, final_dst);
1028 if (can_sleep) { 1028 if (can_sleep)
1029 fl->flags |= FLOWI_FLAG_CAN_SLEEP; 1029 fl->flags |= FLOWI_FLAG_CAN_SLEEP;
1030 err = __xfrm_lookup(sock_net(sk), &dst, fl, sk, 0); 1030
1031 if (err == -EREMOTE) 1031 err = xfrm_lookup(sock_net(sk), &dst, fl, sk, 0);
1032 return ip6_dst_blackhole(sock_net(sk), dst); 1032 if (err)
1033 if (err) 1033 return ERR_PTR(err);
1034 return ERR_PTR(err);
1035 } else {
1036 err = xfrm_lookup(sock_net(sk), &dst, fl, sk, 0);
1037 if (err)
1038 return ERR_PTR(err);
1039 }
1040 return dst; 1034 return dst;
1041} 1035}
1042EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); 1036EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow);
@@ -1070,18 +1064,12 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi *fl,
1070 return ERR_PTR(err); 1064 return ERR_PTR(err);
1071 if (final_dst) 1065 if (final_dst)
1072 ipv6_addr_copy(&fl->fl6_dst, final_dst); 1066 ipv6_addr_copy(&fl->fl6_dst, final_dst);
1073 if (can_sleep) { 1067 if (can_sleep)
1074 fl->flags |= FLOWI_FLAG_CAN_SLEEP; 1068 fl->flags |= FLOWI_FLAG_CAN_SLEEP;
1075 err = __xfrm_lookup(sock_net(sk), &dst, fl, sk, 0); 1069
1076 if (err == -EREMOTE) 1070 err = xfrm_lookup(sock_net(sk), &dst, fl, sk, 0);
1077 return ip6_dst_blackhole(sock_net(sk), dst); 1071 if (err)
1078 if (err) 1072 return ERR_PTR(err);
1079 return ERR_PTR(err);
1080 } else {
1081 err = xfrm_lookup(sock_net(sk), &dst, fl, sk, 0);
1082 if (err)
1083 return ERR_PTR(err);
1084 }
1085 return dst; 1073 return dst;
1086} 1074}
1087EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); 1075EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index cf6fdeabb6f2..053a92ebf2d5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -870,7 +870,7 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk,
870 870
871EXPORT_SYMBOL(ip6_route_output); 871EXPORT_SYMBOL(ip6_route_output);
872 872
873struct dst_entry *ip6_dst_blackhole(struct net *net, struct dst_entry *dst_orig) 873struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
874{ 874{
875 struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1); 875 struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1);
876 struct rt6_info *ort = (struct rt6_info *) dst_orig; 876 struct rt6_info *ort = (struct rt6_info *) dst_orig;
@@ -907,7 +907,6 @@ struct dst_entry *ip6_dst_blackhole(struct net *net, struct dst_entry *dst_orig)
907 dst_release(dst_orig); 907 dst_release(dst_orig);
908 return new ? new : ERR_PTR(-ENOMEM); 908 return new ? new : ERR_PTR(-ENOMEM);
909} 909}
910EXPORT_SYMBOL_GPL(ip6_dst_blackhole);
911 910
912/* 911/*
913 * Destination cache support functions 912 * Destination cache support functions
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index c128ca1affe3..48ce496802fd 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -274,6 +274,7 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
274 .get_tos = xfrm6_get_tos, 274 .get_tos = xfrm6_get_tos,
275 .init_path = xfrm6_init_path, 275 .init_path = xfrm6_init_path,
276 .fill_dst = xfrm6_fill_dst, 276 .fill_dst = xfrm6_fill_dst,
277 .blackhole_route = ip6_blackhole_route,
277}; 278};
278 279
279static int __init xfrm6_policy_init(void) 280static int __init xfrm6_policy_init(void)
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
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, 1760int 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}
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}
1914EXPORT_SYMBOL(xfrm_lookup); 1920EXPORT_SYMBOL(xfrm_lookup);
1915 1921
1916static inline int 1922static inline int