]> 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 f5484ab82b92e53e5365f7de75a822881218a7f4..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:
@@ -954,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;
@@ -967,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:
@@ -1153,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;
 }