instead of a fixed 2048 byte buffer.
# define _PATH_DEVNULL "/dev/null"
#endif
+/* Most route(4) messages are less than 256 bytes. */
+#define IOVEC_BUFSIZ 256
+
#if USE_LOGFILE
void
logger_open(struct dhcpcd_ctx *ctx)
fclose(fp);
return len;
}
+
+static void *
+iovec_realloc(struct iovec *iov, size_t size)
+{
+
+ if (iov->iov_len < size) {
+ void *n;
+
+ if ((n = realloc(iov->iov_base, size)) == NULL)
+ return NULL;
+ iov->iov_base = n;
+ iov->iov_len = size;
+ }
+ return iov->iov_base;
+}
+
+ssize_t
+recvmsg_alloc(int fd, struct msghdr *msg)
+{
+ ssize_t bytes;
+
+ if (msg->msg_iovlen == 0)
+ msg->msg_iovlen = 1;
+
+ for (;;) {
+ msg->msg_flags = 0;
+ if ((bytes = recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC)) == -1)
+ return -1;
+ if (!(msg->msg_flags & MSG_TRUNC))
+ break;
+
+ /* Some buggy kernels return the truncated size. */
+ if (msg->msg_iov->iov_len == (size_t)bytes) {
+ size_t nl;
+
+ nl = (size_t)roundup(bytes + 1, IOVEC_BUFSIZ);
+ if (iovec_realloc(msg->msg_iov, nl) == NULL)
+ return -1;
+ } else {
+ if (iovec_realloc(msg->msg_iov, (size_t)bytes) == NULL)
+ return -1;
+ break;
+ }
+
+ printf ("NEW SIZE %zu", msg->msg_iov->iov_len);
+ }
+
+ bytes = recvmsg(fd, msg, 0);
+ return msg->msg_flags & MSG_TRUNC ? -1 : bytes;
+}
char *hwaddr_ntoa(const uint8_t *, size_t, char *, size_t);
size_t hwaddr_aton(uint8_t *, const char *);
size_t read_hwaddr_aton(uint8_t **, const char *);
+
+ssize_t recvmsg_alloc(int fd, struct msghdr *msg);
#endif
if (control_stop(&ctx) == -1)
logger(&ctx, LOG_ERR, "control_stop: %m:");
eloop_free(ctx.eloop);
+ free(ctx.iov.iov_base);
if (ctx.options & DHCPCD_STARTED && !(ctx.options & DHCPCD_FORKED))
logger(&ctx, LOG_INFO, PACKAGE " exited");
int link_fd;
int seq; /* route message sequence no */
int sseq; /* successful seq no sent */
+ struct iovec iov; /* generic iovec buffer */
#ifdef USE_SIGNALS
sigset_t sigset;
int
if_handlelink(struct dhcpcd_ctx *ctx)
{
- /* route and ifwatchd like a msg buf size of 2048 */
- char buf[2048];
- const char *p, *e;
- size_t msglen;
+ struct msghdr msg;
ssize_t bytes;
- const struct rt_msghdr *rtm;
- if ((bytes = read(ctx->link_fd, buf, sizeof(buf))) == -1)
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = &ctx->iov;
+
+ if ((bytes = recvmsg_alloc(ctx->link_fd, &msg)) == -1)
return -1;
- e = buf + bytes;
- for (p = buf; p < e; p += msglen) {
- rtm = (const void *)p;
- msglen = rtm->rtm_msglen;
- if_dispatch(ctx, rtm);
- }
+ if_dispatch(ctx, ctx->iov.iov_base);
return 0;
}