summaryrefslogtreecommitdiffstats
path: root/src/sync-ftfw.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-09-25 17:10:42 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2008-09-25 17:10:42 +0200
commit99a80b3fe6af95ca711c2d37737408c3703a6184 (patch)
tree3f6291045cfc1e76937438e0ef16896ba6c4cf79 /src/sync-ftfw.c
parent30216bf35c8cfe078ede4c4ad7f43544b469b7d3 (diff)
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.c22
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: