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,
/\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
dhclient.leases(5)
A\bAU\bUT\bTH\bHO\bOR\bR
- 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
+ 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
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.
#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"
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"))
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;
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... ];
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;
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;
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;
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;
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;
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;
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;
-
11
# 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;
/* 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;
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 *));
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 *);
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, ...));
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 *);
ADDRESS = 464,
POTENTIAL_CONFLICT_NIC = 465,
STATE = 466,
- UNKNOWN_STATE = 567
+ UNKNOWN_STATE = 567,
+ CLTT = 568
};
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
#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 {
/* 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 */
#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"
case TIMESTAMP:
case TSTP:
case TSFP:
+ case CLTT:
t = parse_date (cfile);
switch (token) {
case STARTS:
lease.tsfp = t;
break;
+ case CLTT:
+ seenbit = 524288;
+ lease.cltt = t;
+ break;
+
default: /* for gcc, we'll never get here. */
break;
}
#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"
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;
}
/* 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) {
++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;
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;
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;
#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"
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;
}
#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;
/* 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
lease_time = (lease -> tsfp - cur_time
+ peer -> mclt);
}
+ lt.cltt = cur_time;
}
#endif /* FAILOVER_PROTOCOL */
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. */
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);
#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"
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);
}
}
state -> update_queue_head) {
dhcp_failover_send_updates (state);
}
+ dhcp_failover_state_pool_check (state);
break;
default:
break;
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. */
/* 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;
(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,
&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++;
&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);
}
}
}
}
+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, ...)
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
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;
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:
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,
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,
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)
#if defined (DEBUG_FAILOVER_MESSAGES)
char obuf [64];
unsigned obufix = 0;
+ int binding_status;
# define FMA obuf, &obufix, sizeof obuf
failover_print (FMA, "(bndupd");
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,
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,
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;
}
}
#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] = {
#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;
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... */
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;
/* 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);
}
}
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;
}
}
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
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)
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
;
}
lt.ends = cur_time;
lt.billing_class = (struct class *)0;
- supersede_lease (lease, <, 1);
+ supersede_lease (lease, <, 1, 1);
}
}
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
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. */
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.
}
#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;
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 ()
{
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 ()