Hi,

When DNS lookup for remote loghost in @ line in syslog.conf does
not work at startup, retry in intervals.

Please test if you use the feature.

ok?

bluhm

Index: syslogd.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.277
diff -u -p -r1.277 syslogd.c
--- syslogd.c   16 Mar 2023 18:22:08 -0000      1.277
+++ syslogd.c   2 Sep 2023 23:42:22 -0000
@@ -156,9 +156,12 @@ struct filed {
                        struct sockaddr_storage  f_addr;
                        struct buffertls         f_buftls;
                        struct bufferevent      *f_bufev;
+                       struct event             f_ev;
                        struct tls              *f_ctx;
+                       char                    *f_ipproto;
                        char                    *f_host;
-                       int                      f_reconnectwait;
+                       char                    *f_port;
+                       int                      f_retrywait;
                } f_forw;               /* forwarding address */
                char    f_fname[PATH_MAX];
                struct {
@@ -320,6 +323,7 @@ void         tcp_writecb(struct bufferevent *, 
 void    tcp_errorcb(struct bufferevent *, short, void *);
 void    tcp_connectcb(int, short, void *);
 void    tcp_connect_retry(struct bufferevent *, struct filed *);
+void    udp_resolvecb(int, short, void *);
 int     tcpbuf_countmsg(struct bufferevent *bufev);
 void    die_signalcb(int, short, void *);
 void    mark_timercb(int, short, void *);
@@ -1380,7 +1384,7 @@ tcp_writecb(struct bufferevent *bufev, v
         * Successful write, connection to server is good, reset wait time.
         */
        log_debug("loghost \"%s\" successful write", f->f_un.f_forw.f_loghost);
-       f->f_un.f_forw.f_reconnectwait = 0;
+       f->f_un.f_forw.f_retrywait = 0;
 
        if (f->f_dropped > 0 &&
            EVBUFFER_LENGTH(f->f_un.f_forw.f_bufev->output) < MAX_TCPBUF) {
@@ -1453,6 +1457,18 @@ tcp_connectcb(int fd, short event, void 
        struct bufferevent      *bufev = f->f_un.f_forw.f_bufev;
        int                      s;
 
+       if (f->f_un.f_forw.f_addr.ss_family == AF_UNSPEC) {
+               if (priv_getaddrinfo(f->f_un.f_forw.f_ipproto,
+                   f->f_un.f_forw.f_host, f->f_un.f_forw.f_port,
+                   (struct sockaddr*)&f->f_un.f_forw.f_addr,
+                   sizeof(f->f_un.f_forw.f_addr)) != 0) {
+                       log_warnx("bad hostname \"%s\"",
+                           f->f_un.f_forw.f_loghost);
+                       tcp_connect_retry(bufev, f);
+                       return;
+               }
+       }
+
        if ((s = tcp_socket(f)) == -1) {
                tcp_connect_retry(bufev, f);
                return;
@@ -1511,21 +1527,66 @@ tcp_connect_retry(struct bufferevent *bu
 {
        struct timeval           to;
 
-       if (f->f_un.f_forw.f_reconnectwait == 0)
-               f->f_un.f_forw.f_reconnectwait = 1;
+       if (f->f_un.f_forw.f_retrywait == 0)
+               f->f_un.f_forw.f_retrywait = 1;
        else
-               f->f_un.f_forw.f_reconnectwait <<= 1;
-       if (f->f_un.f_forw.f_reconnectwait > 600)
-               f->f_un.f_forw.f_reconnectwait = 600;
-       to.tv_sec = f->f_un.f_forw.f_reconnectwait;
+               f->f_un.f_forw.f_retrywait <<= 1;
+       if (f->f_un.f_forw.f_retrywait > 600)
+               f->f_un.f_forw.f_retrywait = 600;
+       to.tv_sec = f->f_un.f_forw.f_retrywait;
        to.tv_usec = 0;
+       evtimer_add(&f->f_un.f_forw.f_ev, &to);
 
-       log_debug("tcp connect retry: wait %d",
-           f->f_un.f_forw.f_reconnectwait);
+       log_debug("tcp connect retry: wait %d", f->f_un.f_forw.f_retrywait);
        bufferevent_setfd(bufev, -1);
-       /* We can reuse the write event as bufferevent is disabled. */
-       evtimer_set(&bufev->ev_write, tcp_connectcb, f);
-       evtimer_add(&bufev->ev_write, &to);
+}
+
+void
+udp_resolvecb(int fd, short event, void *arg)
+{
+       struct filed            *f = arg;
+       struct timeval           to;
+
+       if (priv_getaddrinfo(f->f_un.f_forw.f_ipproto,
+           f->f_un.f_forw.f_host, f->f_un.f_forw.f_port,
+           (struct sockaddr*)&f->f_un.f_forw.f_addr,
+           sizeof(f->f_un.f_forw.f_addr)) == 0) {
+               switch (f->f_un.f_forw.f_addr.ss_family) {
+               case AF_INET:
+                       log_debug("resolved \"%s\" to IPv4 address",
+                           f->f_un.f_forw.f_loghost);
+                       f->f_file = fd_udp;
+                       break;
+               case AF_INET6:
+                       log_debug("resolved \"%s\" to IPv6 address",
+                           f->f_un.f_forw.f_loghost);
+                       f->f_file = fd_udp6;
+                       break;
+               }
+               f->f_un.f_forw.f_retrywait = 0;
+
+               if (f->f_dropped > 0) {
+                       char ebuf[ERRBUFSIZE];
+
+                       snprintf(ebuf, sizeof(ebuf), "to udp loghost \"%s\"",
+                           f->f_un.f_forw.f_loghost);
+                       dropped_warn(&f->f_dropped, ebuf);
+               }
+               return;
+       }
+       log_warnx("bad hostname \"%s\"", f->f_un.f_forw.f_loghost);
+
+       if (f->f_un.f_forw.f_retrywait == 0)
+               f->f_un.f_forw.f_retrywait = 1;
+       else
+               f->f_un.f_forw.f_retrywait <<= 1;
+       if (f->f_un.f_forw.f_retrywait > 600)
+               f->f_un.f_forw.f_retrywait = 600;
+       to.tv_sec = f->f_un.f_forw.f_retrywait;
+       to.tv_usec = 0;
+       evtimer_add(&f->f_un.f_forw.f_ev, &to);
+
+       log_debug("udp resolve retry: wait %d", f->f_un.f_forw.f_retrywait);
 }
 
 int
@@ -1933,6 +1994,11 @@ fprintlog(struct filed *f, int flags, ch
 
        case F_FORWUDP:
                log_debug(" %s", f->f_un.f_forw.f_loghost);
+               if (f->f_un.f_forw.f_addr.ss_family == AF_UNSPEC) {
+                       log_warnx("not resolved \"%s\"",
+                           f->f_un.f_forw.f_loghost);
+                       break;
+               }
                l = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len +
                    iov[3].iov_len + iov[4].iov_len + iov[5].iov_len +
                    iov[6].iov_len;
@@ -2295,23 +2361,33 @@ init(void)
                        fprintlog(f, 0, (char *)NULL);
 
                switch (f->f_type) {
+               case F_FORWUDP:
+                       evtimer_del(&f->f_un.f_forw.f_ev);
+                       free(f->f_un.f_forw.f_ipproto);
+                       free(f->f_un.f_forw.f_host);
+                       free(f->f_un.f_forw.f_port);
+                       break;
                case F_FORWTLS:
                        if (f->f_un.f_forw.f_ctx) {
                                tls_close(f->f_un.f_forw.f_ctx);
                                tls_free(f->f_un.f_forw.f_ctx);
                        }
-                       free(f->f_un.f_forw.f_host);
                        /* FALLTHROUGH */
                case F_FORWTCP:
+                       evtimer_del(&f->f_un.f_forw.f_ev);
                        tcpbuf_dropped += f->f_dropped +
                             tcpbuf_countmsg(f->f_un.f_forw.f_bufev);
                        bufferevent_free(f->f_un.f_forw.f_bufev);
+                       free(f->f_un.f_forw.f_ipproto);
+                       free(f->f_un.f_forw.f_host);
+                       free(f->f_un.f_forw.f_port);
                        /* FALLTHROUGH */
                case F_FILE:
                        if (f->f_type == F_FILE) {
                                file_dropped += f->f_dropped;
                                f->f_dropped = 0;
                        }
+                       /* FALLTHROUGH */
                case F_TTY:
                case F_CONSOLE:
                case F_PIPE:
@@ -2709,11 +2785,32 @@ cfline(char *line, char *progblock, char
                    sizeof(f->f_un.f_forw.f_addr)) != 0) {
                        log_warnx("bad hostname \"%s\"",
                            f->f_un.f_forw.f_loghost);
+                       f->f_un.f_forw.f_addr.ss_family = AF_UNSPEC;
+               }
+               f->f_un.f_forw.f_ipproto = strdup(ipproto);
+               f->f_un.f_forw.f_host = strdup(host);
+               f->f_un.f_forw.f_port = strdup(port);
+               if (f->f_un.f_forw.f_ipproto == NULL ||
+                   f->f_un.f_forw.f_host == NULL ||
+                   f->f_un.f_forw.f_port == NULL) {
+                       log_warnx("strdup ipproto host port \"%s\"",
+                           f->f_un.f_forw.f_loghost);
+                       free(f->f_un.f_forw.f_ipproto);
+                       free(f->f_un.f_forw.f_host);
+                       free(f->f_un.f_forw.f_port);
                        break;
                }
                f->f_file = -1;
                if (strncmp(proto, "udp", 3) == 0) {
+                       evtimer_set(&f->f_un.f_forw.f_ev, udp_resolvecb, f);
                        switch (f->f_un.f_forw.f_addr.ss_family) {
+                       case AF_UNSPEC:
+                               log_debug("resolve \"%s\" delayed",
+                                   f->f_un.f_forw.f_loghost);
+                               to.tv_sec = 0;
+                               to.tv_usec = 1;
+                               evtimer_add(&f->f_un.f_forw.f_ev, &to);
+                               break;
                        case AF_INET:
                                f->f_file = fd_udp;
                                break;
@@ -2727,26 +2824,23 @@ cfline(char *line, char *progblock, char
                            tcp_dropcb, tcp_writecb, tcp_errorcb, f)) == NULL) {
                                log_warn("bufferevent \"%s\"",
                                    f->f_un.f_forw.f_loghost);
+                               free(f->f_un.f_forw.f_ipproto);
+                               free(f->f_un.f_forw.f_host);
+                               free(f->f_un.f_forw.f_port);
                                break;
                        }
-                       if (strncmp(proto, "tls", 3) == 0) {
-                               f->f_un.f_forw.f_host = strdup(host);
-                               f->f_type = F_FORWTLS;
-                       } else {
-                               f->f_type = F_FORWTCP;
-                       }
                        /*
                         * If we try to connect to a TLS server immediately
                         * syslogd gets an SIGPIPE as the signal handlers have
                         * not been set up.  Delay the connection until the
-                        * event loop is started.  We can reuse the write event
-                        * for that as bufferevent is still disabled.
+                        * event loop is started.
                         */
+                       evtimer_set(&f->f_un.f_forw.f_ev, tcp_connectcb, f);
                        to.tv_sec = 0;
                        to.tv_usec = 1;
-                       evtimer_set(&f->f_un.f_forw.f_bufev->ev_write,
-                           tcp_connectcb, f);
-                       evtimer_add(&f->f_un.f_forw.f_bufev->ev_write, &to);
+                       evtimer_add(&f->f_un.f_forw.f_ev, &to);
+                       f->f_type = (strncmp(proto, "tls", 3) == 0) ?
+                           F_FORWTLS : F_FORWTCP;
                }
                break;
 

Reply via email to