diff --git a/ChangeLog.md b/ChangeLog.md index aea7a88a..9201934e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -13,6 +13,9 @@ make sure to read the whole changelog when upgrading. ### Changes * Introducing Finit progress 𝓜𝓸𝓭𝓮𝓻𝓷 +* Removed built-in inetd super server. If you need this functionality, + use an external inetd, like xinetd, instead. A pull request for a + stand-alone inetd, like watchdogd and getty, is most welcome! * Incompatible `configure` script changes, i.e., you must give proper path arguments to the script, no more guessing just GNU defaults. There are examples in the documentation and the `contrib/` section @@ -76,8 +79,7 @@ make sure to read the whole changelog when upgrading. * Drop `--enable-rw-roots` configure option, use `rw` for your `/` partition in `/etc/fstab` instead to trigger remount at boot * Drop default tty speed (38400) and use 0 (kernel default) instead -* Make `:ID` optional for real, use NULL/zero internally and only - force :ID (numbered) for inetd services, this allows ... +* Make `:ID` optional, use NULL/zero internally this allows ... * Handle use-cases where multiple services share the same PID filem and thus the same condition path, e.g. different instances for different runlevels. Allow custom condition path with `name:foo` @@ -95,14 +97,8 @@ make sure to read the whole changelog when upgrading. * Fix #96: Start udevd as a proper service * Ensure we track run commands as well as task/service, once per runlevel -* Fix #98: FTBFS with `--disable-inetd` -* Make sure to unblock UDP inetd services when connection terminates. - Regression introduced in v3.1 * Ensure run/tasks also go to stopping state on exit, like services, otherwise it is unnecessarily hard to restart them -* Fix #99: Do not try to `SIGKILL` inetd services, they are not backed - by a PID. This caused a use after free issue crashing finit. Found - and fixed by Tobias Waldekranz, Westermo * Fix missing OS/Finit title bug, adds leading newline before banner * Remove "Failed connecting to watchdog ..." error message on systems that do not have a watchdog @@ -110,23 +106,14 @@ make sure to read the whole changelog when upgrading. not yet exist (symlink to `/run`). Added compat layer for access * Fix #103: Register multiple getty if `@console` resolves to >1 TTY, * Fix #105: Only remove /etc/nologin when moving from runlevel 0, 1, 6 -* Fix #106: Don't mark inetd connections for deletion at .conf reload. - Fixed by Jonas Johansson, Westermo -* Fix #107: Stop spawned inetd conncections when stopping inetd service. Fixed by Jonas Johansson, Westermo * Fix #109: Support for PID files in sub-directories to `/var/run` * Handle rename of PID files, by Robert Andersson, Atlas Copco -* Fix #111: Only restart inetd services when necessary. E.g., if the - listening interface is changed. Only stop established connections - which are no longer allowed, i.e. do not touch already allowed - established connections. Fixed by Jonas Johansson, Westermo * Fix #120: Redirect `stdin` to `/dev/null` for services by default * Fix #122: Switch to `nanosleep()` to achieve "signal safe" sleep, fixed by Jacques de Laval, Westermo * Fix #124: Lingering processes in process group when session leader exits. E.g., lingering `logit` processes when parent dies -* Fix: update inetd service args on config change. Found and fixed by - Petrus Hellgren, Westermo * Fix service name matching, e.g. for condition handling, may match with wrong service, by Jonas Holmberg, Westermo * Run all run-parts scripts using `/bin/sh -c foo` just like the standard diff --git a/configure.ac b/configure.ac index 293073f4..212b5aa4 100644 --- a/configure.ac +++ b/configure.ac @@ -74,10 +74,6 @@ AC_ARG_ENABLE(redirect, AS_HELP_STRING([--enable-redirect], [Redirect service output to /dev/null, default: no]),,[ enable_redirect_output=no]) -AC_ARG_ENABLE(inetd, - AS_HELP_STRING([--disable-inetd], [Disable built-in inetd super server, default enabled]),,[ - enable_inetd=yes]) - AC_ARG_ENABLE(logit, AS_HELP_STRING([--disable-logit], [Disable logit, used for log redirection, default: enable]),,[ enable_logit=yes]) @@ -99,11 +95,6 @@ enable_all_plugins=auto AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl]) AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus]) AC_PLUGIN([hotplug], [yes], [Setup and start udev or mdev hotplug daemon]) -AC_PLUGIN([inetd-echo], [no], [Inetd plugin: echo server, RFC862]) -AC_PLUGIN([inetd-chargen], [no], [Inetd plugin: character generator, RFC864]) -AC_PLUGIN([inetd-daytime], [no], [Inetd plugin: daytime server, RFC867]) -AC_PLUGIN([inetd-discard], [no], [Inetd plugin: discard server, RFC863]) -AC_PLUGIN([inetd-time], [no], [Inetd plugin: time (rdate) server, RFC868]) AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load]) AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf]) AC_PLUGIN([x11-common], [no], [Console setup (for X)]) @@ -174,10 +165,6 @@ AS_IF([test "x$enable_redirect" = "xyes"], [ AC_DEFINE(REDIRECT_OUTPUT, 1, [Enable redirection of service output to /dev/null])]) ### Disable features ########################################################################### -AS_IF([test "x$enable_inetd" != "xno"], [ - enable_inetd="yes" - AC_DEFINE(INETD_ENABLED, 1, [Enable built-in inetd])]) - AS_IF([test "x$enable_logit" != "xno"], [ AC_DEFINE(LOGIT_ENABLED, 1, [Enable logit tool, used for log redirection by Finit])]) @@ -232,7 +219,6 @@ AS_IF([test "x$with_random_seed" != "xno"], [ # Control build with automake flags AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"]) -AM_CONDITIONAL(INETD, [test "x$enable_inetd" = "xyes"]) AM_CONDITIONAL(WATCHDOGD, [test "x$enable_watchdog" = "xyes"]) AM_CONDITIONAL(LOGIT, [test "x$enable_logit" = "xyes"]) AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"]) @@ -278,7 +264,6 @@ Behavior: Optional features: Install doc/..........: $enable_doc Install contrib/......: $enable_contrib - Built-in inetd........: $enable_inetd Built-in watchdogd....: $enable_watchdog Built-in logrotate....: $enable_logrotate Scripting tool logit..: $enable_logit diff --git a/plugins/Makefile.am b/plugins/Makefile.am index cb0022ee..d1db541c 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -21,28 +21,6 @@ if BUILD_HOTPLUG_PLUGIN libplug_la_SOURCES += hotplug.c endif -if INETD -if BUILD_INETD_ECHO_PLUGIN -libplug_la_SOURCES += echo.c -endif - -if BUILD_INETD_CHARGEN_PLUGIN -libplug_la_SOURCES += chargen.c -endif - -if BUILD_INETD_DAYTIME_PLUGIN -libplug_la_SOURCES += daytime.c -endif - -if BUILD_INETD_DISCARD_PLUGIN -libplug_la_SOURCES += discard.c -endif - -if BUILD_INETD_TIME_PLUGIN -libplug_la_SOURCES += time.c -endif -endif - if BUILD_MODULES_LOAD_PLUGIN libplug_la_SOURCES += modules-load.c endif @@ -70,28 +48,6 @@ if BUILD_HOTPLUG_PLUGIN pkglib_LTLIBRARIES += hotplug.la endif -if INETD -if BUILD_INETD_ECHO_PLUGIN -pkglib_LTLIBRARIES += echo.la -endif - -if BUILD_INETD_CHARGEN_PLUGIN -pkglib_LTLIBRARIES += chargen.la -endif - -if BUILD_INETD_DAYTIME_PLUGIN -pkglib_LTLIBRARIES += daytime.la -endif - -if BUILD_INETD_DISCARD_PLUGIN -pkglib_LTLIBRARIES += discard.la -endif - -if BUILD_INETD_TIME_PLUGIN -pkglib_LTLIBRARIES += time.la -endif -endif - if BUILD_MODULES_LOAD_PLUGIN pkglib_LTLIBRARIES += modules-load.la endif diff --git a/plugins/chargen.c b/plugins/chargen.c deleted file mode 100644 index 53cf7dbc..00000000 --- a/plugins/chargen.c +++ /dev/null @@ -1,120 +0,0 @@ -/* Optional inetd plugin for the Character Generator Protocol, RFC 864 - * - * Copyright (c) 2016-2021 Joachim Wiberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include /* STDIN_FILENO */ -#include - -#include "plugin.h" - -#define NAME "chargen" -#define PATTERN "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ " - -static char *generator(char *buf, size_t buflen) -{ - size_t num, len, width = 72; - static size_t pos = 0; - const char pattern[] = PATTERN; - - if (buflen < width) - width = buflen; - - len = width; - if (len + 3 > buflen) - len = buflen - 3; - if (pos + len > sizeof(pattern)) { - num = sizeof(pattern) - pos; - len -= num; - } else { - num = width; - if (num + 3 > buflen) - num = buflen - 3; - len = 0; - } - - strncpy(buf, &pattern[pos], num--); - if (len++) - strncpy(&buf[num], pattern, len); - strlcat(buf, "\r\n", width); - - if (++pos >= sizeof(pattern) - 1) - pos = 0; - - return buf; -} - -static int recv_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t *sa_len) -{ - len = recvfrom(sd, buf, len, MSG_DONTWAIT, sa, sa_len); - if (-1 == len) - return -1; /* On error, close connection. */ - - if (inetd_check_loop(sa, *sa_len, NAME)) - return -1; - - return 0; -} - -static int send_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t sa_len) -{ - char *pattern = generator(buf, len); - - return sendto(sd, pattern, strlen(pattern), MSG_DONTWAIT, sa, sa_len); -} - -static int cb(int type) -{ - int sd = STDIN_FILENO; - char buf[BUFSIZ]; - struct sockaddr_storage sa; - socklen_t sa_len = sizeof(sa); - - if (recv_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, &sa_len)) - return -1; - - return send_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, sa_len); -} - -static plugin_t plugin = { - .name = NAME, /* Must match the inetd /etc/services entry */ - .inetd = { - .cmd = cb - }, -}; - -PLUGIN_INIT(plugin_init) -{ - plugin_register(&plugin); -} - -PLUGIN_EXIT(plugin_exit) -{ - plugin_unregister(&plugin); -} - -/** - * Local Variables: - * indent-tabs-mode: t - * c-file-style: "linux" - * End: - */ diff --git a/plugins/daytime.c b/plugins/daytime.c deleted file mode 100644 index d187bda7..00000000 --- a/plugins/daytime.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Optional inetd plugin for Daytime Protocol, RFC 867 - * - * Copyright (c) 2016-2021 Joachim Wiberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include /* STDIN_FILENO */ -#include - -#include "plugin.h" - -#define NAME "daytime" - - -static char *daytime(char *buf, size_t len) -{ - time_t t; - struct tm *tmp; - - t = time(NULL); - tmp = localtime(&t); - - memset(buf, 0, len); - strftime(buf, len, "%a, %B %d, %Y %T-%Z", tmp); - - return buf; -} - -static int recv_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t *sa_len) -{ - len = recvfrom(sd, buf, sizeof(buf), MSG_DONTWAIT, sa, sa_len); - if (-1 == len) - return -1; /* On error, close connection. */ - - if (inetd_check_loop(sa, *sa_len, NAME)) - return -1; - - return 0; -} - -static int send_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t sa_len) -{ - char *now = daytime(buf, len); - - return sendto(sd, now, strlen(now), MSG_DONTWAIT, sa, sa_len); -} - -static int cb(int type) -{ - int sd = STDIN_FILENO; - char buf[BUFSIZ]; - struct sockaddr_storage sa; - socklen_t sa_len = sizeof(sa); - - if (recv_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, &sa_len)) - return -1; - - return send_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, sa_len); -} - -static plugin_t plugin = { - .name = NAME, /* Must match the inetd /etc/services entry */ - .inetd = { - .cmd = cb - } -}; - -PLUGIN_INIT(plugin_init) -{ - plugin_register(&plugin); -} - -PLUGIN_EXIT(plugin_exit) -{ - plugin_unregister(&plugin); -} - -/** - * Local Variables: - * indent-tabs-mode: t - * c-file-style: "linux" - * End: - */ diff --git a/plugins/discard.c b/plugins/discard.c deleted file mode 100644 index 1ad923a9..00000000 --- a/plugins/discard.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Optional inetd plugin for the Discard Protocol, RFC 863 - * - * Copyright (c) 2016-2021 Joachim Wiberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include /* STDIN_FILENO */ -#include - -#include "plugin.h" - -static int cb(int type) -{ - int sd = STDIN_FILENO; - char buf[BUFSIZ]; - ssize_t len; - struct sockaddr_storage sa; - socklen_t sa_len = sizeof(sa); - - len = recvfrom(sd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *)&sa, &sa_len); - if (-1 == len) - return -1; /* On error, close connection. */ - - return 0; -} - -static plugin_t plugin = { - .name = "discard", /* Must match the inetd /etc/services entry */ - .inetd = { - .cmd = cb - }, -}; - -PLUGIN_INIT(plugin_init) -{ - plugin_register(&plugin); -} - -PLUGIN_EXIT(plugin_exit) -{ - plugin_unregister(&plugin); -} - -/** - * Local Variables: - * indent-tabs-mode: t - * c-file-style: "linux" - * End: - */ diff --git a/plugins/echo.c b/plugins/echo.c deleted file mode 100644 index 5b4bd328..00000000 --- a/plugins/echo.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Optional inetd plugin for the Echo Protocol, RFC 862 - * - * Copyright (c) 2016-2021 Joachim Wiberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include /* STDIN_FILENO */ -#include - -#include "plugin.h" - -#define NAME "echo" - -static int recv_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t *sa_len) -{ - len = recvfrom(sd, buf, sizeof(buf), MSG_DONTWAIT, sa, sa_len); - if (-1 == len) - return -1; /* On error, close connection. */ - - if (inetd_check_loop(sa, *sa_len, NAME)) - return -1; - - return len; -} - -static int cb(int type) -{ - int sd = STDIN_FILENO; - char buf[BUFSIZ]; - ssize_t len; - struct sockaddr_storage sa; - socklen_t sa_len = sizeof(sa); - - len = recv_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, &sa_len); - if (-1 == len) - return -1; /* On error, close connection. */ - - return sendto(sd, buf, len, MSG_DONTWAIT, (struct sockaddr *)&sa, sa_len); -} - -static plugin_t plugin = { - .name = NAME, /* Must match the inetd /etc/services entry */ - .inetd = { - .cmd = cb - }, -}; - -PLUGIN_INIT(plugin_init) -{ - plugin_register(&plugin); -} - -PLUGIN_EXIT(plugin_exit) -{ - plugin_unregister(&plugin); -} - -/** - * Local Variables: - * indent-tabs-mode: t - * c-file-style: "linux" - * End: - */ diff --git a/plugins/pidfile.c b/plugins/pidfile.c index 7291f1b6..277351af 100644 --- a/plugins/pidfile.c +++ b/plugins/pidfile.c @@ -287,7 +287,7 @@ static void pidfile_reconf(void *arg) * WAITING to RUNNING will reassert their conditions in that loop, * which in turn may unlock other services, and so on. */ - service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_RUNTASK | SVC_TYPE_INETD); + service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_RUNTASK); } static void pidfile_init(void *arg) diff --git a/plugins/time.c b/plugins/time.c deleted file mode 100644 index 23d8ad1d..00000000 --- a/plugins/time.c +++ /dev/null @@ -1,116 +0,0 @@ -/* Optional inetd plugin for Time Protocol (rdate), RFC 868 - * - * Copyright (c) 2015-2021 Joachim Wiberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include /* STDIN_FILENO */ -#include - -#include "plugin.h" - -#define NAME "time" - -/* UNIX epoch starts midnight, 1st Jan, 1970 */ -#define EPOCH_OFFSET 2208988800ULL - -/* Return number of seconds since midnight, 1st Jan, 1900 */ -static char *rfctime(char *buf, size_t *len) -{ - time_t now; - - now = time(NULL); - if ((time_t)-1 == now) - return NULL; - - /* - * Account for UNIX epoch offset, and - * convert to network byte order - */ - now += EPOCH_OFFSET; - now = htonl(now); - - *len = sizeof(now); - memcpy(buf, &now, *len); - - return buf; -} - -static int recv_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t *sa_len) -{ - len = recvfrom(sd, buf, sizeof(buf), MSG_DONTWAIT, sa, sa_len); - if (-1 == len) - return -1; /* On error, close connection. */ - - if (inetd_check_loop(sa, *sa_len, NAME)) - return -1; - - return 0; -} - -static int send_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t sa_len) -{ - char *now; - - now = rfctime(buf, (size_t *)&len); - if (!now) - return -1; /* On error, close connection. */ - - return sendto(sd, now, len, MSG_DONTWAIT, sa, sa_len); -} - -static int cb(int type) -{ - int sd = STDIN_FILENO; - char buf[BUFSIZ]; - struct sockaddr_storage sa; - socklen_t sa_len = sizeof(sa); - - if (recv_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, &sa_len)) - return -1; /* On error, close connection. */ - - return send_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, sa_len); -} - -static plugin_t plugin = { - .name = NAME, /* Must match the inetd /etc/services entry */ - .inetd = { - .cmd = cb - } -}; - -PLUGIN_INIT(plugin_init) -{ - plugin_register(&plugin); -} - -PLUGIN_EXIT(plugin_exit) -{ - plugin_unregister(&plugin); -} - -/** - * Local Variables: - * indent-tabs-mode: t - * c-file-style: "linux" - * End: - */ diff --git a/src/Makefile.am b/src/Makefile.am index 63a33cce..c8464fcf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,10 +39,7 @@ finit_SOURCES = api.c cgroup.c cgroup.h \ tty.c tty.h \ util.c util.h \ utmp-api.c utmp-api.h -pkginclude_HEADERS = cond.h finit.h helpers.h inetd.h log.h plugin.h svc.h -if INETD -finit_SOURCES += inetd.c inetd.h -endif +pkginclude_HEADERS = cond.h finit.h helpers.h log.h plugin.h svc.h finit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99 finit_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS) diff --git a/src/api.c b/src/api.c index a692aedc..35ac920c 100644 --- a/src/api.c +++ b/src/api.c @@ -158,19 +158,6 @@ static svc_t *do_find(char *buf, size_t len) return svc_find_by_nameid(input, id); } -#ifdef INETD_ENABLED -static int do_query_inetd(char *buf, size_t len) -{ - svc_t *svc; - - svc = do_find(buf, len); - if (!svc || !svc_is_inetd(svc)) - return 1; - - return inetd_filter_str(&svc->inetd, buf, len); -} -#endif /* INETD_ENABLED */ - typedef struct { char *event; void (*cb)(void); @@ -291,14 +278,6 @@ static void api_cb(uev_t *w, void *arg, int events) result = do_restart(rq.data, sizeof(rq.data)); break; -#ifdef INETD_ENABLED - case INIT_CMD_QUERY_INETD: - _d("query inetd"); - strterm(rq.data, sizeof(rq.data)); - result = do_query_inetd(rq.data, sizeof(rq.data)); - break; -#endif - case INIT_CMD_GET_RUNLEVEL: _d("get runlevel"); rq.runlevel = runlevel; diff --git a/src/conf.c b/src/conf.c index 51d0bea0..8f953f1c 100644 --- a/src/conf.c +++ b/src/conf.c @@ -500,16 +500,6 @@ static void parse_dynamic(char *line, struct rlimit rlimit[], char *file) return; } - /* Classic inetd service */ - if (MATCH_CMD(line, "inetd ", x)) { -#ifdef INETD_ENABLED - service_register(SVC_TYPE_INETD, x, rlimit, file); -#else - _e("Finit built with inetd support disabled, cannot register service inetd %s!", x); -#endif - return; - } - /* Read resource limits */ if (MATCH_CMD(line, "rlimit ", x)) { conf_parse_rlimit(x, rlimit); @@ -574,8 +564,8 @@ static int parse_conf(char *file) /* * Get current global limits, which may be overridden from both - * finit.conf, for Finit and its services like inetd+getty, and - * *.conf in finit.d/, for each service(s) listed there. + * finit.conf, for Finit and its services like getty+watchdogd, + * and *.conf in finit.d/, for each service(s) listed there. */ for (int i = 0; i < RLIMIT_NLIMITS; i++) getrlimit(i, &global_rlimit[i]); diff --git a/src/inetd.c b/src/inetd.c deleted file mode 100644 index 096700fe..00000000 --- a/src/inetd.c +++ /dev/null @@ -1,803 +0,0 @@ -/* Classic inetd services launcher for Finit - * - * Copyright (c) 2015-2021 Joachim Wiberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "finit.h" -#include "inetd.h" -#include "helpers.h" -#include "private.h" -#include "service.h" - -#define ENABLE_SOCKOPT(sd, level, opt) \ - do { \ - int val = 1; \ - if (setsockopt(sd, level, opt, &val, sizeof(val)) < 0) \ - logit(LOG_CRIT, "Failed enabling %s on %s service", \ - #opt, inetd->name); \ - } while (0); - -/* Peek into SOCK_DGRAM socket to figure out where an inbound packet comes from. */ -static int inetd_dgram_peek(int sd, char *ifname, size_t len) -{ - struct cmsghdr *cmsg; - struct msghdr msgh; - char cmbuf[0x100]; - - memset(ifname, 0, len); - memset(&msgh, 0, sizeof(msgh)); - msgh.msg_control = cmbuf; - msgh.msg_controllen = sizeof(cmbuf); - - if (recvmsg(sd, &msgh, MSG_PEEK) < 0) - return -1; - - for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg; cmsg = CMSG_NXTHDR(&msgh, cmsg)) { - struct in_pktinfo *ipi = (struct in_pktinfo *)CMSG_DATA(cmsg); - char tmp[IF_NAMESIZE + 1] = { 0 }; - - if (cmsg->cmsg_level != SOL_IP || cmsg->cmsg_type != IP_PKTINFO) - continue; - - if_indextoname(ipi->ipi_ifindex, tmp); - strlcpy(ifname, tmp, len); - - return 0; - } - - return -1; -} - -/* Peek into SOCK_DGRAM socket to figure out where an inbound packet comes from. */ -static void inetd_dgram_drop(int sd, const char *ifname) -{ - char pkt_interface[IF_NAMESIZE + 1]; - char buf[BUFSIZ]; - - while (1) { - inetd_dgram_peek(sd, pkt_interface, sizeof(pkt_interface)); - if (string_compare(pkt_interface, ifname)) { - if (recv(sd, buf, sizeof(buf), 0) < 0) - break; - continue; - } - break; - } -} - -/* Peek into SOCK_STREAM on accepted client socket to figure out inbound interface */ -static int inetd_stream_peek(int sd, char *ifname, size_t ilen) -{ - struct ifaddrs *ifaddr, *ifa; - struct sockaddr_in sin; - socklen_t len = sizeof(sin); - - memset(ifname, 0, ilen); - if (-1 == getsockname(sd, (struct sockaddr *)&sin, &len)) - return -1; - - if (-1 == getifaddrs(&ifaddr)) - return -1; - - for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { - size_t len = sizeof(struct in_addr); - struct sockaddr_in *iin; - - if (!ifa->ifa_addr) - continue; - - if (ifa->ifa_addr->sa_family != AF_INET) - continue; - - iin = (struct sockaddr_in *)ifa->ifa_addr; - if (!memcmp(&sin.sin_addr, &iin->sin_addr, len)) { - strlcpy(ifname, ifa->ifa_name, ilen); - break; - } - } - - freeifaddrs(ifaddr); - - return 0; -} - -static int get_stdin(svc_t *svc, char *iifname, size_t len) -{ - int stdin = svc->inetd.watcher.fd; - char ifname[IF_NAMESIZE + 1] = "UNKNOWN"; - - memset(iifname, 0, len); - if (svc->inetd.type == SOCK_STREAM) { - /* Open new client socket from server socket */ - stdin = accept(stdin, NULL, NULL); - if (stdin < 0) { - logit(LOG_CRIT, "Failed accepting inetd service %d/tcp", svc->inetd.port); - return -1; - } - - _d("New client socket %d accepted for inetd service %d/tcp", stdin, svc->inetd.port); - - inetd_stream_peek(stdin, ifname, sizeof(ifname)); - } else { /* SOCK_DGRAM */ - inetd_dgram_peek(stdin, ifname, sizeof(ifname)); - } - - if (!inetd_is_allowed(&svc->inetd, ifname)) { - logit(LOG_INFO, "Service %s on %s:%d is not allowed", svc->inetd.name, ifname, svc->inetd.port); - if (svc->inetd.type == SOCK_STREAM) - close(stdin); - else - inetd_dgram_drop(stdin, ifname); - - return -1; - } - - /* Return ingress interface */ - strlcpy(iifname, ifname, len); - - return stdin; -} - -/* Socket callback, looks up correct svc and starts it as an inetd service */ -static void socket_cb(uev_t *w, void *arg, int events) -{ - svc_t *svc = (svc_t *)arg, *task; - const char *conn = " connection"; - char iifname[IF_NAMESIZE + 1] = "UNKNOWN"; - char id[MAX_ID_LEN]; - int stdin; - - _d("%s: Got socket event ...", svc->cmd); - if (UEV_ERROR == events) { - logit(LOG_INFO, "%s: Socket error, aborting: %s", svc->cmd, strerror(errno)); - return; - } - - stdin = get_stdin(svc, iifname, sizeof(iifname)); - if (stdin < 0) { - logit(LOG_CRIT, "%s: Unable to accept incoming connection", svc->cmd); - return; - } - - /* - * Make sure to disable O_NONBLOCK on the descriptor before - * passing it to the inetd service, that's what is expected. - */ - if (fcntl(stdin, F_SETFL, fcntl(stdin, F_GETFL, 0) & ~O_NONBLOCK) < 0) { - logit(LOG_CRIT, "Failed disabling non-blocking on %s socket", svc->cmd); - if (svc->inetd.type == SOCK_STREAM) - close(stdin); - return; - } - - snprintf(id, sizeof(id), "%d", svc->inetd.next_id++); - task = svc_new(svc->cmd, id, SVC_TYPE_INETD_CONN); - if (!task) { - logit(LOG_CRIT, "%s: Unable to allocate service for inetd client", svc->cmd); - if (svc->inetd.type == SOCK_STREAM) - close(stdin); - return; - } - - if (!svc->inetd.forking) { - svc_busy(svc); - service_step(svc); - } - - /* Copy inherited attributes from inetd service's svc */ - task->runlevels = svc->runlevels; - - /* - * Only copy the most relevant parts of inetd, in particular we - * must *not* copy the watcher data to the clone! - */ - task->inetd.svc = svc; - task->inetd.cmd = svc->inetd.cmd; - task->inetd.type = svc->inetd.type; - - memcpy(task->rlimit, svc->rlimit, sizeof(task->rlimit)); - memcpy(task->cond, svc->cond, sizeof(task->cond)); - memcpy(task->username, svc->username, sizeof(task->username)); - memcpy(task->group, svc->group, sizeof(task->group)); - memcpy(task->args, svc->args, sizeof(task->args)); - strlcpy(task->desc, svc->desc, sizeof(task->desc) - strlen(conn)); - strlcat(task->desc, conn, sizeof(task->desc)); - strlcpy(task->iifname, iifname, sizeof(task->iifname)); - strlcpy(task->name, svc->name, sizeof(task->name)); - - task->stdin_fd = stdin; - service_step(task); -} - -/* - * Refuse service if the request specifies a reply port corresponding to any internal service. - * This is done as a defense against looping attacks; the remote IP address is logged. - * http://www.freebsd.org/cgi/man.cgi?inetd(8) - * https://svnweb.freebsd.org/base/head/usr.sbin/inetd/inetd.c?revision=298909&view=markup#l2094 - */ -int inetd_check_loop(struct sockaddr *sa, socklen_t len, char *name) -{ - svc_t *svc, *iter = NULL; - char pname[NI_MAXHOST]; - - for (svc = svc_inetd_iterator(&iter, 1); svc; svc = svc_inetd_iterator(&iter, 0)) { - inetd_t *i = &svc->inetd; - - if (!i->builtin || i->type != SOCK_DGRAM) - continue; - - if (((const struct sockaddr_in *)sa)->sin_port == i->port) { - getnameinfo(sa, len, pname, sizeof(pname), NULL, 0, NI_NUMERICHOST); - logit(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s", i->name, "UDP", name, "UDP", pname); - return 1; - } - } - - return 0; -} - -/* Launch Inet socket for service. - * TODO: Add filtering ALLOW/DENY per interface. - */ -static int spawn_socket(inetd_t *inetd) -{ - int sd; - socklen_t len = sizeof(struct sockaddr); - struct sockaddr_in s; - - if (!inetd->type) { - logit(LOG_CRIT, "Invalid inetd service %s, skipping ...", inetd->name); - return -EINVAL; - } - - _d("Spawning server socket for inetd %s, type %s ...", inetd->name, inetd->type == SOCK_STREAM ? "stream" : "dgram"); - sd = socket(AF_INET, inetd->type | SOCK_NONBLOCK | SOCK_CLOEXEC, inetd->proto); - if (-1 == sd) { - logit(LOG_CRIT, "Failed opening inetd socket type %d proto %d", inetd->type, inetd->proto); - return -errno; - } - - ENABLE_SOCKOPT(sd, SOL_SOCKET, SO_REUSEADDR); -#ifdef SO_REUSEPORT - ENABLE_SOCKOPT(sd, SOL_SOCKET, SO_REUSEPORT); -#endif - - memset(&s, 0, sizeof(s)); - s.sin_family = AF_INET; - s.sin_addr.s_addr = INADDR_ANY; - s.sin_port = htons(inetd->port); - if (bind(sd, (struct sockaddr *)&s, len) < 0) { - logit(LOG_CRIT, "Failed binding to port %d, maybe another %s server is already running?", - inetd->port, inetd->name); - close(sd); - return -errno; - } - - if (inetd->port) { - if (inetd->type == SOCK_STREAM) { - if (-1 == listen(sd, 10)) { - logit(LOG_CRIT, "Failed listening to inetd service %s", inetd->name); - close(sd); - return -errno; - } - } else { /* SOCK_DGRAM */ - /* Set extra sockopt to get ifindex from inbound packets */ - ENABLE_SOCKOPT(sd, SOL_IP, IP_PKTINFO); - } - } - - if (uev_io_init(ctx, &inetd->watcher, socket_cb, inetd->svc, sd, UEV_READ)) { - logit(LOG_CRIT, "Failed setting up inetd watcher for %s", inetd->name); - close(sd); - return -errno; - } - - - return 0; -} - -int inetd_start(inetd_t *inetd) -{ - int sd; - char buf[BUFSIZ]; - ssize_t len; - - sd = inetd->watcher.fd; - if (sd == -1) - return spawn_socket(inetd); - - /* Read anything lingering, or clean up socket after failure */ - len = recv(sd, buf, sizeof(buf), MSG_DONTWAIT); - if (len > 0) - _d("Read %zd lingering bytes from socket before (re)starting %s ...", len, inetd->svc->cmd); - - /* Restore O_NONBLOCK for socket */ - if (fcntl(sd, F_SETFL, fcntl(sd, F_GETFL, 0) | O_NONBLOCK)) { - logit(LOG_CRIT, "Cannot safely (re)start %s inetd service", inetd->svc->cmd); - return -errno; - } - - _d("Re-starting %s socket watcher ...", inetd->svc->cmd); - uev_io_start(&inetd->watcher); - - return 0; -} - -void inetd_stop_children(inetd_t *inetd, int check_allowed) -{ - svc_t *svc, *iter = NULL; - - svc = svc_job_iterator(&iter, 1, inetd->svc->job); - while (svc) { - if (!svc_is_inetd(svc)) { - if (!check_allowed || !inetd_is_allowed(inetd, svc->iifname)) { - svc_stop(svc); - service_step(svc); - } - } - svc = svc_job_iterator(&iter, 0, inetd->svc->job); - } -} - -void inetd_stop(inetd_t *inetd) -{ - if (!inetd || !inetd->svc) { - _e("Invalid inetd, cannot stop it..."); - return; - } - - if (inetd->watcher.fd != -1) { - _d("Stopping %s socket watcher ...", inetd->svc->cmd); - uev_io_stop(&inetd->watcher); - - /* - * For dgram inetd services we block the parent SVC - * and halt the watcher, so don't close the socket! - */ - if (!svc_is_busy(inetd->svc)) { - _d("Shutting down inet socket %d ...", inetd->watcher.fd); - close(inetd->watcher.fd); - inetd->watcher.fd = -1; - - inetd_stop_children(inetd, 0); - } - } -} - -static struct servent *fallback_service(char *service, char *proto) -{ - int service_num; - static struct servent lfs; - - service_num = fgetint("/etc/services", " \n\t", service); - if (service_num > 0) { - lfs.s_name = service; - lfs.s_port = htons(service_num); - lfs.s_proto = NULL; - if (!strcmp("tcp", proto) || !strcmp("udp", proto)) - lfs.s_proto = proto; - - return &lfs; - } - - return NULL; -} - -static struct servent *getent_service(char *service, char *proto) -{ - struct servent *ent; - -#ifdef ENABLE_STATIC - ent = fallback_service(service, proto); -#else - ent = getservbyname(service, proto); - if (!ent) - ent = fallback_service(service, proto); -#endif - return ent; -} - -static struct protoent *fallback_proto(char *proto) -{ - int proto_num; - static struct protoent lfp; - - proto_num = fgetint("/etc/protocols", " \n\t", proto); - if (proto_num > 0) { - lfp.p_name = proto; - lfp.p_proto = proto_num; - - return &lfp; - } - - return NULL; -} - -static struct protoent *getent_proto(char *proto) -{ - struct protoent *ent; - -#ifdef ENABLE_STATIC - ent = fallback_proto(proto); -#else - ent = getprotobyname(proto); - if (!ent) - ent = fallback_proto(proto); -#endif - return ent; -} - -static int getent(char *service, char *proto, struct servent **sv, struct protoent **pv) -{ - if (!fexist("/etc/services") || !fexist("/etc/protocols")) { - _w("Cannot register inetd %s/%s, system missing /etc/services or /etc/protocols", service, proto); - return errno = ECANCELED; - } - - *sv = getent_service(service, proto); - if (!*sv) { - const char *errstr; - static struct servent s; - - s.s_name = service; - s.s_port = strtonum(service, 1, UINT16_MAX, &errstr); - s.s_proto = NULL; - if (!strcmp("tcp", proto) || !strcmp("udp", proto)) - s.s_proto = proto; - - if (errstr || !s.s_proto) { - _e("Invalid/unknown inetd service, cannot create custom entry"); - return errno = EINVAL; - } - - _d("Creating cutom inetd service %s/%s", service, proto); - s.s_port = htons(s.s_port); - *sv = &s; - } - - if (pv && (*sv)->s_proto) { - *pv = getent_proto((*sv)->s_proto); - if (!*pv) { - _e("Cannot find proto %s, skipping ...", (*sv)->s_proto); - return errno = EINVAL; - } - } - - return 0; -} - -/* - * Find exact match. - */ -static inetd_filter_t *find_filter(inetd_t *inetd, char *ifname) -{ - inetd_filter_t *filter; - - if (!ifname) - ifname = "*"; - - TAILQ_FOREACH(filter, &inetd->filters, link) { - _d("Checking filters for %s: '%s' vs '%s' (exact match) ...", - inetd->name, filter->ifname, ifname); - - if (!strcmp(filter->ifname, ifname)) - return filter; - } - - return NULL; -} - -/* - * First try exact match, then fall back to any match. - */ -inetd_filter_t *inetd_filter_match(inetd_t *inetd, char *ifname) -{ - inetd_filter_t *filter = find_filter(inetd, ifname); - - if (filter) - return filter; - - TAILQ_FOREACH(filter, &inetd->filters, link) { - _d("Checking filters for %s: '%s' vs '%s' (any match) ...", - inetd->name, filter->ifname, ifname); - - if (!strcmp(filter->ifname, "*")) - return filter; - } - - return NULL; -} - -int inetd_flush(inetd_t *inetd) -{ - inetd_filter_t *filter, *next; - - TAILQ_FOREACH_SAFE(filter, &inetd->filters, link, next) { - TAILQ_REMOVE(&inetd->filters, filter, link); - free(filter); - } - - return 0; -} - -/* Poor man's tcpwrappers filtering */ -int inetd_allow(inetd_t *inetd, char *ifname) -{ - inetd_filter_t *filter; - - if (!inetd) - return errno = EINVAL; - - if (!ifname) - ifname = "*"; - - filter = inetd_filter_match(inetd, ifname); - if (filter) { - _d("Filter %s for inetd %s already exists, skipping ...", ifname, inetd->name); - return 0; - } - - _d("Allow iface %s for service %s (port %d)", ifname, inetd->name, inetd->port); - filter = calloc(1, sizeof(*filter)); - if (!filter) { - _e("Out of memory, cannot add filter to service %s", inetd->name); - return errno = ENOMEM; - } - - filter->deny = 0; - strlcpy(filter->ifname, ifname, sizeof(filter->ifname)); - TAILQ_INSERT_TAIL(&inetd->filters, filter, link); - - return 0; -} - -int inetd_deny(inetd_t *inetd, char *ifname) -{ - inetd_filter_t *filter; - - if (!inetd) - return errno = EINVAL; - - if (!ifname) - ifname = "*"; - - filter = find_filter(inetd, ifname); - if (filter) { - _d("%s filter %s for inetd %s already exists, cannot set deny filter for same, skipping ...", - filter->deny ? "Deny" : "Allow", ifname, inetd->name); - return 1; - } - - _d("Deny iface %s for service %s (port %d)", ifname, inetd->name, inetd->port); - filter = calloc(1, sizeof(*filter)); - if (!filter) { - _e("Out of memory, cannot add filter to service %s", inetd->name); - return errno = ENOMEM; - } - - filter->deny = 1; - strlcpy(filter->ifname, ifname, sizeof(filter->ifname)); - TAILQ_INSERT_TAIL(&inetd->filters, filter, link); - - return 0; -} - -int inetd_is_allowed(inetd_t *inetd, char *ifname) -{ - inetd_filter_t *filter; - - if (!inetd) { - errno = EINVAL; - return 0; - } - - filter = inetd_filter_match(inetd, ifname); - if (filter) { - _d("Found matching filter for %s, deny: %d ... ", inetd->name, filter->deny); - return !filter->deny; - } - - _d("No matching filter for %s ... ", inetd->name); - - return 0; -} - -int inetd_match(inetd_t *inetd, char *service, char *proto) -{ - struct servent *sv = NULL; - struct protoent *pv = NULL; - - if (!inetd || !service || !proto) - return errno = EINVAL; - - if (strncmp(inetd->name, service, sizeof(inetd->name))) - return 0; - - if (getent(service, proto, &sv, &pv)) - return 0; - - if (inetd->proto == pv->p_proto && - inetd->port == ntohs(sv->s_port)) - return 1; - - return 0; -} - -/* Compose presentable string of inetd filters: !eth0,eth1,eth2,!eth3 */ -int inetd_filter_str(inetd_t *inetd, char *str, size_t len) -{ - int prev = 0; - char buf[42]; - inetd_filter_t *filter; - - if (!inetd || !str || len <= 0) { - _e("Dafuq?"); - return 1; - } - - snprintf(str, len, "%s allow %s ", inetd->name, - inetd->type == SOCK_DGRAM ? "UDP" : "TCP"); - TAILQ_FOREACH(filter, &inetd->filters, link) { - char ifname[IFNAMSIZ]; - - if (filter->deny) - continue; - - if (!strlen(filter->ifname)) - snprintf(ifname, sizeof(ifname), "*"); - else - strlcpy(ifname, filter->ifname, sizeof(ifname)); - - snprintf(buf, sizeof(buf), "%s%s:%d", prev ? "," : "", - ifname, inetd->port); - prev = 1; - strlcat(str, buf, len); - } - - prev = 0; - TAILQ_FOREACH(filter, &inetd->filters, link) { - char ifname[IFNAMSIZ]; - - if (!filter->deny) - continue; - if (!prev) { - snprintf(buf, sizeof(buf), " deny "); - strlcat(str, buf, len); - } - - if (!strlen(filter->ifname)) - snprintf(ifname, sizeof(ifname), "*"); - else - strlcpy(ifname, filter->ifname, sizeof(ifname)); - - snprintf(buf, sizeof(buf), "%s%s", prev ? "," : "", ifname); - prev = 1; - strlcat(str, buf, len); - } - - return 0; -} - -svc_t *inetd_find_svc(char *path, char *service, char *proto) -{ - svc_t *svc, *iter = NULL; - - for (svc = svc_inetd_iterator(&iter, 1); svc; svc = svc_inetd_iterator(&iter, 0)) { - if (strncmp(path, svc->cmd, strlen(svc->cmd))) - continue; - - if (inetd_match(&svc->inetd, service, proto)) { - _d("Found a matching inetd svc for %s %s %s", path, service, proto); - return svc; - } - } - - return NULL; -} - -/* - * This function is called to add a new, unique, inetd service. When an - * ifname is given as argument this means *only* run service on this - * interface. If a similar service runs on another port, this function - * must add this ifname as "deny" to that other service. - * - * Example: - * inetd ssh@eth0:222/tcp nowait [2345] /usr/sbin/sshd -i - * inetd ssh/tcp nowait [2345] /usr/sbin/sshd -i - * - * In this example eth0:222 is very specific, so when ssh/tcp (default) - * is added we must find the previous 'ssh' service and add its eth0 as - * deny, so we don't accept port 22 session on eth0. - * - * In the reverse case, where the default (ssh/tcp) entry is listed - * before the specific (eth0:222), the new inetd service must find the - * (any!) previous rule and add its ifname to their deny list. - * - * If equivalent service exists already service_register() will instead call - * inetd_allow(). - */ -int inetd_new(inetd_t *inetd, char *name, char *service, char *proto, int forking, svc_t *svc) -{ - int result; - struct servent *sv = NULL; - struct protoent *pv = NULL; - - if (!inetd || !service || !proto) - return errno = EINVAL; - - result = getent(service, proto, &sv, &pv); - if (result) - return result; - - /* Setup defaults */ - inetd->std = 1; - inetd->port = ntohs(sv->s_port); - inetd->proto = pv->p_proto; - inetd->forking = !!forking; - inetd->next_id = 2; - if (!name) - name = service; - strlcpy(inetd->name, name, sizeof(inetd->name)); - TAILQ_INIT(&inetd->filters); - - /* Naïve mapping tcp->stream, udp->dgram, other->dgram */ - if (!strcasecmp(sv->s_proto, "tcp")) - inetd->type = SOCK_STREAM; - else - inetd->type = SOCK_DGRAM; - - if (inetd->type == SOCK_DGRAM && inetd->forking) { - logit(LOG_WARNING, "%s: 'nowait' is not applicable on UDP services, ignoring", svc->cmd); - inetd->forking = 0; - } - - /* Reset descriptor, used internally */ - inetd->watcher.fd = -1; - - /* Setup socket callback argument */ - inetd->svc = svc; - - _d("New service %s (default port %d proto %s:%d)", name, inetd->port, sv->s_proto, pv->p_proto); - - return 0; -} - -int inetd_del(inetd_t *inetd) -{ - svc_unblock(inetd->svc); - inetd_stop(inetd); - - return inetd_flush(inetd); -} - -/** - * Local Variables: - * indent-tabs-mode: t - * c-file-style: "linux" - * End: - */ diff --git a/src/inetd.h b/src/inetd.h deleted file mode 100644 index 00975df9..00000000 --- a/src/inetd.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Classic inetd services launcher for Finit - * - * Copyright (c) 2015-2021 Joachim Wiberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef FINIT_INETD_H_ -#define FINIT_INETD_H_ - -#include -#include -#include -#include /* BSD sys/queue.h API */ - -typedef struct svc svc_t; - -typedef struct inetd_filter { - TAILQ_ENTRY(inetd_filter) link; - int deny; /* 0:allow, 1:deny */ - char ifname[IFNAMSIZ]; /* E.g., eth0 */ -} inetd_filter_t; - -typedef struct { - uev_t watcher; - svc_t *svc; /* svc_t pointer for the socket callback */ - - int type; /* Socket type: SOCK_STREAM/SOCK_DGRAM */ - int std; /* Standard proto/port from /etc/services */ - int proto; - int port; - int forking; - int builtin; /* Set by built-in inetd services only */ - int next_id; /* Next child job's id */ - char name[10]; - int (*cmd)(int type); /* internal inetd service, like 'time' */ - - TAILQ_HEAD(, inetd_filter) filters; -} inetd_t; - -int inetd_check_loop(struct sockaddr *sa, socklen_t len, char *name); - -int inetd_start (inetd_t *inetd); -void inetd_stop (inetd_t *inetd); -void inetd_stop_children (inetd_t *inetd, int check_allowed); - -int inetd_new (inetd_t *inetd, char *name, char *service, char *proto, int forking, svc_t *svc); -int inetd_del (inetd_t *inetd); - -svc_t *inetd_find_svc (char *path, char *service, char *proto); - -int inetd_match (inetd_t *inetd, char *service, char *proto); -int inetd_filter_str(inetd_t *inetd, char *str, size_t len); - -int inetd_flush (inetd_t *inetd); -int inetd_allow (inetd_t *inetd, char *ifname); -int inetd_deny (inetd_t *inetd, char *ifname); -int inetd_is_allowed(inetd_t *inetd, char *ifname); - -#endif /* FINIT_INETD_H_ */ - -/** - * Local Variables: - * indent-tabs-mode: t - * c-file-style: "linux" - * End: - */ diff --git a/src/initctl.c b/src/initctl.c index 445edbcf..1c0da99a 100644 --- a/src/initctl.c +++ b/src/initctl.c @@ -421,17 +421,14 @@ static int show_status(char *arg) for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) { char jobid[20], args[512] = "", *lvls; + int i; if (!svc->id[0]) snprintf(jobid, sizeof(jobid), "%d", svc->job); else snprintf(jobid, sizeof(jobid), "%d:%s", svc->job, svc->id); - printf("%-9s %8s ", jobid, svc_status(svc)); - if (svc_is_inetd(svc)) - printf("inetd "); - else - printf("%-6d ", svc->pid); + printf("%-9s %8s %-6d ", jobid, svc_status(svc), svc->pid); lvls = runlevel_string(runlevel, svc->runlevels); if (strchr(lvls, '\e')) @@ -445,47 +442,12 @@ static int show_status(char *arg) continue; } -#ifdef INETD_ENABLED - if (svc_is_inetd(svc)) { - char *info; - struct init_request rq = { - .magic = INIT_MAGIC, - .cmd = INIT_CMD_QUERY_INETD, - }; - - snprintf(rq.data, sizeof(rq.data), "%s", jobid); - if (client_send(&rq, sizeof(rq))) { - snprintf(args, sizeof(args), "Unknown inetd"); - info = args; - } else { - size_t len = sizeof(rq.data); - - info = rq.data; - info[len - 1] = 0; - - if (!string_match("internal", svc->cmd)) { - char *ptr; - - ptr = strchr(info, ' '); - if (ptr) - info = ptr + 1; - } - } - - printf("%s %s\n", svc->cmd, info); + for (i = 1; i < MAX_NUM_SVC_ARGS; i++) { + strlcat(args, svc->args[i], sizeof(args)); + strlcat(args, " ", sizeof(args)); } - else -#endif /* INETD_ENABLED */ - { - int i; - for (i = 1; i < MAX_NUM_SVC_ARGS; i++) { - strlcat(args, svc->args[i], sizeof(args)); - strlcat(args, " ", sizeof(args)); - } - - printf("%s %s\n", svc->cmd, args); - } + printf("%s %s\n", svc->cmd, args); } return 0; diff --git a/src/service.c b/src/service.c index 20fa7583..854fd191 100644 --- a/src/service.c +++ b/src/service.c @@ -37,7 +37,6 @@ #include "cond.h" #include "finit.h" #include "helpers.h" -#include "inetd.h" #include "pid.h" #include "private.h" #include "sig.h" @@ -248,17 +247,6 @@ static int lredirect(svc_t *svc) */ static int redirect(svc_t *svc) { - /* Redirect inetd socket to stdin for connection */ -#ifdef INETD_ENABLED - if (svc_is_inetd_conn(svc)) { - dup2(svc->stdin_fd, STDIN_FILENO); - close(svc->stdin_fd); - dup2(STDIN_FILENO, STDOUT_FILENO); - dup2(STDIN_FILENO, STDERR_FILENO); - - return 0; - } -#endif stdin_redirect(); if (svc->log.enabled) { @@ -306,19 +294,14 @@ static int service_start(svc_t *svc) return 1; /* Don't try and start service if it doesn't exist. */ - if (!whichp(svc->cmd) && !svc->inetd.cmd) { + if (!whichp(svc->cmd)) { print(1, "Service %s does not exist", svc->cmd); svc_missing(svc); return 1; } -#ifdef INETD_ENABLED - if (svc_is_inetd(svc)) - return inetd_start(&svc->inetd); -#endif - if (svc_is_sysv(svc)) { + if (svc_is_sysv(svc)) logit(LOG_CONSOLE | LOG_NOTICE, "Calling '%s start' ...", svc->cmd); - } if (!svc->desc[0]) do_progress = 0; @@ -404,22 +387,11 @@ static int service_start(svc_t *svc) redirect(svc); sig_unblock(); - if (svc->inetd.cmd) - status = svc->inetd.cmd(svc->inetd.type); - else if (svc_is_runtask(svc)) + if (svc_is_runtask(svc)) status = exec_runtask(svc->cmd, args); else status = execvp(svc->cmd, args); -#ifdef INETD_ENABLED - if (svc_is_inetd_conn(svc)) { - if (svc->inetd.type == SOCK_STREAM) { - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - } - } else -#endif _exit(status); } else if (log_is_debug()) { char buf[CMD_SIZE] = ""; @@ -455,13 +427,6 @@ static int service_start(svc_t *svc) pid_file_create(svc); break; -#ifdef INETD_ENABLED - case SVC_TYPE_INETD_CONN: - if (svc->inetd.type == SOCK_STREAM) - close(svc->stdin_fd); - break; -#endif - default: break; } @@ -519,22 +484,6 @@ static int service_stop(svc_t *svc) if (svc->state <= SVC_STOPPING_STATE) return 0; -#ifdef INETD_ENABLED - if (svc_is_inetd(svc)) { - int do_progress = runlevel != 1 && !svc_is_busy(svc); - - if (do_progress) - print_desc("Stopping ", svc->desc); - - inetd_stop(&svc->inetd); - - if (do_progress) - print_result(0); - - svc_set_state(svc, SVC_STOPPING_STATE); - return 0; - } else -#endif service_timeout_cancel(svc); if (!svc_is_sysv(svc)) { @@ -792,7 +741,7 @@ static void parse_cmdline_args(svc_t *svc, char *cmd) * service_register - Register service, task or run commands * @type: %SVC_TYPE_SERVICE(0), %SVC_TYPE_TASK(1), %SVC_TYPE_RUN(2) * @cfg: Configuration, complete command, with -- for description text - * @rlimit: Limits for this service/task/run/inetd, may be global limits + * @rlimit: Limits for this service/task/run, may be global limits * @file: The file name service was loaded from * * This function is used to register commands to be run on different @@ -807,7 +756,6 @@ static void parse_cmdline_args(svc_t *svc, char *cmd) * service @username [!0-6,S] /path/to/daemon arg -- Description * task @username [!0-6,S] /path/to/task arg -- Description * run @username [!0-6,S] /path/to/cmd arg -- Description - * inetd tcp/ssh nowait [2345] @root:root /sbin/sshd -i -- Description * * If the username is left out the command is started as root. The [] * brackets denote the allowed runlevels, if left out the default for a @@ -817,46 +765,43 @@ static void parse_cmdline_args(svc_t *svc, char *cmd) * command is listed in more than the [S] runlevel they will be called * when changing runlevel. * - * Services (daemons, not inetd services) also support an optional - * argument. This is for services that, e.g., require a system gateway - * or interface to be up before they are started. Or restarted, or even - * SIGHUP'ed, when the gateway changes or interfaces come and go. The - * special case when a service is declared with means it does not - * support SIGHUP but must be STOP/START'ed at system reconfiguration. + * Services (daemons) also support an optional argument. + * This is for services that depend on another service, e.g. Quagga ripd + * depends on zebra, or require a system gateway or interface to be up + * before they are started. Or restarted, or even SIGHUP'ed, when the + * gateway changes or interfaces come and go. The special case when a + * service is declared with means it does not support SIGHUP but + * must be STOP/START'ed at system reconfiguration. * - * Service conditions can be: pid/ for PID files, net//up - * and net//exists. The condition handling is further described - * in doc/conditions.md, but worth mentioning here is that the condition - * name itself can be modified using the :ID and name:foo syntax. + * Conditions can for example be: pid/NAME:ID for process dependencies, + * net//up or net//exists. The condition handling is + * further described in doc/conditions.md, but worth mentioning here is + * that the condition a services *provides* can be modified using the + * :ID and name:foo syntax. * * For multiple instances of the same command, e.g. multiple DHCP * clients, the user must enter an ID, using the :ID syntax. * - * service :1 /sbin/udhcpc -i eth1 - * service :2 /sbin/udhcpc -i eth2 + * service :eth1 /sbin/udhcpc -i eth1 + * service :eth2 /sbin/udhcpc -i eth2 * - * Without the :ID syntax Finit will overwrite the first service line - * with the contents of the second. The :ID must be [1,MAXINT]. + * Without the :ID syntax, Finit replaces the first service line with + * the contents of the second. The :ID can be any string value and + * defaults to "" (emtpy string). * * Returns: * POSIX OK(0) on success, or non-zero errno exit status on failure. */ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) { -#ifdef INETD_ENABLED - char id_str[MAX_ID_LEN]; - int forking = 0; -#endif + char *cmd, *desc, *runlevels = NULL, *cond = NULL; + char *username = NULL, *log = NULL, *pid = NULL; + char *name = NULL, *halt = NULL, *delay = NULL; + char *id = NULL; int levels = 0; int manual = 0; char *line; - char *id = NULL; - char *username = NULL, *log = NULL, *pid = NULL; - char *service = NULL, *proto = NULL, *ifaces = NULL; - char *cmd, *desc, *runlevels = NULL, *cond = NULL; - char *name = NULL, *halt = NULL, *delay = NULL; svc_t *svc; - plugin_t *plugin = NULL; if (!cfg) { _e("Invalid input argument"); @@ -902,12 +847,6 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) cond = &cmd[1]; else if (cmd[0] == ':') /* :ID */ id = &cmd[1]; -#ifdef INETD_ENABLED - else if (!strncasecmp(cmd, "nowait", 6)) - forking = 1; - else if (!strncasecmp(cmd, "wait", 4)) - forking = 0; -#endif else if (!strncasecmp(cmd, "log", 3)) log = cmd; else if (!strncasecmp(cmd, "pid", 3)) @@ -920,8 +859,6 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) halt = &cmd[5]; else if (!strncasecmp(cmd, "kill:", 5)) delay = &cmd[5]; - else if (cmd[0] != '/' && strchr(cmd, '/')) - service = cmd; /* inetd service/proto */ else break; @@ -938,55 +875,6 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file) return 0; } - /* Example: inetd ssh/tcp@eth0,eth1 or 222/tcp@eth2 */ - if (service) { - ifaces = strchr(service, '@'); - if (ifaces) - *ifaces++ = 0; - - proto = strchr(service, '/'); - if (!proto) - goto incomplete; - *proto++ = 0; - } - -#ifdef INETD_ENABLED - /* Find plugin that provides a callback for this inetd service */ - if (type == SVC_TYPE_INETD) { - if (!strncasecmp(cmd, "internal", 8)) { - char *ptr, *ps = service; - - /* internal.service */ - ptr = strchr(cmd, '.'); - if (ptr) { - *ptr++ = 0; - ps = ptr; - } - - plugin = plugin_find(ps); - if (!plugin || !plugin->inetd.cmd) { - _w("Inetd service %s has no internal plugin, skipping ...", service); - free(line); - return errno = ENOENT; - } - } - - /* Check if known inetd, update command line, then add ifnames for filtering only. */ - svc = inetd_find_svc(cmd, service, proto); - if (svc) { - parse_cmdline_args(svc, cmd); - goto inetd_setup; - } - - /* inetd services need a unique ID, so we must always set one. */ - if (!id) { - snprintf(id_str, sizeof(id_str), "%d", svc_next_id_int(cmd)); - id = id_str; - } - } -recreate: -#endif - if (!id) id = ""; @@ -1004,16 +892,6 @@ recreate: svc_stop(svc); } } -#ifdef INETD_ENABLED - else { - if (svc_is_inetd(svc) && type != SVC_TYPE_INETD) { - _d("Service was previously inetd, deregistering ..."); - inetd_del(&svc->inetd); - svc_del(svc); - goto recreate; - } - } -#endif /* Always clear svc PID file, for now. See TODO */ svc->pidfile[0] = 0; @@ -1031,12 +909,7 @@ recreate: strlcpy(svc->username, username, sizeof(svc->username)); } - if (plugin) { - /* Internal plugin provides this service */ - svc->inetd.cmd = plugin->inetd.cmd; - svc->inetd.builtin = 1; - } else - parse_cmdline_args(svc, cmd); + parse_cmdline_args(svc, cmd); svc->runlevels = levels; _d("Service %s runlevel 0x%2x", svc->cmd, svc->runlevels); @@ -1053,35 +926,6 @@ recreate: if (desc) strlcpy(svc->desc, desc, sizeof(svc->desc)); -#ifdef INETD_ENABLED - if (svc_is_inetd(svc)) { - char *iface, *name = service; - - if (svc->inetd.cmd && plugin) - name = plugin->name; - - if (inetd_new(&svc->inetd, name, service, proto, forking, svc)) { - _e("Failed registering new inetd service %s/%s", service, proto); - free(line); - return svc_del(svc); - } - - inetd_setup: - inetd_flush(&svc->inetd); - - if (!ifaces) { - _d("No specific iface listed for %s, allowing ANY", service); - inetd_allow(&svc->inetd, NULL); - } else { - for (iface = strtok(ifaces, ","); iface; iface = strtok(NULL, ",")) { - if (iface[0] == '!') - inetd_deny(&svc->inetd, &iface[1]); - else - inetd_allow(&svc->inetd, iface); - } - } - } -#endif /* Set configured limits */ memcpy(svc->rlimit, rlimit, sizeof(svc->rlimit)); @@ -1101,44 +945,18 @@ recreate: /* * This function is called when cleaning up lingering (stopped) services - * after a .conf reload, as well as when an inetd connection terminates. + * after a .conf reload. * * We need to ensure we properly stop the service before removing it, * including stopping any pending restart or SIGKILL timers before we * proceed to free() the svc itself. - * - * Remember to not try to stop inetd connections, they only get here - * when already stopped, if we do we end up in a recursive loop. */ void service_unregister(svc_t *svc) { if (!svc) return; - /* - * Only try stopping @svc if it's *not* an inetd connection. - * Prevents infinite recursion when called from service_step() - */ - switch (svc->type) { -#ifdef INETD_ENABLED - case SVC_TYPE_INETD: - inetd_del(&svc->inetd); - break; - - case SVC_TYPE_INETD_CONN: - /* inetd connection, if UDP unblock parent */ - if (svc_is_busy(svc->inetd.svc)) { - svc_unblock(svc->inetd.svc); - service_step(svc->inetd.svc); - } - break; -#endif - - default: - service_stop(svc); - break; - } - + service_stop(svc); svc_del(svc); } @@ -1238,7 +1056,7 @@ static void svc_set_state(svc_t *svc, svc_state_t new) *state = new; /* if PID isn't collected within SVC_TERM_TIMEOUT msec, kill it! */ - if ((*state == SVC_STOPPING_STATE) && !svc_is_inetd(svc)) { + if ((*state == SVC_STOPPING_STATE)) { _d("%s is stopping, wait %d sec before sending SIGKILL ...", svc->cmd, svc->killdelay / 1000); service_timeout_cancel(svc); @@ -1247,7 +1065,7 @@ static void svc_set_state(svc_t *svc, svc_state_t new) } /* - * Transition inetd/task/run/service + * Transition task/run/service * * Returns: non-zero if the @svc is no longer valid (removed) */ @@ -1275,12 +1093,6 @@ restart: break; case SVC_DONE_STATE: -#ifdef INETD_ENABLED - if (svc_is_inetd_conn(svc)) { - service_unregister(svc); - return -1; - } -#endif if (svc_is_changed(svc)) svc_set_state(svc, SVC_HALTED_STATE); break; @@ -1293,11 +1105,8 @@ restart: switch (svc->type) { case SVC_TYPE_SERVICE: - case SVC_TYPE_INETD: - svc_set_state(svc, SVC_HALTED_STATE); break; - case SVC_TYPE_INETD_CONN: case SVC_TYPE_TASK: case SVC_TYPE_RUN: case SVC_TYPE_SYSV: @@ -1322,8 +1131,7 @@ restart: err = service_start(svc); if (err) { (*restart_cnt)++; - if (!svc_is_inetd_conn(svc)) - break; + break; } /* Everything went fine, clean and set state */ @@ -1352,12 +1160,6 @@ restart: break; } - /* Collected inetd connection, drive it to stopping */ - if (svc_is_inetd_conn(svc)) { - svc_set_state(svc, SVC_STOPPING_STATE); - break; - } - if (svc_is_runtask(svc)) { if (svc_is_sysv(svc)) { if (!svc->started) @@ -1384,18 +1186,16 @@ restart: case COND_ON: if (svc_is_changed(svc)) { if (svc->sighup) { - /* wait until all processes has been stopped before continuing... */ + /* + * wait until all processes have been + * stopped before continuing... + */ if (sm_is_in_teardown(&sm)) break; service_restart(svc); - } else { -#ifdef INETD_ENABLED - if (svc_is_inetd(svc)) - inetd_stop_children(&svc->inetd, 1); - else -#endif - service_stop(svc); - } + } else + service_stop(svc); + svc_mark_clean(svc); } break; @@ -1465,7 +1265,7 @@ void service_step_all(int types) void service_worker(void *unused) { - service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_RUNTASK | SVC_TYPE_INETD); + service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_RUNTASK); } /** diff --git a/src/sm.c b/src/sm.c index fb80f441..87564c85 100644 --- a/src/sm.c +++ b/src/sm.c @@ -222,7 +222,7 @@ restart: _d("Stopping services not allowed after reconf ..."); sm->in_teardown = 1; cond_reload(); - service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_INETD); + service_step_all(SVC_TYPE_SERVICE); tty_reload(NULL); sm->state = SM_RELOAD_WAIT_STATE; @@ -244,12 +244,12 @@ restart: svc_clean_dynamic(service_unregister); _d("Starting services after reconf ..."); - service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_INETD); + service_step_all(SVC_TYPE_SERVICE); _d("Calling reconf hooks ..."); plugin_run_hooks(HOOK_SVC_RECONF); - service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_INETD); + service_step_all(SVC_TYPE_SERVICE); _d("Reconfiguration done"); sm->state = SM_RUNNING_STATE; diff --git a/src/svc.c b/src/svc.c index 88dc8b2d..17cd76bf 100644 --- a/src/svc.c +++ b/src/svc.c @@ -72,9 +72,9 @@ static void svc_gc(void *arg) /** * svc_new - Create a new service - * @cmd: External program to call, or 'internal' for internal inetd services + * @cmd: External program to call * @id: Instance id - * @type: Service type, one of service, task, run or inetd + * @type: Service type, one of service, task, run * * Returns: * A pointer to a new &svc_t object, or %NULL if out of empty slots. @@ -169,28 +169,6 @@ svc_t *svc_iterator(svc_t **iter, int first) return svc; } -/** - * svc_inetd_iterator - Naive iterator over all registered inetd services. - * @iter: Iterator, must be a valid pointer - * @first: If set, get first &svc_t, otherwise get next - * - * Returns: - * The first inetd &svc_t when %NULL is given as argument, otherwise the - * next inetd &svc_t until the end when %NULL is returned. - */ -svc_t *svc_inetd_iterator(svc_t **iter, int first) -{ - svc_t *svc; - - for (svc = svc_iterator(iter, first); svc; svc = svc_iterator(iter, 0)) { - if (svc_is_inetd(svc)) - return svc; - } - - return NULL; -} - - /** * svc_named_iterator - Iterates over all instances of a service. * @iter: Iterator, must be a valid pointer @@ -455,8 +433,6 @@ void svc_mark_dynamic(void) for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) { if (svc->protect) continue; - if (svc_is_inetd_conn(svc)) - continue; *((int *)&svc->dirty) = -1; } @@ -547,29 +523,6 @@ int svc_enabled(svc_t *svc) return 1; } -/* - * Same base service, return unique ID as an integer - * Note: intended for use with INETD services. - */ -int svc_next_id_int(char *cmd) -{ - int n = 1; - svc_t *svc, *iter = NULL; - - for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) { - char id[MAX_ID_LEN]; - - snprintf(id, sizeof(id), "%d", n); - - if (!strcmp(svc->cmd, cmd) && strcmp(svc->id, id)) - return n; - - n++; - } - - return 1; -} - int svc_is_unique(svc_t *svc) { svc_t *s, *iter = NULL; diff --git a/src/svc.h b/src/svc.h index 1ca7133e..36853eb8 100644 --- a/src/svc.h +++ b/src/svc.h @@ -30,8 +30,8 @@ #include /* pid_t */ #include #include /* BSD sys/queue.h API */ +#include -#include "inetd.h" #include "helpers.h" typedef int svc_cmd_t; @@ -41,8 +41,6 @@ typedef enum { SVC_TYPE_SERVICE = 1, /* Monitored, will be respawned */ SVC_TYPE_TASK = 2, /* One-shot, runs in parallell */ SVC_TYPE_RUN = 4, /* Like task, but wait for completion */ - SVC_TYPE_INETD = 8, /* Classic inetd service */ - SVC_TYPE_INETD_CONN = 16, /* Single inetd connection */ SVC_TYPE_SYSV = 32, /* SysV style init.d script w/ start/stop */ } svc_type_t; @@ -103,7 +101,7 @@ typedef struct svc { int started; /* Set for run/task/sysv to track if started */ int status; /* From waitpid() when process is collected */ const svc_state_t state; /* Paused, Reloading, Restart, Running, ... */ - svc_type_t type; /* Service, run, task, inetd, ... */ + svc_type_t type; /* Service, run, task, ... */ int protect; /* Services like dbus-daemon & udev by Finit */ const int dirty; /* -1: removal, 0: unmodified, 1: modified */ int starting; /* ... waiting for pidfile to be re-asserted */ @@ -117,11 +115,6 @@ typedef struct svc { char once; /* run/task, (at least) once per runlevel */ const char restart_cnt; /* Incremented for each restart by service monitor. */ - /* For inetd services */ - inetd_t inetd; - int stdin_fd; - char iifname[IF_NAMESIZE + 1]; /* Ingress interface for connection */ - /* Set for services we need to redirect stdout/stderr to syslog */ struct { char enabled; @@ -162,7 +155,6 @@ svc_t *svc_find_by_nameid (char *name, char *id); svc_t *svc_find_by_pidfile (char *fn); svc_t *svc_iterator (svc_t **iter, int first); -svc_t *svc_inetd_iterator (svc_t **iter, int first); svc_t *svc_named_iterator (svc_t **iter, int first, char *cmd); svc_t *svc_job_iterator (svc_t **iter, int first, int job); @@ -179,13 +171,10 @@ int svc_clean_bootstrap (svc_t *svc); void svc_prune_bootstrap (void); int svc_enabled (svc_t *svc); -int svc_next_id_int (char *cmd); int svc_is_unique (svc_t *svc); int svc_parse_jobstr (char *str, size_t len, int (*found)(svc_t *), int (not_found)(char *, char *)); -static inline int svc_is_inetd (svc_t *svc) { return svc && SVC_TYPE_INETD == svc->type; } -static inline int svc_is_inetd_conn(svc_t *svc) { return svc && SVC_TYPE_INETD_CONN == svc->type; } static inline int svc_is_daemon (svc_t *svc) { return svc && SVC_TYPE_SERVICE == svc->type; } static inline int svc_is_sysv (svc_t *svc) { return svc && SVC_TYPE_SYSV == svc->type; } static inline int svc_is_runtask (svc_t *svc) { return svc && (SVC_TYPE_RUNTASK & svc->type); } @@ -246,7 +235,6 @@ static inline char *svc_status(svc_t *svc) case SVC_STOPPING_STATE: switch (svc->type) { - case SVC_TYPE_INETD_CONN: case SVC_TYPE_RUN: case SVC_TYPE_TASK: return "active";