Skip to content

Commit

Permalink
[IPV6]: V6 route events reported with wrong netlink PID and seq number
Browse files Browse the repository at this point in the history
Essentially netlink at the moment always reports a pid and sequence of 0
always for v6 route activities. 
To understand the repurcassions of this look at:
http://lists.quagga.net/pipermail/quagga-dev/2005-June/003507.html

While fixing this, i took the liberty to resolve the outstanding issue
of IPV6 routes inserted via ioctls to have the correct pids as well.

This patch tries to behave as close as possible to the v4 routes i.e
maintains whatever PID the socket issuing the command owns as opposed to
the process. That made the patch a little bulky.

I have tested against both netlink derived utility to add/del routes as
well as ioctl derived one. The Quagga folks have tested against quagga.
This fixes the problem and so far hasnt been detected to introduce any
new issues.

Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jamal Hadi Salim authored and David S. Miller committed Jun 21, 2005
1 parent 19baf83 commit 0d51aa8
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 63 deletions.
9 changes: 6 additions & 3 deletions include/net/ip6_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,17 @@ extern int fib6_walk_continue(struct fib6_walker_t *w);
extern int fib6_add(struct fib6_node *root,
struct rt6_info *rt,
struct nlmsghdr *nlh,
void *rtattr);
void *rtattr,
struct netlink_skb_parms *req);

extern int fib6_del(struct rt6_info *rt,
struct nlmsghdr *nlh,
void *rtattr);
void *rtattr,
struct netlink_skb_parms *req);

extern void inet6_rt_notify(int event, struct rt6_info *rt,
struct nlmsghdr *nlh);
struct nlmsghdr *nlh,
struct netlink_skb_parms *req);

extern void fib6_run_gc(unsigned long dummy);

Expand Down
9 changes: 6 additions & 3 deletions include/net/ip6_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,16 @@ extern int ipv6_route_ioctl(unsigned int cmd, void __user *arg);

extern int ip6_route_add(struct in6_rtmsg *rtmsg,
struct nlmsghdr *,
void *rtattr);
void *rtattr,
struct netlink_skb_parms *req);
extern int ip6_ins_rt(struct rt6_info *,
struct nlmsghdr *,
void *rtattr);
void *rtattr,
struct netlink_skb_parms *req);
extern int ip6_del_rt(struct rt6_info *,
struct nlmsghdr *,
void *rtattr);
void *rtattr,
struct netlink_skb_parms *req);

extern int ip6_rt_addr_add(struct in6_addr *addr,
struct net_device *dev,
Expand Down
14 changes: 7 additions & 7 deletions net/ipv6/addrconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)

if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
if (onlink == 0) {
ip6_del_rt(rt, NULL, NULL);
ip6_del_rt(rt, NULL, NULL, NULL);
rt = NULL;
} else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
rt->rt6i_expires = expires;
Expand Down Expand Up @@ -1340,7 +1340,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
rtmsg.rtmsg_flags |= RTF_NONEXTHOP;

ip6_route_add(&rtmsg, NULL, NULL);
ip6_route_add(&rtmsg, NULL, NULL, NULL);
}

/* Create "default" multicast route to the interface */
Expand All @@ -1357,7 +1357,7 @@ static void addrconf_add_mroute(struct net_device *dev)
rtmsg.rtmsg_ifindex = dev->ifindex;
rtmsg.rtmsg_flags = RTF_UP;
rtmsg.rtmsg_type = RTMSG_NEWROUTE;
ip6_route_add(&rtmsg, NULL, NULL);
ip6_route_add(&rtmsg, NULL, NULL, NULL);
}

static void sit_route_add(struct net_device *dev)
Expand All @@ -1374,7 +1374,7 @@ static void sit_route_add(struct net_device *dev)
rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP;
rtmsg.rtmsg_ifindex = dev->ifindex;

ip6_route_add(&rtmsg, NULL, NULL);
ip6_route_add(&rtmsg, NULL, NULL, NULL);
}

static void addrconf_add_lroute(struct net_device *dev)
Expand Down Expand Up @@ -1467,7 +1467,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
if (rt->rt6i_flags&RTF_EXPIRES) {
if (valid_lft == 0) {
ip6_del_rt(rt, NULL, NULL);
ip6_del_rt(rt, NULL, NULL, NULL);
rt = NULL;
} else {
rt->rt6i_expires = rt_expires;
Expand Down Expand Up @@ -3094,7 +3094,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
switch (event) {
case RTM_NEWADDR:
dst_hold(&ifp->rt->u.dst);
if (ip6_ins_rt(ifp->rt, NULL, NULL))
if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL))
dst_release(&ifp->rt->u.dst);
if (ifp->idev->cnf.forwarding)
addrconf_join_anycast(ifp);
Expand All @@ -3104,7 +3104,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
addrconf_leave_anycast(ifp);
addrconf_leave_solict(ifp->idev, &ifp->addr);
dst_hold(&ifp->rt->u.dst);
if (ip6_del_rt(ifp->rt, NULL, NULL))
if (ip6_del_rt(ifp->rt, NULL, NULL, NULL))
dst_free(&ifp->rt->u.dst);
else
dst_release(&ifp->rt->u.dst);
Expand Down
4 changes: 2 additions & 2 deletions net/ipv6/anycast.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
write_unlock_bh(&idev->lock);

dst_hold(&rt->u.dst);
if (ip6_ins_rt(rt, NULL, NULL))
if (ip6_ins_rt(rt, NULL, NULL, NULL))
dst_release(&rt->u.dst);

addrconf_join_solict(dev, &aca->aca_addr);
Expand Down Expand Up @@ -380,7 +380,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr)
addrconf_leave_solict(idev, &aca->aca_addr);

dst_hold(&aca->aca_rt->u.dst);
if (ip6_del_rt(aca->aca_rt, NULL, NULL))
if (ip6_del_rt(aca->aca_rt, NULL, NULL, NULL))
dst_free(&aca->aca_rt->u.dst);
else
dst_release(&aca->aca_rt->u.dst);
Expand Down
19 changes: 10 additions & 9 deletions net/ipv6/ip6_fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
*/

static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
struct nlmsghdr *nlh)
struct nlmsghdr *nlh, struct netlink_skb_parms *req)
{
struct rt6_info *iter = NULL;
struct rt6_info **ins;
Expand Down Expand Up @@ -449,7 +449,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
*ins = rt;
rt->rt6i_node = fn;
atomic_inc(&rt->rt6i_ref);
inet6_rt_notify(RTM_NEWROUTE, rt, nlh);
inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req);
rt6_stats.fib_rt_entries++;

if ((fn->fn_flags & RTN_RTINFO) == 0) {
Expand Down Expand Up @@ -479,7 +479,8 @@ void fib6_force_start_gc(void)
* with source addr info in sub-trees
*/

int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
int fib6_add(struct fib6_node *root, struct rt6_info *rt,
struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
{
struct fib6_node *fn;
int err = -ENOMEM;
Expand Down Expand Up @@ -552,7 +553,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
}
#endif

err = fib6_add_rt2node(fn, rt, nlh);
err = fib6_add_rt2node(fn, rt, nlh, req);

if (err == 0) {
fib6_start_gc(rt);
Expand Down Expand Up @@ -859,7 +860,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
}

static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
struct nlmsghdr *nlh, void *_rtattr)
struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
{
struct fib6_walker_t *w;
struct rt6_info *rt = *rtp;
Expand Down Expand Up @@ -915,11 +916,11 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
if (atomic_read(&rt->rt6i_ref) != 1) BUG();
}

inet6_rt_notify(RTM_DELROUTE, rt, nlh);
inet6_rt_notify(RTM_DELROUTE, rt, nlh, req);
rt6_release(rt);
}

int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
{
struct fib6_node *fn = rt->rt6i_node;
struct rt6_info **rtp;
Expand All @@ -944,7 +945,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)

for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
if (*rtp == rt) {
fib6_del_route(fn, rtp, nlh, _rtattr);
fib6_del_route(fn, rtp, nlh, _rtattr, req);
return 0;
}
}
Expand Down Expand Up @@ -1073,7 +1074,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
res = c->func(rt, c->arg);
if (res < 0) {
w->leaf = rt;
res = fib6_del(rt, NULL, NULL);
res = fib6_del(rt, NULL, NULL, NULL);
if (res) {
#if RT6_DEBUG >= 2
printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
Expand Down
4 changes: 2 additions & 2 deletions net/ipv6/ndisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
struct rt6_info *rt;
rt = rt6_get_dflt_router(saddr, dev);
if (rt)
ip6_del_rt(rt, NULL, NULL);
ip6_del_rt(rt, NULL, NULL, NULL);
}

out:
Expand Down Expand Up @@ -1096,7 +1096,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)

if (rt && lifetime == 0) {
neigh_clone(neigh);
ip6_del_rt(rt, NULL, NULL);
ip6_del_rt(rt, NULL, NULL, NULL);
rt = NULL;
}

Expand Down
Loading

0 comments on commit 0d51aa8

Please sign in to comment.