From: krw Date: Sun, 11 May 2014 12:40:37 +0000 (+0000) Subject: Rework/restore recorded lease handling. Actually use 'lease' X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=a0eff9f4525e06432caec60b839413096e805b51;p=openbsd 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 --- 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 @@ -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));