NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: lib/54527: syslogd hangs when forwarding logs to a IPv6 host that is down

The following reply was made to PR lib/54527; it has been noted by GNATS.

From: Anthony Mallet <>
Subject: Re: lib/54527: syslogd hangs when forwarding logs to a IPv6 host that is down
Date: Sat, 14 Sep 2019 15:26:49 +0200

 Content-Type: text/plain; charset=us-ascii
 Content-Description: message body text
 Content-Transfer-Encoding: 7bit
 I could finally debug this further. The problem is the following:
 When syslog sends a udp datagram to the remote, unreachable IPv6 host,
 the socket is marked readable and a recv on it will return
 EHOSTDOWN. So far so good.
 However, there is a call to libwrap "fromhost" (syslogd.c:795) that
 eats the error and prevents the further "recvfrom" (syslog.c:802) from
 getting it (that's why recvfrom then block forever).
 I attach a sample program that shows the issue more clearly.
 For UDP sockets, libwrap does "recvfrom( ... MSG_PEEK ...)" to
 determine the remote address. This is the call that gets the
 EHOSTDOWN. However, the hostfrom() function does not return errors, so
 syslogd cannot use this information to avoid the blocking recvfrom().
 Not sure what to do ...
 Content-Type: text/plain;
 Content-Disposition: inline;
 Content-Transfer-Encoding: 7bit
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <err.h>
 #include <event.h>
 #include <netdb.h>
 #include <poll.h>
   struct addrinfo hints = { 0 }, *res, *r;
   struct sockaddr_storage frominet;
   struct pollfd fds;
   socklen_t len;
   char buf[16];
   ssize_t s;
   int error;
   int fd;
   /* setup sending socket */
   hints.ai_flags = AI_PASSIVE;
   hints.ai_family = AF_INET6;
   hints.ai_socktype = SOCK_DGRAM;
   error = getaddrinfo(NULL, "12345", &hints, &res);
   if (error) err(2, "getaddrinfo bind");
   for (r = res; r; r = r->ai_next) {
     fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
     if (fd < 0) err(2, "socket");
     if (bind(fd, r->ai_addr, r->ai_addrlen) < 0)
       err(2, "bind");
   /* non-existent host */
   hints.ai_flags = AI_NUMERICHOST;
   hints.ai_family = AF_INET6;
   hints.ai_socktype = SOCK_DGRAM;
   error = getaddrinfo("fc00::", "12345", &hints, &res);
   if (error) err(2, "getaddrinfo sendto");
   /* send empty datagram */
   for (r = res; r; r = r->ai_next) {
     s = sendto(fd, "", 1, 0, r->ai_addr, r->ai_addrlen);
     if (s == -1)
       err(2, "sendto");
     warnx("sent %zd bytes", s);
   /* wait for events: sock will be readable and return EHOSTDOWN */
   while (1) {
     fds.fd = fd; = POLLIN;
     if (poll(&fds, 1, -1) == 1) {
       warnx("events %d %d",, fds.revents);
       /* do the equivalent of a libwarp "hostfrom" */
       len = sizeof(frominet);
       if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK,
                    (struct sockaddr *)&frominet, &len) < 0) {
         warn("can't get client address");
       /* this blocks because the EHOSTDOWN was eaten above */
       s = recv(fd, buf, sizeof(buf), 0);
       warn("recv %zd", s);
     warnx("not reached :/");
   return 0;

Home | Main Index | Thread Index | Old Index