aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Leblond <eric@inl.fr>2007-09-18 16:07:15 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-09-20 15:13:52 -0400
commit29c5d4afba51c71cfeadd3f74f3c42e064483fb0 (patch)
tree932854319ca02c2c0190ea35b3e38bb929014d45
parent6d0b842d3bf0cc027dcff57a89fb8a6b1fd610e1 (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>
-rw-r--r--net/netfilter/nfnetlink_log.c13
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,
345static int 344static 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
363nlmsg_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
544nlmsg_failure: 544nlmsg_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");