diff options
Diffstat (limited to 'dhcpcd.c')
-rw-r--r-- | dhcpcd.c | 352 |
1 files changed, 211 insertions, 141 deletions
@@ -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); |