]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- A new failover configuration parameter has been introduced for those
authorDavid Hankins <dhankins@isc.org>
Wed, 17 Jun 2009 22:08:42 +0000 (22:08 +0000)
committerDavid Hankins <dhankins@isc.org>
Wed, 17 Jun 2009 22:08:42 +0000 (22:08 +0000)
  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.
  [ISC-Bugs #19600]

RELNOTES
common/conflex.c
includes/dhcpd.h
includes/dhctoken.h
includes/failover.h
server/confpars.c
server/dhcpd.conf.5
server/failover.c

index 312169eba34a06ad7aca9f6f32854640c1d5911e..c9b6b6c6b039111afe62b2430a92d2f9d2abb29d 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -51,6 +51,13 @@ work on other platforms. Please report any problems and suggested fixes to
 
 - 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().
index e7426417221d4c3f589d7f482643fc5e644708ec..d17b3040ae0ce8a113706874ba9d9786fc8a15e7 100644 (file)
@@ -706,50 +706,70 @@ intern(char *atom, enum dhcp_token dfv) {
                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"))
index b0c4969d6ea2ef2d159e872d39987aacdf6cb6a3..d761039911a44247e4637c374c10c97077ae628e 100644 (file)
@@ -3150,6 +3150,7 @@ void dhcp_failover_reconnect (void *);
 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 *,
index 3cb397ac3663a762f4a051f9984931603b66bff3..01ed130372484ca924e60f8bfdf564bd5a563f37 100644 (file)
@@ -354,7 +354,8 @@ enum dhcp_token {
        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 &&  \
index ed3dc961f354809371f2d5346632117940aa77dc..f80beb7d9da6865cc86b987fa000e45a1a6b0b06 100644 (file)
@@ -352,6 +352,8 @@ typedef struct _dhcp_failover_state {
        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
index 63dc465db87767e5da90edb457e22b2f56b696bb..2ccd897218f311e79559bfe77b56b368b86f21c8 100644 (file)
@@ -1012,6 +1012,10 @@ void parse_failover_peer (cfile, group, type)
                        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:
index e5eec88e40fa5efbf515100659c63906387a5306..45e390d621547a14323211c3680a4edb391c4ca8 100644 (file)
@@ -28,7 +28,7 @@
 .\" 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
@@ -741,6 +741,34 @@ failover peer will take over its client load automatically as the
 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
index 773f1e7a0b8ef24e553011644d7aaa76dfd12bde..795f896a66a331c332341eb1f0f42156d5d367c5 100644 (file)
@@ -1797,6 +1797,12 @@ isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *state,
     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);
 
@@ -1805,6 +1811,29 @@ isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *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
@@ -1820,12 +1849,12 @@ isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *state,
            }
 
            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",
@@ -3066,6 +3095,18 @@ void dhcp_failover_listener_restart (void *vs)
        }
 }
 
+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,