summaryrefslogtreecommitdiff
path: root/sbin/dhclient
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2014-12-05 15:47:06 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2014-12-05 15:47:06 +0000
commit3102933c68a271f0c3b5bf4ab50e6229ecd384d1 (patch)
tree9014e33c463a4106a2ddd5b7e6ae95d7e36f2b56 /sbin/dhclient
parent7a578d6d316a6e71be68a75a579eeb1435831c6a (diff)
Move initial wait for network link into the state machine by adding
state S_PREBOOT and associated state_preboot() function. This results in routing socket messages being processed even while the link is being waited for. Thus the RTM_IFINFO message announcing the link is ready can be reacted to immediately, rather than waiting for the sleep(1)'ing process to wake up and look at the link state. Some interfaces seem to lose the first packet sent when the RTM_IFINFO message is reacted to so quickly, so temporarily leave in place an explicit delay before sending the first packet.
Diffstat (limited to 'sbin/dhclient')
-rw-r--r--sbin/dhclient/dhclient.c99
-rw-r--r--sbin/dhclient/dhcpd.h3
2 files changed, 66 insertions, 36 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index f20ffda2903..6a0c323e272 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.338 2014/11/30 00:09:30 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.339 2014/12/05 15:47:05 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -113,6 +113,7 @@ void add_classless_static_routes(int, struct option_data *, struct in_addr);
int compare_lease(struct client_lease *, struct client_lease *);
void set_lease_times(struct client_lease *);
+void state_preboot(void);
void state_reboot(void);
void state_init(void);
void state_selecting(void);
@@ -351,8 +352,10 @@ routehandler(void)
#endif
ifi->linkstat = linkstat;
if (ifi->linkstat) {
+ if (client->state == S_PREBOOT)
+ state_preboot();
client->state = S_REBOOTING;
- state_reboot();
+ set_timeout_interval(1, state_reboot);
} else if (strlen(path_option_db)) {
/* Let monitoring programs see link loss. */
write_file(path_option_db,
@@ -401,7 +404,7 @@ int
main(int argc, char *argv[])
{
struct stat sb;
- int ch, fd, i = 0, socket_fd[2];
+ int ch, fd, socket_fd[2];
extern char *__progname;
struct passwd *pw;
char *ignore_list = NULL;
@@ -503,41 +506,14 @@ main(int argc, char *argv[])
TAILQ_INIT(&client->leases);
TAILQ_INIT(&client->offered_leases);
- read_client_conf(); /* Needed for config->link_timeout below! */
+ read_client_conf();
- if (interface_status(ifi->name) == 0) {
- interface_link_forceup(ifi->name);
- /* Give it up to 4 seconds of silent grace to find link */
- i = -4;
- } else
- i = 0;
-
- while (!(ifi->linkstat = interface_status(ifi->name))) {
- if (i == 0)
- fprintf(stderr, "%s: no link ...", ifi->name);
- else if (i > 0)
- fprintf(stderr, ".");
- fflush(stderr);
- if (++i > config->link_timeout) {
- fprintf(stderr, " sleeping\n");
- goto dispatch;
- }
- sleep(1);
- }
- if (i > 0)
- fprintf(stderr, " got link\n");
-
- dispatch:
if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
error("cannot open %s: %s", _PATH_DEVNULL, strerror(errno));
if ((pw = getpwnam("_dhcp")) == NULL)
error("no such user: _dhcp");
- /* Register the interface. */
- if_register_receive();
- if_register_send();
-
if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
_PATH_DHCLIENT_DB, ifi->name) == -1)
error("asprintf");
@@ -596,6 +572,14 @@ main(int argc, char *argv[])
sizeof(ifi->rdomain)) == -1)
error("setsockopt(ROUTE_TABLEFILTER): %s", strerror(errno));
+ ifi->linkstat = interface_status(ifi->name);
+ if (ifi->linkstat == 0)
+ interface_link_forceup(ifi->name);
+
+ /* Register the interface. */
+ if_register_receive();
+ if_register_send();
+
if (chroot(_PATH_VAREMPTY) == -1)
error("chroot");
if (chdir("/") == -1)
@@ -612,11 +596,13 @@ main(int argc, char *argv[])
setproctitle("%s", ifi->name);
- client->state = S_REBOOTING;
- if (ifi->linkstat)
+ if (ifi->linkstat) {
+ client->state = S_REBOOTING;
state_reboot();
- else
- go_daemon();
+ } else {
+ client->state = S_PREBOOT;
+ state_preboot();
+ }
dispatch();
@@ -635,6 +621,49 @@ usage(void)
exit(1);
}
+void
+state_preboot(void)
+{
+ static int preamble;
+ time_t cur_time;
+ int interval;
+
+ time(&cur_time);
+
+ if (client->first_sending == 0)
+ client->first_sending = cur_time;
+
+ interval = (int)(cur_time - client->first_sending);
+
+ if (log_perror && interval > 3) {
+ if (!preamble) {
+ fprintf(stderr, "%s: no link ....", ifi->name);
+ fflush(stderr);
+ preamble = 1;
+ }
+ if (ifi->linkstat) {
+ fprintf(stderr, " got link\n");
+ fflush(stderr);
+ } else if (interval > config->link_timeout) {
+ fprintf(stderr, " sleeping\n");
+ fflush(stderr);
+ } else {
+ fprintf(stderr, ".");
+ fflush(stderr);
+ }
+ }
+
+ if (!ifi->linkstat) {
+ if (interval > config->link_timeout) {
+ go_daemon();
+ client->state = S_REBOOTING;
+ set_timeout_interval(config->retry_interval,
+ state_reboot);
+ } else
+ set_timeout_interval(1, state_preboot);
+ }
+}
+
/*
* Called when the interface link becomes active.
*/
diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h
index d0bf6e37276..50eb887592e 100644
--- a/sbin/dhclient/dhcpd.h
+++ b/sbin/dhclient/dhcpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcpd.h,v 1.144 2014/11/23 18:22:45 krw Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.145 2014/12/05 15:47:05 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -108,6 +108,7 @@ struct client_lease {
/* Possible states in which the client can be. */
enum dhcp_state {
+ S_PREBOOT,
S_REBOOTING,
S_INIT,
S_SELECTING,