Commit also includes mistakenly added ifam_pid patch for BSD.
It does no harm being here, even though no BSD supports this yet.
}
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;
}
}
- bytes = recvmsg(fd, msg, 0);
+ bytes = recvmsg(fd, msg, flags);
return msg->msg_flags & MSG_TRUNC ? -1 : bytes;
}
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
echo "no"
fi
rm -f _IN6_ADDR_GEN_MODE_NONE.c _IN6_ADDR_GEN_MODE_NONE
-
+else
+ printf "Testing for ifam_pid ... "
+ cat <<EOF >_ifam_pid.c
+#include <net/if.h>
+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
(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
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);
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;
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 */
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;