aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/rtnetlink.c75
1 files changed, 5 insertions, 70 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 193fd8637f9f..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
@@ -519,8 +520,6 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
519 } 520 }
520 521
521 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 522 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
522 u32 rlen;
523
524 if (link->dumpit == NULL) 523 if (link->dumpit == NULL)
525 link = &(rtnetlink_links[PF_UNSPEC][type]); 524 link = &(rtnetlink_links[PF_UNSPEC][type]);
526 525
@@ -531,10 +530,8 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
531 link->dumpit, NULL)) != 0) { 530 link->dumpit, NULL)) != 0) {
532 return -1; 531 return -1;
533 } 532 }
534 rlen = NLMSG_ALIGN(nlh->nlmsg_len); 533
535 if (rlen > skb->len) 534 netlink_queue_skip(nlh, skb);
536 rlen = skb->len;
537 skb_pull(skb, rlen);
538 return -1; 535 return -1;
539 } 536 }
540 537
@@ -573,75 +570,13 @@ err_inval:
573 return -1; 570 return -1;
574} 571}
575 572
576/*
577 * Process one packet of messages.
578 * Malformed skbs with wrong lengths of messages are discarded silently.
579 */
580
581static inline int rtnetlink_rcv_skb(struct sk_buff *skb)
582{
583 int err;
584 struct nlmsghdr * nlh;
585
586 while (skb->len >= NLMSG_SPACE(0)) {
587 u32 rlen;
588
589 nlh = (struct nlmsghdr *)skb->data;
590 if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
591 return 0;
592 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
593 if (rlen > skb->len)
594 rlen = skb->len;
595 if (rtnetlink_rcv_msg(skb, nlh, &err)) {
596 /* Not error, but we must interrupt processing here:
597 * Note, that in this case we do not pull message
598 * from skb, it will be processed later.
599 */
600 if (err == 0)
601 return -1;
602 netlink_ack(skb, nlh, err);
603 } else if (nlh->nlmsg_flags&NLM_F_ACK)
604 netlink_ack(skb, nlh, 0);
605 skb_pull(skb, rlen);
606 }
607
608 return 0;
609}
610
611/*
612 * rtnetlink input queue processing routine:
613 * - process as much as there was in the queue upon entry.
614 * - feed skbs to rtnetlink_rcv_skb, until it refuse a message,
615 * that will occur, when a dump started.
616 */
617
618static void rtnetlink_rcv(struct sock *sk, int len) 573static void rtnetlink_rcv(struct sock *sk, int len)
619{ 574{
620 unsigned int qlen = skb_queue_len(&sk->sk_receive_queue); 575 unsigned int qlen = 0;
621 576
622 do { 577 do {
623 struct sk_buff *skb;
624
625 rtnl_lock(); 578 rtnl_lock();
626 579 netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg);
627 if (qlen > skb_queue_len(&sk->sk_receive_queue))
628 qlen = skb_queue_len(&sk->sk_receive_queue);
629
630 for (; qlen; qlen--) {
631 skb = skb_dequeue(&sk->sk_receive_queue);
632 if (rtnetlink_rcv_skb(skb)) {
633 if (skb->len)
634 skb_queue_head(&sk->sk_receive_queue,
635 skb);
636 else {
637 kfree_skb(skb);
638 qlen--;
639 }
640 break;
641 }
642 kfree_skb(skb);
643 }
644
645 up(&rtnl_sem); 580 up(&rtnl_sem);
646 581
647 netdev_run_todo(); 582 netdev_run_todo();