diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/rtnetlink.c | 75 |
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 | ||
53 | DECLARE_MUTEX(rtnl_sem); | 54 | DECLARE_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 | |||
581 | static 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 | |||
618 | static void rtnetlink_rcv(struct sock *sk, int len) | 573 | static 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(); |