aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c68
1 files changed, 33 insertions, 35 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index b8f6cadc5b3a..31b67059ac29 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2639,52 +2639,54 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2639{ 2639{
2640 struct rtable *rt = (struct rtable*)skb->dst; 2640 struct rtable *rt = (struct rtable*)skb->dst;
2641 struct rtmsg *r; 2641 struct rtmsg *r;
2642 struct nlmsghdr *nlh; 2642 struct nlmsghdr *nlh;
2643 unsigned char *b = skb->tail;
2644 struct rta_cacheinfo ci; 2643 struct rta_cacheinfo ci;
2645#ifdef CONFIG_IP_MROUTE 2644
2646 struct rtattr *eptr; 2645 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
2647#endif 2646 if (nlh == NULL)
2648 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); 2647 return -ENOBUFS;
2649 r = NLMSG_DATA(nlh); 2648
2649 r = nlmsg_data(nlh);
2650 r->rtm_family = AF_INET; 2650 r->rtm_family = AF_INET;
2651 r->rtm_dst_len = 32; 2651 r->rtm_dst_len = 32;
2652 r->rtm_src_len = 0; 2652 r->rtm_src_len = 0;
2653 r->rtm_tos = rt->fl.fl4_tos; 2653 r->rtm_tos = rt->fl.fl4_tos;
2654 r->rtm_table = RT_TABLE_MAIN; 2654 r->rtm_table = RT_TABLE_MAIN;
2655 RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN); 2655 NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
2656 r->rtm_type = rt->rt_type; 2656 r->rtm_type = rt->rt_type;
2657 r->rtm_scope = RT_SCOPE_UNIVERSE; 2657 r->rtm_scope = RT_SCOPE_UNIVERSE;
2658 r->rtm_protocol = RTPROT_UNSPEC; 2658 r->rtm_protocol = RTPROT_UNSPEC;
2659 r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; 2659 r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
2660 if (rt->rt_flags & RTCF_NOTIFY) 2660 if (rt->rt_flags & RTCF_NOTIFY)
2661 r->rtm_flags |= RTM_F_NOTIFY; 2661 r->rtm_flags |= RTM_F_NOTIFY;
2662 RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst); 2662
2663 NLA_PUT_U32(skb, RTA_DST, rt->rt_dst);
2664
2663 if (rt->fl.fl4_src) { 2665 if (rt->fl.fl4_src) {
2664 r->rtm_src_len = 32; 2666 r->rtm_src_len = 32;
2665 RTA_PUT(skb, RTA_SRC, 4, &rt->fl.fl4_src); 2667 NLA_PUT_U32(skb, RTA_SRC, rt->fl.fl4_src);
2666 } 2668 }
2667 if (rt->u.dst.dev) 2669 if (rt->u.dst.dev)
2668 RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex); 2670 NLA_PUT_U32(skb, RTA_OIF, rt->u.dst.dev->ifindex);
2669#ifdef CONFIG_NET_CLS_ROUTE 2671#ifdef CONFIG_NET_CLS_ROUTE
2670 if (rt->u.dst.tclassid) 2672 if (rt->u.dst.tclassid)
2671 RTA_PUT(skb, RTA_FLOW, 4, &rt->u.dst.tclassid); 2673 NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid);
2672#endif 2674#endif
2673#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED 2675#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
2674 if (rt->rt_multipath_alg != IP_MP_ALG_NONE) { 2676 if (rt->rt_multipath_alg != IP_MP_ALG_NONE)
2675 __u32 alg = rt->rt_multipath_alg; 2677 NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
2676
2677 RTA_PUT(skb, RTA_MP_ALGO, 4, &alg);
2678 }
2679#endif 2678#endif
2680 if (rt->fl.iif) 2679 if (rt->fl.iif)
2681 RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_spec_dst); 2680 NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_spec_dst);
2682 else if (rt->rt_src != rt->fl.fl4_src) 2681 else if (rt->rt_src != rt->fl.fl4_src)
2683 RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_src); 2682 NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_src);
2683
2684 if (rt->rt_dst != rt->rt_gateway) 2684 if (rt->rt_dst != rt->rt_gateway)
2685 RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway); 2685 NLA_PUT_U32(skb, RTA_GATEWAY, rt->rt_gateway);
2686
2686 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) 2687 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
2687 goto rtattr_failure; 2688 goto nla_put_failure;
2689
2688 ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); 2690 ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
2689 ci.rta_used = rt->u.dst.__use; 2691 ci.rta_used = rt->u.dst.__use;
2690 ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt); 2692 ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
@@ -2701,10 +2703,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2701 ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp; 2703 ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;
2702 } 2704 }
2703 } 2705 }
2704#ifdef CONFIG_IP_MROUTE 2706
2705 eptr = (struct rtattr*)skb->tail;
2706#endif
2707 RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
2708 if (rt->fl.iif) { 2707 if (rt->fl.iif) {
2709#ifdef CONFIG_IP_MROUTE 2708#ifdef CONFIG_IP_MROUTE
2710 u32 dst = rt->rt_dst; 2709 u32 dst = rt->rt_dst;
@@ -2716,25 +2715,24 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2716 if (!nowait) { 2715 if (!nowait) {
2717 if (err == 0) 2716 if (err == 0)
2718 return 0; 2717 return 0;
2719 goto nlmsg_failure; 2718 goto nla_put_failure;
2720 } else { 2719 } else {
2721 if (err == -EMSGSIZE) 2720 if (err == -EMSGSIZE)
2722 goto nlmsg_failure; 2721 goto nla_put_failure;
2723 ((struct rta_cacheinfo*)RTA_DATA(eptr))->rta_error = err; 2722 ci.rta_error = err;
2724 } 2723 }
2725 } 2724 }
2726 } else 2725 } else
2727#endif 2726#endif
2728 RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); 2727 NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif);
2729 } 2728 }
2730 2729
2731 nlh->nlmsg_len = skb->tail - b; 2730 NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
2732 return skb->len; 2731
2732 return nlmsg_end(skb, nlh);
2733 2733
2734nlmsg_failure: 2734nla_put_failure:
2735rtattr_failure: 2735 return nlmsg_cancel(skb, nlh);
2736 skb_trim(skb, b - skb->data);
2737 return -1;
2738} 2736}
2739 2737
2740int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) 2738int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)