mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
[RTNETLINK]: Use generic netlink receive queue processor
Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
88fc2c8431
commit
9ac4a16983
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user