diff options
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 83 |
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 | ||
53 | DECLARE_MUTEX(rtnl_sem); | 54 | DECLARE_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 | ||
465 | static int rtnetlink_done(struct netlink_callback *cb) | ||
466 | { | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | /* Protected by RTNL sempahore. */ | 466 | /* Protected by RTNL sempahore. */ |
471 | static struct rtattr **rta_buf; | 467 | static struct rtattr **rta_buf; |
472 | static int rtattr_max; | 468 | static 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 | |||
587 | static 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 | |||
624 | static void rtnetlink_rcv(struct sock *sk, int len) | 573 | static 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(); |