aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 18e00ce1719a..3eed045c65a5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -4670,20 +4670,31 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
4670 int iif, int type, u32 portid, u32 seq, 4670 int iif, int type, u32 portid, u32 seq,
4671 unsigned int flags) 4671 unsigned int flags)
4672{ 4672{
4673 struct rtmsg *rtm; 4673 struct rt6_info *rt6 = (struct rt6_info *)dst;
4674 struct rt6key *rt6_dst, *rt6_src;
4675 u32 *pmetrics, table, rt6_flags;
4674 struct nlmsghdr *nlh; 4676 struct nlmsghdr *nlh;
4677 struct rtmsg *rtm;
4675 long expires = 0; 4678 long expires = 0;
4676 u32 *pmetrics;
4677 u32 table;
4678 4679
4679 nlh = nlmsg_put(skb, portid, seq, type, sizeof(*rtm), flags); 4680 nlh = nlmsg_put(skb, portid, seq, type, sizeof(*rtm), flags);
4680 if (!nlh) 4681 if (!nlh)
4681 return -EMSGSIZE; 4682 return -EMSGSIZE;
4682 4683
4684 if (rt6) {
4685 rt6_dst = &rt6->rt6i_dst;
4686 rt6_src = &rt6->rt6i_src;
4687 rt6_flags = rt6->rt6i_flags;
4688 } else {
4689 rt6_dst = &rt->fib6_dst;
4690 rt6_src = &rt->fib6_src;
4691 rt6_flags = rt->fib6_flags;
4692 }
4693
4683 rtm = nlmsg_data(nlh); 4694 rtm = nlmsg_data(nlh);
4684 rtm->rtm_family = AF_INET6; 4695 rtm->rtm_family = AF_INET6;
4685 rtm->rtm_dst_len = rt->fib6_dst.plen; 4696 rtm->rtm_dst_len = rt6_dst->plen;
4686 rtm->rtm_src_len = rt->fib6_src.plen; 4697 rtm->rtm_src_len = rt6_src->plen;
4687 rtm->rtm_tos = 0; 4698 rtm->rtm_tos = 0;
4688 if (rt->fib6_table) 4699 if (rt->fib6_table)
4689 table = rt->fib6_table->tb6_id; 4700 table = rt->fib6_table->tb6_id;
@@ -4698,7 +4709,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
4698 rtm->rtm_scope = RT_SCOPE_UNIVERSE; 4709 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
4699 rtm->rtm_protocol = rt->fib6_protocol; 4710 rtm->rtm_protocol = rt->fib6_protocol;
4700 4711
4701 if (rt->fib6_flags & RTF_CACHE) 4712 if (rt6_flags & RTF_CACHE)
4702 rtm->rtm_flags |= RTM_F_CLONED; 4713 rtm->rtm_flags |= RTM_F_CLONED;
4703 4714
4704 if (dest) { 4715 if (dest) {
@@ -4706,7 +4717,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
4706 goto nla_put_failure; 4717 goto nla_put_failure;
4707 rtm->rtm_dst_len = 128; 4718 rtm->rtm_dst_len = 128;
4708 } else if (rtm->rtm_dst_len) 4719 } else if (rtm->rtm_dst_len)
4709 if (nla_put_in6_addr(skb, RTA_DST, &rt->fib6_dst.addr)) 4720 if (nla_put_in6_addr(skb, RTA_DST, &rt6_dst->addr))
4710 goto nla_put_failure; 4721 goto nla_put_failure;
4711#ifdef CONFIG_IPV6_SUBTREES 4722#ifdef CONFIG_IPV6_SUBTREES
4712 if (src) { 4723 if (src) {
@@ -4714,12 +4725,12 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
4714 goto nla_put_failure; 4725 goto nla_put_failure;
4715 rtm->rtm_src_len = 128; 4726 rtm->rtm_src_len = 128;
4716 } else if (rtm->rtm_src_len && 4727 } else if (rtm->rtm_src_len &&
4717 nla_put_in6_addr(skb, RTA_SRC, &rt->fib6_src.addr)) 4728 nla_put_in6_addr(skb, RTA_SRC, &rt6_src->addr))
4718 goto nla_put_failure; 4729 goto nla_put_failure;
4719#endif 4730#endif
4720 if (iif) { 4731 if (iif) {
4721#ifdef CONFIG_IPV6_MROUTE 4732#ifdef CONFIG_IPV6_MROUTE
4722 if (ipv6_addr_is_multicast(&rt->fib6_dst.addr)) { 4733 if (ipv6_addr_is_multicast(&rt6_dst->addr)) {
4723 int err = ip6mr_get_route(net, skb, rtm, portid); 4734 int err = ip6mr_get_route(net, skb, rtm, portid);
4724 4735
4725 if (err == 0) 4736 if (err == 0)
@@ -4754,7 +4765,14 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
4754 /* For multipath routes, walk the siblings list and add 4765 /* For multipath routes, walk the siblings list and add
4755 * each as a nexthop within RTA_MULTIPATH. 4766 * each as a nexthop within RTA_MULTIPATH.
4756 */ 4767 */
4757 if (rt->fib6_nsiblings) { 4768 if (rt6) {
4769 if (rt6_flags & RTF_GATEWAY &&
4770 nla_put_in6_addr(skb, RTA_GATEWAY, &rt6->rt6i_gateway))
4771 goto nla_put_failure;
4772
4773 if (dst->dev && nla_put_u32(skb, RTA_OIF, dst->dev->ifindex))
4774 goto nla_put_failure;
4775 } else if (rt->fib6_nsiblings) {
4758 struct fib6_info *sibling, *next_sibling; 4776 struct fib6_info *sibling, *next_sibling;
4759 struct nlattr *mp; 4777 struct nlattr *mp;
4760 4778
@@ -4777,7 +4795,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
4777 goto nla_put_failure; 4795 goto nla_put_failure;
4778 } 4796 }
4779 4797
4780 if (rt->fib6_flags & RTF_EXPIRES) { 4798 if (rt6_flags & RTF_EXPIRES) {
4781 expires = dst ? dst->expires : rt->expires; 4799 expires = dst ? dst->expires : rt->expires;
4782 expires -= jiffies; 4800 expires -= jiffies;
4783 } 4801 }
@@ -4785,7 +4803,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
4785 if (rtnl_put_cacheinfo(skb, dst, 0, expires, dst ? dst->error : 0) < 0) 4803 if (rtnl_put_cacheinfo(skb, dst, 0, expires, dst ? dst->error : 0) < 0)
4786 goto nla_put_failure; 4804 goto nla_put_failure;
4787 4805
4788 if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->fib6_flags))) 4806 if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt6_flags)))
4789 goto nla_put_failure; 4807 goto nla_put_failure;
4790 4808
4791 4809