From a1849f41cd607c17c582952e02d5d9caa2db180f Mon Sep 17 00:00:00 2001 From: james Date: Thu, 17 Jul 2008 18:56:09 +0000 Subject: 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 --- reliable.c | 56 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file 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; -- cgit