From b7950256137a5b03fbf9faf8c6e42b056bf93973 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 22 Jul 2026 04:41:40 +0900 Subject: [PATCH] kpasswd: add sd_notify start/stop signals This commit adds optional integration with systemd's state notifification system. When built with libsystemd, kpasswdd notifies systemd once it is ready to serve and when it begins a clean shutdown, as well as publishing a status line reporting how many password change requests have been processed. --- kpasswd/Makefile.am | 5 ++- kpasswd/kpasswdd.c | 89 ++++++++++++++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 27 deletions(-) diff --git a/kpasswd/Makefile.am b/kpasswd/Makefile.am index 771e9b402..5d3b08a1d 100644 --- a/kpasswd/Makefile.am +++ b/kpasswd/Makefile.am @@ -24,7 +24,10 @@ kpasswdd_LDADD = \ $(LDADD) \ $(LIB_pidfile) \ $(LIB_dlopen) \ - $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB) + $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB) \ + $(SYSTEMD_LIBS) + +kpasswdd_CFLAGS = $(SYSTEMD_CFLAGS) LDADD = $(top_builddir)/lib/krb5/libkrb5.la \ $(top_builddir)/lib/asn1/libasn1.la \ diff --git a/kpasswd/kpasswdd.c b/kpasswd/kpasswdd.c index 43a733589..8166c5a94 100644 --- a/kpasswd/kpasswdd.c +++ b/kpasswd/kpasswdd.c @@ -41,6 +41,11 @@ RCSID("$Id$"); #include #include #include +#ifdef HAVE_SYSTEMD +#include +/* how often (seconds) to refresh the sd_notify STATUS line while idle */ +#define STATUS_INTERVAL 30 +#endif static krb5_context context; static krb5_log_facility *log_facility; @@ -745,38 +750,70 @@ doit(krb5_keytab keytab, int port) roken_detach_finish(NULL, daemon_child); - while (exit_flag == 0) { - krb5_ssize_t retx; - fd_set fdset = real_fdset; + { + struct timeval *tmoutp = NULL; +#ifdef HAVE_SYSTEMD + unsigned long nrequests = 0; + struct timeval tmout; - retx = select(maxfd + 1, &fdset, NULL, NULL, NULL); - if (retx < 0) { - if (errno == EINTR) - continue; - else - krb5_err(context, 1, errno, "select"); - } - for (i = 0; i < n; ++i) - if (FD_ISSET(sockets[i], &fdset)) { - u_char buf[BUFSIZ]; - socklen_t addrlen = sizeof(__ss); + tmoutp = &tmout; + sd_notify(0, "READY=1"); + sd_notifyf(0, "STATUS=Serving; %lu password change request(s) processed", + nrequests); +#endif - retx = recvfrom(sockets[i], buf, sizeof(buf), 0, - sa, &addrlen); - if (retx < 0) { - if (errno == EINTR) - break; - else - krb5_err(context, 1, errno, "recvfrom"); - } + while (exit_flag == 0) { + krb5_ssize_t retx; + fd_set fdset = real_fdset; - process(keytab, sockets[i], - &addrs.val[i], - sa, addrlen, - buf, retx); +#ifdef HAVE_SYSTEMD + tmout.tv_sec = STATUS_INTERVAL; + tmout.tv_usec = 0; +#endif + retx = select(maxfd + 1, &fdset, NULL, NULL, tmoutp); + if (retx < 0) { + if (errno == EINTR) + continue; + else + krb5_err(context, 1, errno, "select"); } +#ifdef HAVE_SYSTEMD + if (retx == 0) { + /* select timed out: refresh our systemd status line */ + sd_notifyf(0, "STATUS=Serving; %lu password change request(s) " + "processed", nrequests); + continue; + } +#endif + for (i = 0; i < n; ++i) + if (FD_ISSET(sockets[i], &fdset)) { + u_char buf[BUFSIZ]; + socklen_t addrlen = sizeof(__ss); + + retx = recvfrom(sockets[i], buf, sizeof(buf), 0, + sa, &addrlen); + if (retx < 0) { + if (errno == EINTR) + break; + else + krb5_err(context, 1, errno, "recvfrom"); + } + + process(keytab, sockets[i], + &addrs.val[i], + sa, addrlen, + buf, retx); +#ifdef HAVE_SYSTEMD + nrequests++; +#endif + } + } } +#ifdef HAVE_SYSTEMD + sd_notify(0, "STOPPING=1"); +#endif + for (i = 0; i < n; ++i) close(sockets[i]); free(sockets);