Commit b5383434 authored by Mathew Richardson's avatar Mathew Richardson Committed by David S. Miller

[IPV6]: Allow protocol to percolate up into rt6 routing operations.

parent c96fa28d
...@@ -72,6 +72,8 @@ struct rt6_info ...@@ -72,6 +72,8 @@ struct rt6_info
struct rt6key rt6i_dst; struct rt6key rt6i_dst;
struct rt6key rt6i_src; struct rt6key rt6i_src;
u8 rt6i_protocol;
}; };
struct fib6_walker_t struct fib6_walker_t
...@@ -160,11 +162,14 @@ extern int fib6_walk(struct fib6_walker_t *w); ...@@ -160,11 +162,14 @@ extern int fib6_walk(struct fib6_walker_t *w);
extern int fib6_walk_continue(struct fib6_walker_t *w); extern int fib6_walk_continue(struct fib6_walker_t *w);
extern int fib6_add(struct fib6_node *root, 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); extern void fib6_run_gc(unsigned long dummy);
......
...@@ -37,8 +37,10 @@ extern void ip6_route_cleanup(void); ...@@ -37,8 +37,10 @@ extern void ip6_route_cleanup(void);
extern int ipv6_route_ioctl(unsigned int cmd, void *arg); extern int ipv6_route_ioctl(unsigned int cmd, void *arg);
extern int ip6_route_add(struct in6_rtmsg *rtmsg); extern int ip6_route_add(struct in6_rtmsg *rtmsg,
extern int ip6_del_rt(struct rt6_info *); struct nlmsghdr *);
extern int ip6_del_rt(struct rt6_info *,
struct nlmsghdr *);
extern int ip6_rt_addr_add(struct in6_addr *addr, extern int ip6_rt_addr_add(struct in6_addr *addr,
struct net_device *dev); struct net_device *dev);
......
...@@ -1202,7 +1202,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, ...@@ -1202,7 +1202,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT)) if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
rtmsg.rtmsg_flags |= RTF_NONEXTHOP; rtmsg.rtmsg_flags |= RTF_NONEXTHOP;
ip6_route_add(&rtmsg); ip6_route_add(&rtmsg, NULL);
} }
/* Create "default" multicast route to the interface */ /* Create "default" multicast route to the interface */
...@@ -1219,7 +1219,7 @@ static void addrconf_add_mroute(struct net_device *dev) ...@@ -1219,7 +1219,7 @@ static void addrconf_add_mroute(struct net_device *dev)
rtmsg.rtmsg_ifindex = dev->ifindex; rtmsg.rtmsg_ifindex = dev->ifindex;
rtmsg.rtmsg_flags = RTF_UP|RTF_ADDRCONF; rtmsg.rtmsg_flags = RTF_UP|RTF_ADDRCONF;
rtmsg.rtmsg_type = RTMSG_NEWROUTE; rtmsg.rtmsg_type = RTMSG_NEWROUTE;
ip6_route_add(&rtmsg); ip6_route_add(&rtmsg, NULL);
} }
static void sit_route_add(struct net_device *dev) static void sit_route_add(struct net_device *dev)
...@@ -1236,7 +1236,7 @@ static void sit_route_add(struct net_device *dev) ...@@ -1236,7 +1236,7 @@ static void sit_route_add(struct net_device *dev)
rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP; rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP;
rtmsg.rtmsg_ifindex = dev->ifindex; rtmsg.rtmsg_ifindex = dev->ifindex;
ip6_route_add(&rtmsg); ip6_route_add(&rtmsg, NULL);
} }
static void addrconf_add_lroute(struct net_device *dev) static void addrconf_add_lroute(struct net_device *dev)
...@@ -1328,7 +1328,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1328,7 +1328,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 && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
if (rt->rt6i_flags&RTF_EXPIRES) { if (rt->rt6i_flags&RTF_EXPIRES) {
if (pinfo->onlink == 0 || valid_lft == 0) { if (pinfo->onlink == 0 || valid_lft == 0) {
ip6_del_rt(rt); ip6_del_rt(rt, NULL);
rt = NULL; rt = NULL;
} else { } else {
rt->rt6i_expires = rt_expires; rt->rt6i_expires = rt_expires;
...@@ -1952,7 +1952,7 @@ static void addrconf_rs_timer(unsigned long data) ...@@ -1952,7 +1952,7 @@ static void addrconf_rs_timer(unsigned long data)
rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex; rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex;
ip6_route_add(&rtmsg); ip6_route_add(&rtmsg, NULL);
} }
out: out:
......
...@@ -423,7 +423,8 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, ...@@ -423,7 +423,8 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
* Insert routing information in a node. * 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 *iter = NULL;
struct rt6_info **ins; struct rt6_info **ins;
...@@ -480,7 +481,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt) ...@@ -480,7 +481,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt)
*ins = rt; *ins = rt;
rt->rt6i_node = fn; rt->rt6i_node = fn;
atomic_inc(&rt->rt6i_ref); atomic_inc(&rt->rt6i_ref);
inet6_rt_notify(RTM_NEWROUTE, rt); inet6_rt_notify(RTM_NEWROUTE, rt, nlh);
rt6_stats.fib_rt_entries++; rt6_stats.fib_rt_entries++;
if ((fn->fn_flags & RTN_RTINFO) == 0) { if ((fn->fn_flags & RTN_RTINFO) == 0) {
...@@ -504,7 +505,7 @@ static __inline__ void fib6_start_gc(struct rt6_info *rt) ...@@ -504,7 +505,7 @@ static __inline__ void fib6_start_gc(struct rt6_info *rt)
* with source addr info in sub-trees * 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; struct fib6_node *fn;
int err = -ENOMEM; int err = -ENOMEM;
...@@ -577,7 +578,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt) ...@@ -577,7 +578,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt)
} }
#endif #endif
err = fib6_add_rt2node(fn, rt); err = fib6_add_rt2node(fn, rt, nlh);
if (err == 0) { if (err == 0) {
fib6_start_gc(rt); fib6_start_gc(rt);
...@@ -885,7 +886,8 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) ...@@ -885,7 +886,8 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
} }
} }
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 fib6_walker_t *w;
struct rt6_info *rt = *rtp; struct rt6_info *rt = *rtp;
...@@ -940,11 +942,11 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp) ...@@ -940,11 +942,11 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp)
if (atomic_read(&rt->rt6i_ref) != 1) BUG(); if (atomic_read(&rt->rt6i_ref) != 1) BUG();
} }
inet6_rt_notify(RTM_DELROUTE, rt); inet6_rt_notify(RTM_DELROUTE, rt, nlh);
rt6_release(rt); 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 fib6_node *fn = rt->rt6i_node;
struct rt6_info **rtp; struct rt6_info **rtp;
...@@ -969,7 +971,7 @@ int fib6_del(struct rt6_info *rt) ...@@ -969,7 +971,7 @@ int fib6_del(struct rt6_info *rt)
for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) { for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
if (*rtp == rt) { if (*rtp == rt) {
fib6_del_route(fn, rtp); fib6_del_route(fn, rtp, nlh);
return 0; return 0;
} }
} }
...@@ -1098,7 +1100,7 @@ static int fib6_clean_node(struct fib6_walker_t *w) ...@@ -1098,7 +1100,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
res = c->func(rt, c->arg); res = c->func(rt, c->arg);
if (res < 0) { if (res < 0) {
w->leaf = rt; w->leaf = rt;
res = fib6_del(rt); res = fib6_del(rt, NULL);
if (res) { if (res) {
#if RT6_DEBUG >= 2 #if RT6_DEBUG >= 2
printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res); printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
......
...@@ -961,7 +961,7 @@ void ndisc_recv_na(struct sk_buff *skb) ...@@ -961,7 +961,7 @@ void ndisc_recv_na(struct sk_buff *skb)
struct rt6_info *rt; struct rt6_info *rt;
rt = rt6_get_dflt_router(saddr, dev); rt = rt6_get_dflt_router(saddr, dev);
if (rt) if (rt)
ip6_del_rt(rt); ip6_del_rt(rt, NULL);
} }
} else { } else {
if (msg->icmph.icmp6_router) if (msg->icmph.icmp6_router)
...@@ -1035,7 +1035,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) ...@@ -1035,7 +1035,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
if (rt && lifetime == 0) { if (rt && lifetime == 0) {
ip6_del_rt(rt); ip6_del_rt(rt, NULL);
rt = NULL; rt = NULL;
} }
......
...@@ -318,12 +318,12 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, ...@@ -318,12 +318,12 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
be destroyed. be destroyed.
*/ */
static int rt6_ins(struct rt6_info *rt) static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh)
{ {
int err; int err;
write_lock_bh(&rt6_lock); 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); write_unlock_bh(&rt6_lock);
return err; return err;
...@@ -366,7 +366,7 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, ...@@ -366,7 +366,7 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
dst_hold(&rt->u.dst); dst_hold(&rt->u.dst);
err = rt6_ins(rt); err = rt6_ins(rt, NULL);
if (err == 0) if (err == 0)
return rt; return rt;
...@@ -522,7 +522,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) ...@@ -522,7 +522,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
if (rt) { if (rt) {
if (rt->rt6i_flags & RTF_CACHE) if (rt->rt6i_flags & RTF_CACHE)
ip6_del_rt(rt); ip6_del_rt(rt, NULL);
else else
dst_release(dst); dst_release(dst);
} }
...@@ -625,9 +625,10 @@ static int ipv6_get_hoplimit(struct net_device *dev) ...@@ -625,9 +625,10 @@ static int ipv6_get_hoplimit(struct net_device *dev)
* *
*/ */
int ip6_route_add(struct in6_rtmsg *rtmsg) int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
{ {
int err; int err;
struct rtmsg *r;
struct rt6_info *rt; struct rt6_info *rt;
struct net_device *dev = NULL; struct net_device *dev = NULL;
int addr_type; int addr_type;
...@@ -648,6 +649,11 @@ int ip6_route_add(struct in6_rtmsg *rtmsg) ...@@ -648,6 +649,11 @@ int ip6_route_add(struct in6_rtmsg *rtmsg)
rt->u.dst.obsolete = -1; rt->u.dst.obsolete = -1;
rt->rt6i_expires = rtmsg->rtmsg_info; 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); addr_type = ipv6_addr_type(&rtmsg->rtmsg_dst);
...@@ -772,7 +778,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg) ...@@ -772,7 +778,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg)
if (dst_metric(&rt->u.dst, RTAX_ADVMSS) > 65535-20) if (dst_metric(&rt->u.dst, RTAX_ADVMSS) > 65535-20)
rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535; rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535;
rt->u.dst.dev = dev; rt->u.dst.dev = dev;
return rt6_ins(rt); return rt6_ins(rt, nlh);
out: out:
if (dev) if (dev)
...@@ -781,7 +787,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg) ...@@ -781,7 +787,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg)
return err; return err;
} }
int ip6_del_rt(struct rt6_info *rt) int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh)
{ {
int err; int err;
...@@ -793,13 +799,13 @@ int ip6_del_rt(struct rt6_info *rt) ...@@ -793,13 +799,13 @@ int ip6_del_rt(struct rt6_info *rt)
dst_release(&rt->u.dst); dst_release(&rt->u.dst);
err = fib6_del(rt); err = fib6_del(rt, nlh);
write_unlock_bh(&rt6_lock); write_unlock_bh(&rt6_lock);
return err; return err;
} }
static int ip6_route_del(struct in6_rtmsg *rtmsg) static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
{ {
struct fib6_node *fn; struct fib6_node *fn;
struct rt6_info *rt; struct rt6_info *rt;
...@@ -826,7 +832,7 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg) ...@@ -826,7 +832,7 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg)
dst_hold(&rt->u.dst); dst_hold(&rt->u.dst);
read_unlock_bh(&rt6_lock); read_unlock_bh(&rt6_lock);
return ip6_del_rt(rt); return ip6_del_rt(rt, nlh);
} }
} }
read_unlock_bh(&rt6_lock); read_unlock_bh(&rt6_lock);
...@@ -928,11 +934,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, ...@@ -928,11 +934,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
nrt->u.dst.metrics[RTAX_ADVMSS-1] = 65535; nrt->u.dst.metrics[RTAX_ADVMSS-1] = 65535;
nrt->rt6i_hoplimit = ipv6_get_hoplimit(neigh->dev); nrt->rt6i_hoplimit = ipv6_get_hoplimit(neigh->dev);
if (rt6_ins(nrt)) if (rt6_ins(nrt, NULL))
goto out; goto out;
if (rt->rt6i_flags&RTF_CACHE) { if (rt->rt6i_flags&RTF_CACHE) {
ip6_del_rt(rt); ip6_del_rt(rt, NULL);
return; return;
} }
...@@ -1018,7 +1024,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, ...@@ -1018,7 +1024,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires); dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES; nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
rt6_ins(nrt); rt6_ins(nrt, NULL);
} }
out: out:
...@@ -1091,7 +1097,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, ...@@ -1091,7 +1097,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
rtmsg.rtmsg_ifindex = dev->ifindex; rtmsg.rtmsg_ifindex = dev->ifindex;
ip6_route_add(&rtmsg); ip6_route_add(&rtmsg, NULL);
return rt6_get_dflt_router(gwaddr, dev); return rt6_get_dflt_router(gwaddr, dev);
} }
...@@ -1117,7 +1123,7 @@ void rt6_purge_dflt_routers(int last_resort) ...@@ -1117,7 +1123,7 @@ void rt6_purge_dflt_routers(int last_resort)
read_unlock_bh(&rt6_lock); read_unlock_bh(&rt6_lock);
ip6_del_rt(rt); ip6_del_rt(rt, NULL);
goto restart; goto restart;
} }
...@@ -1143,10 +1149,10 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg) ...@@ -1143,10 +1149,10 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg)
rtnl_lock(); rtnl_lock();
switch (cmd) { switch (cmd) {
case SIOCADDRT: case SIOCADDRT:
err = ip6_route_add(&rtmsg); err = ip6_route_add(&rtmsg, NULL);
break; break;
case SIOCDELRT: case SIOCDELRT:
err = ip6_route_del(&rtmsg); err = ip6_route_del(&rtmsg, NULL);
break; break;
default: default:
err = -EINVAL; err = -EINVAL;
...@@ -1203,7 +1209,7 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev) ...@@ -1203,7 +1209,7 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev)
ipv6_addr_copy(&rt->rt6i_dst.addr, addr); ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
rt->rt6i_dst.plen = 128; rt->rt6i_dst.plen = 128;
rt6_ins(rt); rt6_ins(rt, NULL);
return 0; return 0;
} }
...@@ -1220,7 +1226,7 @@ int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev) ...@@ -1220,7 +1226,7 @@ int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev)
rt = rt6_lookup(addr, NULL, loopback_dev.ifindex, 1); rt = rt6_lookup(addr, NULL, loopback_dev.ifindex, 1);
if (rt) { if (rt) {
if (rt->rt6i_dst.plen == 128) if (rt->rt6i_dst.plen == 128)
err = ip6_del_rt(rt); err = ip6_del_rt(rt, NULL);
else else
dst_release(&rt->u.dst); dst_release(&rt->u.dst);
} }
...@@ -1350,7 +1356,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -1350,7 +1356,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
return -EINVAL; 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) int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
...@@ -1360,7 +1366,7 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -1360,7 +1366,7 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
return -EINVAL; return -EINVAL;
return ip6_route_add(&rtmsg); return ip6_route_add(&rtmsg, nlh);
} }
struct rt6_rtnl_dump_arg struct rt6_rtnl_dump_arg
...@@ -1373,13 +1379,18 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, ...@@ -1373,13 +1379,18 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
struct in6_addr *dst, struct in6_addr *dst,
struct in6_addr *src, struct in6_addr *src,
int iif, int iif,
int type, u32 pid, u32 seq) int type, u32 pid, u32 seq,
struct nlmsghdr *in_nlh)
{ {
struct rtmsg *rtm; struct rtmsg *rtm;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
unsigned char *b = skb->tail; unsigned char *b = skb->tail;
struct rta_cacheinfo ci; struct rta_cacheinfo ci;
if (!pid && in_nlh) {
pid = in_nlh->nlmsg_pid;
}
nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*rtm)); nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*rtm));
rtm = NLMSG_DATA(nlh); rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_INET6; rtm->rtm_family = AF_INET6;
...@@ -1395,7 +1406,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, ...@@ -1395,7 +1406,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
rtm->rtm_type = RTN_UNICAST; rtm->rtm_type = RTN_UNICAST;
rtm->rtm_flags = 0; rtm->rtm_flags = 0;
rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_scope = RT_SCOPE_UNIVERSE;
rtm->rtm_protocol = RTPROT_BOOT; rtm->rtm_protocol = rt->rt6i_protocol;
if (rt->rt6i_flags&RTF_DYNAMIC) if (rt->rt6i_flags&RTF_DYNAMIC)
rtm->rtm_protocol = RTPROT_REDIRECT; rtm->rtm_protocol = RTPROT_REDIRECT;
else if (rt->rt6i_flags&(RTF_ADDRCONF|RTF_ALLONLINK)) else if (rt->rt6i_flags&(RTF_ADDRCONF|RTF_ALLONLINK))
...@@ -1458,7 +1469,8 @@ static int rt6_dump_route(struct rt6_info *rt, void *p_arg) ...@@ -1458,7 +1469,8 @@ static int rt6_dump_route(struct rt6_info *rt, void *p_arg)
struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg; 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, 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) static int fib6_dump_node(struct fib6_walker_t *w)
...@@ -1608,7 +1620,8 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) ...@@ -1608,7 +1620,8 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
fl.nl_u.ip6_u.daddr, fl.nl_u.ip6_u.daddr,
fl.nl_u.ip6_u.saddr, fl.nl_u.ip6_u.saddr,
iif, 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) { if (err < 0) {
err = -EMSGSIZE; err = -EMSGSIZE;
goto out_free; goto out_free;
...@@ -1624,7 +1637,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) ...@@ -1624,7 +1637,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
goto out; goto out;
} }
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; struct sk_buff *skb;
int size = NLMSG_SPACE(sizeof(struct rtmsg)+256); int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
...@@ -1634,7 +1647,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt) ...@@ -1634,7 +1647,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt)
netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS); netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
return; 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); kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL); netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
return; return;
......
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