diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-09-25 17:10:42 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-09-25 17:10:42 +0200 |
commit | 99a80b3fe6af95ca711c2d37737408c3703a6184 (patch) | |
tree | 3f6291045cfc1e76937438e0ef16896ba6c4cf79 /src/sync-ftfw.c | |
parent | 30216bf35c8cfe078ede4c4ad7f43544b469b7d3 (diff) | |
download | conntrack-tools-99a80b3fe6af95ca711c2d37737408c3703a6184.tar.gz conntrack-tools-99a80b3fe6af95ca711c2d37737408c3703a6184.zip |
ftfw: reset window and flush the resend queue during helloing
This fixes two bugs when a hello message is received:
* We can create malformed nack messages during the helloing.
We have to reset the acknowlegdment window, otherwise we may
create malformed nack messages.
* We have to empty the resend list/queue when a hello message is
received, otherwise the entries get stuck to the resend queue
once the sequence number wraps around.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/sync-ftfw.c')
-rw-r--r-- | src/sync-ftfw.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index 11c0638..b7eabdf 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -260,6 +260,12 @@ static int rs_queue_empty(void *data1, const void *data2) struct nethdr *net = data1; const struct nethdr_ack *h = data2; + if (h == NULL) { + dp("inconditional remove from queue (seq=%u)\n", net->seq); + queue_del(rs_queue, data1); + return 0; + } + if (between(net->seq, h->from, h->to)) { dp("remove from queue (seq=%u)\n", net->seq); queue_del(rs_queue, data1); @@ -362,8 +368,22 @@ static int ftfw_recv(const struct nethdr *net) { int ret = MSG_DATA; - if (digest_hello(net)) + if (digest_hello(net)) { + /* we have received a hello while we had data to acknowledge. + * reset the window, the other doesn't know anthing about it. */ + if (ack_from_set && before(net->seq, ack_from)) { + window = CONFIG(window_size) - 1; + ack_from = net->seq; + } + + /* XXX: flush the resend queues since the other does not + * know anything about that data, we are unreliable until + * the helloing finishes */ + queue_iterate(rs_queue, NULL, rs_queue_empty); + rs_list_empty(STATE_SYNC(internal), 0, ~0U); + goto bypass; + } switch (mcast_track_seq(net->seq, &exp_seq)) { case SEQ_AFTER: |