Hi,

I have added functionality that allows syslogd to receive and send
UDP packets via inet6 sockets.

I will split this diff into smaller parts to make review and
discussion easier.

bluhm

Index: usr.sbin/syslogd/privsep.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/privsep.c,v
retrieving revision 1.34
diff -u -p -u -p -r1.34 privsep.c
--- usr.sbin/syslogd/privsep.c  23 Nov 2008 04:29:42 -0000      1.34
+++ usr.sbin/syslogd/privsep.c  18 Aug 2014 23:48:18 -0000
@@ -67,8 +67,8 @@ enum cmd_types {
        PRIV_OPEN_UTMP,         /* open utmp for reading only */
        PRIV_OPEN_CONFIG,       /* open config file for reading only */
        PRIV_CONFIG_MODIFIED,   /* check if config file has been modified */
-       PRIV_GETHOSTSERV,       /* resolve host/service names */
-       PRIV_GETHOSTBYADDR,     /* resolve numeric address into hostname */
+       PRIV_GETADDRINFO,       /* resolve host/service names */
+       PRIV_GETNAMEINFO,       /* resolve numeric address into hostname */
        PRIV_DONE_CONFIG_PARSE  /* signal that the initial config parse is done 
*/
 };
 
@@ -76,7 +76,7 @@ static int priv_fd = -1;
 static volatile pid_t child_pid = -1;
 static char config_file[MAXPATHLEN];
 static struct stat cf_info;
-static int allow_gethostbyaddr = 0;
+static int allow_getnameinfo = 0;
 static volatile sig_atomic_t cur_state = STATE_INIT;
 
 /* Queue for the allowed logfiles */
@@ -100,12 +100,12 @@ static int  may_read(int, void *, size_t
 int
 priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[])
 {
-       int i, fd, socks[2], cmd, addr_len, addr_af, result, restart;
-       size_t path_len, hostname_len, servname_len;
-       char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN];
+       int i, fd, socks[2], cmd, addr_len, result, restart;
+       size_t path_len, protoname_len, hostname_len, servname_len;
+       char path[MAXPATHLEN], protoname[16], hostname[MAXHOSTNAMELEN];
        char servname[MAXHOSTNAMELEN];
+       struct sockaddr_storage addr;
        struct stat cf_stat;
-       struct hostent *hp;
        struct passwd *pw;
        struct addrinfo hints, *res0;
        struct sigaction sa;
@@ -177,6 +177,8 @@ priv_init(char *conf, int numeric, int l
                        close(pfd[PFD_UNIX_0 + i].fd);
        if (pfd[PFD_INET].fd != -1)
                close(pfd[PFD_INET].fd);
+       if (pfd[PFD_INET6].fd != -1)
+               close(pfd[PFD_INET6].fd);
        if (pfd[PFD_CTLSOCK].fd != -1)
                close(pfd[PFD_CTLSOCK].fd);
        if (pfd[PFD_CTLCONN].fd != -1)
@@ -191,11 +193,11 @@ priv_init(char *conf, int numeric, int l
        if (stat(config_file, &cf_info) < 0)
                err(1, "stat config file failed");
 
-       /* Save whether or not the child can have access to gethostbyaddr(3) */
+       /* Save whether or not the child can have access to getnameinfo(3) */
        if (numeric > 0)
-               allow_gethostbyaddr = 0;
+               allow_getnameinfo = 0;
        else
-               allow_gethostbyaddr = 1;
+               allow_getnameinfo = 1;
 
        TAILQ_INIT(&lognames);
        increase_state(STATE_CONFIG);
@@ -210,7 +212,7 @@ priv_init(char *conf, int numeric, int l
                        /* Expecting: length, path */
                        must_read(socks[0], &path_len, sizeof(size_t));
                        if (path_len == 0 || path_len > sizeof(path))
-                               _exit(0);
+                               _exit(1);
                        must_read(socks[0], &path, path_len);
                        path[path_len - 1] = '\0';
                        check_tty_name(path, path_len);
@@ -229,7 +231,7 @@ priv_init(char *conf, int numeric, int l
                        /* Expecting: length, path */
                        must_read(socks[0], &path_len, sizeof(size_t));
                        if (path_len == 0 || path_len > sizeof(path))
-                               _exit(0);
+                               _exit(1);
                        must_read(socks[0], &path, path_len);
                        path[path_len - 1] = '\0';
                        check_log_name(path, path_len);
@@ -289,24 +291,46 @@ priv_init(char *conf, int numeric, int l
                        increase_state(STATE_RUNNING);
                        break;
 
-               case PRIV_GETHOSTSERV:
-                       dprintf("[priv]: msg PRIV_GETHOSTSERV received\n");
-                       /* Expecting: len, hostname, len, servname */
+               case PRIV_GETADDRINFO:
+                       dprintf("[priv]: msg PRIV_GETADDRINFO received\n");
+                       /* Expecting: len, proto, len, host, len, serv */
+                       must_read(socks[0], &protoname_len, sizeof(size_t));
+                       if (protoname_len == 0 ||
+                           protoname_len > sizeof(protoname))
+                               _exit(1);
+                       must_read(socks[0], &protoname, protoname_len);
+                       protoname[protoname_len - 1] = '\0';
+
                        must_read(socks[0], &hostname_len, sizeof(size_t));
-                       if (hostname_len == 0 || hostname_len > 
sizeof(hostname))
-                               _exit(0);
+                       if (hostname_len == 0 ||
+                           hostname_len > sizeof(hostname))
+                               _exit(1);
                        must_read(socks[0], &hostname, hostname_len);
                        hostname[hostname_len - 1] = '\0';
 
                        must_read(socks[0], &servname_len, sizeof(size_t));
-                       if (servname_len == 0 || servname_len > 
sizeof(servname))
-                               _exit(0);
+                       if (servname_len == 0 ||
+                           servname_len > sizeof(servname))
+                               _exit(1);
                        must_read(socks[0], &servname, servname_len);
                        servname[servname_len - 1] = '\0';
 
-                       memset(&hints, '\0', sizeof(hints));
-                       hints.ai_family = AF_INET;
-                       hints.ai_socktype = SOCK_DGRAM;
+                       memset(&hints, 0, sizeof(hints));
+                       if (strcmp(protoname, "udp") == 0) {
+                               hints.ai_family = PF_UNSPEC;
+                               hints.ai_socktype = SOCK_DGRAM;
+                               hints.ai_protocol = IPPROTO_UDP;
+                       } else if (strcmp(protoname, "udp4") == 0) {
+                               hints.ai_family = AF_INET;
+                               hints.ai_socktype = SOCK_DGRAM;
+                               hints.ai_protocol = IPPROTO_UDP;
+                       } else if (strcmp(protoname, "udp6") == 0) {
+                               hints.ai_family = AF_INET6;
+                               hints.ai_socktype = SOCK_DGRAM;
+                               hints.ai_protocol = IPPROTO_UDP;
+                       } else {
+                               errx(1, "unknown protocol %s", protoname);
+                       }
                        i = getaddrinfo(hostname, servname, &hints, &res0);
                        if (i != 0 || res0 == NULL) {
                                addr_len = 0;
@@ -320,24 +344,24 @@ priv_init(char *conf, int numeric, int l
                        }
                        break;
 
-               case PRIV_GETHOSTBYADDR:
-                       dprintf("[priv]: msg PRIV_GETHOSTBYADDR received\n");
-                       if (!allow_gethostbyaddr)
-                               errx(1, "rejected attempt to gethostbyaddr");
-                       /* Expecting: length, address, address family */
+               case PRIV_GETNAMEINFO:
+                       dprintf("[priv]: msg PRIV_GETNAMEINFO received\n");
+                       if (!allow_getnameinfo)
+                               errx(1, "rejected attempt to getnameinfo");
+                       /* Expecting: length, sockaddr */
                        must_read(socks[0], &addr_len, sizeof(int));
-                       if (addr_len <= 0 || addr_len > sizeof(hostname))
-                               _exit(0);
-                       must_read(socks[0], hostname, addr_len);
-                       must_read(socks[0], &addr_af, sizeof(int));
-                       hp = gethostbyaddr(hostname, addr_len, addr_af);
-                       if (hp == NULL) {
+                       if (addr_len <= 0 || addr_len > sizeof(addr))
+                               _exit(1);
+                       must_read(socks[0], &addr, addr_len);
+                       if (getnameinfo((struct sockaddr *)&addr, addr_len,
+                           hostname, sizeof(hostname), NULL, 0,
+                           NI_NOFQDN|NI_NAMEREQD|NI_DGRAM) != 0) {
                                addr_len = 0;
                                must_write(socks[0], &addr_len, sizeof(int));
                        } else {
-                               addr_len = strlen(hp->h_name) + 1;
+                               addr_len = strlen(hostname) + 1;
                                must_write(socks[0], &addr_len, sizeof(int));
-                               must_write(socks[0], hp->h_name, addr_len);
+                               must_write(socks[0], hostname, addr_len);
                        }
                        break;
                default:
@@ -362,7 +386,7 @@ priv_init(char *conf, int numeric, int l
                execvp(argv[0], argv);
        }
        unlink(_PATH_LOGPID);
-       _exit(1);
+       _exit(0);
 }
 
 static int
@@ -659,25 +683,30 @@ priv_config_parse_done(void)
 /* Name/service to address translation.  Response is placed into addr, and
  * the length is returned (zero on error) */
 int
-priv_gethostserv(char *host, char *serv, struct sockaddr *addr,
+priv_getaddrinfo(char *proto, char *host, char *serv, struct sockaddr *addr,
     size_t addr_len)
 {
-       char hostcpy[MAXHOSTNAMELEN], servcpy[MAXHOSTNAMELEN];
+       char protocpy[16], hostcpy[MAXHOSTNAMELEN], servcpy[MAXHOSTNAMELEN];
        int cmd, ret_len;
-       size_t hostname_len, servname_len;
+       size_t protoname_len, hostname_len, servname_len;
 
        if (priv_fd < 0)
-               errx(1, "%s: called from privileged portion", 
"priv_gethostserv");
+               errx(1, "%s: called from privileged portion", 
"priv_getaddrinfo");
 
-       if (strlcpy(hostcpy, host, sizeof hostcpy) >= sizeof(hostcpy))
-               errx(1, "%s: overflow attempt in hostname", "priv_gethostserv");
+       if (strlcpy(protocpy, proto, sizeof(protocpy)) >= sizeof(protocpy))
+               errx(1, "%s: overflow attempt in protoname", 
"priv_getaddrinfo");
+       protoname_len = strlen(protocpy) + 1;
+       if (strlcpy(hostcpy, host, sizeof(hostcpy)) >= sizeof(hostcpy))
+               errx(1, "%s: overflow attempt in hostname", "priv_getaddrinfo");
        hostname_len = strlen(hostcpy) + 1;
-       if (strlcpy(servcpy, serv, sizeof servcpy) >= sizeof(servcpy))
-               errx(1, "%s: overflow attempt in servname", "priv_gethostserv");
+       if (strlcpy(servcpy, serv, sizeof(servcpy)) >= sizeof(servcpy))
+               errx(1, "%s: overflow attempt in servname", "priv_getaddrinfo");
        servname_len = strlen(servcpy) + 1;
 
-       cmd = PRIV_GETHOSTSERV;
+       cmd = PRIV_GETADDRINFO;
        must_write(priv_fd, &cmd, sizeof(int));
+       must_write(priv_fd, &protoname_len, sizeof(size_t));
+       must_write(priv_fd, protocpy, protoname_len);
        must_write(priv_fd, &hostname_len, sizeof(size_t));
        must_write(priv_fd, hostcpy, hostname_len);
        must_write(priv_fd, &servname_len, sizeof(size_t));
@@ -692,7 +721,7 @@ priv_gethostserv(char *host, char *serv,
 
        /* Make sure we aren't overflowing the passed in buffer */
        if (addr_len < ret_len)
-               errx(1, "%s: overflow attempt in return", "priv_gethostserv");
+               errx(1, "%s: overflow attempt in return", "priv_getaddrinfo");
 
        /* Read the resolved address and make sure we got all of it */
        memset(addr, '\0', addr_len);
@@ -704,33 +733,33 @@ priv_gethostserv(char *host, char *serv,
 /* Reverse address resolution; response is placed into res, and length of
  * response is returned (zero on error) */
 int
-priv_gethostbyaddr(char *addr, int addr_len, int af, char *res, size_t res_len)
+priv_getnameinfo(struct sockaddr *sa, socklen_t salen, char *host,
+    size_t hostlen)
 {
        int cmd, ret_len;
 
        if (priv_fd < 0)
-               errx(1, "%s called from privileged portion", 
"priv_gethostbyaddr");
+               errx(1, "%s called from privileged portion", 
"priv_getnameinfo");
 
-       cmd = PRIV_GETHOSTBYADDR;
+       cmd = PRIV_GETNAMEINFO;
        must_write(priv_fd, &cmd, sizeof(int));
-       must_write(priv_fd, &addr_len, sizeof(int));
-       must_write(priv_fd, addr, addr_len);
-       must_write(priv_fd, &af, sizeof(int));
+       must_write(priv_fd, &salen, sizeof(int));
+       must_write(priv_fd, sa, salen);
 
        /* Expect back an integer size, and then a string of that length */
        must_read(priv_fd, &ret_len, sizeof(int));
 
        /* Check there was no error (indicated by a return of 0) */
        if (!ret_len)
-               return 0;
+               return (-1);
 
        /* Check we don't overflow the passed in buffer */
-       if (res_len < ret_len)
-               errx(1, "%s: overflow attempt in return", "priv_gethostbyaddr");
+       if (hostlen < ret_len)
+               errx(1, "%s: overflow attempt in return", "priv_getnameinfo");
 
        /* Read the resolved hostname */
-       must_read(priv_fd, res, ret_len);
-       return ret_len;
+       must_read(priv_fd, host, ret_len);
+       return (0);
 }
 
 /* Pass the signal through to child */
@@ -797,7 +826,7 @@ must_read(int fd, void *buf, size_t n)
                        if (errno == EINTR || errno == EAGAIN)
                                continue;
                case 0:
-                       _exit(0);
+                       _exit(1);
                default:
                        pos += res;
                }
@@ -819,7 +848,7 @@ must_write(int fd, void *buf, size_t n)
                        if (errno == EINTR || errno == EAGAIN)
                                continue;
                case 0:
-                       _exit(0);
+                       _exit(1);
                default:
                        pos += res;
                }
Index: usr.sbin/syslogd/syslogd.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.111
diff -u -p -u -p -r1.111 syslogd.c
--- usr.sbin/syslogd/syslogd.c  14 Jul 2014 04:02:33 -0000      1.111
+++ usr.sbin/syslogd/syslogd.c  18 Aug 2014 23:48:18 -0000
@@ -127,7 +127,7 @@ struct filed {
        union {
                char    f_uname[MAXUNAMES][UT_NAMESIZE+1];
                struct {
-                       char    f_hname[MAXHOSTNAMELEN];
+                       char    f_loghost[2*MAXHOSTNAMELEN];
                        struct sockaddr_storage f_addr;
                } f_forw;               /* forwarding address */
                char    f_fname[MAXPATHLEN];
@@ -188,13 +188,14 @@ int       Debug;                  /* debug flag */
 int    Startup = 1;            /* startup flag */
 char   LocalHostName[MAXHOSTNAMELEN];  /* our hostname */
 char   *LocalDomain;           /* our local domain name */
-int    InetInuse = 0;          /* non-zero if INET sockets are being used */
 int    Initialized = 0;        /* set when we have initialized ourselves */
 
 int    MarkInterval = 20 * 60; /* interval between marks in seconds */
 int    MarkSeq = 0;            /* mark sequence number */
 int    SecureMode = 1;         /* when true, speak only unix domain socks */
 int    NoDNS = 0;              /* when true, will refrain from doing DNS 
lookups */
+int    IPv4Only = 0;           /* when true, disable IPv6 */
+int    IPv6Only = 0;           /* when true, disable IPv4 */
 int    IncludeHostname = 0;    /* include RFC 3164 style hostnames when 
forwarding */
 
 char   *ctlsock_path = NULL;   /* Path to control socket */
@@ -250,7 +251,7 @@ volatile sig_atomic_t WantDie;
 volatile sig_atomic_t DoInit;
 
 struct filed *cfline(char *, char *);
-void    cvthname(struct sockaddr_in *, char *, size_t);
+void    cvthname(struct sockaddr *, char *, size_t);
 int    decode(const char *, const CODE *);
 void   dodie(int);
 void   doinit(int);
@@ -268,6 +269,7 @@ void        reapchild(int);
 char   *ttymsg(struct iovec *, int, char *, int);
 void   usage(void);
 void   wallmsg(struct filed *, struct iovec *);
+int    loghost(char *, char **, char **, char **);
 int    getmsgbufsize(void);
 int    unix_socket(char *, int, mode_t);
 void   double_rbuf(int);
@@ -282,7 +284,7 @@ main(int argc, char *argv[])
 {
        int ch, i, linesize, fd;
        struct sockaddr_un fromunix;
-       struct sockaddr_in frominet;
+       struct sockaddr_storage from;
        socklen_t len;
        char *p, *line;
        char resolve[MAXHOSTNAMELEN];
@@ -290,8 +292,14 @@ main(int argc, char *argv[])
        struct addrinfo hints, *res, *res0;
        FILE *fp;
 
-       while ((ch = getopt(argc, argv, "dhnuf:m:p:a:s:")) != -1)
+       while ((ch = getopt(argc, argv, "46dhnuf:m:p:a:s:")) != -1)
                switch (ch) {
+               case '4':               /* disable IPv6 */
+                       IPv4Only = 1;
+                       break;
+               case '6':               /* disable IPv4 */
+                       IPv6Only = 1;
+                       break;
                case 'd':               /* debug */
                        Debug++;
                        break;
@@ -369,7 +377,7 @@ main(int argc, char *argv[])
        }
 
        memset(&hints, 0, sizeof(hints));
-       hints.ai_family = AF_INET;
+       hints.ai_family = PF_UNSPEC;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_protocol = IPPROTO_UDP;
        hints.ai_flags = AI_PASSIVE;
@@ -384,13 +392,18 @@ main(int argc, char *argv[])
        for (res = res0; res; res = res->ai_next) {
                struct pollfd *pfdp;
 
-               if (res->ai_family == AF_INET)
+               switch (res->ai_family) {
+               case AF_INET:
+                       if (IPv6Only)
+                               continue;
                        pfdp = &pfd[PFD_INET];
-               else {
-                       /*
-                        * XXX AF_INET6 is skipped on purpose, need to
-                        * fix '@' handling first.
-                        */
+                       break;
+               case AF_INET6:
+                       if (IPv4Only)
+                               continue;
+                       pfdp = &pfd[PFD_INET6];
+                       break;
+               default:
                        continue;
                }
 
@@ -410,7 +423,6 @@ main(int argc, char *argv[])
                        continue;
                }
 
-               InetInuse = 1;
                pfdp->fd = fd;
                if (SecureMode)
                        shutdown(pfdp->fd, SHUT_RD);
@@ -582,18 +594,31 @@ main(int argc, char *argv[])
                        }
                }
                if ((pfd[PFD_INET].revents & POLLIN) != 0) {
-                       len = sizeof(frominet);
+                       len = sizeof(from);
                        i = recvfrom(pfd[PFD_INET].fd, line, MAXLINE, 0,
-                           (struct sockaddr *)&frominet, &len);
+                           (struct sockaddr *)&from, &len);
                        if (i > 0) {
                                line[i] = '\0';
-                               cvthname(&frominet, resolve,
-                                   sizeof resolve);
+                               cvthname((struct sockaddr *)&from, resolve,
+                                   sizeof(resolve));
                                dprintf("cvthname res: %s\n", resolve);
                                printline(resolve, line);
                        } else if (i < 0 && errno != EINTR)
                                logerror("recvfrom inet");
                }
+               if ((pfd[PFD_INET6].revents & POLLIN) != 0) {
+                       len = sizeof(from);
+                       i = recvfrom(pfd[PFD_INET6].fd, line, MAXLINE, 0,
+                           (struct sockaddr *)&from, &len);
+                       if (i > 0) {
+                               line[i] = '\0';
+                               cvthname((struct sockaddr *)&from, resolve,
+                                   sizeof(resolve));
+                               dprintf("cvthname res: %s\n", resolve);
+                               printline(resolve, line);
+                       } else if (i < 0 && errno != EINTR)
+                               logerror("recvfrom inet6");
+               }
                if ((pfd[PFD_CTLSOCK].revents & POLLIN) != 0)
                        ctlsock_accept_handler();
                if ((pfd[PFD_CTLCONN].revents & POLLIN) != 0)
@@ -627,7 +652,7 @@ usage(void)
 {
 
        (void)fprintf(stderr,
-           "usage: syslogd [-dhnu] [-a path] [-f config_file] [-m 
mark_interval]\n"
+           "usage: syslogd [-46dhnu] [-a path] [-f config_file] [-m 
mark_interval]\n"
            "               [-p log_socket] [-s reporting_socket]\n");
        exit(1);
 }
@@ -849,7 +874,7 @@ fprintlog(struct filed *f, int flags, ch
 {
        struct iovec iov[6];
        struct iovec *v;
-       int l, retryonce;
+       int fd, l, retryonce;
        char line[MAXLINE + 1], repbuf[80], greetings[500];
 
        v = iov;
@@ -905,14 +930,25 @@ fprintlog(struct filed *f, int flags, ch
                break;
 
        case F_FORW:
-               dprintf(" %s\n", f->f_un.f_forw.f_hname);
+               dprintf(" %s\n", f->f_un.f_forw.f_loghost);
+               switch (f->f_un.f_forw.f_addr.ss_family) {
+               case AF_INET:
+                       fd = pfd[PFD_INET].fd;
+                       break;
+               case AF_INET6:
+                       fd = pfd[PFD_INET6].fd;
+                       break;
+               default:
+                       fd = -1;
+                       break;
+               }
                if ((l = snprintf(line, sizeof(line), "<%d>%.15s %s%s%s",
                    f->f_prevpri, (char *)iov[0].iov_base,
                    IncludeHostname ? LocalHostName : "",
                    IncludeHostname ? " " : "",
                    (char *)iov[4].iov_base)) >= sizeof(line) || l == -1)
                        l = strlen(line);
-               if (sendto(pfd[PFD_INET].fd, line, l, 0,
+               if (sendto(fd, line, l, 0,
                    (struct sockaddr *)&f->f_un.f_forw.f_addr,
                    f->f_un.f_forw.f_addr.ss_len) != l) {
                        switch (errno) {
@@ -1014,7 +1050,7 @@ fprintlog(struct filed *f, int flags, ch
        case F_MEMBUF:
                dprintf("\n");
                snprintf(line, sizeof(line), "%.15s %s %s",
-                   (char *)iov[0].iov_base, (char *)iov[2].iov_base, 
+                   (char *)iov[0].iov_base, (char *)iov[2].iov_base,
                    (char *)iov[4].iov_base);
                if (ringbuf_append_line(f->f_un.f_mb.f_rb, line) == 1)
                        f->f_un.f_mb.f_overflow = 1;
@@ -1096,38 +1132,19 @@ reapchild(int signo)
  * Return a printable representation of a host address.
  */
 void
-cvthname(struct sockaddr_in *f, char *result, size_t res_len)
+cvthname(struct sockaddr *f, char *result, size_t res_len)
 {
-       sigset_t omask, nmask;
-       char *p, *ip;
-       int ret_len;
-
-       if (f->sin_family != AF_INET) {
+       if (getnameinfo(f, f->sa_len, result, res_len, NULL, 0,
+           NI_NUMERICHOST|NI_NUMERICSERV|NI_DGRAM) != 0) {
                dprintf("Malformed from address\n");
                strlcpy(result, "???", res_len);
                return;
        }
-
-       ip = inet_ntoa(f->sin_addr);
-       dprintf("cvthname(%s)\n", ip);
-       if (NoDNS) {
-               strlcpy(result, ip, res_len);
+       if (NoDNS)
                return;
-       }
 
-       sigemptyset(&nmask);
-       sigaddset(&nmask, SIGHUP);
-       sigprocmask(SIG_BLOCK, &nmask, &omask);
-
-       ret_len = priv_gethostbyaddr((char *)&f->sin_addr,
-               sizeof(struct in_addr), f->sin_family, result, res_len);
-
-       sigprocmask(SIG_SETMASK, &omask, NULL);
-       if (ret_len == 0) {
-               dprintf("Host name for your address (%s) unknown\n", ip);
-               strlcpy(result, ip, res_len);
-       } else if ((p = strchr(result, '.')) && strcmp(p + 1, LocalDomain) == 0)
-               *p = '\0';
+       if (priv_getnameinfo(f, f->sa_len, result, res_len) != 0)
+               dprintf("Host name for your address (%s) unknown\n", result);
 }
 
 void
@@ -1367,7 +1384,7 @@ init(void)
                                break;
 
                        case F_FORW:
-                               printf("%s", f->f_un.f_forw.f_hname);
+                               printf("%s", f->f_un.f_forw.f_loghost);
                                break;
 
                        case F_USERS:
@@ -1429,7 +1446,7 @@ cfline(char *line, char *prog)
 {
        int i, pri, addr_len;
        size_t rb_len;
-       char *bp, *p, *q, *cp;
+       char *bp, *p, *q, *proto, *host, *port;
        char buf[MAXLINE], ebuf[100];
        struct filed *xf, *f, *d;
 
@@ -1526,24 +1543,49 @@ cfline(char *line, char *prog)
 
        switch (*p) {
        case '@':
-               if (!InetInuse)
-                       break;
-               if ((cp = strrchr(++p, ':')) != NULL)
-                       *cp++ = '\0';
-               if ((strlcpy(f->f_un.f_forw.f_hname, p,
-                   sizeof(f->f_un.f_forw.f_hname)) >=
-                   sizeof(f->f_un.f_forw.f_hname))) {
-                       snprintf(ebuf, sizeof(ebuf), "hostname too long \"%s\"",
+               if ((strlcpy(f->f_un.f_forw.f_loghost, p,
+                   sizeof(f->f_un.f_forw.f_loghost)) >=
+                   sizeof(f->f_un.f_forw.f_loghost))) {
+                       snprintf(ebuf, sizeof(ebuf), "loghost too long \"%s\"",
                            p);
                        logerror(ebuf);
                        break;
                }
-               addr_len = priv_gethostserv(f->f_un.f_forw.f_hname, 
-                   cp == NULL ? "syslog" : cp, 
-                   (struct sockaddr*)&f->f_un.f_forw.f_addr, 
+               if (loghost(++p, &proto, &host, &port) == -1) {
+                       snprintf(ebuf, sizeof(ebuf), "bad loghost \"%s\"",
+                           f->f_un.f_forw.f_loghost);
+                       logerror(ebuf);
+                       break;
+               }
+               if (proto == NULL || strcmp(proto, "udp") == 0) {
+                       /* no further checks */
+               } else if (strcmp(proto, "udp4") == 0) {
+                       if (pfd[PFD_INET].fd == -1) {
+                               snprintf(ebuf, sizeof(ebuf), "no udp4 \"%s\"",
+                                   f->f_un.f_forw.f_loghost);
+                               logerror(ebuf);
+                               break;
+                       }
+               } else if (strcmp(proto, "udp6") == 0) {
+                       if (pfd[PFD_INET6].fd == -1) {
+                               snprintf(ebuf, sizeof(ebuf), "no udp6 \"%s\"",
+                                   f->f_un.f_forw.f_loghost);
+                               logerror(ebuf);
+                               break;
+                       }
+               } else {
+                       snprintf(ebuf, sizeof(ebuf), "bad protocol \"%s\"",
+                           f->f_un.f_forw.f_loghost);
+                       logerror(ebuf);
+                       break;
+               }
+               addr_len = priv_getaddrinfo(proto == NULL ? "udp" : proto,
+                   host, port == NULL ? "syslog" : port,
+                   (struct sockaddr*)&f->f_un.f_forw.f_addr,
                    sizeof(f->f_un.f_forw.f_addr));
                if (addr_len < 1) {
-                       snprintf(ebuf, sizeof(ebuf), "bad hostname \"%s\"", p);
+                       snprintf(ebuf, sizeof(ebuf), "bad hostname \"%s\"",
+                           f->f_un.f_forw.f_loghost);
                        logerror(ebuf);
                        break;
                }
@@ -1652,6 +1694,33 @@ cfline(char *line, char *prog)
        return (f);
 }
 
+/*
+ * Parse the host and port parts from a loghost string.
+ */
+int
+loghost(char *str, char **proto, char **host, char **port)
+{
+       *proto = NULL;
+       if ((*host = strchr(str, ':')) &&
+           (*host)[1] == '/' && (*host)[2] == '/') {
+               *proto = str;
+               **host = '\0';
+               str = *host + 3;
+       }
+       *host = str;
+       if (**host == '[') {
+               (*host)++;
+               str = strchr(*host, ']');
+               if (str == NULL)
+                       return (-1);
+               *str++ = '\0';
+       }
+       *port = strrchr(str, ':');
+       if (*port != NULL)
+               *(*port)++ = '\0';
+
+       return (0);
+}
 
 /*
  * Retrieve the size of the kernel message buffer, via sysctl.
Index: usr.sbin/syslogd/syslogd.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.h,v
retrieving revision 1.8
diff -u -p -u -p -r1.8 syslogd.h
--- usr.sbin/syslogd/syslogd.h  19 Aug 2013 06:09:23 -0000      1.8
+++ usr.sbin/syslogd/syslogd.h  18 Aug 2014 23:47:01 -0000
@@ -26,8 +26,8 @@ FILE *priv_open_utmp(void);
 FILE *priv_open_config(void);
 void  priv_config_parse_done(void);
 int   priv_config_modified(void);
-int   priv_gethostserv(char *, char *, struct sockaddr *, size_t);
-int   priv_gethostbyaddr(char *, int, int, char *, size_t);
+int   priv_getaddrinfo(char *, char *, char *, struct sockaddr *, size_t);
+int   priv_getnameinfo(struct sockaddr *, socklen_t, char *, size_t);
 
 /* Terminal message */
 char *ttymsg(struct iovec *, int, char *, int);

Attachment: pgpsjpe3q8a5j.pgp
Description: PGP signature

Reply via email to