From: Roy Marples Date: Fri, 21 Feb 2014 16:10:55 +0000 (+0000) Subject: Add a USE_SIGNALS define. X-Git-Tag: v6.3.0~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6618e7ea8b51794b2a9a93d50896a9e50269f19a;p=thirdparty%2Fdhcpcd.git Add a USE_SIGNALS define. If we're not using signals then we also create a control socket in the non MASTER case. We then use this to communicate instead of signals. --- diff --git a/control.c b/control.c index bba78c11..a39176f9 100644 --- a/control.c +++ b/control.c @@ -47,42 +47,32 @@ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) #endif -static void -control_remove(void *arg) -{ - struct dhcpcd_ctx *ctx; - struct fd_list *l, *n, *last = NULL; - - ctx = arg; - l = ctx->control_fds; - while (l) { - n = l->next; - if (l == arg) { - eloop_event_delete(ctx->eloop, l->fd); - close(l->fd); - if (last == NULL) - ctx->control_fds = l->next; - else - last->next = l->next; - free(l); - break; - } - last = l; - l = n; - } -} - static void control_handle_data(void *arg) { - struct fd_list *l = arg; + struct fd_list *l = arg, *lp, *last; char buffer[1024], *e, *p, *argvp[255], **ap; ssize_t bytes; int argc; bytes = read(l->fd, buffer, sizeof(buffer) - 1); if (bytes == -1 || bytes == 0) { - control_remove(l); + /* Control was closed or there was an error. + * Remove it from our list. */ + last = NULL; + for (lp = l->ctx->control_fds; lp; lp = lp->next) { + if (lp == l) { + eloop_event_delete(lp->ctx->eloop, lp->fd); + close(lp->fd); + if (last == NULL) + lp->ctx->control_fds = lp->next; + else + last->next = lp->next; + free(lp); + break; + } + last = lp; + } return; } buffer[bytes] = '\0'; @@ -130,7 +120,7 @@ control_handle(void *arg) } static int -make_sock(struct dhcpcd_ctx *ctx, struct sockaddr_un *sun) +make_sock(struct dhcpcd_ctx *ctx, struct sockaddr_un *sun, const char *ifname) { #ifdef SOCK_CLOEXEC @@ -159,26 +149,29 @@ make_sock(struct dhcpcd_ctx *ctx, struct sockaddr_un *sun) #endif memset(sun, 0, sizeof(*sun)); sun->sun_family = AF_UNIX; - strlcpy(sun->sun_path, CONTROLSOCKET, sizeof(sun->sun_path)); + snprintf(sun->sun_path, sizeof(sun->sun_path), CONTROLSOCKET, + ifname ? "-" : "", ifname ? ifname : ""); + strlcpy(ctx->control_sock, sun->sun_path, sizeof(ctx->control_sock)); return SUN_LEN(sun); } int -control_start(struct dhcpcd_ctx *ctx) +control_start(struct dhcpcd_ctx *ctx, const char *ifname) { struct sockaddr_un sun; int len; - if ((len = make_sock(ctx, &sun)) == -1) + if ((len = make_sock(ctx, &sun, ifname)) == -1) return -1; - unlink(CONTROLSOCKET); + unlink(ctx->control_sock); if (bind(ctx->control_fd, (struct sockaddr *)&sun, len) == -1 || - chmod(CONTROLSOCKET, + chmod(ctx->control_sock, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1 || listen(ctx->control_fd, sizeof(ctx->control_fds)) == -1) { close(ctx->control_fd); ctx->control_fd = -1; + unlink(ctx->control_sock); return -1; } eloop_event_add(ctx->eloop, ctx->control_fd, control_handle, ctx); @@ -191,11 +184,13 @@ control_stop(struct dhcpcd_ctx *ctx) int retval = 0; struct fd_list *l; + if (ctx->control_fd == -1) + return 0; eloop_event_delete(ctx->eloop, ctx->control_fd); if (shutdown(ctx->control_fd, SHUT_RDWR) == -1) retval = 1; ctx->control_fd = -1; - if (unlink(CONTROLSOCKET) == -1) + if (unlink(ctx->control_sock) == -1) retval = -1; l = ctx->control_fds; @@ -211,12 +206,12 @@ control_stop(struct dhcpcd_ctx *ctx) } int -control_open(struct dhcpcd_ctx *ctx) +control_open(struct dhcpcd_ctx *ctx, const char *ifname) { struct sockaddr_un sun; int len; - if ((len = make_sock(ctx, &sun)) == -1) + if ((len = make_sock(ctx, &sun, ifname)) == -1) return -1; if (connect(ctx->control_fd, (struct sockaddr *)&sun, len) == -1) { close(ctx->control_fd); @@ -249,3 +244,13 @@ control_send(struct dhcpcd_ctx *ctx, int argc, char * const *argv) } return write(ctx->control_fd, buffer, p - buffer); } + +void +control_close(struct dhcpcd_ctx *ctx) +{ + + if (ctx->control_fd != -1) { + close(ctx->control_fd); + ctx->control_fd = -1; + } +} diff --git a/control.h b/control.h index 5ca647f7..7a4bb255 100644 --- a/control.h +++ b/control.h @@ -37,9 +37,10 @@ struct fd_list { int listener; }; -int control_start(struct dhcpcd_ctx *); +int control_start(struct dhcpcd_ctx *, const char *); int control_stop(struct dhcpcd_ctx *); -int control_open(struct dhcpcd_ctx *); +int control_open(struct dhcpcd_ctx *, const char *); int control_send(struct dhcpcd_ctx *, int, char * const *); +void control_close(struct dhcpcd_ctx *ctx); #endif diff --git a/defs.h b/defs.h index f477272e..32c49cd8 100644 --- a/defs.h +++ b/defs.h @@ -52,10 +52,19 @@ # define PIDFILE RUNDIR "/" PACKAGE "%s%s.pid" #endif #ifndef CONTROLSOCKET -# define CONTROLSOCKET RUNDIR "/" PACKAGE ".sock" +# define CONTROLSOCKET RUNDIR "/" PACKAGE "%s%s.sock" #endif #ifndef RDM_MONOFILE # define RDM_MONOFILE DBDIR "/" PACKAGE "-rdm.monotonic" #endif +#ifndef NO_SIGNALS +# define USE_SIGNALS +#endif +#ifndef USE_SIGNALS +# ifndef THERE_IS_NO_FORK +# define THERE_IS_NO_FORK +# endif +#endif + #endif diff --git a/dhcpcd.c b/dhcpcd.c index 34251c58..fb232164 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -67,6 +67,7 @@ const char dhcpcd_copyright[] = "Copyright (c) 2006-2014 Roy Marples"; #include "platform.h" #include "script.h" +#ifdef USE_SIGNALS const int handle_sigs[] = { SIGALRM, SIGHUP, @@ -79,7 +80,9 @@ const int handle_sigs[] = { /* Handling signals needs *some* context */ static struct dhcpcd_ctx *dhcpcd_ctx; +#endif +#if defined(USE_SIGNALS) || !defined(THERE_IS_NO_FORK) static pid_t read_pid(const char *pidfile) { @@ -96,6 +99,17 @@ read_pid(const char *pidfile) return pid; } +static inline int +write_pid(int fd, pid_t pid) +{ + + if (ftruncate(fd, (off_t)0) == -1) + return -1; + lseek(fd, (off_t)0, SEEK_SET); + return dprintf(fd, "%d\n", (int)pid); +} +#endif + static void usage(void) { @@ -195,21 +209,12 @@ handle_exit_timeout(void *arg) eloop_timeout_add_sec(ctx->eloop, timeout, handle_exit_timeout, ctx); } -static inline int -write_pid(int fd, pid_t pid) -{ - - if (ftruncate(fd, (off_t)0) == -1) - return -1; - lseek(fd, (off_t)0, SEEK_SET); - return dprintf(fd, "%d\n", (int)pid); -} - /* Returns the pid of the child, otherwise 0. */ pid_t daemonise(struct dhcpcd_ctx *ctx) { #ifdef THERE_IS_NO_FORK + eloop_timeout_delete(ctx->eloop, handle_exit_timeout, ctx); errno = ENOSYS; return 0; #else @@ -821,6 +826,27 @@ reconf_reboot(struct dhcpcd_ctx *ctx, int action, int argc, char **argv, int oi) sort_interfaces(ctx); } +static void +stop_all_interfaces(struct dhcpcd_ctx *ctx, int do_release) +{ + struct interface *ifp; + + /* drop_dhcp could change the order, so we do it like this. */ + for (;;) { + /* Be sane and drop the last config first */ + ifp = TAILQ_LAST(ctx->ifaces, if_head); + if (ifp == NULL) + break; + if (do_release) { + ifp->options->options |= DHCPCD_RELEASE; + ifp->options->options &= ~DHCPCD_PERSISTENT; + } + ifp->options->options |= DHCPCD_EXITING; + stop_interface(ifp); + } +} + +#ifdef USE_SIGNALS struct dhcpcd_siginfo { int signo; pid_t pid; @@ -886,21 +912,8 @@ handle_signal1(void *arg) return; } - if (!(ctx->options & DHCPCD_TEST)) { - /* drop_dhcp could change the order, so we do it like this. */ - for (;;) { - /* Be sane and drop the last config first */ - ifp = TAILQ_LAST(ctx->ifaces, if_head); - if (ifp == NULL) - break; - if (do_release) { - ifp->options->options |= DHCPCD_RELEASE; - ifp->options->options &= ~DHCPCD_PERSISTENT; - } - ifp->options->options |= DHCPCD_EXITING; - stop_interface(ifp); - } - } + if (!(ctx->options & DHCPCD_TEST)) + stop_all_interfaces(ctx, do_release); eloop_exit(ctx->eloop, EXIT_FAILURE); } @@ -917,6 +930,30 @@ handle_signal(__unused int sig, siginfo_t *siginfo, __unused void *context) handle_signal1, &dhcpcd_siginfo); } +static int +signal_init(void (*func)(int, siginfo_t *, void *), sigset_t *oldset) +{ + unsigned int i; + struct sigaction sa; + sigset_t newset; + + sigfillset(&newset); + if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) + return -1; + + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = func; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + + for (i = 0; handle_sigs[i]; i++) { + if (sigaction(handle_sigs[i], &sa, NULL) == -1) + return -1; + } + return 0; +} +#endif + int handle_args(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc, char **argv) { @@ -1000,17 +1037,19 @@ handle_args(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc, char **argv) } /* Log the command */ - len = 0; + len = 1; for (opt = 0; opt < argc; opt++) len += strlen(argv[opt]) + 1; - tmp = p = malloc(len + 1); + tmp = malloc(len); if (tmp == NULL) { syslog(LOG_ERR, "%s: %m", __func__); return -1; } + p = tmp; for (opt = 0; opt < argc; opt++) { l = strlen(argv[opt]); - strlcpy(p, argv[opt], l + 1); + strlcpy(p, argv[opt], len); + len -= l + 1; p += l; *p++ = ' '; } @@ -1037,13 +1076,12 @@ handle_args(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc, char **argv) } } - /* We need at least one interface */ - if (optind == argc) { - syslog(LOG_ERR, "%s: no interface", __func__); - return -1; - } - if (do_release || do_exit) { + if (optind == argc) { + stop_all_interfaces(ctx, do_release); + eloop_exit(ctx->eloop, EXIT_SUCCESS); + return 0; + } for (oi = optind; oi < argc; oi++) { if ((ifp = find_interface(ctx, argv[oi])) == NULL) continue; @@ -1061,29 +1099,6 @@ handle_args(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc, char **argv) return 0; } -static int -signal_init(void (*func)(int, siginfo_t *, void *), sigset_t *oldset) -{ - unsigned int i; - struct sigaction sa; - sigset_t newset; - - sigfillset(&newset); - if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) - return -1; - - memset(&sa, 0, sizeof(sa)); - sa.sa_sigaction = func; - sa.sa_flags = SA_SIGINFO; - sigemptyset(&sa.sa_mask); - - for (i = 0; handle_sigs[i]; i++) { - if (sigaction(handle_sigs[i], &sa, NULL) == -1) - return -1; - } - return 0; -} - int main(int argc, char **argv) { @@ -1092,13 +1107,21 @@ main(int argc, char **argv) struct if_options *ifo; struct interface *ifp; uint16_t family = 0; - int opt, oi = 0, sig = 0, i; + int opt, oi = 0, i; size_t len; +#if defined(USE_SIGNALS) || !defined(THERE_IS_NO_FORK) pid_t pid; +#endif +#ifdef USE_SIGNALS + int sig; +#endif struct timespec ts; memset(&ctx, 0, sizeof(ctx)); - dhcpcd_ctx = &ctx; /* for our signal handler */ +#ifdef USE_SIGNALS + dhcpcd_ctx = &ctx; + sig = 0; +#endif closefrom(3); openlog(PACKAGE, LOG_PERROR | LOG_PID, LOG_DAEMON); setlogmask(LOG_UPTO(LOG_INFO)); @@ -1136,6 +1159,7 @@ main(int argc, char **argv) case 'f': ctx.cffile = optarg; break; +#ifdef USE_SIGNALS case 'g': sig = SIGUSR1; break; @@ -1148,6 +1172,7 @@ main(int argc, char **argv) case 'x': sig = SIGTERM; break; +#endif case 'T': i = 1; break; @@ -1246,12 +1271,20 @@ main(int argc, char **argv) goto exit_success; } +#ifdef USE_SIGNALS if (!(ctx.options & (DHCPCD_MASTER | DHCPCD_TEST))) { - if ((i = control_open(&ctx)) != -1) { +#endif + if (ctx.options & DHCPCD_MASTER) + i = -1; + else + i = control_open(&ctx, argv[optind]); + if (i == -1) + i = control_open(&ctx, NULL); + if (i != -1) { syslog(LOG_INFO, "sending commands to master dhcpcd process"); len = control_send(&ctx, argc, argv); - close(i); + control_close(&ctx); if (len > 0) { syslog(LOG_DEBUG, "send OK"); goto exit_success; @@ -1263,12 +1296,21 @@ main(int argc, char **argv) if (errno != ENOENT) syslog(LOG_ERR, "control_open: %m"); } +#ifdef USE_SIGNALS } +#endif if (geteuid()) syslog(LOG_WARNING, PACKAGE " will not work correctly unless run as root"); + ctx.eloop = eloop_init(); + if (ctx.eloop == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + goto exit_failure; + } + +#ifdef USE_SIGNALS if (sig != 0) { pid = read_pid(pidfile); if (pid != 0) @@ -1335,30 +1377,28 @@ main(int argc, char **argv) } } - syslog(LOG_INFO, "version " VERSION " starting"); - ctx.options |= DHCPCD_STARTED; - ctx.eloop = eloop_init(); - if (ctx.eloop == NULL) { - syslog(LOG_ERR, "%s: %m", __func__); + + if (ctx.options & DHCPCD_MASTER) { + if (control_start(&ctx, NULL) == -1) + syslog(LOG_ERR, "control_start: %m"); + } +#else + if (control_start(&ctx, + ctx.options & DHCPCD_MASTER ? NULL : argv[optind]) == -1) + { + syslog(LOG_ERR, "control_start: %m"); goto exit_failure; } +#endif + syslog(LOG_INFO, "version " VERSION " starting"); + ctx.options |= DHCPCD_STARTED; +#ifdef USE_SIGNALS /* Save signal mask, block and redirect signals to our handler */ if (signal_init(handle_signal, &ctx.sigset) == -1) { syslog(LOG_ERR, "signal_setup: %m"); goto exit_failure; } - - if (ctx.options & DHCPCD_MASTER) { - if (control_start(&ctx) == -1) - syslog(LOG_ERR, "control_start: %m"); - } - -#if 0 - if (options & DHCPCD_IPV6RS && disable_rtadv() == -1) { - syslog(LOG_ERR, "disable_rtadvd: %m"); - options &= ~DHCPCD_IPV6RS; - } #endif ctx.ifc = argc - optind; @@ -1462,7 +1502,7 @@ main(int argc, char **argv) eloop_timeout_add_sec(ctx.eloop, 0, start_interface, ifp); } - i = eloop_start(ctx.eloop, &ctx.sigset); + i = eloop_start(&ctx); goto exit1; exit_success: @@ -1493,11 +1533,9 @@ exit1: ipv4_ctxfree(&ctx); ipv6_ctxfree(&ctx); dev_stop(&ctx, !(ctx.options & DHCPCD_FORKED)); + if (!(ctx.options & DHCPCD_FORKED) && control_stop(&ctx) == -1) + syslog(LOG_ERR, "control_stop: %m:"); if (ctx.pid_fd != -1) { - if (ctx.options & DHCPCD_MASTER) { - if (control_stop(&ctx) == -1) - syslog(LOG_ERR, "control_stop: %m:"); - } close(ctx.pid_fd); unlink(pidfile); } diff --git a/dhcpcd.h b/dhcpcd.h index 895c3e93..eee5ef8e 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -32,6 +32,7 @@ #include #include +#include "defs.h" #include "control.h" #include "if-options.h" @@ -71,7 +72,9 @@ struct interface { TAILQ_HEAD(if_head, interface); struct dhcpcd_ctx { +#ifdef USE_SIGNALS sigset_t sigset; +#endif const char *cffile; unsigned long long options; int argc; @@ -92,6 +95,7 @@ struct dhcpcd_ctx { int control_fd; struct fd_list *control_fds; + char control_sock[sizeof(CONTROLSOCKET) + IF_NAMESIZE]; /* DHCP Enterprise options, RFC3925 */ struct dhcp_opt *vivso; @@ -131,9 +135,12 @@ struct dhcpcd_ctx { #endif }; +#ifdef USE_SIGNALS extern const int handle_sigs[]; +#endif pid_t daemonise(struct dhcpcd_ctx *); + struct interface *find_interface(struct dhcpcd_ctx *, const char *); int handle_args(struct dhcpcd_ctx *, struct fd_list *, int, char **); void handle_carrier(struct dhcpcd_ctx *, int, int, const char *); diff --git a/eloop.c b/eloop.c index a653cb9c..3554b8c9 100644 --- a/eloop.c +++ b/eloop.c @@ -324,8 +324,9 @@ void eloop_free(struct eloop_ctx *ctx) } int -eloop_start(struct eloop_ctx *ctx, const sigset_t *sigmask) +eloop_start(struct dhcpcd_ctx *dctx) { + struct eloop_ctx *ctx; struct timeval now; int n; struct eloop_event *e; @@ -333,7 +334,11 @@ eloop_start(struct eloop_ctx *ctx, const sigset_t *sigmask) struct timeval tv; struct timespec ts, *tsp; void (*t0)(void *); +#ifndef USE_SIGNALS + int timeout; +#endif + ctx = dctx->eloop; for (;;) { if (ctx->exitnow) break; @@ -365,7 +370,20 @@ eloop_start(struct eloop_ctx *ctx, const sigset_t *sigmask) break; } - n = pollts(ctx->fds, ctx->events_len, tsp, sigmask); +#ifdef USE_SIGNALS + n = pollts(ctx->fds, ctx->events_len, tsp, &dctx->sigset); +#else + if (tsp == NULL) + timeout = -1; + else if (tsp->tv_sec > INT_MAX / 1000 || + (tsp->tv_sec == INT_MAX / 1000 && + (tsp->tv_nsec + 999999) / 1000000 > INT_MAX % 1000000)) + timeout = INT_MAX; + else + timeout = tsp->tv_sec * 1000 + + (tsp->tv_nsec + 999999) / 1000000; + n = poll(ctx->fds, ctx->events_len, timeout); +#endif if (n == -1) { if (errno == EAGAIN || errno == EINTR) continue; diff --git a/eloop.h b/eloop.h index 45439cbb..f81eb933 100644 --- a/eloop.h +++ b/eloop.h @@ -94,6 +94,6 @@ void eloop_q_timeouts_delete(struct eloop_ctx *, int, void *, struct eloop_ctx * eloop_init(void); void eloop_free(struct eloop_ctx *); void eloop_exit(struct eloop_ctx *, int); -int eloop_start(struct eloop_ctx *, const sigset_t *); +int eloop_start(struct dhcpcd_ctx *); #endif diff --git a/script.c b/script.c index 13e2a8d8..1fc5538f 100644 --- a/script.c +++ b/script.c @@ -76,26 +76,36 @@ if_printoptions(void) printf(" - %s\n", *p); } +#ifdef USE_SIGNALS +#define U +#else +#define U __unused +#endif static int -exec_script(const sigset_t *sigs, char *const *argv, char *const *env) +exec_script(U const struct dhcpcd_ctx *ctx, char *const *argv, char *const *env) +#undef U { pid_t pid; posix_spawnattr_t attr; + int i; +#ifdef USE_SIGNALS short flags; sigset_t defsigs; - int i; +#endif /* posix_spawn is a safe way of executing another image * and changing signals back to how they should be. */ if (posix_spawnattr_init(&attr) == -1) return -1; +#ifdef USE_SIGNALS flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF; posix_spawnattr_setflags(&attr, flags); sigemptyset(&defsigs); for (i = 0; i < handle_sigs[i]; i++) sigaddset(&defsigs, handle_sigs[i]); posix_spawnattr_setsigdefault(&attr, &defsigs); - posix_spawnattr_setsigmask(&attr, sigs); + posix_spawnattr_setsigmask(&attr, &ctx->sigset); +#endif errno = 0; i = posix_spawn(&pid, argv[0], NULL, &attr, argv, env); if (i) { @@ -557,7 +567,7 @@ script_runreason(const struct interface *ifp, const char *reason) } env[++elen] = NULL; - pid = exec_script(&ifp->ctx->sigset, argv, env); + pid = exec_script(ifp->ctx, argv, env); if (pid == -1) syslog(LOG_ERR, "%s: %s: %m", __func__, argv[0]); else if (pid != 0) {