From: Roy Marples Date: Wed, 3 Sep 2008 16:49:28 +0000 (+0000) Subject: Add a control socket so that interfaces can be dynamically re-set. X-Git-Tag: v5.0.0~312 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f43e585355e50bd2e7021380db6fc792662f76be;p=thirdparty%2Fdhcpcd.git Add a control socket so that interfaces can be dynamically re-set. This requires the event loop argument being changed to void * so we can send arguments other than an interface. --- diff --git a/Makefile b/Makefile index 58ca6ba0..691f6b92 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # Copyright 2008 Roy Marples PROG= dhcpcd -SRCS= arp.c bind.c common.c dhcp.c dhcpcd.c duid.c eloop.c +SRCS= arp.c bind.c common.c control.c dhcp.c dhcpcd.c duid.c eloop.c SRCS+= if-options.c ipv4ll.c logger.c net.c signals.c SRCS+= configure.c SRCS+= ${SRC_IF} ${SRC_PF} diff --git a/arp.c b/arp.c index 71431dc8..8935ea65 100644 --- a/arp.c +++ b/arp.c @@ -52,9 +52,10 @@ handle_arp_failure(struct interface *iface) add_timeout_sec(DHCP_ARP_FAIL, start_interface, iface); } -void -handle_arp_packet(struct interface *iface) +static void +handle_arp_packet(void *arg) { + struct interface *iface = arg; struct arphdr reply; uint32_t reply_s; uint32_t reply_t; @@ -123,8 +124,9 @@ handle_arp_packet(struct interface *iface) } void -send_arp_announce(struct interface *iface) +send_arp_announce(void *arg) { + struct interface *iface = arg; struct if_state *state = iface->state; struct timeval tv; @@ -167,8 +169,9 @@ send_arp_announce(struct interface *iface) } void -send_arp_probe(struct interface *iface) +send_arp_probe(void *arg) { + struct interface *iface = arg; struct if_state *state = iface->state; struct in_addr addr; struct timeval tv; diff --git a/arp.h b/arp.h index 3cfe55a7..c9bc9e49 100644 --- a/arp.h +++ b/arp.h @@ -28,8 +28,6 @@ #ifndef ARP_H #define ARP_H -#include "dhcpcd.h" - /* These are for IPV4LL, RFC 3927. * We put them here as we use the timings for all ARP foo. */ #define PROBE_WAIT 1 @@ -43,7 +41,6 @@ #define RATE_LIMIT_INTERVAL 60 #define DEFEND_INTERVAL 10 -void send_arp_announce(struct interface *); -void send_arp_probe(struct interface *); -void handle_arp_packet(struct interface *); +void send_arp_announce(void *); +void send_arp_probe(void *); #endif diff --git a/bind.c b/bind.c index 452738cd..22cfd045 100644 --- a/bind.c +++ b/bind.c @@ -98,8 +98,10 @@ daemonise(void) } #endif -void bind_interface(struct interface *iface) +void +bind_interface(void *arg) { + struct interface *iface = arg; struct if_state *state = iface->state; struct if_options *ifo = state->options; struct dhcp_lease *lease = &state->lease; diff --git a/bind.h b/bind.h index 5aaabf70..f64d1c66 100644 --- a/bind.h +++ b/bind.h @@ -29,7 +29,6 @@ #define BIND_H #include "config.h" -#include "dhcpcd.h" #ifdef THERE_IS_NO_FORK #define daemonise() {} #else @@ -37,5 +36,5 @@ pid_t daemonise(void); #endif extern int can_daemonise; -void bind_interface(struct interface *); +void bind_interface(void *); #endif diff --git a/config.h b/config.h index 801c89cd..7315fa02 100644 --- a/config.h +++ b/config.h @@ -71,5 +71,8 @@ #ifndef PIDFILE # define PIDFILE RUNDIR "/" PACKAGE "%s%s.pid" #endif +#ifndef CONTROLSOCKET +# define CONTROLSOCKET RUNDIR "/" PACKAGE ".sock" +#endif #endif diff --git a/control.c b/control.c new file mode 100644 index 00000000..6b0f1a19 --- /dev/null +++ b/control.c @@ -0,0 +1,163 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright 2006-2008 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 +#include + +#include "config.h" +#include "common.h" +#include "control.h" +#include "eloop.h" +#include "dhcpcd.h" + +static int fd = -1; +struct sockaddr_un sun; +static char buffer[1024]; +static char *argvp[255]; + +static void +handle_control_data(void *arg) +{ + ssize_t bytes; + int argc, s = (int)arg; + char *e, *p; + char **ap; + + for (;;) { + bytes = read(s, buffer, sizeof(buffer)); + if (bytes == -1 || bytes == 0) { + close(s); + delete_event(s); + return; + } + p = buffer; + e = buffer + bytes; + argc = 0; + ap = argvp; + while (p < e && (size_t)argc < sizeof(argvp)) { + argc++; + *ap++ = p; + p += strlen(p) + 1; + } + handle_args(argc, argvp); + } +} + +static void +handle_control(_unused void *arg) +{ + struct sockaddr_un run; + socklen_t len; + int s; + + len = sizeof(run); + if ((s = accept(fd, (struct sockaddr *)&run, &len)) == -1) + return; + add_event(s, handle_control_data, (void *)s); +} + +static int +make_sock(void) +{ + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) + return -1; + memset(&sun, 0, sizeof(sun)); + sun.sun_family = AF_UNIX; + strlcpy(sun.sun_path, CONTROLSOCKET, sizeof(sun.sun_path)); + return sizeof(sun.sun_family) + strlen(sun.sun_path) + 1; +} + +int +start_control(void) +{ + int len; + + if ((len = make_sock()) == -1) + return -1; + unlink(CONTROLSOCKET); + if (bind(fd, (struct sockaddr *)&sun, len) == -1 || + chmod(CONTROLSOCKET, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1 || + set_cloexec(fd) == -1 || + set_nonblock(fd) == -1 || + listen(fd, 0) == -1) + { + close(fd); + return -1; + } + add_event(fd, handle_control, NULL); + return fd; +} + +int +stop_control(void) +{ + int retval = 0; + if (close(fd) == -1) + retval = 1; + if (unlink(CONTROLSOCKET) == -1) + retval = -1; + return retval; +} + +int +open_control(void) +{ + int len; + + if ((len = make_sock()) == -1) + return -1; + return connect(fd, (struct sockaddr *)&sun, len); +} + +int +send_control(int argc, char * const *argv) +{ + char *p = buffer; + int i; + size_t len; + + if (argc > 255) { + errno = ENOBUFS; + return -1; + } + for (i = 0; i < argc; i++) { + len = strlen(argv[i]) + 1; + if ((p - buffer) + len > sizeof(buffer)) { + errno = ENOBUFS; + return -1; + } + memcpy(p, argv[i], len); + p += len; + } + return write(fd, buffer, p - buffer); +} diff --git a/control.h b/control.h new file mode 100644 index 00000000..44406902 --- /dev/null +++ b/control.h @@ -0,0 +1,38 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright 2006-2008 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 CONTROL_H +#define CONTROL_H + +#include "dhcpcd.h" + +int start_control(void); +int stop_control(void); +int open_control(void); +int send_control(int, char * const *); + +#endif diff --git a/dhcpcd.8.in b/dhcpcd.8.in index 68d7f950..aba3b866 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 1, 2008 +.Dd September 3, 2008 .Dt DHCPCD 8 SMM .Sh NAME .Nm dhcpcd @@ -436,9 +436,10 @@ RFC 3442, RFC 3927, RFC 4361, RFC 4390, RFC 4702. .Sh AUTHORS .An Roy Marples .Sh BUGS -You cannot release a lease - this will be fixed before the first release. -.Pp -You cannot dynamically add or remove interfaces either manually or detected. +.Nm +does not wait for commands to complete when sending them to the master +.Nm +process. .Pp One of the goals for one instance managing multiple interfaces is more intelligent route and configuration management. diff --git a/dhcpcd.c b/dhcpcd.c index 96d8cf70..c84164eb 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -50,6 +50,7 @@ const char copyright[] = "Copyright (c) 2006-2008 Roy Marples"; #include "config.h" #include "common.h" #include "configure.h" +#include "control.h" #include "dhcpcd.h" #include "dhcpf.h" #include "duid.h" @@ -63,13 +64,13 @@ const char copyright[] = "Copyright (c) 2006-2008 Roy Marples"; /* We should define a maximum for the NAK exponential backoff */ #define NAKOFF_MAX 60 +int master = 0; int pidfd = -1; static int linkfd = -1; static char cffile[PATH_MAX]; static char pidfile[PATH_MAX] = { '\0' }; static struct interface *ifaces = NULL; - struct dhcp_op { uint8_t value; const char *name; @@ -140,13 +141,18 @@ cleanup(void) if (linkfd != -1) close(linkfd); if (pidfd > -1) { + if (master) { + if (stop_control() == -1) + logger(LOG_ERR, "stop_control: %s", + strerror(errno)); + } close(pidfd); unlink(pidfile); } } void -handle_exit_timeout(_unused struct interface *iface) +handle_exit_timeout(_unused void *arg) { logger(LOG_ERR, "timed out"); exit(EXIT_FAILURE); @@ -186,7 +192,7 @@ close_sockets(struct interface *iface) static void send_message(struct interface *iface, int type, - void (*function)(struct interface *)) + void (*callback)(void *)) { struct if_state *state = iface->state; struct dhcp_message *dhcp; @@ -196,7 +202,7 @@ send_message(struct interface *iface, int type, in_addr_t a = 0; struct timeval tv; - if (!function) + if (!callback) logger(LOG_DEBUG, "%s: sending %s with xid 0x%x", iface->name, get_dhcp_op(type), state->xid); else { @@ -243,31 +249,33 @@ send_message(struct interface *iface, int type, iface->name, strerror(errno)); } free(dhcp); - if (function) - add_timeout_tv(&tv, function, iface); + if (callback) + add_timeout_tv(&tv, callback, iface); } static void -send_discover(struct interface *iface) +send_discover(void *arg) { - send_message(iface, DHCP_DISCOVER, send_discover); + send_message((struct interface *)arg, DHCP_DISCOVER, send_discover); } void -send_request(struct interface *iface) +send_request(void *arg) { - send_message(iface, DHCP_REQUEST, send_request); + send_message((struct interface *)arg, DHCP_REQUEST, send_request); } static void -send_renew(struct interface *iface) +send_renew(void *arg) { - send_message(iface, DHCP_REQUEST, send_renew); + send_message((struct interface *)arg, DHCP_REQUEST, send_renew); } void -start_renew(struct interface *iface) +start_renew(void *arg) { + struct interface *iface = arg; + logger(LOG_INFO, "%s: renewing lease of %s", iface->name, inet_ntoa(iface->state->lease.addr)); iface->state->state = DHS_RENEWING; @@ -276,14 +284,16 @@ start_renew(struct interface *iface) } static void -send_rebind(struct interface *iface) +send_rebind(void *arg) { - send_message(iface, DHCP_REQUEST, send_rebind); + send_message((struct interface *)arg, DHCP_REQUEST, send_rebind); } void -start_rebind(struct interface *iface) +start_rebind(void *arg) { + struct interface *iface = arg; + logger(LOG_ERR, "%s: failed to renew, attmepting to rebind", iface->name); iface->state->state = DHS_REBINDING; @@ -293,8 +303,9 @@ start_rebind(struct interface *iface) } void -start_expire(struct interface *iface) +start_expire(void *arg) { + struct interface *iface = arg; int ll = IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr)); logger(LOG_ERR, "%s: lease expired", iface->name); @@ -468,8 +479,9 @@ handle_dhcp(struct interface *iface, struct dhcp_message **dhcpp) } static void -handle_dhcp_packet(struct interface *iface) +handle_dhcp_packet(void *arg) { + struct interface *iface = arg; uint8_t *packet; struct dhcp_message *dhcp = NULL; const uint8_t *pp; @@ -552,8 +564,9 @@ open_sockets(struct interface *iface) } static void -handle_link(struct interface *iface) +handle_link(_unused void *arg) { + struct interface *iface; int retval; retval = link_changed(linkfd, ifaces); @@ -593,8 +606,9 @@ handle_link(struct interface *iface) } void -start_discover(struct interface *iface) +start_discover(void *arg) { + struct interface *iface = arg; struct if_options *ifo = iface->state->options; iface->state->state = DHS_DISCOVERING; @@ -630,9 +644,24 @@ start_reboot(struct interface *iface) send_rebind(iface); } +static void +send_release(struct interface *iface) +{ + if (iface->state->lease.addr.s_addr && + !IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr))) + { + logger(LOG_INFO, "%s: releasing lease of %s", + iface->name, inet_ntoa(iface->state->lease.addr)); + open_sockets(iface); + send_message(iface, DHCP_RELEASE, NULL); + } +} + void -start_interface(struct interface *iface) +start_interface(void *arg) { + struct interface *iface = arg; + iface->start_uptime = uptime(); if (!iface->state->lease.addr.s_addr) start_discover(iface); @@ -643,25 +672,18 @@ start_interface(struct interface *iface) } static void -init_state(struct interface *iface, int argc, char **argv) +configure_interface(struct interface *iface, int argc, char **argv) { - struct if_state *ifs; + struct if_state *ifs = iface->state; struct if_options *ifo; uint8_t *duid; size_t len = 0, ifl; - if (iface->state) { - ifs = iface->state; - free_options(ifs->options); - } else - ifs = iface->state = xzalloc(sizeof(*ifs)); - - ifs->state = DHS_INIT; - ifs->nakoff = 1; + free_options(ifs->options); ifo = ifs->options = read_config(cffile, iface->name); add_options(ifo, argc, argv); - if (ifo->metric) + if (ifo->metric != -1) iface->metric = ifo->metric; if (*ifo->clientid) { @@ -696,10 +718,26 @@ init_state(struct interface *iface, int argc, char **argv) } } - if (!(ifo->options & DHCPCD_TEST)) +} + +static void +init_state(struct interface *iface, int argc, char **argv) +{ + struct if_state *ifs; + + if (iface->state) { + ifs = iface->state; + } else + ifs = iface->state = xzalloc(sizeof(*ifs)); + + ifs->state = DHS_INIT; + ifs->nakoff = 1; + configure_interface(iface, argc, argv); + + if (!(ifs->options->options & DHCPCD_TEST)) run_script(iface, "PREINIT"); - if (ifo->options & DHCPCD_LINK) { + if (ifs->options->options & DHCPCD_LINK) { switch (carrier_status(iface->name)) { case 0: ifs->carrier = LINK_DOWN; @@ -719,9 +757,11 @@ init_state(struct interface *iface, int argc, char **argv) } static void -handle_signal(struct interface *iface) +handle_signal(_unused void *arg) { + struct interface *iface; int sig = signal_read(); + int do_reboot = 0, do_release = 0; switch (sig) { case SIGINT: @@ -730,6 +770,14 @@ handle_signal(struct interface *iface) case SIGTERM: logger(LOG_INFO, "received SIGTERM, stopping"); break; + case SIGALRM: + logger(LOG_INFO, "received SIGALRM, rebinding lease"); + do_reboot = 1; + break; + case SIGHUP: + logger(LOG_INFO, "received SIGHUP, releasing lease"); + do_release = 1; + break; default: logger (LOG_ERR, "received signal %d, but don't know what to do with it", @@ -740,18 +788,97 @@ handle_signal(struct interface *iface) for (iface = ifaces; iface; iface = iface->next) { if (!iface->state) continue; - if (!(iface->state->options->options & DHCPCD_PERSISTENT)) - drop_config(iface, "STOP"); + if (do_reboot) + start_reboot(iface); + else { + if (do_release) + send_release(iface); + if (!(iface->state->options->options & DHCPCD_PERSISTENT)) + drop_config(iface, do_release ? "RELEASE" : "STOP"); + } } exit(EXIT_FAILURE); } +int +handle_args(int argc, char **argv) +{ + struct interface *ifs, *ifp, *ifl = NULL, *ifn; + int do_exit = 0, do_release = 0, do_reboot = 0, opt, oi = 0; + + optind = 0; + while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1) + { + switch (opt) { + case 'k': + do_release = 1; + break; + case 'n': + do_reboot = 1; + break; + case 'x': + do_exit = 1; + break; + } + } + + /* We only deal with one interface here */ + if (optind == argc) { + logger(LOG_ERR, "handle_args: no interface"); + return -1; + } + + if (do_release || do_reboot || do_exit) { + oi = optind; + while (oi < argc) { + for (ifp = ifaces; ifp && (ifn = ifp->next, 1); ifp = ifn) { + if (strcmp(ifp->name, argv[oi]) == 0) { + if (do_release) + send_release(ifp); + if (do_exit || do_release) { + drop_config(ifp, do_release ? "RELEASE" : "STOP"); + close_sockets(ifp); + delete_timeout(NULL, ifp); + if (ifl) + ifl->next = ifp->next; + else + ifaces = ifp->next; + free_interface(ifp); + continue; + } else if (do_reboot) { + configure_interface(ifp, argc, argv); + start_reboot(ifp); + } + } + ifl = ifp; + } + oi++; + } + return 0; + } + + if ((ifs = discover_interfaces(argc, argv))) { + argc += optind; + argv -= optind; + for (ifp = ifs; ifp; ifp = ifp->next) + init_state(ifp, argc, argv); + if (ifaces) { + ifp = ifaces; + while (ifp->next) + ifp = ifp->next; + ifp->next = ifs; + } else + ifaces = ifs; + } + return 0; +} + int main(int argc, char **argv) { struct if_options *ifo; struct interface *iface; - int opt, oi = 0, test = 0, signal_fd, sig = 0, i; + int opt, oi = 0, test = 0, signal_fd, sig = 0, i, control_fd; pid_t pid; struct timespec ts; @@ -781,6 +908,12 @@ main(int argc, char **argv) case 'f': strlcpy(cffile, optarg, sizeof(cffile)); break; + case 'k': + sig = SIGHUP; + break; + case 'n': + sig = SIGALRM; + break; case 'x': sig = SIGTERM; break; @@ -803,27 +936,45 @@ main(int argc, char **argv) usage(); exit(EXIT_FAILURE); } - if (test) - ifo->options |= DHCPCD_TEST | DHCPCD_PERSISTENT; -#ifdef THERE_IS_NO_FORK - ifo->options &= ~DHCPCD_DAEMONISE; -#endif /* If we have any other args, we should run as a single dhcpcd instance * for that interface. */ if (optind == argc - 1) snprintf(pidfile, sizeof(pidfile), PIDFILE, "-", argv[optind]); - else + else { snprintf(pidfile, sizeof(pidfile), PIDFILE, "", ""); - - if (geteuid()) - logger(LOG_WARNING, PACKAGE " will not work correctly unless" - " run as root"); + master = 1; + } + + if (test) + ifo->options |= DHCPCD_TEST | DHCPCD_PERSISTENT; +#ifdef THERE_IS_NO_FORK + ifo->options &= ~DHCPCD_DAEMONISE; +#endif chdir("/"); umask(022); atexit(cleanup); + if (!master) { + control_fd = open_control(); + if (control_fd != -1) { + logger(LOG_INFO, "sending commands to master dhcpcd process"); + i = send_control(argc, argv); + if (i > 0) { + logger(LOG_DEBUG, "send OK"); + exit(EXIT_SUCCESS); + } else { + logger(LOG_ERR, "failed to send commands"); + exit(EXIT_FAILURE); + } + } + } + + if (geteuid()) + logger(LOG_WARNING, PACKAGE " will not work correctly unless" + " run as root"); + if (sig != 0) { i = -1; pid = read_pid(); @@ -886,6 +1037,13 @@ main(int argc, char **argv) exit(EXIT_FAILURE); add_event(signal_fd, handle_signal, NULL); + if (master) { + if (start_control() == -1) { + logger(LOG_ERR, "start_control: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + } + if (ifo->options & DHCPCD_LINK) { linkfd = open_link_socket(); if (linkfd == -1) diff --git a/dhcpcd.h b/dhcpcd.h index 86aa4959..c2ea5c78 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -28,7 +28,6 @@ #ifndef DHCPCD_H #define DHCPCD_H -#include #include #include @@ -105,14 +104,15 @@ struct interface }; extern int pidfd; -void handle_exit_timeout(struct interface *); -void send_request(struct interface *); -void start_interface(struct interface *); -void start_discover(struct interface *); -void start_renew(struct interface *); -void start_rebind(struct interface *); +int handle_args(int, char **); +void handle_exit_timeout(void *); +void send_request(void *); +void start_interface(void *); +void start_discover(void *); +void start_renew(void *); +void start_rebind(void *); void start_reboot(struct interface *); -void start_expire(struct interface *); +void start_expire(void *); void send_decline(struct interface *); void close_sockets(struct interface *); void drop_config(struct interface *, const char *); diff --git a/eloop.c b/eloop.c index 63914162..1fa75bc4 100644 --- a/eloop.c +++ b/eloop.c @@ -41,16 +41,16 @@ static struct timeval now = {0, 0}; static struct event { int fd; - void (*callback)(struct interface *); - struct interface *iface; + void (*callback)(void *); + void *arg; struct event *next; } *events = NULL; static struct event *free_events = NULL; static struct timeout { struct timeval when; - void (*callback)(struct interface *); - struct interface *iface; + void (*callback)(void *); + void *arg; struct timeout *next; } *timeouts = NULL; static struct timeout *free_timeouts = NULL; @@ -93,7 +93,7 @@ cleanup(void) #endif void -add_event(int fd, void (*callback)(struct interface *), struct interface *iface) +add_event(int fd, void (*callback)(void *), void *arg) { struct event *e, *last = NULL; @@ -101,7 +101,7 @@ add_event(int fd, void (*callback)(struct interface *), struct interface *iface) for (e = events; e; e = e->next) { if (e->fd == fd) { e->callback = callback; - e->iface = iface; + e->arg = arg; return; } last = e; @@ -115,7 +115,7 @@ add_event(int fd, void (*callback)(struct interface *), struct interface *iface) e = xmalloc(sizeof(*e)); e->fd = fd; e->callback = callback; - e->iface = iface; + e->arg = arg; e->next = NULL; if (last) last->next = e; @@ -144,7 +144,7 @@ delete_event(int fd) void add_timeout_tv(const struct timeval *when, - void (*callback)(struct interface *), struct interface *iface) + void (*callback)(void *), void *arg) { struct timeval w; struct timeout *t, *tt = NULL; @@ -154,7 +154,7 @@ add_timeout_tv(const struct timeval *when, /* Remove existing timeout if present */ for (t = timeouts; t; t = t->next) { - if (t->callback == callback && t->iface == iface) { + if (t->callback == callback && t->arg == arg) { if (tt) tt->next = t->next; else @@ -176,7 +176,7 @@ add_timeout_tv(const struct timeval *when, t->when.tv_sec = w.tv_sec; t->when.tv_usec = w.tv_usec; t->callback = callback; - t->iface = iface; + t->arg = arg; /* The timeout list should be in chronological order, * soonest first. @@ -199,30 +199,30 @@ add_timeout_tv(const struct timeval *when, void add_timeout_sec(time_t when, - void (*callback)(struct interface *), struct interface *iface) + void (*callback)(void *), void *arg) { struct timeval tv; tv.tv_sec = when; tv.tv_usec = 0; - add_timeout_tv(&tv, callback, iface); + add_timeout_tv(&tv, callback, arg); } /* This deletes all timeouts for the interface EXCEPT for ones with the * callbacks given. Handy for deleting everything apart from the expire * timeout. */ void -delete_timeouts(struct interface *iface, - void (*callback)(struct interface *), ...) +delete_timeouts(void *arg, + void (*callback)(void *), ...) { struct timeout *t, *tt, *last = NULL; va_list va; - void (*f)(struct interface *); + void (*f)(void *); for (t = timeouts; t && (tt = t->next, 1); t = tt) { - if (t->iface == iface && t->callback != callback) { + if (t->arg == arg && t->callback != callback) { va_start(va, callback); - while ((f = va_arg(va, void (*)(struct interface *)))) + while ((f = va_arg(va, void (*)(void *)))) if (f == t->callback) break; va_end(va); @@ -240,12 +240,12 @@ delete_timeouts(struct interface *iface, } void -delete_timeout(void (*callback)(struct interface *), struct interface *iface) +delete_timeout(void (*callback)(void *), void *arg) { struct timeout *t, *tt, *last = NULL; for (t = timeouts; t && (tt = t->next, 1); t = tt) { - if (t->iface == iface && + if (t->arg == arg && (!callback || t->callback == callback)) { if (last) @@ -281,7 +281,7 @@ start_eloop(void) if (timercmp(&now, &timeouts->when, >)) { t = timeouts; timeouts = timeouts->next; - t->callback(t->iface); + t->callback(t->arg); t->next = free_timeouts; free_timeouts = t; continue; @@ -338,7 +338,7 @@ start_eloop(void) continue; for (e = events; e; e = e->next) { if (e->fd == fds[i].fd) { - e->callback(e->iface); + e->callback(e->arg); break; } } diff --git a/eloop.h b/eloop.h index 18e64ee6..f29425bf 100644 --- a/eloop.h +++ b/eloop.h @@ -32,13 +32,12 @@ #include "dhcpcd.h" -void add_event(int fd, void (*)(struct interface *), struct interface *); +void add_event(int fd, void (*)(void *), void *); void delete_event(int fd); -void add_timeout_sec(time_t, void (*)(struct interface *), struct interface *); -void add_timeout_tv(const struct timeval *, - void (*)(struct interface *), struct interface *); -void delete_timeout(void (*)(struct interface *), struct interface *); -void delete_timeouts(struct interface *, void (*)(struct interface *), ...); +void add_timeout_sec(time_t, void (*)(void *), void *); +void add_timeout_tv(const struct timeval *, void (*)(void *), void *); +void delete_timeout(void (*)(void *), void *); +void delete_timeouts(void *, void (*)(void *), ...); void start_eloop(void); #endif diff --git a/if-options.c b/if-options.c index 836bf8de..f6f9140b 100644 --- a/if-options.c +++ b/if-options.c @@ -293,6 +293,8 @@ parse_option(struct if_options *ifo, int opt, const char *arg) } *ifo->vendorclassid = (uint8_t)s; break; + case 'k': + break; case 'l': if (*arg == '-') { logger(LOG_ERR, @@ -313,6 +315,8 @@ parse_option(struct if_options *ifo, int opt, const char *arg) return -1; } break; + case 'n': + break; case 'o': if (make_option_mask(ifo->requestmask, arg, 1) != 0) { logger(LOG_ERR, "unknown option `%s'", arg); @@ -557,6 +561,7 @@ read_config(const char *file, const char *ifname) ifo->options |= DHCPCD_CLIENTID | DHCPCD_GATEWAY | DHCPCD_DAEMONISE; ifo->options |= DHCPCD_ARP | DHCPCD_IPV4LL | DHCPCD_LINK; ifo->timeout = DEFAULT_TIMEOUT; + ifo->metric = -1; gethostname(ifo->hostname + 1, sizeof(ifo->hostname)); if (strcmp(ifo->hostname + 1, "(none)") == 0 || strcmp(ifo->hostname + 1, "localhost") == 0) @@ -642,12 +647,14 @@ free_options(struct if_options *ifo) { size_t i; - if (ifo->environ) { - i = 0; - while (ifo->environ[i]) - free(ifo->environ[i++]); - free(ifo->environ); + if (ifo) { + if (ifo->environ) { + i = 0; + while (ifo->environ[i]) + free(ifo->environ[i++]); + free(ifo->environ); + } + free(ifo->blacklist); + free(ifo); } - free(ifo->blacklist); - free(ifo); } diff --git a/ipv4ll.c b/ipv4ll.c index 3e8786f0..c7b0586a 100644 --- a/ipv4ll.c +++ b/ipv4ll.c @@ -73,8 +73,10 @@ make_ipv4ll_lease(uint32_t old_addr) } void -start_ipv4ll(struct interface *iface) +start_ipv4ll(void *arg) { + struct interface *iface = arg; + iface->state->probes = 0; iface->state->claims = 0; if (iface->addr.s_addr) { @@ -94,8 +96,9 @@ start_ipv4ll(struct interface *iface) } void -handle_ipv4ll_failure(struct interface *iface) +handle_ipv4ll_failure(void *arg) { + struct interface *iface = arg; time_t up; if (iface->state->fail.s_addr == iface->state->lease.addr.s_addr) { diff --git a/ipv4ll.h b/ipv4ll.h index 82f8d59f..8c1d7e52 100644 --- a/ipv4ll.h +++ b/ipv4ll.h @@ -28,8 +28,6 @@ #ifndef IPV4LL_H #define IPV4LL_H -#include "net.h" - -void start_ipv4ll(struct interface *); -void handle_ipv4ll_failure(struct interface *); +void start_ipv4ll(void *); +void handle_ipv4ll_failure(void *); #endif