diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 42 |
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 | ||