diff options
Diffstat (limited to 'net/core')
-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 193fd8637f9..8700379685e 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -49,6 +49,7 @@ #include <net/udp.h> #include <net/sock.h> #include <net/pkt_sched.h> +#include <net/netlink.h> DECLARE_MUTEX(rtnl_sem); @@ -519,8 +520,6 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) } if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { - u32 rlen; - if (link->dumpit == NULL) link = &(rtnetlink_links[PF_UNSPEC][type]); @@ -531,10 +530,8 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) link->dumpit, NULL)) != 0) { return -1; } - rlen = NLMSG_ALIGN(nlh->nlmsg_len); - if (rlen > skb->len) - rlen = skb->len; - skb_pull(skb, rlen); + + netlink_queue_skip(nlh, skb); return -1; } @@ -573,75 +570,13 @@ err_inval: return -1; } -/* - * Process one packet of messages. - * Malformed skbs with wrong lengths of messages are discarded silently. - */ - -static inline int rtnetlink_rcv_skb(struct sk_buff *skb) -{ - int err; - struct nlmsghdr * nlh; - - while (skb->len >= NLMSG_SPACE(0)) { - u32 rlen; - - nlh = (struct nlmsghdr *)skb->data; - if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) - return 0; - rlen = NLMSG_ALIGN(nlh->nlmsg_len); - if (rlen > skb->len) - rlen = skb->len; - if (rtnetlink_rcv_msg(skb, nlh, &err)) { - /* Not error, but we must interrupt processing here: - * Note, that in this case we do not pull message - * from skb, it will be processed later. - */ - if (err == 0) - return -1; - netlink_ack(skb, nlh, err); - } else if (nlh->nlmsg_flags&NLM_F_ACK) - netlink_ack(skb, nlh, 0); - skb_pull(skb, rlen); - } - - return 0; -} - -/* - * rtnetlink input queue processing routine: - * - process as much as there was in the queue upon entry. - * - feed skbs to rtnetlink_rcv_skb, until it refuse a message, - * that will occur, when a dump started. - */ - static void rtnetlink_rcv(struct sock *sk, int len) { - unsigned int qlen = skb_queue_len(&sk->sk_receive_queue); + unsigned int qlen = 0; do { - struct sk_buff *skb; - rtnl_lock(); - - if (qlen > skb_queue_len(&sk->sk_receive_queue)) - qlen = skb_queue_len(&sk->sk_receive_queue); - - for (; qlen; qlen--) { - skb = skb_dequeue(&sk->sk_receive_queue); - if (rtnetlink_rcv_skb(skb)) { - if (skb->len) - skb_queue_head(&sk->sk_receive_queue, - skb); - else { - kfree_skb(skb); - qlen--; - } - break; - } - kfree_skb(skb); - } - + netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg); up(&rtnl_sem); netdev_run_todo(); |