]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Implement pool request and response so that secondary can operate.
authorTed Lemon <source@isc.org>
Thu, 4 May 2000 18:58:16 +0000 (18:58 +0000)
committerTed Lemon <source@isc.org>
Thu, 4 May 2000 18:58:16 +0000 (18:58 +0000)
12 files changed:
client/dhclient.cat8
common/conflex.c
common/dhcp-options.cat5
includes/dhcpd.h
includes/dhctoken.h
includes/failover.h
includes/site.h
server/confpars.c
server/db.c
server/dhcp.c
server/failover.c
server/mdb.c

index a58bbb6038148e50aeeb4fd3ced489a375609b18..eb274700cd0c5c676be9d65bbb453ece84c588e6 100644 (file)
@@ -10,7 +10,7 @@ N\bNA\bAM\bME\bE
 S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS
        d\bdh\bhc\bcl\bli\bie\ben\bnt\bt  [  -\b-p\bp  _\bp_\bo_\br_\bt  ] [ -\b-d\bd ] [ -\b-D\bD ] [ -\b-q\bq ] [ -\b-c\bc ] [ -\b-l\blf\bf
        _\bl_\be_\ba_\bs_\be_\b-_\bf_\bi_\bl_\be ] [ -\b-p\bpf\bf _\bp_\bi_\bd_\b-_\bf_\bi_\bl_\be ] [ -\b-c\bcf\bf  _\bc_\bo_\bn_\bf_\bi_\bg_\b-_\bf_\bi_\bl_\be  ]  [  -\b-s\bs
-       server ] [ _\bi_\bf_\b0 [ _\b._\b._\b._\bi_\bf_\bN ] ]
+       server ] [ -\b-w\bw ] [ _\bi_\bf_\b0 [ _\b._\b._\b._\bi_\bf_\bN ] ]
 
 D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
        The  Internet  Software  Consortium DHCP Client, dhclient,
@@ -160,8 +160,19 @@ dhclient(8)                                           dhclient(8)
        /\b/v\bva\bar\br/\b/d\bdb\bb or /\b/v\bva\bar\br/\b/r\bru\bun\bn has not yet been mounted when the DHCP
        client is started.
 
+       The  DHCP  client normally exits if it isn't able to iden­
+       tify any network interfaces to configure.   On laptop com­
+       puters  and  other computers with hot-swappable I/O buses,
+       it is possible that a broadcast  interface  may  be  added
+       after  system  startup.   The -\b-w\bw flag can be used to cause
+       the client not to exit  when  it  doesn't  find  any  such
+       interfaces.    The d\bdh\bhc\bcp\bpc\bcc\bcp\bp (\b(8\b8)\b) program can then be used to
+       notify the client when a network interface has been  added
+       or removed, so that the client can configure an IP address
+       on that interface.
+
 C\bCO\bON\bNF\bFI\bIG\bGU\bUR\bRA\bAT\bTI\bIO\bON\bN
-       The  syntax  of  the  dhclient.conf(8)  file  is discussed
+       The syntax  of  the  dhclient.conf(8)  file  is  discussed
        seperately.
 
 F\bFI\bIL\bLE\bES\bS
@@ -173,23 +184,12 @@ S\bSE\bEE\bE A\bAL\bLS\bSO\bO
        dhclient.leases(5)
 
 A\bAU\bUT\bTH\bHO\bOR\bR
-       d\bdh\bhc\bcl\bli\bie\ben\bnt\bt(\b(8\b8)\bhas been written  for  the  Internet  Software
-       Consortium  by Ted Lemon <mellon@fugue.com> in cooperation
-       with Vixie Enterprises.  To learn more about the  Internet
+       d\bdh\bhc\bcl\bli\bie\ben\bnt\bt(\b(8\b8)\b has  been  written  for the Internet Software
+       Consortium by Ted Lemon <mellon@fugue.com> in  cooperation
+       with  Vixie Enterprises.  To learn more about the Internet
        Software Consortium, see h\bht\btt\btp\bp:\b:/\b//\b/w\bww\bww\bw.\b.v\bvi\bix\bx.\b.c\bco\bom\bm/\b/i\bis\bsc\bc.\b.  To learn
        more about Vixie Enterprises, see h\bht\btt\btp\bp:\b:/\b//\b/w\bww\bww\bw.\b.v\bvi\bix\bx.\b.c\bco\bom\bm.\b.
 
-       This client was substantially  modified  and  enhanced  by
-       Elliot  Poger for use on Linux while he was working on the
-       MosquitoNet project at Stanford.
-
-       The current version owes much to Elliot's  Linux  enhance­
-       ments,  but  was  substantially  reorganized and partially
-       rewritten by Ted Lemon so as to use  the  same  networking
-       framework  that  the  Internet  Software  Consortium  DHCP
-       server uses.   Much system-specific configuration code was
-       moved  into  a  shell  script  so that as support for more
-       operating systems is added, it will not  be  necessary  to
 
 
 
@@ -202,20 +202,20 @@ A\bAU\bUT\bTH\bHO\bOR\bR
 dhclient(8)                                           dhclient(8)
 
 
-       port  and  maintain  system-specific configuration code to
-       these operating systems - instead, the  shell  script  can
-       invoke the native tools to accomplish the same purpose.
-
-
-
-
-
-
-
-
-
-
+       This  client  was  substantially  modified and enhanced by
+       Elliot Poger for use on Linux while he was working on  the
+       MosquitoNet project at Stanford.
 
+       The  current  version owes much to Elliot's Linux enhance­
+       ments, but was  substantially  reorganized  and  partially
+       rewritten  by  Ted  Lemon so as to use the same networking
+       framework  that  the  Internet  Software  Consortium  DHCP
+       server uses.   Much system-specific configuration code was
+       moved into a shell script so  that  as  support  for  more
+       operating  systems  is  added, it will not be necessary to
+       port and maintain system-specific  configuration  code  to
+       these  operating  systems  - instead, the shell script can
+       invoke the native tools to accomplish the same purpose.
 
 
 
index 0d7bc89cf91da74f25ef3c056bae053c04f1e85f..1074a37a45673bbb06ba0dd27831c1e0d28f469d 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: conflex.c,v 1.73 2000/05/03 05:56:28 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: conflex.c,v 1.74 2000/05/04 18:57:57 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -562,6 +562,8 @@ static enum dhcp_token intern (atom, dfv)
                        return CONCAT;
                if (!strcasecmp (atom + 1, "ommunications-interrupted"))
                        return COMMUNICATIONS_INTERRUPTED;
+               if (!strcasecmp (atom + 1, "ltt"))
+                       return CLTT;
                break;
              case 'd':
                if (!strcasecmp (atom + 1, "ns-update"))
index 3275f213022495b3f757a8e0f1d2ed27fb2f41af..c87cb22e964082410295aa2e35869bb98c54294b 100644 (file)
@@ -94,10 +94,10 @@ dhcpd-options(5)                                 dhcpd-options(5)
           assume  that all subnets of the IP network to which the
           client is connected use the same MTU as the  subnet  of
           that network to which the client is directly connected.
-          A value of 1 indicates that all subnets share the  same
-          MTU.   A value of 0 means that the client should assume
-          that some subnets of the directly connected network may
-          have smaller MTUs.
+          A value of true indicates that all  subnets  share  the
+          same  MTU.   A  value  of  false  means that the client
+          should assume that some subnets of  the  directly  con­
+          nected network may have smaller MTUs.
 
        o\bop\bpt\bti\bio\bon\bn a\bar\brp\bp-\b-c\bca\bac\bch\bhe\be-\b-t\bti\bim\bme\beo\bou\but\bt _\bu_\bi_\bn_\bt_\b3_\b2;\b;
 
@@ -240,9 +240,9 @@ dhcpd-options(5)                                 dhcpd-options(5)
           This  option specifies whether or not the client should
           use Ethernet Version 2 (RFC 894)  or  IEEE  802.3  (RFC
           1042) encapsulation if the interface is an Ethernet.  A
-          value of 0 indicates that the client should use RFC 894
-          encapsulation.   A  value  of  1  means that the client
-          should use RFC 1042 encapsulation.
+          value of false indicates that the client should use RFC
+          894  encapsulation.   A  value  of  true means that the
+          client should use RFC 1042 encapsulation.
 
        o\bop\bpt\bti\bio\bon\bn i\bie\ben\bn1\b11\b16\b6-\b-n\bna\bam\bme\be-\b-s\bse\ber\brv\bve\ber\brs\bs _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs [,\b, _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs...  ];
 
@@ -276,9 +276,9 @@ dhcpd-options(5)                                 dhcpd-options(5)
        o\bop\bpt\bti\bio\bon\bn i\bip\bp-\b-f\bfo\bor\brw\bwa\bar\brd\bdi\bin\bng\bg _\bf_\bl_\ba_\bg;\b;
 
           This option specifies whether the client should config­
-          ure  its  IP layer for packet forwarding.  A value of 0
-          means disable IP forwarding, and a  value  of  1  means
-          enable IP forwarding.
+          ure  its  IP  layer  for packet forwarding.  A value of
+          false means disable IP forwarding, and a value of  true
+          means enable IP forwarding.
 
        o\bop\bpt\bti\bio\bon\bn i\bir\brc\bc-\b-s\bse\ber\brv\bve\ber\br _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs [,\b, _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs... ];\b;
 
@@ -302,8 +302,8 @@ dhcpd-options(5)                                 dhcpd-options(5)
 
           This  option specifies whether or not the client should
           respond to subnet mask requests using ICMP.  A value of
-          0  indicates  that  the  client  should not respond.  A
-          value of 1 means that the client should respond.
+          false  indicates that the client should not respond.  A
+          value of true means that the client should respond.
 
        o\bop\bpt\bti\bio\bon\bn m\bma\bax\bx-\b-d\bdg\bgr\bra\bam\bm-\b-r\bre\bea\bas\bss\bse\bem\bmb\bbl\bly\by _\bu_\bi_\bn_\bt_\b1_\b6;\b;
 
@@ -466,7 +466,7 @@ dhcpd-options(5)                                 dhcpd-options(5)
 dhcpd-options(5)                                 dhcpd-options(5)
 
 
-          forwarding  of  such  datagrams, and a value of 1 means
+          forwarding of such datagrams, and a value of true means
           allow forwarding.
 
        o\bop\bpt\bti\bio\bon\bn n\bnt\btp\bp-\b-s\bse\ber\brv\bve\ber\brs\bs _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs [,\b, _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs...  ];\b;
@@ -492,10 +492,10 @@ dhcpd-options(5)                                 dhcpd-options(5)
        o\bop\bpt\bti\bio\bon\bn p\bpe\ber\brf\bfo\bor\brm\bm-\b-m\bma\bas\bsk\bk-\b-d\bdi\bis\bsc\bco\bov\bve\ber\bry\by _\bf_\bl_\ba_\bg;\b;
 
           This option specifies whether or not the client  should
-          perform subnet mask discovery using ICMP.  A value of 0
-          indicates that the client should not perform mask  dis­
-          covery.  A value of 1 means that the client should per­
-          form mask discovery.
+          perform  subnet  mask discovery using ICMP.  A value of
+          false indicates that the client should not perform mask
+          discovery.   A  value  of  true  means  that the client
+          should perform mask discovery.
 
        o\bop\bpt\bti\bio\bon\bn p\bpo\bol\bli\bic\bcy\by-\b-f\bfi\bil\blt\bte\ber\br _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs
                          [,\b, _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs...];\b;
@@ -547,10 +547,10 @@ dhcpd-options(5)                                 dhcpd-options(5)
 
           This option specifies whether or not the client  should
           solicit  routers  using  the Router Discovery mechanism
-          defined in RFC 1256.  A value of 0 indicates  that  the
-          client should not perform router discovery.  A value of
-          1 means that the client should perform  router  discov­
-          ery.
+          defined in RFC 1256.  A value of false  indicates  that
+          the  client  should  not  perform  router discovery.  A
+          value of true means  that  the  client  should  perform
+          router discovery.
 
        o\bop\bpt\bti\bio\bon\bn r\bro\bou\but\bte\ber\br-\b-s\bso\bol\bli\bic\bci\bit\bta\bat\bti\bio\bon\bn-\b-a\bad\bdd\bdr\bre\bes\bss\bs _\bi_\bp_\b-_\ba_\bd_\bd_\br_\be_\bs_\bs;\b;
 
@@ -638,9 +638,9 @@ dhcpd-options(5)                                 dhcpd-options(5)
           This option specifies the whether  or  not  the  client
           should  send  TCP  keepalive  messages  with a octet of
           garbage for compatibility with  older  implementations.
-          A  value of 0 indicates that a garbage octet should not
-          be sent. A value of 1 indicates that  a  garbage  octet
-          should be sent.
+          A  value of false indicates that a garbage octet should
+          not be sent. A value of true indicates that  a  garbage
+          octet should be sent.
 
        o\bop\bpt\bti\bio\bon\bn t\btc\bcp\bp-\b-k\bke\bee\bep\bpa\bal\bli\biv\bve\be-\b-i\bin\bnt\bte\ber\brv\bva\bal\bl _\bu_\bi_\bn_\bt_\b3_\b2;\b;
 
@@ -690,7 +690,8 @@ dhcpd-options(5)                                 dhcpd-options(5)
           negotiate the use of trailers (RFC 893 [14]) when using
           the  ARP  protocol.   A  value  of 0 indicates that the
           client should not attempt to use trailers.  A value  of
-          1 means that the client should attempt to use trailers.
+          true means that the client should attempt to use trail­
+          ers.
 
        o\bop\bpt\bti\bio\bon\bn u\bua\bap\bp-\b-s\bse\ber\brv\bve\ber\brs\bs _\bt_\be_\bx_\bt;\b;
 
@@ -720,7 +721,6 @@ dhcpd-options(5)                                 dhcpd-options(5)
 
 
 
-
                                                                11
 
 
index 490c95f73ee0bd089080e5fb22048cd3dc974d3a..7e4695c1e1cccf0b800ae3d89dc06d39095981ea 100644 (file)
@@ -271,7 +271,8 @@ struct lease {
 #      define ON_UPDATE_QUEUE          64
 #      define ON_ACK_QUEUE             128
 #      define EPHEMERAL_FLAGS          (BOOTP_LEASE | MS_NULL_TERMINATION | \
-                                        ABANDONED_LEASE | PEER_IS_OWNER)
+                                        ABANDONED_LEASE | PEER_IS_OWNER | \
+                                        ON_ACK_QUEUE | ON_UPDATE_QUEUE)
 
        struct lease_state *state;
 
@@ -1943,6 +1944,8 @@ isc_result_t dhcp_class_create (omapi_object_t **,
 
 /* mdb.c */
 
+extern struct subnet *subnets;
+extern struct shared_network *shared_networks;
 extern struct hash_table *host_hw_addr_hash;
 extern struct hash_table *host_uid_hash;
 extern struct hash_table *host_name_hash;
@@ -1976,7 +1979,7 @@ void new_shared_network_interface PROTO ((struct parse *,
 int subnet_inner_than PROTO ((struct subnet *, struct subnet *, int));
 void enter_subnet PROTO ((struct subnet *));
 void enter_lease PROTO ((struct lease *));
-int supersede_lease PROTO ((struct lease *, struct lease *, int));
+int supersede_lease PROTO ((struct lease *, struct lease *, int, int));
 void release_lease PROTO ((struct lease *, struct packet *));
 void abandon_lease PROTO ((struct lease *, const char *));
 void dissociate_lease PROTO ((struct lease *));
@@ -2055,6 +2058,9 @@ isc_result_t dhcp_failover_state_transition (dhcp_failover_state_t *,
                                             const char *);
 isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *,
                                      enum failover_state);
+int dhcp_failover_pool_rebalance (dhcp_failover_state_t *);
+int dhcp_failover_pool_check (struct pool *);
+int dhcp_failover_state_pool_check (dhcp_failover_state_t *);
 isc_result_t dhcp_failover_send_updates (dhcp_failover_state_t *);
 int dhcp_failover_queue_update (struct lease *);
 void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *, struct lease *);
@@ -2084,6 +2090,10 @@ isc_result_t dhcp_failover_state_remove PROTO ((omapi_object_t *,
 int dhcp_failover_state_match (dhcp_failover_state_t *, u_int8_t *, unsigned);
 const char *dhcp_failover_reject_reason_print (int);
 const char *dhcp_failover_state_name_print (enum failover_state);
+failover_option_t *dhcp_failover_option_printf PROTO ((unsigned, char *,
+                                                      unsigned *,
+                                                      unsigned, 
+                                                      const char *, ...));
 failover_option_t *dhcp_failover_make_option PROTO ((unsigned, char *,
                                                     unsigned *,
                                                     unsigned, ...));
@@ -2096,10 +2106,15 @@ isc_result_t dhcp_failover_send_disconnect PROTO ((omapi_object_t *,
                                                   int, const char *));
 isc_result_t dhcp_failover_send_bind_update (dhcp_failover_state_t *,
                                             struct lease *);
-isc_result_t dhcp_failover_process_bindupdate (dhcp_failover_state_t *,
-                                              failover_message_t *);
-isc_result_t dhcp_failover_process_bindack (dhcp_failover_state_t *,
-                                           failover_message_t *);
+isc_result_t dhcp_failover_send_bind_ack (dhcp_failover_state_t *,
+                                         struct lease *, failover_message_t *,
+                                         int, const char *);
+isc_result_t dhcp_failover_send_poolreq (dhcp_failover_state_t *);
+isc_result_t dhcp_failover_send_poolresp (dhcp_failover_state_t *, int);
+isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *,
+                                               failover_message_t *);
+isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *,
+                                            failover_message_t *);
 void failover_print PROTO ((char *, unsigned *, unsigned, const char *));
 void update_partner PROTO ((struct lease *));
 int load_balance_mine (struct packet *, dhcp_failover_state_t *);
index 0fcfd0cd486efb7b23500385b530de7b6d6b41fd..41f86b229a01d9c2b6e00e0411dbd84661ddc249 100644 (file)
@@ -266,7 +266,8 @@ enum dhcp_token {
        ADDRESS = 464,
        POTENTIAL_CONFLICT_NIC = 465,
        STATE = 466,
-       UNKNOWN_STATE = 567
+       UNKNOWN_STATE = 567,
+       CLTT = 568
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index b41d3d2c82e47c604514ef3e355370b47e2ea58a..8617cdb3632cf237d4b9aad7b4c099a421f0b112 100644 (file)
@@ -156,6 +156,15 @@ typedef struct {
 #define FTR_HBA_CONFLICT       19
 #define FTR_UNKNOWN            254
 
+/* Lease states: */
+#define FTS_FREE               1
+#define FTS_ACTIVE             2
+#define FTS_EXPIRED            3
+#define FTS_RELEASED           4
+#define FTS_ABANDONED          5
+#define FTS_RESET              6
+#define FTS_BACKUP             7
+
 #define DHCP_FAILOVER_MAX_MESSAGE_SIZE 2048
 
 typedef struct {
index f3a81b45aa5ca9b22defbf79ab3077809ada8ed0..aea811fb2a50330413432d5c0e52b688a1cc0b29 100644 (file)
 /* Define this if you want exhaustive (and very slow) checking of the
    malloc pool for corruption. */
 
-/* #define DEBUG_MALLOC_POOL */
+#define DEBUG_MALLOC_POOL
 
 /* Define this if you want to maintain a history of the last N operations
    that changed reference counts on objects.   This can be used to debug
    cases where an object is dereferenced too often, or not often enough. */
 
-/* #define DEBUG_RC_HISTORY */
+#define DEBUG_RC_HISTORY
 
 /* Define this if you want to see the history every cycle. */
 
 /* #define DEBUG_RC_HISTORY_EXHAUSTIVELY */
+
 /* This is the number of history entries to maintain - by default, 256. */
 
-/* #define RC_HISTORY_MAX 1024 */
+#define RC_HISTORY_MAX 1024
 
 /* Define this if you want dhcpd to dump core when a non-fatal memory
    allocation error is detected (i.e., something that would cause a
    memory leak rather than a memory smash). */
 
-/* #define POINTER_DEBUG */
+#define POINTER_DEBUG
 
 /* Define this if you want debugging output for DHCP failover protocol
    messages. */
 
-/* #define DEBUG_FAILOVER_MESSAGES */
+#define DEBUG_FAILOVER_MESSAGES
 
 /* Define this if you want debugging output for DHCP failover protocol
    lease assignment timing. */
 
-/* #define DEBUG_FAILOVER_TIMING */
+#define DEBUG_FAILOVER_TIMING
 
 /* Define this if you want DHCP failover protocol support in the DHCP
    server. */
 
-/* #define FAILOVER_PROTOCOL */
+#define FAILOVER_PROTOCOL
 
 /* Define this if you want the dhcpd.pid file to go somewhere other than
    the default (which varies from system to system, but is usually either
 /* Define this to change the logging facility used by dhcpd. */
 
 /* #define DHCPD_LOG_FACILITY LOG_DAEMON */
-
-/* Define this to support the failover protocol.   This probably won't work
-   right now. */
-
-/* #define FAILOVER_PROTOCOL */
index 00e9698b831af486218b4202edc70ab6cd179ccf..50f0c5b50e56cee7d8efeabccc5b4a9849198913 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: confpars.c,v 1.108 2000/05/03 06:19:29 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: confpars.c,v 1.109 2000/05/04 18:58:11 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -2140,6 +2140,7 @@ struct lease *parse_lease_declaration (cfile)
                      case TIMESTAMP:
                      case TSTP:
                      case TSFP:
+                     case CLTT:
                        t = parse_date (cfile);
                        switch (token) {
                              case STARTS:
@@ -2167,6 +2168,11 @@ struct lease *parse_lease_declaration (cfile)
                                lease.tsfp = t;
                                break;
                                
+                             case CLTT:
+                               seenbit = 524288;
+                               lease.cltt = t;
+                               break;
+                               
                              default: /* for gcc, we'll never get here. */
                                break;
                        }
index 57373e6a761f35e378f184c108ee918df3e2e3bd..488c670a6589876697ff391036f1076224d60428 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: db.c,v 1.48 2000/05/03 06:23:05 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: db.c,v 1.49 2000/05/04 18:58:12 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -69,7 +69,7 @@ int write_lease (lease)
        if (counting)
                ++count;
        errno = 0;
-       fprintf (db_file, "lease %s {\n", piaddr (lease -> ip_addr));
+       fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
        if (errno) {
                ++errors;
        }
@@ -77,32 +77,36 @@ int write_lease (lease)
        /* Note: the following is not a Y2K bug - it's a Y1.9K bug.   Until
           somebody invents a time machine, I think we can safely disregard
           it. */
-       if (lease -> starts != MAX_TIME) {
-               t = gmtime (&lease -> starts);
-               sprintf (tbuf, "%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);
-       } else
-               strcpy (tbuf, "never;");
-       errno = 0;
-       fprintf (db_file, "  starts %s\n", tbuf);
-       if (errno) {
-               ++errors;
+       if (lease -> starts) {
+               if (lease -> starts != MAX_TIME) {
+                       t = gmtime (&lease -> starts);
+                       sprintf (tbuf, "%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);
+               } else
+                       strcpy (tbuf, "never;");
+               errno = 0;
+               fprintf (db_file, "\n  starts %s", tbuf);
+               if (errno) {
+                       ++errors;
+               }
        }
 
-       if (lease -> ends != MAX_TIME) {
-               t = gmtime (&lease -> ends);
-               sprintf (tbuf, "%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);
-       } else
-               strcpy (tbuf, "never;");
-       errno = 0;
-       fprintf (db_file, "  ends %s", tbuf);
-       if (errno) {
-               ++errors;
+       if (lease -> ends) {
+               if (lease -> ends != MAX_TIME) {
+                       t = gmtime (&lease -> ends);
+                       sprintf (tbuf, "%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);
+               } else
+                       strcpy (tbuf, "never;");
+               errno = 0;
+               fprintf (db_file, "\n  ends %s", tbuf);
+               if (errno) {
+                       ++errors;
+               }
        }
 
        if (lease -> tstp) {
@@ -127,6 +131,17 @@ int write_lease (lease)
                        ++errors;
                }
        }
+       if (lease -> cltt) {
+               t = gmtime (&lease -> cltt);
+               errno = 0;
+               fprintf (db_file, "\n  cltt %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);
+               if (errno) {
+                       ++errors;
+               }
+       }
 
        if (lease -> flags & PEER_IS_OWNER) {
                errno = 0;
@@ -503,7 +518,7 @@ int write_failover_state (dhcp_failover_state_t *state)
        int errors = 0;
 
        errno = 0;
-       fprintf (db_file, "failover peer \"%s\" state {", state -> name);
+       fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
        if (errno)
                ++errors;
 
@@ -527,7 +542,7 @@ int write_failover_state (dhcp_failover_state_t *state)
                 t -> tm_hour, t -> tm_min, t -> tm_sec);
        if (errno)
                ++errors;
-       fprintf (db_file, "\n}\n\n");
+       fprintf (db_file, "\n}\n");
        if (errno)
                ++errors;
 
index 97e5209e58ac0ce557a91af8b76b0576286bbc48..afb982cf8a96b741f664a9e9aa13da21c9ce304e 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dhcp.c,v 1.147 2000/05/03 23:03:50 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dhcp.c,v 1.148 2000/05/04 18:58:13 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -172,6 +172,10 @@ void dhcpdiscover (packet, ms_nulltp)
                                          packet -> shared_network -> name);
                        return;
                }
+#if defined (FAILOVER_PROTOCOL)
+               if (lease -> pool && lease -> pool -> failover_peer)
+                       dhcp_failover_pool_check (lease -> pool);
+#endif
                allocatedp = 1;
        }
 
@@ -1493,7 +1497,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
 #if defined (FAILOVER_PROTOCOL)
                /* Okay, we know the lease duration.   Now check the
                   failover state, if any. */
-               if (lease -> pool -> shared_network -> failover_peer) {
+               if (lease -> pool -> failover_peer) {
                        dhcp_failover_state_t *peer =
                            lease -> pool -> failover_peer;
 
@@ -1507,11 +1511,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                                /* Here we're assuming that if we don't have
                                   to update tstp, there's already an update
                                   queued.   May want to revisit this.  */
-                               if (cur_time + lease_time < lease -> tstp) {
-                                       lease -> tstp = cur_time + lease_time;
-                                       if (offer == DHCPACK)
-                                               update_partner (lease);
-                               }
+                               if (cur_time + lease_time > lease -> tstp)
+                                       lt.tstp = cur_time + lease_time;
+
                                /* Now choose a lease time that is either
                                   MCLT, for a lease that's never before been
                                   assigned, or TSFP + MCLT for a lease that
@@ -1526,6 +1528,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                                        lease_time = (lease -> tsfp  - cur_time
                                                      + peer -> mclt);
                        }
+                       lt.cltt = cur_time;
                }
 #endif /* FAILOVER_PROTOCOL */
 
@@ -1608,7 +1611,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
        if (ms_nulltp)
                lease -> flags |= MS_NULL_TERMINATION;
        else
-               lease -> flags &= MS_NULL_TERMINATION;
+               lease -> flags &= ~MS_NULL_TERMINATION;
 
        /* If there are statements to execute when the lease is
           committed, execute them. */
@@ -1646,7 +1649,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                   and we can't write the lease, don't ACK it (or BOOTREPLY
                   it) either. */
 
-               if (!(supersede_lease (lease, &lt, !offer || offer == DHCPACK)
+               if (!(supersede_lease (lease, &lt, !offer || offer == DHCPACK,
+                                      offer == DHCPACK)
                      || (offer && offer != DHCPACK))) {
                        log_info ("%s: database update failed", msg);
                        free_lease_state (state, MDL);
index 66bda194123089e43367533b071073cba427d54b..ddee88276b024c875cd379b43a525fe1f89a8d9f 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: failover.c,v 1.12 2000/05/03 23:07:54 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: failover.c,v 1.13 2000/05/04 18:58:15 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -1147,9 +1147,15 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
                    omapi_disconnect (link -> outer, 1);
                    return ISC_R_SUCCESS;
                } else if (link -> imsg -> type == FTM_BNDUPD) {
-                       dhcp_failover_process_bindupdate (state, link -> imsg);
+                       dhcp_failover_process_bind_update (state,
+                                                          link -> imsg);
                } else if (link -> imsg -> type == FTM_BNDACK) {
-                       dhcp_failover_process_bindack (state, link -> imsg);
+                       dhcp_failover_process_bind_ack (state, link -> imsg);
+               } else if (link -> imsg -> type == FTM_POOLREQ) {
+                       dhcp_failover_pool_rebalance (state);
+               } else if (link -> imsg -> type == FTM_POOLRESP) {
+                       log_info ("pool response: %d leases",
+                                 link -> imsg -> addresses_transferred);
                }
        }
 
@@ -1336,6 +1342,7 @@ isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *state,
            state -> update_queue_head) {
                dhcp_failover_send_updates (state);
        }
+       dhcp_failover_state_pool_check (state);
        break;
       default:
        break;
@@ -1344,11 +1351,110 @@ isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *state,
     return ISC_R_SUCCESS;
 }
 
+int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state)
+{
+       int lts;
+       int leases_queued = 0;
+       struct lease *lp;
+       struct shared_network *s;
+       struct pool *p;
+
+       if (state -> my_state != normal || state -> i_am == secondary)
+               return 0;
+
+       for (s = shared_networks; s; s = s -> next) {
+           for (p = s -> pools; p; p = p -> next) {
+               if (p -> failover_peer != state)
+                   continue;
+               log_info ("pool %lx total %d  local free %d  peer free %d",
+                         (unsigned long)p, p -> lease_count,
+                         p -> local_leases, p -> peer_leases);
+
+               lts = ((p -> local_leases +
+                       p -> peer_leases) / 2) - p -> peer_leases;
+               if (lts > 1) {
+                   struct lease lt;
+
+                   leases_queued += lts;
+                   for (lp = p -> last_lease; lp && lts;
+                        lp = lp -> prev) {
+                       if (!(lp -> flags & PEER_IS_OWNER)) {
+                               lp -> flags |= PEER_IS_OWNER;
+                               lp -> tstp = cur_time;
+                           if (!write_lease (lp) ||
+                               !commit_leases () ||
+                               !dhcp_failover_queue_update (lp)) {
+                                   log_info ("%s lease %s on giveaway",
+                                             "unable to commit",
+                                             piaddr (lp -> ip_addr));
+                           }
+                       }
+                   }
+               }
+
+               if (lts > 1) {
+                       log_info ("lease imbalance - lts = %d", lts);
+                       leases_queued -= lts;
+               }
+           }
+       }
+       dhcp_failover_send_poolresp (state, leases_queued);
+       return leases_queued;
+}
+
+int dhcp_failover_pool_check (struct pool *pool)
+{
+       int lts;
+       struct lease *lp;
+
+       if (!pool -> failover_peer ||
+           pool -> failover_peer -> i_am == primary ||
+           pool -> failover_peer -> my_state != normal)
+               return 0;
+
+       log_info ("pool %lx total %d  local free %d  peer free %d",
+                 (unsigned long)pool, pool -> lease_count,
+                 pool -> local_leases, pool -> peer_leases);
+
+       lts = ((pool -> local_leases +
+               pool -> peer_leases) / 2) - pool -> local_leases;
+       if (lts > 1) {
+               /* XXX What about multiple pools? */
+               dhcp_failover_send_poolreq (pool -> failover_peer);
+               return 1;
+       }
+       return 0;
+}
+
+int dhcp_failover_state_pool_check (dhcp_failover_state_t *state)
+{
+       struct lease *lp;
+       struct shared_network *s;
+       struct pool *p;
+
+       for (s = shared_networks; s; s = s -> next) {
+               for (p = s -> pools; p; p = p -> next) {
+                       if (p -> failover_peer != state)
+                               continue;
+                       /* Only need to request rebalance on one pool. */
+                       if (dhcp_failover_pool_check (p))
+                               return 1;
+               }
+       }
+       return 0;
+}
+
 isc_result_t dhcp_failover_send_updates (dhcp_failover_state_t *state)
 {
        struct lease *lp = (struct lease *)0;
        isc_result_t status;
 
+       /* Can't update peer if we're not talking to it! */
+       if (state -> my_state != normal &&
+           state -> my_state != recover &&
+           state -> my_state != potential_conflict)
+               return ISC_R_SUCCESS;
+
        while (state -> max_flying_updates > state -> cur_unacked_updates &&
               state -> update_queue_head) {
                /* Grab the head of the update queue. */
@@ -1359,7 +1465,7 @@ isc_result_t dhcp_failover_send_updates (dhcp_failover_state_t *state)
                /* Send the update to the peer. */
                status = dhcp_failover_send_bind_update (state, lp);
                if (status != ISC_R_SUCCESS) {
-                       omapi_object_dereference ((omapi_object_t **)lp, MDL);
+                       omapi_object_dereference ((omapi_object_t **)&lp, MDL);
                        return status;
                }
                lp -> flags &= ~ON_UPDATE_QUEUE;
@@ -1374,7 +1480,7 @@ isc_result_t dhcp_failover_send_updates (dhcp_failover_state_t *state)
                                                (omapi_object_t *)
                                                lp -> next_pending, MDL);
                        omapi_object_dereference ((omapi_object_t **)
-                                                 lp -> next_pending, MDL);
+                                                 &lp -> next_pending, MDL);
                } else {
                        omapi_object_dereference ((omapi_object_t **)
                                                  &state -> update_queue_tail,
@@ -1398,7 +1504,7 @@ isc_result_t dhcp_failover_send_updates (dhcp_failover_state_t *state)
                                        &state -> ack_queue_tail,
                                        (omapi_object_t *)lp, MDL);
                lp -> flags |= ON_ACK_QUEUE;
-               omapi_object_dereference ((omapi_object_t **)lp, MDL);
+               omapi_object_dereference ((omapi_object_t **)&lp, MDL);
 
                /* Count the object as an unacked update. */
                state -> cur_unacked_updates++;
@@ -1478,15 +1584,15 @@ void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *state,
                                          &lp -> next_pending, MDL);
                if (lease -> next_pending)
                        omapi_object_reference ((omapi_object_t **)
-                                               lp -> next_pending,
+                                               &lp -> next_pending,
                                                (omapi_object_t *)
                                                lease -> next_pending, MDL);
                else {
                        omapi_object_dereference ((omapi_object_t **)
-                                                 state -> ack_queue_tail,
+                                                 &state -> ack_queue_tail,
                                                  MDL);
                        omapi_object_reference ((omapi_object_t **)
-                                               state -> ack_queue_tail,
+                                               &state -> ack_queue_tail,
                                                (omapi_object_t *)lp, MDL);
                }
        }
@@ -2080,6 +2186,28 @@ const char *dhcp_failover_state_name_print (enum failover_state state)
        }
 }
 
+failover_option_t *dhcp_failover_option_printf (unsigned code,
+                                               char *obuf,
+                                               unsigned *obufix,
+                                               unsigned obufmax,
+                                               const char *fmt, ...) {
+       va_list va;
+       char tbuf [256];
+
+       va_start (va, fmt);
+#if defined (HAVE_SNPRINTF)
+       /* Presumably if we have snprintf, we also have
+          vsnprintf. */
+       vsnprintf (tbuf, sizeof tbuf, fmt, va);
+#else
+       vsprintf (tbuf, fmt, va);
+#endif
+       va_end (va);
+
+       return dhcp_failover_make_option (code, obuf, obufix, obufmax,
+                                         strlen (tbuf), tbuf);
+}
+
 failover_option_t *dhcp_failover_make_option (unsigned code,
                                              char *obuf, unsigned *obufix,
                                              unsigned obufmax, ...)
@@ -2092,10 +2220,11 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
        u_int8_t *iaddr;
        unsigned ilen;
        u_int8_t *bval;
-       char *fmt;
+       char *txt;
 #if defined (DEBUG_FAILOVER_MESSAGES)
        char tbuf [256];
 #endif
+
        /* Note that the failover_option structure is used differently on
           input than on output - on input, count is an element count, and
           on output it's the number of bytes total in the option, including
@@ -2133,21 +2262,14 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
 
                      case FT_TEXT_OR_BYTES:
                      case FT_TEXT:
-                       fmt = va_arg (va, char *);
-#if defined (HAVE_SNPRINTF)
-                       /* Presumably if we have snprintf, we also have
-                           vsnprintf. */
-                       vsnprintf (tbuf, sizeof tbuf, fmt, va);
-#else
-                       vsprintf (tbuf, fmt, va);
-#endif
-                       size = strlen (tbuf);
-                       count = size;
+                       txt = va_arg (va, char *);
+                       size = count;
                        break;
 
                      case FT_IPADDR:
                        ilen = va_arg (va, unsigned);
                        size = count * ilen;
+                       break;
 
                      case FT_UINT32:
                        size = count * 4;
@@ -2248,11 +2370,10 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
              case FT_TEXT_OR_BYTES:
              case FT_TEXT:
 #if defined (DEBUG_FAILOVER_MESSAGES)
-               failover_print (obuf, obufix, obufmax, " \"");
+               sprintf (tbuf, "\"%s\"", txt);
                failover_print (obuf, obufix, obufmax, tbuf);
-               failover_print (obuf, obufix, obufmax, "\"");
 #endif
-               memcpy (&option.data [4], tbuf, count);
+               memcpy (&option.data [4], txt, count);
                break;
 
              case FT_DDNS:
@@ -2427,8 +2548,8 @@ isc_result_t dhcp_failover_send_connect (omapi_object_t *l)
                                              state -> max_flying_updates),
                   dhcp_failover_make_option (FTO_RECEIVE_TIMER, FMA,
                                              state -> max_response_delay),
-                  dhcp_failover_make_option (FTO_VENDOR_CLASS, FMA,
-                                             "isc-%s", DHCP_VERSION),
+                  dhcp_failover_option_printf (FTO_VENDOR_CLASS, FMA,
+                                               "isc-%s", DHCP_VERSION),
                   dhcp_failover_make_option (FTO_PROTOCOL_VERSION, FMA,
                                              DHCP_FAILOVER_VERSION),
                   dhcp_failover_make_option (FTO_TLS_REQUEST, FMA,
@@ -2481,8 +2602,8 @@ isc_result_t dhcp_failover_send_connectack (omapi_object_t *l, int reason)
                                              state -> max_flying_updates),
                   dhcp_failover_make_option (FTO_RECEIVE_TIMER, FMA,
                                              state -> max_response_delay),
-                  dhcp_failover_make_option (FTO_VENDOR_CLASS, FMA,
-                                             "isc-%s", DHCP_VERSION),
+                  dhcp_failover_option_printf (FTO_VENDOR_CLASS, FMA,
+                                               "isc-%s", DHCP_VERSION),
                   dhcp_failover_make_option (FTO_PROTOCOL_VERSION, FMA,
                                              DHCP_FAILOVER_VERSION),
                   dhcp_failover_make_option (FTO_TLS_REQUEST, FMA,
@@ -2528,18 +2649,18 @@ isc_result_t dhcp_failover_send_disconnect (omapi_object_t *l,
        if (!l -> outer || l -> outer -> type != omapi_type_connection)
                return ISC_R_INVALIDARG;
 
+       if (!message && reason)
+               message = dhcp_failover_reject_reason_print (reason);
+
        status = (dhcp_failover_put_message
                  (link, l -> outer,
                   FTM_DISCONNECT,
                   dhcp_failover_make_option (FTO_REJECT_REASON,
                                              FMA, reason),
                   (message
-                   ? dhcp_failover_make_option (FTO_MESSAGE, FMA, message)
-                   : (reason
-                      ? (dhcp_failover_make_option
-                         (FTO_MESSAGE,
-                          FMA, dhcp_failover_reject_reason_print (reason)))
-                      : &skip_failover_option)),
+                   ? dhcp_failover_make_option (FTO_MESSAGE, FMA,
+                                                strlen (message), message)
+                   : &skip_failover_option),
                   (failover_option_t *)0));
 
 #if defined (DEBUG_FAILOVER_MESSAGES)
@@ -2563,6 +2684,7 @@ isc_result_t dhcp_failover_send_bind_update (dhcp_failover_state_t *state,
 #if defined (DEBUG_FAILOVER_MESSAGES)  
        char obuf [64];
        unsigned obufix = 0;
+       int binding_status;
        
 # define FMA obuf, &obufix, sizeof obuf
        failover_print (FMA, "(bndupd");
@@ -2578,6 +2700,27 @@ isc_result_t dhcp_failover_send_bind_update (dhcp_failover_state_t *state,
        if (!link -> outer || link -> outer -> type != omapi_type_connection)
                return ISC_R_INVALIDARG;
 
+       /* Kludge up the binding status. */
+       if (lease -> flags & ABANDONED)
+               binding_status = FTS_ABANDONED;
+       else if (lease -> tsfp <= cur_time) {
+               if (lease -> flags & PEER_IS_OWNER) {
+                       if (state -> i_am == primary)
+                               binding_status = FTS_BACKUP;
+                       else
+                               binding_status = FTS_FREE;
+               } else {
+                       if (state -> i_am == primary)
+                               binding_status = FTS_FREE;
+                       else
+                               binding_status = FTS_BACKUP;
+               }
+       } else if (lease -> ends <= cur_time) {
+               binding_status = FTS_EXPIRED;
+       } else
+               binding_status = FTS_ACTIVE;
+
+       /* Send the update. */
        status = (dhcp_failover_put_message
                  (link, link -> outer,
                   FTM_BNDUPD,
@@ -2585,15 +2728,17 @@ isc_result_t dhcp_failover_send_bind_update (dhcp_failover_state_t *state,
                                              lease -> ip_addr.len,
                                              lease -> ip_addr.iabuf),
                   dhcp_failover_make_option (FTO_BINDING_STATUS, FMA,
-                                             0 /* ??? */),
+                                             binding_status),
                   lease -> uid_len
                   ? dhcp_failover_make_option (FTO_CLIENT_IDENTIFIER, FMA,
                                                lease -> uid_len,
                                                lease -> uid)
                   : &skip_failover_option,
-                  dhcp_failover_make_option (FTO_CHADDR, FMA,
-                                             lease -> hardware_addr.hlen,
-                                             lease -> hardware_addr.hbuf),
+                  lease -> hardware_addr.hlen
+                  ? dhcp_failover_make_option (FTO_CHADDR, FMA,
+                                               lease -> hardware_addr.hlen,
+                                               lease -> hardware_addr.hbuf)
+                  : &skip_failover_option,
                   dhcp_failover_make_option (FTO_LEASE_EXPIRY, FMA,
                                              lease -> ends),
                   dhcp_failover_make_option (FTO_POTENTIAL_EXPIRY, FMA,
@@ -2618,15 +2763,314 @@ isc_result_t dhcp_failover_send_bind_update (dhcp_failover_state_t *state,
        return status;
 }
 
-isc_result_t dhcp_failover_process_bindupdate (dhcp_failover_state_t *state,
-                                              failover_message_t *msg) {
-       log_info ("failover: bind update.");
+/* Send a Bind ACK message. */
+
+isc_result_t dhcp_failover_send_bind_ack (dhcp_failover_state_t *state,
+                                         struct lease *lease,
+                                         failover_message_t *msg,
+                                         int reason, const char *message)
+{
+       dhcp_failover_link_t *link;
+       isc_result_t status;
+#if defined (DEBUG_FAILOVER_MESSAGES)  
+       char obuf [64];
+       unsigned obufix = 0;
+       int binding_status;
+       
+# define FMA obuf, &obufix, sizeof obuf
+       failover_print (FMA, "(bndack");
+#else
+# define FMA (unsigned char *)0, (unsigned *)0, 0
+#endif
+
+       if (!state -> link_to_peer ||
+           state -> link_to_peer -> type != dhcp_type_failover_link)
+               return ISC_R_INVALIDARG;
+       link = (dhcp_failover_link_t *)state -> link_to_peer;
+
+       if (!link -> outer || link -> outer -> type != omapi_type_connection)
+               return ISC_R_INVALIDARG;
+
+       /* Kludge up the binding status. */
+       if (lease -> flags & ABANDONED)
+               binding_status = FTS_ABANDONED;
+       else if (lease -> tsfp <= cur_time) {
+               if (lease -> flags & PEER_IS_OWNER) {
+                       if (state -> i_am == primary)
+                               binding_status = FTS_BACKUP;
+                       else
+                               binding_status = FTS_FREE;
+               } else {
+                       if (state -> i_am == primary)
+                               binding_status = FTS_FREE;
+                       else
+                               binding_status = FTS_BACKUP;
+               }
+       } else if (lease -> ends <= cur_time) {
+               binding_status = FTS_EXPIRED;
+       } else
+               binding_status = FTS_ACTIVE;
+
+       if (!message && reason)
+               message = dhcp_failover_reject_reason_print (reason);
+
+       /* Send the update. */
+       status = (dhcp_failover_put_message
+                 (link, link -> outer,
+                  FTM_BNDACK,
+                  dhcp_failover_make_option (FTO_ASSIGNED_IP_ADDRESS, FMA,
+                                             lease -> ip_addr.len,
+                                             lease -> ip_addr.iabuf),
+                  dhcp_failover_make_option (FTO_BINDING_STATUS, FMA,
+                                             binding_status),
+                  lease -> uid_len
+                  ? dhcp_failover_make_option (FTO_CLIENT_IDENTIFIER, FMA,
+                                               lease -> uid_len,
+                                               lease -> uid)
+                  : &skip_failover_option,
+                  lease -> hardware_addr.hlen
+                  ? dhcp_failover_make_option (FTO_CHADDR, FMA,
+                                               lease -> hardware_addr.hlen,
+                                               lease -> hardware_addr.hbuf)
+                  : &skip_failover_option,
+                  dhcp_failover_make_option (FTO_LEASE_EXPIRY, FMA,
+                                             msg -> expiry),
+                  dhcp_failover_make_option (FTO_POTENTIAL_EXPIRY, FMA,
+                                             msg -> potential_expiry),
+                  dhcp_failover_make_option (FTO_STOS, FMA,
+                                             msg -> stos),
+                  dhcp_failover_make_option (FTO_CLTT, FMA,
+                                             msg -> client_ltt),
+                  reason
+                  ? dhcp_failover_make_option (FTO_REJECT_REASON,
+                                               FMA, reason)
+                  : &skip_failover_option,
+                  (message
+                   ? dhcp_failover_make_option (FTO_MESSAGE, FMA,
+                                                strlen (message), message)
+                   : &skip_failover_option),
+                  &skip_failover_option,       /* XXX DDNS */
+                  &skip_failover_option,       /* XXX request options */
+                  &skip_failover_option,       /* XXX reply options */
+                  (failover_option_t *)0));
+
+#if defined (DEBUG_FAILOVER_MESSAGES)
+       if (status != ISC_R_SUCCESS)
+               failover_print (FMA, " (failed)");
+       failover_print (FMA, ")");
+       if (obufix) {
+               log_debug ("%s", obuf);
+       }
+#endif
+       return status;
+}
+
+isc_result_t dhcp_failover_send_poolreq (dhcp_failover_state_t *state)
+{
+       dhcp_failover_link_t *link;
+       isc_result_t status;
+#if defined (DEBUG_FAILOVER_MESSAGES)  
+       char obuf [64];
+       unsigned obufix = 0;
+       
+# define FMA obuf, &obufix, sizeof obuf
+       failover_print (FMA, "(poolreq");
+#else
+# define FMA (unsigned char *)0, (unsigned *)0, 0
+#endif
+
+       if (!state -> link_to_peer ||
+           state -> link_to_peer -> type != dhcp_type_failover_link)
+               return ISC_R_INVALIDARG;
+       link = (dhcp_failover_link_t *)state -> link_to_peer;
+
+       if (!link -> outer || link -> outer -> type != omapi_type_connection)
+               return ISC_R_INVALIDARG;
+
+       status = (dhcp_failover_put_message
+                 (link, link -> outer,
+                  FTM_POOLREQ,
+                  (failover_option_t *)0));
+
+#if defined (DEBUG_FAILOVER_MESSAGES)
+       if (status != ISC_R_SUCCESS)
+               failover_print (FMA, " (failed)");
+       failover_print (FMA, ")");
+       if (obufix) {
+               log_debug ("%s", obuf);
+       }
+#endif
+       return status;
+}
+
+isc_result_t dhcp_failover_send_poolresp (dhcp_failover_state_t *state,
+                                         int leases)
+{
+       dhcp_failover_link_t *link;
+       isc_result_t status;
+#if defined (DEBUG_FAILOVER_MESSAGES)  
+       char obuf [64];
+       unsigned obufix = 0;
+       
+# define FMA obuf, &obufix, sizeof obuf
+       failover_print (FMA, "(poolreq");
+#else
+# define FMA (unsigned char *)0, (unsigned *)0, 0
+#endif
+
+       if (!state -> link_to_peer ||
+           state -> link_to_peer -> type != dhcp_type_failover_link)
+               return ISC_R_INVALIDARG;
+       link = (dhcp_failover_link_t *)state -> link_to_peer;
+
+       if (!link -> outer || link -> outer -> type != omapi_type_connection)
+               return ISC_R_INVALIDARG;
+
+       status = (dhcp_failover_put_message
+                 (link, link -> outer,
+                  FTM_POOLREQ,
+                  dhcp_failover_make_option (FTO_ADDRESSES_TRANSFERRED, FMA,
+                                             leases),
+                  (failover_option_t *)0));
+
+#if defined (DEBUG_FAILOVER_MESSAGES)
+       if (status != ISC_R_SUCCESS)
+               failover_print (FMA, " (failed)");
+       failover_print (FMA, ")");
+       if (obufix) {
+               log_debug ("%s", obuf);
+       }
+#endif
+       return status;
+}
+
+isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
+                                              failover_message_t *msg)
+{
+       struct lease lt, *lease;
+       struct iaddr ia;
+
+       ia.len = sizeof msg -> assigned_addr;
+       memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
+
+       lease = find_lease_by_ip_addr (ia);
+       if (!lease) {
+               log_info ("bind update on %s from %s: no such lease.",
+                         piaddr (ia), state -> name);
+               return ISC_R_SUCCESS;
+       }
+
+       /* XXX check for conflicts. */
+
+       /* Install the new info. */
+       lt = *lease;
+       lt.on_expiry = 0;
+       lt.on_release = 0;
+       lt.on_commit = 0;
+
+       if (msg -> options_present & FTB_CHADDR) {
+               if (msg -> chaddr.count > sizeof lt.hardware_addr.hbuf) {
+                       log_info ("bind update on %s from %s: chaddr too long",
+                                 piaddr (ia), state -> name);
+                       return ISC_R_SUCCESS;
+               }
+               lt.hardware_addr.hlen = msg -> chaddr.count;
+               memcpy (lt.hardware_addr.hbuf, msg -> chaddr.data,
+                       msg -> chaddr.count);
+       }               
+
+       if (msg -> options_present & FTB_CLIENT_IDENTIFIER) {
+               lt.uid_len = msg -> client_identifier.count;
+               if (lt.uid_len > sizeof lt.uid_buf) {
+                       lt.uid_max = lt.uid_len;
+                       lt.uid = dmalloc (lt.uid_len, MDL);
+                       if (!lt.uid)
+                               return ISC_R_SUCCESS;
+               } else {
+                       lt.uid_max = sizeof lt.uid_buf;
+                       lt.uid = lt.uid_buf;
+               }
+               memcpy (lt.uid, msg -> client_identifier.data, lt.uid_len);
+       }
+               
+       /* XXX Times may need to be adjusted based on clock skew! */
+       if (msg -> options_present & FTB_STOS) {
+               lt.starts = msg -> stos;
+       }
+       if (msg -> options_present & FTB_LEASE_EXPIRY) {
+               lt.ends = msg -> expiry;
+       }
+       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_BINDING_STATUS) {
+               if (state -> i_am == primary) {
+                       if (msg -> binding_status == FTS_BACKUP)
+                               lease -> flags |= PEER_IS_OWNER;
+                       else if (msg -> binding_status == FTS_FREE)
+                               lease -> flags &= ~PEER_IS_OWNER;
+               } else {
+                       if (msg -> binding_status == FTS_BACKUP)
+                               lease -> flags &= PEER_IS_OWNER;
+                       else if (msg -> binding_status == FTS_FREE)
+                               lease -> flags |= ~PEER_IS_OWNER;
+               }
+       }
+
+       /* Try to install the new information. */
+       if (!supersede_lease (lease, &lt, 1, 0)) {
+               dhcp_failover_send_bind_ack (state, lease, msg,
+                                            FTR_MISC_REJECT,
+                                            "database update failed.");
+       } else
+               dhcp_failover_send_bind_ack (state, lease, msg, 0, 0);
+
        return ISC_R_SUCCESS;
 }
 
-isc_result_t dhcp_failover_process_bindack (dhcp_failover_state_t *state,
-                                           failover_message_t *msg) {
-       log_info ("failover: bind ack.");
+isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *state,
+                                            failover_message_t *msg)
+{
+       struct lease lt, *lease;
+       struct iaddr ia;
+
+       ia.len = sizeof msg -> assigned_addr;
+       memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
+
+       lease = find_lease_by_ip_addr (ia);
+       if (!lease) {
+               log_info ("bind update on %s from %s: no such lease.",
+                         piaddr (ia), state -> name);
+               return ISC_R_SUCCESS;
+       }
+
+       /* XXX check for conflicts. */
+
+       /* Install the new info. */
+       lt = *lease;
+       lt.on_expiry = 0;
+       lt.on_release = 0;
+       lt.on_commit = 0;
+
+       /* XXX Times may need to be adjusted based on clock skew! */
+       if (msg -> options_present & FTB_POTENTIAL_EXPIRY) {
+               lt.tsfp = msg -> potential_expiry;
+       }
+
+       /* Try to install the new information. */
+       supersede_lease (lease, &lt, 1, 0);
+
+       state -> cur_unacked_updates--;
+       dhcp_failover_ack_queue_remove (state, lease);
+
+       /* If there are updates pending, we've created space to send at
+          least one. */
+       dhcp_failover_send_updates (state);
+
        return ISC_R_SUCCESS;
 }
 
@@ -2655,10 +3099,6 @@ void failover_print (char *obuf,
 }      
 #endif /* defined (DEBUG_FAILOVER_MESSAGES) */
 
-void update_partner (struct lease *lease)
-{
-}
-
 /* Taken from draft-ietf-dhc-loadb-01.txt: */
 /* A "mixing table" of 256 distinct values, in pseudo-random order. */
 unsigned char loadb_mx_tbl[256] = {
index 0e10fc165c705682c27664cc959b409b0a6155a1..1803e38d7fdbde27f18b3510357077fb6d1052ee 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: mdb.c,v 1.30 2000/05/03 06:34:13 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: mdb.c,v 1.31 2000/05/04 18:58:16 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 
-static struct subnet *subnets;
-static struct shared_network *shared_networks;
+struct subnet *subnets;
+struct shared_network *shared_networks;
 struct hash_table *host_hw_addr_hash;
 struct hash_table *host_uid_hash;
 struct hash_table *lease_uid_hash;
@@ -622,6 +622,7 @@ void new_address_range (low, high, subnet, pool)
                          address_range [i].ip_addr.iabuf,
                          address_range [i].ip_addr.len,
                          (unsigned char *)&address_range [i]);
+               address_range [i].refcnt = 1; /* XXX */
        }
 
        /* Find out if any dangling leases are in range... */
@@ -647,7 +648,7 @@ void new_address_range (low, high, subnet, pool)
                        address_range [lhost - i].hostname = lp -> hostname;
                        address_range [lhost - i].client_hostname =
                                lp -> client_hostname;
-                       supersede_lease (&address_range [lhost - i], lp, 0);
+                       supersede_lease (&address_range [lhost - i], lp, 0, 0);
                        free_lease (lp, MDL);
                } else
                        plp = lp;
@@ -808,7 +809,7 @@ void enter_lease (lease)
                /* Record the hostname information in the lease. */
                comp -> hostname = lease -> hostname;
                comp -> client_hostname = lease -> client_hostname;
-               supersede_lease (comp, lease, 0);
+               supersede_lease (comp, lease, 0, 0);
        }
 }
 
@@ -817,9 +818,10 @@ void enter_lease (lease)
    list of leases by expiry time so that we can always find the oldest
    lease. */
 
-int supersede_lease (comp, lease, commit)
+int supersede_lease (comp, lease, commit, propogate)
        struct lease *comp, *lease;
        int commit;
+       int propogate;
 {
        int enter_uid = 0;
        int enter_hwaddr = 0;
@@ -1048,6 +1050,22 @@ int supersede_lease (comp, lease, commit)
                }
        }
        comp -> pool -> insertion_point = comp;
+#if defined (FAILOVER_PROTOCOL)
+       if (comp -> ends <= cur_time && lease -> ends > cur_time) {
+               if (lease -> flags & PEER_IS_OWNER)
+                       comp -> pool -> peer_leases--;
+               else
+                       comp -> pool -> local_leases--;
+       } else if (comp -> ends > cur_time && lease -> ends <= cur_time) {
+               if (lease -> flags & PEER_IS_OWNER)
+                       comp -> pool -> peer_leases++;
+               else
+                       comp -> pool -> local_leases++;
+       }               
+       comp -> cltt = lease -> cltt;
+       comp -> tstp = lease -> tstp;
+       comp -> tsfp = lease -> tsfp;
+#endif /* FAILOVER_PROTOCOL */
        comp -> ends = lease -> ends;
 
        /* If there's an expiry event on this lease, process it or
@@ -1103,7 +1121,7 @@ int supersede_lease (comp, lease, commit)
                                     struct lease *foo;
                                     struct lease *install = comp;
                                     for (foo = comp;
-                                         foo -> ends == comp -> ends;
+                                        foo && foo -> ends == comp -> ends;
                                          foo = foo -> next) {
 #if !defined (FAILOVER_PROTOCOL)
                                             if (foo -> on_expiry)
@@ -1122,7 +1140,7 @@ int supersede_lease (comp, lease, commit)
           nonzero if we did. */
        return commit && write_lease (comp) && commit_leases ()
 #if defined (FAILOVER_PROTOCOL)
-               && dhcp_failover_queue_update (comp)
+               && (!propogate || dhcp_failover_queue_update (comp))
 #endif
                ;
 }
@@ -1166,7 +1184,7 @@ void release_lease (lease, packet)
 
                lt.ends = cur_time;
                lt.billing_class = (struct class *)0;
-               supersede_lease (lease, &lt, 1);
+               supersede_lease (lease, &lt, 1, 1);
        }
 }
 
@@ -1198,7 +1216,7 @@ void abandon_lease (lease, message)
        lt.uid = (unsigned char *)0;
        lt.uid_len = 0;
        lt.billing_class = (struct class *)0;
-       supersede_lease (lease, &lt, 1);
+       supersede_lease (lease, &lt, 1, 1);
 }
 
 /* Abandon the specified lease (set its timeout to infinity and its
@@ -1225,7 +1243,7 @@ void dissociate_lease (lease)
        lt.uid = (unsigned char *)0;
        lt.uid_len = 0;
        lt.billing_class = (struct class *)0;
-       supersede_lease (lease, &lt, 1);
+       supersede_lease (lease, &lt, 1, 1);
 }
 
 /* Timer called when a lease in a particular pool expires. */
@@ -1260,10 +1278,6 @@ void pool_timer (vpool)
                if (lease -> on_release)
                        executable_statement_dereference (&lease -> on_release,
                                                          MDL);
-#if defined (FAILOVER_PROTOCOL)
-               lease -> tstp = 0;
-               update_partner (lease);
-#endif
                
                /* There are two problems with writing the lease out here.
 
@@ -1290,9 +1304,9 @@ void pool_timer (vpool)
                }
 #if defined (FAILOVER_PROTOCOL)
                if (lease -> flags & PEER_IS_OWNER)
-                       pool -> peer_leases--;
+                       pool -> peer_leases++;
                else
-                       pool -> local_leases--;
+                       pool -> local_leases++;
 #endif
        }
        pool -> next_expiry = lease;
@@ -1552,7 +1566,10 @@ void write_leases ()
                log_fatal ("Can't commit leases to new database: %m");
 }
 
-/* Write all interesting leases to permanent storage. */
+/* Run expiry events on every pool.   This is called on startup so that
+   any expiry events that occurred after the server stopped and before it
+   was restarted can be run.   At the same time, if failover support is
+   compiled in, we compute the balance of leases for the pool. */
 
 void expire_all_pools ()
 {
@@ -1560,12 +1577,35 @@ void expire_all_pools ()
        struct pool *p;
        struct hash_bucket *hb;
        int i;
+       struct lease *l;
 
        /* Loop through each pool in each shared network and call the
           expiry routine on the pool. */
-       for (s = shared_networks; s; s = s -> next)
-               for (p = s -> pools; p; p = p -> next)
-                       pool_timer (p);
+       for (s = shared_networks; s; s = s -> next) {
+           for (p = s -> pools; p; p = p -> next) {
+               pool_timer (p);
+
+#if defined (FAILOVER_PROTOCOL)
+               p -> lease_count = 0;
+               p -> local_leases = 0;
+               p -> peer_leases = 0;
+               
+               for (l = p -> leases; l; l = l -> next) {
+                       p -> lease_count++;
+                       if (l -> ends <= cur_time) {
+                               if (l -> flags & PEER_IS_OWNER)
+                                       p -> peer_leases++;
+                               else
+                                       p -> local_leases++;
+                       }
+                       if (p -> failover_peer &&
+                           l -> tstp > l -> tsfp &&
+                           !(l -> flags & ON_UPDATE_QUEUE))
+                               dhcp_failover_queue_update (l);
+               }
+#endif
+           }
+       }
 }
 
 void dump_subnets ()