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.c166
1 files changed, 83 insertions, 83 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index b873cbcdd0b8..20ffe8e88c0f 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2639,51 +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 NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
2655 r->rtm_type = rt->rt_type; 2656 r->rtm_type = rt->rt_type;
2656 r->rtm_scope = RT_SCOPE_UNIVERSE; 2657 r->rtm_scope = RT_SCOPE_UNIVERSE;
2657 r->rtm_protocol = RTPROT_UNSPEC; 2658 r->rtm_protocol = RTPROT_UNSPEC;
2658 r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; 2659 r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
2659 if (rt->rt_flags & RTCF_NOTIFY) 2660 if (rt->rt_flags & RTCF_NOTIFY)
2660 r->rtm_flags |= RTM_F_NOTIFY; 2661 r->rtm_flags |= RTM_F_NOTIFY;
2661 RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst); 2662
2663 NLA_PUT_U32(skb, RTA_DST, rt->rt_dst);
2664
2662 if (rt->fl.fl4_src) { 2665 if (rt->fl.fl4_src) {
2663 r->rtm_src_len = 32; 2666 r->rtm_src_len = 32;
2664 RTA_PUT(skb, RTA_SRC, 4, &rt->fl.fl4_src); 2667 NLA_PUT_U32(skb, RTA_SRC, rt->fl.fl4_src);
2665 } 2668 }
2666 if (rt->u.dst.dev) 2669 if (rt->u.dst.dev)
2667 RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex); 2670 NLA_PUT_U32(skb, RTA_OIF, rt->u.dst.dev->ifindex);
2668#ifdef CONFIG_NET_CLS_ROUTE 2671#ifdef CONFIG_NET_CLS_ROUTE
2669 if (rt->u.dst.tclassid) 2672 if (rt->u.dst.tclassid)
2670 RTA_PUT(skb, RTA_FLOW, 4, &rt->u.dst.tclassid); 2673 NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid);
2671#endif 2674#endif
2672#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED 2675#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
2673 if (rt->rt_multipath_alg != IP_MP_ALG_NONE) { 2676 if (rt->rt_multipath_alg != IP_MP_ALG_NONE)
2674 __u32 alg = rt->rt_multipath_alg; 2677 NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
2675
2676 RTA_PUT(skb, RTA_MP_ALGO, 4, &alg);
2677 }
2678#endif 2678#endif
2679 if (rt->fl.iif) 2679 if (rt->fl.iif)
2680 RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_spec_dst); 2680 NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_spec_dst);
2681 else if (rt->rt_src != rt->fl.fl4_src) 2681 else if (rt->rt_src != rt->fl.fl4_src)
2682 RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_src); 2682 NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_src);
2683
2683 if (rt->rt_dst != rt->rt_gateway) 2684 if (rt->rt_dst != rt->rt_gateway)
2684 RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway); 2685 NLA_PUT_U32(skb, RTA_GATEWAY, rt->rt_gateway);
2686
2685 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) 2687 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
2686 goto rtattr_failure; 2688 goto nla_put_failure;
2689
2687 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);
2688 ci.rta_used = rt->u.dst.__use; 2691 ci.rta_used = rt->u.dst.__use;
2689 ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt); 2692 ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
@@ -2700,10 +2703,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2700 ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp; 2703 ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;
2701 } 2704 }
2702 } 2705 }
2703#ifdef CONFIG_IP_MROUTE 2706
2704 eptr = (struct rtattr*)skb->tail;
2705#endif
2706 RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
2707 if (rt->fl.iif) { 2707 if (rt->fl.iif) {
2708#ifdef CONFIG_IP_MROUTE 2708#ifdef CONFIG_IP_MROUTE
2709 u32 dst = rt->rt_dst; 2709 u32 dst = rt->rt_dst;
@@ -2715,41 +2715,46 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2715 if (!nowait) { 2715 if (!nowait) {
2716 if (err == 0) 2716 if (err == 0)
2717 return 0; 2717 return 0;
2718 goto nlmsg_failure; 2718 goto nla_put_failure;
2719 } else { 2719 } else {
2720 if (err == -EMSGSIZE) 2720 if (err == -EMSGSIZE)
2721 goto nlmsg_failure; 2721 goto nla_put_failure;
2722 ((struct rta_cacheinfo*)RTA_DATA(eptr))->rta_error = err; 2722 ci.rta_error = err;
2723 } 2723 }
2724 } 2724 }
2725 } else 2725 } else
2726#endif 2726#endif
2727 RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); 2727 NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif);
2728 } 2728 }
2729 2729
2730 nlh->nlmsg_len = skb->tail - b; 2730 NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
2731 return skb->len; 2731
2732 return nlmsg_end(skb, nlh);
2732 2733
2733nlmsg_failure: 2734nla_put_failure:
2734rtattr_failure: 2735 return nlmsg_cancel(skb, nlh);
2735 skb_trim(skb, b - skb->data);
2736 return -1;
2737} 2736}
2738 2737
2739int 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)
2740{ 2739{
2741 struct rtattr **rta = arg; 2740 struct rtmsg *rtm;
2742 struct rtmsg *rtm = NLMSG_DATA(nlh); 2741 struct nlattr *tb[RTA_MAX+1];
2743 struct rtable *rt = NULL; 2742 struct rtable *rt = NULL;
2744 u32 dst = 0; 2743 u32 dst, src, iif;
2745 u32 src = 0; 2744 int err;
2746 int iif = 0;
2747 int err = -ENOBUFS;
2748 struct sk_buff *skb; 2745 struct sk_buff *skb;
2749 2746
2747 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
2748 if (err < 0)
2749 goto errout;
2750
2751 rtm = nlmsg_data(nlh);
2752
2750 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 2753 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
2751 if (!skb) 2754 if (skb == NULL) {
2752 goto out; 2755 err = -ENOBUFS;
2756 goto errout;
2757 }
2753 2758
2754 /* Reserve room for dummy headers, this skb can pass 2759 /* Reserve room for dummy headers, this skb can pass
2755 through good chunk of routing engine. 2760 through good chunk of routing engine.
@@ -2760,62 +2765,61 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
2760 skb->nh.iph->protocol = IPPROTO_ICMP; 2765 skb->nh.iph->protocol = IPPROTO_ICMP;
2761 skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr)); 2766 skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
2762 2767
2763 if (rta[RTA_SRC - 1]) 2768 src = tb[RTA_SRC] ? nla_get_u32(tb[RTA_SRC]) : 0;
2764 memcpy(&src, RTA_DATA(rta[RTA_SRC - 1]), 4); 2769 dst = tb[RTA_DST] ? nla_get_u32(tb[RTA_DST]) : 0;
2765 if (rta[RTA_DST - 1]) 2770 iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
2766 memcpy(&dst, RTA_DATA(rta[RTA_DST - 1]), 4);
2767 if (rta[RTA_IIF - 1])
2768 memcpy(&iif, RTA_DATA(rta[RTA_IIF - 1]), sizeof(int));
2769 2771
2770 if (iif) { 2772 if (iif) {
2771 struct net_device *dev = __dev_get_by_index(iif); 2773 struct net_device *dev;
2772 err = -ENODEV; 2774
2773 if (!dev) 2775 dev = __dev_get_by_index(iif);
2774 goto out_free; 2776 if (dev == NULL) {
2777 err = -ENODEV;
2778 goto errout_free;
2779 }
2780
2775 skb->protocol = htons(ETH_P_IP); 2781 skb->protocol = htons(ETH_P_IP);
2776 skb->dev = dev; 2782 skb->dev = dev;
2777 local_bh_disable(); 2783 local_bh_disable();
2778 err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev); 2784 err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
2779 local_bh_enable(); 2785 local_bh_enable();
2780 rt = (struct rtable*)skb->dst; 2786
2781 if (!err && rt->u.dst.error) 2787 rt = (struct rtable*) skb->dst;
2788 if (err == 0 && rt->u.dst.error)
2782 err = -rt->u.dst.error; 2789 err = -rt->u.dst.error;
2783 } else { 2790 } else {
2784 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst, 2791 struct flowi fl = {
2785 .saddr = src, 2792 .nl_u = {
2786 .tos = rtm->rtm_tos } } }; 2793 .ip4_u = {
2787 int oif = 0; 2794 .daddr = dst,
2788 if (rta[RTA_OIF - 1]) 2795 .saddr = src,
2789 memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int)); 2796 .tos = rtm->rtm_tos,
2790 fl.oif = oif; 2797 },
2798 },
2799 .oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0,
2800 };
2791 err = ip_route_output_key(&rt, &fl); 2801 err = ip_route_output_key(&rt, &fl);
2792 } 2802 }
2803
2793 if (err) 2804 if (err)
2794 goto out_free; 2805 goto errout_free;
2795 2806
2796 skb->dst = &rt->u.dst; 2807 skb->dst = &rt->u.dst;
2797 if (rtm->rtm_flags & RTM_F_NOTIFY) 2808 if (rtm->rtm_flags & RTM_F_NOTIFY)
2798 rt->rt_flags |= RTCF_NOTIFY; 2809 rt->rt_flags |= RTCF_NOTIFY;
2799 2810
2800 NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
2801
2802 err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, 2811 err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
2803 RTM_NEWROUTE, 0, 0); 2812 RTM_NEWROUTE, 0, 0);
2804 if (!err) 2813 if (err <= 0)
2805 goto out_free; 2814 goto errout_free;
2806 if (err < 0) {
2807 err = -EMSGSIZE;
2808 goto out_free;
2809 }
2810 2815
2811 err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); 2816 err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
2812 if (err > 0) 2817errout:
2813 err = 0; 2818 return err;
2814out: return err;
2815 2819
2816out_free: 2820errout_free:
2817 kfree_skb(skb); 2821 kfree_skb(skb);
2818 goto out; 2822 goto errout;
2819} 2823}
2820 2824
2821int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) 2825int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
@@ -3143,13 +3147,9 @@ int __init ip_rt_init(void)
3143 } 3147 }
3144#endif 3148#endif
3145 3149
3146 ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache", 3150 ipv4_dst_ops.kmem_cachep =
3147 sizeof(struct rtable), 3151 kmem_cache_create("ip_dst_cache", sizeof(struct rtable), 0,
3148 0, SLAB_HWCACHE_ALIGN, 3152 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
3149 NULL, NULL);
3150
3151 if (!ipv4_dst_ops.kmem_cachep)
3152 panic("IP: failed to allocate ip_dst_cache\n");
3153 3153
3154 rt_hash_table = (struct rt_hash_bucket *) 3154 rt_hash_table = (struct rt_hash_bucket *)
3155 alloc_large_system_hash("IP route cache", 3155 alloc_large_system_hash("IP route cache",