]> git.meshlink.io Git - utcp/blobdiff - utcp.c
Guard against NULL pointer dereferencing.
[utcp] / utcp.c
diff --git a/utcp.c b/utcp.c
index f46cdf7f649f0ee4ef77b0c8ebe0a673d5f24af0..21fbea6c4eea4df28380098bdff43edb33441775 100644 (file)
--- a/utcp.c
+++ b/utcp.c
@@ -366,7 +366,7 @@ static void ack(struct utcp_connection *c, bool sendatleastone) {
                c->snd.nxt += seglen;
                left -= seglen;
 
-               if(c->state != ESTABLISHED && !left && seglen) {
+               if(c->state != ESTABLISHED && seglen && c->snd.nxt == c->snd.last) {
                        switch(c->state) {
                        case FIN_WAIT_1:
                        case CLOSING:
@@ -486,7 +486,6 @@ static void retransmit(struct utcp_connection *c) {
                        pkt->hdr.ack = c->rcv.nxt;
                        pkt->hdr.ctl = ACK;
                        uint32_t len = seqdiff(c->snd.nxt, c->snd.una);
-                       fprintf(stderr, "retransmit %u %u %u\n", pkt->hdr.seq, pkt->hdr.ack, len);
                        if(c->state == FIN_WAIT_1)
                                len--;
                        if(len > utcp->mtu)
@@ -782,7 +781,6 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
                        c->dupack++;
                        if(c->dupack == 3) {
                                debug("Triplicate ACK\n");
-                               fprintf(stderr, "Triplicate ACK\n");
                                //TODO: Resend one packet and go to fast recovery mode. See RFC 6582.
                                //We do a very simple variant here; reset the nxt pointer to the last acknowledged packet from the peer.
                                //This will cause us to start retransmitting, but at the same speed as the incoming ACKs arrive,
@@ -956,7 +954,7 @@ reset:
 }
 
 int utcp_shutdown(struct utcp_connection *c, int dir) {
-       debug("%p shutdown %d\n", c ? c->utcp : NULL, dir);
+       debug("%p shutdown %d at %u\n", c ? c->utcp : NULL, dir, c->snd.last);
        if(!c) {
                errno = EFAULT;
                return -1;
@@ -969,6 +967,7 @@ int utcp_shutdown(struct utcp_connection *c, int dir) {
        }
 
        // TODO: handle dir
+       // TODO: check that repeated calls with the same parameters should have no effect
 
        switch(c->state) {
        case CLOSED:
@@ -1155,60 +1154,71 @@ void utcp_exit(struct utcp *utcp) {
 }
 
 uint16_t utcp_get_mtu(struct utcp *utcp) {
-       return utcp->mtu;
+       return utcp ? utcp->mtu : 0;
 }
 
 void utcp_set_mtu(struct utcp *utcp, uint16_t mtu) {
        // TODO: handle overhead of the header
-       utcp->mtu = mtu;
+       if(utcp)
+               utcp->mtu = mtu;
 }
 
 int utcp_get_user_timeout(struct utcp *u) {
-       return u->timeout;
+       return u ? u->timeout : 0;
 }
 
 void utcp_set_user_timeout(struct utcp *u, int timeout) {
-       u->timeout = timeout;
+       if(u)
+               u->timeout = timeout;
 }
 
 size_t utcp_get_sndbuf(struct utcp_connection *c) {
-       return c->sndbuf.maxsize;
+       return c ? c->sndbuf.maxsize : 0;
 }
 
 size_t utcp_get_sndbuf_free(struct utcp_connection *c) {
-       return buffer_free(&c->sndbuf);
+       if(c && (c->state == ESTABLISHED || c->state == CLOSE_WAIT))
+               return buffer_free(&c->sndbuf);
+       else
+               return 0;
 }
 
 void utcp_set_sndbuf(struct utcp_connection *c, size_t size) {
+       if(!c)
+               return;
        c->sndbuf.maxsize = size;
        if(c->sndbuf.maxsize != size)
                c->sndbuf.maxsize = -1;
 }
 
 bool utcp_get_nodelay(struct utcp_connection *c) {
-       return c->nodelay;
+       return c ? c->nodelay : false;
 }
 
 void utcp_set_nodelay(struct utcp_connection *c, bool nodelay) {
-       c->nodelay = nodelay;
+       if(c)
+               c->nodelay = nodelay;
 }
 
 bool utcp_get_keepalive(struct utcp_connection *c) {
-       return c->keepalive;
+       return c ? c->keepalive : false;
 }
 
 void utcp_set_keepalive(struct utcp_connection *c, bool keepalive) {
-       c->keepalive = keepalive;
+       if(c)
+               c->keepalive = keepalive;
 }
 
 size_t utcp_get_outq(struct utcp_connection *c) {
-       return seqdiff(c->snd.nxt, c->snd.una);
+       return c ? seqdiff(c->snd.nxt, c->snd.una) : 0;
 }
 
 void utcp_set_recv_cb(struct utcp_connection *c, utcp_recv_t recv) {
-       c->recv = recv;
+       if(c)
+               c->recv = recv;
 }
 
 void utcp_set_poll_cb(struct utcp_connection *c, utcp_poll_t poll) {
-       c->poll = poll;
+       if(c)
+               c->poll = poll;
 }