2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-03 15:56:00 +00:00

Rework DHCP lease state handling to be compatible with failover protocol.

This commit is contained in:
Ted Lemon
2000-06-02 21:27:21 +00:00
parent 7bb809483c
commit 007e3ee4df
15 changed files with 1317 additions and 883 deletions

View File

@@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: failover.c,v 1.15 2000/05/17 16:04:26 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: failover.c,v 1.16 2000/06/02 21:27:17 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -383,6 +383,8 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
a state object. */
/* XXX this should be authenticated! */
if (link -> imsg -> type == FTM_CONNECT) {
const char *errmsg;
int reason;
/* See if we can find a failover_state object that
matches this connection. This message should only
be received by a secondary from a primary. */
@@ -396,10 +398,13 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
/* If we can't find a failover protocol state
for this remote host, drop the connection */
if (!state) {
errmsg = "unknown server";
reason = FTR_INVALID_PARTNER;
badconnect:
/* XXX Send a refusal message first?
XXX Look in protocol spec for guidance. */
log_error ("Failover CONNECT from %s %d.%d.%d.%d",
"unknown server",
log_error ("Failover CONNECT from %d.%d.%d.%d: %s",
((u_int8_t *)
(&link -> imsg -> server_addr)) [0],
((u_int8_t *)
@@ -407,15 +412,32 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
((u_int8_t *)
(&link -> imsg -> server_addr)) [2],
((u_int8_t *)
(&link -> imsg -> server_addr)) [3]);
(&link -> imsg -> server_addr)) [3],
errmsg);
dhcp_failover_send_connectack
((omapi_object_t *)link,
FTR_INVALID_PARTNER);
((omapi_object_t *)link, state,
reason, errmsg);
omapi_disconnect (c, 0);
link -> state = dhcp_flink_disconnected;
return ISC_R_SUCCESS;
}
if (!(link -> imsg -> options_present & FTB_HBA) ||
link -> imsg -> hba.count != 32) {
errmsg = "invalid HBA";
reason = FTR_HBA_CONFLICT; /* XXX */
goto badconnect;
}
if (state -> hba)
dfree (state -> hba, MDL);
state -> hba = dmalloc (32, MDL);
if (!state -> hba) {
errmsg = "no memory";
reason = FTR_MISC_REJECT;
goto badconnect;
}
memcpy (state -> hba, link -> imsg -> hba.data, 32);
if (!link -> state_object)
dhcp_failover_state_reference
(&link -> state_object, state, MDL);
@@ -567,7 +589,7 @@ static isc_result_t do_a_failover_option (c, link)
ft_options [option_code].type == FT_DDNS1) {
ddns_fqdn_t *ddns =
((ddns_fqdn_t *)
(((char *)&link -> imsg) +
(((char *)link -> imsg) +
ft_options [option_code].offset));
op_count = (ft_options [option_code].type == FT_DDNS1
@@ -613,7 +635,7 @@ static isc_result_t do_a_failover_option (c, link)
op_count = option_len / op_size;
fo = ((failover_option_t *)
(((char *)&link -> imsg) +
(((char *)link -> imsg) +
ft_options [option_code].offset));
fo -> count = op_count;
@@ -1052,7 +1074,7 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
dhcp_failover_link_reference (&state -> link_to_peer,
link, MDL);
status = (dhcp_failover_send_connectack
((omapi_object_t *)link, 0));
((omapi_object_t *)link, state, 0, 0));
if (status != ISC_R_SUCCESS) {
dhcp_failover_link_dereference
(&state -> link_to_peer, MDL);
@@ -1061,8 +1083,10 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
}
dhcp_failover_state_transition (state, "connect");
} else if (link -> imsg -> type == FTM_CONNECTACK) {
const char *errmsg;
int reason;
if (link -> imsg -> reject_reason) {
log_error ("Failover CONNECTACK from %d.%d.%d.%d%s%s",
log_error ("Failover CONNECT to %d.%d.%d.%d%s%s",
((u_int8_t *)
(&link -> imsg -> server_addr)) [0],
((u_int8_t *)
@@ -1074,6 +1098,7 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
" rejected: ",
(dhcp_failover_reject_reason_print
(link -> imsg -> reject_reason)));
/* XXX print message from peer if peer sent message. */
omapi_disconnect (link -> outer, 1);
return ISC_R_SUCCESS;
}
@@ -1082,8 +1107,10 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
(state,
(u_int8_t *)&link -> imsg -> server_addr,
sizeof link -> imsg -> server_addr)) {
log_error ("Failover CONNECTACK from %s %d.%d.%d.%d",
"unknown server",
errmsg = "unknown server";
reason = FTR_INVALID_PARTNER;
badconnectack:
log_error ("Failover CONNECTACK from %d.%d.%d.%d: %s",
((u_int8_t *)
(&link -> imsg -> server_addr)) [0],
((u_int8_t *)
@@ -1091,27 +1118,19 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
((u_int8_t *)
(&link -> imsg -> server_addr)) [2],
((u_int8_t *)
(&link -> imsg -> server_addr)) [3]);
(&link -> imsg -> server_addr)) [3],
errmsg);
dhcp_failover_send_disconnect ((omapi_object_t *)link,
FTR_INVALID_PARTNER, 0);
reason, errmsg);
omapi_disconnect (link -> outer, 0);
}
if (state -> link_to_peer) {
log_error ("Failover CONNECTACK %s %d.%d.%d.%d",
"while already connected",
((u_int8_t *)
(&link -> imsg -> server_addr)) [0],
((u_int8_t *)
(&link -> imsg -> server_addr)) [1],
((u_int8_t *)
(&link -> imsg -> server_addr)) [2],
((u_int8_t *)
(&link -> imsg -> server_addr)) [3]);
dhcp_failover_send_disconnect ((omapi_object_t *)link,
FTR_DUP_CONNECTION, 0);
omapi_disconnect (link -> outer, 0);
errmsg = "already connected";
reason = FTR_DUP_CONNECTION;
goto badconnectack;
}
dhcp_failover_link_reference (&state -> link_to_peer,
link, MDL);
dhcp_failover_state_transition (state, "connect");
@@ -1331,9 +1350,14 @@ int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state)
{
int lts;
int leases_queued = 0;
struct lease *lp;
struct lease *lp = (struct lease *)0;
struct lease *next = (struct lease *)0;
struct shared_network *s;
struct pool *p;
int polarity;
binding_state_t peer_lease_state;
binding_state_t my_lease_state;
struct lease **lq;
if (state -> my_state != normal || state -> i_am == secondary)
return 0;
@@ -1342,32 +1366,59 @@ int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state)
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",
log_info ("pool %lx total %d free %d backup %d",
(unsigned long)p, p -> lease_count,
p -> local_leases, p -> peer_leases);
p -> free_leases, p -> backup_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));
}
}
}
/* Right now we're giving the peer half of the free leases.
If we have more leases than the peer (i.e., more than
half), then the number of leases we have, less the number
of leases the peer has, will be how many more leases we
have than the peer has. So if we send half that number
to the peer, we should be even. */
if (p -> failover_peer -> i_am == primary) {
lts = (p -> free_leases - p -> backup_leases) / 2;
peer_lease_state = FTS_BACKUP;
my_lease_state = FTS_FREE;
lq = &p -> free;
} else {
lts = (p -> backup_leases - p -> free_leases) / 2;
peer_lease_state = FTS_FREE;
my_lease_state = FTS_BACKUP;
lq = &p -> backup;
}
if (lts > 1) {
lease_reference (&lp, *lq, MDL);
while (lp && lts) {
/* Remember the next lease in the list. */
if (next)
lease_dereference (&next, MDL);
if (lp -> next)
lease_reference (&next, lp -> next, MDL);
--lts;
++leases_queued;
lp -> next_binding_state = peer_lease_state;
lp -> tstp = cur_time;
lp -> starts = cur_time;
if (!supersede_lease (lp, (struct lease *)0, 1, 1, 0))
{
log_info ("can't commit lease %s on giveaway",
piaddr (lp -> ip_addr));
}
lease_dereference (&lp, MDL);
if (next)
lease_reference (&lp, next, MDL);
}
if (next)
lease_dereference (&next, MDL);
if (lp)
lease_dereference (&lp, MDL);
}
if (lts > 1) {
log_info ("lease imbalance - lts = %d", lts);
leases_queued -= lts;
@@ -1375,6 +1426,7 @@ int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state)
}
}
dhcp_failover_send_poolresp (state, leases_queued);
dhcp_failover_send_updates (state);
return leases_queued;
}
@@ -1388,12 +1440,15 @@ int dhcp_failover_pool_check (struct pool *pool)
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);
if (pool -> failover_peer -> i_am == primary)
lts = (pool -> backup_leases - pool -> free_leases) / 2;
else
lts = (pool -> free_leases - pool -> backup_leases) / 2;
log_info ("pool %lx total %d free %d backup %d lts %d",
(unsigned long)pool, pool -> lease_count,
pool -> free_leases, pool -> backup_leases, lts);
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);
@@ -1477,7 +1532,7 @@ isc_result_t dhcp_failover_send_updates (dhcp_failover_state_t *state)
not an error for this to be called on a lease for which there's no
failover peer. */
int dhcp_failover_queue_update (struct lease *lease)
int dhcp_failover_queue_update (struct lease *lease, int immediate)
{
dhcp_failover_state_t *state;
@@ -1509,7 +1564,8 @@ int dhcp_failover_queue_update (struct lease *lease)
}
lease_reference (&state -> update_queue_tail, lease, MDL);
lease -> flags |= ON_UPDATE_QUEUE;
dhcp_failover_send_updates (state);
if (immediate)
dhcp_failover_send_updates (state);
return 1;
}
@@ -1530,7 +1586,7 @@ void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *state,
return;
}
for (lp = state -> ack_queue_head;
lp -> next_pending != lease; lp = lp -> next_pending)
lp && lp -> next_pending != lease; lp = lp -> next_pending)
;
if (lp) {
lease_dereference (&lp -> next_pending, MDL);
@@ -2140,7 +2196,8 @@ failover_option_t *dhcp_failover_option_printf (unsigned code,
char *obuf,
unsigned *obufix,
unsigned obufmax,
const char *fmt, ...) {
const char *fmt, ...)
{
va_list va;
char tbuf [256];
@@ -2472,6 +2529,7 @@ isc_result_t dhcp_failover_send_connect (omapi_object_t *l)
dhcp_failover_link_t *link;
dhcp_failover_state_t *state;
isc_result_t status;
char hba [32];
#if defined (DEBUG_FAILOVER_MESSAGES)
char obuf [64];
unsigned obufix = 0;
@@ -2489,6 +2547,12 @@ isc_result_t dhcp_failover_send_connect (omapi_object_t *l)
if (!l -> outer || l -> outer -> type != omapi_type_connection)
return ISC_R_INVALIDARG;
if (state -> hba) {
int i;
for (i = 0; i < 32; i++)
hba [i] = ~state -> hba [i];
}
status = (dhcp_failover_put_message
(link, l -> outer,
FTM_CONNECT,
@@ -2507,7 +2571,9 @@ isc_result_t dhcp_failover_send_connect (omapi_object_t *l)
0, 0),
dhcp_failover_make_option (FTO_MCLT, FMA,
state -> mclt),
dhcp_failover_make_option (FTO_HBA, FMA, 32, state -> hba),
(state -> hba
? dhcp_failover_make_option (FTO_HBA, FMA, 32, hba)
: &skip_failover_option),
(failover_option_t *)0));
#if defined (DEBUG_FAILOVER_MESSAGES)
@@ -2521,10 +2587,11 @@ isc_result_t dhcp_failover_send_connect (omapi_object_t *l)
return status;
}
isc_result_t dhcp_failover_send_connectack (omapi_object_t *l, int reason)
isc_result_t dhcp_failover_send_connectack (omapi_object_t *l,
dhcp_failover_state_t *state,
int reason, const char *errmsg)
{
dhcp_failover_link_t *link;
dhcp_failover_state_t *state;
isc_result_t status;
#if defined (DEBUG_FAILOVER_MESSAGES)
char obuf [64];
@@ -2539,20 +2606,26 @@ isc_result_t dhcp_failover_send_connectack (omapi_object_t *l, int reason)
if (!l || l -> type != dhcp_type_failover_link)
return ISC_R_INVALIDARG;
link = (dhcp_failover_link_t *)l;
state = link -> state_object;
if (!l -> outer || l -> outer -> type != omapi_type_connection)
return ISC_R_INVALIDARG;
status = (dhcp_failover_put_message
(link, l -> outer,
FTM_CONNECTACK,
dhcp_failover_make_option (FTO_SERVER_ADDR, FMA,
state -> server_identifier.len,
state -> server_identifier.data),
dhcp_failover_make_option (FTO_MAX_UNACKED, FMA,
state -> max_flying_updates),
dhcp_failover_make_option (FTO_RECEIVE_TIMER, FMA,
state -> max_response_delay),
(state
? (dhcp_failover_make_option
(FTO_SERVER_ADDR, FMA,
state -> server_identifier.len,
state -> server_identifier.data))
: &skip_failover_option),
(state
? dhcp_failover_make_option (FTO_MAX_UNACKED, FMA,
state -> max_flying_updates)
: &skip_failover_option),
(state
? dhcp_failover_make_option (FTO_RECEIVE_TIMER, FMA,
state -> max_response_delay)
: &skip_failover_option),
dhcp_failover_option_printf (FTO_VENDOR_CLASS, FMA,
"isc-%s", DHCP_VERSION),
dhcp_failover_make_option (FTO_PROTOCOL_VERSION, FMA,
@@ -2563,7 +2636,11 @@ isc_result_t dhcp_failover_send_connectack (omapi_object_t *l, int reason)
? dhcp_failover_make_option (FTO_REJECT_REASON,
FMA, reason)
: &skip_failover_option),
(failover_option_t *)0));
(errmsg
? dhcp_failover_make_option (FTO_MESSAGE, FMA,
strlen (errmsg), errmsg)
: &skip_failover_option),
(failover_option_t *)0));
#if defined (DEBUG_FAILOVER_MESSAGES)
if (status != ISC_R_SUCCESS)
@@ -2635,7 +2712,6 @@ 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");
@@ -2651,26 +2727,6 @@ 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,
@@ -2679,7 +2735,7 @@ 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,
binding_status),
lease -> binding_state),
lease -> uid_len
? dhcp_failover_make_option (FTO_CLIENT_IDENTIFIER, FMA,
lease -> uid_len,
@@ -2726,7 +2782,6 @@ isc_result_t dhcp_failover_send_bind_ack (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, "(bndack");
@@ -2742,26 +2797,6 @@ isc_result_t dhcp_failover_send_bind_ack (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;
if (!message && reason)
message = dhcp_failover_reject_reason_print (reason);
@@ -2773,7 +2808,7 @@ isc_result_t dhcp_failover_send_bind_ack (dhcp_failover_state_t *state,
lease -> ip_addr.len,
lease -> ip_addr.iabuf),
dhcp_failover_make_option (FTO_BINDING_STATUS, FMA,
binding_status),
lease -> binding_state),
lease -> uid_len
? dhcp_failover_make_option (FTO_CLIENT_IDENTIFIER, FMA,
lease -> uid_len,
@@ -2864,7 +2899,7 @@ isc_result_t dhcp_failover_send_poolresp (dhcp_failover_state_t *state,
unsigned obufix = 0;
# define FMA obuf, &obufix, sizeof obuf
failover_print (FMA, "(poolreq");
failover_print (FMA, "(poolresp");
#else
# define FMA (unsigned char *)0, (unsigned *)0, 0
#endif
@@ -2902,6 +2937,7 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
struct iaddr ia;
int reason = FTR_MISC_REJECT;
const char *message;
int new_binding_state;
ia.len = sizeof msg -> assigned_addr;
memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
@@ -2964,21 +3000,20 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
}
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;
/* Check the requested transition to make sure it's
valid. */
new_binding_state = (binding_state_transition_check
(lease, state, msg -> binding_status));
if (new_binding_state != msg -> binding_status) {
dhcp_failover_send_bind_ack
(state, lease, msg, FTR_FATAL_CONFLICT,
"invalid binding state transition");
}
lt -> next_binding_state = new_binding_state;
}
/* Try to install the new information. */
if (!supersede_lease (lease, lt, 1, 0)) {
if (!supersede_lease (lease, lt, 1, 0, 0)) {
message = "database update failed";
bad:
dhcp_failover_send_bind_ack (state, lease, msg,
@@ -3022,7 +3057,7 @@ isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *state,
}
/* Try to install the new information. */
supersede_lease (lease, lt, 1, 0);
supersede_lease (lease, lt, 1, 0, 0);
state -> cur_unacked_updates--;
dhcp_failover_ack_queue_remove (state, lease);
@@ -3120,6 +3155,11 @@ int load_balance_mine (struct packet *packet, dhcp_failover_state_t *state)
return 1;
}
/* If we don't have a hash bucket array, we can't tell if this
one's ours, so we assume it's not. */
if (!state -> hba)
return 0;
oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_CLIENT_IDENTIFIER);
memset (&ds, 0, sizeof ds);
@@ -3139,6 +3179,195 @@ int load_balance_mine (struct packet *packet, dhcp_failover_state_t *state)
return !hm;
}
binding_state_t binding_state_transition_check (struct lease *lease,
dhcp_failover_state_t *state,
binding_state_t binding_state)
{
/* If there is no transition, it's no problem. */
if (binding_state == lease -> binding_state)
return binding_state;
/* This is really only dealing with what to do with bind updates when
we're in the normal state - if we were down and came back, and the
peer is in partner_down state, then we should take whatever it
sends, as long as it hasn't done anything illegal. What about
when we're in potential_conflict? */
/* Also, we should sanity check things here - the partner shouldn't
be allowed to set a lease to the EXPIRED state when it hasn't
expired, for example. */
/* Note that tsfp had better be set from the latest bind update
_before_ this function is called! */
switch (lease -> binding_state) {
case FTS_FREE:
case FTS_ABANDONED:
switch (binding_state) {
case FTS_ACTIVE:
case FTS_ABANDONED:
case FTS_BACKUP:
case FTS_RESERVED:
case FTS_BOOTP:
/* If the lease was free, and our peer is primary,
then it can make it active, or abandoned, or
backup. Abandoned is treated like free in
this case. */
if (state -> i_am == secondary)
return binding_state;
/* Otherwise, it can't do any sort of state
transition. */
case FTS_FREE: /* for compiler */
case FTS_EXPIRED:
case FTS_RELEASED:
case FTS_RESET:
return FTS_FREE;
}
case FTS_ACTIVE:
case FTS_RESERVED:
case FTS_BOOTP:
/* The secondary can't change the state of an active
lease. */
if (state -> i_am == primary)
return FTS_ACTIVE;
/* So this is only for transitions made by the primary: */
switch (binding_state) {
case FTS_FREE:
case FTS_BACKUP:
/* Can't set a lease to free or backup until the
peer agrees that it's expired. */
if (lease -> tsfp > cur_time)
return FTS_ACTIVE;
return binding_state;
case FTS_EXPIRED:
if (lease -> ends > cur_time)
return lease -> binding_state;
case FTS_RESERVED:
case FTS_BOOTP:
case FTS_RELEASED:
case FTS_ABANDONED:
case FTS_RESET:
case FTS_ACTIVE:
return binding_state;
}
case FTS_EXPIRED:
switch (binding_state) {
case FTS_FREE:
case FTS_BACKUP:
/* Can't set a lease to free or backup until the
peer agrees that it's expired. */
if (lease -> tsfp > cur_time)
return FTS_ACTIVE;
return binding_state;
case FTS_RESERVED:
case FTS_BOOTP:
case FTS_ACTIVE:
case FTS_RELEASED:
case FTS_ABANDONED:
case FTS_RESET:
case FTS_EXPIRED:
return binding_state;
}
case FTS_RELEASED:
switch (binding_state) {
case FTS_FREE:
case FTS_BACKUP:
/* Can't set a lease to free or backup until the
peer agrees that it's expired. */
if (lease -> tsfp > cur_time)
return FTS_ACTIVE;
return binding_state;
case FTS_RESERVED:
case FTS_BOOTP:
case FTS_EXPIRED:
case FTS_ABANDONED:
case FTS_RESET:
case FTS_ACTIVE:
case FTS_RELEASED:
return binding_state;
}
case FTS_RESET:
switch (binding_state) {
case FTS_FREE:
case FTS_BACKUP:
/* Can't set a lease to free or backup until the
peer agrees that it's expired. */
if (lease -> tsfp > cur_time)
return FTS_ACTIVE;
return binding_state;
case FTS_ACTIVE:
case FTS_RESERVED:
case FTS_BOOTP:
case FTS_EXPIRED:
case FTS_RELEASED:
case FTS_ABANDONED:
case FTS_RESET:
return binding_state;
}
case FTS_BACKUP:
switch (binding_state) {
case FTS_ACTIVE:
case FTS_ABANDONED:
case FTS_FREE:
case FTS_RESERVED:
case FTS_BOOTP:
/* If the lease was in backup, and our peer is
secondary, then it can make it active, or
abandoned, or free. */
if (state -> i_am == primary)
return binding_state;
/* Otherwise, it can't do any sort of state
transition. */
case FTS_EXPIRED:
case FTS_RELEASED:
case FTS_RESET:
return lease -> binding_state;
case FTS_BACKUP:
return FTS_BACKUP;
}
}
/*NOTREACHED*/
return lease -> binding_state;
}
int lease_mine_to_extend (struct lease *lease)
{
dhcp_failover_state_t *peer;
if (lease && lease -> pool &&
lease -> pool -> failover_peer) {
peer = lease -> pool -> failover_peer;
/* XXX This does't seem right - either peer can extend a lease to MCLT. */
if (peer -> my_state == normal) { /* XXX */
switch (lease -> binding_state) {
case FTS_ACTIVE:
case FTS_ABANDONED:
case FTS_RESET:
case FTS_RELEASED:
case FTS_EXPIRED:
case FTS_FREE:
case FTS_BOOTP:
case FTS_RESERVED:
if (peer -> i_am == secondary)
return 0;
break;
case FTS_BACKUP:
if (peer -> i_am == primary)
return 0;
break;
}
}
}
return 1;
}
OMAPI_OBJECT_ALLOC (dhcp_failover_state, dhcp_failover_state_t,
dhcp_type_failover_state)
OMAPI_OBJECT_ALLOC (dhcp_failover_listener, dhcp_failover_listener_t,