diff --git a/src/inetd.c b/src/inetd.c index 043fbe47..a5ed80e7 100644 --- a/src/inetd.c +++ b/src/inetd.c @@ -122,7 +122,7 @@ static int inetd_stream_peek(int sd, char *ifname) return 0; } -static int get_stdin(svc_t *svc) +static int get_stdin(svc_t *svc, char* iifname) { int stdin = svc->inetd.watcher.fd; char ifname[IF_NAMESIZE] = "UNKNOWN"; @@ -152,6 +152,9 @@ static int get_stdin(svc_t *svc) return -1; } + /* Return ingress interface */ + strncpy(iifname, ifname, IF_NAMESIZE); + return stdin; } @@ -160,6 +163,7 @@ 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] = "UNKNOWN"; int stdin; _d("%s: Got socket event ...", svc->cmd); @@ -168,7 +172,7 @@ static void socket_cb(uev_t *w, void *arg, int events) return; } - stdin = get_stdin(svc); + stdin = get_stdin(svc, iifname); if (stdin < 0) { logit(LOG_CRIT, "%s: Unable to accept incoming connection", svc->cmd); return; @@ -216,6 +220,7 @@ static void socket_cb(uev_t *w, void *arg, int events) 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)); + strncpy(task->iifname, iifname, sizeof(task->iifname)); task->stdin_fd = stdin; service_step(task); @@ -335,6 +340,22 @@ int inetd_start(inetd_t *inetd) 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) { @@ -351,20 +372,11 @@ void inetd_stop(inetd_t *inetd) * and halt the watcher, so don't close the socket! */ if (!svc_is_busy(inetd->svc)) { - svc_t *svc, *iter = NULL; - _d("Shutting down inet socket %d ...", inetd->watcher.fd); close(inetd->watcher.fd); inetd->watcher.fd = -1; - svc = svc_job_iterator(&iter, 1, inetd->svc->job); - while (svc) { - if (!svc_is_inetd(svc)) { - svc_stop(svc); - service_step(svc); - } - svc = svc_job_iterator(&iter, 0, inetd->svc->job); - } + inetd_stop_children(inetd, 0); } } } diff --git a/src/inetd.h b/src/inetd.h index bf349836..babc2ddf 100644 --- a/src/inetd.h +++ b/src/inetd.h @@ -58,6 +58,7 @@ 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); diff --git a/src/service.c b/src/service.c index 187bd962..43aac6e9 100644 --- a/src/service.c +++ b/src/service.c @@ -1114,7 +1114,12 @@ restart: break; service_restart(svc); } else { - service_stop(svc); +#ifdef INETD_ENABLED + if (svc_is_inetd(svc)) + inetd_stop_children(&svc->inetd, 1); + else +#endif + service_stop(svc); } svc_mark_clean(svc); } diff --git a/src/svc.h b/src/svc.h index 84405048..53189e0e 100644 --- a/src/svc.h +++ b/src/svc.h @@ -109,6 +109,7 @@ typedef struct svc { /* For inetd services */ inetd_t inetd; int stdin_fd; + char iifname[IF_NAMESIZE]; /* Ingress interface for connection */ /* Set for services we need to redirect stdout/stderr to syslog */ struct {