summaryrefslogtreecommitdiffstats
path: root/dhcpcd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2014-02-21 16:10:55 +0000
committerRoy Marples <roy@marples.name>2014-02-21 16:10:55 +0000
commit6618e7ea8b51794b2a9a93d50896a9e50269f19a (patch)
tree64dcdac3000bb7ad228592a6acbd8ae2e82f17fc /dhcpcd.c
parent11a06bb9b129a3dd3c872e142bd3334cf560bb54 (diff)
downloaddhcpcd-6618e7ea8b51794b2a9a93d50896a9e50269f19a.tar.xz
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.
Diffstat (limited to 'dhcpcd.c')
-rw-r--r--dhcpcd.c202
1 files changed, 120 insertions, 82 deletions
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);
}