diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5015c50a5ba7..6ebdb7b6744c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -84,9 +84,9 @@ static void ip6_dst_ifdown(struct dst_entry *, | |||
84 | static int ip6_dst_gc(struct dst_ops *ops); | 84 | static int ip6_dst_gc(struct dst_ops *ops); |
85 | 85 | ||
86 | static int ip6_pkt_discard(struct sk_buff *skb); | 86 | static int ip6_pkt_discard(struct sk_buff *skb); |
87 | static int ip6_pkt_discard_out(struct sk_buff *skb); | 87 | static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb); |
88 | static int ip6_pkt_prohibit(struct sk_buff *skb); | 88 | static int ip6_pkt_prohibit(struct sk_buff *skb); |
89 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | 89 | static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb); |
90 | static void ip6_link_failure(struct sk_buff *skb); | 90 | static void ip6_link_failure(struct sk_buff *skb); |
91 | static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | 91 | static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, |
92 | struct sk_buff *skb, u32 mtu); | 92 | struct sk_buff *skb, u32 mtu); |
@@ -290,7 +290,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = { | |||
290 | .obsolete = DST_OBSOLETE_FORCE_CHK, | 290 | .obsolete = DST_OBSOLETE_FORCE_CHK, |
291 | .error = -EINVAL, | 291 | .error = -EINVAL, |
292 | .input = dst_discard, | 292 | .input = dst_discard, |
293 | .output = dst_discard, | 293 | .output = dst_discard_sk, |
294 | }, | 294 | }, |
295 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 295 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
296 | .rt6i_protocol = RTPROT_KERNEL, | 296 | .rt6i_protocol = RTPROT_KERNEL, |
@@ -1058,7 +1058,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori | |||
1058 | 1058 | ||
1059 | new->__use = 1; | 1059 | new->__use = 1; |
1060 | new->input = dst_discard; | 1060 | new->input = dst_discard; |
1061 | new->output = dst_discard; | 1061 | new->output = dst_discard_sk; |
1062 | 1062 | ||
1063 | if (dst_metrics_read_only(&ort->dst)) | 1063 | if (dst_metrics_read_only(&ort->dst)) |
1064 | new->_metrics = ort->dst._metrics; | 1064 | new->_metrics = ort->dst._metrics; |
@@ -1273,6 +1273,7 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark) | |||
1273 | struct flowi6 fl6; | 1273 | struct flowi6 fl6; |
1274 | 1274 | ||
1275 | memset(&fl6, 0, sizeof(fl6)); | 1275 | memset(&fl6, 0, sizeof(fl6)); |
1276 | fl6.flowi6_iif = LOOPBACK_IFINDEX; | ||
1276 | fl6.flowi6_oif = oif; | 1277 | fl6.flowi6_oif = oif; |
1277 | fl6.flowi6_mark = mark; | 1278 | fl6.flowi6_mark = mark; |
1278 | fl6.daddr = iph->daddr; | 1279 | fl6.daddr = iph->daddr; |
@@ -1294,6 +1295,7 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, | |||
1294 | struct flowi6 fl6; | 1295 | struct flowi6 fl6; |
1295 | 1296 | ||
1296 | memset(&fl6, 0, sizeof(fl6)); | 1297 | memset(&fl6, 0, sizeof(fl6)); |
1298 | fl6.flowi6_iif = LOOPBACK_IFINDEX; | ||
1297 | fl6.flowi6_oif = oif; | 1299 | fl6.flowi6_oif = oif; |
1298 | fl6.flowi6_mark = mark; | 1300 | fl6.flowi6_mark = mark; |
1299 | fl6.daddr = msg->dest; | 1301 | fl6.daddr = msg->dest; |
@@ -1338,7 +1340,7 @@ static unsigned int ip6_mtu(const struct dst_entry *dst) | |||
1338 | unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); | 1340 | unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); |
1339 | 1341 | ||
1340 | if (mtu) | 1342 | if (mtu) |
1341 | return mtu; | 1343 | goto out; |
1342 | 1344 | ||
1343 | mtu = IPV6_MIN_MTU; | 1345 | mtu = IPV6_MIN_MTU; |
1344 | 1346 | ||
@@ -1348,7 +1350,8 @@ static unsigned int ip6_mtu(const struct dst_entry *dst) | |||
1348 | mtu = idev->cnf.mtu6; | 1350 | mtu = idev->cnf.mtu6; |
1349 | rcu_read_unlock(); | 1351 | rcu_read_unlock(); |
1350 | 1352 | ||
1351 | return mtu; | 1353 | out: |
1354 | return min_t(unsigned int, mtu, IP6_MAX_MTU); | ||
1352 | } | 1355 | } |
1353 | 1356 | ||
1354 | static struct dst_entry *icmp6_dst_gc_list; | 1357 | static struct dst_entry *icmp6_dst_gc_list; |
@@ -1576,7 +1579,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1576 | switch (cfg->fc_type) { | 1579 | switch (cfg->fc_type) { |
1577 | case RTN_BLACKHOLE: | 1580 | case RTN_BLACKHOLE: |
1578 | rt->dst.error = -EINVAL; | 1581 | rt->dst.error = -EINVAL; |
1579 | rt->dst.output = dst_discard; | 1582 | rt->dst.output = dst_discard_sk; |
1580 | rt->dst.input = dst_discard; | 1583 | rt->dst.input = dst_discard; |
1581 | break; | 1584 | break; |
1582 | case RTN_PROHIBIT: | 1585 | case RTN_PROHIBIT: |
@@ -2128,7 +2131,7 @@ static int ip6_pkt_discard(struct sk_buff *skb) | |||
2128 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES); | 2131 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES); |
2129 | } | 2132 | } |
2130 | 2133 | ||
2131 | static int ip6_pkt_discard_out(struct sk_buff *skb) | 2134 | static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb) |
2132 | { | 2135 | { |
2133 | skb->dev = skb_dst(skb)->dev; | 2136 | skb->dev = skb_dst(skb)->dev; |
2134 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); | 2137 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); |
@@ -2139,7 +2142,7 @@ static int ip6_pkt_prohibit(struct sk_buff *skb) | |||
2139 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); | 2142 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); |
2140 | } | 2143 | } |
2141 | 2144 | ||
2142 | static int ip6_pkt_prohibit_out(struct sk_buff *skb) | 2145 | static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb) |
2143 | { | 2146 | { |
2144 | skb->dev = skb_dst(skb)->dev; | 2147 | skb->dev = skb_dst(skb)->dev; |
2145 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); | 2148 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); |
@@ -2231,6 +2234,27 @@ void rt6_remove_prefsrc(struct inet6_ifaddr *ifp) | |||
2231 | fib6_clean_all(net, fib6_remove_prefsrc, &adni); | 2234 | fib6_clean_all(net, fib6_remove_prefsrc, &adni); |
2232 | } | 2235 | } |
2233 | 2236 | ||
2237 | #define RTF_RA_ROUTER (RTF_ADDRCONF | RTF_DEFAULT | RTF_GATEWAY) | ||
2238 | #define RTF_CACHE_GATEWAY (RTF_GATEWAY | RTF_CACHE) | ||
2239 | |||
2240 | /* Remove routers and update dst entries when gateway turn into host. */ | ||
2241 | static int fib6_clean_tohost(struct rt6_info *rt, void *arg) | ||
2242 | { | ||
2243 | struct in6_addr *gateway = (struct in6_addr *)arg; | ||
2244 | |||
2245 | if ((((rt->rt6i_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) || | ||
2246 | ((rt->rt6i_flags & RTF_CACHE_GATEWAY) == RTF_CACHE_GATEWAY)) && | ||
2247 | ipv6_addr_equal(gateway, &rt->rt6i_gateway)) { | ||
2248 | return -1; | ||
2249 | } | ||
2250 | return 0; | ||
2251 | } | ||
2252 | |||
2253 | void rt6_clean_tohost(struct net *net, struct in6_addr *gateway) | ||
2254 | { | ||
2255 | fib6_clean_all(net, fib6_clean_tohost, gateway); | ||
2256 | } | ||
2257 | |||
2234 | struct arg_dev_net { | 2258 | struct arg_dev_net { |
2235 | struct net_device *dev; | 2259 | struct net_device *dev; |
2236 | struct net *net; | 2260 | struct net *net; |
@@ -2706,6 +2730,9 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh) | |||
2706 | if (tb[RTA_OIF]) | 2730 | if (tb[RTA_OIF]) |
2707 | oif = nla_get_u32(tb[RTA_OIF]); | 2731 | oif = nla_get_u32(tb[RTA_OIF]); |
2708 | 2732 | ||
2733 | if (tb[RTA_MARK]) | ||
2734 | fl6.flowi6_mark = nla_get_u32(tb[RTA_MARK]); | ||
2735 | |||
2709 | if (iif) { | 2736 | if (iif) { |
2710 | struct net_device *dev; | 2737 | struct net_device *dev; |
2711 | int flags = 0; | 2738 | int flags = 0; |