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 | |
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>
-rw-r--r-- | include/net/dst.h | 8 | ||||
-rw-r--r-- | include/net/ipv6.h | 4 | ||||
-rw-r--r-- | include/net/route.h | 1 | ||||
-rw-r--r-- | include/net/xfrm.h | 1 | ||||
-rw-r--r-- | net/ipv4/route.c | 20 | ||||
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 1 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 32 | ||||
-rw-r--r-- | net/ipv6/route.c | 3 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 1 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 46 |
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 | } |
435 | static 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 |
442 | extern int xfrm_lookup(struct net *net, struct dst_entry **dst_p, | 436 | extern 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); |
444 | extern 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); |
523 | extern struct dst_entry * ip6_dst_blackhole(struct net *net, | 523 | extern 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); | |||
121 | extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); | 121 | extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); |
122 | extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); | 122 | extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); |
123 | extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk); | 123 | extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk); |
124 | extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); | ||
124 | 125 | ||
125 | extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, | 126 | extern 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 | ||
285 | extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); | 286 | extern 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 | 2678 | struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) | |
2679 | static 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 | ||
2722 | int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp, | 2720 | int 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 | } |
1042 | EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); | 1036 | EXPORT_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 | } |
1087 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); | 1075 | EXPORT_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 | ||
871 | EXPORT_SYMBOL(ip6_route_output); | 871 | EXPORT_SYMBOL(ip6_route_output); |
872 | 872 | ||
873 | struct dst_entry *ip6_dst_blackhole(struct net *net, struct dst_entry *dst_orig) | 873 | struct 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 | } |
910 | EXPORT_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 | ||
279 | static int __init xfrm6_policy_init(void) | 280 | static 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 | ||
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 |