From: Roy Marples Date: Fri, 7 Jun 2013 12:44:19 +0000 (+0000) Subject: Move signal handling into dhcpcd.c X-Git-Tag: v6.0.0~39 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=336dd1b83b3cec02226dfb3048e0be895aafbd37;p=thirdparty%2Fdhcpcd.git Move signal handling into dhcpcd.c Log the PID of the signal caller Move syslog functions out of the signal handler if we're not exiting as it's not safe. Close existing IPv4 sockets when restarting an interface. Fix control handling keeping current flags and accepting new ones. --- diff --git a/Makefile b/Makefile index b941c6e7..e11b4071 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ PROG= dhcpcd SRCS= common.c control.c dhcpcd.c duid.c eloop.c -SRCS+= if-options.c if-pref.c net.c script.c signals.c +SRCS+= if-options.c if-pref.c net.c script.c SRCS+= dhcp-common.c CFLAGS?= -O2 diff --git a/dhcp.c b/dhcp.c index 6c25da9a..8e95ff7e 100644 --- a/dhcp.c +++ b/dhcp.c @@ -2522,17 +2522,17 @@ dhcp_init(struct interface *ifp) if (state == NULL) { ifp->if_data[IF_DATA_DHCP] = calloc(1, sizeof(*state)); state = D_STATE(ifp); + if (state == NULL) + return -1; + /* 0 is a valid fd, so init to -1 */ + state->raw_fd = state->udp_fd = state->arp_fd = -1; } - if (state == NULL) - return -1; state->state = DHS_INIT; state->reason = "PREINIT"; state->nakoff = 0; snprintf(state->leasefile, sizeof(state->leasefile), LEASEFILE, ifp->name); - /* 0 is a valid fd, so init to -1 */ - state->raw_fd = state->udp_fd = state->arp_fd = -1; ifo = ifp->options; /* We need to drop the leasefile so that start_interface @@ -2618,6 +2618,9 @@ dhcp_start(struct interface *ifp) return; } + /* Close any pre-existing sockets as we're starting over */ + dhcp_close(ifp); + state = D_STATE(ifp); state->start_uptime = uptime(); free(state->offer); diff --git a/dhcp6.c b/dhcp6.c index d50092b9..7604de81 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -2300,6 +2300,16 @@ dhcp6_start(struct interface *ifp, enum DH6S init_state) return 0; } +void +dhcp6_reboot(struct interface *ifp) +{ + struct dhcp6_state *state; + + state = D6_STATE(ifp); + if (state && state->state == DH6S_BOUND) + dhcp6_startrebind(ifp); +} + static void dhcp6_freedrop(struct interface *ifp, int drop, const char *reason) { diff --git a/dhcp6.h b/dhcp6.h index f1b8c7dc..4cd28051 100644 --- a/dhcp6.h +++ b/dhcp6.h @@ -216,6 +216,7 @@ void dhcp6_printoptions(void); int dhcp6_addrexists(const struct ipv6_addr *); int dhcp6_find_delegates(struct interface *); int dhcp6_start(struct interface *, enum DH6S); +void dhcp6_reboot(struct interface *); ssize_t dhcp6_env(char **, const char *, const struct interface *, const struct dhcp6_message *, ssize_t); void dhcp6_free(struct interface *); @@ -226,6 +227,7 @@ void dhcp6_drop(struct interface *, const char *); #define dhcp6_addrexists(a) #define dhcp6_find_delegates(a); #define dhcp6_start(a, b) 0 +#define dhcp6_reboot(a) #define dhcp6_env(a, b, c, d, e) #define dhcp6_free(a) #define dhcp6_drop(a, b) diff --git a/dhcpcd.c b/dhcpcd.c index 253d3dfc..25e98072 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -66,7 +66,6 @@ const char copyright[] = "Copyright (c) 2006-2013 Roy Marples"; #include "net.h" #include "platform.h" #include "script.h" -#include "signals.h" struct if_head *ifaces = NULL; char vendor[VENDORCLASSID_MAX_LEN]; @@ -78,6 +77,15 @@ int ifdc = 0; char **ifdv = NULL; sigset_t dhcpcd_sigset; +const int handle_sigs[] = { + SIGALRM, + SIGHUP, + SIGINT, + SIGPIPE, + SIGTERM, + SIGUSR1, + 0 +}; static char *cffile; static char *pidfile; @@ -611,6 +619,7 @@ if_reboot(struct interface *ifp, int argc, char **argv) oldopts = ifp->options->options; configure_interface(ifp, argc, argv); dhcp_reboot_newopts(ifp, oldopts); + dhcp6_reboot(ifp); start_interface(ifp); } @@ -634,8 +643,8 @@ reconf_reboot(int action, int argc, char **argv, int oi) ipv4_applyaddr(ifn); free_interface(ifp); } else { - TAILQ_INSERT_TAIL(ifaces, ifp, next); init_state(ifp, argc, argv); + TAILQ_INSERT_TAIL(ifaces, ifp, next); start_interface(ifp); } } @@ -646,11 +655,15 @@ reconf_reboot(int action, int argc, char **argv, int oi) /* ARGSUSED */ static void -sig_reboot(__unused void *arg) +sig_reboot(void *arg) { + siginfo_t *siginfo = arg; struct if_options *ifo; int i; + syslog(LOG_INFO, "received SIGALRM from PID %d, rebinding", + (int)siginfo->si_pid); + for (i = 0; i < ifac; i++) free(ifav[i]); free(ifav); @@ -674,17 +687,20 @@ sig_reboot(__unused void *arg) } static void -sig_reconf(__unused void *arg) +sig_reconf(void *arg) { + siginfo_t *siginfo = arg; struct interface *ifp; + syslog(LOG_INFO, "received SIGUSR from PID %d, reconfiguring", + (int)siginfo->si_pid); TAILQ_FOREACH(ifp, ifaces, next) { ipv4_applyaddr(ifp); } } -void -handle_signal(int sig) +static void +handle_signal(int sig, siginfo_t *siginfo, __unused void *context) { struct interface *ifp; int do_release; @@ -692,30 +708,32 @@ handle_signal(int sig) do_release = 0; switch (sig) { case SIGINT: - syslog(LOG_INFO, "received SIGINT, stopping"); + syslog(LOG_INFO, "received SIGINT from PID %d, stopping", + (int)siginfo->si_pid); break; case SIGTERM: - syslog(LOG_INFO, "received SIGTERM, stopping"); + syslog(LOG_INFO, "received SIGTERM from PID %d, stopping", + (int)siginfo->si_pid); break; case SIGALRM: - syslog(LOG_INFO, "received SIGALRM, rebinding"); - eloop_timeout_add_now(sig_reboot, NULL); + eloop_timeout_add_now(sig_reboot, siginfo); return; case SIGHUP: - syslog(LOG_INFO, "received SIGHUP, releasing"); + syslog(LOG_INFO, "received SIGHUP from PID %d, releasing", + (int)siginfo->si_pid); do_release = 1; break; case SIGUSR1: - syslog(LOG_INFO, "received SIGUSR, reconfiguring"); - eloop_timeout_add_now(sig_reconf, NULL); + eloop_timeout_add_now(sig_reconf, siginfo); return; case SIGPIPE: syslog(LOG_WARNING, "received SIGPIPE"); return; default: syslog(LOG_ERR, - "received signal %d, but don't know what to do with it", - sig); + "received signal %d from PID %d, " + "but don't know what to do with it", + sig, (int)siginfo->si_pid); return; } @@ -876,6 +894,29 @@ handle_args(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) { diff --git a/dhcpcd.h b/dhcpcd.h index 61af4664..50b0174b 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -77,13 +77,14 @@ extern int ifdc; extern char **ifdv; extern struct if_options *if_options; +extern const int handle_sigs[]; + pid_t daemonise(void); struct interface *find_interface(const char *); int handle_args(struct fd_list *, int, char **); void handle_carrier(int, int, const char *); void handle_interface(int, const char *); void handle_hwaddr(const char *, unsigned char *, size_t); -void handle_signal(int); void drop_interface(struct interface *, const char *); int select_profile(struct interface *, const char *); diff --git a/net.c b/net.c index 04b29743..ae932243 100644 --- a/net.c +++ b/net.c @@ -241,8 +241,6 @@ discover_interfaces(int argc, char * const *argv) const struct sockaddr_ll *sll; #endif - - if (getifaddrs(&ifaddrs) == -1) return NULL; @@ -289,23 +287,23 @@ discover_interfaces(int argc, char * const *argv) continue; p = argv[i]; } else { + p = ifa->ifa_name; /* -1 means we're discovering against a specific * interface, but we still need the below rules * to apply. */ if (argc == -1 && strcmp(argv[0], ifa->ifa_name) != 0) continue; - for (i = 0; i < ifdc; i++) - if (!fnmatch(ifdv[i], ifa->ifa_name, 0)) - break; - if (i < ifdc) - continue; - for (i = 0; i < ifac; i++) - if (!fnmatch(ifav[i], ifa->ifa_name, 0)) - break; - if (ifac && i == ifac) - continue; - p = ifa->ifa_name; } + for (i = 0; i < ifdc; i++) + if (!fnmatch(ifdv[i], p, 0)) + break; + if (i < ifdc) + continue; + for (i = 0; i < ifac; i++) + if (!fnmatch(ifav[i], p, 0)) + break; + if (ifac && i == ifac) + continue; ifp = calloc(1, sizeof(*ifp)); if (ifp == NULL) diff --git a/script.c b/script.c index 8617bfb1..80dfaa2f 100644 --- a/script.c +++ b/script.c @@ -51,7 +51,6 @@ #include "ipv6rs.h" #include "net.h" #include "script.h" -#include "signals.h" #define DEFAULT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin" diff --git a/signals.c b/signals.c deleted file mode 100644 index 4e2d299b..00000000 --- a/signals.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright (c) 2006-2013 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include - -#include "common.h" -#include "eloop.h" -#include "signals.h" - -static int signal_pipe[2]; -static void (*signal_callback)(int); - -const int handle_sigs[] = { - SIGALRM, - SIGHUP, - SIGINT, - SIGPIPE, - SIGTERM, - SIGUSR1, - 0 -}; - -static void -signal_handler(int sig) -{ - int serrno = errno; - - if (write(signal_pipe[1], &sig, sizeof(sig)) != sizeof(sig)) - syslog(LOG_ERR, "%s: write: %m", __func__); - errno = serrno; -} - -/* ARGSUSED */ -static void -signal_read(__unused void *arg) -{ - int sig = -1; - char buf[16]; - ssize_t bytes; - - memset(buf, 0, sizeof(buf)); - bytes = read(signal_pipe[0], buf, sizeof(buf)); - if (signal_callback && bytes >= 0 && (size_t)bytes >= sizeof(sig)) { - memcpy(&sig, buf, sizeof(sig)); - signal_callback(sig); - } -} - -static int -signal_handle(void (*func)(int)) -{ - unsigned int i; - struct sigaction sa; - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = func; - sigemptyset(&sa.sa_mask); - - for (i = 0; handle_sigs[i]; i++) { - if (sigaction(handle_sigs[i], &sa, NULL) == -1) - return -1; - } - return 0; -} - -int -signal_setup(void) -{ - - return signal_handle(signal_handler); -} - -int -signal_reset(void) -{ - - return signal_handle(SIG_DFL); -} - -int -signal_init(void (*func)(int), sigset_t *oldset) -{ - sigset_t newset; - - if (pipe(signal_pipe) == -1) - return -1; - if (set_nonblock(signal_pipe[0]) == -1) - return -1; - if (set_cloexec(signal_pipe[0]) == -1 || - set_cloexec(signal_pipe[1] == -1)) - return -1; - - sigfillset(&newset); - if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) - return -1; - - /* Because functions we need to reboot/reconf out interfaces - * are not async signal safe, we need to setup a signal pipe - * so that the actual handler is executed in our event loop. */ - signal_callback = func; - eloop_event_add(signal_pipe[0], signal_read, NULL); - return signal_setup(); -} diff --git a/signals.h b/signals.h deleted file mode 100644 index eb5e5fff..00000000 --- a/signals.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright (c) 2006-2013 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef SIGNALS_H -#define SIGNALS_H - -extern const int handle_sigs[]; - -int signal_setup(void); -int signal_reset(void); -int signal_init(void (*)(int), sigset_t *); - -#endif