diff options
| author | Eric Leblond <eric@inl.fr> | 2007-09-18 16:07:15 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2007-09-20 15:13:52 -0400 |
| commit | 29c5d4afba51c71cfeadd3f74f3c42e064483fb0 (patch) | |
| tree | 932854319ca02c2c0190ea35b3e38bb929014d45 /net | |
| parent | 6d0b842d3bf0cc027dcff57a89fb8a6b1fd610e1 (diff) | |
[NETFILTER]: nfnetlink_log: fix sending of multipart messages
The following patch fixes the handling of netlink packets containing
multiple messages.
As exposed during netfilter workshop, nfnetlink_log was overwritten the
message type of the last message (setting it to MSG_DONE) in a multipart
packet. The consequence was libnfnetlink to ignore the last message in the
packet.
The following patch adds a supplementary message (with type MSG_DONE) af
the end of the netlink skb.
Signed-off-by: Eric Leblond <eric@inl.fr>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
| -rw-r--r-- | net/netfilter/nfnetlink_log.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index e185a5b55913..2351533a8507 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
| @@ -58,7 +58,6 @@ struct nfulnl_instance { | |||
| 58 | 58 | ||
| 59 | unsigned int qlen; /* number of nlmsgs in skb */ | 59 | unsigned int qlen; /* number of nlmsgs in skb */ |
| 60 | struct sk_buff *skb; /* pre-allocatd skb */ | 60 | struct sk_buff *skb; /* pre-allocatd skb */ |
| 61 | struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ | ||
| 62 | struct timer_list timer; | 61 | struct timer_list timer; |
| 63 | int peer_pid; /* PID of the peer process */ | 62 | int peer_pid; /* PID of the peer process */ |
| 64 | 63 | ||
| @@ -345,10 +344,12 @@ static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, | |||
| 345 | static int | 344 | static int |
| 346 | __nfulnl_send(struct nfulnl_instance *inst) | 345 | __nfulnl_send(struct nfulnl_instance *inst) |
| 347 | { | 346 | { |
| 348 | int status; | 347 | int status = -1; |
| 349 | 348 | ||
| 350 | if (inst->qlen > 1) | 349 | if (inst->qlen > 1) |
| 351 | inst->lastnlh->nlmsg_type = NLMSG_DONE; | 350 | NLMSG_PUT(inst->skb, 0, 0, |
| 351 | NLMSG_DONE, | ||
| 352 | sizeof(struct nfgenmsg)); | ||
| 352 | 353 | ||
| 353 | status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT); | 354 | status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT); |
| 354 | if (status < 0) { | 355 | if (status < 0) { |
| @@ -358,8 +359,8 @@ __nfulnl_send(struct nfulnl_instance *inst) | |||
| 358 | 359 | ||
| 359 | inst->qlen = 0; | 360 | inst->qlen = 0; |
| 360 | inst->skb = NULL; | 361 | inst->skb = NULL; |
| 361 | inst->lastnlh = NULL; | ||
| 362 | 362 | ||
| 363 | nlmsg_failure: | ||
| 363 | return status; | 364 | return status; |
| 364 | } | 365 | } |
| 365 | 366 | ||
| @@ -538,7 +539,6 @@ __build_packet_message(struct nfulnl_instance *inst, | |||
| 538 | } | 539 | } |
| 539 | 540 | ||
| 540 | nlh->nlmsg_len = inst->skb->tail - old_tail; | 541 | nlh->nlmsg_len = inst->skb->tail - old_tail; |
| 541 | inst->lastnlh = nlh; | ||
| 542 | return 0; | 542 | return 0; |
| 543 | 543 | ||
| 544 | nlmsg_failure: | 544 | nlmsg_failure: |
| @@ -644,7 +644,8 @@ nfulnl_log_packet(unsigned int pf, | |||
| 644 | } | 644 | } |
| 645 | 645 | ||
| 646 | if (inst->qlen >= qthreshold || | 646 | if (inst->qlen >= qthreshold || |
| 647 | (inst->skb && size > skb_tailroom(inst->skb))) { | 647 | (inst->skb && size > |
| 648 | skb_tailroom(inst->skb) - sizeof(struct nfgenmsg))) { | ||
| 648 | /* either the queue len is too high or we don't have | 649 | /* either the queue len is too high or we don't have |
| 649 | * enough room in the skb left. flush to userspace. */ | 650 | * enough room in the skb left. flush to userspace. */ |
| 650 | UDEBUG("flushing old skb\n"); | 651 | UDEBUG("flushing old skb\n"); |
