aboutsummaryrefslogtreecommitdiffstats
path: root/dhcpcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'dhcpcd.c')
-rw-r--r--dhcpcd.c352
1 files changed, 211 insertions, 141 deletions
diff --git a/dhcpcd.c b/dhcpcd.c
index 155c07b..8a008a0 100644
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1,6 +1,6 @@
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2010 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
* SUCH DAMAGE.
*/
-const char copyright[] = "Copyright (c) 2006-2010 Roy Marples";
+const char copyright[] = "Copyright (c) 2006-2012 Roy Marples";
#include <sys/file.h>
#include <sys/socket.h>
@@ -67,7 +67,9 @@ const char copyright[] = "Copyright (c) 2006-2010 Roy Marples";
#include "if-options.h"
#include "if-pref.h"
#include "ipv4ll.h"
+#include "ipv6rs.h"
#include "net.h"
+#include "platform.h"
#include "signals.h"
#ifdef ANDROID
@@ -85,7 +87,7 @@ const char copyright[] = "Copyright (c) 2006-2010 Roy Marples";
#define RELEASE_DELAY_S 0
#define RELEASE_DELAY_NS 10000000
-int options = 0;
+unsigned long long options = 0;
int pidfd = -1;
struct interface *ifaces = NULL;
int ifac = 0;
@@ -102,7 +104,7 @@ static char **ifv;
static int ifc;
static char *cffile;
static char *pidfile;
-static int linkfd = -1;
+static int linkfd = -1, ipv6rsfd = -1;
struct dhcp_op {
uint8_t value;
@@ -153,15 +155,24 @@ read_pid(void)
static void
usage(void)
{
- printf("usage: "PACKAGE" [-adgknpqwxyADEGHJKLOTV] [-c script] [-f file]"
- " [-e var=val]\n"
- " [-h hostname] [-i classID ] [-l leasetime]"
- " [-m metric] [-o option]\n"
- " [-r ipaddr] [-s ipaddr] [-t timeout]"
- " [-u userclass]\n"
- " [-F none|ptr|both] [-I clientID] [-C hookscript]"
- " [-Q option]\n"
- " [-X ipaddr] <interface>\n");
+
+printf("usage: "PACKAGE"\t[-aABbDdEGgHJKkLnpqTVw]\n"
+ "\t\t[-C, --nohook hook] [-c, --script script]\n"
+ "\t\t[-e, --env value] [-F, --fqdn FQDN] [-f, --config file]\n"
+ "\t\t[-h, --hostname hostname] [-I, --clientid clientid]\n"
+ "\t\t[-i, --vendorclassid vendorclassid] [-l, --leasetime seconds]\n"
+ "\t\t[-m, --metric metric] [-O, --nooption option]\n"
+ "\t\t[-o, --option option] [-Q, --require option]\n"
+ "\t\t[-r, --request address] [-S, --static value]\n"
+ "\t\t[-s, --inform address[/cidr]] [-t, --timeout seconds]\n"
+ "\t\t[-u, --userclass class] [-v, --vendor code, value]\n"
+ "\t\t[-W, --whitelist address[/cidr]] [-y, --reboot seconds]\n"
+ "\t\t[-X, --blacklist address[/cidr]] [-Z, --denyinterfaces pattern]\n"
+ "\t\t[-z, --allowinterfaces pattern] [interface] [...]\n"
+ " "PACKAGE"\t-k, --release [interface]\n"
+ " "PACKAGE"\t-U, --dumplease interface\n"
+ " "PACKAGE"\t-v, --version\n"
+ " "PACKAGE"\t-x, --exit [interface]\n");
}
static void
@@ -217,13 +228,13 @@ handle_exit_timeout(_unused void *arg)
exit(EXIT_FAILURE);
}
options &= ~DHCPCD_TIMEOUT_IPV4LL;
- timeout = (PROBE_NUM * PROBE_MAX) + PROBE_WAIT + 1;
+ timeout = (PROBE_NUM * PROBE_MAX) + (PROBE_WAIT * 2);
syslog(LOG_WARNING, "allowing %d seconds for IPv4LL timeout", timeout);
add_timeout_sec(timeout, handle_exit_timeout, NULL);
}
void
-drop_config(struct interface *iface, const char *reason)
+drop_dhcp(struct interface *iface, const char *reason)
{
free(iface->state->old);
iface->state->old = iface->state->new;
@@ -252,8 +263,13 @@ stop_interface(struct interface *iface)
struct interface *ifp, *ifl = NULL;
syslog(LOG_INFO, "%s: removing interface", iface->name);
+ if (iface->ras) {
+ ipv6rs_free(iface);
+ iface->ras = NULL;
+ run_script_reason(iface, "ROUTERADVERT");
+ }
if (strcmp(iface->state->reason, "RELEASE") != 0)
- drop_config(iface, "STOP");
+ drop_dhcp(iface, "STOP");
close_sockets(iface);
delete_timeout(NULL, iface);
for (ifp = ifaces; ifp; ifp = ifp->next) {
@@ -357,7 +373,7 @@ send_message(struct interface *iface, int type,
if (r == -1) {
syslog(LOG_ERR, "%s: send_raw_packet: %m", iface->name);
if (!(options & DHCPCD_TEST))
- drop_config(iface, "FAIL");
+ drop_dhcp(iface, "FAIL");
close_sockets(iface);
delete_timeout(NULL, iface);
callback = NULL;
@@ -416,7 +432,7 @@ start_expire(void *arg)
syslog(LOG_ERR, "%s: lease expired", iface->name);
delete_timeout(NULL, iface);
- drop_config(iface, "EXPIRE");
+ drop_dhcp(iface, "EXPIRE");
unlink(iface->leasefile);
if (iface->carrier != LINK_DOWN)
start_interface(iface);
@@ -513,7 +529,7 @@ handle_dhcp(struct interface *iface, struct dhcp_message **dhcpp, const struct i
/* We should restart on a NAK */
log_dhcp(LOG_WARNING, "NAK:", iface, dhcp, from);
if (!(options & DHCPCD_TEST)) {
- drop_config(iface, "NAK");
+ drop_dhcp(iface, "NAK");
unlink(iface->leasefile);
}
close_sockets(iface);
@@ -537,7 +553,17 @@ handle_dhcp(struct interface *iface, struct dhcp_message **dhcpp, const struct i
log_dhcp(LOG_WARNING, "reject DHCP", iface, dhcp, from);
return;
}
- }
+ }
+
+ /* Ensure that the address offered is valid */
+ if ((type == 0 || type == DHCP_OFFER || type == DHCP_ACK) &&
+ (dhcp->ciaddr == INADDR_ANY || dhcp->ciaddr == INADDR_BROADCAST) &&
+ (dhcp->yiaddr == INADDR_ANY || dhcp->yiaddr == INADDR_BROADCAST))
+ {
+ log_dhcp(LOG_WARNING, "reject invalid address",
+ iface, dhcp, from);
+ return;
+ }
/* No NAK, so reset the backoff */
state->nakoff = 1;
@@ -640,7 +666,7 @@ handle_dhcp_packet(void *arg)
const uint8_t *pp;
ssize_t bytes;
struct in_addr from;
- int i;
+ int i, partialcsum = 0;
/* We loop through until our buffer is empty.
* The benefit is that if we get >1 DHCP packet in our buffer and
@@ -648,10 +674,10 @@ handle_dhcp_packet(void *arg)
packet = xmalloc(udp_dhcp_len);
for(;;) {
bytes = get_raw_packet(iface, ETHERTYPE_IP,
- packet, udp_dhcp_len);
+ packet, udp_dhcp_len, &partialcsum);
if (bytes == 0 || bytes == -1)
break;
- if (valid_udp_packet(packet, bytes, &from) == -1) {
+ if (valid_udp_packet(packet, bytes, &from, partialcsum) == -1) {
syslog(LOG_ERR, "%s: invalid UDP packet from %s",
iface->name, inet_ntoa(from));
continue;
@@ -733,7 +759,7 @@ send_release(struct interface *iface)
ts.tv_sec = RELEASE_DELAY_S;
ts.tv_nsec = RELEASE_DELAY_NS;
nanosleep(&ts, NULL);
- drop_config(iface, "RELEASE");
+ drop_dhcp(iface, "RELEASE");
}
unlink(iface->leasefile);
}
@@ -760,6 +786,8 @@ configure_interface1(struct interface *iface)
if (iface->flags & IFF_NOARP ||
ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))
ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL);
+ if (!(iface->flags & (IFF_POINTOPOINT | IFF_LOOPBACK | IFF_MULTICAST)))
+ ifo->options &= ~DHCPCD_IPV6RS;
if (ifo->options & DHCPCD_LINK && carrier_status(iface) == -1)
ifo->options &= ~DHCPCD_LINK;
@@ -818,7 +846,7 @@ configure_interface1(struct interface *iface)
if (ifo->options & DHCPCD_CLIENTID)
syslog(LOG_DEBUG, "%s: using ClientID %s", iface->name,
hwaddr_ntoa(iface->clientid + 1, *iface->clientid));
- else
+ else if (iface->hwlen)
syslog(LOG_DEBUG, "%s: using hwaddr %s", iface->name,
hwaddr_ntoa(iface->hwaddr, iface->hwlen));
}
@@ -870,8 +898,8 @@ configure_interface(struct interface *iface, int argc, char **argv)
configure_interface1(iface);
}
-static void
-handle_carrier(const char *ifname)
+void
+handle_carrier(int action, int flags, const char *ifname)
{
struct interface *iface;
int carrier;
@@ -881,20 +909,36 @@ handle_carrier(const char *ifname)
for (iface = ifaces; iface; iface = iface->next)
if (strcmp(iface->name, ifname) == 0)
break;
- if (!iface || !(iface->state->options->options & DHCPCD_LINK))
+ if (!iface) {
+ if (options & DHCPCD_LINK)
+ handle_interface(1, ifname);
+ return;
+ }
+ if (!(iface->state->options->options & DHCPCD_LINK))
return;
- carrier = carrier_status(iface);
+
+ if (action) {
+ carrier = action == 1 ? 1 : 0;
+ iface->flags = flags;
+ } else
+ carrier = carrier_status(iface);
+
if (carrier == -1)
syslog(LOG_ERR, "%s: carrier_status: %m", ifname);
- else if (carrier == 0 || !(iface->flags & IFF_RUNNING)) {
+ else if (carrier == 0 || ~iface->flags & IFF_UP) {
if (iface->carrier != LINK_DOWN) {
iface->carrier = LINK_DOWN;
syslog(LOG_INFO, "%s: carrier lost", iface->name);
close_sockets(iface);
delete_timeouts(iface, start_expire, NULL);
- drop_config(iface, "NOCARRIER");
+ if (iface->ras) {
+ ipv6rs_free(iface);
+ iface->ras = NULL;
+ run_script_reason(iface, "ROUTERADVERT");
+ }
+ drop_dhcp(iface, "NOCARRIER");
}
- } else if (carrier == 1 && (iface->flags & IFF_RUNNING)) {
+ } else if (carrier == 1 && !(~iface->flags & IFF_UP)) {
if (iface->carrier != LINK_UP) {
iface->carrier = LINK_UP;
syslog(LOG_INFO, "%s: carrier acquired", iface->name);
@@ -914,21 +958,37 @@ start_discover(void *arg)
{
struct interface *iface = arg;
struct if_options *ifo = iface->state->options;
+ int timeout = ifo->timeout;
+
+ /* If we're rebooting and we're not daemonised then we need
+ * to shorten the normal timeout to ensure we try correctly
+ * for a fallback or IPv4LL address. */
+ if (iface->state->state == DHS_REBOOT &&
+ !(options & DHCPCD_DAEMONISED))
+ {
+ timeout -= ifo->reboot;
+ if (timeout <= 0)
+ timeout = 2;
+ }
iface->state->state = DHS_DISCOVER;
iface->state->xid = dhcp_xid(iface);
delete_timeout(NULL, iface);
if (ifo->fallback)
- add_timeout_sec(ifo->timeout, start_fallback, iface);
+ add_timeout_sec(timeout, start_fallback, iface);
else if (ifo->options & DHCPCD_IPV4LL &&
!IN_LINKLOCAL(htonl(iface->addr.s_addr)))
{
if (IN_LINKLOCAL(htonl(iface->state->fail.s_addr)))
add_timeout_sec(RATE_LIMIT_INTERVAL, start_ipv4ll, iface);
else
- add_timeout_sec(ifo->timeout, start_ipv4ll, iface);
+ add_timeout_sec(timeout, start_ipv4ll, iface);
}
- syslog(LOG_INFO, "%s: broadcasting for a lease", iface->name);
+ if (ifo->options & DHCPCD_REQUEST)
+ syslog(LOG_INFO, "%s: broadcasting for a lease (requesting %s)",
+ iface->name, inet_ntoa(ifo->req_addr));
+ else
+ syslog(LOG_INFO, "%s: broadcasting for a lease", iface->name);
send_discover(iface);
}
@@ -1110,7 +1170,7 @@ start_interface(void *arg)
uint32_t l;
int nolease;
- handle_carrier(iface->name);
+ handle_carrier(0, 0, iface->name);
if (iface->carrier == LINK_DOWN) {
syslog(LOG_INFO, "%s: waiting for carrier", iface->name);
return;
@@ -1120,6 +1180,13 @@ start_interface(void *arg)
free(iface->state->offer);
iface->state->offer = NULL;
+ if (options & DHCPCD_IPV6RS && ifo->options & DHCPCD_IPV6RS) {
+ if (check_ipv6(iface->name) == 1)
+ ipv6rs_start(iface);
+ else
+ ifo->options &= ~DHCPCD_IPV6RS;
+ }
+
if (iface->state->arping_index < ifo->arping_len) {
start_arping(iface);
return;
@@ -1135,7 +1202,7 @@ start_interface(void *arg)
if (iface->hwlen == 0 && ifo->clientid[0] == '\0') {
syslog(LOG_WARNING, "%s: needs a clientid to configure",
iface->name);
- drop_config(iface, "FAIL");
+ drop_dhcp(iface, "FAIL");
close_sockets(iface);
delete_timeout(NULL, iface);
return;
@@ -1238,9 +1305,6 @@ handle_interface(int action, const char *ifname)
if (ifp != NULL)
stop_interface(ifp);
return;
- } else if (action == 0) {
- handle_carrier(ifname);
- return;
}
/* If running off an interface list, check it's in it. */
@@ -1297,7 +1361,7 @@ handle_hwaddr(const char *ifname, unsigned char *hwaddr, size_t hwlen)
syslog(LOG_INFO,
"%s: expiring for new hardware address",
ifp->name);
- drop_config(ifp, "EXPIRE");
+ drop_dhcp(ifp, "EXPIRE");
}
memcpy(ifp->hwaddr, hwaddr, hwlen);
ifp->hwlen = hwlen;
@@ -1331,43 +1395,44 @@ handle_ifa(int type, const char *ifname,
break;
if (ifp == NULL)
return;
+
+ if (type == RTM_DELADDR) {
+ if (ifp->state->new &&
+ ifp->state->new->yiaddr == addr->s_addr)
+ syslog(LOG_INFO, "%s: removing IP address %s/%d",
+ ifp->name, inet_ntoa(ifp->state->lease.addr),
+ inet_ntocidr(ifp->state->lease.net));
+ return;
+ }
+
+ if (type != RTM_NEWADDR)
+ return;
+
ifo = ifp->state->options;
if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)) == 0 ||
ifo->req_addr.s_addr != INADDR_ANY)
return;
-
- switch (type) {
- case RTM_DELADDR:
- if (ifp->state->new &&
- ifp->state->new->yiaddr == addr->s_addr)
- drop_config(ifp, "EXPIRE");
- break;
- case RTM_NEWADDR:
- free(ifp->state->old);
- ifp->state->old = ifp->state->new;
- ifp->state->new = dhcp_message_new(addr, net);
- ifp->dst.s_addr = dst ? dst->s_addr : INADDR_ANY;
- if (dst) {
- for (i = 1; i < 255; i++)
- if (i != DHO_ROUTER &&
- has_option_mask(ifo->dstmask, i))
- dhcp_message_add_addr(
- ifp->state->new,
- i, *dst);
- }
- ifp->state->reason = "STATIC";
- build_routes();
- run_script(ifp);
- if (ifo->options & DHCPCD_INFORM) {
- ifp->state->state = DHS_INFORM;
- ifp->state->xid = dhcp_xid(ifp);
- ifp->state->lease.server.s_addr =
- dst ? dst->s_addr : INADDR_ANY;
- ifp->addr = *addr;
- ifp->net = *net;
- send_inform(ifp);
- }
- break;
+
+ free(ifp->state->old);
+ ifp->state->old = ifp->state->new;
+ ifp->state->new = dhcp_message_new(addr, net);
+ ifp->dst.s_addr = dst ? dst->s_addr : INADDR_ANY;
+ if (dst) {
+ for (i = 1; i < 255; i++)
+ if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i))
+ dhcp_message_add_addr(ifp->state->new, i, *dst);
+ }
+ ifp->state->reason = "STATIC";
+ build_routes();
+ run_script(ifp);
+ if (ifo->options & DHCPCD_INFORM) {
+ ifp->state->state = DHS_INFORM;
+ ifp->state->xid = dhcp_xid(ifp);
+ ifp->state->lease.server.s_addr =
+ dst ? dst->s_addr : INADDR_ANY;
+ ifp->addr = *addr;
+ ifp->net = *net;
+ send_inform(ifp);
}
}
@@ -1395,7 +1460,7 @@ if_reboot(struct interface *iface, int argc, char **argv)
(opt & (DHCPCD_INFORM | DHCPCD_STATIC) &&
!(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))))
{
- drop_config(iface, "EXPIRE");
+ drop_dhcp(iface, "EXPIRE");
} else {
free(iface->state->offer);
iface->state->offer = NULL;
@@ -1412,25 +1477,6 @@ reconf_reboot(int action, int argc, char **argv, int oi)
if (ifs == NULL)
return;
- /* Remove any old interfaces */
- if (ifaces) {
- for (ifl = NULL; ifl != ifaces;) {
- /* Work our way backwards */
- for (ifp = ifaces; ifp; ifp = ifp->next)
- if (ifp->next == ifl) {
- ifl = ifp;
- break;
- }
- for (ifn = ifs; ifn; ifn = ifn->next)
- if (strcmp(ifn->name, ifp->name) == 0)
- break;
- if (ifn == NULL) {
- ifl = ifp->next;
- stop_interface(ifp);
- }
- }
- }
-
for (ifp = ifs; ifp && (ift = ifp->next, 1); ifp = ift) {
ifl = NULL;
for (ifn = ifaces; ifn; ifn = ifn->next) {
@@ -1502,7 +1548,7 @@ handle_signal(_unused void *arg)
ifo->options |= DHCPCD_DAEMONISED;
options = ifo->options;
free_options(ifo);
- reconf_reboot(1, 0, NULL, 0);
+ reconf_reboot(1, ifc, ifv, 0);
#endif
return;
case SIGHUP:
@@ -1528,7 +1574,7 @@ handle_signal(_unused void *arg)
if (options & DHCPCD_TEST)
exit(EXIT_FAILURE);
- /* As drop_config could re-arrange the order, we do it like this. */
+ /* As drop_dhcp could re-arrange the order, we do it like this. */
for (;;) {
/* Be sane and drop the last config first */
ifl = NULL;
@@ -1586,8 +1632,11 @@ handle_args(struct fd_list *fd, int argc, char **argv)
} else if (strcmp(*argv, "--getinterfaces") == 0) {
len = 0;
if (argc == 1) {
- for (ifp = ifaces; ifp; ifp = ifp->next)
+ for (ifp = ifaces; ifp; ifp = ifp->next) {
len++;
+ if (ifp->ras)
+ len++;
+ }
len = write(fd->fd, &len, sizeof(len));
if (len != sizeof(len))
return -1;
@@ -1598,8 +1647,11 @@ handle_args(struct fd_list *fd, int argc, char **argv)
opt = 0;
while (argv[++opt] != NULL) {
for (ifp = ifaces; ifp; ifp = ifp->next)
- if (strcmp(argv[opt], ifp->name) == 0)
+ if (strcmp(argv[opt], ifp->name) == 0) {
len++;
+ if (ifp->ras)
+ len++;
+ }
}
len = write(fd->fd, &len, sizeof(len));
if (len != sizeof(len))
@@ -1948,7 +2000,7 @@ main(int argc, char **argv)
if (sig != SIGALRM)
exit(EXIT_FAILURE);
} else {
- if (sig == SIGALRM)
+ if (sig == SIGALRM || sig == SIGUSR1)
exit(EXIT_SUCCESS);
/* Spin until it exits */
syslog(LOG_INFO, "waiting for pid %d to exit", pid);
@@ -1980,50 +2032,47 @@ main(int argc, char **argv)
}
/* Ensure we have the needed directories */
- if (mkdir(RUNDIR, 0755) == -1 && errno != EEXIST) {
+ if (mkdir(RUNDIR, 0755) == -1 && errno != EEXIST)
syslog(LOG_ERR, "mkdir `%s': %m", RUNDIR);
- exit(EXIT_FAILURE);
- }
- if (mkdir(DBDIR, 0755) == -1 && errno != EEXIST) {
+ if (mkdir(DBDIR, 0755) == -1 && errno != EEXIST)
syslog(LOG_ERR, "mkdir `%s': %m", DBDIR);
- exit(EXIT_FAILURE);
- }
#endif
+
pidfd = open(pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0664);
- if (pidfd == -1) {
+ if (pidfd == -1)
syslog(LOG_ERR, "open `%s': %m", pidfile);
- exit(EXIT_FAILURE);
- }
- /* Lock the file so that only one instance of dhcpcd runs
- * on an interface */
- if (flock(pidfd, LOCK_EX | LOCK_NB) == -1) {
- syslog(LOG_ERR, "flock `%s': %m", pidfile);
- exit(EXIT_FAILURE);
- }
- if (set_cloexec(pidfd) == -1)
- exit(EXIT_FAILURE);
+ else {
+ /* Lock the file so that only one instance of dhcpcd
+ * runs on an interface */
+ if (flock(pidfd, LOCK_EX | LOCK_NB) == -1) {
+ syslog(LOG_ERR, "flock `%s': %m", pidfile);
+ exit(EXIT_FAILURE);
+ }
+ if (set_cloexec(pidfd) == -1)
+ exit(EXIT_FAILURE);
#ifdef ANDROID
- if (optind != argc - 1) {
- syslog(LOG_ERR, "Android requires an interface");
- exit(EXIT_FAILURE);
- }
+ if (optind != argc - 1) {
+ syslog(LOG_ERR, "Android requires an interface");
+ exit(EXIT_FAILURE);
+ }
- if (strncmp(argv[optind], "p2p", 3) == 0) {
- strncpy(p2p_interface, "p2p", sizeof(p2p_interface));
- } else {
- strncpy(p2p_interface, argv[optind], sizeof(p2p_interface));
- }
+ if (strncmp(argv[optind], "p2p", 3) == 0) {
+ strncpy(p2p_interface, "p2p", sizeof(p2p_interface));
+ } else {
+ strncpy(p2p_interface, argv[optind], sizeof(p2p_interface));
+ }
- if (snprintf(pidpropname,
- sizeof(pidpropname),
- "dhcp.%s.pid", p2p_interface) >= PROPERTY_KEY_MAX)
- exit(EXIT_FAILURE);
- if (snprintf(pidpropval, sizeof(pidpropval), "%d", getpid()) >= PROPERTY_VALUE_MAX)
- exit(EXIT_FAILURE);
- property_set(pidpropname, pidpropval);
+ if (snprintf(pidpropname,
+ sizeof(pidpropname),
+ "dhcp.%s.pid", p2p_interface) >= PROPERTY_KEY_MAX)
+ exit(EXIT_FAILURE);
+ if (snprintf(pidpropval, sizeof(pidpropval), "%d", getpid()) >= PROPERTY_VALUE_MAX)
+ exit(EXIT_FAILURE);
+ property_set(pidpropname, pidpropval);
#else
- writepid(pidfd, getpid());
+ writepid(pidfd, getpid());
#endif
+ }
}
syslog(LOG_INFO, "version " VERSION " starting");
@@ -2035,10 +2084,8 @@ main(int argc, char **argv)
add_event(signal_fd, handle_signal, NULL);
if (options & DHCPCD_MASTER) {
- if (start_control() == -1) {
+ if (start_control() == -1)
syslog(LOG_ERR, "start_control: %m");
- exit(EXIT_FAILURE);
- }
}
if (init_sockets() == -1) {
@@ -2053,6 +2100,26 @@ main(int argc, char **argv)
add_event(linkfd, handle_link, NULL);
}
+#if 0
+ if (options & DHCPCD_IPV6RS && disable_rtadv() == -1) {
+ syslog(LOG_ERR, "ipv6rs: %m");
+ options &= ~DHCPCD_IPV6RS;
+ }
+#endif
+
+ if (options & DHCPCD_IPV6RS && !check_ipv6(NULL))
+ options &= ~DHCPCD_IPV6RS;
+ if (options & DHCPCD_IPV6RS) {
+ ipv6rsfd = ipv6rs_open();
+ if (ipv6rsfd == -1) {
+ syslog(LOG_ERR, "ipv6rs: %m");
+ options &= ~DHCPCD_IPV6RS;
+ } else {
+ add_event(ipv6rsfd, ipv6rs_handledata, NULL);
+// atexit(restore_rtadv);
+ }
+ }
+
ifc = argc - optind;
ifv = argv + optind;
@@ -2094,7 +2161,7 @@ main(int argc, char **argv)
if (!(options & DHCPCD_BACKGROUND)) {
/* If we don't have a carrier, we may have to wait for a second
- * before one becomes available if we brought an interface up. */
+ * before one becomes available if we brought an interface up */
if (opt == 0 &&
options & DHCPCD_LINK &&
options & DHCPCD_WAITUP &&
@@ -2104,24 +2171,27 @@ main(int argc, char **argv)
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
for (iface = ifaces; iface; iface = iface->next) {
- handle_carrier(iface->name);
+ handle_carrier(0, 0, iface->name);
if (iface->carrier != LINK_DOWN) {
opt = 1;
break;
}
}
}
+ if (options & DHCPCD_MASTER)
+ i = if_options->timeout;
+ else
+ i = ifaces->state->options->timeout;
if (opt == 0 &&
options & DHCPCD_LINK &&
!(options & DHCPCD_WAITIP))
{
syslog(LOG_WARNING, "no interfaces have a carrier");
daemonise();
- } else if (if_options->timeout > 0) {
+ } else if (i > 0) {
if (options & DHCPCD_IPV4LL)
options |= DHCPCD_TIMEOUT_IPV4LL;
- add_timeout_sec(if_options->timeout,
- handle_exit_timeout, NULL);
+ add_timeout_sec(i, handle_exit_timeout, NULL);
}
}
free_options(if_options);