summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-09-25 17:06:12 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2008-09-25 17:06:12 +0200
commit30216bf35c8cfe078ede4c4ad7f43544b469b7d3 (patch)
tree41e81ba74183f307e90f05ef7cbdf69db49df392 /src
parent3863f882469117afd6a2ad7ce25711b619f43b27 (diff)
downloadconntrack-tools-30216bf35c8cfe078ede4c4ad7f43544b469b7d3.tar.gz
conntrack-tools-30216bf35c8cfe078ede4c4ad7f43544b469b7d3.zip
ftfw: fix race condition in the helloing routine
This patch fixes a race condition that can prevent one node from sending the initial hello message required to reset the sequence tracking. node A node B | | start | | hello msg |----------------------->| stop | | start | | |<-----------------------| hello-back msg In the picture above, the node A never sends the hello messages. Thus, the node B drops the next messages as they are in the before boundary. This patch adds a new state to the the helloing state-machine to fix this problem. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/sync-ftfw.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c
index 8dd5554..11c0638 100644
--- a/src/sync-ftfw.c
+++ b/src/sync-ftfw.c
@@ -46,7 +46,14 @@ static uint32_t window;
static uint32_t ack_from;
static int ack_from_set = 0;
static struct alarm_block alive_alarm;
-static int hello_state = SAY_HELLO;
+
+enum {
+ HELLO_INIT,
+ HELLO_SAY,
+ HELLO_DONE,
+};
+static int hello_state = HELLO_INIT;
+static int say_hello_back;
/* XXX: alive message expiration configurable */
#define ALIVE_INT 1
@@ -96,13 +103,17 @@ static void tx_queue_add_ctlmsg(uint32_t flags, uint32_t from, uint32_t to)
};
switch(hello_state) {
- case SAY_HELLO:
+ case HELLO_INIT:
+ hello_state = HELLO_SAY;
+ /* fall through */
+ case HELLO_SAY:
ack.flags |= NET_F_HELLO;
break;
- case HELLO_BACK:
+ }
+
+ if (say_hello_back) {
ack.flags |= NET_F_HELLO_BACK;
- hello_state = HELLO_DONE;
- break;
+ say_hello_back = 0;
}
queue_add(tx_queue, &ack, NETHDR_ACK_SIZ);
@@ -335,12 +346,13 @@ static int digest_hello(const struct nethdr *net)
int ret = 0;
if (IS_HELLO(net)) {
- dlog(LOG_NOTICE, "The other node says HELLO");
- hello_state = HELLO_BACK;
+ say_hello_back = 1;
ret = 1;
- } else if (IS_HELLO_BACK(net)) {
- dlog(LOG_NOTICE, "The other node says HELLO BACK");
- hello_state = HELLO_DONE;
+ }
+ if (IS_HELLO_BACK(net)) {
+ /* this is a hello back for a requested hello */
+ if (hello_state == HELLO_SAY)
+ hello_state = HELLO_DONE;
}
return ret;
@@ -428,15 +440,19 @@ static void ftfw_send(struct nethdr *net, struct us_conntrack *u)
}
switch(hello_state) {
- case SAY_HELLO:
+ case HELLO_INIT:
+ hello_state = HELLO_SAY;
+ /* fall through */
+ case HELLO_SAY:
net->flags = ntohs(net->flags) | NET_F_HELLO;
net->flags = htons(net->flags);
break;
- case HELLO_BACK:
+ }
+
+ if (say_hello_back) {
net->flags = ntohs(net->flags) | NET_F_HELLO_BACK;
net->flags = htons(net->flags);
- hello_state = HELLO_DONE;
- break;
+ say_hello_back = 0;
}
cn->seq = ntohl(net->seq);