diff --git a/usr.sbin/syslogd/syslogd.h b/usr.sbin/syslogd/syslogd.h --- a/usr.sbin/syslogd/syslogd.h +++ b/usr.sbin/syslogd/syslogd.h @@ -156,7 +156,8 @@ char f_fname[MAXPATHLEN]; /* F_FILE, F_CONSOLE, F_TTY */ struct { char f_hname[MAXHOSTNAMELEN]; - struct addrinfo *f_addr; + int *f_addr_fds; + size_t f_num_addr_fds; }; /* F_FORW */ struct { char f_pname[MAXPATHLEN]; diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c --- a/usr.sbin/syslogd/syslogd.c +++ b/usr.sbin/syslogd/syslogd.c @@ -364,9 +364,12 @@ switch (f->f_type) { case F_FORW: - if (f->f_addr != NULL) { - freeaddrinfo(f->f_addr); - f->f_addr = NULL; + if (f->f_addr_fds != NULL) { + for (size_t i = 0; i < f->f_num_addr_fds; ++i) + close(f->f_addr_fds[i]); + free(f->f_addr_fds); + f->f_addr_fds = NULL; + f->f_num_addr_fds = 0; } /* FALLTHROUGH */ case F_FILE: @@ -1742,30 +1745,49 @@ static void fprintlog_write(struct filed *f, struct iovlist *il, int flags) { - struct msghdr msghdr; - struct addrinfo *r; - struct socklist *sl; const char *msgret; - ssize_t lsent; switch (f->f_type) { - case F_FORW: - dprintf(" %s", f->f_hname); - switch (f->f_addr->ai_family) { + case F_FORW: { + ssize_t lsent; + + if (Debug) { + int domain, sockfd = f->f_addr_fds[0]; + socklen_t len = sizeof(domain); + + if (getsockopt(sockfd, SOL_SOCKET, SO_DOMAIN, + &domain, &len) < 0) + err(1, "getsockopt"); + + printf(" %s", f->f_hname); + switch (domain) { #ifdef INET - case AF_INET: - dprintf(":%d\n", - ntohs(satosin(f->f_addr->ai_addr)->sin_port)); - break; + case AF_INET: { + struct sockaddr_in sin; + + len = sizeof(sin); + if (getpeername(sockfd, + (struct sockaddr *)&sin, &len) < 0) + err(1, "getpeername"); + printf(":%d\n", ntohs(sin.sin_port)); + break; + } #endif #ifdef INET6 - case AF_INET6: - dprintf(":%d\n", - ntohs(satosin6(f->f_addr->ai_addr)->sin6_port)); - break; + case AF_INET6: { + struct sockaddr_in6 sin6; + + len = sizeof(sin6); + if (getpeername(sockfd, + (struct sockaddr *)&sin6, &len) < 0) + err(1, "getpeername"); + printf(":%d\n", ntohs(sin6.sin6_port)); + break; + } #endif - default: - dprintf("\n"); + default: + printf("\n"); + } } #if defined(INET) || defined(INET6) @@ -1773,24 +1795,13 @@ iovlist_truncate(il, MaxForwardLen); #endif - lsent = 0; - for (r = f->f_addr; r; r = r->ai_next) { - memset(&msghdr, 0, sizeof(msghdr)); - msghdr.msg_name = r->ai_addr; - msghdr.msg_namelen = r->ai_addrlen; - msghdr.msg_iov = il->iov; - msghdr.msg_iovlen = il->iovcnt; - STAILQ_FOREACH(sl, &shead, next) { - if (sl->sl_socket < 0) - continue; - if (sl->sl_sa == NULL || - sl->sl_family == AF_UNSPEC || - sl->sl_family == AF_LOCAL) - continue; - lsent = sendmsg(sl->sl_socket, &msghdr, 0); - if (lsent == (ssize_t)il->totalsize) - break; - } + for (size_t i = 0; i < f->f_num_addr_fds; ++i) { + struct msghdr msg = { + .msg_iov = il->iov, + .msg_iovlen = il->iovcnt, + }; + + lsent = sendmsg(f->f_addr_fds[i], &msg, 0); if (lsent == (ssize_t)il->totalsize && !send_to_all) break; } @@ -1822,6 +1833,7 @@ } } break; + } case F_FILE: dprintf(" %s\n", f->f_fname); @@ -2650,17 +2662,36 @@ printf("%s%s", _PATH_DEV, f->f_fname); break; - case F_FORW: - switch (f->f_addr->ai_family) { + case F_FORW: { + int domain, sockfd = f->f_addr_fds[0]; + socklen_t len = sizeof(domain); + + if (getsockopt(sockfd, SOL_SOCKET, SO_DOMAIN, + &domain, &len) < 0) + err(1, "getsockopt"); + + switch (domain) { #ifdef INET - case AF_INET: - port = ntohs(satosin(f->f_addr->ai_addr)->sin_port); + case AF_INET: { + struct sockaddr_in sin; + + len = sizeof(sin); + if (getpeername(sockfd, (struct sockaddr *)&sin, &len) < 0) + err(1, "getpeername"); + port = ntohs(sin.sin_port); break; + } #endif #ifdef INET6 - case AF_INET6: - port = ntohs(satosin6(f->f_addr->ai_addr)->sin6_port); + case AF_INET6: { + struct sockaddr_in6 sin6; + + len = sizeof(sin6); + if (getpeername(sockfd, (struct sockaddr *)&sin6, &len) < 0) + err(1, "getpeername"); + port = ntohs(sin6.sin6_port); break; + } #endif default: port = 0; @@ -2671,6 +2702,7 @@ printf("%s", f->f_hname); } break; + } case F_PIPE: printf("%s", f->f_pname); @@ -2948,7 +2980,7 @@ static void parse_action(const char *p, struct filed *f) { - struct addrinfo hints, *res; + struct addrinfo *ai, hints, *res; int error, i; const char *q; bool syncfile; @@ -3003,7 +3035,28 @@ dprintf("%s\n", gai_strerror(error)); break; } - f->f_addr = res; + + for (ai = res; ai != NULL; ai = ai->ai_next) + ++f->f_num_addr_fds; + + f->f_addr_fds = calloc(f->f_num_addr_fds, + sizeof(*f->f_addr_fds)); + if (f->f_addr_fds == NULL) + err(1, "malloc failed"); + + for (ai = res, i = 0; ai != NULL; ai = ai->ai_next, ++i) { + int *sockp = &f->f_addr_fds[i]; + + *sockp = socket(ai->ai_family, ai->ai_socktype, 0); + if (*sockp < 0) + err(1, "socket"); + if (connect(*sockp, ai->ai_addr, ai->ai_addrlen) < 0) + err(1, "connect"); + /* Make it a write-only socket. */ + if (shutdown(*sockp, SHUT_RD) < 0) + err(1, "shutdown"); + } + f->f_type = F_FORW; break; diff --git a/usr.sbin/syslogd/syslogd_cap_config.c b/usr.sbin/syslogd/syslogd_cap_config.c --- a/usr.sbin/syslogd/syslogd_cap_config.c +++ b/usr.sbin/syslogd/syslogd_cap_config.c @@ -137,18 +137,9 @@ } else if (f_type == F_FILE || f_type == F_CONSOLE || f_type == F_TTY) { nvlist_add_string(nvl_filed, "f_fname", filed->f_fname); } else if (f_type == F_FORW) { - struct addrinfo *ai = filed->f_addr, *cur; - nvlist_t *nvl_addrinfo; - nvlist_add_string(nvl_filed, "f_hname", filed->f_hname); - if (filed->f_addr != NULL) { - for (cur = ai; cur != NULL; cur = cur->ai_next) { - nvl_addrinfo = addrinfo_pack(cur); - nvlist_append_nvlist_array(nvl_filed, - "f_addr", nvl_addrinfo); - nvlist_destroy(nvl_addrinfo); - } - } + nvlist_add_descriptor_array(nvl_filed, "f_addr_fds", + filed->f_addr_fds, filed->f_num_addr_fds); } else if (filed->f_type == F_PIPE) { nvlist_add_string(nvl_filed, "f_pname", filed->f_pname); if (filed->f_procdesc >= 0) { @@ -217,19 +208,21 @@ (void)strlcpy(filed->f_fname, nvlist_get_string(nvl_filed, "f_fname"), sizeof(filed->f_fname)); } else if (f_type == F_FORW) { - const nvlist_t * const *f_addr; - struct addrinfo *ai, **next = NULL; + const int *f_addr_fds; (void)strlcpy(filed->f_hname, nvlist_get_string(nvl_filed, "f_hname"), sizeof(filed->f_hname)); - f_addr = nvlist_get_nvlist_array(nvl_filed, "f_addr", &sz); - for (i = 0; i < sz; ++i) { - ai = addrinfo_unpack(f_addr[i]); - if (next == NULL) - filed->f_addr = ai; - else - *next = ai; - next = &ai->ai_next; + + f_addr_fds = nvlist_get_descriptor_array(nvl_filed, + "f_addr_fds", &filed->f_num_addr_fds); + filed->f_addr_fds = calloc(filed->f_num_addr_fds, + sizeof(*f_addr_fds)); + if (filed->f_addr_fds == NULL) + err(1, "calloc"); + for (i = 0; i < filed->f_num_addr_fds; ++i) { + filed->f_addr_fds[i] = dup(f_addr_fds[i]); + if (filed->f_addr_fds[i] < 0) + err(1, "dup"); } } else if (filed->f_type == F_PIPE) { (void)strlcpy(filed->f_pname, nvlist_get_string(nvl_filed,