Hello, On 2023/06/22 13:22:56 +0000, Robert Larsson <larssonrobert...@gmail.com> wrote: > Hello, > > Syslog can be configured to send log to remote hosts using both > IP-addresses and resolvable hostnames. DNS resolution of these hostnames > is done in the "cfline()" function, which is invoked only during parsing > of the configuration file. > > If DNS is not available when syslog starts, no attempts are made at a > later stage to perform this resolution, so a temporary outage during > startup causes the log stream to be permanently disabled. > > I took a stab at implementing a fix to this, but would very much > appreciate if someone experienced could review it as I am not at all > confident in my C coding abilities. > > The patch adds a new variable - "f_resolved" - which is set to zero on > startup. If syslog is about to attempt a TCP connection and "f_resolved" > is zero, a new function "resolve_host" is called to try a DNS > resolution. With UDP, this resolution is attempted before every sendmsg > if address resolution failed earlier - I'm worried this might cause > overhead, but I also didn't want to overcomplicate things.
I don't have any opinion on this, I just stumbled on the thread and noticed that the diff was mangled due to whitespaces. Please consider fixing your MUA or attaching a diff. To test, you could send the diff to yourself and see if it applies. While here however, point out some obvious style(9) violation > Index: syslogd.c > =================================================================== > RCS file: /cvs/src/usr.sbin/syslogd/syslogd.c,v > retrieving revision 1.277 > diff -u -p -u -r1.277 syslogd.c > --- syslogd.c 16 Mar 2023 18:22:08 -0000 1.277 > +++ syslogd.c 22 Jun 2023 12:41:09 -0000 > @@ -159,6 +159,7 @@ struct filed { > struct tls *f_ctx; > char *f_host; > int f_reconnectwait; > + char f_resolved; > } f_forw; /* forwarding address */ > char f_fname[PATH_MAX]; > struct { > @@ -1446,6 +1447,75 @@ tcp_errorcb(struct bufferevent *bufev, s > log_info(LOG_WARNING, "%s", ebuf); > } > > +int > +resolve_host(struct filed *f) > +{ > + int retval = -1; > + char *loghostcpy = NULL, *ipproto, *proto, *host, *port; > + > + if (f->f_un.f_forw.f_loghost[0] != '@') { > + log_warnx("invalid loghost \"%s\"", > + f->f_un.f_forw.f_loghost); > + goto cleanup; > + } > + > + // loghost_parse breaks the loghost line in a strtok:y way, > + // so we work on a copy. Note that loghost_parse uses this > + // buffer to store proto, host and port, so don't free this > + // until we are completely done. please don't use C++ style comments, but /* C style comments */ > + loghostcpy = strdup(f->f_un.f_forw.f_loghost+1); > + if(loghostcpy == NULL) { use spaces between if and the condition + if (loghostcpy == NULL) { > + log_warnx("strdup error: %d", errno); I fear the raw `errno' value is useless. consider using log_warn("strdup"); instead, which appends the error description to the message. (note the difference, it's log_warn not log_warnx.) > + goto cleanup; > + } > + > + if(loghost_parse(loghostcpy, &proto, &host, &port) == -1) { same spacing as noted before. > + log_warnx("bad loghost \"%s\"", > + f->f_un.f_forw.f_loghost); > + goto cleanup; > + } > + > + // This code somewhat repeats tests in cfline(), but maybe > + // not enought to warrant breaking it out into a separate > + // function? > + ipproto = proto; > + if (strcmp(proto, "tls") == 0) { > + ipproto = "tcp"; > + } else if (strcmp(proto, "tls4") == 0) { > + ipproto = "tcp4"; > + } else if (strcmp(proto, "tls6") == 0) { > + ipproto = "tcp6"; > + } else if ( > + strcmp(proto, "tcp") == 0 || \ > + strcmp(proto, "tcp4") == 0 || \ > + strcmp(proto, "tcp6") == 0 || \ > + strcmp(proto, "udp") == 0 || \ > + strcmp(proto, "udp4") == 0 || \ > + strcmp(proto, "udp6") == 0) { this is not shell scripting, no need for \ to break lines. also, similar constructs are often spelled as else if (strcmp(...) == 0 || strcmp(...) == 0 || strcmp(...) == 0 || ...) { /* ... */ } > + ; instead of an empty body I'd reverse the previous logic and error there. > + } else { > + log_warnx("bad protocol \"%s\"", > + f->f_un.f_forw.f_loghost); > + goto cleanup; > + } > + > + if (priv_getaddrinfo(ipproto, host, port, > + (struct sockaddr*)&f->f_un.f_forw.f_addr, > + sizeof(f->f_un.f_forw.f_addr)) != 0) { > + log_warnx("could not resolve \"%s\"", > + host); > + goto cleanup; > + } > + > + f->f_un.f_forw.f_resolved = 1; > + retval = 0; > +cleanup: > + if(loghostcpy != NULL) > + free(loghostcpy); > + log_debug("resolve host: %s for \"%s\"", retval ? "failed" : > "successful", f->f_un.f_forw.f_loghost); > + return retval; > +} > + > void > tcp_connectcb(int fd, short event, void *arg) > { > @@ -1453,6 +1523,12 @@ 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_resolved) { > + if(resolve_host(f) == -1) { > + goto error; > + } > + } > + > if ((s = tcp_socket(f)) == -1) { > tcp_connect_retry(bufev, f); > return; > @@ -1943,6 +2019,22 @@ fprintlog(struct filed *f, int flags, ch > else > iov[5].iov_len = 0; > } > + > + if(!f->f_un.f_forw.f_resolved) { > + if(resolve_host(f) == -1) { > + break; > + } > + switch (f->f_un.f_forw.f_addr.ss_family) { > + case AF_INET: > + f->f_file = fd_udp; > + break; > + case AF_INET6: > + f->f_file = fd_udp6; > + break; > + } > + } > + > + > memset(&msghdr, 0, sizeof(msghdr)); > msghdr.msg_name = &f->f_un.f_forw.f_addr; > msghdr.msg_namelen = f->f_un.f_forw.f_addr.ss_len; > @@ -2704,25 +2796,12 @@ cfline(char *line, char *progblock, char > f->f_un.f_forw.f_loghost); > break; > } > - if (priv_getaddrinfo(ipproto, host, 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); > - break; > - } > f->f_file = -1; > if (strncmp(proto, "udp", 3) == 0) { > - switch (f->f_un.f_forw.f_addr.ss_family) { > - case AF_INET: > - f->f_file = fd_udp; > - break; > - case AF_INET6: > - f->f_file = fd_udp6; > - break; > - } > + f->f_un.f_forw.f_resolved = 0; > f->f_type = F_FORWUDP; > } else if (strncmp(ipproto, "tcp", 3) == 0) { > + f->f_un.f_forw.f_resolved = 0; > if ((f->f_un.f_forw.f_bufev = bufferevent_new(-1, > tcp_dropcb, tcp_writecb, tcp_errorcb, f)) == NULL) { > log_warn("bufferevent \"%s\"", Thanks, Omar Polo