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; - : 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