}
free(dhcp);
if (r == -1) {
- stop_interface(iface);
+ /* We failed to send a packet?
+ * This should only happen if the link has gone down whilst
+ * we are working and managed to get here before we processed
+ * the link down message.
+ * Or we could be configured not to look at them or it's a
+ * buggy driver. Either way, we need to drop everything
+ * and start over. */
+ drop_config(iface, "STOP");
+ close_sockets(iface);
+ delete_timeout(NULL, iface);
+ add_timeout_sec(DHCP_ARP_FAIL, start_interface, iface);
} else {
if (callback)
add_timeout_tv(&tv, callback, iface);
main(int argc, char **argv)
{
struct if_options *ifo;
- struct interface *iface;
+ struct interface *iface, **ifs, **ifp;
int opt, oi = 0, signal_fd, sig = 0, i, control_fd;
size_t len;
pid_t pid;
if (options & DHCPCD_BACKGROUND)
daemonise();
- for (iface = ifaces; iface; iface = iface->next)
+ for (iface = ifaces, len = 0; iface; iface = iface->next, len++)
init_state(iface, argc, argv);
sort_interfaces();
- for (iface = ifaces; iface; iface = iface->next)
- start_interface(iface);
+ /* When we start an interface, it could be stopped right away or
+ * the order could change.
+ * We also don't want to start an interface more than once.
+ * So we store an array of ifaces instead of relying on ->next. */
+ if (len != 0) {
+ ifs = ifp = xmalloc(sizeof(*iface) * len);
+ for (iface = ifaces; iface; iface = iface->next)
+ *ifp++ = iface;
+ ifp = ifs;
+ while (--len != 0)
+ start_interface(*ifp++);
+ free(ifs);
+ }
+
start_eloop();
exit(EXIT_SUCCESS);
}