- Some type declaration corrections to u_int16_t were made in common/tr.c
(Token Ring support) thanks to a patch from Jason Vas Dias at RedHat.
+- A failover bug that was allowing leases that EXPIRED or were RELEASED
+ where tsfp and tstp are identical timestamps to languish in these
+ transitional states has been repaired. As a side effect, lease
+ databases should be kept more consistent overall, not just for these
+ transitional states.
+
Changes since 3.0.3b3
- dhclient.conf documentation for interface {} was updated to reflect recent
#ifndef lint
static char copyright[] =
-"$Id: conflex.c,v 1.92.2.14 2005/08/26 22:45:44 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
+"$Id: conflex.c,v 1.92.2.15 2005/09/22 16:19:56 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
return ADDRESS;
if (!strcasecmp (atom + 1, "ctive"))
return TOKEN_ACTIVE;
+ if (!strcasecmp (atom + 1, "tsfp"))
+ return ATSFP;
break;
case 'b':
if (!strcasecmp (atom + 1, "ackup"))
struct lease_state *state;
+ /* 'tsfp' is more of an 'effective' tsfp. It may be calculated from
+ * stos+mclt for example if it's an expired lease and the server is
+ * in partner-down state. 'atsfp' is zeroed whenever a lease is
+ * updated - and only set when the peer acknowledges it. This
+ * ensures every state change is transmitted.
+ */
TIME tstp; /* Time sent to partner. */
TIME tsfp; /* Time sent from partner. */
+ TIME atsfp; /* Actual time sent from partner. */
TIME cltt; /* Client last transaction time. */
struct lease *next_pending;
};
REFRESH = 612,
DOMAIN_NAME = 613,
DO_FORWARD_UPDATE = 614,
- KNOWN_CLIENTS = 615
+ KNOWN_CLIENTS = 615,
+ ATSFP = 616
};
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
#ifndef lint
static char copyright[] =
-"$Id: confpars.c,v 1.143.2.25 2005/08/26 22:45:49 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
+"$Id: confpars.c,v 1.143.2.26 2005/09/22 16:19:58 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
seenbit = 131072;
lease -> tsfp = t;
break;
+
+ case ATSFP:
+ seenbit = 262144;
+ lease->atsfp = t;
+ break;
case CLTT:
seenbit = 524288;
Persistent database management routines for DHCPD... */
/*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
#ifndef lint
static char copyright[] =
-"$Id: db.c,v 1.63.2.11 2004/06/17 20:54:40 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
+"$Id: db.c,v 1.63.2.12 2005/09/22 16:19:59 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
++errors;
}
}
+ if (lease->atsfp) {
+ t = gmtime(&lease->atsfp);
+ if (fprintf(db_file,
+ "\n atsfp %d %d/%02d/%02d %02d:%02d:%02d;",
+ t->tm_wday, t->tm_year + 1900, t->tm_mon + 1,
+ t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec) <= 0)
+ ++errors;
+ }
if (lease -> cltt) {
t = gmtime (&lease -> cltt);
errno = 0;
.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
.\" ``http://www.nominum.com''.
.\"
-.\" $Id: dhcpd.8,v 1.18.2.11 2005/09/01 22:03:26 dhankins Exp $
+.\" $Id: dhcpd.8,v 1.18.2.12 2005/09/22 16:19:59 dhankins Exp $
.\"
.TH dhcpd 8
.SH NAME
.RE
.B tsfp \fItime\fR examine
.RS 0.5i
-the time when the lease's current state ends, as understood by the
-failover peer (if there is no failover peer, this value is
-undefined).
+the adjusted time when the lease's current state ends, as understood by
+the failover peer (if there is no failover peer, this value is
+undefined). Generally this value is only adjusted for expired, released,
+or reset leases while the server is operating in partner-down state, and
+otherwise is simply the value supplied by the peer.
+.RE
+.B atsfp \fItime\fR examine
+.RS 0.5i
+the actual tsfp value sent from the peer. This value is forgotten when a
+lease binding state change is made, to facillitate retransmission logic.
.RE
.PP
.B cltt \fItime\fR examine
#ifndef lint
static char copyright[] =
-"$Id: failover.c,v 1.53.2.39 2005/08/26 22:45:50 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
+"$Id: failover.c,v 1.53.2.40 2005/09/22 16:19:59 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
if (msg -> options_present & FTB_CLTT) {
lt -> cltt = msg -> client_ltt;
}
- if (msg -> options_present & FTB_POTENTIAL_EXPIRY) {
- lt -> tsfp = msg -> potential_expiry;
+ if (msg->options_present & FTB_POTENTIAL_EXPIRY) {
+ lt->atsfp = lt->tsfp = msg->potential_expiry;
}
if (msg -> options_present & FTB_BINDING_STATUS) {
if (msg -> options_present & FTB_POTENTIAL_EXPIRY) {
/* XXX it could be a problem to do this directly if the
XXX lease is sorted by tsfp. */
+ lease->atsfp = lease->tsfp = msg->potential_expiry;
+
if ((lease -> binding_state == FTS_EXPIRED ||
lease -> binding_state == FTS_RESET ||
lease -> binding_state == FTS_RELEASED) &&
(msg -> options_present & FTB_BINDING_STATUS) &&
msg -> binding_status == FTS_FREE)
{
- lease -> tsfp = msg -> potential_expiry;
lease -> next_binding_state = FTS_FREE;
supersede_lease (lease, (struct lease *)0, 0, 0, 0);
write_lease (lease);
if (state -> me.state == normal)
commit_leases ();
} else {
- lease -> tsfp = msg -> potential_expiry;
if ((lease -> desired_binding_state !=
lease -> binding_state) &&
(msg -> options_present & FTB_BINDING_STATUS) &&
expiry routine on the pool. */
for (s = shared_networks; s; s = s -> next) {
for (p = s -> pools; p; p = p -> next) {
+ if (p->failover_peer != state)
+ continue;
+
lptr [FREE_LEASES] = &p -> free;
lptr [ACTIVE_LEASES] = &p -> active;
lptr [EXPIRED_LEASES] = &p -> expired;
for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
for (l = *(lptr [i]); l; l = l -> next) {
- if (p -> failover_peer == state &&
- ((everythingp &&
- (l -> starts != MIN_TIME ||
- l -> ends != MIN_TIME)) ||
- l -> tstp > l -> tsfp)) {
+ if ((everythingp &&
+ (l->starts != MIN_TIME ||
+ l->ends != MIN_TIME)) ||
+ (l->tstp > l->atsfp) ||
+ (i == EXPIRED_LEASES)) {
l -> desired_binding_state = l -> binding_state;
dhcp_failover_queue_update (l, 0);
}
case FTS_RESET:
case FTS_RELEASED:
case FTS_EXPIRED:
+ /* XXX - upon entering partner down state, the server
+ * sets tsfp to stos + mclt. this checks that tsfp
+ * + mclt expire before continuing. pick one? i
+ * think abandoned should be treated this way, but
+ * reset/released/expired should check cur_time only.
+ */
if (peer -> service_state == service_partner_down &&
(lease -> tsfp < peer -> me.stos
? peer -> me.stos + peer -> mclt < cur_time
#ifndef lint
static char copyright[] =
-"$Id: mdb.c,v 1.67.2.22 2005/03/03 16:55:25 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
+"$Id: mdb.c,v 1.67.2.23 2005/09/22 16:19:59 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
comp -> uid = (unsigned char *)0;
} else
enter_uid = 1;
-
+
if (comp -> hardware_addr.hlen &&
((comp -> hardware_addr.hlen !=
lease -> hardware_addr.hlen) ||
enter_hwaddr = 1;
} else if (!comp -> hardware_addr.hlen)
enter_hwaddr = 1;
-
+
/* If the lease has been billed to a class, remove the billing. */
if (comp -> billing_class != lease -> billing_class) {
if (comp -> billing_class)
executable_statement_reference (&comp -> on_release,
lease -> on_release, MDL);
}
-
+
/* Record the lease in the uid hash if necessary. */
if (enter_uid && comp -> uid) {
uid_hash_add (comp);
}
-
+
/* Record it in the hardware address hash if necessary. */
if (enter_hwaddr && lease -> hardware_addr.hlen) {
hw_hash_add (comp);
}
-
+
#if defined (FAILOVER_PROTOCOL)
- comp -> cltt = lease -> cltt;
- comp -> tstp = lease -> tstp;
- comp -> tsfp = lease -> tsfp;
+ comp->cltt = lease->cltt;
+ comp->tstp = lease->tstp;
+ comp->tsfp = lease->tsfp;
+ /* If this lease update is transmitted, reduce atsfp to zero. */
+ if (propogate)
+ comp->atsfp = 0;
+ else
+ comp->atsfp = lease->atsfp;
#endif /* FAILOVER_PROTOCOL */
- comp -> ends = lease -> ends;
- comp -> next_binding_state = lease -> next_binding_state;
+ comp->ends = lease->ends;
+ comp->next_binding_state = lease->next_binding_state;
just_move_it:
if (!comp -> pool) {
/* Remove the lease from its current place in its current
timer sequence. */
+ /* XXX this is horrid. */
prev = (struct lease *)0;
for (lp = *lq; lp; lp = lp -> next) {
if (lp == comp)
executable_statement_reference (< -> on_release,
lease -> on_release,
file, line);
- lt -> flags = lease -> flags;
- lt -> tstp = lease -> tstp;
- lt -> tsfp = lease -> tsfp;
- lt -> cltt = lease -> cltt;
- lt -> binding_state = lease -> binding_state;
- lt -> next_binding_state = lease -> next_binding_state;
- status = lease_reference (lp, lt, file, line);
- lease_dereference (<, MDL);
+ lt->flags = lease->flags;
+ lt->tstp = lease->tstp;
+ lt->tsfp = lease->tsfp;
+ lt->atsfp = lease->atsfp;
+ lt->cltt = lease -> cltt;
+ lt->binding_state = lease->binding_state;
+ lt->next_binding_state = lease->next_binding_state;
+ status = lease_reference(lp, lt, file, line);
+ lease_dereference(<, MDL);
return status == ISC_R_SUCCESS;
}
}
#if defined (FAILOVER_PROTOCOL)
if (p -> failover_peer &&
- l -> tstp > l -> tsfp &&
+ l -> tstp > l -> atsfp &&
!(l -> flags & ON_UPDATE_QUEUE)) {
l -> desired_binding_state = l -> binding_state;
dhcp_failover_queue_update (l, 1);
#ifndef lint
static char copyright[] =
-"$Id: omapi.c,v 1.46.2.20 2005/08/26 22:45:50 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
+"$Id: omapi.c,v 1.46.2.21 2005/09/22 16:20:00 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
if (status != ISC_R_SUCCESS)
return status;
+ status = omapi_connection_put_name(c, "atsfp");
+ if (status != ISC_R_SUCCESS)
+ return status;
+ status = omapi_connection_put_uint32(c, sizeof(TIME));
+ if (status != ISC_R_SUCCESS)
+ return status;
+ status = omapi_connection_copyin(c,
+ (const unsigned char *)&(lease->atsfp), sizeof(TIME));
+ if (status != ISC_R_SUCCESS)
+ return status;
+
status = omapi_connection_put_name (c, "cltt");
if (status != ISC_R_SUCCESS)
return status;