diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 143 |
1 files changed, 78 insertions, 65 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5f0043c30b7..0e1f4b2cd3d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3,7 +3,7 @@ * FIB front-end. * * Authors: - * Pedro Roque <roque@di.fc.ul.pt> + * Pedro Roque <roque@di.fc.ul.pt> * * $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $ * @@ -201,7 +201,7 @@ static void ip6_dst_destroy(struct dst_entry *dst) if (idev != NULL) { rt->rt6i_idev = NULL; in6_dev_put(idev); - } + } } static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, @@ -243,7 +243,7 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, struct rt6_info *sprt; if (oif) { - for (sprt = rt; sprt; sprt = sprt->u.next) { + for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) { struct net_device *dev = sprt->rt6i_dev; if (dev->ifindex == oif) return sprt; @@ -252,7 +252,7 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, sprt->rt6i_idev->dev->ifindex != oif) { if (strict && oif) continue; - if (local && (!oif || + if (local && (!oif || local->rt6i_idev->dev->ifindex == oif)) continue; } @@ -311,12 +311,21 @@ static inline void rt6_probe(struct rt6_info *rt) static int inline rt6_check_dev(struct rt6_info *rt, int oif) { struct net_device *dev = rt->rt6i_dev; - if (!oif || dev->ifindex == oif) + int ret = 0; + + if (!oif) return 2; - if ((dev->flags & IFF_LOOPBACK) && - rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif) - return 1; - return 0; + if (dev->flags & IFF_LOOPBACK) { + if (!WARN_ON(rt->rt6i_idev == NULL) && + rt->rt6i_idev->dev->ifindex == oif) + ret = 1; + else + return 0; + } + if (dev->ifindex == oif) + return 2; + + return ret; } static int inline rt6_check_neigh(struct rt6_info *rt) @@ -341,7 +350,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif, int strict) { int m, n; - + m = rt6_check_dev(rt, oif); if (!m && (strict & RT6_LOOKUP_F_IFACE)) return -1; @@ -367,7 +376,7 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, for (rt = rt0, metric = rt0->rt6i_metric; rt && rt->rt6i_metric == metric && (!last || rt != rt0); - rt = rt->u.next) { + rt = rt->u.dst.rt6_next) { int m; if (rt6_check_expired(rt)) @@ -395,9 +404,9 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, /* no entries matched; do round-robin */ static DEFINE_SPINLOCK(lock); spin_lock(&lock); - *head = rt0->u.next; - rt0->u.next = last->u.next; - last->u.next = rt0; + *head = rt0->u.dst.rt6_next; + rt0->u.dst.rt6_next = last->u.dst.rt6_next; + last->u.dst.rt6_next = rt0; spin_unlock(&lock); } @@ -714,7 +723,7 @@ void ip6_route_input(struct sk_buff *skb) .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, }, }, - .mark = skb->mark, + .mark = skb->mark, .proto = iph->nexthdr, }; @@ -879,9 +888,9 @@ static inline unsigned int ipv6_advmss(unsigned int mtu) mtu = ip6_rt_min_advmss; /* - * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and - * corresponding MSS is IPV6_MAXPLEN - tcp_header_size. - * IPV6_MAXPLEN is also valid and means: "any MSS, + * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and + * corresponding MSS is IPV6_MAXPLEN - tcp_header_size. + * IPV6_MAXPLEN is also valid and means: "any MSS, * rely only on pmtu discovery" */ if (mtu > IPV6_MAXPLEN - sizeof(struct tcphdr)) @@ -892,7 +901,7 @@ static inline unsigned int ipv6_advmss(unsigned int mtu) static struct dst_entry *ndisc_dst_gc_list; static DEFINE_SPINLOCK(ndisc_lock); -struct dst_entry *ndisc_dst_alloc(struct net_device *dev, +struct dst_entry *ndisc_dst_alloc(struct net_device *dev, struct neighbour *neigh, struct in6_addr *addr, int (*output)(struct sk_buff *)) @@ -925,8 +934,8 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, rt->u.dst.output = output; #if 0 /* there's no chance to use these for ndisc */ - rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST - ? DST_HOST + rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST + ? DST_HOST : 0; ipv6_addr_copy(&rt->rt6i_dst.addr, addr); rt->rt6i_dst.plen = 128; @@ -949,7 +958,7 @@ int ndisc_dst_gc(int *more) int freed; next = NULL; - freed = 0; + freed = 0; spin_lock_bh(&ndisc_lock); pprev = &ndisc_dst_gc_list; @@ -1267,9 +1276,9 @@ static int ip6_route_del(struct fib6_config *cfg) fn = fib6_locate(&table->tb6_root, &cfg->fc_dst, cfg->fc_dst_len, &cfg->fc_src, cfg->fc_src_len); - + if (fn) { - for (rt = fn->leaf; rt; rt = rt->u.next) { + for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { if (cfg->fc_ifindex && (rt->rt6i_dev == NULL || rt->rt6i_dev->ifindex != cfg->fc_ifindex)) @@ -1320,7 +1329,7 @@ static struct rt6_info *__ip6_route_redirect(struct fib6_table *table, read_lock_bh(&table->tb6_lock); fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); restart: - for (rt = fn->leaf; rt; rt = rt->u.next) { + for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { /* * Current route is on-link; redirect is always invalid. * @@ -1396,7 +1405,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, * We have finally decided to accept it. */ - neigh_update(neigh, lladdr, NUD_STALE, + neigh_update(neigh, lladdr, NUD_STALE, NEIGH_UPDATE_F_WEAK_OVERRIDE| NEIGH_UPDATE_F_OVERRIDE| (on_link ? 0 : (NEIGH_UPDATE_F_OVERRIDE_ISROUTER| @@ -1445,7 +1454,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, } out: - dst_release(&rt->u.dst); + dst_release(&rt->u.dst); return; } @@ -1469,7 +1478,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, if (pmtu < IPV6_MIN_MTU) { /* - * According to RFC2460, PMTU is set to the IPv6 Minimum Link + * According to RFC2460, PMTU is set to the IPv6 Minimum Link * MTU (1280) and a fragment header should always be included * after a node receiving Too Big message reporting PMTU is * less than the IPv6 Minimum Link MTU. @@ -1581,7 +1590,7 @@ static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixle if (!fn) goto out; - for (rt = fn->leaf; rt; rt = rt->u.next) { + for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { if (rt->rt6i_dev->ifindex != ifindex) continue; if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) @@ -1623,7 +1632,7 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle #endif struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev) -{ +{ struct rt6_info *rt; struct fib6_table *table; @@ -1632,7 +1641,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d return NULL; write_lock_bh(&table->tb6_lock); - for (rt = table->tb6_root.leaf; rt; rt=rt->u.next) { + for (rt = table->tb6_root.leaf; rt; rt=rt->u.dst.rt6_next) { if (dev == rt->rt6i_dev && ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && ipv6_addr_equal(&rt->rt6i_gateway, addr)) @@ -1675,7 +1684,7 @@ void rt6_purge_dflt_routers(void) restart: read_lock_bh(&table->tb6_lock); - for (rt = table->tb6_root.leaf; rt; rt = rt->u.next) { + for (rt = table->tb6_root.leaf; rt; rt = rt->u.dst.rt6_next) { if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { dst_hold(&rt->u.dst); read_unlock_bh(&table->tb6_lock); @@ -1887,8 +1896,8 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) */ if (rt->rt6i_dev == arg->dev && !dst_metric_locked(&rt->u.dst, RTAX_MTU) && - (dst_mtu(&rt->u.dst) > arg->mtu || - (dst_mtu(&rt->u.dst) < arg->mtu && + (dst_mtu(&rt->u.dst) > arg->mtu || + (dst_mtu(&rt->u.dst) < arg->mtu && dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu); @@ -2040,7 +2049,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); if (nlh == NULL) - return -ENOBUFS; + return -EMSGSIZE; rtm = nlmsg_data(nlh); rtm->rtm_family = AF_INET6; @@ -2074,13 +2083,13 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, if (dst) { NLA_PUT(skb, RTA_DST, 16, dst); - rtm->rtm_dst_len = 128; + rtm->rtm_dst_len = 128; } else if (rtm->rtm_dst_len) NLA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr); #ifdef CONFIG_IPV6_SUBTREES if (src) { NLA_PUT(skb, RTA_SRC, 16, src); - rtm->rtm_src_len = 128; + rtm->rtm_src_len = 128; } else if (rtm->rtm_src_len) NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); #endif @@ -2111,7 +2120,8 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, return nlmsg_end(skb, nlh); nla_put_failure: - return nlmsg_cancel(skb, nlh); + nlmsg_cancel(skb, nlh); + return -EMSGSIZE; } int rt6_dump_route(struct rt6_info *rt, void *p_arg) @@ -2222,9 +2232,12 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) goto errout; err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); - /* failure implies BUG in rt6_nlmsg_size() */ - BUG_ON(err < 0); - + if (err < 0) { + /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ + WARN_ON(err == -EMSGSIZE); + kfree_skb(skb); + goto errout; + } err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); errout: if (err < 0) @@ -2286,7 +2299,7 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) arg->len += sprintf(arg->buffer + arg->len, " %08x %08x %08x %08x %8s\n", rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt), - rt->u.dst.__use, rt->rt6i_flags, + rt->u.dst.__use, rt->rt6i_flags, rt->rt6i_dev ? rt->rt6i_dev->name : ""); return 0; } @@ -2332,7 +2345,7 @@ static int rt6_stats_seq_open(struct inode *inode, struct file *file) return single_open(file, rt6_stats_seq_show, NULL); } -static struct file_operations rt6_stats_seq_fops = { +static const struct file_operations rt6_stats_seq_fops = { .owner = THIS_MODULE, .open = rt6_stats_seq_open, .read = seq_read, @@ -2358,91 +2371,91 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, } ctl_table ipv6_route_table[] = { - { - .ctl_name = NET_IPV6_ROUTE_FLUSH, + { + .ctl_name = NET_IPV6_ROUTE_FLUSH, .procname = "flush", - .data = &flush_delay, + .data = &flush_delay, .maxlen = sizeof(int), .mode = 0200, - .proc_handler = &ipv6_sysctl_rtcache_flush + .proc_handler = &ipv6_sysctl_rtcache_flush }, { .ctl_name = NET_IPV6_ROUTE_GC_THRESH, .procname = "gc_thresh", - .data = &ip6_dst_ops.gc_thresh, + .data = &ip6_dst_ops.gc_thresh, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV6_ROUTE_MAX_SIZE, .procname = "max_size", - .data = &ip6_rt_max_size, + .data = &ip6_rt_max_size, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV6_ROUTE_GC_MIN_INTERVAL, .procname = "gc_min_interval", - .data = &ip6_rt_gc_min_interval, + .data = &ip6_rt_gc_min_interval, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, + .proc_handler = &proc_dointvec_jiffies, .strategy = &sysctl_jiffies, }, { .ctl_name = NET_IPV6_ROUTE_GC_TIMEOUT, .procname = "gc_timeout", - .data = &ip6_rt_gc_timeout, + .data = &ip6_rt_gc_timeout, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, + .proc_handler = &proc_dointvec_jiffies, .strategy = &sysctl_jiffies, }, { .ctl_name = NET_IPV6_ROUTE_GC_INTERVAL, .procname = "gc_interval", - .data = &ip6_rt_gc_interval, + .data = &ip6_rt_gc_interval, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, + .proc_handler = &proc_dointvec_jiffies, .strategy = &sysctl_jiffies, }, { .ctl_name = NET_IPV6_ROUTE_GC_ELASTICITY, .procname = "gc_elasticity", - .data = &ip6_rt_gc_elasticity, + .data = &ip6_rt_gc_elasticity, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, + .proc_handler = &proc_dointvec_jiffies, .strategy = &sysctl_jiffies, }, { .ctl_name = NET_IPV6_ROUTE_MTU_EXPIRES, .procname = "mtu_expires", - .data = &ip6_rt_mtu_expires, + .data = &ip6_rt_mtu_expires, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, + .proc_handler = &proc_dointvec_jiffies, .strategy = &sysctl_jiffies, }, { .ctl_name = NET_IPV6_ROUTE_MIN_ADVMSS, .procname = "min_adv_mss", - .data = &ip6_rt_min_advmss, + .data = &ip6_rt_min_advmss, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, + .proc_handler = &proc_dointvec_jiffies, .strategy = &sysctl_jiffies, }, { .ctl_name = NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS, .procname = "gc_min_interval_ms", - .data = &ip6_rt_gc_min_interval, + .data = &ip6_rt_gc_min_interval, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_ms_jiffies, + .proc_handler = &proc_dointvec_ms_jiffies, .strategy = &sysctl_ms_jiffies, }, { .ctl_name = 0 } |