Re: Netlink and IPv6

From: kuznet@ms2.inr.ac.ru
Date: Thu Apr 10 2003 - 14:48:02 EST


Hello!

> I'm including a patch that avoids touching in6_rtmsg, and instead
> passes the netlink message around. Is this acceptable?

Yes, it looks OK. [original diff is copied for Dave]

Sigh... actually, I hoped you do the work on passing all the attributes
(protocol field does not look as a thing of priority) but, certainly,
it would not be fair to force you to do this when you need protocol only. :-)

Alexey

diff -ru --exclude-from=exclude linux-2.4.20.orig/include/net/ip6_fib.h linux-2.4.20/include/net/ip6_fib.h
--- linux-2.4.20.orig/include/net/ip6_fib.h 2000-12-11 16:30:48.000000000 -0500
+++ linux-2.4.20/include/net/ip6_fib.h 2003-04-10 12:07:18.000000000 -0400
@@ -80,6 +80,8 @@
 
         struct rt6key rt6i_dst;
         struct rt6key rt6i_src;
+
+ u8 rt6i_protocol;
 };
 
 struct fib6_walker_t
@@ -168,11 +170,14 @@
 extern int fib6_walk_continue(struct fib6_walker_t *w);
 
 extern int fib6_add(struct fib6_node *root,
- struct rt6_info *rt);
+ struct rt6_info *rt,
+ struct nlmsghdr *nlh);
 
-extern int fib6_del(struct rt6_info *rt);
+extern int fib6_del(struct rt6_info *rt,
+ struct nlmsghdr *nlh);
 
-extern void inet6_rt_notify(int event, struct rt6_info *rt);
+extern void inet6_rt_notify(int event, struct rt6_info *rt,
+ struct nlmsghdr *nlh);
 
 extern void fib6_run_gc(unsigned long dummy);
 
diff -ru --exclude-from=exclude linux-2.4.20.orig/include/net/ip6_route.h linux-2.4.20/include/net/ip6_route.h
--- linux-2.4.20.orig/include/net/ip6_route.h 2000-12-11 16:30:48.000000000 -0500
+++ linux-2.4.20/include/net/ip6_route.h 2003-04-10 12:07:18.000000000 -0400
@@ -36,8 +36,10 @@
 
 extern int ipv6_route_ioctl(unsigned int cmd, void *arg);
 
-extern int ip6_route_add(struct in6_rtmsg *rtmsg);
-extern int ip6_del_rt(struct rt6_info *);
+extern int ip6_route_add(struct in6_rtmsg *rtmsg,
+ struct nlmsghdr *);
+extern int ip6_del_rt(struct rt6_info *,
+ struct nlmsghdr *);
 
 extern int ip6_rt_addr_add(struct in6_addr *addr,
                                                 struct net_device *dev);
diff -ru --exclude-from=exclude linux-2.4.20.orig/net/ipv6/addrconf.c linux-2.4.20/net/ipv6/addrconf.c
--- linux-2.4.20.orig/net/ipv6/addrconf.c 2002-11-28 18:53:15.000000000 -0500
+++ linux-2.4.20/net/ipv6/addrconf.c 2003-04-10 11:50:18.000000000 -0400
@@ -744,7 +744,7 @@
         if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
                 rtmsg.rtmsg_flags |= RTF_NONEXTHOP;
 
- ip6_route_add(&rtmsg);
+ ip6_route_add(&rtmsg, NULL);
 }
 
 /* Create "default" multicast route to the interface */
@@ -761,7 +761,7 @@
         rtmsg.rtmsg_ifindex = dev->ifindex;
         rtmsg.rtmsg_flags = RTF_UP|RTF_ADDRCONF;
         rtmsg.rtmsg_type = RTMSG_NEWROUTE;
- ip6_route_add(&rtmsg);
+ ip6_route_add(&rtmsg, NULL);
 }
 
 static void sit_route_add(struct net_device *dev)
@@ -778,7 +778,7 @@
         rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP;
         rtmsg.rtmsg_ifindex = dev->ifindex;
 
- ip6_route_add(&rtmsg);
+ ip6_route_add(&rtmsg, NULL);
 }
 
 static void addrconf_add_lroute(struct net_device *dev)
@@ -870,7 +870,7 @@
         if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
                 if (rt->rt6i_flags&RTF_EXPIRES) {
                         if (pinfo->onlink == 0 || valid_lft == 0) {
- ip6_del_rt(rt);
+ ip6_del_rt(rt, NULL);
                                 rt = NULL;
                         } else {
                                 rt->rt6i_expires = rt_expires;
@@ -1455,7 +1455,7 @@
 
                 rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex;
 
- ip6_route_add(&rtmsg);
+ ip6_route_add(&rtmsg, NULL);
         }
 
 out:
diff -ru --exclude-from=exclude linux-2.4.20.orig/net/ipv6/ip6_fib.c linux-2.4.20/net/ipv6/ip6_fib.c
--- linux-2.4.20.orig/net/ipv6/ip6_fib.c 2002-11-28 18:53:15.000000000 -0500
+++ linux-2.4.20/net/ipv6/ip6_fib.c 2003-04-10 11:59:02.000000000 -0400
@@ -423,7 +423,8 @@
  * Insert routing information in a node.
  */
 
-static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt)
+static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
+ struct nlmsghdr *nlh)
 {
         struct rt6_info *iter = NULL;
         struct rt6_info **ins;
@@ -481,7 +482,7 @@
         *ins = rt;
         rt->rt6i_node = fn;
         atomic_inc(&rt->rt6i_ref);
- inet6_rt_notify(RTM_NEWROUTE, rt);
+ inet6_rt_notify(RTM_NEWROUTE, rt, nlh);
         rt6_stats.fib_rt_entries++;
 
         if ((fn->fn_flags & RTN_RTINFO) == 0) {
@@ -505,7 +506,7 @@
  * with source addr info in sub-trees
  */
 
-int fib6_add(struct fib6_node *root, struct rt6_info *rt)
+int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh)
 {
         struct fib6_node *fn;
         int err = -ENOMEM;
@@ -578,7 +579,7 @@
         }
 #endif
 
- err = fib6_add_rt2node(fn, rt);
+ err = fib6_add_rt2node(fn, rt, nlh);
 
         if (err == 0) {
                 fib6_start_gc(rt);
@@ -886,7 +887,8 @@
         }
 }
 
-static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp)
+static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+ struct nlmsghdr *nlh)
 {
         struct fib6_walker_t *w;
         struct rt6_info *rt = *rtp;
@@ -941,11 +943,11 @@
                 if (atomic_read(&rt->rt6i_ref) != 1) BUG();
         }
 
- inet6_rt_notify(RTM_DELROUTE, rt);
+ inet6_rt_notify(RTM_DELROUTE, rt, nlh);
         rt6_release(rt);
 }
 
-int fib6_del(struct rt6_info *rt)
+int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh)
 {
         struct fib6_node *fn = rt->rt6i_node;
         struct rt6_info **rtp;
@@ -970,7 +972,7 @@
 
         for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
                 if (*rtp == rt) {
- fib6_del_route(fn, rtp);
+ fib6_del_route(fn, rtp, nlh);
                         return 0;
                 }
         }
@@ -1099,7 +1101,7 @@
                 res = c->func(rt, c->arg);
                 if (res < 0) {
                         w->leaf = rt;
- res = fib6_del(rt);
+ res = fib6_del(rt, 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);
diff -ru --exclude-from=exclude linux-2.4.20.orig/net/ipv6/ip6_fw.c linux-2.4.20/net/ipv6/ip6_fw.c
--- linux-2.4.20.orig/net/ipv6/ip6_fw.c 2001-12-21 12:42:05.000000000 -0500
+++ linux-2.4.20/net/ipv6/ip6_fw.c 2003-04-10 11:50:26.000000000 -0400
@@ -303,7 +303,7 @@
         rl->info.uli_u.data = msg->u.data;
 
         rtmsg.rtmsg_flags = RTF_NONEXTHOP|RTF_POLICY;
- err = ip6_route_add(&rtmsg);
+ err = ip6_route_add(&rtmsg, NULL);
 
         if (err) {
                 ip6_fwrule_free(rl);
diff -ru --exclude-from=exclude linux-2.4.20.orig/net/ipv6/ndisc.c linux-2.4.20/net/ipv6/ndisc.c
--- linux-2.4.20.orig/net/ipv6/ndisc.c 2002-11-28 18:53:15.000000000 -0500
+++ linux-2.4.20/net/ipv6/ndisc.c 2003-04-10 11:36:06.000000000 -0400
@@ -642,7 +642,7 @@
         rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
 
         if (rt && lifetime == 0) {
- ip6_del_rt(rt);
+ ip6_del_rt(rt, NULL);
                 rt = NULL;
         }
 
@@ -1235,7 +1235,7 @@
                                         struct rt6_info *rt;
                                         rt = rt6_get_dflt_router(saddr, skb->dev);
                                         if (rt) {
- ip6_del_rt(rt);
+ ip6_del_rt(rt, NULL);
                                         }
                                 }
                         } else {
diff -ru --exclude-from=exclude linux-2.4.20.orig/net/ipv6/route.c linux-2.4.20/net/ipv6/route.c
--- linux-2.4.20.orig/net/ipv6/route.c 2002-11-28 18:53:15.000000000 -0500
+++ linux-2.4.20/net/ipv6/route.c 2003-04-10 13:06:12.000000000 -0400
@@ -261,12 +261,12 @@
    be destroyed.
  */
 
-static int rt6_ins(struct rt6_info *rt)
+static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh)
 {
         int err;
 
         write_lock_bh(&rt6_lock);
- err = fib6_add(&ip6_routing_table, rt);
+ err = fib6_add(&ip6_routing_table, rt, nlh);
         write_unlock_bh(&rt6_lock);
 
         return err;
@@ -309,7 +309,7 @@
 
                 dst_clone(&rt->u.dst);
 
- err = rt6_ins(rt);
+ err = rt6_ins(rt, NULL);
                 if (err == 0)
                         return rt;
 
@@ -555,7 +555,7 @@
 
         if (rt) {
                 if (rt->rt6i_flags & RTF_CACHE)
- ip6_del_rt(rt);
+ ip6_del_rt(rt, NULL);
                 else
                         dst_release(dst);
         }
@@ -646,9 +646,10 @@
  *
  */
 
-int ip6_route_add(struct in6_rtmsg *rtmsg)
+int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
 {
         int err;
+ struct rtmsg *r;
         struct rt6_info *rt;
         struct net_device *dev = NULL;
         int addr_type;
@@ -669,6 +670,11 @@
 
         rt->u.dst.obsolete = -1;
         rt->rt6i_expires = rtmsg->rtmsg_info;
+ if (nlh && (r = NLMSG_DATA(nlh))) {
+ rt->rt6i_protocol = r->rtm_protocol;
+ } else {
+ rt->rt6i_protocol = RTPROT_BOOT;
+ }
 
         addr_type = ipv6_addr_type(&rtmsg->rtmsg_dst);
 
@@ -793,7 +799,7 @@
         if (rt->u.dst.advmss > 65535-20)
                 rt->u.dst.advmss = 65535;
         rt->u.dst.dev = dev;
- return rt6_ins(rt);
+ return rt6_ins(rt, nlh);
 
 out:
         if (dev)
@@ -802,7 +808,7 @@
         return err;
 }
 
-int ip6_del_rt(struct rt6_info *rt)
+int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh)
 {
         int err;
 
@@ -814,13 +820,13 @@
 
         dst_release(&rt->u.dst);
 
- err = fib6_del(rt);
+ err = fib6_del(rt, nlh);
         write_unlock_bh(&rt6_lock);
 
         return err;
 }
 
-int ip6_route_del(struct in6_rtmsg *rtmsg)
+int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
 {
         struct fib6_node *fn;
         struct rt6_info *rt;
@@ -847,7 +853,7 @@
                         dst_clone(&rt->u.dst);
                         read_unlock_bh(&rt6_lock);
 
- return ip6_del_rt(rt);
+ return ip6_del_rt(rt, nlh);
                 }
         }
         read_unlock_bh(&rt6_lock);
@@ -949,11 +955,11 @@
                 rt->u.dst.advmss = 65535;
         nrt->rt6i_hoplimit = ipv6_get_hoplimit(neigh->dev);
 
- if (rt6_ins(nrt))
+ if (rt6_ins(nrt, NULL))
                 goto out;
 
         if (rt->rt6i_flags&RTF_CACHE) {
- ip6_del_rt(rt);
+ ip6_del_rt(rt, NULL);
                 return;
         }
 
@@ -1039,7 +1045,7 @@
                 dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
                 nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
                 nrt->u.dst.pmtu = pmtu;
- rt6_ins(nrt);
+ rt6_ins(nrt, NULL);
         }
 
 out:
@@ -1112,7 +1118,7 @@
 
         rtmsg.rtmsg_ifindex = dev->ifindex;
 
- ip6_route_add(&rtmsg);
+ ip6_route_add(&rtmsg, NULL);
         return rt6_get_dflt_router(gwaddr, dev);
 }
 
@@ -1138,7 +1144,7 @@
 
                         read_unlock_bh(&rt6_lock);
 
- ip6_del_rt(rt);
+ ip6_del_rt(rt, NULL);
 
                         goto restart;
                 }
@@ -1164,10 +1170,10 @@
                 rtnl_lock();
                 switch (cmd) {
                 case SIOCADDRT:
- err = ip6_route_add(&rtmsg);
+ err = ip6_route_add(&rtmsg, NULL);
                         break;
                 case SIOCDELRT:
- err = ip6_route_del(&rtmsg);
+ err = ip6_route_del(&rtmsg, NULL);
                         break;
                 default:
                         err = -EINVAL;
@@ -1224,7 +1230,7 @@
 
         ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
         rt->rt6i_dst.plen = 128;
- rt6_ins(rt);
+ rt6_ins(rt, NULL);
 
         return 0;
 }
@@ -1241,7 +1247,7 @@
         rt = rt6_lookup(addr, NULL, loopback_dev.ifindex, 1);
         if (rt) {
                 if (rt->rt6i_dst.plen == 128)
- err = ip6_del_rt(rt);
+ err = ip6_del_rt(rt, NULL);
                 else
                         dst_release(&rt->u.dst);
         }
@@ -1357,7 +1363,7 @@
 
         nrt->rt6i_flags |= RTF_CACHE;
         dst_clone(&nrt->u.dst);
- err = rt6_ins(nrt);
+ err = rt6_ins(nrt, NULL);
         if (err)
                 nrt->u.dst.error = err;
         return nrt;
@@ -1481,7 +1487,7 @@
 
         if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
                 return -EINVAL;
- return ip6_route_del(&rtmsg);
+ return ip6_route_del(&rtmsg, nlh);
 }
 
 int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -1491,7 +1497,7 @@
 
         if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
                 return -EINVAL;
- return ip6_route_add(&rtmsg);
+ return ip6_route_add(&rtmsg, nlh);
 }
 
 struct rt6_rtnl_dump_arg
@@ -1504,13 +1510,18 @@
                          struct in6_addr *dst,
                          struct in6_addr *src,
                          int iif,
- int type, u32 pid, u32 seq)
+ int type, u32 pid, u32 seq,
+ struct nlmsghdr *in_nlh)
 {
         struct rtmsg *rtm;
         struct nlmsghdr *nlh;
         unsigned char *b = skb->tail;
         struct rta_cacheinfo ci;
 
+ if (!pid && in_nlh) {
+ pid = in_nlh->nlmsg_pid;
+ }
+
         nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*rtm));
         rtm = NLMSG_DATA(nlh);
         rtm->rtm_family = AF_INET6;
@@ -1526,7 +1537,7 @@
                 rtm->rtm_type = RTN_UNICAST;
         rtm->rtm_flags = 0;
         rtm->rtm_scope = RT_SCOPE_UNIVERSE;
- rtm->rtm_protocol = RTPROT_BOOT;
+ rtm->rtm_protocol = rt->rt6i_protocol;
         if (rt->rt6i_flags&RTF_DYNAMIC)
                 rtm->rtm_protocol = RTPROT_REDIRECT;
         else if (rt->rt6i_flags&(RTF_ADDRCONF|RTF_ALLONLINK))
@@ -1589,7 +1600,8 @@
         struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) 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);
+ NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
+ NULL);
 }
 
 static int fib6_dump_node(struct fib6_walker_t *w)
@@ -1737,7 +1749,8 @@
                             fl.nl_u.ip6_u.daddr,
                             fl.nl_u.ip6_u.saddr,
                             iif,
- RTM_NEWROUTE, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq);
+ RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
+ nlh->nlmsg_seq, nlh);
         if (err < 0)
                 return -EMSGSIZE;
 
@@ -1747,7 +1760,7 @@
         return 0;
 }
 
-void inet6_rt_notify(int event, struct rt6_info *rt)
+void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh)
 {
         struct sk_buff *skb;
         int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
@@ -1757,7 +1770,7 @@
                 netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
                 return;
         }
- if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0) < 0) {
+ if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh) < 0) {
                 kfree_skb(skb);
                 netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
                 return;
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html



This archive was generated by hypermail 2b29 : Tue Apr 15 2003 - 22:00:01 EST