diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2014-12-05 15:47:06 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2014-12-05 15:47:06 +0000 |
commit | 3102933c68a271f0c3b5bf4ab50e6229ecd384d1 (patch) | |
tree | 9014e33c463a4106a2ddd5b7e6ae95d7e36f2b56 /sbin/dhclient | |
parent | 7a578d6d316a6e71be68a75a579eeb1435831c6a (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.c | 99 | ||||
-rw-r--r-- | sbin/dhclient/dhcpd.h | 3 |
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, |