Commit f3200f7e authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6] ensure rt6i_idev is non-NULL when setting up new rt6_info{}.

Signed-off-by: default avatarHideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
parent c2de5154
...@@ -617,8 +617,13 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, ...@@ -617,8 +617,13 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
struct in6_addr *addr, struct in6_addr *addr,
int (*output)(struct sk_buff **)) int (*output)(struct sk_buff **))
{ {
struct rt6_info *rt = ip6_dst_alloc(); struct rt6_info *rt;
struct inet6_dev *idev = in6_dev_get(dev);
if (unlikely(idev == NULL))
return NULL;
rt = ip6_dst_alloc();
if (unlikely(rt == NULL)) if (unlikely(rt == NULL))
goto out; goto out;
...@@ -629,7 +634,7 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, ...@@ -629,7 +634,7 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
neigh = ndisc_get_neigh(dev, addr); neigh = ndisc_get_neigh(dev, addr);
rt->rt6i_dev = dev; rt->rt6i_dev = dev;
rt->rt6i_idev = in6_dev_get(dev); rt->rt6i_idev = idev;
rt->rt6i_nexthop = neigh; rt->rt6i_nexthop = neigh;
atomic_set(&rt->u.dst.__refcnt, 1); atomic_set(&rt->u.dst.__refcnt, 1);
rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
...@@ -740,8 +745,9 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) ...@@ -740,8 +745,9 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
int err; int err;
struct rtmsg *r; struct rtmsg *r;
struct rtattr **rta; struct rtattr **rta;
struct rt6_info *rt; struct rt6_info *rt = NULL;
struct net_device *dev = NULL; struct net_device *dev = NULL;
struct inet6_dev *idev = NULL;
int addr_type; int addr_type;
rta = (struct rtattr **) _rtattr; rta = (struct rtattr **) _rtattr;
...@@ -753,9 +759,13 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) ...@@ -753,9 +759,13 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
return -EINVAL; return -EINVAL;
#endif #endif
if (rtmsg->rtmsg_ifindex) { if (rtmsg->rtmsg_ifindex) {
err = -ENODEV;
dev = dev_get_by_index(rtmsg->rtmsg_ifindex); dev = dev_get_by_index(rtmsg->rtmsg_ifindex);
if (!dev) if (!dev)
return -ENODEV; goto out;
idev = in6_dev_get(dev);
if (!idev)
goto out;
} }
if (rtmsg->rtmsg_metric == 0) if (rtmsg->rtmsg_metric == 0)
...@@ -802,10 +812,17 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) ...@@ -802,10 +812,17 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
*/ */
if ((rtmsg->rtmsg_flags&RTF_REJECT) || if ((rtmsg->rtmsg_flags&RTF_REJECT) ||
(dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
if (dev) if (dev && dev != &loopback_dev) {
dev_put(dev); dev_put(dev);
in6_dev_put(idev);
dev = &loopback_dev; dev = &loopback_dev;
dev_hold(dev); dev_hold(dev);
idev = in6_dev_get(dev);
if (!idev) {
err = -ENODEV;
goto out;
}
}
rt->u.dst.output = ip6_pkt_discard_out; rt->u.dst.output = ip6_pkt_discard_out;
rt->u.dst.input = ip6_pkt_discard; rt->u.dst.input = ip6_pkt_discard;
rt->u.dst.error = -ENETUNREACH; rt->u.dst.error = -ENETUNREACH;
...@@ -847,7 +864,9 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) ...@@ -847,7 +864,9 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
} }
} else { } else {
dev = grt->rt6i_dev; dev = grt->rt6i_dev;
idev = grt->rt6i_idev;
dev_hold(dev); dev_hold(dev);
in6_dev_hold(grt->rt6i_idev);
} }
if (!(grt->rt6i_flags&RTF_GATEWAY)) if (!(grt->rt6i_flags&RTF_GATEWAY))
err = 0; err = 0;
...@@ -909,7 +928,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) ...@@ -909,7 +928,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
if (!rt->u.dst.metrics[RTAX_ADVMSS-1]) if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst)); rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst));
rt->u.dst.dev = dev; rt->u.dst.dev = dev;
rt->rt6i_idev = in6_dev_get(dev); rt->rt6i_idev = idev;
return ip6_ins_rt(rt, nlh, _rtattr); return ip6_ins_rt(rt, nlh, _rtattr);
out: out:
...@@ -1363,6 +1382,10 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast) ...@@ -1363,6 +1382,10 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast)
int err = 0; int err = 0;
idev = in6_dev_get(&loopback_dev); idev = in6_dev_get(&loopback_dev);
if (!idev) {
err = -ENODEV;
goto out;
}
rt = addrconf_dst_alloc(idev, addr, anycast); rt = addrconf_dst_alloc(idev, addr, anycast);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment