I noticed on my laptop that if I tried to start unwind(8) via rcctl(8)
while I already had some other process bound to tcp/udp port 53 (e.g. unbound(8)), rcctl(8) would falsely report the service started "ok" while in /var/log/daemon unwind(8) would report: fatal in main: could not bind to 127.0.0.1 or ::1 on port 53 Since unwind(8) daemonizes before the exit(3) call, rcctl(8) doesn't identify the failure. The below diff splits unwind.c:open_ports() and moves the socket bind/listen calls to before calling daemon(3). The imsg composition is kept in the location of the original call to open_ports() in main(). The sockets have SOCK_CLOEXEC added to them since they're now created before the fork/execvp dance creating the frontend and resolver processes. Feedback or OK? -dv@ Index: sbin/unwind/unwind.c =================================================================== RCS file: /cvs/src/sbin/unwind/unwind.c,v retrieving revision 1.61 diff -u -p -r1.61 unwind.c --- sbin/unwind/unwind.c 27 Feb 2021 10:32:28 -0000 1.61 +++ sbin/unwind/unwind.c 4 Apr 2021 14:57:52 -0000 @@ -56,6 +56,13 @@ enum uw_process { PROC_FRONTEND, }; +struct uw_socks { + int tcp4sock; + int tcp6sock; + int udp4sock; + int udp6sock; +}; + __dead void usage(void); __dead void main_shutdown(void); @@ -71,7 +78,7 @@ static int main_imsg_send_config(struct int main_reload(void); int main_sendall(enum imsg_type, void *, uint16_t); -void open_ports(void); +void open_ports(struct uw_socks *); void solicit_dns_proposals(void); void send_blocklist_fd(void); @@ -127,6 +134,7 @@ main(int argc, char *argv[]) int pipe_main2frontend[2], pipe_main2resolver[2]; int control_fd, ta_fd; char *csock, *saved_argv0; + struct uw_socks socks = { -1, -1, -1, -1 }; csock = _PATH_UNWIND_SOCKET; @@ -203,6 +211,8 @@ main(int argc, char *argv[]) log_init(debug, LOG_DAEMON); log_setverbose(cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2 | OPT_VERBOSE3)); + open_ports(&socks); + if (!debug) daemon(1, 0); @@ -259,7 +269,15 @@ main(int argc, char *argv[]) &iev_resolver->ibuf)) fatal("could not establish imsg links"); - open_ports(); + /* Send opened sockets to the frontend */ + if (socks.udp4sock != -1) + main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, socks.udp4sock); + if (socks.udp6sock != -1) + main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, socks.udp6sock); + if (socks.tcp4sock != -1) + main_imsg_compose_frontend_fd(IMSG_TCP4SOCK, 0, socks.tcp4sock); + if (socks.tcp6sock != -1) + main_imsg_compose_frontend_fd(IMSG_TCP6SOCK, 0, socks.tcp6sock); if ((control_fd = control_init(csock)) == -1) fatalx("control socket setup failed"); @@ -724,7 +742,7 @@ config_clear(struct uw_conf *conf) } void -open_ports(void) +open_ports(struct uw_socks *socks) { struct addrinfo hints, *res0; int udp4sock = -1, udp6sock = -1, error, bsize = 65535; @@ -738,8 +756,9 @@ open_ports(void) error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); if (!error && res0) { - if ((udp4sock = socket(res0->ai_family, res0->ai_socktype, - res0->ai_protocol)) != -1) { + if ((udp4sock = socket(res0->ai_family, + res0->ai_socktype | SOCK_CLOEXEC, + res0->ai_protocol)) != -1) { if (setsockopt(udp4sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) log_warn("setting SO_REUSEADDR on socket"); @@ -759,8 +778,9 @@ open_ports(void) hints.ai_family = AF_INET6; error = getaddrinfo("::1", "domain", &hints, &res0); if (!error && res0) { - if ((udp6sock = socket(res0->ai_family, res0->ai_socktype, - res0->ai_protocol)) != -1) { + if ((udp6sock = socket(res0->ai_family, + res0->ai_socktype | SOCK_CLOEXEC, + res0->ai_protocol)) != -1) { if (setsockopt(udp6sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) log_warn("setting SO_REUSEADDR on socket"); @@ -783,8 +803,8 @@ open_ports(void) error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); if (!error && res0) { if ((tcp4sock = socket(res0->ai_family, - res0->ai_socktype | SOCK_NONBLOCK, - res0->ai_protocol)) != -1) { + res0->ai_socktype | SOCK_NONBLOCK | SOCK_CLOEXEC, + res0->ai_protocol)) != -1) { if (setsockopt(tcp4sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) log_warn("setting SO_REUSEADDR on socket"); @@ -809,8 +829,8 @@ open_ports(void) error = getaddrinfo("::1", "domain", &hints, &res0); if (!error && res0) { if ((tcp6sock = socket(res0->ai_family, - res0->ai_socktype | SOCK_NONBLOCK, - res0->ai_protocol)) != -1) { + res0->ai_socktype | SOCK_NONBLOCK | SOCK_CLOEXEC, + res0->ai_protocol)) != -1) { if (setsockopt(tcp6sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) log_warn("setting SO_REUSEADDR on socket"); @@ -835,14 +855,10 @@ open_ports(void) tcp6sock == -1)) fatalx("could not bind to 127.0.0.1 or ::1 on port 53"); - if (udp4sock != -1) - main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock); - if (udp6sock != -1) - main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock); - if (tcp4sock != -1) - main_imsg_compose_frontend_fd(IMSG_TCP4SOCK, 0, tcp4sock); - if (tcp6sock != -1) - main_imsg_compose_frontend_fd(IMSG_TCP6SOCK, 0, tcp6sock); + socks->tcp4sock = tcp4sock; + socks->tcp6sock = tcp6sock; + socks->udp4sock = udp4sock; + socks->udp6sock = udp6sock; } void |
Free forum by Nabble | Edit this page |