From: Roy Marples Date: Fri, 2 Sep 2016 08:09:47 +0000 (+0000) Subject: Rework the recvmsg_realloc function to handle flags. X-Git-Tag: v6.11.4~64 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c62f687eb8edf0eafca1aeed8c9241ee4a3f4797;p=thirdparty%2Fdhcpcd.git Rework the recvmsg_realloc function to handle flags. Commit also includes mistakenly added ifam_pid patch for BSD. It does no harm being here, even though no BSD supports this yet. --- diff --git a/common.c b/common.c index 3c0de44e..9b62a6a5 100644 --- a/common.c +++ b/common.c @@ -397,21 +397,19 @@ iovec_realloc(struct iovec *iov, size_t size) } ssize_t -recvmsg_alloc(int fd, struct msghdr *msg) +recvmsg_realloc(int fd, struct msghdr *msg, int flags) { ssize_t bytes; - if (msg->msg_iovlen == 0) - msg->msg_iovlen = 1; - for (;;) { - msg->msg_flags &= ~MSG_TRUNC; - if ((bytes = recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC)) == -1) + msg->msg_flags = 0; + bytes = recvmsg(fd, msg, flags | MSG_PEEK | MSG_TRUNC); + if (bytes == -1) return -1; if (!(msg->msg_flags & MSG_TRUNC)) break; - /* Some buggy kernels return the truncated size. */ + /* Some kernels return the truncated size. */ if (msg->msg_iov->iov_len == (size_t)bytes) { size_t nl; @@ -425,6 +423,6 @@ recvmsg_alloc(int fd, struct msghdr *msg) } } - bytes = recvmsg(fd, msg, 0); + bytes = recvmsg(fd, msg, flags); return msg->msg_flags & MSG_TRUNC ? -1 : bytes; } diff --git a/common.h b/common.h index 38924bc3..da9aea96 100644 --- a/common.h +++ b/common.h @@ -197,5 +197,5 @@ 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); +ssize_t recvmsg_realloc(int, struct msghdr *, int); #endif diff --git a/configure b/configure index 0f22c869..a6ed2f29 100755 --- a/configure +++ b/configure @@ -506,7 +506,22 @@ EOF echo "no" fi rm -f _IN6_ADDR_GEN_MODE_NONE.c _IN6_ADDR_GEN_MODE_NONE - +else + printf "Testing for ifam_pid ... " + cat <_ifam_pid.c +#include +int main(void) { + struct ifa_msghdr ifam = { }; + return (int)ifam.ifam_pid; +} +EOF + if $XCC _ifam_pid.c -o _ifam_pid 2>&3; then + echo "yes" + echo "#define HAVE_IFAM_PID" >>$CONFIG_H + else + echo "no" + fi + rm -f _ifam_pid.c _ifam_pid fi abort=false diff --git a/if-bsd.c b/if-bsd.c index fbcb5172..7bc54e09 100644 --- a/if-bsd.c +++ b/if-bsd.c @@ -1312,32 +1312,43 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm) (unsigned int)ifm->ifm_flags, ifp->name); } -static void -if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) +static int +if_ownmsgpid(struct dhcpcd_ctx *ctx, pid_t pid, int seq) { - const struct sockaddr *sa; /* Ignore messages generated by us */ - if (rtm->rtm_pid == getpid()) { + if (getpid() == pid) { ctx->options &= ~DHCPCD_RTM_PPID; - return; + return 1; } /* Ignore messages sent by the parent after forking */ if ((ctx->options & (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED)) == (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED) && - rtm->rtm_pid == ctx->ppid) + ctx->ppid == pid) { /* If this is the last successful message sent, * clear the check flag as it's possible another * process could re-use the same pid and also - * manipulate therouting table. */ - if (rtm->rtm_seq == ctx->pseq) + * manipulate the routing table. */ + if (ctx->pseq == seq) ctx->options &= ~DHCPCD_RTM_PPID; - return; + return 1; } + /* Not a message we made. */ + return 0; +} + +static void +if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) +{ + const struct sockaddr *sa; + + if (if_ownmsgpid(ctx, rtm->rtm_pid, rtm->rtm_seq)) + return; + sa = (const void *)(rtm + 1); switch (sa->sa_family) { #ifdef INET @@ -1395,9 +1406,11 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) struct interface *ifp; const struct sockaddr *rti_info[RTAX_MAX]; - /* XXX We have no way of knowing who generated these - * messages wich truely sucks because we want to - * avoid listening to our own delete messages. */ +#ifdef HAVE_IFAM_PID + if (if_ownmsgpid(ctx, ifam->ifam_pid, 0)) + return; +#endif + if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL) return; get_addrs(ifam->ifam_addrs, ifam + 1, rti_info); @@ -1521,8 +1534,9 @@ if_handlelink(struct dhcpcd_ctx *ctx) memset(&msg, 0, sizeof(msg)); msg.msg_iov = &ctx->iov; + msg.msg_iovlen = 1; - if ((bytes = recvmsg_alloc(ctx->link_fd, &msg)) == -1) + if ((bytes = recvmsg_realloc(ctx->link_fd, &msg, 0)) == -1) return -1; if_dispatch(ctx, ctx->iov.iov_base); return 0; diff --git a/if-linux.c b/if-linux.c index 9d379193..c247b101 100644 --- a/if-linux.c +++ b/if-linux.c @@ -344,12 +344,12 @@ get_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp, int fd, int flags, int r; 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) + msg.msg_iovlen = 1; + if ((bytes = recvmsg_realloc(fd, &msg, flags)) == -1) return -1; /* Check sender */ diff --git a/if-sun.c b/if-sun.c index 064ab936..8ce1887b 100644 --- a/if-sun.c +++ b/if-sun.c @@ -774,8 +774,9 @@ if_handlelink(struct dhcpcd_ctx *ctx) memset(&msg, 0, sizeof(msg)); msg.msg_iov = &ctx->iov; + msg.msg_iovlen = 1; - if ((bytes = recvmsg_alloc(ctx->link_fd, &msg)) == -1) + if ((bytes = recvmsg_realloc(ctx->link_fd, &msg, 0)) == -1) return -1; if_dispatch(ctx, ctx->iov.iov_base); return 0;