]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Move signal handling into dhcpcd.c
authorRoy Marples <roy@marples.name>
Fri, 7 Jun 2013 12:44:19 +0000 (12:44 +0000)
committerRoy Marples <roy@marples.name>
Fri, 7 Jun 2013 12:44:19 +0000 (12:44 +0000)
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.

Makefile
dhcp.c
dhcp6.c
dhcp6.h
dhcpcd.c
dhcpcd.h
net.c
script.c
signals.c [deleted file]
signals.h [deleted file]

index b941c6e76e6fcd096a11d6e861383e26de9378ca..e11b40713f9088a63e1dcf2e9ae5015797eda808 100644 (file)
--- 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 6c25da9ad4613e101c501030e3ad0333b1bc0797..8e95ff7e1692aea93d4f7f02cfa68a8f519972d2 100644 (file)
--- 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 d50092b9b6cd97eb89a243be346838a362fa2d86..7604de812ca58416ef31205bed656eb973745d16 100644 (file)
--- 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 f1b8c7dc345fb0f47b0a688b35435f83105e219b..4cd280512283f1717c6a4de8b8aa8617dbef793e 100644 (file)
--- 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)
index 253d3dfc43198c6fc357302903aa6e7c01977d93..25e98072ca13b1d35e8189e5a68d5bf10d48c6f5 100644 (file)
--- 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)
 {
index 61af4664690500439664e10ae47fd40ec49a5dda..50b0174b2ff79e70b8897a7b9aa145dda0fae70d 100644 (file)
--- 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 04b29743c61b32aa5151e439d99690863f8c08aa..ae932243454f5f43e7569839599e35342ed1f40e 100644 (file)
--- 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)
index 8617bfb18a202e08cd495bc43efc855448136c97..80dfaa2fdcb6b7cf008ed8ee91b60767b21f6aba 100644 (file)
--- 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 (file)
index 4e2d299..0000000
--- a/signals.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
- * 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 <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#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 (file)
index eb5e5ff..0000000
--- a/signals.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
- * 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