# Copyright 2008 Roy Marples <roy@marples.name>
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}
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;
}
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;
}
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;
#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
#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
}
#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;
#define BIND_H
#include "config.h"
-#include "dhcpcd.h"
#ifdef THERE_IS_NO_FORK
#define daemonise() {}
#else
#endif
extern int can_daemonise;
-void bind_interface(struct interface *);
+void bind_interface(void *);
#endif
#ifndef PIDFILE
# define PIDFILE RUNDIR "/" PACKAGE "%s%s.pid"
#endif
+#ifndef CONTROLSOCKET
+# define CONTROLSOCKET RUNDIR "/" PACKAGE ".sock"
+#endif
#endif
--- /dev/null
+/*
+ * dhcpcd - DHCP client daemon
+ * Copyright 2006-2008 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 <sys/stat.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#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);
+}
--- /dev/null
+/*
+ * dhcpcd - DHCP client daemon
+ * Copyright 2006-2008 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 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
.\" 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
.Sh AUTHORS
.An Roy Marples <roy@marples.name>
.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.
#include "config.h"
#include "common.h"
#include "configure.h"
+#include "control.h"
#include "dhcpcd.h"
#include "dhcpf.h"
#include "duid.h"
/* 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;
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);
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;
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 {
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;
}
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;
}
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);
}
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;
}
static void
-handle_link(struct interface *iface)
+handle_link(_unused void *arg)
{
+ struct interface *iface;
int retval;
retval = link_changed(linkfd, ifaces);
}
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;
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);
}
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) {
}
}
- 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;
}
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:
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",
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;
case 'f':
strlcpy(cffile, optarg, sizeof(cffile));
break;
+ case 'k':
+ sig = SIGHUP;
+ break;
+ case 'n':
+ sig = SIGALRM;
+ break;
case 'x':
sig = SIGTERM;
break;
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();
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)
#ifndef DHCPCD_H
#define DHCPCD_H
-#include <sys/socket.h>
#include <net/if.h>
#include <limits.h>
};
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 *);
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;
#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;
for (e = events; e; e = e->next) {
if (e->fd == fd) {
e->callback = callback;
- e->iface = iface;
+ e->arg = arg;
return;
}
last = e;
e = xmalloc(sizeof(*e));
e->fd = fd;
e->callback = callback;
- e->iface = iface;
+ e->arg = arg;
e->next = NULL;
if (last)
last->next = e;
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;
/* 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
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.
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);
}
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)
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;
continue;
for (e = events; e; e = e->next) {
if (e->fd == fds[i].fd) {
- e->callback(e->iface);
+ e->callback(e->arg);
break;
}
}
#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
}
*ifo->vendorclassid = (uint8_t)s;
break;
+ case 'k':
+ break;
case 'l':
if (*arg == '-') {
logger(LOG_ERR,
return -1;
}
break;
+ case 'n':
+ break;
case 'o':
if (make_option_mask(ifo->requestmask, arg, 1) != 0) {
logger(LOG_ERR, "unknown option `%s'", arg);
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)
{
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);
}
}
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) {
}
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) {
#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