2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-22 09:57:20 +00:00

[master] Don't call pool_timer recusively

Add a flag to avoid supersede_lease calling pool_timer
recursively when pool_timer can't handle that.
rt38002
This commit is contained in:
Shawn Routhier 2014-12-10 19:08:05 -08:00
parent 433927d38e
commit 491bf4a27f
6 changed files with 61 additions and 46 deletions

View File

@ -197,6 +197,11 @@ by Eric Young (eay@cryptsoft.com).
bug and supplying a patch. bug and supplying a patch.
[ISC-Bugs #35712] [ISC-Bugs #35712]
- Avoid calling pool_timer() recursively from supersede_lease(). This could
result in leases changing state incorrectly or delaying the running of the
leae expiration code.
[ISC-Bugs #38002]
Changes since 4.3.1b1 Changes since 4.3.1b1
- Modify the linux and openwrt dhclient scripts to process information - Modify the linux and openwrt dhclient scripts to process information

View File

@ -3349,7 +3349,7 @@ void new_shared_network_interface (struct parse *,
int subnet_inner_than(const struct subnet *, const struct subnet *, int); int subnet_inner_than(const struct subnet *, const struct subnet *, int);
void enter_subnet (struct subnet *); void enter_subnet (struct subnet *);
void enter_lease (struct lease *); void enter_lease (struct lease *);
int supersede_lease (struct lease *, struct lease *, int, int, int); int supersede_lease (struct lease *, struct lease *, int, int, int, int);
void make_binding_state_transition (struct lease *); void make_binding_state_transition (struct lease *);
int lease_copy (struct lease **, struct lease *, const char *, int); int lease_copy (struct lease **, struct lease *, const char *, int);
void release_lease (struct lease *, struct packet *); void release_lease (struct lease *, struct packet *);

View File

@ -2963,7 +2963,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
*/ */
if ((use_old_lease == 0) && if ((use_old_lease == 0) &&
!supersede_lease(lease, lt, commit, !supersede_lease(lease, lt, commit,
offer == DHCPACK, offer == DHCPACK)) { offer == DHCPACK, offer == DHCPACK, 0)) {
#else /* defined(DELAYED_ACK) */ #else /* defined(DELAYED_ACK) */
/* /*
* If there already isn't a need for a lease commit, and we * If there already isn't a need for a lease commit, and we
@ -2983,7 +2983,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
*/ */
if ((use_old_lease == 0) && if ((use_old_lease == 0) &&
!supersede_lease(lease, lt, 0, !supersede_lease(lease, lt, 0,
!offer || offer == DHCPACK, 0)) { !offer || offer == DHCPACK, 0, 0)) {
#endif #endif
log_info ("%s: database update failed", msg); log_info ("%s: database update failed", msg);
free_lease_state (state, MDL); free_lease_state (state, MDL);

View File

@ -2602,7 +2602,7 @@ dhcp_failover_pool_dobalance(dhcp_failover_state_t *state,
lp->tstp = cur_time; lp->tstp = cur_time;
lp->starts = cur_time; lp->starts = cur_time;
if (!supersede_lease(lp, NULL, 0, 1, 0) || if (!supersede_lease(lp, NULL, 0, 1, 0, 0) ||
!write_lease(lp)) !write_lease(lp))
log_error("can't commit lease %s on " log_error("can't commit lease %s on "
"giveaway", piaddr(lp->ip_addr)); "giveaway", piaddr(lp->ip_addr));
@ -5412,7 +5412,7 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
lease->rewind_binding_state = lt->next_binding_state; lease->rewind_binding_state = lt->next_binding_state;
/* Try to install the new information. */ /* Try to install the new information. */
if (!supersede_lease (lease, lt, 0, 0, 0) || if (!supersede_lease (lease, lt, 0, 0, 0, 0) ||
!write_lease (lease)) { !write_lease (lease)) {
message = "database update failed"; message = "database update failed";
bad: bad:
@ -5430,7 +5430,7 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
lease->tstp = cur_time; lease->tstp = cur_time;
lease->starts = cur_time; lease->starts = cur_time;
if (!supersede_lease(lease, NULL, 0, 1, 0) || if (!supersede_lease(lease, NULL, 0, 1, 0, 0) ||
!write_lease(lease)) !write_lease(lease))
log_error("can't commit lease %s for mac addr " log_error("can't commit lease %s for mac addr "
"affinity", piaddr(lease->ip_addr)); "affinity", piaddr(lease->ip_addr));
@ -5557,7 +5557,7 @@ isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *state,
/* The peer will have made this state change, so set rewind. */ /* The peer will have made this state change, so set rewind. */
lease->rewind_binding_state = lease->next_binding_state; lease->rewind_binding_state = lease->next_binding_state;
supersede_lease(lease, (struct lease *)0, 0, 0, 0); supersede_lease(lease, NULL, 0, 0, 0, 0);
write_lease(lease); write_lease(lease);
/* Lease has returned to FREE state from the /* Lease has returned to FREE state from the
@ -5582,8 +5582,7 @@ isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *state,
if (lease->desired_binding_state != lease->binding_state) { if (lease->desired_binding_state != lease->binding_state) {
lease->next_binding_state = lease->next_binding_state =
lease->desired_binding_state; lease->desired_binding_state;
supersede_lease(lease, supersede_lease(lease, NULL, 0, 0, 0, 0);
(struct lease *)0, 0, 0, 0);
} }
write_lease(lease); write_lease(lease);
/* Commit the lease only after a two-second timeout, /* Commit the lease only after a two-second timeout,
@ -5613,7 +5612,7 @@ isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *state,
lease->next_binding_state = FTS_BACKUP; lease->next_binding_state = FTS_BACKUP;
lease->tstp = lease->starts = cur_time; lease->tstp = lease->starts = cur_time;
if (!supersede_lease(lease, NULL, 0, 1, 0) || if (!supersede_lease(lease, NULL, 0, 1, 0, 0) ||
!write_lease(lease)) !write_lease(lease))
log_error("can't commit lease %s for " log_error("can't commit lease %s for "
"client affinity", piaddr(lease->ip_addr)); "client affinity", piaddr(lease->ip_addr));

View File

@ -1091,11 +1091,12 @@ void enter_lease (lease)
list of leases by expiry time so that we can always find the oldest list of leases by expiry time so that we can always find the oldest
lease. */ lease. */
int supersede_lease (comp, lease, commit, propogate, pimmediate) int supersede_lease (comp, lease, commit, propogate, pimmediate, from_pool)
struct lease *comp, *lease; struct lease *comp, *lease;
int commit; int commit;
int propogate; int propogate;
int pimmediate; int pimmediate;
int from_pool;
{ {
struct lease *lp, **lq, *prev; struct lease *lp, **lq, *prev;
struct timeval tv; struct timeval tv;
@ -1446,15 +1447,17 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
dhcp_failover_pool_check(comp->pool); dhcp_failover_pool_check(comp->pool);
#endif #endif
/* If the current binding state has already expired, do an /* If the current binding state has already expired and we haven't
expiry event right now. */ * been called from pool_timer, do an expiry event right now.
*/
/* XXX At some point we should optimize this so that we don't /* XXX At some point we should optimize this so that we don't
XXX write the lease twice, but this is a safe way to fix the XXX write the lease twice, but this is a safe way to fix the
XXX problem for 3.0 (I hope!). */ XXX problem for 3.0 (I hope!). */
if ((commit || !pimmediate) && if ((from_pool == 0) &&
comp -> sort_time < cur_time && (commit || !pimmediate) &&
comp -> next_binding_state != comp -> binding_state) (comp->sort_time < cur_time) &&
pool_timer (comp -> pool); (comp->next_binding_state != comp->binding_state))
pool_timer(comp->pool);
return 1; return 1;
} }
@ -1779,7 +1782,7 @@ void release_lease (lease, packet)
#else #else
lease -> next_binding_state = FTS_FREE; lease -> next_binding_state = FTS_FREE;
#endif #endif
supersede_lease (lease, (struct lease *)0, 1, 1, 1); supersede_lease(lease, NULL, 1, 1, 1, 0);
} }
} }
@ -1812,7 +1815,7 @@ void abandon_lease (lease, message)
lt -> uid = (unsigned char *)0; lt -> uid = (unsigned char *)0;
lt -> uid_len = 0; lt -> uid_len = 0;
lt -> uid_max = 0; lt -> uid_max = 0;
supersede_lease (lease, lt, 1, 1, 1); supersede_lease (lease, lt, 1, 1, 1, 0);
lease_dereference (&lt, MDL); lease_dereference (&lt, MDL);
} }
@ -1854,7 +1857,7 @@ void dissociate_lease (lease)
lt -> uid = (unsigned char *)0; lt -> uid = (unsigned char *)0;
lt -> uid_len = 0; lt -> uid_len = 0;
lt -> uid_max = 0; lt -> uid_max = 0;
supersede_lease (lease, lt, 1, 1, 1); supersede_lease (lease, lt, 1, 1, 1, 0);
lease_dereference (&lt, MDL); lease_dereference (&lt, MDL);
} }
#endif #endif
@ -1864,8 +1867,8 @@ void pool_timer (vpool)
void *vpool; void *vpool;
{ {
struct pool *pool; struct pool *pool;
struct lease *next = (struct lease *)0; struct lease *next = NULL;
struct lease *lease = (struct lease *)0; struct lease *lease = NULL;
#define FREE_LEASES 0 #define FREE_LEASES 0
#define ACTIVE_LEASES 1 #define ACTIVE_LEASES 1
#define EXPIRED_LEASES 2 #define EXPIRED_LEASES 2
@ -1879,11 +1882,11 @@ void pool_timer (vpool)
pool = (struct pool *)vpool; pool = (struct pool *)vpool;
lptr [FREE_LEASES] = &pool -> free; lptr[FREE_LEASES] = &pool->free;
lptr [ACTIVE_LEASES] = &pool -> active; lptr[ACTIVE_LEASES] = &pool->active;
lptr [EXPIRED_LEASES] = &pool -> expired; lptr[EXPIRED_LEASES] = &pool->expired;
lptr [ABANDONED_LEASES] = &pool -> abandoned; lptr[ABANDONED_LEASES] = &pool->abandoned;
lptr [BACKUP_LEASES] = &pool -> backup; lptr[BACKUP_LEASES] = &pool->backup;
lptr[RESERVED_LEASES] = &pool->reserved; lptr[RESERVED_LEASES] = &pool->reserved;
for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) { for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
@ -1919,20 +1922,20 @@ void pool_timer (vpool)
continue; continue;
} }
#endif #endif
lease_reference (&lease, *(lptr [i]), MDL); lease_reference(&lease, *(lptr [i]), MDL);
while (lease) { while (lease) {
/* Remember the next lease in the list. */ /* Remember the next lease in the list. */
if (next) if (next)
lease_dereference (&next, MDL); lease_dereference(&next, MDL);
if (lease -> next) if (lease -> next)
lease_reference (&next, lease -> next, MDL); lease_reference(&next, lease->next, MDL);
/* If we've run out of things to expire on this list, /* If we've run out of things to expire on this list,
stop. */ stop. */
if (lease -> sort_time > cur_time) { if (lease->sort_time > cur_time) {
if (lease -> sort_time < next_expiry) if (lease->sort_time < next_expiry)
next_expiry = lease -> sort_time; next_expiry = lease->sort_time;
break; break;
} }
@ -1962,27 +1965,35 @@ void pool_timer (vpool)
lease->next_binding_state = lease->next_binding_state =
lease->rewind_binding_state; lease->rewind_binding_state;
#endif #endif
supersede_lease(lease, NULL, 1, 1, 1); supersede_lease(lease, NULL, 1, 1, 1, 1);
} }
lease_dereference (&lease, MDL); lease_dereference(&lease, MDL);
if (next) if (next)
lease_reference (&lease, next, MDL); lease_reference(&lease, next, MDL);
} }
if (next) if (next)
lease_dereference (&next, MDL); lease_dereference(&next, MDL);
if (lease) if (lease)
lease_dereference (&lease, MDL); lease_dereference(&lease, MDL);
} }
if (next_expiry != MAX_TIME) {
pool -> next_event_time = next_expiry; /* If we found something to expire and its expiration time
tv . tv_sec = pool -> next_event_time; * is either less than the current expiration time or the
tv . tv_usec = 0; * current expiration time is already expired update the
* timer.
*/
if ((next_expiry != MAX_TIME) &&
((pool->next_event_time > next_expiry) ||
(pool->next_event_time <= cur_time))) {
pool->next_event_time = next_expiry;
tv.tv_sec = pool->next_event_time;
tv.tv_usec = 0;
add_timeout (&tv, pool_timer, pool, add_timeout (&tv, pool_timer, pool,
(tvref_t)pool_reference, (tvref_t)pool_reference,
(tvunref_t)pool_dereference); (tvunref_t)pool_dereference);
} else } else
pool -> next_event_time = MIN_TIME; pool->next_event_time = MIN_TIME;
} }

View File

@ -227,7 +227,7 @@ isc_result_t dhcp_lease_set_value (omapi_object_t *h,
if (lease -> binding_state != bar) { if (lease -> binding_state != bar) {
lease -> next_binding_state = bar; lease -> next_binding_state = bar;
if (supersede_lease (lease, 0, 1, 1, 1)) { if (supersede_lease (lease, NULL, 1, 1, 1, 0)) {
log_info ("lease %s state changed from %s to %s", log_info ("lease %s state changed from %s to %s",
piaddr(lease->ip_addr), ols, nls); piaddr(lease->ip_addr), ols, nls);
return ISC_R_SUCCESS; return ISC_R_SUCCESS;
@ -260,7 +260,7 @@ isc_result_t dhcp_lease_set_value (omapi_object_t *h,
return status; return status;
old_lease_end = lease->ends; old_lease_end = lease->ends;
lease->ends = lease_end; lease->ends = lease_end;
if (supersede_lease (lease, 0, 1, 1, 1)) { if (supersede_lease (lease, NULL, 1, 1, 1, 0)) {
log_info ("lease %s end changed from %lu to %lu", log_info ("lease %s end changed from %lu to %lu",
piaddr(lease->ip_addr), old_lease_end, lease_end); piaddr(lease->ip_addr), old_lease_end, lease_end);
return ISC_R_SUCCESS; return ISC_R_SUCCESS;
@ -279,7 +279,7 @@ isc_result_t dhcp_lease_set_value (omapi_object_t *h,
(lease->flags & ~EPHEMERAL_FLAGS); (lease->flags & ~EPHEMERAL_FLAGS);
if(oldflags == lease->flags) if(oldflags == lease->flags)
return ISC_R_SUCCESS; return ISC_R_SUCCESS;
if (!supersede_lease(lease, NULL, 1, 1, 1)) { if (!supersede_lease(lease, NULL, 1, 1, 1, 0)) {
log_error("Failed to update flags for lease %s.", log_error("Failed to update flags for lease %s.",
piaddr(lease->ip_addr)); piaddr(lease->ip_addr));
return ISC_R_IOERROR; return ISC_R_IOERROR;