diff options
Diffstat (limited to 'net/ipv4/fib_frontend.c')
-rw-r--r-- | net/ipv4/fib_frontend.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 7e30c7b50a28..ee94bd32d6dc 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -758,7 +758,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
758 | unsigned int e = 0, s_e; | 758 | unsigned int e = 0, s_e; |
759 | struct fib_table *tb; | 759 | struct fib_table *tb; |
760 | struct hlist_head *head; | 760 | struct hlist_head *head; |
761 | int dumped = 0; | 761 | int dumped = 0, err; |
762 | 762 | ||
763 | if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) && | 763 | if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) && |
764 | ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED) | 764 | ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED) |
@@ -778,20 +778,27 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
778 | if (dumped) | 778 | if (dumped) |
779 | memset(&cb->args[2], 0, sizeof(cb->args) - | 779 | memset(&cb->args[2], 0, sizeof(cb->args) - |
780 | 2 * sizeof(cb->args[0])); | 780 | 2 * sizeof(cb->args[0])); |
781 | if (fib_table_dump(tb, skb, cb) < 0) | 781 | err = fib_table_dump(tb, skb, cb); |
782 | goto out; | 782 | if (err < 0) { |
783 | if (likely(skb->len)) | ||
784 | goto out; | ||
785 | |||
786 | goto out_err; | ||
787 | } | ||
783 | dumped = 1; | 788 | dumped = 1; |
784 | next: | 789 | next: |
785 | e++; | 790 | e++; |
786 | } | 791 | } |
787 | } | 792 | } |
788 | out: | 793 | out: |
794 | err = skb->len; | ||
795 | out_err: | ||
789 | rcu_read_unlock(); | 796 | rcu_read_unlock(); |
790 | 797 | ||
791 | cb->args[1] = e; | 798 | cb->args[1] = e; |
792 | cb->args[0] = h; | 799 | cb->args[0] = h; |
793 | 800 | ||
794 | return skb->len; | 801 | return err; |
795 | } | 802 | } |
796 | 803 | ||
797 | /* Prepare and feed intra-kernel routing request. | 804 | /* Prepare and feed intra-kernel routing request. |
@@ -1081,7 +1088,8 @@ static void nl_fib_input(struct sk_buff *skb) | |||
1081 | 1088 | ||
1082 | net = sock_net(skb->sk); | 1089 | net = sock_net(skb->sk); |
1083 | nlh = nlmsg_hdr(skb); | 1090 | nlh = nlmsg_hdr(skb); |
1084 | if (skb->len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len || | 1091 | if (skb->len < nlmsg_total_size(sizeof(*frn)) || |
1092 | skb->len < nlh->nlmsg_len || | ||
1085 | nlmsg_len(nlh) < sizeof(*frn)) | 1093 | nlmsg_len(nlh) < sizeof(*frn)) |
1086 | return; | 1094 | return; |
1087 | 1095 | ||
@@ -1312,13 +1320,14 @@ static struct pernet_operations fib_net_ops = { | |||
1312 | 1320 | ||
1313 | void __init ip_fib_init(void) | 1321 | void __init ip_fib_init(void) |
1314 | { | 1322 | { |
1315 | rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL); | 1323 | fib_trie_init(); |
1316 | rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL); | ||
1317 | rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL); | ||
1318 | 1324 | ||
1319 | register_pernet_subsys(&fib_net_ops); | 1325 | register_pernet_subsys(&fib_net_ops); |
1326 | |||
1320 | register_netdevice_notifier(&fib_netdev_notifier); | 1327 | register_netdevice_notifier(&fib_netdev_notifier); |
1321 | register_inetaddr_notifier(&fib_inetaddr_notifier); | 1328 | register_inetaddr_notifier(&fib_inetaddr_notifier); |
1322 | 1329 | ||
1323 | fib_trie_init(); | 1330 | rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL); |
1331 | rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL); | ||
1332 | rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL); | ||
1324 | } | 1333 | } |