summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2014-05-11 12:40:38 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2014-05-11 12:40:38 +0000
commit53c0d747c1b55df8abbb172d11205f682936adbe (patch)
treea1ad8a5c63058636b04ce39b6e630a0e77dedc20
parentd6a3690ec27dca93c7eb1d2bc4a8709ec34453f5 (diff)
Rework/restore recorded lease handling. Actually use 'lease'
statements in dhclient.conf. Recorded and static leases should now be bound to interfaces when appropriate. .... Ken
-rw-r--r--sbin/dhclient/clparse.c52
-rw-r--r--sbin/dhclient/dhclient.c153
2 files changed, 84 insertions, 121 deletions
diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c
index 69b30bc801a..ebbda2c0c25 100644
--- a/sbin/dhclient/clparse.c
+++ b/sbin/dhclient/clparse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clparse.c,v 1.85 2014/05/05 18:02:49 krw Exp $ */
+/* $OpenBSD: clparse.c,v 1.86 2014/05/11 12:40:37 krw Exp $ */
/* Parser for dhclient config and lease files. */
@@ -486,55 +486,21 @@ parse_client_lease_statement(FILE *cfile, int is_static)
}
/*
- * The new lease may supersede a lease that's not the active
- * lease but is still on the lease list, so scan the lease list
- * looking for a lease with the same address, and if we find it,
- * toss it.
+ * The new lease will supersede a lease of the same type and for
+ * the same address.
*/
TAILQ_FOREACH_SAFE(lp, &client->leases, next, pl) {
- if (lp->address.s_addr == lease->address.s_addr) {
+ if (lp->address.s_addr == lease->address.s_addr &&
+ lp->is_static == lease->is_static) {
TAILQ_REMOVE(&client->leases, lp, next);
free_client_lease(lp);
}
}
- /*
- * If this is a preloaded lease, just put it on the list of
- * recorded leases - don't make it the active lease.
- */
- if (is_static) {
- TAILQ_INSERT_HEAD(&client->leases, lease, next);
- return;
- }
-
- /*
- * The last lease in the lease file on a particular interface is
- * the active lease for that interface. Of course, we don't
- * know what the last lease in the file is until we've parsed
- * the whole file, so at this point, we assume that the lease we
- * just parsed is the active lease for its interface. If
- * there's already an active lease for the interface, and this
- * lease is for the same ip address, then we just toss the old
- * active lease and replace it with this one. If this lease is
- * for a different address, then if the old active lease has
- * expired, we dump it; if not, we put it on the list of leases
- * for this interface which are still valid but no longer
- * active.
- */
- if (client->active) {
- if (client->active->expiry < time(NULL))
- free_client_lease(client->active);
- else if (client->active->address.s_addr ==
- lease->address.s_addr)
- free_client_lease(client->active);
- else {
- TAILQ_INSERT_HEAD(&client->leases, client->active,
- next);
- }
- }
- client->active = lease;
-
- /* Phew. */
+ if (is_static)
+ TAILQ_INSERT_TAIL(&client->leases, lease, next);
+ else
+ TAILQ_INSERT_HEAD(&client->leases, lease, next);
}
/*
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 993a6914201..8398522eb13 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.303 2014/05/05 18:02:49 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.304 2014/05/11 12:40:37 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -626,10 +626,31 @@ usage(void)
void
state_reboot(void)
{
+ struct client_lease *lp, *pl;
+ time_t cur_time;
+
cancel_timeout();
deleting.s_addr = INADDR_ANY;
adding.s_addr = INADDR_ANY;
+ time(&cur_time);
+ if (client->active && client->active->expiry <= cur_time) {
+ free_client_lease(client->active);
+ client->active = NULL;
+ }
+
+ /* Run through the list of leases and see if one can be used. */
+ TAILQ_FOREACH_SAFE(lp, &client->leases, next, pl) {
+ if (client->active || lp->is_static)
+ break;
+ else if (lp->expiry <= cur_time)
+ free_client_lease(lp);
+ else {
+ client->active = lp;
+ break;
+ }
+ }
+
/* If we don't remember an active lease, go straight to INIT. */
if (!client->active || client->active->is_bootp) {
client->state = S_INIT;
@@ -784,7 +805,16 @@ bind_lease(void)
{
struct in_addr gateway, mask;
struct option_data *options, *opt;
- struct client_lease *lease;
+ struct client_lease *lease, *pl;
+
+ /*
+ * If it's been here before (e.g. static lease), clear out any
+ * old resolv_conf.
+ */
+ if (client->new->resolv_conf) {
+ free(client->new->resolv_conf);
+ client->new->resolv_conf = NULL;
+ }
lease = apply_defaults(client->new);
options = lease->options;
@@ -866,20 +896,28 @@ bind_lease(void)
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 0, 0,
client->new->resolv_conf, strlen(client->new->resolv_conf));
- /* Replace the old active lease with the new one. */
newlease:
- if (client->active)
- free_client_lease(client->active);
+ /* Replace the old active lease with the new one. */
client->active = client->new;
client->new = NULL;
+ rewrite_option_db(client->active, lease);
+ free_client_lease(lease);
+
+ /* Remove previous dynamic lease(es) for this address. */
+ TAILQ_FOREACH_SAFE(lease, &client->leases, next, pl) {
+ if (lease->is_static)
+ break;
+ if (client->active != lease && lease->address.s_addr ==
+ client->active->address.s_addr)
+ free_client_lease(lease);
+ }
+ if (!client->active->is_static)
+ TAILQ_INSERT_HEAD(&client->leases, client->active, next);
client->state = S_BOUND;
/* Write out new leases file. */
rewrite_client_leases();
- rewrite_option_db(client->active, lease);
-
- free_client_lease(lease);
/* Set timeout to start the renewal process. */
set_timeout(client->active->renewal, state_bound);
@@ -1185,73 +1223,30 @@ send_discover(void)
void
state_panic(void)
{
- struct client_lease *loop = client->active;
+ struct client_lease *lp, *pl;
time_t cur_time;
time(&cur_time);
note("No acceptable DHCPOFFERS received.");
- /*
- * We may not have an active lease, but we may have some predefined
- * leases that we can try.
- */
- if (!client->active && !TAILQ_EMPTY(&client->leases))
- goto activate_next;
-
/* Run through the list of leases and see if one can be used. */
- while (client->active) {
- if (client->active->expiry > cur_time) {
+ time(&cur_time);
+ TAILQ_FOREACH_SAFE(lp, &client->leases, next, pl) {
+ if (lp->is_static) {
+ set_lease_times(lp);
+ note("Trying static lease %s", inet_ntoa(lp->address));
+ } else if (lp->expiry <= cur_time) {
+ free_client_lease(lp);
+ continue;
+ } else
note("Trying recorded lease %s",
- inet_ntoa(client->active->address));
-
- /*
- * If the old lease is still good and doesn't
- * yet need renewal, go into BOUND state and
- * timeout at the renewal time.
- */
- if (cur_time < client->active->renewal) {
- client->state = S_BOUND;
- note("bound: renewal in %lld seconds.",
- (long long)(client->active->renewal
- - cur_time));
- set_timeout(client->active->renewal,
- state_bound);
- } else {
- client->state = S_BOUND;
- note("bound: immediate renewal.");
- state_bound();
- }
- go_daemon();
- return;
- }
+ inet_ntoa(lp->address));
- /* If there are no other leases, give up. */
- if (TAILQ_EMPTY(&client->leases)) {
- TAILQ_INSERT_HEAD(&client->leases, client->active,
- next);
- client->active = NULL;
- break;
- }
-
-activate_next:
- /*
- * Otherwise, put the active lease at the end of the lease
- * list, and try another lease.
- */
- if (client->active)
- TAILQ_INSERT_TAIL(&client->leases, client->active,
- next);
- client->active = TAILQ_FIRST(&client->leases);
- TAILQ_REMOVE(&client->leases, client->active, next);
+ client->new = lp;
+ client->state = S_REQUESTING;
+ bind_lease();
- /*
- * If we already tried this lease, we've exhausted the set of
- * leases, so we might as well give up for now.
- */
- if (client->active == loop)
- break;
- else if (!loop)
- loop = client->active;
+ return;
}
/*
@@ -1584,8 +1579,18 @@ make_decline(struct client_lease *lease)
void
free_client_lease(struct client_lease *lease)
{
+ struct client_lease *lp, *pl;
int i;
+ /* Static leases are forever. */
+ if (lease->is_static)
+ return;
+
+ TAILQ_FOREACH_SAFE(lp, &client->leases, next, pl) {
+ if (lease == lp)
+ TAILQ_REMOVE(&client->leases, lp, next);
+ }
+
if (lease->server_name)
free(lease->server_name);
if (lease->filename)
@@ -1604,6 +1609,7 @@ rewrite_client_leases(void)
{
struct client_lease *lp;
char *leasestr;
+ time_t cur_time;
if (!leaseFile) /* XXX */
error("lease file not open");
@@ -1619,14 +1625,13 @@ rewrite_client_leases(void)
* the leases in client->leases in reverse order to recreate
* the chonological order required.
*/
+ time(&cur_time);
TAILQ_FOREACH_REVERSE(lp, &client->leases, _leases, next) {
- /* Skip any leases that duplicate the active lease address. */
- if (client->active && lp->address.s_addr ==
- client->active->address.s_addr)
- continue;
/* Don't write out static leases from dhclient.conf. */
if (lp->is_static)
continue;
+ if (lp->expiry <= cur_time)
+ continue;
leasestr = lease_as_string("lease", lp);
if (leasestr)
fprintf(leaseFile, "%s", leasestr);
@@ -1634,14 +1639,6 @@ rewrite_client_leases(void)
warning("cannot make lease into string");
}
- if (client->active) {
- leasestr = lease_as_string("lease", client->active);
- if (leasestr)
- fprintf(leaseFile, "%s", leasestr);
- else
- warning("cannot make lease into string");
- }
-
fflush(leaseFile);
ftruncate(fileno(leaseFile), ftello(leaseFile));
fsync(fileno(leaseFile));