- Added client -D option to specify DUID type to send.
+- A new failover configuration parameter has been introduced for those
+ environments where DHCP servers can be reasonably guaranteed to be
+ "down" when the failover TCP socket is severed, "auto-partner-down".
+ This parameter is not generally safe, and by default is disabled, so
+ please carefully review the documentation of this parameter in the
+ dhcpd.conf(5) manpage before determining to use it yourself.
+
Changes since 4.1.0 (bug fixes)
- Remove infinite loop in token_print_indent_concat().
break;
case 'a':
- if (!strncasecmp (atom + 1, "uth", 3)) {
- if (!strncasecmp (atom + 3, "uthenticat", 10)) {
- if (!strcasecmp (atom + 13, "ed"))
- return AUTHENTICATED;
- if (!strcasecmp (atom + 13, "ion"))
- return AUTHENTICATION;
+ if (!strcasecmp(atom + 1, "bandoned"))
+ return TOKEN_ABANDONED;
+ if (!strcasecmp(atom + 1, "ctive"))
+ return TOKEN_ACTIVE;
+ if (!strncasecmp(atom + 1, "dd", 2)) {
+ if (atom[3] == '\0')
+ return TOKEN_ADD;
+ else if (!strcasecmp(atom + 3, "ress"))
+ return ADDRESS;
+ break;
+ }
+ if (!strcasecmp(atom + 1, "fter"))
+ return AFTER;
+ if (isascii(atom[1]) && (tolower(atom[1]) == 'l')) {
+ if (!strcasecmp(atom + 2, "gorithm"))
+ return ALGORITHM;
+ if (!strcasecmp(atom + 2, "ias"))
+ return ALIAS;
+ if (isascii(atom[2]) && (tolower(atom[2]) == 'l')) {
+ if (atom[3] == '\0')
+ return ALL;
+ else if (!strcasecmp(atom + 3, "ow"))
+ return ALLOW;
break;
}
- if (!strcasecmp (atom + 1, "uthoritative"))
- return AUTHORITATIVE;
+ if (!strcasecmp(atom + 2, "so"))
+ return TOKEN_ALSO;
break;
}
- if (!strcasecmp (atom + 1, "nd"))
- return AND;
- if (!strcasecmp(atom + 1, "nycast-mac"))
- return ANYCAST_MAC;
- if (!strcasecmp (atom + 1, "ppend"))
+ if (isascii(atom[1]) && (tolower(atom[1]) == 'n')) {
+ if (!strcasecmp(atom + 2, "d"))
+ return AND;
+ if (!strcasecmp(atom + 2, "ycast-mac"))
+ return ANYCAST_MAC;
+ break;
+ }
+ if (!strcasecmp(atom + 1, "ppend"))
return APPEND;
- if (!strcasecmp (atom + 1, "llow"))
- return ALLOW;
- if (!strcasecmp (atom + 1, "lias"))
- return ALIAS;
- if (!strcasecmp (atom + 1, "lgorithm"))
- return ALGORITHM;
- if (!strcasecmp (atom + 1, "lso"))
- return TOKEN_ALSO;
- if (!strcasecmp (atom + 1, "bandoned"))
- return TOKEN_ABANDONED;
- if (!strcasecmp (atom + 1, "dd"))
- return TOKEN_ADD;
- if (!strcasecmp (atom + 1, "ll"))
- return ALL;
- if (!strcasecmp (atom + 1, "t"))
- return AT;
- if (!strcasecmp (atom + 1, "rray"))
+ if (!strcasecmp(atom + 1, "rray"))
return ARRAY;
- if (!strcasecmp (atom + 1, "ddress"))
- return ADDRESS;
- if (!strcasecmp (atom + 1, "ctive"))
- return TOKEN_ACTIVE;
- if (!strcasecmp (atom + 1, "tsfp"))
- return ATSFP;
- if (!strcasecmp (atom + 1, "fter"))
- return AFTER;
+ if (isascii(atom[1]) && (tolower(atom[1]) == 't')) {
+ if (atom[2] == '\0')
+ return AT;
+ if (!strcasecmp(atom + 2, "sfp"))
+ return ATSFP;
+ break;
+ }
+ if (!strncasecmp(atom + 1, "ut", 2)) {
+ if (isascii(atom[3] && (tolower(atom[3]) == 'h'))) {
+ if (!strncasecmp(atom + 4, "enticat", 7)) {
+ if (!strcasecmp(atom + 11, "ed"))
+ return AUTHENTICATED;
+ if (!strcasecmp(atom + 11, "ion"))
+ return AUTHENTICATION;
+ break;
+ }
+ if (!strcasecmp(atom + 4, "oritative"))
+ return AUTHORITATIVE;
+ break;
+ }
+ if (!strcasecmp(atom + 3, "o-partner-down"))
+ return AUTO_PARTNER_DOWN;
+ break;
+ }
break;
case 'b':
if (!strcasecmp (atom + 1, "ackup"))
void dhcp_failover_startup_timeout (void *);
void dhcp_failover_link_startup_timeout (void *);
void dhcp_failover_listener_restart (void *);
+void dhcp_failover_auto_partner_down(void *vs);
isc_result_t dhcp_failover_state_get_value PROTO ((omapi_object_t *,
omapi_object_t *,
omapi_data_string_t *,
PREFIX6 = 657,
FIXED_PREFIX6 = 658,
ANYCAST_MAC = 659,
- CONFLICT_DONE = 660
+ CONFLICT_DONE = 660,
+ AUTO_PARTNER_DOWN = 661
};
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
u_int32_t max_balance, min_balance;
TIME last_balance, sched_balance;
+ u_int32_t auto_partner_down;
+
enum service_state service_state;
const char *nrr; /* Printable reason why we're in the
not_responding service state (empty
tp = &peer->min_balance;
goto parse_idle;
+ case AUTO_PARTNER_DOWN:
+ tp = &peer->auto_partner_down;
+ goto parse_idle;
+
case MAX_RESPONSE_DELAY:
tp = &cp -> max_response_delay;
parse_idle:
.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
.\" ``http://www.nominum.com''.
.\"
-.\" $Id: dhcpd.conf.5,v 1.103 2009/03/30 18:28:55 jreed Exp $
+.\" $Id: dhcpd.conf.5,v 1.104 2009/06/17 22:08:42 dhankins Exp $
.\"
.TH dhcpd.conf 5
.SH NAME
clients retry.
.RE
.PP
+The
+.I auto-partner-down
+statement
+.RS 0.25i
+.PP
+.B auto-partner-down \fIseconds\fR\fB;\fR
+.PP
+This statement instructs the server to initiate a timed delay upon entering
+the communications-interrupted state (any situation of being out-of-contact
+with the remote failover peer). At the conclusion of the timer, the server
+will automatically enter the partner-down state. This permits the server
+to allocate leases from the partner's free lease pool after an STOS+MCLT
+timer expires, which can be dangerous if the partner is in fact operating
+at the time (the two servers will give conflicting bindings).
+.PP
+Think very carefully before enabling this feature. The partner-down and
+communications-interrupted states are intentionally segregated because
+there do exist situations where a failover server can fail to communicate
+with its peer, but still has the ability to receive and reply to requests
+from DHCP clients. In general, this feature should only be used in those
+deployments where the failover servers are directly connected to one
+another, such as by a dedicated hardwired link ("a heartbeat cable").
+.PP
+A zero value disables the auto-partner-down feature (also the default), and
+any positive value indicates the time in seconds to wait before automatically
+entering partner-down.
+.RE
+.PP
The Failover pool balance statements.
.RS 0.25i
.PP
if (new_state != startup && saved_state == startup)
cancel_timeout (dhcp_failover_startup_timeout, state);
+ /*
+ * If the state changes for any reason, cancel 'delayed auto state
+ * changes' (currently there is just the one).
+ */
+ cancel_timeout(dhcp_failover_auto_partner_down, state);
+
/* Set our service state. */
dhcp_failover_set_service_state (state);
dhcp_failover_send_state (state);
switch (new_state) {
+ case communications_interrupted:
+ /*
+ * There is an optional feature to automatically enter partner
+ * down after a timer expires, upon entering comms-interrupted.
+ * This feature is generally not safe except in specific
+ * circumstances.
+ *
+ * A zero value (also the default) disables it.
+ */
+ if (state->auto_partner_down == 0)
+ break;
+
+#if defined (DEBUG_FAILOVER_TIMING)
+ log_info("add_timeout +%ul dhcp_failover_auto_partner_down",
+ (unsigned long)state->auto_partner_down);
+#endif
+ tv.tv_sec = cur_time + state->auto_partner_down;
+ tv.tv_usec = 0;
+ add_timeout(&tv, dhcp_failover_auto_partner_down, state,
+ (tvref_t)omapi_object_reference,
+ (tvunref_t)omapi_object_dereference);
+ break;
+
case normal:
/* Upon entering normal state, the server is expected to retransmit
* all pending binding updates. This is a good opportunity to
}
break;
-
+
case potential_conflict:
if (state -> i_am == primary)
dhcp_failover_send_update_request (state);
break;
-
+
case startup:
#if defined (DEBUG_FAILOVER_TIMING)
log_info ("add_timeout +15 %s",
}
}
+void
+dhcp_failover_auto_partner_down(void *vs)
+{
+ dhcp_failover_state_t *state = vs;
+
+#if defined (DEBUG_FAILOVER_TIMING)
+ log_info("dhcp_failover_auto_partner_down");
+#endif
+
+ dhcp_failover_set_state(state, partner_down);
+}
+
isc_result_t dhcp_failover_state_get_value (omapi_object_t *h,
omapi_object_t *id,
omapi_data_string_t *name,