mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-29 13:28:14 +00:00
Rework DHCP lease state handling to be compatible with failover protocol.
This commit is contained in:
parent
7bb809483c
commit
007e3ee4df
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: clparse.c,v 1.44 2000/05/16 23:01:57 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: clparse.c,v 1.45 2000/06/02 21:26:55 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -291,7 +291,7 @@ void parse_client_statement (cfile, ip, config)
|
||||
return;
|
||||
}
|
||||
config -> auth_policy = policy;
|
||||
} else if (token != BOOTP) {
|
||||
} else if (token != TOKEN_BOOTP) {
|
||||
if (policy != P_PREFER &&
|
||||
policy != P_IGNORE &&
|
||||
policy != P_ACCEPT) {
|
||||
@ -919,7 +919,7 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp)
|
||||
parse_warn (cfile, "unknown key %s", val);
|
||||
parse_semi (cfile);
|
||||
break;
|
||||
case BOOTP:
|
||||
case TOKEN_BOOTP:
|
||||
lease -> is_bootp = 1;
|
||||
break;
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char ocopyright[] =
|
||||
"$Id: dhclient.c,v 1.104 2000/05/30 21:43:42 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: dhclient.c,v 1.105 2000/06/02 21:26:57 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -779,7 +779,7 @@ void bind_lease (client)
|
||||
}
|
||||
|
||||
/* Write out the new lease. */
|
||||
write_client_lease (client, client -> new, 0);
|
||||
write_client_lease (client, client -> new, 0, 0);
|
||||
|
||||
/* Replace the old active lease with the new one. */
|
||||
if (client -> active)
|
||||
@ -1561,17 +1561,49 @@ void send_release (cpp)
|
||||
struct client_state *client = cpp;
|
||||
|
||||
int result;
|
||||
struct sockaddr_in destination;
|
||||
struct in_addr from;
|
||||
|
||||
memcpy (&from, client -> active -> address.iabuf,
|
||||
sizeof from);
|
||||
memcpy (&destination.sin_addr.s_addr,
|
||||
client -> destination.iabuf,
|
||||
sizeof destination.sin_addr.s_addr);
|
||||
destination.sin_port = remote_port;
|
||||
destination.sin_family = AF_INET;
|
||||
#ifdef HAVE_SA_LEN
|
||||
destination.sin_len = sizeof destination;
|
||||
#endif
|
||||
|
||||
|
||||
/* Set the lease to end now, so that we don't accidentally
|
||||
reuse it if we restart before the old expiry time. */
|
||||
client -> active -> expiry =
|
||||
client -> active -> renewal =
|
||||
client -> active -> rebind = cur_time;
|
||||
if (!write_client_lease (client, client -> active, 1, 1)) {
|
||||
log_error ("Can't release lease: lease write failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
log_info ("DHCPRELEASE on %s to %s port %d",
|
||||
client -> name ? client -> name : client -> interface -> name,
|
||||
inet_ntoa (sockaddr_broadcast.sin_addr),
|
||||
ntohs (sockaddr_broadcast.sin_port));
|
||||
inet_ntoa (destination.sin_addr),
|
||||
ntohs (destination.sin_port));
|
||||
|
||||
if (fallback_interface)
|
||||
result = send_packet (fallback_interface,
|
||||
(struct packet *)0,
|
||||
&client -> packet,
|
||||
client -> packet_length,
|
||||
from, &destination,
|
||||
(struct hardware *)0);
|
||||
else
|
||||
/* Send out a packet. */
|
||||
result = send_packet (client -> interface, (struct packet *)0,
|
||||
&client -> packet,
|
||||
client -> packet_length,
|
||||
inaddr_any, &sockaddr_broadcast,
|
||||
from, &destination,
|
||||
(struct hardware *)0);
|
||||
}
|
||||
|
||||
@ -1926,11 +1958,11 @@ void rewrite_client_leases ()
|
||||
for (ip = interfaces; ip; ip = ip -> next) {
|
||||
for (client = ip -> client; client; client = client -> next) {
|
||||
for (lp = client -> leases; lp; lp = lp -> next) {
|
||||
write_client_lease (client, lp, 1);
|
||||
write_client_lease (client, lp, 1, 0);
|
||||
}
|
||||
if (client -> active)
|
||||
write_client_lease (client,
|
||||
client -> active, 1);
|
||||
client -> active, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1939,20 +1971,21 @@ void rewrite_client_leases ()
|
||||
for (ip = dummy_interfaces; ip; ip = ip -> next) {
|
||||
for (client = ip -> client; client; client = client -> next) {
|
||||
for (lp = client -> leases; lp; lp = lp -> next) {
|
||||
write_client_lease (client, lp, 1);
|
||||
write_client_lease (client, lp, 1, 0);
|
||||
}
|
||||
if (client -> active)
|
||||
write_client_lease (client,
|
||||
client -> active, 1);
|
||||
client -> active, 1, 0);
|
||||
}
|
||||
}
|
||||
fflush (leaseFile);
|
||||
}
|
||||
|
||||
void write_client_lease (client, lease, rewrite)
|
||||
int write_client_lease (client, lease, rewrite, makesure)
|
||||
struct client_state *client;
|
||||
struct client_lease *lease;
|
||||
int rewrite;
|
||||
int makesure;
|
||||
{
|
||||
int i;
|
||||
struct tm *t;
|
||||
@ -1960,6 +1993,7 @@ void write_client_lease (client, lease, rewrite)
|
||||
struct option_cache *oc;
|
||||
struct data_string ds;
|
||||
pair *hash;
|
||||
int errors = 0;
|
||||
|
||||
if (!rewrite) {
|
||||
if (leases_written++ > 20) {
|
||||
@ -1971,7 +2005,7 @@ void write_client_lease (client, lease, rewrite)
|
||||
/* If the lease came from the config file, we don't need to stash
|
||||
a copy in the lease database. */
|
||||
if (lease -> is_static)
|
||||
return;
|
||||
return 1;
|
||||
|
||||
if (!leaseFile) { /* XXX */
|
||||
leaseFile = fopen (path_dhclient_db, "w");
|
||||
@ -1979,6 +2013,7 @@ void write_client_lease (client, lease, rewrite)
|
||||
log_fatal ("can't create %s: %m", path_dhclient_db);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
fprintf (leaseFile, "lease {\n");
|
||||
if (lease -> is_bootp)
|
||||
fprintf (leaseFile, " bootp;\n");
|
||||
@ -1997,6 +2032,10 @@ void write_client_lease (client, lease, rewrite)
|
||||
if (lease -> medium)
|
||||
fprintf (leaseFile, " medium \"%s\";\n",
|
||||
lease -> medium -> string);
|
||||
if (errno != 0) {
|
||||
errors++;
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
memset (&ds, 0, sizeof ds);
|
||||
|
||||
@ -2018,6 +2057,10 @@ void write_client_lease (client, lease, rewrite)
|
||||
(oc -> option -> code,
|
||||
ds.data, ds.len, 1, 1));
|
||||
data_string_forget (&ds, MDL);
|
||||
if (errno != 0) {
|
||||
errors++;
|
||||
errno = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2045,6 +2088,17 @@ void write_client_lease (client, lease, rewrite)
|
||||
t -> tm_hour, t -> tm_min, t -> tm_sec);
|
||||
fprintf (leaseFile, "}\n");
|
||||
fflush (leaseFile);
|
||||
if (errno != 0) {
|
||||
errors++;
|
||||
errno = 0;
|
||||
}
|
||||
if (!errors && makesure) {
|
||||
if (fsync (fileno (leaseFile)) < 0) {
|
||||
log_info ("write_client_lease: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return errors ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Variables holding name of script and file pointer for writing to
|
||||
@ -2357,6 +2411,9 @@ void client_location_changed ()
|
||||
void do_release(client)
|
||||
struct client_state *client;
|
||||
{
|
||||
struct data_string ds;
|
||||
struct option_cache *oc;
|
||||
|
||||
/* make_request doesn't initialize xid because it normally comes
|
||||
from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
|
||||
so pick an xid now. */
|
||||
@ -2367,6 +2424,24 @@ void do_release(client)
|
||||
/* Make a DHCPRELEASE packet, and set appropriate per-interface
|
||||
flags. */
|
||||
make_release (client, client -> active);
|
||||
|
||||
memset (&ds, 0, sizeof ds);
|
||||
oc = lookup_option (&dhcp_universe,
|
||||
client -> active -> options,
|
||||
DHO_DHCP_SERVER_IDENTIFIER);
|
||||
if (oc &&
|
||||
evaluate_option_cache (&ds, (struct packet *)0,
|
||||
(struct lease *)0,
|
||||
(struct option_state *)0,
|
||||
client -> active -> options,
|
||||
&global_scope, oc, MDL)) {
|
||||
if (ds.len > 3) {
|
||||
memcpy (client -> destination.iabuf,
|
||||
ds.data, 4);
|
||||
client -> destination.len = 4;
|
||||
} else
|
||||
client -> destination = iaddr_broadcast;
|
||||
} else
|
||||
client -> destination = iaddr_broadcast;
|
||||
client -> first_sending = cur_time;
|
||||
client -> interval = client -> config -> initial_interval;
|
||||
@ -2376,13 +2451,8 @@ void do_release(client)
|
||||
|
||||
/* Send out the first and only DHCPRELEASE packet. */
|
||||
send_release (client);
|
||||
}
|
||||
|
||||
/* remove the timeouts for this client */
|
||||
cancel_timeout (NULL, client);
|
||||
|
||||
/* if there was no lease, nothing to "do" */
|
||||
if (client -> active) {
|
||||
/* Do the client script RELEASE operation. */
|
||||
script_init (client,
|
||||
"RELEASE", (struct string_list *)0);
|
||||
if (client -> alias)
|
||||
@ -2390,6 +2460,9 @@ void do_release(client)
|
||||
client -> alias);
|
||||
script_go (client);
|
||||
}
|
||||
|
||||
/* remove the timeouts for this client */
|
||||
cancel_timeout (0, client);
|
||||
}
|
||||
|
||||
int dhclient_interface_shutdown_hook (struct interface_info *interface)
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: conflex.c,v 1.75 2000/05/16 23:02:11 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: conflex.c,v 1.76 2000/06/02 21:27:01 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -503,7 +503,7 @@ static enum dhcp_token intern (atom, dfv)
|
||||
if (!strcasecmp (atom + 1, "lgorithm"))
|
||||
return ALGORITHM;
|
||||
if (!strcasecmp (atom + 1, "bandoned"))
|
||||
return ABANDONED;
|
||||
return TOKEN_ABANDONED;
|
||||
if (!strcasecmp (atom + 1, "dd"))
|
||||
return TOKEN_ADD;
|
||||
if (!strcasecmp (atom + 1, "ll"))
|
||||
@ -514,14 +514,20 @@ static enum dhcp_token intern (atom, dfv)
|
||||
return ARRAY;
|
||||
if (!strcasecmp (atom + 1, "ddress"))
|
||||
return ADDRESS;
|
||||
if (!strcasecmp (atom + 1, "ctive"))
|
||||
return TOKEN_ACTIVE;
|
||||
break;
|
||||
case 'b':
|
||||
if (!strcasecmp (atom + 1, "ackup"))
|
||||
return TOKEN_BACKUP;
|
||||
if (!strcasecmp (atom + 1, "ootp"))
|
||||
return TOKEN_BOOTP;
|
||||
if (!strcasecmp (atom + 1, "inding"))
|
||||
return BINDING;
|
||||
if (!strcasecmp (atom + 1, "inary-to-ascii"))
|
||||
return BINARY_TO_ASCII;
|
||||
if (!strcasecmp (atom + 1, "ackoff-cutoff"))
|
||||
return BACKOFF_CUTOFF;
|
||||
if (!strcasecmp (atom + 1, "ootp"))
|
||||
return BOOTP;
|
||||
if (!strcasecmp (atom + 1, "ooting"))
|
||||
return BOOTING;
|
||||
if (!strcasecmp (atom + 1, "oot-unknown-clients"))
|
||||
@ -575,7 +581,7 @@ static enum dhcp_token intern (atom, dfv)
|
||||
if (!strcasecmp (atom + 1, "eny"))
|
||||
return DENY;
|
||||
if (!strcasecmp (atom + 1, "eleted"))
|
||||
return DELETED;
|
||||
return TOKEN_DELETED;
|
||||
if (!strcasecmp (atom + 1, "elete"))
|
||||
return TOKEN_DELETE;
|
||||
if (!strncasecmp (atom + 1, "efault", 6)) {
|
||||
@ -619,6 +625,8 @@ static enum dhcp_token intern (atom, dfv)
|
||||
return EXPIRY;
|
||||
if (!strcasecmp (atom + 2, "pire"))
|
||||
return EXPIRE;
|
||||
if (!strcasecmp (atom + 2, "pired"))
|
||||
return TOKEN_EXPIRED;
|
||||
}
|
||||
if (!strcasecmp (atom + 1, "ncode-int"))
|
||||
return ENCODE_INT;
|
||||
@ -649,6 +657,8 @@ static enum dhcp_token intern (atom, dfv)
|
||||
return FUNCTION;
|
||||
if (!strcasecmp (atom + 1, "ailover"))
|
||||
return FAILOVER;
|
||||
if (!strcasecmp (atom + 1, "ree"))
|
||||
return TOKEN_FREE;
|
||||
break;
|
||||
case 'g':
|
||||
if (!strcasecmp (atom + 1, "iaddr"))
|
||||
@ -779,6 +789,8 @@ static enum dhcp_token intern (atom, dfv)
|
||||
return NS_NXRRSET;
|
||||
if (!strcasecmp (atom + 1, "ull"))
|
||||
return TOKEN_NULL;
|
||||
if (!strcasecmp (atom + 1, "ext"))
|
||||
return TOKEN_NEXT;
|
||||
break;
|
||||
case 'o':
|
||||
if (!strcasecmp (atom + 1, "r"))
|
||||
@ -850,6 +862,12 @@ static enum dhcp_token intern (atom, dfv)
|
||||
return RELEASE;
|
||||
if (!strcasecmp (atom + 1, "efused"))
|
||||
return NS_REFUSED;
|
||||
if (!strcasecmp (atom + 1, "eleased"))
|
||||
return TOKEN_RELEASED;
|
||||
if (!strcasecmp (atom + 1, "eset"))
|
||||
return TOKEN_RESET;
|
||||
if (!strcasecmp (atom + 1, "eserved"))
|
||||
return TOKEN_RESERVED;
|
||||
break;
|
||||
case 's':
|
||||
if (!strcasecmp (atom + 1, "tate"))
|
||||
|
@ -238,12 +238,10 @@ struct hardware {
|
||||
struct lease {
|
||||
OMAPI_OBJECT_PREAMBLE;
|
||||
struct lease *next;
|
||||
struct lease *prev;
|
||||
struct lease *n_uid, *n_hw;
|
||||
struct lease *waitq_next;
|
||||
|
||||
struct iaddr ip_addr;
|
||||
TIME starts, ends, timestamp;
|
||||
TIME starts, ends, timestamp, sort_time;
|
||||
unsigned char *uid;
|
||||
unsigned uid_len;
|
||||
unsigned uid_max;
|
||||
@ -261,18 +259,16 @@ struct lease {
|
||||
struct executable_statement *on_commit;
|
||||
struct executable_statement *on_release;
|
||||
|
||||
int flags;
|
||||
u_int16_t flags;
|
||||
# define STATIC_LEASE 1
|
||||
# define BOOTP_LEASE 2
|
||||
# define PERSISTENT_FLAGS (0)
|
||||
# define MS_NULL_TERMINATION 8
|
||||
# define ABANDONED_LEASE 16
|
||||
# define PEER_IS_OWNER 32
|
||||
# define ON_UPDATE_QUEUE 64
|
||||
# define ON_ACK_QUEUE 128
|
||||
# define EPHEMERAL_FLAGS (BOOTP_LEASE | MS_NULL_TERMINATION | \
|
||||
ABANDONED_LEASE | PEER_IS_OWNER | \
|
||||
# define ON_UPDATE_QUEUE 16
|
||||
# define ON_ACK_QUEUE 32
|
||||
# define EPHEMERAL_FLAGS (MS_NULL_TERMINATION | \
|
||||
ON_ACK_QUEUE | ON_UPDATE_QUEUE)
|
||||
binding_state_t binding_state; /* See failover.h, FTS_*. */
|
||||
binding_state_t next_binding_state; /* See failover.h, FTS_*. */
|
||||
|
||||
struct lease_state *state;
|
||||
|
||||
@ -500,14 +496,16 @@ struct pool {
|
||||
struct shared_network *shared_network;
|
||||
struct permit *permit_list;
|
||||
struct permit *prohibit_list;
|
||||
struct lease *leases;
|
||||
struct lease *insertion_point;
|
||||
struct lease *last_lease;
|
||||
struct lease *next_expiry;
|
||||
struct lease *active;
|
||||
struct lease *expired;
|
||||
struct lease *free;
|
||||
struct lease *backup;
|
||||
struct lease *abandoned;
|
||||
TIME next_event_time;
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
int lease_count;
|
||||
int local_leases;
|
||||
int peer_leases;
|
||||
int free_leases;
|
||||
int backup_leases;
|
||||
dhcp_failover_state_t *failover_peer;
|
||||
#endif
|
||||
};
|
||||
@ -1550,6 +1548,8 @@ extern u_int32_t fto_allowed [];
|
||||
extern int ft_sizes [];
|
||||
extern const char *dhcp_flink_state_names [];
|
||||
#endif
|
||||
extern const char *binding_state_names [];
|
||||
|
||||
extern struct universe agent_universe;
|
||||
extern struct option agent_options [256];
|
||||
extern struct universe server_universe;
|
||||
@ -1617,8 +1617,8 @@ void make_release PROTO ((struct client_state *, struct client_lease *));
|
||||
|
||||
void destroy_client_lease PROTO ((struct client_lease *));
|
||||
void rewrite_client_leases PROTO ((void));
|
||||
void write_client_lease PROTO ((struct client_state *,
|
||||
struct client_lease *, int));
|
||||
int write_client_lease PROTO ((struct client_state *,
|
||||
struct client_lease *, int, int));
|
||||
char *dhcp_option_ev_name PROTO ((struct option *));
|
||||
|
||||
void script_init PROTO ((struct client_state *, const char *,
|
||||
@ -2115,7 +2115,8 @@ 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));
|
||||
int supersede_lease PROTO ((struct lease *, struct lease *, int, int, int));
|
||||
void process_state_transition (struct lease *);
|
||||
int lease_copy PROTO ((struct lease **, struct lease *, const char *, int));
|
||||
void release_lease PROTO ((struct lease *, struct packet *));
|
||||
void abandon_lease PROTO ((struct lease *, const char *));
|
||||
@ -2205,7 +2206,7 @@ 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 *);
|
||||
int dhcp_failover_queue_update (struct lease *, int);
|
||||
void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *, struct lease *);
|
||||
isc_result_t dhcp_failover_state_set_value PROTO ((omapi_object_t *,
|
||||
omapi_object_t *,
|
||||
@ -2243,7 +2244,9 @@ failover_option_t *dhcp_failover_make_option PROTO ((unsigned, char *,
|
||||
isc_result_t dhcp_failover_put_message (dhcp_failover_link_t *,
|
||||
omapi_object_t *, int, ...);
|
||||
isc_result_t dhcp_failover_send_connect PROTO ((omapi_object_t *));
|
||||
isc_result_t dhcp_failover_send_connectack PROTO ((omapi_object_t *, int));
|
||||
isc_result_t dhcp_failover_send_connectack PROTO ((omapi_object_t *,
|
||||
dhcp_failover_state_t *,
|
||||
int, const char *));
|
||||
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 *,
|
||||
@ -2260,6 +2263,11 @@ isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_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 *);
|
||||
binding_state_t binding_state_transition_check (struct lease *,
|
||||
dhcp_failover_state_t *,
|
||||
binding_state_t);
|
||||
int lease_mine_to_extend (struct lease *);
|
||||
|
||||
OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_state, dhcp_failover_state_t,
|
||||
dhcp_type_failover_state)
|
||||
OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_listener, dhcp_failover_listener_t,
|
||||
|
@ -114,7 +114,6 @@ enum dhcp_token {
|
||||
EXPIRE = 308,
|
||||
UNKNOWN_CLIENTS = 309,
|
||||
ALLOW = 310,
|
||||
BOOTP = 311,
|
||||
DENY = 312,
|
||||
BOOTING = 313,
|
||||
DEFAULT = 314,
|
||||
@ -122,7 +121,7 @@ enum dhcp_token {
|
||||
MEDIUM = 316,
|
||||
ALIAS = 317,
|
||||
REBOOT = 318,
|
||||
ABANDONED = 319,
|
||||
TOKEN_ABANDONED = 319,
|
||||
BACKOFF_CUTOFF = 320,
|
||||
INITIAL_INTERVAL = 321,
|
||||
NAMESERVER = 322,
|
||||
@ -216,7 +215,7 @@ enum dhcp_token {
|
||||
STATIC = 414,
|
||||
NEVER = 415,
|
||||
INFINITE = 416,
|
||||
DELETED = 417,
|
||||
TOKEN_DELETED = 417,
|
||||
UPDATED_DNS_RR = 418,
|
||||
DNS_DELETE = 419,
|
||||
DUPLICATES = 420,
|
||||
@ -268,7 +267,17 @@ enum dhcp_token {
|
||||
STATE = 466,
|
||||
UNKNOWN_STATE = 567,
|
||||
CLTT = 568,
|
||||
INCLUDE = 569
|
||||
INCLUDE = 569,
|
||||
BINDING = 570,
|
||||
TOKEN_FREE = 571,
|
||||
TOKEN_ACTIVE = 572,
|
||||
TOKEN_EXPIRED = 573,
|
||||
TOKEN_RELEASED = 574,
|
||||
TOKEN_RESET = 575,
|
||||
TOKEN_BACKUP = 576,
|
||||
TOKEN_RESERVED = 577,
|
||||
TOKEN_BOOTP = 578,
|
||||
TOKEN_NEXT = 579,
|
||||
};
|
||||
|
||||
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
|
||||
|
@ -157,13 +157,17 @@ typedef struct {
|
||||
#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
|
||||
typedef enum {
|
||||
FTS_FREE = 1,
|
||||
FTS_ACTIVE = 2,
|
||||
FTS_EXPIRED = 3,
|
||||
FTS_RELEASED = 4,
|
||||
FTS_ABANDONED = 5,
|
||||
FTS_RESET = 6,
|
||||
FTS_BACKUP = 7,
|
||||
FTS_RESERVED = 8,
|
||||
FTS_BOOTP = 9
|
||||
} binding_state_t;
|
||||
|
||||
#define DHCP_FAILOVER_MAX_MESSAGE_SIZE 2048
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: confpars.c,v 1.112 2000/05/18 20:21:43 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: confpars.c,v 1.113 2000/06/02 21:27:11 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -711,6 +711,10 @@ void parse_failover_peer (cfile, group, type)
|
||||
|
||||
case SECONDARY:
|
||||
peer -> i_am = secondary;
|
||||
if (peer -> hba)
|
||||
parse_warn (cfile,
|
||||
"secondary may not define %s",
|
||||
"load balance settings.");
|
||||
break;
|
||||
|
||||
case PEER:
|
||||
@ -783,6 +787,10 @@ void parse_failover_peer (cfile, group, type)
|
||||
|
||||
case HBA:
|
||||
hba_len = 32;
|
||||
if (peer -> i_am == secondary)
|
||||
parse_warn (cfile,
|
||||
"secondary may not define %s",
|
||||
"load balance settings.");
|
||||
if (!parse_numeric_aggregate (cfile, hba, &hba_len,
|
||||
COLON, 16, 8)) {
|
||||
skip_to_rbrace (cfile, 1);
|
||||
@ -806,6 +814,10 @@ void parse_failover_peer (cfile, group, type)
|
||||
|
||||
case SPLIT:
|
||||
token = next_token (&val, cfile);
|
||||
if (peer -> i_am == secondary)
|
||||
parse_warn (cfile,
|
||||
"secondary may not define %s",
|
||||
"load balance settings.");
|
||||
if (token != NUMBER) {
|
||||
parse_warn (cfile, "expecting number");
|
||||
badsplit:
|
||||
@ -868,6 +880,11 @@ void parse_failover_peer (cfile, group, type)
|
||||
}
|
||||
} while (token != RBRACE);
|
||||
|
||||
if (peer -> i_am == primary && !peer -> hba) {
|
||||
parse_warn (cfile,
|
||||
"primary failover server must have hba or split.");
|
||||
}
|
||||
|
||||
if (type == SHARED_NET_DECL) {
|
||||
group -> shared_network -> failover_peer = peer;
|
||||
}
|
||||
@ -1175,7 +1192,7 @@ void parse_pool_statement (cfile, group, type)
|
||||
|
||||
case DYNAMIC:
|
||||
permit -> type = permit_dynamic_bootp_clients;
|
||||
if (next_token (&val, cfile) != BOOTP) {
|
||||
if (next_token (&val, cfile) != TOKEN_BOOTP) {
|
||||
parse_warn (cfile,
|
||||
"expecting \"bootp\"");
|
||||
skip_to_semi (cfile);
|
||||
@ -1385,7 +1402,7 @@ void parse_host_declaration (cfile, group)
|
||||
}
|
||||
/* If the host declaration was created by the server,
|
||||
remember to save it. */
|
||||
if (token == DELETED) {
|
||||
if (token == TOKEN_DELETED) {
|
||||
deleted = 1;
|
||||
token = next_token (&val, cfile);
|
||||
if (!parse_semi (cfile))
|
||||
@ -2071,7 +2088,7 @@ void parse_group_declaration (cfile, group)
|
||||
token = next_token (&val, cfile);
|
||||
parse_warn (cfile, "unexpected end of file");
|
||||
break;
|
||||
} else if (token == DELETED) {
|
||||
} else if (token == TOKEN_DELETED) {
|
||||
token = next_token (&val, cfile);
|
||||
parse_semi (cfile);
|
||||
deletedp = 1;
|
||||
@ -2215,6 +2232,7 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile)
|
||||
int noequal, newbinding;
|
||||
struct binding *binding;
|
||||
isc_result_t status;
|
||||
binding_state_t *statep;
|
||||
|
||||
lease = (struct lease *)0;
|
||||
status = lease_allocate (&lease, MDL);
|
||||
@ -2351,34 +2369,76 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile)
|
||||
break;
|
||||
|
||||
case DYNAMIC_BOOTP:
|
||||
seenbit = 128;
|
||||
lease -> flags |= BOOTP_LEASE;
|
||||
parse_semi (cfile);
|
||||
break;
|
||||
|
||||
case PEER:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != IS) {
|
||||
parse_warn (cfile, "expecting \"is\".");
|
||||
skip_to_rbrace (cfile, 1);
|
||||
lease_dereference (&lease, MDL);
|
||||
return 0;
|
||||
}
|
||||
token = next_token (&val, cfile);
|
||||
if (token != OWNER) {
|
||||
parse_warn (cfile, "expecting \"owner\".");
|
||||
skip_to_rbrace (cfile, 1);
|
||||
lease_dereference (&lease, MDL);
|
||||
return 0;
|
||||
}
|
||||
seenbit = 262144;
|
||||
lease -> flags |= PEER_IS_OWNER;
|
||||
parse_semi (cfile);
|
||||
break;
|
||||
|
||||
case ABANDONED:
|
||||
seenbit = 256;
|
||||
lease -> flags |= ABANDONED_LEASE;
|
||||
lease -> binding_state = FTS_BOOTP;
|
||||
lease -> next_binding_state = FTS_BOOTP;
|
||||
parse_semi (cfile);
|
||||
break;
|
||||
|
||||
case TOKEN_ABANDONED:
|
||||
seenbit = 256;
|
||||
lease -> binding_state = FTS_ABANDONED;
|
||||
lease -> next_binding_state = FTS_ABANDONED;
|
||||
parse_semi (cfile);
|
||||
break;
|
||||
|
||||
case TOKEN_NEXT:
|
||||
seenbit = 128;
|
||||
statep = &lease -> next_binding_state;
|
||||
goto do_binding_state;
|
||||
|
||||
case BINDING:
|
||||
seenbit = 256;
|
||||
statep = &lease -> binding_state;
|
||||
|
||||
do_binding_state:
|
||||
token = next_token (&val, cfile);
|
||||
if (token != STATE) {
|
||||
parse_warn (cfile, "expecting 'state'");
|
||||
skip_to_semi (cfile);
|
||||
break;
|
||||
}
|
||||
token = next_token (&val, cfile);
|
||||
switch (token) {
|
||||
case TOKEN_ABANDONED:
|
||||
*statep = FTS_ABANDONED;
|
||||
break;
|
||||
case TOKEN_FREE:
|
||||
*statep = FTS_FREE;
|
||||
break;
|
||||
case TOKEN_ACTIVE:
|
||||
*statep = FTS_ACTIVE;
|
||||
break;
|
||||
case TOKEN_EXPIRED:
|
||||
*statep = FTS_EXPIRED;
|
||||
break;
|
||||
case TOKEN_RELEASED:
|
||||
*statep = FTS_RELEASED;
|
||||
break;
|
||||
case TOKEN_RESET:
|
||||
*statep = FTS_RESET;
|
||||
break;
|
||||
case TOKEN_BACKUP:
|
||||
*statep = FTS_BACKUP;
|
||||
break;
|
||||
case TOKEN_RESERVED:
|
||||
*statep = FTS_RESERVED;
|
||||
break;
|
||||
case TOKEN_BOOTP:
|
||||
*statep = FTS_BOOTP;
|
||||
break;
|
||||
default:
|
||||
parse_warn (cfile,
|
||||
"%s: expecting a binding state.",
|
||||
val);
|
||||
skip_to_semi (cfile);
|
||||
break;
|
||||
}
|
||||
/* If no next binding state is specified, it's
|
||||
the same as the current state. */
|
||||
if (!(seenmask & 128) && seenbit == 256)
|
||||
lease -> next_binding_state =
|
||||
lease -> binding_state;
|
||||
parse_semi (cfile);
|
||||
break;
|
||||
|
||||
@ -2817,7 +2877,7 @@ int parse_allow_deny (oc, cfile, flag)
|
||||
|
||||
token = next_token (&val, cfile);
|
||||
switch (token) {
|
||||
case BOOTP:
|
||||
case TOKEN_BOOTP:
|
||||
status = option_cache (oc, (struct data_string *)0, data,
|
||||
&server_options [SV_ALLOW_BOOTP]);
|
||||
break;
|
||||
|
36
server/db.c
36
server/db.c
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: db.c,v 1.50 2000/05/16 23:03:39 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: db.c,v 1.51 2000/06/02 21:27:12 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -143,13 +143,19 @@ int write_lease (lease)
|
||||
}
|
||||
}
|
||||
|
||||
if (lease -> flags & PEER_IS_OWNER) {
|
||||
errno = 0;
|
||||
fprintf (db_file, "\n peer is owner;");
|
||||
if (errno) {
|
||||
++errors;
|
||||
}
|
||||
}
|
||||
fprintf (db_file, "\n binding state %s;",
|
||||
((lease -> binding_state > 0 &&
|
||||
lease -> binding_state <= FTS_BOOTP)
|
||||
? binding_state_names [lease -> binding_state - 1]
|
||||
: "abandoned"));
|
||||
|
||||
if (lease -> binding_state != lease -> next_binding_state)
|
||||
fprintf (db_file, "\n next binding state %s;",
|
||||
((lease -> next_binding_state > 0 &&
|
||||
lease -> next_binding_state <= FTS_BOOTP)
|
||||
? (binding_state_names
|
||||
[lease -> next_binding_state - 1])
|
||||
: "abandoned"));
|
||||
|
||||
/* If this lease is billed to a class and is still valid,
|
||||
write it out. */
|
||||
@ -190,20 +196,6 @@ int write_lease (lease)
|
||||
putc (';', db_file);
|
||||
}
|
||||
}
|
||||
if (lease -> flags & BOOTP_LEASE) {
|
||||
errno = 0;
|
||||
fprintf (db_file, "\n dynamic-bootp;");
|
||||
if (errno) {
|
||||
++errors;
|
||||
}
|
||||
}
|
||||
if (lease -> flags & ABANDONED_LEASE) {
|
||||
errno = 0;
|
||||
fprintf (db_file, "\n abandoned;");
|
||||
if (errno) {
|
||||
++errors;
|
||||
}
|
||||
}
|
||||
for (b = lease -> scope.bindings; b; b = b -> next) {
|
||||
if (!b -> value)
|
||||
continue;
|
||||
|
260
server/dhcp.c
260
server/dhcp.c
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: dhcp.c,v 1.150 2000/05/17 16:04:25 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: dhcp.c,v 1.151 2000/06/02 21:27:13 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -138,16 +138,11 @@ void dhcpdiscover (packet, ms_nulltp)
|
||||
: packet -> interface -> name);
|
||||
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
if (lease && lease -> pool &&
|
||||
lease -> pool -> failover_peer) {
|
||||
peer = lease -> pool -> failover_peer;
|
||||
if ((lease -> flags & PEER_IS_OWNER) &&
|
||||
peer -> my_state == normal) {
|
||||
log_info ("%s: letting peer %s respond.",
|
||||
msgbuf, peer -> name);
|
||||
if (lease && !lease_mine_to_extend (lease)) {
|
||||
log_info ("%s: letting peer %s answer", msgbuf,
|
||||
lease -> pool -> failover_peer -> name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sourceless packets don't make sense here. */
|
||||
@ -191,7 +186,7 @@ void dhcpdiscover (packet, ms_nulltp)
|
||||
if (allocatedp && lease && lease -> pool &&
|
||||
lease -> pool -> failover_peer) {
|
||||
peer = lease -> pool -> failover_peer;
|
||||
if (peer -> hba && peer -> my_state == normal) {
|
||||
if (peer -> my_state == normal) {
|
||||
if (!load_balance_mine (packet, peer)) {
|
||||
log_debug ("%s: load balance to peer %s",
|
||||
msgbuf, peer -> name);
|
||||
@ -256,6 +251,7 @@ void dhcprequest (packet, ms_nulltp)
|
||||
find_lease (&lease, packet,
|
||||
subnet -> shared_network, &ours, MDL);
|
||||
|
||||
|
||||
if (lease && lease -> client_hostname &&
|
||||
db_printable (lease -> client_hostname))
|
||||
s = lease -> client_hostname;
|
||||
@ -278,6 +274,14 @@ void dhcprequest (packet, ms_nulltp)
|
||||
? inet_ntoa (packet -> raw -> giaddr)
|
||||
: packet -> interface -> name);
|
||||
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
if (lease && !lease_mine_to_extend (lease)) {
|
||||
log_info ("%s: letting peer %s answer", msgbuf,
|
||||
lease -> pool -> failover_peer -> name);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If a client on a given network REQUESTs a lease on an
|
||||
address on a different network, NAK it. If the Requested
|
||||
Address option was used, the protocol says that it must
|
||||
@ -360,7 +364,7 @@ void dhcprequest (packet, ms_nulltp)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
#if defined (FAILOVER_PROTOCOL) && 0 /* XXX this isn't the same as above! */
|
||||
/* If we found a lease, but it belongs to a failover peer, and
|
||||
the client is in the SELECTING state, ignore the request -
|
||||
it's not ours. */
|
||||
@ -420,6 +424,7 @@ void dhcprelease (packet, ms_nulltp)
|
||||
struct option_cache *oc;
|
||||
struct data_string data;
|
||||
char *s;
|
||||
char msgbuf [1024]; /* XXX */
|
||||
|
||||
/* DHCPRELEASE must not specify address in requested-address
|
||||
option, but old protocol specs weren't explicit about this,
|
||||
@ -469,7 +474,8 @@ void dhcprelease (packet, ms_nulltp)
|
||||
s = (char *)0;
|
||||
|
||||
/* Say what we're doing... */
|
||||
log_info ("DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)",
|
||||
sprintf (msgbuf,
|
||||
"DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)",
|
||||
inet_ntoa (packet -> raw -> ciaddr),
|
||||
(packet -> raw -> htype
|
||||
? print_hw_addr (packet -> raw -> htype,
|
||||
@ -485,11 +491,27 @@ void dhcprelease (packet, ms_nulltp)
|
||||
: packet -> interface -> name,
|
||||
lease ? "" : "not ");
|
||||
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
if (lease && !lease_mine_to_extend (lease)) {
|
||||
/* DHCPRELEASE messages are unicast, so if the client
|
||||
sent the DHCPRELEASE to us, it's not going to send it
|
||||
to the peer. Not sure why this would happen, and
|
||||
if it does happen I think we still have to change the
|
||||
lease state.
|
||||
XXX See what it says in the draft about this. */
|
||||
log_info ("%s: peer %s holds lease",
|
||||
msgbuf, lease -> pool -> failover_peer -> name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we found a lease, release it. */
|
||||
if (lease && lease -> ends > cur_time) {
|
||||
release_lease (lease, packet);
|
||||
lease_dereference (&lease, MDL);
|
||||
log_info ("%s", msgbuf);
|
||||
}
|
||||
out:
|
||||
if (lease)
|
||||
lease_dereference (&lease, MDL);
|
||||
}
|
||||
|
||||
void dhcpdecline (packet, ms_nulltp)
|
||||
@ -505,6 +527,7 @@ void dhcpdecline (packet, ms_nulltp)
|
||||
int i;
|
||||
const char *status;
|
||||
char *s;
|
||||
char msgbuf [1024]; /* XXX */
|
||||
|
||||
/* DHCPDECLINE must specify address. */
|
||||
if (!(oc = lookup_option (&dhcp_universe, packet -> options,
|
||||
@ -522,6 +545,36 @@ void dhcpdecline (packet, ms_nulltp)
|
||||
data_string_forget (&data, MDL);
|
||||
find_lease_by_ip_addr (&lease, cip, MDL);
|
||||
|
||||
if (lease && lease -> client_hostname &&
|
||||
db_printable (lease -> client_hostname))
|
||||
s = lease -> client_hostname;
|
||||
else
|
||||
s = (char *)0;
|
||||
|
||||
sprintf (msgbuf, "DHCPDECLINE of %s from %s %s%s%svia %s",
|
||||
piaddr (cip),
|
||||
(packet -> raw -> htype
|
||||
? print_hw_addr (packet -> raw -> htype,
|
||||
packet -> raw -> hlen,
|
||||
packet -> raw -> chaddr)
|
||||
: (lease
|
||||
? print_hex_1 (lease -> uid_len, lease -> uid,
|
||||
lease -> uid_len)
|
||||
: "<no identifier>")),
|
||||
s ? "(" : "", s ? s : "", s ? ") " : "",
|
||||
packet -> raw -> giaddr.s_addr
|
||||
? inet_ntoa (packet -> raw -> giaddr)
|
||||
: packet -> interface -> name);
|
||||
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
if (lease && !lease_mine_to_extend (lease)) {
|
||||
if (!ignorep)
|
||||
log_info ("%s: peer %s holds lease", msgbuf,
|
||||
lease -> pool -> failover_peer -> name);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
option_state_allocate (&options, MDL);
|
||||
|
||||
/* Execute statements in scope starting with the subnet scope. */
|
||||
@ -549,37 +602,17 @@ void dhcpdecline (packet, ms_nulltp)
|
||||
/* If we found a lease, mark it as unusable and complain. */
|
||||
if (lease) {
|
||||
abandon_lease (lease, "declined.");
|
||||
status = "";
|
||||
status = "abandoned";
|
||||
}
|
||||
status = " (not found)";
|
||||
status = "not found";
|
||||
} else
|
||||
status = " (ignored)";
|
||||
status = "ignored";
|
||||
|
||||
if (!ignorep) {
|
||||
char *s;
|
||||
if (lease && lease -> client_hostname &&
|
||||
db_printable (lease -> client_hostname))
|
||||
s = lease -> client_hostname;
|
||||
else
|
||||
s = (char *)0;
|
||||
|
||||
log_info ("DHCPDECLINE of %s from %s %s%s%svia %s %s",
|
||||
piaddr (cip),
|
||||
(packet -> raw -> htype
|
||||
? print_hw_addr (packet -> raw -> htype,
|
||||
packet -> raw -> hlen,
|
||||
packet -> raw -> chaddr)
|
||||
: (lease
|
||||
? print_hex_1 (lease -> uid_len, lease -> uid,
|
||||
lease -> uid_len)
|
||||
: "<no identifier>")),
|
||||
s ? "(" : "", s ? s : "", s ? ") " : "",
|
||||
packet -> raw -> giaddr.s_addr
|
||||
? inet_ntoa (packet -> raw -> giaddr)
|
||||
: packet -> interface -> name,
|
||||
status);
|
||||
}
|
||||
if (!ignorep)
|
||||
log_info ("%s: %s", msgbuf, status);
|
||||
|
||||
out:
|
||||
if (options)
|
||||
option_state_dereference (&options, MDL);
|
||||
if (lease)
|
||||
lease_dereference (&lease, MDL);
|
||||
@ -1358,7 +1391,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
|
||||
|
||||
/* Try to find a matching host declaration for this lease. */
|
||||
if (!lease -> host) {
|
||||
struct host_decl *hp;
|
||||
struct host_decl *hp = (struct host_decl *)0;
|
||||
struct host_decl *h;
|
||||
|
||||
/* Try to find a host_decl that matches the client
|
||||
identifier or hardware address on the packet, and
|
||||
@ -1371,11 +1405,12 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
|
||||
evaluate_option_cache (&d1, packet, lease,
|
||||
packet -> options, state -> options,
|
||||
&lease -> scope, oc, MDL)) {
|
||||
struct host_decl *h;
|
||||
hp = (struct host_decl *)0;
|
||||
find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
|
||||
data_string_forget (&d1, MDL);
|
||||
if (!hp)
|
||||
if (hp)
|
||||
host_reference (&lease -> host, hp, MDL);
|
||||
}
|
||||
if (!hp) {
|
||||
find_hosts_by_haddr (&hp,
|
||||
packet -> raw -> htype,
|
||||
packet -> raw -> chaddr,
|
||||
@ -1387,10 +1422,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
|
||||
}
|
||||
if (h)
|
||||
host_reference (&lease -> host, hp, MDL);
|
||||
}
|
||||
if (hp)
|
||||
host_dereference (&hp, MDL);
|
||||
} else
|
||||
lease -> host = (struct host_decl *)0;
|
||||
}
|
||||
|
||||
/* Drop the request if it's not allowed for this client. By
|
||||
@ -1640,6 +1674,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
|
||||
lt -> ends = when;
|
||||
else
|
||||
lt -> ends = state -> offered_expiry;
|
||||
lt -> next_binding_state = FTS_ACTIVE;
|
||||
} else {
|
||||
lease_time = MAX_TIME - cur_time;
|
||||
|
||||
@ -1669,7 +1704,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
|
||||
}
|
||||
|
||||
lt -> ends = state -> offered_expiry = cur_time + lease_time;
|
||||
lt -> flags = BOOTP_LEASE;
|
||||
lt -> next_binding_state = FTS_BOOTP;
|
||||
}
|
||||
|
||||
lt -> timestamp = cur_time;
|
||||
@ -1752,29 +1787,13 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
|
||||
it) either. */
|
||||
|
||||
if (!(supersede_lease (lease, lt, !offer || offer == DHCPACK,
|
||||
offer == DHCPACK)
|
||||
offer == DHCPACK, offer == DHCPACK)
|
||||
|| (offer && offer != DHCPACK))) {
|
||||
log_info ("%s: database update failed", msg);
|
||||
free_lease_state (state, MDL);
|
||||
static_lease_dereference (lease, MDL);
|
||||
lease_dereference (<, MDL);
|
||||
return;
|
||||
} else {
|
||||
/* If this is a DHCPOFFER transaction, supersede_lease
|
||||
will not add the timer for the expire event to the
|
||||
queue. This is because DHCPOFFERS are not commited,
|
||||
and supersede_lease only adds commited leases to the
|
||||
timer queue. So if supersede_lease set this lease
|
||||
as the next one to expire for the pool we need to
|
||||
put it on the timer queue ourself. */
|
||||
/* XXX need to think about this. */
|
||||
if (offer == DHCPOFFER && lease -> pool &&
|
||||
lease -> pool -> next_expiry == lease)
|
||||
add_timeout (lease -> ends, pool_timer,
|
||||
lease -> pool,
|
||||
(tvref_t)omapi_object_reference,
|
||||
(tvunref_t)
|
||||
omapi_object_dereference);
|
||||
}
|
||||
}
|
||||
lease_dereference (<, MDL);
|
||||
@ -2637,7 +2656,6 @@ int find_lease (struct lease **lp,
|
||||
/* Toss ip_lease if it hasn't yet expired and doesn't belong to the
|
||||
client. */
|
||||
if (ip_lease &&
|
||||
ip_lease -> ends >= cur_time &&
|
||||
((ip_lease -> uid &&
|
||||
(!have_client_identifier ||
|
||||
ip_lease -> uid_len != client_identifier.len ||
|
||||
@ -2649,25 +2667,43 @@ int find_lease (struct lease **lp,
|
||||
memcmp (&ip_lease -> hardware_addr.hbuf [1],
|
||||
packet -> raw -> chaddr,
|
||||
(unsigned)(ip_lease -> hardware_addr.hlen - 1)))))) {
|
||||
/* If we're not doing failover, the only state in which
|
||||
we can allocate this lease to the client is FTS_FREE.
|
||||
If we are doing failover, and this lease is part of a
|
||||
failover pool, then if we're the primary, state has to be
|
||||
FTS_FREE; if we're the secondary, state has to be
|
||||
FTS_BACKUP. */
|
||||
if ((ip_lease -> binding_state != FTS_FREE &&
|
||||
ip_lease -> binding_state != FTS_BACKUP)
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
||
|
||||
(ip_lease -> pool -> failover_peer &&
|
||||
((ip_lease -> binding_state == FTS_FREE &&
|
||||
ip_lease -> pool -> failover_peer -> i_am == secondary)
|
||||
||
|
||||
(ip_lease -> binding_state == FTS_BACKUP &&
|
||||
ip_lease -> pool -> failover_peer -> i_am == primary)))
|
||||
#endif
|
||||
) {
|
||||
#if defined (DEBUG_FIND_LEASE)
|
||||
if (ip_lease)
|
||||
log_info ("rejecting lease for requested address.");
|
||||
#endif
|
||||
lease_dereference (&ip_lease, MDL);
|
||||
}
|
||||
}
|
||||
|
||||
/* If for some reason the client has more than one lease
|
||||
on the subnet that matches its uid, pick the one that
|
||||
it asked for and (if we can) free the other. */
|
||||
if (ip_lease &&
|
||||
ip_lease -> ends >= cur_time &&
|
||||
ip_lease -> binding_state == FTS_ACTIVE &&
|
||||
ip_lease -> uid && ip_lease != uid_lease) {
|
||||
if (have_client_identifier &&
|
||||
(ip_lease -> uid_len == client_identifier.len) &&
|
||||
!memcmp (client_identifier.data,
|
||||
ip_lease -> uid, ip_lease -> uid_len)) {
|
||||
if (uid_lease) {
|
||||
if (uid_lease -> ends > cur_time) {
|
||||
if (uid_lease -> binding_state == FTS_ACTIVE) {
|
||||
log_error ("client %s has duplicate%s on %s",
|
||||
(print_hw_addr
|
||||
(packet -> raw -> htype,
|
||||
@ -2722,17 +2758,6 @@ int find_lease (struct lease **lp,
|
||||
if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
|
||||
goto db_conflict;
|
||||
|
||||
/* Make sure the client is permitted to use the requested lease. */
|
||||
if (ip_lease &&
|
||||
((ip_lease -> pool -> prohibit_list &&
|
||||
permitted (packet, ip_lease -> pool -> prohibit_list)) ||
|
||||
(ip_lease -> pool -> permit_list &&
|
||||
!permitted (packet, ip_lease -> pool -> permit_list)))) {
|
||||
if (!packet -> raw -> ciaddr.s_addr)
|
||||
release_lease (ip_lease, packet);
|
||||
lease_dereference (&ip_lease, MDL);
|
||||
}
|
||||
|
||||
/* Toss extra pointers to the same lease... */
|
||||
if (hw_lease && hw_lease == uid_lease) {
|
||||
#if defined (DEBUG_FIND_LEASE)
|
||||
@ -2753,6 +2778,37 @@ int find_lease (struct lease **lp,
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Make sure the client is permitted to use the requested lease. */
|
||||
if (ip_lease &&
|
||||
((ip_lease -> pool -> prohibit_list &&
|
||||
permitted (packet, ip_lease -> pool -> prohibit_list)) ||
|
||||
(ip_lease -> pool -> permit_list &&
|
||||
!permitted (packet, ip_lease -> pool -> permit_list)))) {
|
||||
if (!packet -> raw -> ciaddr.s_addr)
|
||||
release_lease (ip_lease, packet);
|
||||
lease_dereference (&ip_lease, MDL);
|
||||
}
|
||||
|
||||
if (uid_lease &&
|
||||
((uid_lease -> pool -> prohibit_list &&
|
||||
permitted (packet, uid_lease -> pool -> prohibit_list)) ||
|
||||
(uid_lease -> pool -> permit_list &&
|
||||
!permitted (packet, uid_lease -> pool -> permit_list)))) {
|
||||
if (!packet -> raw -> ciaddr.s_addr)
|
||||
release_lease (uid_lease, packet);
|
||||
lease_dereference (&uid_lease, MDL);
|
||||
}
|
||||
|
||||
if (hw_lease &&
|
||||
((hw_lease -> pool -> prohibit_list &&
|
||||
permitted (packet, hw_lease -> pool -> prohibit_list)) ||
|
||||
(hw_lease -> pool -> permit_list &&
|
||||
!permitted (packet, hw_lease -> pool -> permit_list)))) {
|
||||
if (!packet -> raw -> ciaddr.s_addr)
|
||||
release_lease (hw_lease, packet);
|
||||
lease_dereference (&hw_lease, MDL);
|
||||
}
|
||||
|
||||
/* If we've already eliminated the lease, it wasn't there to
|
||||
begin with. If we have come up with a matching lease,
|
||||
set the message to bad network in case we have to throw it out. */
|
||||
@ -2862,12 +2918,13 @@ int find_lease (struct lease **lp,
|
||||
requested, we assume that previous bugginess on the part
|
||||
of the client, or a server database loss, caused the lease to
|
||||
be abandoned, so we reclaim it and let the client have it. */
|
||||
if (lease && (lease -> flags & ABANDONED_LEASE) && lease == ip_lease &&
|
||||
if (lease &&
|
||||
(lease -> binding_state == FTS_ABANDONED) &&
|
||||
lease == ip_lease &&
|
||||
packet -> packet_type == DHCPREQUEST) {
|
||||
log_error ("Reclaiming REQUESTed abandoned IP address %s.",
|
||||
piaddr (lease -> ip_addr));
|
||||
lease -> flags &= ~ABANDONED_LEASE;
|
||||
} else if (lease && (lease -> flags & ABANDONED_LEASE)) {
|
||||
} else if (lease && (lease -> binding_state == FTS_ABANDONED)) {
|
||||
/* Otherwise, if it's not the one the client requested, we do not
|
||||
return it - instead, we claim it's ours, causing a DHCPNAK to be
|
||||
sent if this lookup is for a DHCPREQUEST, and force the client
|
||||
@ -2941,6 +2998,7 @@ int mockup_lease (struct lease **lp, struct packet *packet,
|
||||
lease -> hardware_addr = hp -> interface;
|
||||
lease -> starts = lease -> timestamp = lease -> ends = MIN_TIME;
|
||||
lease -> flags = STATIC_LEASE;
|
||||
lease -> binding_state = FTS_FREE;
|
||||
lease_reference (lp, lease, MDL);
|
||||
lease_dereference (&lease, MDL);
|
||||
return 1;
|
||||
@ -2986,6 +3044,7 @@ int allocate_lease (struct lease **lp, struct packet *packet,
|
||||
struct pool *pool, int *peer_has_leases)
|
||||
{
|
||||
struct lease *lease = (struct lease *)0;
|
||||
struct lease **lq;
|
||||
struct permit *permit;
|
||||
|
||||
if (!pool)
|
||||
@ -2998,31 +3057,39 @@ int allocate_lease (struct lease **lp, struct packet *packet,
|
||||
return allocate_lease (lp, packet, pool -> next,
|
||||
peer_has_leases);
|
||||
|
||||
lease = pool -> last_lease;
|
||||
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
/* Peer_has_leases just says that we found at least one free lease.
|
||||
If no free lease is returned, the caller can deduce that this
|
||||
means the peer is hogging all the free leases, so we can print
|
||||
a better error message. */
|
||||
if (lease)
|
||||
*peer_has_leases = 1;
|
||||
|
||||
/* XXX Do we need code here to ignore PEER_IS_OWNER and just check
|
||||
XXX tstp if we're in, e.g., PARTNER_DOWN? Where do we deal with
|
||||
XXX CONFLICT_DETECTED, et al? */
|
||||
/* XXX This should be handled by the lease binding "state machine" -
|
||||
XXX that is, when we get here, if a lease could be allocated, it
|
||||
XXX will have the correct binding state so that the following code
|
||||
XXX will result in its being allocated. */
|
||||
/* Skip to the most expired lease in the pool that is not owned by a
|
||||
failover peer. */
|
||||
if (lease -> pool && lease -> pool -> failover_peer) {
|
||||
while (lease &&
|
||||
(lease -> flags & PEER_IS_OWNER) &&
|
||||
(lease -> ends <=
|
||||
cur_time + lease -> pool -> failover_peer -> mclt))
|
||||
lease = lease -> prev;
|
||||
/* We didn't find an unexpired lease that we own? */
|
||||
if (lease && lease -> flags & PEER_IS_OWNER)
|
||||
lease = (struct lease *)0;
|
||||
if (pool -> failover_peer) {
|
||||
if (pool -> failover_peer -> i_am == primary) {
|
||||
if (pool -> backup)
|
||||
*peer_has_leases = 1;
|
||||
lease = pool -> free;
|
||||
if (!lease)
|
||||
lease = pool -> abandoned;
|
||||
} else {
|
||||
if (pool -> free)
|
||||
*peer_has_leases = 1;
|
||||
lease = pool -> backup;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (pool -> free)
|
||||
lease = pool -> free;
|
||||
else
|
||||
lease = pool -> abandoned;
|
||||
#endif
|
||||
|
||||
/* If there are no leases in the pool that have
|
||||
@ -3035,7 +3102,7 @@ int allocate_lease (struct lease **lp, struct packet *packet,
|
||||
better, take it. */
|
||||
/* XXX what if there are non-abandoned leases that are younger
|
||||
XXX than this? Shouldn't we hunt for those here? */
|
||||
if ((lease -> flags & ABANDONED_LEASE)) {
|
||||
if (lease -> binding_state == FTS_ABANDONED) {
|
||||
/* If we already have a non-abandoned lease that we didn't
|
||||
love, but that's okay, don't reclaim the abandoned lease. */
|
||||
if (*lp)
|
||||
@ -3045,7 +3112,6 @@ int allocate_lease (struct lease **lp, struct packet *packet,
|
||||
pool -> next, peer_has_leases)) {
|
||||
log_error ("Reclaiming abandoned IP address %s.",
|
||||
piaddr (lease -> ip_addr));
|
||||
lease -> flags &= ~ABANDONED_LEASE;
|
||||
lease_reference (lp, lease, MDL);
|
||||
}
|
||||
return 1;
|
||||
|
@ -1272,18 +1272,21 @@ override the use of the name in the host declaration.
|
||||
\fBnot authoritative;\fR
|
||||
.PP
|
||||
The DHCP server will normally assume that the configuration
|
||||
information about a given network segment is known to be correct and
|
||||
is authoritative. So if a client requests an IP address on a given
|
||||
network segment that the server knows is not valid for that segment,
|
||||
the server will respond with a DHCPNAK message, causing the client to
|
||||
forget its IP address and try to get a new one.
|
||||
information about a given network segment is not known to be correct
|
||||
and is not authoritative. This is so that if a naive user installs a
|
||||
DHCP server not fully understanding how to configure it, it does not
|
||||
send spurious DHCPNAK messages to clients that have obtained addresses
|
||||
from a legitimate DHCP server on the network.
|
||||
.PP
|
||||
If a DHCP server is being configured by somebody who is not the
|
||||
network administrator and who therefore does not wish to assert this
|
||||
level of authority, then the statement "not authoritative" should be
|
||||
written in the appropriate scope in the configuration file.
|
||||
Network administrators setting up authoritative DHCP servers for their
|
||||
networks should always write \fBauthoritative;\fR at the top of their
|
||||
configuration file to indicate that the DHCP server \fIshould\fR send
|
||||
DHCPNAK messages to misconfigured clients. If this is not done,
|
||||
clients will be unable to get a correct IP address after changing
|
||||
subnets until their old lease has expired, which could take quite a
|
||||
long time.
|
||||
.PP
|
||||
Usually, writing \fBnot authoritative;\fR at the top level of the file
|
||||
Usually, writing \fBauthoritative;\fR at the top level of the file
|
||||
should be sufficient. However, if a DHCP server is to be set up so
|
||||
that it is aware of some networks for which it is authoritative and
|
||||
some networks for which it is not, it may be more appropriate to
|
||||
|
@ -1478,22 +1478,25 @@ dhcpd.conf(5) dhcpd.conf(5)
|
||||
nnoott aauutthhoorriittaattiivvee;;
|
||||
|
||||
The DHCP server will normally assume that the configura
|
||||
tion information about a given network segment is known to
|
||||
be correct and is authoritative. So if a client requests
|
||||
an IP address on a given network segment that the server
|
||||
knows is not valid for that segment, the server will
|
||||
respond with a DHCPNAK message, causing the client to for
|
||||
get its IP address and try to get a new one.
|
||||
tion information about a given network segment is not
|
||||
known to be correct and is not authoritative. This is so
|
||||
that if a naive user installs a DHCP server not fully
|
||||
understanding how to configure it, it does not send spuri
|
||||
ous DHCPNAK messages to clients that have obtained
|
||||
addresses from a legitimate DHCP server on the network.
|
||||
|
||||
If a DHCP server is being configured by somebody who is
|
||||
not the network administrator and who therefore does not
|
||||
wish to assert this level of authority, then the statement
|
||||
"not authoritative" should be written in the appropriate
|
||||
scope in the configuration file.
|
||||
Network administrators setting up authoritative DHCP
|
||||
servers for their networks should always write aauutthhoorriittaa
|
||||
ttiivvee;; at the top of their configuration file to indicate
|
||||
that the DHCP server _s_h_o_u_l_d send DHCPNAK messages to mis
|
||||
configured clients. If this is not done, clients will be
|
||||
unable to get a correct IP address after changing subnets
|
||||
until their old lease has expired, which could take quite
|
||||
a long time.
|
||||
|
||||
Usually, writing nnoott aauutthhoorriittaattiivvee;; at the top level of
|
||||
the file should be sufficient. However, if a DHCP server
|
||||
is to be set up so that it is aware of some networks for
|
||||
Usually, writing aauutthhoorriittaattiivvee;; at the top level of the
|
||||
file should be sufficient. However, if a DHCP server is
|
||||
to be set up so that it is aware of some networks for
|
||||
which it is authoritative and some networks for which it
|
||||
is not, it may be more appropriate to declare authority on
|
||||
a per-network-segment basis.
|
||||
@ -1508,9 +1511,6 @@ dhcpd.conf(5) dhcpd.conf(5)
|
||||
that the server is authoritative for some host declara
|
||||
tions and not others.
|
||||
|
||||
TThhee _a_l_w_a_y_s_-_r_e_p_l_y_-_r_f_c_1_0_4_8 ssttaatteemmeenntt
|
||||
|
||||
|
||||
|
||||
|
||||
23
|
||||
@ -1522,6 +1522,8 @@ dhcpd.conf(5) dhcpd.conf(5)
|
||||
dhcpd.conf(5) dhcpd.conf(5)
|
||||
|
||||
|
||||
TThhee _a_l_w_a_y_s_-_r_e_p_l_y_-_r_f_c_1_0_4_8 ssttaatteemmeenntt
|
||||
|
||||
aallwwaayyss--rreeppllyy--rrffcc11004488 _f_l_a_g;;
|
||||
|
||||
Some BOOTP clients expect RFC1048-style responses, but do
|
||||
@ -1574,8 +1576,6 @@ dhcpd.conf(5) dhcpd.conf(5)
|
||||
|
||||
uussee--lleeaassee--aaddddrr--ffoorr--ddeeffaauulltt--rroouuttee _f_l_a_g;;
|
||||
|
||||
If the _u_s_e_-_l_e_a_s_e_-_a_d_d_r_-_f_o_r_-_d_e_f_a_u_l_t_-_r_o_u_t_e parameter is true
|
||||
in a given scope, then instead of sending the value
|
||||
|
||||
|
||||
|
||||
@ -1588,11 +1588,13 @@ dhcpd.conf(5) dhcpd.conf(5)
|
||||
dhcpd.conf(5) dhcpd.conf(5)
|
||||
|
||||
|
||||
specified in the routers option (or sending no value at
|
||||
all), the IP address of the lease being assigned is sent
|
||||
to the client. This supposedly causes Win95 machines to
|
||||
ARP for all IP addresses, which can be helpful if your
|
||||
router is configured for proxy ARP.
|
||||
If the _u_s_e_-_l_e_a_s_e_-_a_d_d_r_-_f_o_r_-_d_e_f_a_u_l_t_-_r_o_u_t_e parameter is true
|
||||
in a given scope, then instead of sending the value speci
|
||||
fied in the routers option (or sending no value at all),
|
||||
the IP address of the lease being assigned is sent to the
|
||||
client. This supposedly causes Win95 machines to ARP for
|
||||
all IP addresses, which can be helpful if your router is
|
||||
configured for proxy ARP.
|
||||
|
||||
TThhee _s_e_r_v_e_r_-_i_d_e_n_t_i_f_i_e_r ssttaatteemmeenntt
|
||||
|
||||
@ -1640,8 +1642,6 @@ RREEFFEERREENNCCEE:: OOPPTTIIOONN SSTTAATTEEMMEENNTTSS
|
||||
SSEEEE AALLSSOO
|
||||
dhcpd.conf(5), dhcpd.leases(5), RFC2132, RFC2131.
|
||||
|
||||
AAUUTTHHOORR
|
||||
ddhhccppdd((88)) was written by Ted Lemon <mellon@vix.com> under a
|
||||
|
||||
|
||||
|
||||
@ -1654,6 +1654,8 @@ AAUUTTHHOORR
|
||||
dhcpd.conf(5) dhcpd.conf(5)
|
||||
|
||||
|
||||
AAUUTTHHOORR
|
||||
ddhhccppdd((88)) was written by Ted Lemon <mellon@vix.com> under a
|
||||
contract with Vixie Labs. Funding for this project was
|
||||
provided by the Internet Software Consortium. Information
|
||||
about the Internet Software Consortium can be found at
|
||||
@ -1706,8 +1708,6 @@ dhcpd.conf(5) dhcpd.conf(5)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
lts = ((p -> local_leases +
|
||||
p -> peer_leases) / 2) - p -> peer_leases;
|
||||
if (lts > 1) {
|
||||
struct lease lt;
|
||||
lease_reference (&lp, *lq, MDL);
|
||||
|
||||
leases_queued += lts;
|
||||
for (lp = p -> last_lease; lp && lts;
|
||||
lp = lp -> prev) {
|
||||
if (!(lp -> flags & PEER_IS_OWNER)) {
|
||||
lp -> flags |= PEER_IS_OWNER;
|
||||
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;
|
||||
if (!write_lease (lp) ||
|
||||
!commit_leases () ||
|
||||
!dhcp_failover_queue_update (lp)) {
|
||||
log_info ("%s lease %s on giveaway",
|
||||
"unable to commit",
|
||||
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,6 +1564,7 @@ int dhcp_failover_queue_update (struct lease *lease)
|
||||
}
|
||||
lease_reference (&state -> update_queue_tail, lease, MDL);
|
||||
lease -> flags |= ON_UPDATE_QUEUE;
|
||||
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
|
||||
? (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 -> 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,6 +2636,10 @@ 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),
|
||||
(errmsg
|
||||
? dhcp_failover_make_option (FTO_MESSAGE, FMA,
|
||||
strlen (errmsg), errmsg)
|
||||
: &skip_failover_option),
|
||||
(failover_option_t *)0));
|
||||
|
||||
#if defined (DEBUG_FAILOVER_MESSAGES)
|
||||
@ -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,
|
||||
|
734
server/mdb.c
734
server/mdb.c
@ -3,7 +3,7 @@
|
||||
Server-specific in-memory database support. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||
* Copyright (c) 1996-2000 Internet Software Consortium.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: mdb.c,v 1.32 2000/05/16 23:03:46 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: mdb.c,v 1.33 2000/06/02 21:27:19 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -498,10 +498,6 @@ void new_address_range (low, high, subnet, pool)
|
||||
subnet -> netmask,
|
||||
i + min)),
|
||||
isc_result_totext (status));
|
||||
/* Fill in the last lease if it hasn't been already... */
|
||||
if (!pool -> last_lease) {
|
||||
lease_reference (&pool -> last_lease, lp, MDL);
|
||||
}
|
||||
#endif
|
||||
lp -> ip_addr = ip_addr (subnet -> net,
|
||||
subnet -> netmask, i + min);
|
||||
@ -509,34 +505,20 @@ void new_address_range (low, high, subnet, pool)
|
||||
lp -> ends = MIN_TIME;
|
||||
subnet_reference (&lp -> subnet, subnet, MDL);
|
||||
pool_reference (&lp -> pool, pool, MDL);
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
if (pool -> failover_peer &&
|
||||
pool -> failover_peer -> i_am == secondary)
|
||||
lp -> flags = PEER_IS_OWNER;
|
||||
else
|
||||
lp -> binding_state = FTS_FREE;
|
||||
lp -> next_binding_state = FTS_FREE;
|
||||
lp -> flags = 0;
|
||||
#endif
|
||||
|
||||
/* Link this entry into the list. */
|
||||
if (pool -> leases) {
|
||||
lease_reference (&lp -> next, pool -> leases, MDL);
|
||||
lease_dereference (&pool -> leases, MDL);
|
||||
if (pool -> free) {
|
||||
lease_reference (&lp -> next, pool -> free, MDL);
|
||||
lease_dereference (&pool -> free, MDL);
|
||||
}
|
||||
lease_reference (&pool -> leases, lp, MDL);
|
||||
if (lp -> next)
|
||||
lease_reference (&lp -> next -> prev,
|
||||
pool -> leases, MDL);
|
||||
lease_reference (&pool -> free, lp, MDL);
|
||||
lease_hash_add (lease_ip_addr_hash, lp -> ip_addr.iabuf,
|
||||
lp -> ip_addr.len, lp, MDL);
|
||||
}
|
||||
|
||||
#if defined (COMPACT_LEASES)
|
||||
/* Fill in the last lease if it hasn't been already... */
|
||||
if (!pool -> last_lease) {
|
||||
lease_reference (&pool -> last_lease, &address_range [0], MDL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Find out if any dangling leases are in range... */
|
||||
plp = (struct lease *)0;
|
||||
for (lp = dangling_leases; lp; lp = lp -> next) {
|
||||
@ -568,7 +550,7 @@ void new_address_range (low, high, subnet, pool)
|
||||
lp -> hostname = (char *)0;
|
||||
lt -> client_hostname = lp -> client_hostname;
|
||||
lp -> client_hostname = (char *)0;
|
||||
supersede_lease (lt, lp, 0, 0);
|
||||
supersede_lease (lt, lp, 0, 0, 0);
|
||||
lease_dereference (<, MDL);
|
||||
}
|
||||
lease_dereference (&lp, MDL);
|
||||
@ -744,15 +726,13 @@ void enter_lease (lease)
|
||||
/* If we don't have a place for this lease yet, save it for
|
||||
later. */
|
||||
if (!find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
|
||||
if (comp -> next)
|
||||
lease_dereference (&comp -> next, MDL);
|
||||
if (lease -> next)
|
||||
lease_dereference (&lease -> next, MDL);
|
||||
if (dangling_leases)
|
||||
lease_reference (&comp -> next, dangling_leases, MDL);
|
||||
lease_reference (&dangling_leases, comp, MDL);
|
||||
if (comp -> prev)
|
||||
lease_dereference (&comp -> prev, MDL);
|
||||
lease_reference (&lease -> next, dangling_leases, MDL);
|
||||
lease_reference (&dangling_leases, lease, MDL);
|
||||
} else {
|
||||
supersede_lease (comp, lease, 0, 0);
|
||||
supersede_lease (comp, lease, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -761,14 +741,20 @@ 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, propogate)
|
||||
int supersede_lease (comp, lease, commit, propogate, pimmediate)
|
||||
struct lease *comp, *lease;
|
||||
int commit;
|
||||
int propogate;
|
||||
int pimmediate;
|
||||
{
|
||||
int enter_uid = 0;
|
||||
int enter_hwaddr = 0;
|
||||
struct lease *lp;
|
||||
struct lease *lp, **lq, *prev;
|
||||
TIME lp_next_state;
|
||||
|
||||
/* If there is no sample lease, just do the move. */
|
||||
if (!lease)
|
||||
goto just_move_it;
|
||||
|
||||
/* Static leases are not currently kept in the database... */
|
||||
if (lease -> flags & STATIC_LEASE)
|
||||
@ -783,8 +769,10 @@ int supersede_lease (comp, lease, commit, propogate)
|
||||
lease, then we allow that, in case a dynamic BOOTP lease is
|
||||
requested *after* a DHCP lease has been assigned. */
|
||||
|
||||
if (!(lease -> flags & ABANDONED_LEASE) &&
|
||||
comp -> ends > cur_time &&
|
||||
if (lease -> binding_state != FTS_ABANDONED &&
|
||||
(comp -> binding_state == FTS_ACTIVE ||
|
||||
comp -> binding_state == FTS_RESERVED ||
|
||||
comp -> binding_state == FTS_BOOTP) &&
|
||||
(((comp -> uid && lease -> uid) &&
|
||||
(comp -> uid_len != lease -> uid_len ||
|
||||
memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
|
||||
@ -905,274 +893,234 @@ int supersede_lease (comp, lease, commit, propogate)
|
||||
hw_hash_add (comp);
|
||||
}
|
||||
|
||||
/* Remove the lease from its current place in the
|
||||
timeout sequence. */
|
||||
if (comp -> prev) {
|
||||
lease_dereference (&comp -> prev -> next, MDL);
|
||||
if (comp -> next) {
|
||||
lease_reference (&comp -> prev -> next,
|
||||
comp -> next, MDL);
|
||||
lease_dereference (&comp -> next, MDL);
|
||||
}
|
||||
} else {
|
||||
lease_dereference (&comp -> pool -> leases, MDL);
|
||||
if (comp -> next) {
|
||||
lease_reference (&comp -> pool -> leases,
|
||||
comp -> next, MDL);
|
||||
}
|
||||
}
|
||||
if (comp -> next) {
|
||||
lease_dereference (&comp -> next -> prev, MDL);
|
||||
if (comp -> prev) {
|
||||
lease_reference (&comp -> next -> prev,
|
||||
comp -> prev, MDL);
|
||||
}
|
||||
}
|
||||
if (comp -> pool -> last_lease == comp) {
|
||||
lease_dereference (&comp -> pool -> last_lease, MDL);
|
||||
if (comp -> prev)
|
||||
lease_reference (&comp -> pool -> last_lease,
|
||||
comp -> prev, MDL);
|
||||
}
|
||||
if (comp -> prev)
|
||||
lease_dereference (&comp -> prev, MDL);
|
||||
if (comp -> next)
|
||||
lease_dereference (&comp -> next, MDL);
|
||||
|
||||
|
||||
/* If there's an expiry event on this lease, get rid of it
|
||||
(we may wind up putting it back, but we can't count on
|
||||
that here without too much additional complexity). */
|
||||
if (comp -> pool -> next_expiry == comp) {
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
lp = comp -> prev;
|
||||
#else
|
||||
for (lp = comp -> prev; lp; lp = lp -> prev)
|
||||
if (lp -> on_expiry)
|
||||
break;
|
||||
#endif
|
||||
if (lp
|
||||
#if !defined (FAILOVER_PROTOCOL)
|
||||
&& lp -> on_expiry
|
||||
#endif
|
||||
) {
|
||||
lease_dereference (&comp -> pool -> next_expiry, MDL);
|
||||
lease_reference (&comp -> pool -> next_expiry,
|
||||
lp, MDL);
|
||||
if (commit)
|
||||
add_timeout (lp -> ends,
|
||||
pool_timer, lp -> pool,
|
||||
(tvref_t)pool_reference,
|
||||
(tvunref_t)pool_dereference);
|
||||
} else {
|
||||
lease_dereference (&comp -> pool -> next_expiry, MDL);
|
||||
if (commit)
|
||||
cancel_timeout (pool_timer, comp -> pool);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the last insertion point... */
|
||||
if (comp == comp -> pool -> insertion_point ||
|
||||
!comp -> pool -> insertion_point) {
|
||||
lp = comp -> pool -> leases;
|
||||
} else {
|
||||
lp = comp -> pool -> insertion_point;
|
||||
}
|
||||
|
||||
if (!lp) {
|
||||
/* Nothing on the list yet? Just make comp the
|
||||
head of the list. */
|
||||
lease_reference (&comp -> pool -> leases, comp, MDL);
|
||||
if (comp -> pool -> last_lease) {
|
||||
lease_dereference (&comp -> pool -> last_lease, MDL);
|
||||
lease_reference (&comp -> pool -> last_lease,
|
||||
comp, MDL);
|
||||
}
|
||||
} else if (lp -> ends > lease -> ends) {
|
||||
/* Skip down the list until we run out of list
|
||||
or find a place for comp. */
|
||||
while (lp -> next && lp -> ends > lease -> ends) {
|
||||
lp = lp -> next;
|
||||
}
|
||||
if (lp -> ends > lease -> ends) {
|
||||
/* If we ran out of list, put comp at the end. */
|
||||
lease_reference (&lp -> next, comp, MDL);
|
||||
lease_reference (&comp -> prev, lp, MDL);
|
||||
if (comp -> pool -> last_lease)
|
||||
lease_dereference (&comp -> pool -> last_lease,
|
||||
MDL);
|
||||
lease_reference (&comp -> pool -> last_lease,
|
||||
comp, MDL);
|
||||
} else {
|
||||
/* If we didn't, put it between lp and
|
||||
the previous item on the list. */
|
||||
if (lp -> prev) {
|
||||
lease_reference (&comp -> prev,
|
||||
lp -> prev, MDL);
|
||||
lease_dereference (&lp -> prev -> next, MDL);
|
||||
lease_reference (&comp -> prev -> next,
|
||||
comp, MDL);
|
||||
lease_dereference (&lp -> prev, MDL);
|
||||
} else {
|
||||
if (comp -> pool -> leases)
|
||||
lease_dereference
|
||||
(&comp -> pool -> leases, MDL);
|
||||
lease_reference (&comp -> pool -> leases,
|
||||
comp, MDL);
|
||||
}
|
||||
lease_reference (&comp -> next, lp, MDL);
|
||||
lease_reference (&lp -> prev, comp, MDL);
|
||||
}
|
||||
} else {
|
||||
/* Skip up the list until we run out of list
|
||||
or find a place for comp. */
|
||||
while (lp -> prev && lp -> ends < lease -> ends) {
|
||||
lp = lp -> prev;
|
||||
}
|
||||
if (lp -> ends < lease -> ends) {
|
||||
/* If we ran out of list, put comp at the beginning. */
|
||||
lease_reference (&lp -> prev, comp, MDL);
|
||||
lease_reference (&comp -> next, lp, MDL);
|
||||
if (comp -> pool -> leases)
|
||||
lease_dereference (&comp -> pool -> leases,
|
||||
MDL);
|
||||
lease_reference (&comp -> pool -> leases, comp, MDL);
|
||||
} else {
|
||||
/* If we didn't, put it between lp and
|
||||
the next item on the list. */
|
||||
if (lp -> next) {
|
||||
lease_reference (&comp -> next,
|
||||
lp -> next, MDL);
|
||||
lease_dereference (&lp -> next -> prev, MDL);
|
||||
lease_reference (&lp -> next -> prev,
|
||||
comp, MDL);
|
||||
lease_dereference (&lp -> next, MDL);
|
||||
} else {
|
||||
/* XXX are we really supposed to
|
||||
XXX be doing this? */
|
||||
if (comp -> pool -> last_lease)
|
||||
lease_dereference
|
||||
(&comp -> pool -> last_lease,
|
||||
MDL);
|
||||
lease_reference (&comp -> pool -> last_lease,
|
||||
comp, MDL);
|
||||
}
|
||||
lease_reference (&comp -> prev, lp, MDL);
|
||||
lease_reference (&lp -> next, comp, MDL);
|
||||
}
|
||||
}
|
||||
if (comp -> pool -> insertion_point)
|
||||
lease_dereference (&comp -> pool -> insertion_point, MDL);
|
||||
lease_reference (&comp -> pool -> insertion_point, comp, MDL);
|
||||
#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;
|
||||
comp -> next_binding_state = lease -> next_binding_state;
|
||||
|
||||
/* If there's an expiry event on this lease, process it or
|
||||
queue it. */
|
||||
#if !defined (FAILOVER_PROTOCOL)
|
||||
if (comp -> on_expiry) {
|
||||
#endif
|
||||
if (comp -> ends <= cur_time && commit) {
|
||||
if (comp -> on_expiry) {
|
||||
execute_statements ((struct packet *)0, lease,
|
||||
(struct option_state *)0,
|
||||
(struct option_state *)0, /* XXX */
|
||||
&lease -> scope,
|
||||
comp -> on_expiry);
|
||||
executable_statement_dereference (&comp -> on_expiry,
|
||||
MDL);
|
||||
just_move_it:
|
||||
/* Figure out which queue it's on. */
|
||||
switch (comp -> binding_state) {
|
||||
case FTS_FREE:
|
||||
lq = &comp -> pool -> free;
|
||||
comp -> pool -> free_leases--;
|
||||
break;
|
||||
|
||||
case FTS_ACTIVE:
|
||||
case FTS_RESERVED:
|
||||
case FTS_BOOTP:
|
||||
lq = &comp -> pool -> active;
|
||||
break;
|
||||
|
||||
case FTS_EXPIRED:
|
||||
case FTS_RELEASED:
|
||||
case FTS_RESET:
|
||||
lq = &comp -> pool -> expired;
|
||||
break;
|
||||
|
||||
case FTS_ABANDONED:
|
||||
lq = &comp -> pool -> abandoned;
|
||||
break;
|
||||
|
||||
case FTS_BACKUP:
|
||||
lq = &comp -> pool -> backup;
|
||||
comp -> pool -> backup_leases--;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error ("Lease with bogus binding state: %d",
|
||||
comp -> binding_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No sense releasing a lease after it's expired. */
|
||||
if (comp -> on_release)
|
||||
executable_statement_dereference
|
||||
(&comp -> on_release, MDL);
|
||||
/* Remove the lease from its current place in its current
|
||||
timer sequence. */
|
||||
prev = (struct lease *)0;
|
||||
for (lp = *lq; lp; lp = lp -> next) {
|
||||
if (lp == comp)
|
||||
break;
|
||||
prev = lp;
|
||||
}
|
||||
|
||||
if (!lp) {
|
||||
log_error ("Lease with binding state %s not on its queue.",
|
||||
(comp -> binding_state < 1 &&
|
||||
comp -> binding_state < FTS_BOOTP)
|
||||
? "unknown"
|
||||
: binding_state_names [comp -> binding_state - 1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
lease_dereference (&prev -> next, MDL);
|
||||
if (comp -> next) {
|
||||
lease_reference (&prev -> next, comp -> next, MDL);
|
||||
lease_dereference (&comp -> next, MDL);
|
||||
}
|
||||
} else {
|
||||
/* If this is the next lease that will timeout on the
|
||||
pool, zap the old timeout and set the timeout on
|
||||
this pool to the time that the lease ends.
|
||||
lease_dereference (lq, MDL);
|
||||
if (comp -> next) {
|
||||
lease_reference (lq, comp -> next, MDL);
|
||||
lease_dereference (&comp -> next, MDL);
|
||||
}
|
||||
}
|
||||
|
||||
We do not actually set the timeout unless commit is
|
||||
true - we don't want to thrash the timer queue when
|
||||
reading the lease database. Instead, the database
|
||||
code calls the expiry event on each pool after
|
||||
reading in the lease file, and the expiry code sets
|
||||
the timer if there's anything left to expire after
|
||||
it's run any outstanding expiry events on the
|
||||
pool. */
|
||||
if (comp -> pool) {
|
||||
if (!comp -> pool -> next_expiry ||
|
||||
(comp -> ends <
|
||||
comp -> pool -> next_expiry -> ends)) {
|
||||
if (comp -> pool -> next_expiry)
|
||||
lease_dereference
|
||||
(&comp -> pool -> next_expiry,
|
||||
MDL);
|
||||
lease_reference
|
||||
(&comp -> pool -> next_expiry,
|
||||
comp, MDL);
|
||||
/* Make the state transition. */
|
||||
if (commit)
|
||||
add_timeout (comp -> ends,
|
||||
pool_timer,
|
||||
comp -> pool,
|
||||
process_state_transition (comp);
|
||||
|
||||
/* Figure out which queue it's going to. */
|
||||
switch (comp -> binding_state) {
|
||||
case FTS_FREE:
|
||||
lq = &comp -> pool -> free;
|
||||
comp -> pool -> free_leases++;
|
||||
comp -> sort_time = comp -> ends;
|
||||
break;
|
||||
|
||||
case FTS_ACTIVE:
|
||||
case FTS_RESERVED:
|
||||
case FTS_BOOTP:
|
||||
lq = &comp -> pool -> active;
|
||||
comp -> sort_time = comp -> ends;
|
||||
break;
|
||||
|
||||
case FTS_EXPIRED:
|
||||
case FTS_RELEASED:
|
||||
case FTS_RESET:
|
||||
lq = &comp -> pool -> expired;
|
||||
comp -> sort_time = comp -> ends;
|
||||
|
||||
break;
|
||||
|
||||
case FTS_ABANDONED:
|
||||
lq = &comp -> pool -> abandoned;
|
||||
comp -> sort_time = comp -> ends;
|
||||
break;
|
||||
|
||||
case FTS_BACKUP:
|
||||
lq = &comp -> pool -> backup;
|
||||
comp -> pool -> backup_leases++;
|
||||
comp -> sort_time = comp -> ends;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error ("Lease with bogus binding state: %d",
|
||||
comp -> binding_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Insertion sort the lease onto the appropriate queue. */
|
||||
prev = (struct lease *)0;
|
||||
for (lp = *lq; lp; lp = lp -> next) {
|
||||
if (lp -> sort_time > comp -> sort_time)
|
||||
break;
|
||||
prev = lp;
|
||||
}
|
||||
if (prev) {
|
||||
if (prev -> next) {
|
||||
lease_reference (&comp -> next, prev -> next, MDL);
|
||||
lease_dereference (&prev -> next, MDL);
|
||||
}
|
||||
lease_reference (&prev -> next, comp, MDL);
|
||||
} else {
|
||||
if (*lq) {
|
||||
lease_reference (&comp -> next, *lq, MDL);
|
||||
lease_dereference (lq, MDL);
|
||||
}
|
||||
lease_reference (lq, comp, MDL);
|
||||
}
|
||||
|
||||
/* If this is the next lease that will timeout on the pool,
|
||||
zap the old timeout and set the timeout on this pool to the
|
||||
time that the lease's next event will happen.
|
||||
|
||||
We do not actually set the timeout unless commit is true -
|
||||
we don't want to thrash the timer queue when reading the
|
||||
lease database. Instead, the database code calls the
|
||||
expiry event on each pool after reading in the lease file,
|
||||
and the expiry code sets the timer if there's anything left
|
||||
to expire after it's run any outstanding expiry events on
|
||||
the pool. */
|
||||
if (commit &&
|
||||
comp -> sort_time != MIN_TIME &&
|
||||
comp -> sort_time < cur_time &&
|
||||
comp -> sort_time < comp -> pool -> next_event_time) {
|
||||
comp -> pool -> next_event_time = comp -> sort_time;
|
||||
add_timeout (comp -> pool -> next_event_time,
|
||||
pool_timer, comp -> pool,
|
||||
(tvref_t)pool_reference,
|
||||
(tvunref_t)
|
||||
pool_dereference);
|
||||
} else if (comp -> ends ==
|
||||
comp -> pool -> next_expiry -> ends) {
|
||||
/* If there are other leases that expire at
|
||||
the same time as comp, we need to make
|
||||
sure that we have the one that appears
|
||||
last on the list that needs an expiry
|
||||
event - otherwise we'll miss expiry
|
||||
events until the server restarts. */
|
||||
struct lease *foo;
|
||||
struct lease *install = comp;
|
||||
for (foo = comp;
|
||||
foo && foo -> ends == comp -> ends;
|
||||
foo = foo -> next) {
|
||||
#if !defined (FAILOVER_PROTOCOL)
|
||||
if (foo -> on_expiry)
|
||||
#endif
|
||||
install = foo;
|
||||
(tvunref_t)pool_dereference);
|
||||
}
|
||||
lease_dereference
|
||||
(&comp -> pool -> next_expiry,
|
||||
MDL);
|
||||
lease_reference
|
||||
(&comp -> pool -> next_expiry,
|
||||
install, MDL);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !defined (FAILOVER_PROTOCOL)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return zero if we didn't commit the lease to permanent storage;
|
||||
nonzero if we did. */
|
||||
return commit && write_lease (comp) && commit_leases ()
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
&& (!propogate || dhcp_failover_queue_update (comp))
|
||||
&& (!propogate ||
|
||||
dhcp_failover_queue_update (comp, pimmediate))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
void process_state_transition (struct lease *lease)
|
||||
{
|
||||
/* If the lease was active and is now no longer active, but isn't
|
||||
released, then it just expired, so do the expiry event. */
|
||||
if (lease -> next_binding_state != lease -> binding_state &&
|
||||
(lease -> binding_state == FTS_ACTIVE ||
|
||||
lease -> binding_state == FTS_BOOTP ||
|
||||
lease -> binding_state == FTS_RESERVED) &&
|
||||
lease -> next_binding_state != FTS_RELEASED) {
|
||||
if (lease -> on_expiry) {
|
||||
execute_statements ((struct packet *)0, lease,
|
||||
(struct option_state *)0,
|
||||
(struct option_state *)0, /* XXX */
|
||||
&lease -> scope,
|
||||
lease -> on_expiry);
|
||||
executable_statement_dereference (&lease -> on_expiry,
|
||||
MDL);
|
||||
}
|
||||
|
||||
/* No sense releasing a lease after it's expired. */
|
||||
if (lease -> on_release)
|
||||
executable_statement_dereference (&lease -> on_release,
|
||||
MDL);
|
||||
/* Send the expiry time to the peer. */
|
||||
lease -> tstp = lease -> ends;
|
||||
}
|
||||
|
||||
/* If the lease was active and is now released, do the release
|
||||
event. */
|
||||
if ((lease -> binding_state == FTS_ACTIVE ||
|
||||
lease -> binding_state == FTS_BOOTP ||
|
||||
lease -> binding_state == FTS_RESERVED) &&
|
||||
lease -> next_binding_state == FTS_RELEASED) {
|
||||
if (lease -> on_release) {
|
||||
execute_statements ((struct packet *)0, lease,
|
||||
(struct option_state *)0,
|
||||
(struct option_state *)0, /* XXX */
|
||||
&lease -> scope,
|
||||
lease -> on_release);
|
||||
executable_statement_dereference (&lease -> on_release,
|
||||
MDL);
|
||||
}
|
||||
|
||||
/* A released lease can't expire. */
|
||||
if (lease -> on_expiry)
|
||||
executable_statement_dereference (&lease -> on_expiry,
|
||||
MDL);
|
||||
|
||||
/* Send the release time (should be == cur_time) to the
|
||||
peer. */
|
||||
lease -> tstp = lease -> ends;
|
||||
}
|
||||
|
||||
lease -> binding_state = lease -> next_binding_state;
|
||||
}
|
||||
|
||||
/* Copy the contents of one lease into another, correctly maintaining
|
||||
reference counts. */
|
||||
int lease_copy (struct lease **lp,
|
||||
@ -1242,6 +1190,8 @@ int lease_copy (struct lease **lp,
|
||||
lt -> tstp = lease -> tstp;
|
||||
lt -> tsfp = lease -> tsfp;
|
||||
lt -> cltt = lease -> cltt;
|
||||
lt -> binding_state = lease -> binding_state;
|
||||
lt -> next_binding_state = lease -> next_binding_state;
|
||||
status = lease_reference (lp, lt, file, line);
|
||||
lease_dereference (<, MDL);
|
||||
return status == ISC_R_SUCCESS;
|
||||
@ -1252,8 +1202,6 @@ void release_lease (lease, packet)
|
||||
struct lease *lease;
|
||||
struct packet *packet;
|
||||
{
|
||||
struct lease *lt;
|
||||
|
||||
/* If there are statements to execute when the lease is
|
||||
released, execute them. */
|
||||
if (lease -> on_release) {
|
||||
@ -1272,21 +1220,26 @@ void release_lease (lease, packet)
|
||||
executable_statement_dereference (&lease -> on_expiry, MDL);
|
||||
|
||||
if (lease -> ends > cur_time) {
|
||||
if (!lease_copy (<, lease, MDL))
|
||||
return;
|
||||
|
||||
if (lt -> on_commit)
|
||||
executable_statement_dereference (< -> on_commit,
|
||||
if (lease -> on_commit)
|
||||
executable_statement_dereference (&lease -> on_commit,
|
||||
MDL);
|
||||
|
||||
/* Blow away any bindings. */
|
||||
lt -> scope.bindings = (struct binding *)0;
|
||||
|
||||
lt -> ends = cur_time;
|
||||
if (lt -> billing_class)
|
||||
class_dereference (< -> billing_class, MDL);
|
||||
supersede_lease (lease, lt, 1, 1);
|
||||
lease_dereference (<, MDL);
|
||||
/* XXX free them?!? */
|
||||
lease -> scope.bindings = (struct binding *)0;
|
||||
lease -> ends = cur_time;
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
if (lease -> pool && lease -> pool -> failover_peer) {
|
||||
lease -> next_binding_state = FTS_RELEASED;
|
||||
} else {
|
||||
lease -> next_binding_state = FTS_FREE;
|
||||
}
|
||||
#else
|
||||
lease -> next_binding_state = FTS_FREE;
|
||||
#endif
|
||||
if (lease -> billing_class)
|
||||
class_dereference (&lease -> billing_class, MDL);
|
||||
supersede_lease (lease, (struct lease *)0, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1299,7 +1252,6 @@ void abandon_lease (lease, message)
|
||||
{
|
||||
struct lease *lt = (struct lease *)0;
|
||||
|
||||
lease -> flags |= ABANDONED_LEASE;
|
||||
if (!lease_copy (<, lease, MDL))
|
||||
return;
|
||||
|
||||
@ -1312,8 +1264,9 @@ void abandon_lease (lease, message)
|
||||
|
||||
/* Blow away any bindings. */
|
||||
lt -> scope.bindings = (struct binding *)0;
|
||||
|
||||
lt -> ends = cur_time; /* XXX */
|
||||
lt -> next_binding_state = FTS_ABANDONED;
|
||||
|
||||
log_error ("Abandoning IP address %s: %s",
|
||||
piaddr (lease -> ip_addr), message);
|
||||
lt -> hardware_addr.hlen = 0;
|
||||
@ -1324,7 +1277,7 @@ void abandon_lease (lease, message)
|
||||
lt -> uid_max = 0;
|
||||
if (lt -> billing_class)
|
||||
class_dereference (< -> billing_class, MDL);
|
||||
supersede_lease (lease, lt, 1, 1);
|
||||
supersede_lease (lease, lt, 1, 1, 1);
|
||||
lease_dereference (<, MDL);
|
||||
}
|
||||
|
||||
@ -1349,6 +1302,15 @@ void dissociate_lease (lease)
|
||||
/* Blow away any bindings. */
|
||||
lt -> scope.bindings = (struct binding *)0;
|
||||
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
if (lease -> pool && lease -> pool -> failover_peer) {
|
||||
lt -> next_binding_state = FTS_RESET;
|
||||
} else {
|
||||
lt -> next_binding_state = FTS_FREE;
|
||||
}
|
||||
#else
|
||||
lt -> next_binding_state = FTS_FREE;
|
||||
#endif
|
||||
lt -> ends = cur_time; /* XXX */
|
||||
lt -> hardware_addr.hlen = 0;
|
||||
if (lt -> uid != lt -> uid_buf)
|
||||
@ -1358,7 +1320,7 @@ void dissociate_lease (lease)
|
||||
lt -> uid_max = 0;
|
||||
if (lt -> billing_class)
|
||||
class_dereference (< -> billing_class, MDL);
|
||||
supersede_lease (lease, lt, 1, 1);
|
||||
supersede_lease (lease, lt, 1, 1, 1);
|
||||
lease_dereference (<, MDL);
|
||||
}
|
||||
|
||||
@ -1367,72 +1329,75 @@ void pool_timer (vpool)
|
||||
void *vpool;
|
||||
{
|
||||
struct pool *pool;
|
||||
struct lease *lease;
|
||||
struct lease *lt = (struct lease *)0;
|
||||
struct lease *next = (struct lease *)0;
|
||||
struct lease *lease = (struct lease *)0;
|
||||
struct lease **lptr [5];
|
||||
TIME next_expiry = MAX_TIME;
|
||||
int i;
|
||||
|
||||
pool = (struct pool *)vpool;
|
||||
for (lease = pool -> next_expiry; lease; lease = lease -> prev) {
|
||||
/* Stop processing when we get to the first lease that has not
|
||||
yet expired. */
|
||||
if (lease -> ends > cur_time)
|
||||
|
||||
#define FREE_LEASES 0
|
||||
lptr [FREE_LEASES] = &pool -> free;
|
||||
#define ACTIVE_LEASES 1
|
||||
lptr [ACTIVE_LEASES] = &pool -> active;
|
||||
#define EXPIRED_LEASES 2
|
||||
lptr [EXPIRED_LEASES] = &pool -> expired;
|
||||
#define ABANDONED_LEASES 3
|
||||
lptr [ABANDONED_LEASES] = &pool -> abandoned;
|
||||
#define BACKUP_LEASES 4
|
||||
lptr [BACKUP_LEASES] = &pool -> backup;
|
||||
|
||||
for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
|
||||
/* If there's nothing on the queue, skip it. */
|
||||
if (!*(lptr [i]))
|
||||
continue;
|
||||
|
||||
lease_reference (&lease, *(lptr [i]), MDL);
|
||||
|
||||
while (lease) {
|
||||
/* Remember the next lease in the list. */
|
||||
if (next)
|
||||
lease_dereference (&next, MDL);
|
||||
if (lease -> next)
|
||||
lease_reference (&next, lease -> next, MDL);
|
||||
|
||||
/* If we've run out of things to expire on this list,
|
||||
stop. */
|
||||
if (lease -> sort_time > cur_time) {
|
||||
if (lease -> sort_time < next_expiry)
|
||||
next_expiry = lease -> sort_time;
|
||||
break;
|
||||
|
||||
/* Skip entries that aren't set to expire. */
|
||||
if (lease -> on_expiry) {
|
||||
/* Okay, the current lease needs to expire, so
|
||||
do it. */
|
||||
execute_statements ((struct packet *)0, lease,
|
||||
(struct option_state *)0,
|
||||
(struct option_state *)0, /* XXX */
|
||||
&lease -> scope,
|
||||
lease -> on_expiry);
|
||||
if (lease -> on_expiry)
|
||||
executable_statement_dereference
|
||||
(&lease -> on_expiry, MDL);
|
||||
}
|
||||
|
||||
/* If there's an on_release event, blow it away. */
|
||||
if (lease -> on_release)
|
||||
executable_statement_dereference (&lease -> on_release,
|
||||
MDL);
|
||||
/* If there is a pending state change, and
|
||||
this lease has gotten to the time when the
|
||||
state change should happen, just call
|
||||
supersede_lease on it to make the change
|
||||
happen. */
|
||||
if (lease -> next_binding_state !=
|
||||
lease -> binding_state)
|
||||
supersede_lease (lease,
|
||||
(struct lease *)0, 1, 1, 1);
|
||||
|
||||
/* There are two problems with writing the lease out here.
|
||||
|
||||
The first is that we've just done a commit, and the write
|
||||
may fail, in which case we will redo the operation. If the
|
||||
operation is not idempotent, we're in trouble here. I have
|
||||
no proposed solution for this problem - make the event
|
||||
idempotent, or make sure that it at least isn't harmful to
|
||||
do it twice.
|
||||
|
||||
The second is that if we just read in the lease file and ran
|
||||
all the expiry events, we're going to rewrite all expiring
|
||||
leases twice. There's no real answer for this - if we
|
||||
postpone writing until we've expired all leases, we're
|
||||
increasing the window to lose as described above. I guess a
|
||||
dirty bit on the lease would work. Hm. */
|
||||
if (!write_lease (lease)) {
|
||||
log_error ("Error updating lease %s after expiry",
|
||||
piaddr (lease -> ip_addr));
|
||||
lease_dereference (&lease, MDL);
|
||||
if (next)
|
||||
lease_reference (&lease, next, MDL);
|
||||
}
|
||||
if (!commit_leases ()) {
|
||||
log_error ("Error committing after writing lease %s",
|
||||
piaddr (lease -> ip_addr));
|
||||
if (next)
|
||||
lease_dereference (&next, MDL);
|
||||
if (lease)
|
||||
lease_dereference (&lease, MDL);
|
||||
}
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
if (lease -> flags & PEER_IS_OWNER)
|
||||
pool -> peer_leases++;
|
||||
else
|
||||
pool -> local_leases++;
|
||||
#endif
|
||||
}
|
||||
if (pool -> next_expiry)
|
||||
lease_dereference (&pool -> next_expiry, MDL);
|
||||
if (lease) {
|
||||
lease_reference (&pool -> next_expiry, lease, MDL);
|
||||
add_timeout (lease -> ends, pool_timer, pool,
|
||||
if (next_expiry != MAX_TIME) {
|
||||
pool -> next_event_time = next_expiry;
|
||||
add_timeout (pool -> next_event_time, pool_timer, pool,
|
||||
(tvref_t)pool_reference,
|
||||
(tvunref_t)pool_dereference);
|
||||
}
|
||||
} else
|
||||
pool -> next_event_time = MIN_TIME;
|
||||
|
||||
}
|
||||
|
||||
/* Locate the lease associated with a given IP address... */
|
||||
@ -1618,6 +1583,7 @@ void write_leases ()
|
||||
struct hash_bucket *hb;
|
||||
int i;
|
||||
int num_written;
|
||||
struct lease **lptr [5];
|
||||
|
||||
/* Write all the dynamically-created group declarations. */
|
||||
if (group_name_hash) {
|
||||
@ -1683,18 +1649,25 @@ void write_leases ()
|
||||
num_written = 0;
|
||||
for (s = shared_networks; s; s = s -> next) {
|
||||
for (p = s -> pools; p; p = p -> next) {
|
||||
for (l = p -> leases; l; l = l -> next) {
|
||||
lptr [FREE_LEASES] = &p -> free;
|
||||
lptr [ACTIVE_LEASES] = &p -> active;
|
||||
lptr [EXPIRED_LEASES] = &p -> expired;
|
||||
lptr [ABANDONED_LEASES] = &p -> abandoned;
|
||||
lptr [BACKUP_LEASES] = &p -> backup;
|
||||
|
||||
for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
|
||||
for (l = *(lptr [i]); l; l = l -> next) {
|
||||
if (l -> hardware_addr.hlen ||
|
||||
l -> uid_len ||
|
||||
(l -> flags & ABANDONED_LEASE)) {
|
||||
(l -> binding_state != FTS_FREE)) {
|
||||
if (!write_lease (l))
|
||||
log_fatal ("Can't rewrite %s",
|
||||
"lease database");
|
||||
log_fatal ("Can't rewrite lease database");
|
||||
num_written++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log_info ("Wrote %d leases to leases file.", num_written);
|
||||
if (!commit_leases ())
|
||||
log_fatal ("Can't commit leases to new database: %m");
|
||||
@ -1712,6 +1685,7 @@ void expire_all_pools ()
|
||||
struct hash_bucket *hb;
|
||||
int i;
|
||||
struct lease *l;
|
||||
struct lease **lptr [5];
|
||||
|
||||
/* Loop through each pool in each shared network and call the
|
||||
expiry routine on the pool. */
|
||||
@ -1721,21 +1695,29 @@ void expire_all_pools ()
|
||||
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
p -> lease_count = 0;
|
||||
p -> local_leases = 0;
|
||||
p -> peer_leases = 0;
|
||||
p -> free_leases = 0;
|
||||
p -> backup_leases = 0;
|
||||
|
||||
for (l = p -> leases; l; l = l -> next) {
|
||||
lptr [FREE_LEASES] = &p -> free;
|
||||
lptr [ACTIVE_LEASES] = &p -> active;
|
||||
lptr [EXPIRED_LEASES] = &p -> expired;
|
||||
lptr [ABANDONED_LEASES] = &p -> abandoned;
|
||||
lptr [BACKUP_LEASES] = &p -> backup;
|
||||
|
||||
for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
|
||||
for (l = *(lptr [i]); 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 (l -> binding_state == FTS_FREE)
|
||||
p -> free_leases++;
|
||||
else if (l -> binding_state == FTS_BACKUP)
|
||||
p -> backup_leases++;
|
||||
}
|
||||
if (p -> failover_peer &&
|
||||
l -> tstp > l -> tsfp &&
|
||||
!(l -> flags & ON_UPDATE_QUEUE))
|
||||
dhcp_failover_queue_update (l);
|
||||
dhcp_failover_queue_update (l, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1748,6 +1730,8 @@ void dump_subnets ()
|
||||
struct shared_network *s;
|
||||
struct subnet *n;
|
||||
struct pool *p;
|
||||
struct lease **lptr [5];
|
||||
int i;
|
||||
|
||||
log_info ("Subnets:");
|
||||
for (n = subnets; n; n = n -> next_subnet) {
|
||||
@ -1759,11 +1743,17 @@ void dump_subnets ()
|
||||
for (s = shared_networks; s; s = s -> next) {
|
||||
log_info (" %s", s -> name);
|
||||
for (p = s -> pools; p; p = p -> next) {
|
||||
for (l = p -> leases; l; l = l -> next) {
|
||||
lptr [FREE_LEASES] = &p -> free;
|
||||
lptr [ACTIVE_LEASES] = &p -> active;
|
||||
lptr [EXPIRED_LEASES] = &p -> expired;
|
||||
lptr [ABANDONED_LEASES] = &p -> abandoned;
|
||||
lptr [BACKUP_LEASES] = &p -> backup;
|
||||
|
||||
for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
|
||||
for (l = *(lptr [i]); l; l = l -> next) {
|
||||
print_lease (l);
|
||||
}
|
||||
log_debug ("Last Lease:");
|
||||
print_lease (p -> last_lease);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: omapi.c,v 1.28 2000/05/16 23:03:48 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: omapi.c,v 1.29 2000/06/02 21:27:20 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -179,27 +179,21 @@ isc_result_t dhcp_lease_set_value (omapi_object_t *h,
|
||||
lease = (struct lease *)h;
|
||||
|
||||
/* We're skipping a lot of things it might be interesting to
|
||||
set - for now, we just make it possible to whack the abandoned
|
||||
flag. */
|
||||
if (!omapi_ds_strcmp (name, "abandoned")) {
|
||||
int bar;
|
||||
set - for now, we just make it possible to whack the state. */
|
||||
if (!omapi_ds_strcmp (name, "state")) {
|
||||
unsigned long bar;
|
||||
status = omapi_get_int_value (&bar, value);
|
||||
if (status != ISC_R_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (value -> type == omapi_datatype_int)
|
||||
bar = value -> u.integer;
|
||||
else if (value -> type == omapi_datatype_data &&
|
||||
value -> u.buffer.len == sizeof (int)) {
|
||||
memcpy (&bar, value -> u.buffer.value, sizeof bar);
|
||||
/* No need to byte-swap here. */
|
||||
} else
|
||||
if (bar < 1 || bar > FTS_BOOTP)
|
||||
return ISC_R_INVALIDARG;
|
||||
|
||||
foo = lease -> flags;
|
||||
if (bar)
|
||||
lease -> flags |= ABANDONED_LEASE;
|
||||
else
|
||||
lease -> flags &= ~ABANDONED_LEASE;
|
||||
if (foo != lease -> flags)
|
||||
if (lease -> binding_state != bar) {
|
||||
lease -> next_binding_state = bar;
|
||||
if (supersede_lease (lease, 0, 1, 1, 1))
|
||||
return ISC_R_SUCCESS;
|
||||
return ISC_R_IOERROR;
|
||||
}
|
||||
return ISC_R_UNCHANGED;
|
||||
}
|
||||
|
||||
@ -226,14 +220,9 @@ isc_result_t dhcp_lease_get_value (omapi_object_t *h, omapi_object_t *id,
|
||||
return ISC_R_INVALIDARG;
|
||||
lease = (struct lease *)h;
|
||||
|
||||
if (!omapi_ds_strcmp (name, "abandoned"))
|
||||
if (!omapi_ds_strcmp (name, "state"))
|
||||
return omapi_make_int_value (value, name,
|
||||
(lease -> flags &
|
||||
ABANDONED_LEASE) ? 1 : 0, MDL);
|
||||
else if (!omapi_ds_strcmp (name, "bootpp"))
|
||||
return omapi_make_int_value (value, name,
|
||||
(lease -> flags &
|
||||
BOOTP_LEASE) ? 1 : 0, MDL);
|
||||
(int)lease -> binding_state, MDL);
|
||||
else if (!omapi_ds_strcmp (name, "ip-address"))
|
||||
return omapi_make_const_value (value, name,
|
||||
lease -> ip_addr.iabuf,
|
||||
@ -362,7 +351,7 @@ isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
|
||||
return ISC_R_INVALIDARG;
|
||||
if (!write_lease (lease) || !commit_leases ()
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
|| !dhcp_failover_queue_update (lease)
|
||||
|| !dhcp_failover_queue_update (lease, 1)
|
||||
#endif
|
||||
) {
|
||||
return ISC_R_IOERROR;
|
||||
@ -395,26 +384,13 @@ isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
|
||||
|
||||
/* Write out all the values. */
|
||||
|
||||
status = omapi_connection_put_name (c, "abandoned");
|
||||
status = omapi_connection_put_name (c, "state");
|
||||
if (status != ISC_R_SUCCESS)
|
||||
return status;
|
||||
status = omapi_connection_put_uint32 (c, sizeof (int));
|
||||
if (status != ISC_R_SUCCESS)
|
||||
return status;
|
||||
status = omapi_connection_put_uint32 (c, (lease -> flags &
|
||||
ABANDONED_LEASE) ? 1U : 0U);
|
||||
if (status != ISC_R_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = omapi_connection_put_name (c, "bootpp");
|
||||
if (status != ISC_R_SUCCESS)
|
||||
return status;
|
||||
status = omapi_connection_put_uint32 (c, sizeof (int));
|
||||
if (status != ISC_R_SUCCESS)
|
||||
return status;
|
||||
status = omapi_connection_put_uint32 (c, ((unsigned)
|
||||
((lease -> flags &
|
||||
BOOTP_LEASE) ? 1 : 0)));
|
||||
status = omapi_connection_put_uint32 (c, lease -> binding_state);
|
||||
if (status != ISC_R_SUCCESS)
|
||||
return status;
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: stables.c,v 1.12 2000/05/16 23:03:49 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: stables.c,v 1.13 2000/06/02 21:27:21 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -176,6 +176,12 @@ const char *dhcp_flink_state_names [] = {
|
||||
};
|
||||
#endif /* FAILOVER_PROTOCOL */
|
||||
|
||||
/* Failover binding state names. These are used even if there is no
|
||||
failover protocol support. */
|
||||
const char *binding_state_names [] = {
|
||||
"free", "active", "expired", "released", "abandoned",
|
||||
"reset", "backup", "reserved", "bootp" };
|
||||
|
||||
struct universe agent_universe;
|
||||
struct option agent_options [256] = {
|
||||
{ "pad", "", &agent_universe, 0 },
|
||||
|
Loading…
x
Reference in New Issue
Block a user