summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2008-07-17 18:56:09 +0000
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2008-07-17 18:56:09 +0000
commita1849f41cd607c17c582952e02d5d9caa2db180f (patch)
treee2fe3f4cf11748704cd02de45eeea535d9f3ccb5
parente691cd568ab5a0e34924a3b80693af6125209d76 (diff)
downloadopenvpn-a1849f41cd607c17c582952e02d5d9caa2db180f.tar.gz
openvpn-a1849f41cd607c17c582952e02d5d9caa2db180f.tar.xz
openvpn-a1849f41cd607c17c582952e02d5d9caa2db180f.zip
Support wraparound of reliable.[ch] packet IDs. In
practice, wraparound of the packet ID sequence is extremely unlikely since the sequence is restarted for each mid-session TLS renegotiation. But we will support it for completeness. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3065 e7ae566f-a301-0410-adde-c780ea21d3b5
-rw-r--r--reliable.c56
1 files changed, 44 insertions, 12 deletions
diff --git a/reliable.c b/reliable.c
index 743a008..4958f7e 100644
--- a/reliable.c
+++ b/reliable.c
@@ -38,6 +38,39 @@
#include "memdbg.h"
+/*
+ * verify that test - base < extent while allowing for base or test wraparound
+ */
+static inline bool
+reliable_pid_in_range (const packet_id_type test,
+ const packet_id_type base,
+ const unsigned int extent)
+{
+ if (test >= base)
+ {
+ if (test - base < extent)
+ return true;
+ }
+ else
+ {
+ const packet_id_type be = base + extent;
+ if (test < be && be < base)
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * verify that p1 < p2 while allowing for p1 or p2 wraparound
+ */
+static inline bool
+reliable_pid_min (const packet_id_type p1,
+ const packet_id_type p2)
+{
+ return !reliable_pid_in_range (p1, p2, 0x80000000);
+}
+
/* check if a particular packet_id is present in ack */
static inline bool
reliable_ack_packet_id_present (struct reliable_ack *ack, packet_id_type pid)
@@ -330,7 +363,7 @@ reliable_not_replay (const struct reliable *rel, packet_id_type id)
{
struct gc_arena gc = gc_new ();
int i;
- if (id < rel->packet_id)
+ if (reliable_pid_min (id, rel->packet_id))
goto bad;
for (i = 0; i < rel->size; ++i)
{
@@ -352,18 +385,17 @@ bool
reliable_wont_break_sequentiality (const struct reliable *rel, packet_id_type id)
{
struct gc_arena gc = gc_new ();
- int ret;
- if ((int)id < (int)rel->packet_id + rel->size)
- {
- ret = true;
- }
- else
+ const int ret = reliable_pid_in_range (id, rel->packet_id, rel->size);
+
+ if (!ret)
{
dmsg (D_REL_LOW, "ACK " packet_id_format " breaks sequentiality: %s",
(packet_id_print_type)id, reliable_print_ids (rel, &gc));
- ret = false;
}
+
+ dmsg (D_REL_DEBUG, "ACK RWBS rel->size=%d rel->packet_id=%08x id=%08x ret=%d\n", rel->size, rel->packet_id, id, ret);
+
gc_free (&gc);
return ret;
}
@@ -401,7 +433,7 @@ reliable_get_buf_output_sequenced (struct reliable *rel)
const struct reliable_entry *e = &rel->array[i];
if (e->active)
{
- if (!min_id_defined || e->packet_id < min_id)
+ if (!min_id_defined || reliable_pid_min (e->packet_id, min_id))
{
min_id_defined = true;
min_id = e->packet_id;
@@ -409,7 +441,7 @@ reliable_get_buf_output_sequenced (struct reliable *rel)
}
}
- if (!min_id_defined || (int)(rel->packet_id - min_id) < rel->size)
+ if (!min_id_defined || reliable_pid_in_range (rel->packet_id, min_id, rel->size))
{
ret = reliable_get_buf (rel);
}
@@ -496,7 +528,7 @@ reliable_send (struct reliable *rel, int *opcode)
struct reliable_entry *e = &rel->array[i];
if (e->active && local_now >= e->next_try)
{
- if (!best || e->packet_id < best->packet_id)
+ if (!best || reliable_pid_min (e->packet_id, best->packet_id))
best = e;
}
}
@@ -592,7 +624,7 @@ reliable_mark_active_incoming (struct reliable *rel, struct buffer *buf,
e->packet_id = pid;
/* check for replay */
- ASSERT (pid >= rel->packet_id);
+ ASSERT (!reliable_pid_min (pid, rel->packet_id));
e->opcode = opcode;
e->next_try = 0;