aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c83
1 files changed, 6 insertions, 77 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 9bed7569ce3f..8700379685e0 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -49,6 +49,7 @@
49#include <net/udp.h> 49#include <net/udp.h>
50#include <net/sock.h> 50#include <net/sock.h>
51#include <net/pkt_sched.h> 51#include <net/pkt_sched.h>
52#include <net/netlink.h>
52 53
53DECLARE_MUTEX(rtnl_sem); 54DECLARE_MUTEX(rtnl_sem);
54 55
@@ -462,11 +463,6 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
462 netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_KERNEL); 463 netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_KERNEL);
463} 464}
464 465
465static int rtnetlink_done(struct netlink_callback *cb)
466{
467 return 0;
468}
469
470/* Protected by RTNL sempahore. */ 466/* Protected by RTNL sempahore. */
471static struct rtattr **rta_buf; 467static struct rtattr **rta_buf;
472static int rtattr_max; 468static int rtattr_max;
@@ -524,8 +520,6 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
524 } 520 }
525 521
526 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 522 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
527 u32 rlen;
528
529 if (link->dumpit == NULL) 523 if (link->dumpit == NULL)
530 link = &(rtnetlink_links[PF_UNSPEC][type]); 524 link = &(rtnetlink_links[PF_UNSPEC][type]);
531 525
@@ -533,14 +527,11 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
533 goto err_inval; 527 goto err_inval;
534 528
535 if ((*errp = netlink_dump_start(rtnl, skb, nlh, 529 if ((*errp = netlink_dump_start(rtnl, skb, nlh,
536 link->dumpit, 530 link->dumpit, NULL)) != 0) {
537 rtnetlink_done)) != 0) {
538 return -1; 531 return -1;
539 } 532 }
540 rlen = NLMSG_ALIGN(nlh->nlmsg_len); 533
541 if (rlen > skb->len) 534 netlink_queue_skip(nlh, skb);
542 rlen = skb->len;
543 skb_pull(skb, rlen);
544 return -1; 535 return -1;
545 } 536 }
546 537
@@ -579,75 +570,13 @@ err_inval:
579 return -1; 570 return -1;
580} 571}
581 572
582/*
583 * Process one packet of messages.
584 * Malformed skbs with wrong lengths of messages are discarded silently.
585 */
586
587static inline int rtnetlink_rcv_skb(struct sk_buff *skb)
588{
589 int err;
590 struct nlmsghdr * nlh;
591
592 while (skb->len >= NLMSG_SPACE(0)) {
593 u32 rlen;
594
595 nlh = (struct nlmsghdr *)skb->data;
596 if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
597 return 0;
598 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
599 if (rlen > skb->len)
600 rlen = skb->len;
601 if (rtnetlink_rcv_msg(skb, nlh, &err)) {
602 /* Not error, but we must interrupt processing here:
603 * Note, that in this case we do not pull message
604 * from skb, it will be processed later.
605 */
606 if (err == 0)
607 return -1;
608 netlink_ack(skb, nlh, err);
609 } else if (nlh->nlmsg_flags&NLM_F_ACK)
610 netlink_ack(skb, nlh, 0);
611 skb_pull(skb, rlen);
612 }
613
614 return 0;
615}
616
617/*
618 * rtnetlink input queue processing routine:
619 * - process as much as there was in the queue upon entry.
620 * - feed skbs to rtnetlink_rcv_skb, until it refuse a message,
621 * that will occur, when a dump started.
622 */
623
624static void rtnetlink_rcv(struct sock *sk, int len) 573static void rtnetlink_rcv(struct sock *sk, int len)
625{ 574{
626 unsigned int qlen = skb_queue_len(&sk->sk_receive_queue); 575 unsigned int qlen = 0;
627 576
628 do { 577 do {
629 struct sk_buff *skb;
630
631 rtnl_lock(); 578 rtnl_lock();
632 579 netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg);
633 if (qlen > skb_queue_len(&sk->sk_receive_queue))
634 qlen = skb_queue_len(&sk->sk_receive_queue);
635
636 for (; qlen; qlen--) {
637 skb = skb_dequeue(&sk->sk_receive_queue);
638 if (rtnetlink_rcv_skb(skb)) {
639 if (skb->len)
640 skb_queue_head(&sk->sk_receive_queue,
641 skb);
642 else {
643 kfree_skb(skb);
644 qlen--;
645 }
646 break;
647 }
648 kfree_skb(skb);
649 }
650
651 up(&rtnl_sem); 580 up(&rtnl_sem);
652 581
653 netdev_run_todo(); 582 netdev_run_todo();