From 8c8e27c53ea5a5e44e5d2dc6b9cc330ffaf8969e Mon Sep 17 00:00:00 2001 From: Ted Lemon Date: Thu, 4 May 2000 18:58:16 +0000 Subject: [PATCH] Implement pool request and response so that secondary can operate. --- client/dhclient.cat8 | 58 ++--- common/conflex.c | 4 +- common/dhcp-options.cat5 | 52 ++-- includes/dhcpd.h | 27 +- includes/dhctoken.h | 3 +- includes/failover.h | 9 + includes/site.h | 20 +- server/confpars.c | 8 +- server/db.c | 71 ++++-- server/dhcp.c | 22 +- server/failover.c | 534 +++++++++++++++++++++++++++++++++++---- server/mdb.c | 82 ++++-- 12 files changed, 709 insertions(+), 181 deletions(-) diff --git a/client/dhclient.cat8 b/client/dhclient.cat8 index a58bbb603..eb274700c 100644 --- a/client/dhclient.cat8 +++ b/client/dhclient.cat8 @@ -10,7 +10,7 @@ NNAAMMEE SSYYNNOOPPSSIISS ddhhcclliieenntt [ --pp _p_o_r_t ] [ --dd ] [ --DD ] [ --qq ] [ --cc ] [ --llff _l_e_a_s_e_-_f_i_l_e ] [ --ppff _p_i_d_-_f_i_l_e ] [ --ccff _c_o_n_f_i_g_-_f_i_l_e ] [ --ss - server ] [ _i_f_0 [ _._._._i_f_N ] ] + server ] [ --ww ] [ _i_f_0 [ _._._._i_f_N ] ] DDEESSCCRRIIPPTTIIOONN The Internet Software Consortium DHCP Client, dhclient, @@ -160,8 +160,19 @@ dhclient(8) dhclient(8) //vvaarr//ddbb or //vvaarr//rruunn 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 --ww flag can be used to cause + the client not to exit when it doesn't find any such + interfaces. The ddhhccppccccpp ((88)) 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. + CCOONNFFIIGGUURRAATTIIOONN - The syntax of the dhclient.conf(8) file is discussed + The syntax of the dhclient.conf(8) file is discussed seperately. FFIILLEESS @@ -173,23 +184,12 @@ SSEEEE AALLSSOO dhclient.leases(5) AAUUTTHHOORR - ddhhcclliieenntt((88)) has been written for the Internet Software - Consortium by Ted Lemon in cooperation - with Vixie Enterprises. To learn more about the Internet + ddhhcclliieenntt((88)) has been written for the Internet Software + Consortium by Ted Lemon in cooperation + with Vixie Enterprises. To learn more about the Internet Software Consortium, see hhttttpp::////wwwwww..vviixx..ccoomm//iisscc.. To learn more about Vixie Enterprises, see hhttttpp::////wwwwww..vviixx..ccoomm.. - 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 @@ AAUUTTHHOORR 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. diff --git a/common/conflex.c b/common/conflex.c index 0d7bc89cf..1074a37a4 100644 --- a/common/conflex.c +++ b/common/conflex.c @@ -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")) diff --git a/common/dhcp-options.cat5 b/common/dhcp-options.cat5 index 3275f2130..c87cb22e9 100644 --- a/common/dhcp-options.cat5 +++ b/common/dhcp-options.cat5 @@ -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. ooppttiioonn aarrpp--ccaacchhee--ttiimmeeoouutt _u_i_n_t_3_2;; @@ -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. ooppttiioonn iieenn111166--nnaammee--sseerrvveerrss _i_p_-_a_d_d_r_e_s_s [,, _i_p_-_a_d_d_r_e_s_s... ]; @@ -276,9 +276,9 @@ dhcpd-options(5) dhcpd-options(5) ooppttiioonn iipp--ffoorrwwaarrddiinngg _f_l_a_g;; 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. ooppttiioonn iirrcc--sseerrvveerr _i_p_-_a_d_d_r_e_s_s [,, _i_p_-_a_d_d_r_e_s_s... ];; @@ -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. ooppttiioonn mmaaxx--ddggrraamm--rreeaasssseemmbbllyy _u_i_n_t_1_6;; @@ -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. ooppttiioonn nnttpp--sseerrvveerrss _i_p_-_a_d_d_r_e_s_s [,, _i_p_-_a_d_d_r_e_s_s... ];; @@ -492,10 +492,10 @@ dhcpd-options(5) dhcpd-options(5) ooppttiioonn ppeerrffoorrmm--mmaasskk--ddiissccoovveerryy _f_l_a_g;; 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. ooppttiioonn ppoolliiccyy--ffiilltteerr _i_p_-_a_d_d_r_e_s_s _i_p_-_a_d_d_r_e_s_s [,, _i_p_-_a_d_d_r_e_s_s _i_p_-_a_d_d_r_e_s_s...];; @@ -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. ooppttiioonn rroouutteerr--ssoolliicciittaattiioonn--aaddddrreessss _i_p_-_a_d_d_r_e_s_s;; @@ -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. ooppttiioonn ttccpp--kkeeeeppaalliivvee--iinntteerrvvaall _u_i_n_t_3_2;; @@ -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. ooppttiioonn uuaapp--sseerrvveerrss _t_e_x_t;; @@ -720,7 +721,6 @@ dhcpd-options(5) dhcpd-options(5) - 11 diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 490c95f73..7e4695c1e 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -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 *); diff --git a/includes/dhctoken.h b/includes/dhctoken.h index 0fcfd0cd4..41f86b229 100644 --- a/includes/dhctoken.h +++ b/includes/dhctoken.h @@ -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 && \ diff --git a/includes/failover.h b/includes/failover.h index b41d3d2c8..8617cdb36 100644 --- a/includes/failover.h +++ b/includes/failover.h @@ -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 { diff --git a/includes/site.h b/includes/site.h index f3a81b45a..aea811fb2 100644 --- a/includes/site.h +++ b/includes/site.h @@ -50,41 +50,42 @@ /* 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 @@ -152,8 +153,3 @@ /* 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 */ diff --git a/server/confpars.c b/server/confpars.c index 00e9698b8..50f0c5b50 100644 --- a/server/confpars.c +++ b/server/confpars.c @@ -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; } diff --git a/server/db.c b/server/db.c index 57373e6a7..488c670a6 100644 --- a/server/db.c +++ b/server/db.c @@ -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; diff --git a/server/dhcp.c b/server/dhcp.c index 97e5209e5..afb982cf8 100644 --- a/server/dhcp.c +++ b/server/dhcp.c @@ -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, <, !offer || offer == DHCPACK) + if (!(supersede_lease (lease, <, !offer || offer == DHCPACK, + offer == DHCPACK) || (offer && offer != DHCPACK))) { log_info ("%s: database update failed", msg); free_lease_state (state, MDL); diff --git a/server/failover.c b/server/failover.c index 66bda1941..ddee88276 100644 --- a/server/failover.c +++ b/server/failover.c @@ -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, <, 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, <, 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] = { diff --git a/server/mdb.c b/server/mdb.c index 0e10fc165..1803e38d7 100644 --- a/server/mdb.c +++ b/server/mdb.c @@ -43,13 +43,13 @@ #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, <, 1); + supersede_lease (lease, <, 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, <, 1); + supersede_lease (lease, <, 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, <, 1); + supersede_lease (lease, <, 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 () -- 2.47.3