]> git.meshlink.io Git - utcp/commitdiff
Do proper modulo 2^32 comparisons of sequence numbers.
authorGuus Sliepen <guus@sliepen.org>
Fri, 25 Jul 2014 11:28:43 +0000 (13:28 +0200)
committerGuus Sliepen <guus@sliepen.org>
Fri, 25 Jul 2014 11:28:43 +0000 (13:28 +0200)
UTCP
utcp.c

diff --git a/UTCP b/UTCP
index f7b66ba24a2993adf04eb5f2bc989b0be2ae532f..d5edf564fb93533662533529eba3da378f1fcd21 100644 (file)
--- a/UTCP
+++ b/UTCP
@@ -21,7 +21,6 @@ TODO v1.0:
 * Implement send buffer
 * Window scaling
 * Handle retransmission
-* Do proper modulo 2^32 comparisons of sequence numbers
 
 TODO v2.0:
 
diff --git a/utcp.c b/utcp.c
index e6f70f7b5c18f4ad83dbe427418186837ab24e8d..7db7b5e043ed450251d532c8ccbcf4f4d9dbe06e 100644 (file)
--- a/utcp.c
+++ b/utcp.c
@@ -370,6 +370,10 @@ static void swap_ports(struct hdr *hdr) {
        hdr->dst = tmp;
 }
 
+static int16_t seqdiff(uint16_t a, uint16_t b) {
+       return a -b;
+}
+
 int utcp_recv(struct utcp *utcp, void *data, size_t len) {
        if(!utcp) {
                errno = EFAULT;
@@ -444,7 +448,7 @@ int utcp_recv(struct utcp *utcp, void *data, size_t len) {
        
        if(c->state == SYN_SENT) {
                if(hdr.ctl & ACK) {
-                       if(hdr.ack <= c->snd.iss || hdr.ack > c->snd.nxt) {
+                       if(seqdiff(hdr.ack, c->snd.iss) <= 0 || seqdiff(hdr.ack, c->snd.nxt) > 0) {
                                fprintf(stderr, "Invalid ACK, %u %u %u\n", hdr.ack, c->snd.iss, c->snd.nxt);
                                goto reset;
                        }
@@ -465,7 +469,7 @@ int utcp_recv(struct utcp *utcp, void *data, size_t len) {
 
                        if(hdr.ctl & ACK)
                                c->snd.una = hdr.ack;
-                       if(c->snd.una > c->snd.iss) {
+                       if(seqdiff(c->snd.una, c->snd.iss) > 0) {
                                set_state(c, ESTABLISHED);
                                // TODO: signal app?
                                swap_ports(&hdr);
@@ -563,7 +567,7 @@ int utcp_recv(struct utcp *utcp, void *data, size_t len) {
 
        switch(c->state) {
        case SYN_RECEIVED:
-               if(hdr.ack >= c->snd.una && hdr.ack <= c->snd.nxt)
+               if(seqdiff(hdr.ack, c->snd.una) >= 0 && seqdiff(hdr.ack, c->snd.nxt) <= 0)
                        c->utcp->accept(c, hdr.dst);
                
                if(c->state != ESTABLISHED)
@@ -571,13 +575,13 @@ int utcp_recv(struct utcp *utcp, void *data, size_t len) {
                break;
        case ESTABLISHED:
        case CLOSE_WAIT:
-               if(hdr.ack < c->snd.una)
+               if(seqdiff(hdr.ack, c->snd.una) < 0)
                        return 0;
-               if(hdr.ack > c->snd.nxt)
+               if(seqdiff(hdr.ack, c->snd.nxt) > 0)
                        goto ack_and_drop;
-               if(hdr.ack > c->snd.una && hdr.ack <= c->snd.nxt) {
+               if(seqdiff(hdr.ack, c->snd.una) > 0 && seqdiff(hdr.ack, c->snd.nxt) <= 0) {
                        c->snd.una = hdr.ack;
-                       if(c->snd.wl1 < hdr.seq || (c->snd.wl1 == hdr.seq && c->snd.wl2 <= hdr.ack)) {
+                       if(seqdiff(c->snd.wl1, hdr.seq) < 0 || (c->snd.wl1 == hdr.seq && seqdiff(c->snd.wl2, hdr.ack) <= 0)) {
                                c->snd.wnd = hdr.wnd;
                                c->snd.wl1 = hdr.seq;
                                c->snd.wl2 = hdr.ack;