From: Roy Marples Date: Thu, 1 Sep 2016 17:01:26 +0000 (+0000) Subject: Linux now uses recvmsg_alloc as well, reducing duplicated code. X-Git-Tag: v6.11.4~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ea25975d6baa9e06c37261d62d0a4e4ab4ac9501;p=thirdparty%2Fdhcpcd.git Linux now uses recvmsg_alloc as well, reducing duplicated code. --- diff --git a/common.c b/common.c index 59d11371..a0b1be14 100644 --- a/common.c +++ b/common.c @@ -402,7 +402,7 @@ recvmsg_alloc(int fd, struct msghdr *msg) msg->msg_iovlen = 1; for (;;) { - msg->msg_flags = 0; + msg->msg_flags &= ~MSG_TRUNC; if ((bytes = recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC)) == -1) return -1; if (!(msg->msg_flags & MSG_TRUNC)) diff --git a/if-linux.c b/if-linux.c index 26018ba5..9d379193 100644 --- a/if-linux.c +++ b/if-linux.c @@ -337,72 +337,44 @@ static int get_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp, int fd, int flags, int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *)) { - char *buf = NULL, *nbuf; + struct msghdr msg; + struct sockaddr_nl nladdr; ssize_t bytes; - size_t buflen; struct nlmsghdr *nlm; - struct sockaddr_nl nladdr; - socklen_t nladdr_len; int r; - buflen = 0; - r = -1; - for (;;) { - bytes = recv(fd, NULL, 0, - flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC); - if (bytes == -1) - goto eexit; - if ((size_t)bytes == buflen) { - /* Support kernels older than 2.6.22 */ - if (bytes == 0) - bytes = 512; - else - bytes *= 2; - } - if (buflen < (size_t)bytes) { - /* Alloc 1 more so we work with older kernels */ - buflen = (size_t)bytes + 1; - nbuf = realloc(buf, buflen); - if (nbuf == NULL) - goto eexit; - buf = nbuf; - } - nladdr.nl_pid = 0; /* XXX clang static analyzer bug? */ - nladdr_len = sizeof(nladdr); - bytes = recvfrom(fd, buf, buflen, flags, - (struct sockaddr *)&nladdr, &nladdr_len); - if (bytes == -1 || bytes == 0) - goto eexit; + memset(&msg, 0, sizeof(msg)); + msg.msg_flags = flags; + msg.msg_name = &nladdr; + msg.msg_namelen = sizeof(nladdr); + memset(&nladdr, 0, sizeof(nladdr)); + msg.msg_iov = &ctx->iov; + if ((bytes = recvmsg_alloc(fd, &msg)) == -1) + return -1; - /* Check sender */ - if (nladdr_len != sizeof(nladdr)) { - errno = EINVAL; - goto eexit; - } - /* Ignore message if it is not from kernel */ - if (nladdr.nl_pid != 0) { - r = 0; - continue; - } + /* Check sender */ + if (msg.msg_namelen != sizeof(nladdr)) { + errno = EINVAL; + return -1; + } + /* Ignore message if it is not from kernel */ + if (nladdr.nl_pid != 0) + return 0; - for (nlm = (void *)buf; - nlm && NLMSG_OK(nlm, (size_t)bytes); - nlm = NLMSG_NEXT(nlm, bytes)) - { - r = err_netlink(nlm); - if (r == -1) - goto eexit; - - if (r == 0 && callback) { - r = callback(ctx, ifp, nlm); - if (r != 0) - goto eexit; - } + r = 0; + for (nlm = ctx->iov.iov_base; + nlm && NLMSG_OK(nlm, (size_t)bytes); + nlm = NLMSG_NEXT(nlm, bytes)) + { + if ((r = err_netlink(nlm)) == -1) + return -1; + if (r == 0 && callback) { + r = callback(ctx, ifp, nlm); + if (r != 0) + return r; } } -eexit: - free(buf); return r; }