Hi List I use recvmsg(2) a fair bit in code. However, a lot of the time I can't be certain how large a buffer I would need, so they all ship with a handy function called recvmsg_realloc, which as you can guess, will realloc the last iovec so that the whole message fits. Think of it as a convenience function akin to getline(3).
OK, it's not just my code. For BSD, a fair few progs read from the routing socket with a fixed 2048 char buffer. While this should be plently, due to the use of read(2) it could overflow if the system is sending more than the program can process. Looking over the tree, the following progs should be re-coded to use recvmsg rather than their current (and potentially buggy how I understand it) read(2) implementation, and thus benefit from recvmsg_realloc: wpa_supplicant route ifwatchd rtadvd dhcpcd I'd like to add this to libc instead of bolting it on for this and possibly more applications. Or just recode the above with a fixed width buffer and use recvmsg, keeping this out of libc. Comments welcome, protoype below. Roy ------------------------------------------------------------------------ #define IOVEC_BUFSIZ 256 ssize_t recvmsg_realloc(int fd, struct msghdr *msg, int flags) { struct iovec *iov; ssize_t slen; size_t len; void *n; assert(msg != NULL); assert(msg->msg_iov != NULL && msg->msg_iovlen > 0); assert((flags & (MSG_PEEK | MSG_TRUNC)) == 0); /* Assume we are reallocing the last iovec. */ iov = &msg->msg_iov[msg->msg_iovlen - 1]; for (;;) { /* Passing MSG_TRUNC should return the actual size * needed. */ slen = recvmsg(fd, msg, flags | MSG_PEEK | MSG_TRUNC); if (slen == -1) return -1; if (!(msg->msg_flags & MSG_TRUNC)) break; len = (size_t)slen; /* Some kernels return the size of the receive buffer * on truncation, not the actual size needed. * So grow the buffer and try again. */ if (iov->iov_len == len) len++; else if (iov->iov_len > len) break; len = roundup(len, IOVEC_BUFSIZ); if ((n = realloc(iov->iov_base, len)) == NULL) return -1; iov->iov_base = n; iov->iov_len = len; } slen = recvmsg(fd, msg, flags); if (slen != -1 && msg->msg_flags & MSG_TRUNC) { /* This should not be possible ... */ errno = ENOBUFS; return -1; } return slen; }