diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-09-25 17:06:12 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-09-25 17:06:12 +0200 |
commit | 30216bf35c8cfe078ede4c4ad7f43544b469b7d3 (patch) | |
tree | 41e81ba74183f307e90f05ef7cbdf69db49df392 /src | |
parent | 3863f882469117afd6a2ad7ce25711b619f43b27 (diff) | |
download | conntrack-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.c | 44 |
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); |