BUG/MINOR: log: fix logging to both FD and IP
PiBa-NL reported an issue affecting logs when stdout is enabled at the
same time as an IP address. It does not affect FD and UNIX, but does
still affect multiple FDs. What happens is that the condition to detect
that the initialization was not made relies on the FD being -1, and in
this case the FD points to the *unique* FD used for AF_INET sockets, so
the configured socket used for outgoing logs over UDP gets overwritten
by the last configured FD. This is not appropriate, so instead we rely
on the sin_port part of the IPv4-mapped address to store the
initialization state for each FD.
This part deserves being significantly revamped, as IPv6 is still not
possible due to the way the FDs are managed, and inherited FDs are a
bit hackish.
Note that this patch relies on "MINOR: tools: preset the port of
fd-based "sockets" to zero" in order to operate properly.
No backport is needed.
diff --git a/src/log.c b/src/log.c
index 37c2dbd..e0c74bc 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1355,8 +1355,7 @@
nblogger = 0;
list_for_each_entry(tmp, logsrvs, list) {
const struct logsrv *logsrv = tmp;
- int *plogfd = logsrv->addr.ss_family == AF_UNIX ?
- &logfdunix : &logfdinet;
+ int *plogfd;
char *pid_sep1 = "", *pid_sep2 = "";
char logheader_short[3];
int sent;
@@ -1375,15 +1374,24 @@
if (level > logsrv->level)
continue;
- if (unlikely(*plogfd < 0)) {
- /* socket not successfully initialized yet */
- if (logsrv->addr.ss_family == AF_UNSPEC) {
- /* the socket's address is a file descriptor */
- *plogfd = ((struct sockaddr_in *)&logsrv->addr)->sin_addr.s_addr;
+ if (logsrv->addr.ss_family == AF_UNSPEC) {
+ /* the socket's address is a file descriptor */
+ plogfd = (int *)&((struct sockaddr_in *)&logsrv->addr)->sin_addr.s_addr;
+ if (unlikely(!((struct sockaddr_in *)&logsrv->addr)->sin_port)) {
+ /* FD not yet initialized to non-blocking mode */
fcntl(*plogfd, F_SETFL, O_NONBLOCK);
+ ((struct sockaddr_in *)&logsrv->addr)->sin_port = 1;
}
- else if ((*plogfd = socket(logsrv->addr.ss_family, SOCK_DGRAM,
- (logsrv->addr.ss_family == AF_UNIX) ? 0 : IPPROTO_UDP)) < 0) {
+ }
+ else if (logsrv->addr.ss_family == AF_UNIX)
+ plogfd = &logfdunix;
+ else
+ plogfd = &logfdinet;
+
+ if (unlikely(*plogfd < 0)) {
+ /* socket not successfully initialized yet */
+ if ((*plogfd = socket(logsrv->addr.ss_family, SOCK_DGRAM,
+ (logsrv->addr.ss_family == AF_UNIX) ? 0 : IPPROTO_UDP)) < 0) {
static char once;
if (!once) {