From 03573b41ca6a054b86c7d83b69621d5152c35d6c Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Mon, 15 Jun 2015 14:10:40 +0200 Subject: [PATCH] Add support for a deny filter syntax to inetd services This patch changes the syntax for custom inetd services and adds support for deny filters. The new syntax is: inetd service/proto[@iface,!iface,...] This means the second column now defines what@from and the third to/what process. For internal services on a custom port the internal.service syntax must be specified, so Finit can properly bind the inetd service to the correct plugin. Here follows a few examples: inetd time/udp wait [2345] internal -- UNIX rdate service inetd time/tcp nowait [2345] internal -- UNIX rdate service inetd 3737/tcp nowait [2345] internal.time -- UNIX rdate service inetd telnet/tcp@*,!eth1,!eth0, nowait [2345] /sbin/telnetd -i -F -- Telnet service inetd 2323/tcp@eth1,eth2,eth0 nowait [2345] /sbin/telnetd -i -F -- Telnet service inetd 222/tcp@eth0 nowait [2345] /sbin/dropbear -i -R -F -- SSH service inetd ssh/tcp@*,!eth0 nowait [2345] /sbin/dropbear -i -R -F -- SSH service Access to telnet on port `2323` is only possible from interfaces `eth0`, `eth1` and `eth2`. The standard telnet port (`23`) is available from all other interfaces, but also `eth2`. The `*` notation used in the ssh stanza means *any* interface, however, here `eth0` is not allowed. NOTE: This patch breaks syntax compatibility with Finit v1.12! Signed-off-by: Joachim Nilsson --- README.md | 121 ++++++++++++++++++++++++++++-------------------- TODO.md | 11 ----- client.c | 12 +++-- inetd.c | 134 ++++++++++++++++++------------------------------------ inetd.h | 5 +- initctl.c | 2 +- service.c | 87 +++++++++++++++++++++-------------- 7 files changed, 177 insertions(+), 195 deletions(-) diff --git a/README.md b/README.md index 41505887..475a7073 100644 --- a/README.md +++ b/README.md @@ -235,18 +235,17 @@ the static configuration from `/etc/finit.conf`. This is the default behavior, so no include directives are necessary. To add a new service, simply drop a `.conf` file in `/etc/finit.d` and -send `SIGHUP` to finit, or call `init q`. Any service read from this -directory is flagged as a dynamic service, so changes to their .conf +send `SIGHUP` to PID 1, or call `finit q`. Any service read from this +directory is flagged as a dynamic service, so changes to their `.conf` files, or even removal of the files, is detected at `SIGHUP`. -- If a service's .conf file has been removed, the service is stopped. -- If the file has changed the service is reloaded, stopped and - restarted. -- If it is a new service, it is started -- respecting runlevels and - callbacks. +- If a service's `.conf` file has been removed, the service is stopped. +- If the file is modified, the service is reloaded, stopped and started. +- If a new service is detected, it is started -- respecting runlevels + and return values from any callbacks. The `/etc/finit.d` directory was previously the default Finit `runparts` -directory. Finit no longer has a default runparts, so make sure to +directory. Finit no longer has a default `runparts`, so make sure to update your setup, or the finit configuration, accordingly. **Note:** Configurations read from `/etc/finit.d` are read *after* @@ -314,8 +313,14 @@ default all services, tasks, run commands and TTYs listed without a set of runlevels get a default set `[234]` assigned. The default runlevel after boot is 2. -To specify an allowed set of runlevels for a `service`, `run` command, `task`, -or `tty`, add `[NNN]` to it in your `/etc/finit.conf`, like this: +Finit supports runlevels 0-9, and S, with 0 reserved for halt, 6 reboot +and S for services to only run at bootstrap. Runlevel 1 is the single +user level, where usually no networking is enabled. In Finit this is +more of a policy for the user to define. Normally only runlevels 1-6 +are used, and even more commonly, only the default runlevel is used. + +To specify an allowed set of runlevels for a `service`, `run` command, +`task`, or `tty`, add `[NNN]` to your `/etc/finit.conf`, like this: service [S12345] /sbin/syslogd -n -x -- System log daemon run [S] /etc/init.d/acpid start -- Starting ACPI Daemon @@ -340,7 +345,13 @@ are called in the order listed and subsequent commands are not started until a run command has completed. Switching between runlevels can be done by calling init with a single -argument, e.g. init 5 switches to runlevel 5. +argument, e.g. init 5 switches to runlevel 5. When changing +runlevels Finit also automatically reloads all `.conf` files in the +`/etc/finit.d/` directory. So if you want to set a new system config, +switch to runlevel 1, change all config files in the system, and touch +all `.conf` files in `/etc/finit.d` before switching back to the +previous runlevel again -- that way Finit can both stop old services and +start any new ones for you, without rebooting the system. Inetd @@ -360,29 +371,25 @@ traffic using a poor man's [TCP wrappers]. The syntax is very similar to the traditional `/etc/inetd.conf`, yet keeping with the style of Finit: # Launch SSH on demand, in runlevels 2-5 as root - inetd ssh/tcp nowait [2345] @root:root /usr/sbin/sshd -i + inetd ssh/tcp nowait [2345] @root:root /usr/sbin/sshd -i -A more advanced example: +A more advanced example is listed below, please not the *incompatible +syntax change* that was made between Finit v1.12 and v1.13 to support +deny filters: # Start sshd if inbound connection on eth0, port 222, or # inbound on eth1, port 22. Ignore on other interfaces. - inetd ssh@eth0:222/tcp nowait [2345] /usr/sbin/sshd -i - inetd ssh@eth1:22/tcp nowait [2345] /usr/sbin/sshd -i + inetd 222/tcp@eth0 nowait [2345] /usr/sbin/sshd -i + inetd ssh/tcp@eth1,eth1 nowait [2345] /usr/sbin/sshd -i If `eth0` is your Internet interface you may want to avoid using the default port. To run ssh on port 222, and all others on port 22: - inetd ssh@eth0:222/tcp nowait [2345] /usr/sbin/sshd -i - inetd ssh/tcp nowait [2345] /usr/sbin/sshd -i + inetd 222/tcp@eth0 nowait [2345] /usr/sbin/sshd -i + inetd ssh/tcp@*,!eth0 nowait [2345] /usr/sbin/sshd -i + +Compared to Finit v1.12 you must *explicitly deny* access from `eth0`! -*This actually adds a deny rule for eth0 on ssh/tcp, implicitly.* You -can even list the services in reverse order with the same result: - - inetd ssh/tcp nowait [2345] /usr/sbin/sshd -i - inetd ssh@eth0:222/tcp nowait [2345] /usr/sbin/sshd -i - -There is no specific deny syntax available yet, see the TODO file for -more details on how this can be implemented. **Internal Services** @@ -415,8 +422,8 @@ Also, remember the UNIX year 2038 bug, or in the case of RFC 868 (and some NTP implementations), year 2036! **Note:** There is currently no verification that the same port is used - more than once. So a standard http service will clash with an ssh - entry `ssh@*:80/tcp`. + more than once. So a standard `inetd http/tcp` service will clash + with an ssh entry for the same port `inetd 80/tcp` ... Hooks, Callbacks & Plugins @@ -517,42 +524,58 @@ Rebooting & Halting ------------------- Finit handles `SIGUSR1` and `SIGUSR2` for reboot and halt, and listens -to `/dev/initctl` so system reboot and halt commands should also work. -This latter functionality is implemented in the optional `initctl.so` -plugin and can be accessed with the `initctl` command line tool (which -is symlinked to `finit`). +to `/dev/initctl` so system reboot and halt commands also work. This +latter functionality is implemented in the optional `initctl.so` plugin +and can be accessed with the `telinit` command line tool, symlinked to +`finit`). - ~ # initctl - Usage: initctl [OPTIONS] [ | ] + ~ # telinit + Usage: telinit [OPTIONS] [q | Q | 0-9] + + Options: + -h, --help This help text + -v, --version Show Finit version + + Commands: + q | Q Reload *.conf in /etc/finit.d/, like SIGHUP + 0 - 9 Change runlevel: 0 halt, 6 reboot + +Finit also implements a more modern API to query status, and start/stop +services, called `initctl`. + + ~ # initctl -h + Usage: initctl [OPTIONS] Options: - -d, --debug Toggle Finit debug -v, --verbose Verbose output -h, --help This help text Commands: debug Toggle Finit debug - q | reload Reload *.conf in /etc/finit.d/ - runlevel <1-6> Set new runlevel + reload Reload *.conf in /etc/finit.d/ + runlevel <0-9> Change runlevel: 0 halt, 6 reboot status Show status of services start Start stopped service stop Stop running service restart Restart (stop/start) running service reload Reload (SIGHUP) running service version Show Finit version - - ~ # initctl status - # Status PID Runlevels Service Description - ==================================================================================== - 1 running 480 [S12345] /sbin/watchdog System watchdog daemon - 2 running 481 [S12345] /sbin/syslogd System log daemon - 3 running 519 [S12345] /sbin/klogd Kernel log daemon - 4:1 stopped 0 [345] /sbin/dropbear SSH daemon - 4:2 stopped 0 [345] /sbin/dropbear SSH daemon - 5:1 waiting 0 [2345] internal UNIX rdate service - 5:2 waiting 0 [2345] internal UNIX rdate service - 6:1 waiting 0 [2345] /sbin/telnetd Telnet service - 6:2 waiting 0 [2345] /sbin/telnetd Telnet service + +Remember, you can only start/stop services that match the current +runlevel. Hence, if the runlevel is 2, the below Dropbear SSH service +cannot be started. + + ~ # initctl status -v + 1 running 476 [S12345] /sbin/watchdog -T 16 -t 2 -F /dev/watchdog + 2 running 477 [S12345] /sbin/syslogd -n -b 3 -D + 3 running 478 [S12345] /sbin/klogd -n + 4:1 inetd 0 [2345] internal time allow *:37 + 4:2 inetd 0 [2345] internal time allow *:37 + 4:3 inetd 0 [2345] internal 3737 allow *:3737 + 5:1 inetd 0 [2345] /sbin/telnetd allow *:23 deny eth0,eth1 + 5:2 inetd 0 [2345] /sbin/telnetd allow eth0:2323,eth2:2323,eth1:2323 + 6:1 inetd 0 [2345] /sbin/dropbear allow eth0:222 + 6:2 inetd 0 [2345] /sbin/dropbear allow *:22 deny eth0 Building diff --git a/TODO.md b/TODO.md index d9024454..90fe3fd0 100644 --- a/TODO.md +++ b/TODO.md @@ -59,17 +59,6 @@ to achieve compatibility would be to add a plugin to finit which reads Inetd ----- -wkz says we need deny rules and better syntax! we agrees - - -wkz --> inetd telnet/tcp @!eth0 -wkz --> inetd 2323/tcp @eth0 -wkz --> 77/udp wait [2345] @finit/time - -jnn --> telnet@eth0,eth1/tcp -jnn --> 2323@eth2/tcp -jnn --> 3000/udp wait [2345] time/internal - Optimize interface filtering by using socket filter. The functions `inet_*_peek()` and `inetd_is_allowed()` used for interace filtering should be possible to rewrite as socket filters. diff --git a/client.c b/client.c index 1adb0337..38410c38 100644 --- a/client.c +++ b/client.c @@ -59,14 +59,16 @@ static int do_send(int cmd, int runlevel) return result; } -/* telinit q | telinit <1-6> */ +/* telinit q | telinit <0-9> */ static int usage(int rc) { - fprintf(stderr, "Usage: %s \n\n" + fprintf(stderr, "Usage: %s [OPTIONS] [q | Q | 0-9]\n\n" "Options:\n" - " -v, --verbose Verbose output\n" " -h, --help This help text\n\n" - " -V, --version Show Finit version\n\n", __progname); + " -V, --version Show Finit version\n\n" + "Commands:\n" + " q | Q Reload *.conf in /etc/finit.d/, like SIGHUP\n" + " 0 - 9 Change runlevel: 0 halt, 6 reboot\n\n", __progname); return rc; } @@ -95,7 +97,7 @@ int client(int argc, char *argv[]) if (optind < argc) { int req = (int)argv[optind][0]; - /* Compat: 'init <1-9>' */ + /* Compat: 'init <0-9>' */ if (isdigit(req)) return do_send(INIT_CMD_RUNLVL, req); diff --git a/inetd.c b/inetd.c index a316a57c..5d01d0cb 100644 --- a/inetd.c +++ b/inetd.c @@ -219,14 +219,28 @@ static int getent(char *service, char *proto, struct servent **sv, struct protoe { *sv = getservbyname(service, proto); if (!*sv) { - _pe("Invalid inetd %s/%s (service/proto), skipping", service, proto); - return errno = EINVAL; + static struct servent s; + + s.s_name = service; + s.s_port = atonum(service); + s.s_proto = NULL; + if (!strcmp("tcp", proto) || !strcmp("udp", proto)) + s.s_proto = proto; + + if (s.s_port == -1 || !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) { *pv = getprotobyname((*sv)->s_proto); if (!*pv) { - _pe("Cannot find proto %s, skipping.", (*sv)->s_proto); + _e("Cannot find proto %s, skipping.", (*sv)->s_proto); return errno = EINVAL; } } @@ -242,7 +256,7 @@ static inetd_filter_t *find_filter(inetd_t *inetd, char *ifname) inetd_filter_t *filter; if (!ifname) - ifname = ""; + ifname = "*"; LIST_FOREACH(filter, &inetd->filters, link) { _d("Checking filters for %s: '%s' vs '%s' (exact match) ...", @@ -265,20 +279,18 @@ inetd_filter_t *inetd_filter_match(inetd_t *inetd, char *ifname) if (filter) return filter; - if (!ifname) - ifname = ""; - LIST_FOREACH(filter, &inetd->filters, link) { _d("Checking filters for %s: '%s' vs '%s' (any match) ...", inetd->name, filter->ifname, ifname); - if (!strlen(filter->ifname)) + if (!strcmp(filter->ifname, "*")) return filter; } return NULL; } +/* Poor man's tcpwrappers filtering */ int inetd_allow(inetd_t *inetd, char *ifname) { inetd_filter_t *filter; @@ -286,21 +298,22 @@ int inetd_allow(inetd_t *inetd, char *ifname) 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); + _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); + _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; } - if (!ifname) - ifname = ""; filter->deny = 0; strlcpy(filter->ifname, ifname, sizeof(filter->ifname)); LIST_INSERT_HEAD(&inetd->filters, filter, link); @@ -315,26 +328,23 @@ int inetd_deny(inetd_t *inetd, char *ifname) if (!inetd) return errno = EINVAL; - /* Reset to NULL for debug output below */ - if (!ifname[0]) - ifname = NULL; + 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); + filter->deny ? "Deny" : "Allow", ifname, inetd->name); return 1; } - _d("Deny iface %s for service %s (port %d)", ifname ?: "*", inetd->name, inetd->port); + _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; } - if (!ifname) - ifname = ""; filter->deny = 1; strlcpy(filter->ifname, ifname, sizeof(filter->ifname)); LIST_INSERT_HEAD(&inetd->filters, filter, link); @@ -362,9 +372,10 @@ int inetd_is_allowed(inetd_t *inetd, char *ifname) return 0; } -int inetd_match(inetd_t *inetd, char *service, char *proto, char *port) +int inetd_match(inetd_t *inetd, char *service, char *proto) { - int cport = port ? atonum(port) : -1; + struct servent *sv = NULL; + struct protoent *pv = NULL; if (!inetd || !service || !proto) return errno = EINVAL; @@ -372,20 +383,12 @@ int inetd_match(inetd_t *inetd, char *service, char *proto, char *port) if (strncmp(inetd->name, service, sizeof(inetd->name))) return 0; - if (cport != -1) { - if (inetd->port == cport) - return 1; - } else { - struct servent *sv = NULL; - struct protoent *pv = NULL; + if (getent(service, proto, &sv, &pv)) + return 0; - if (getent(service, proto, &sv, &pv)) - return 0; - - if (inetd->proto == ntohs(pv->p_proto) && - inetd->port == ntohs(sv->s_port)) - return 1; - } + if (inetd->proto == ntohs(pv->p_proto) && + inetd->port == ntohs(sv->s_port)) + return 1; return 0; } @@ -410,7 +413,7 @@ int inetd_filter_str(inetd_t *inetd, char *str, size_t len) continue; if (!strlen(filter->ifname)) - snprintf(ifname, sizeof(ifname), "ANY"); + snprintf(ifname, sizeof(ifname), "*"); else strlcpy(ifname, filter->ifname, sizeof(ifname)); @@ -432,7 +435,7 @@ int inetd_filter_str(inetd_t *inetd, char *str, size_t len) } if (!strlen(filter->ifname)) - snprintf(ifname, sizeof(ifname), "ANY"); + snprintf(ifname, sizeof(ifname), "*"); else strlcpy(ifname, filter->ifname, sizeof(ifname)); @@ -465,7 +468,7 @@ int inetd_filter_str(inetd_t *inetd, char *str, size_t len) * If equivalent service exists already service_register() will instead call * inetd_allow(). */ -int inetd_new(inetd_t *inetd, char *service, char *proto, int forking) +int inetd_new(inetd_t *inetd, char *service, char *proto, int forking, void *arg) { int result; struct servent *sv = NULL; @@ -494,6 +497,9 @@ int inetd_new(inetd_t *inetd, char *service, char *proto, int forking) /* Reset descriptor, used internally */ inetd->watcher.fd = -1; + /* Setup socket callback argument */ + inetd->arg = arg; + _d("New service %s (default port %d proto %s:%d)", service, inetd->port, sv->s_proto, pv->p_proto); return 0; @@ -509,60 +515,6 @@ int inetd_del(inetd_t *inetd) return 0; } -int inetd_init(inetd_t *inetd, void *arg, char *ifname, char *port) -{ - int result, cport = -1; - svc_t *svc; - - if (!inetd || !arg) - return errno = EINVAL; - - if (port) - cport = atonum(port); - - if (cport != -1 && cport != inetd->port) { - inetd->std = 0; - inetd->port = cport; - } - - /* Setup socket callback argument */ - inetd->arg = arg; - - /* Poor man's tcpwrappers filtering */ - result = inetd_allow(inetd, ifname); - - /* For each similar service, on other port, add their ifnames as deny to ours. */ - for (svc = svc_inetd_iterator(1); svc; svc = svc_inetd_iterator(0)) { - inetd_filter_t *filter; - - /* Skip ourselves */ - if (&svc->inetd == inetd) - continue; - - /* Skip different service types (telnet != ssh) */ - if (strcmp(svc->inetd.name, inetd->name)) - continue; - - /* Deny all their interfaces from using my service */ - LIST_FOREACH(filter, &svc->inetd.filters, link) { - if (filter->deny) - continue; - - inetd_deny(inetd, filter->ifname); - } - - /* Deny my interfaces from using their service ... */ - LIST_FOREACH(filter, &inetd->filters, link) { - if (filter->deny) - continue; - - inetd_deny(&svc->inetd, filter->ifname); - } - } - - return result; -} - /** * Local Variables: * version-control: t diff --git a/inetd.h b/inetd.h index ea3b7e9c..2fc35e8a 100644 --- a/inetd.h +++ b/inetd.h @@ -60,11 +60,10 @@ void inetd_stop (inetd_t *inetd); int inetd_respawn (pid_t pid); -int inetd_new (inetd_t *inetd, char *service, char *proto, int forking); +int inetd_new (inetd_t *inetd, char *service, char *proto, int forking, void *arg); int inetd_del (inetd_t *inetd); -int inetd_init (inetd_t *inetd, void *arg, char *ifname, char *port); -int inetd_match (inetd_t *inetd, char *service, char *proto, char *port); +int inetd_match (inetd_t *inetd, char *service, char *proto); int inetd_filter_str (inetd_t *inetd, char *str, size_t len); int inetd_allow (inetd_t *inetd, char *ifname); diff --git a/initctl.c b/initctl.c index 2956fe88..3af26293 100644 --- a/initctl.c +++ b/initctl.c @@ -198,7 +198,7 @@ static int usage(int rc) "Commands:\n" " debug Toggle Finit debug\n" " reload Reload *.conf in /etc/finit.d/\n" - " runlevel <1-6> Set new runlevel\n" + " runlevel <0-9> Change runlevel: 0 halt, 6 reboot\n" " status Show status of services\n" " start Start stopped service\n" " stop Stop running service\n" diff --git a/service.c b/service.c index c01a7509..009756f0 100644 --- a/service.c +++ b/service.c @@ -42,7 +42,7 @@ static int is_norespawn (void); static void restart_lost_procs (void); static void svc_dance (svc_t *svc); static void utmp_save (int pre, int now); -static svc_t *find_inetd_svc (char *path, char *service, char *proto, char *port); +static svc_t *find_inetd_svc (char *path, char *service, char *proto); /** @@ -537,7 +537,7 @@ int service_register(int type, char *line, time_t mtime, char *username) #ifndef INETD_DISABLED int forking = 0; #endif - char *service = NULL, *proto = NULL, *iface = NULL, *port = NULL; + char *service = NULL, *proto = NULL, *ifaces = NULL; char *cmd, *desc, *runlevels = NULL; svc_t *svc; plugin_t *plugin = NULL; @@ -582,37 +582,42 @@ int service_register(int type, char *line, time_t mtime, char *username) goto incomplete; } - /* Example: inetd ssh@eth0:222/tcp */ + /* 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; - - port = strchr(service, ':'); - if (port) - *port++ = 0; - - iface = strchr(service, '@'); - if (iface) - *iface++ = 0; } #ifndef INETD_DISABLED /* Find plugin that provides a callback for this inetd service */ if (type == SVC_TYPE_INETD) { if (!strncasecmp(cmd, "internal", 8)) { - plugin = plugin_find(service); + char *ptr, *ps = service; + + /* internal.service */ + ptr = strchr(cmd, '.'); + if (ptr) { + *ptr++ = 0; + ps = ptr; + } + + plugin = plugin_find(ps); if (!plugin || !plugin->inetd.cmd) { _e("Inetd service %s has no internal plugin, skipping.", service); return errno = ENOENT; } } - /* Check if known inetd, then add ifname for filtering only. */ - svc = find_inetd_svc(cmd, service, proto, port); + /* Check if known inetd, then add ifnames for filtering only. */ + svc = find_inetd_svc(cmd, service, proto); if (svc) - return inetd_allow(&svc->inetd, iface); + goto inetd_setup; id = svc_next_id(cmd); } @@ -644,23 +649,6 @@ int service_register(int type, char *line, time_t mtime, char *username) strlcpy(svc->username, username, sizeof(svc->username)); } -#ifndef INETD_DISABLED - if (svc_is_inetd(svc)) { - int result; - - _d("Creating new svc job %d inetd %s proto %s iface %s port %s", - svc->job, service, proto, iface, port); - result = inetd_new(&svc->inetd, service, proto, forking); - result += inetd_init(&svc->inetd, svc, iface, port); - - if (result) { - _e("Failed registering new inetd service %s.", service); - inetd_del(&svc->inetd); - return svc_del(svc); - } - } -#endif - if (plugin) { /* Internal plugin provides this service */ svc->inetd.cmd = plugin->inetd.cmd; @@ -681,6 +669,35 @@ int service_register(int type, char *line, time_t mtime, char *username) svc->runlevels = parse_runlevels(runlevels); _d("Service %s runlevel 0x%2x", svc->cmd, svc->runlevels); +#ifndef INETD_DISABLED + if (svc_is_inetd(svc)) { + char *iface; + + _d("Creating new svc job %d inetd %s proto %s iface %s", + svc->job, service, proto, ifaces); + if (inetd_new(&svc->inetd, service, proto, forking, svc)) { + _e("Failed registering new inetd service %s.", service); + inetd_del(&svc->inetd); + return svc_del(svc); + } + + inetd_setup: + if (!ifaces) { + _d("No specific iface listed for %s, allowing ANY.", service); + return inetd_allow(&svc->inetd, NULL); + } + + _d("Setting up interface filters for inetd service %s ...", service); + for (iface = strtok(ifaces, ","); iface; iface = strtok(NULL, ",")) { + _d("Checking interface name %s ...", iface); + if (iface[0] == '!') + inetd_deny(&svc->inetd, &iface[1]); + else + inetd_allow(&svc->inetd, iface); + } + } +#endif + return 0; } @@ -814,7 +831,7 @@ static void utmp_save(int pre, int now) } #ifndef INETD_DISABLED -static svc_t *find_inetd_svc(char *path, char *service, char *proto, char *port) +static svc_t *find_inetd_svc(char *path, char *service, char *proto) { svc_t *svc; @@ -822,8 +839,8 @@ static svc_t *find_inetd_svc(char *path, char *service, char *proto, char *port) if (strncmp(path, svc->cmd, strlen(svc->cmd))) continue; - if (inetd_match(&svc->inetd, service, proto, port)) { - _d("Found a matching inetd svc for %s %s %s %s", path, service, proto, port); + if (inetd_match(&svc->inetd, service, proto)) { + _d("Found a matching inetd svc for %s %s %s", path, service, proto); return svc; } }