[IPV6]: V6 route events reported with wrong netlink PID and seq number
authorJamal Hadi Salim <hadi@cyberus.ca>
Tue, 21 Jun 2005 20:51:04 +0000 (13:51 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Jun 2005 20:51:04 +0000 (13:51 -0700)
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>
include/net/ip6_fib.h
include/net/ip6_route.h
net/ipv6/addrconf.c
net/ipv6/anycast.c
net/ipv6/ip6_fib.c
net/ipv6/ndisc.c
net/ipv6/route.c

index 31990451819454f6dc8e2f6db16572dc36428f01..a66e9de16a6cbe40535254983ebb650b8433e599 100644 (file)
@@ -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);
 
index d5d1dd10cdb8da7e40b8a65f9b8fc16c87b1814a..f920706d526b4397288240e9e11bf6bcaa07db54 100644 (file)
@@ -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,
index 47a30c3188ea72a3b27e8414541b2eca0ecf7672..14f5c53235fe664f71d18fca9fe0c84cf3edc2e0 100644 (file)
@@ -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;
@@ -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 */
@@ -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)
@@ -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)
@@ -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;
@@ -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);
@@ -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);
index 5d22ca3cca2ebca84348fb44aebde51ee9e396ff..6b7294047238387ea6c20420938f8b46990c057b 100644 (file)
@@ -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);
@@ -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);
index 405740b75abb7f693d66285815ffdd24a9f17740..1b354aa979340f41c0bc5d413f87dbdf2ff69117 100644 (file)
@@ -394,7 +394,7 @@ insert_above:
  */
 
 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;
@@ -449,7 +449,7 @@ out:
        *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) {
@@ -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;
@@ -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);
@@ -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;
@@ -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;
@@ -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;
                }
        }
@@ -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);
index 7c291f4e9edce067774e38458e727a27bf640f68..7ae72d4c9bd2cbc31cb23f8ad553109bd5fd657a 100644 (file)
@@ -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:
@@ -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;
        }
 
index 1f5b226c357370a51ec7f71ba7174ab6a6f58aeb..878789b3122de74a29ffe4b9cf59963d35bb7b11 100644 (file)
@@ -384,12 +384,13 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
    be destroyed.
  */
 
-int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh,
+               void *_rtattr, struct netlink_skb_parms *req)
 {
        int err;
 
        write_lock_bh(&rt6_lock);
-       err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr);
+       err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr, req);
        write_unlock_bh(&rt6_lock);
 
        return err;
@@ -400,7 +401,7 @@ int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
  */
 
 static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
-                               struct in6_addr *saddr)
+                               struct in6_addr *saddr, struct netlink_skb_parms *req)
 {
        int err;
        struct rt6_info *rt;
@@ -432,7 +433,7 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
 
                dst_hold(&rt->u.dst);
 
-               err = ip6_ins_rt(rt, NULL, NULL);
+               err = ip6_ins_rt(rt, NULL, NULL, req);
                if (err == 0)
                        return rt;
 
@@ -491,7 +492,8 @@ restart:
                read_unlock_bh(&rt6_lock);
 
                nrt = rt6_cow(rt, &skb->nh.ipv6h->daddr,
-                             &skb->nh.ipv6h->saddr);
+                             &skb->nh.ipv6h->saddr,
+                             &NETLINK_CB(skb));
 
                dst_release(&rt->u.dst);
                rt = nrt;
@@ -551,7 +553,7 @@ restart:
                dst_hold(&rt->u.dst);
                read_unlock_bh(&rt6_lock);
 
-               nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src);
+               nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src, NULL);
 
                dst_release(&rt->u.dst);
                rt = nrt;
@@ -598,7 +600,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
 
        if (rt) {
                if (rt->rt6i_flags & RTF_CACHE)
-                       ip6_del_rt(rt, NULL, NULL);
+                       ip6_del_rt(rt, NULL, NULL, NULL);
                else
                        dst_release(dst);
        }
@@ -787,7 +789,8 @@ int ipv6_get_hoplimit(struct net_device *dev)
  *
  */
 
-int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, 
+               void *_rtattr, struct netlink_skb_parms *req)
 {
        int err;
        struct rtmsg *r;
@@ -974,7 +977,7 @@ install_route:
                rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
        rt->u.dst.dev = dev;
        rt->rt6i_idev = idev;
-       return ip6_ins_rt(rt, nlh, _rtattr);
+       return ip6_ins_rt(rt, nlh, _rtattr, req);
 
 out:
        if (dev)
@@ -986,7 +989,7 @@ out:
        return err;
 }
 
-int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
        int err;
 
@@ -994,7 +997,7 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
 
        rt6_reset_dflt_pointer(NULL);
 
-       err = fib6_del(rt, nlh, _rtattr);
+       err = fib6_del(rt, nlh, _rtattr, req);
        dst_release(&rt->u.dst);
 
        write_unlock_bh(&rt6_lock);
@@ -1002,7 +1005,7 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
        return err;
 }
 
-static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
+static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
        struct fib6_node *fn;
        struct rt6_info *rt;
@@ -1029,7 +1032,7 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r
                        dst_hold(&rt->u.dst);
                        read_unlock_bh(&rt6_lock);
 
-                       return ip6_del_rt(rt, nlh, _rtattr);
+                       return ip6_del_rt(rt, nlh, _rtattr, req);
                }
        }
        read_unlock_bh(&rt6_lock);
@@ -1136,11 +1139,11 @@ source_ok:
        nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
        nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
 
-       if (ip6_ins_rt(nrt, NULL, NULL))
+       if (ip6_ins_rt(nrt, NULL, NULL, NULL))
                goto out;
 
        if (rt->rt6i_flags&RTF_CACHE) {
-               ip6_del_rt(rt, NULL, NULL);
+               ip6_del_rt(rt, NULL, NULL, NULL);
                return;
        }
 
@@ -1204,7 +1207,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
           2. It is gatewayed route or NONEXTHOP route. Action: clone it.
         */
        if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
-               nrt = rt6_cow(rt, daddr, saddr);
+               nrt = rt6_cow(rt, daddr, saddr, NULL);
                if (!nrt->u.dst.error) {
                        nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
                        if (allfrag)
@@ -1232,7 +1235,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
                nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
                if (allfrag)
                        nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
-               ip6_ins_rt(nrt, NULL, NULL);
+               ip6_ins_rt(nrt, NULL, NULL, NULL);
        }
 
 out:
@@ -1305,7 +1308,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
 
        rtmsg.rtmsg_ifindex = dev->ifindex;
 
-       ip6_route_add(&rtmsg, NULL, NULL);
+       ip6_route_add(&rtmsg, NULL, NULL, NULL);
        return rt6_get_dflt_router(gwaddr, dev);
 }
 
@@ -1323,7 +1326,7 @@ restart:
 
                        read_unlock_bh(&rt6_lock);
 
-                       ip6_del_rt(rt, NULL, NULL);
+                       ip6_del_rt(rt, NULL, NULL, NULL);
 
                        goto restart;
                }
@@ -1349,10 +1352,10 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
                rtnl_lock();
                switch (cmd) {
                case SIOCADDRT:
-                       err = ip6_route_add(&rtmsg, NULL, NULL);
+                       err = ip6_route_add(&rtmsg, NULL, NULL, NULL);
                        break;
                case SIOCDELRT:
-                       err = ip6_route_del(&rtmsg, NULL, NULL);
+                       err = ip6_route_del(&rtmsg, NULL, NULL, NULL);
                        break;
                default:
                        err = -EINVAL;
@@ -1546,7 +1549,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 
        if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
                return -EINVAL;
-       return ip6_route_del(&rtmsg, nlh, arg);
+       return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb));
 }
 
 int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -1556,7 +1559,7 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 
        if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
                return -EINVAL;
-       return ip6_route_add(&rtmsg, nlh, arg);
+       return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb));
 }
 
 struct rt6_rtnl_dump_arg
@@ -1566,12 +1569,9 @@ struct rt6_rtnl_dump_arg
 };
 
 static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
-                        struct in6_addr *dst,
-                        struct in6_addr *src,
-                        int iif,
-                        int type, u32 pid, u32 seq,
-                        struct nlmsghdr *in_nlh, int prefix,
-                        unsigned int flags)
+                        struct in6_addr *dst, struct in6_addr *src,
+                        int iif, int type, u32 pid, u32 seq,
+                        int prefix, unsigned int flags)
 {
        struct rtmsg *rtm;
        struct nlmsghdr  *nlh;
@@ -1585,10 +1585,6 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
                }
        }
 
-       if (!pid && in_nlh) {
-               pid = in_nlh->nlmsg_pid;
-       }
-
        nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags);
        rtm = NLMSG_DATA(nlh);
        rtm->rtm_family = AF_INET6;
@@ -1675,7 +1671,7 @@ static int rt6_dump_route(struct rt6_info *rt, void *p_arg)
 
        return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
                     NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
-                    NULL, prefix, NLM_F_MULTI);
+                    prefix, NLM_F_MULTI);
 }
 
 static int fib6_dump_node(struct fib6_walker_t *w)
@@ -1823,7 +1819,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
                            &fl.fl6_dst, &fl.fl6_src,
                            iif,
                            RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
-                           nlh->nlmsg_seq, nlh, 0, 0);
+                           nlh->nlmsg_seq, 0, 0);
        if (err < 0) {
                err = -EMSGSIZE;
                goto out_free;
@@ -1839,17 +1835,25 @@ out_free:
        goto out;       
 }
 
-void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh)
+void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh, 
+                       struct netlink_skb_parms *req)
 {
        struct sk_buff *skb;
        int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
+       u32 pid = current->pid;
+       u32 seq = 0;
 
+       if (req)
+               pid = req->pid;
+       if (nlh)
+               seq = nlh->nlmsg_seq;
+       
        skb = alloc_skb(size, gfp_any());
        if (!skb) {
                netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
                return;
        }
-       if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0, 0) < 0) {
+       if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) {
                kfree_skb(skb);
                netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
                return;