aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c45
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 *,
84static int ip6_dst_gc(struct dst_ops *ops); 84static int ip6_dst_gc(struct dst_ops *ops);
85 85
86static int ip6_pkt_discard(struct sk_buff *skb); 86static int ip6_pkt_discard(struct sk_buff *skb);
87static int ip6_pkt_discard_out(struct sk_buff *skb); 87static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb);
88static int ip6_pkt_prohibit(struct sk_buff *skb); 88static int ip6_pkt_prohibit(struct sk_buff *skb);
89static int ip6_pkt_prohibit_out(struct sk_buff *skb); 89static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb);
90static void ip6_link_failure(struct sk_buff *skb); 90static void ip6_link_failure(struct sk_buff *skb);
91static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, 91static 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; 1353out:
1354 return min_t(unsigned int, mtu, IP6_MAX_MTU);
1352} 1355}
1353 1356
1354static struct dst_entry *icmp6_dst_gc_list; 1357static 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
2131static int ip6_pkt_discard_out(struct sk_buff *skb) 2134static 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
2142static int ip6_pkt_prohibit_out(struct sk_buff *skb) 2145static 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. */
2241static 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
2253void rt6_clean_tohost(struct net *net, struct in6_addr *gateway)
2254{
2255 fib6_clean_all(net, fib6_clean_tohost, gateway);
2256}
2257
2234struct arg_dev_net { 2258struct 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;