]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lib: fix sync_recv to handle segmentation
authorVincent Bernat <bernat@luffy.cx>
Sat, 30 Mar 2013 14:42:51 +0000 (15:42 +0100)
committerVincent Bernat <bernat@luffy.cx>
Sat, 30 Mar 2013 14:42:51 +0000 (15:42 +0100)
While it should not happen with Unix sockets, a read() can return only
partial data. Therefore, we continue to poll until we get the
appropriate length.

This fix was proposed by Chris Yang. Closes #31.

src/lib/connection.c

index 3b3227ccb691aad1728fca65fc3bc69eae0c793c..2fe7c44d6c0dbf4582a8b16a60dfda21c7a6a42a 100644 (file)
@@ -68,6 +68,7 @@ sync_recv(lldpctl_conn_t *lldpctl,
 {
        struct lldpctl_conn_sync_t *conn = user_data;
        size_t nb;
+       size_t remain, offset = 0;
 
        if (conn->fd == -1 &&
            ((conn->fd = sync_connect(lldpctl)) == -1)) {
@@ -75,14 +76,17 @@ sync_recv(lldpctl_conn_t *lldpctl,
                return LLDPCTL_ERR_CANNOT_CONNECT;
        }
 
-       while ((nb = read(conn->fd, (void*)data, length)) == -1) {
-               if (errno == EAGAIN || errno == EINTR) continue;
-               return LLDPCTL_ERR_CALLBACK_FAILURE;
-       }
-       return nb;
+       remain = length;
+       do {
+               if ((nb = read(conn->fd, (void*)data + offset, remain)) == -1 &&
+                   (errno == EAGAIN || errno == EINTR))
+                       continue;
+               remain -= nb;
+               offset += nb;
+       } while (remain > 0 && nb > 0);
+       return offset;
 }
 
-
 lldpctl_conn_t*
 lldpctl_new(lldpctl_send_callback send, lldpctl_recv_callback recv, void *user_data)
 {