diff options
| -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(); | 
