mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-29 21:38:10 +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
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -291,7 +291,7 @@ void parse_client_statement (cfile, ip, config)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
config -> auth_policy = policy;
|
config -> auth_policy = policy;
|
||||||
} else if (token != BOOTP) {
|
} else if (token != TOKEN_BOOTP) {
|
||||||
if (policy != P_PREFER &&
|
if (policy != P_PREFER &&
|
||||||
policy != P_IGNORE &&
|
policy != P_IGNORE &&
|
||||||
policy != P_ACCEPT) {
|
policy != P_ACCEPT) {
|
||||||
@ -919,7 +919,7 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp)
|
|||||||
parse_warn (cfile, "unknown key %s", val);
|
parse_warn (cfile, "unknown key %s", val);
|
||||||
parse_semi (cfile);
|
parse_semi (cfile);
|
||||||
break;
|
break;
|
||||||
case BOOTP:
|
case TOKEN_BOOTP:
|
||||||
lease -> is_bootp = 1;
|
lease -> is_bootp = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char ocopyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -779,7 +779,7 @@ void bind_lease (client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write out the new lease. */
|
/* 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. */
|
/* Replace the old active lease with the new one. */
|
||||||
if (client -> active)
|
if (client -> active)
|
||||||
@ -1561,18 +1561,50 @@ void send_release (cpp)
|
|||||||
struct client_state *client = cpp;
|
struct client_state *client = cpp;
|
||||||
|
|
||||||
int result;
|
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",
|
log_info ("DHCPRELEASE on %s to %s port %d",
|
||||||
client -> name ? client -> name : client -> interface -> name,
|
client -> name ? client -> name : client -> interface -> name,
|
||||||
inet_ntoa (sockaddr_broadcast.sin_addr),
|
inet_ntoa (destination.sin_addr),
|
||||||
ntohs (sockaddr_broadcast.sin_port));
|
ntohs (destination.sin_port));
|
||||||
|
|
||||||
/* Send out a packet. */
|
if (fallback_interface)
|
||||||
result = send_packet (client -> interface, (struct packet *)0,
|
result = send_packet (fallback_interface,
|
||||||
&client -> packet,
|
(struct packet *)0,
|
||||||
client -> packet_length,
|
&client -> packet,
|
||||||
inaddr_any, &sockaddr_broadcast,
|
client -> packet_length,
|
||||||
(struct hardware *)0);
|
from, &destination,
|
||||||
|
(struct hardware *)0);
|
||||||
|
else
|
||||||
|
/* Send out a packet. */
|
||||||
|
result = send_packet (client -> interface, (struct packet *)0,
|
||||||
|
&client -> packet,
|
||||||
|
client -> packet_length,
|
||||||
|
from, &destination,
|
||||||
|
(struct hardware *)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void make_client_options (client, lease, type, sid, rip, prl, op)
|
void make_client_options (client, lease, type, sid, rip, prl, op)
|
||||||
@ -1926,11 +1958,11 @@ void rewrite_client_leases ()
|
|||||||
for (ip = interfaces; ip; ip = ip -> next) {
|
for (ip = interfaces; ip; ip = ip -> next) {
|
||||||
for (client = ip -> client; client; client = client -> next) {
|
for (client = ip -> client; client; client = client -> next) {
|
||||||
for (lp = client -> leases; lp; lp = lp -> 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)
|
if (client -> active)
|
||||||
write_client_lease (client,
|
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 (ip = dummy_interfaces; ip; ip = ip -> next) {
|
||||||
for (client = ip -> client; client; client = client -> next) {
|
for (client = ip -> client; client; client = client -> next) {
|
||||||
for (lp = client -> leases; lp; lp = lp -> 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)
|
if (client -> active)
|
||||||
write_client_lease (client,
|
write_client_lease (client,
|
||||||
client -> active, 1);
|
client -> active, 1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fflush (leaseFile);
|
fflush (leaseFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_client_lease (client, lease, rewrite)
|
int write_client_lease (client, lease, rewrite, makesure)
|
||||||
struct client_state *client;
|
struct client_state *client;
|
||||||
struct client_lease *lease;
|
struct client_lease *lease;
|
||||||
int rewrite;
|
int rewrite;
|
||||||
|
int makesure;
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct tm *t;
|
struct tm *t;
|
||||||
@ -1960,6 +1993,7 @@ void write_client_lease (client, lease, rewrite)
|
|||||||
struct option_cache *oc;
|
struct option_cache *oc;
|
||||||
struct data_string ds;
|
struct data_string ds;
|
||||||
pair *hash;
|
pair *hash;
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
if (!rewrite) {
|
if (!rewrite) {
|
||||||
if (leases_written++ > 20) {
|
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
|
/* If the lease came from the config file, we don't need to stash
|
||||||
a copy in the lease database. */
|
a copy in the lease database. */
|
||||||
if (lease -> is_static)
|
if (lease -> is_static)
|
||||||
return;
|
return 1;
|
||||||
|
|
||||||
if (!leaseFile) { /* XXX */
|
if (!leaseFile) { /* XXX */
|
||||||
leaseFile = fopen (path_dhclient_db, "w");
|
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);
|
log_fatal ("can't create %s: %m", path_dhclient_db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
fprintf (leaseFile, "lease {\n");
|
fprintf (leaseFile, "lease {\n");
|
||||||
if (lease -> is_bootp)
|
if (lease -> is_bootp)
|
||||||
fprintf (leaseFile, " bootp;\n");
|
fprintf (leaseFile, " bootp;\n");
|
||||||
@ -1997,6 +2032,10 @@ void write_client_lease (client, lease, rewrite)
|
|||||||
if (lease -> medium)
|
if (lease -> medium)
|
||||||
fprintf (leaseFile, " medium \"%s\";\n",
|
fprintf (leaseFile, " medium \"%s\";\n",
|
||||||
lease -> medium -> string);
|
lease -> medium -> string);
|
||||||
|
if (errno != 0) {
|
||||||
|
errors++;
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
|
||||||
memset (&ds, 0, sizeof ds);
|
memset (&ds, 0, sizeof ds);
|
||||||
|
|
||||||
@ -2018,6 +2057,10 @@ void write_client_lease (client, lease, rewrite)
|
|||||||
(oc -> option -> code,
|
(oc -> option -> code,
|
||||||
ds.data, ds.len, 1, 1));
|
ds.data, ds.len, 1, 1));
|
||||||
data_string_forget (&ds, MDL);
|
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);
|
t -> tm_hour, t -> tm_min, t -> tm_sec);
|
||||||
fprintf (leaseFile, "}\n");
|
fprintf (leaseFile, "}\n");
|
||||||
fflush (leaseFile);
|
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
|
/* Variables holding name of script and file pointer for writing to
|
||||||
@ -2357,6 +2411,9 @@ void client_location_changed ()
|
|||||||
void do_release(client)
|
void do_release(client)
|
||||||
struct client_state *client;
|
struct client_state *client;
|
||||||
{
|
{
|
||||||
|
struct data_string ds;
|
||||||
|
struct option_cache *oc;
|
||||||
|
|
||||||
/* make_request doesn't initialize xid because it normally comes
|
/* make_request doesn't initialize xid because it normally comes
|
||||||
from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
|
from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
|
||||||
so pick an xid now. */
|
so pick an xid now. */
|
||||||
@ -2367,7 +2424,25 @@ void do_release(client)
|
|||||||
/* Make a DHCPRELEASE packet, and set appropriate per-interface
|
/* Make a DHCPRELEASE packet, and set appropriate per-interface
|
||||||
flags. */
|
flags. */
|
||||||
make_release (client, client -> active);
|
make_release (client, client -> active);
|
||||||
client -> destination = iaddr_broadcast;
|
|
||||||
|
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 -> first_sending = cur_time;
|
||||||
client -> interval = client -> config -> initial_interval;
|
client -> interval = client -> config -> initial_interval;
|
||||||
|
|
||||||
@ -2376,13 +2451,8 @@ void do_release(client)
|
|||||||
|
|
||||||
/* Send out the first and only DHCPRELEASE packet. */
|
/* Send out the first and only DHCPRELEASE packet. */
|
||||||
send_release (client);
|
send_release (client);
|
||||||
}
|
|
||||||
|
|
||||||
/* remove the timeouts for this client */
|
/* Do the client script RELEASE operation. */
|
||||||
cancel_timeout (NULL, client);
|
|
||||||
|
|
||||||
/* if there was no lease, nothing to "do" */
|
|
||||||
if (client -> active) {
|
|
||||||
script_init (client,
|
script_init (client,
|
||||||
"RELEASE", (struct string_list *)0);
|
"RELEASE", (struct string_list *)0);
|
||||||
if (client -> alias)
|
if (client -> alias)
|
||||||
@ -2390,6 +2460,9 @@ void do_release(client)
|
|||||||
client -> alias);
|
client -> alias);
|
||||||
script_go (client);
|
script_go (client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* remove the timeouts for this client */
|
||||||
|
cancel_timeout (0, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dhclient_interface_shutdown_hook (struct interface_info *interface)
|
int dhclient_interface_shutdown_hook (struct interface_info *interface)
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -503,7 +503,7 @@ static enum dhcp_token intern (atom, dfv)
|
|||||||
if (!strcasecmp (atom + 1, "lgorithm"))
|
if (!strcasecmp (atom + 1, "lgorithm"))
|
||||||
return ALGORITHM;
|
return ALGORITHM;
|
||||||
if (!strcasecmp (atom + 1, "bandoned"))
|
if (!strcasecmp (atom + 1, "bandoned"))
|
||||||
return ABANDONED;
|
return TOKEN_ABANDONED;
|
||||||
if (!strcasecmp (atom + 1, "dd"))
|
if (!strcasecmp (atom + 1, "dd"))
|
||||||
return TOKEN_ADD;
|
return TOKEN_ADD;
|
||||||
if (!strcasecmp (atom + 1, "ll"))
|
if (!strcasecmp (atom + 1, "ll"))
|
||||||
@ -514,14 +514,20 @@ static enum dhcp_token intern (atom, dfv)
|
|||||||
return ARRAY;
|
return ARRAY;
|
||||||
if (!strcasecmp (atom + 1, "ddress"))
|
if (!strcasecmp (atom + 1, "ddress"))
|
||||||
return ADDRESS;
|
return ADDRESS;
|
||||||
|
if (!strcasecmp (atom + 1, "ctive"))
|
||||||
|
return TOKEN_ACTIVE;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
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"))
|
if (!strcasecmp (atom + 1, "inary-to-ascii"))
|
||||||
return BINARY_TO_ASCII;
|
return BINARY_TO_ASCII;
|
||||||
if (!strcasecmp (atom + 1, "ackoff-cutoff"))
|
if (!strcasecmp (atom + 1, "ackoff-cutoff"))
|
||||||
return BACKOFF_CUTOFF;
|
return BACKOFF_CUTOFF;
|
||||||
if (!strcasecmp (atom + 1, "ootp"))
|
|
||||||
return BOOTP;
|
|
||||||
if (!strcasecmp (atom + 1, "ooting"))
|
if (!strcasecmp (atom + 1, "ooting"))
|
||||||
return BOOTING;
|
return BOOTING;
|
||||||
if (!strcasecmp (atom + 1, "oot-unknown-clients"))
|
if (!strcasecmp (atom + 1, "oot-unknown-clients"))
|
||||||
@ -575,7 +581,7 @@ static enum dhcp_token intern (atom, dfv)
|
|||||||
if (!strcasecmp (atom + 1, "eny"))
|
if (!strcasecmp (atom + 1, "eny"))
|
||||||
return DENY;
|
return DENY;
|
||||||
if (!strcasecmp (atom + 1, "eleted"))
|
if (!strcasecmp (atom + 1, "eleted"))
|
||||||
return DELETED;
|
return TOKEN_DELETED;
|
||||||
if (!strcasecmp (atom + 1, "elete"))
|
if (!strcasecmp (atom + 1, "elete"))
|
||||||
return TOKEN_DELETE;
|
return TOKEN_DELETE;
|
||||||
if (!strncasecmp (atom + 1, "efault", 6)) {
|
if (!strncasecmp (atom + 1, "efault", 6)) {
|
||||||
@ -619,6 +625,8 @@ static enum dhcp_token intern (atom, dfv)
|
|||||||
return EXPIRY;
|
return EXPIRY;
|
||||||
if (!strcasecmp (atom + 2, "pire"))
|
if (!strcasecmp (atom + 2, "pire"))
|
||||||
return EXPIRE;
|
return EXPIRE;
|
||||||
|
if (!strcasecmp (atom + 2, "pired"))
|
||||||
|
return TOKEN_EXPIRED;
|
||||||
}
|
}
|
||||||
if (!strcasecmp (atom + 1, "ncode-int"))
|
if (!strcasecmp (atom + 1, "ncode-int"))
|
||||||
return ENCODE_INT;
|
return ENCODE_INT;
|
||||||
@ -649,6 +657,8 @@ static enum dhcp_token intern (atom, dfv)
|
|||||||
return FUNCTION;
|
return FUNCTION;
|
||||||
if (!strcasecmp (atom + 1, "ailover"))
|
if (!strcasecmp (atom + 1, "ailover"))
|
||||||
return FAILOVER;
|
return FAILOVER;
|
||||||
|
if (!strcasecmp (atom + 1, "ree"))
|
||||||
|
return TOKEN_FREE;
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
if (!strcasecmp (atom + 1, "iaddr"))
|
if (!strcasecmp (atom + 1, "iaddr"))
|
||||||
@ -779,6 +789,8 @@ static enum dhcp_token intern (atom, dfv)
|
|||||||
return NS_NXRRSET;
|
return NS_NXRRSET;
|
||||||
if (!strcasecmp (atom + 1, "ull"))
|
if (!strcasecmp (atom + 1, "ull"))
|
||||||
return TOKEN_NULL;
|
return TOKEN_NULL;
|
||||||
|
if (!strcasecmp (atom + 1, "ext"))
|
||||||
|
return TOKEN_NEXT;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if (!strcasecmp (atom + 1, "r"))
|
if (!strcasecmp (atom + 1, "r"))
|
||||||
@ -850,6 +862,12 @@ static enum dhcp_token intern (atom, dfv)
|
|||||||
return RELEASE;
|
return RELEASE;
|
||||||
if (!strcasecmp (atom + 1, "efused"))
|
if (!strcasecmp (atom + 1, "efused"))
|
||||||
return NS_REFUSED;
|
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;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (!strcasecmp (atom + 1, "tate"))
|
if (!strcasecmp (atom + 1, "tate"))
|
||||||
|
@ -238,12 +238,10 @@ struct hardware {
|
|||||||
struct lease {
|
struct lease {
|
||||||
OMAPI_OBJECT_PREAMBLE;
|
OMAPI_OBJECT_PREAMBLE;
|
||||||
struct lease *next;
|
struct lease *next;
|
||||||
struct lease *prev;
|
|
||||||
struct lease *n_uid, *n_hw;
|
struct lease *n_uid, *n_hw;
|
||||||
struct lease *waitq_next;
|
|
||||||
|
|
||||||
struct iaddr ip_addr;
|
struct iaddr ip_addr;
|
||||||
TIME starts, ends, timestamp;
|
TIME starts, ends, timestamp, sort_time;
|
||||||
unsigned char *uid;
|
unsigned char *uid;
|
||||||
unsigned uid_len;
|
unsigned uid_len;
|
||||||
unsigned uid_max;
|
unsigned uid_max;
|
||||||
@ -261,18 +259,16 @@ struct lease {
|
|||||||
struct executable_statement *on_commit;
|
struct executable_statement *on_commit;
|
||||||
struct executable_statement *on_release;
|
struct executable_statement *on_release;
|
||||||
|
|
||||||
int flags;
|
u_int16_t flags;
|
||||||
# define STATIC_LEASE 1
|
# define STATIC_LEASE 1
|
||||||
# define BOOTP_LEASE 2
|
|
||||||
# define PERSISTENT_FLAGS (0)
|
# define PERSISTENT_FLAGS (0)
|
||||||
# define MS_NULL_TERMINATION 8
|
# define MS_NULL_TERMINATION 8
|
||||||
# define ABANDONED_LEASE 16
|
# define ON_UPDATE_QUEUE 16
|
||||||
# define PEER_IS_OWNER 32
|
# define ON_ACK_QUEUE 32
|
||||||
# define ON_UPDATE_QUEUE 64
|
# define EPHEMERAL_FLAGS (MS_NULL_TERMINATION | \
|
||||||
# define ON_ACK_QUEUE 128
|
|
||||||
# define EPHEMERAL_FLAGS (BOOTP_LEASE | MS_NULL_TERMINATION | \
|
|
||||||
ABANDONED_LEASE | PEER_IS_OWNER | \
|
|
||||||
ON_ACK_QUEUE | ON_UPDATE_QUEUE)
|
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;
|
struct lease_state *state;
|
||||||
|
|
||||||
@ -500,14 +496,16 @@ struct pool {
|
|||||||
struct shared_network *shared_network;
|
struct shared_network *shared_network;
|
||||||
struct permit *permit_list;
|
struct permit *permit_list;
|
||||||
struct permit *prohibit_list;
|
struct permit *prohibit_list;
|
||||||
struct lease *leases;
|
struct lease *active;
|
||||||
struct lease *insertion_point;
|
struct lease *expired;
|
||||||
struct lease *last_lease;
|
struct lease *free;
|
||||||
struct lease *next_expiry;
|
struct lease *backup;
|
||||||
|
struct lease *abandoned;
|
||||||
|
TIME next_event_time;
|
||||||
#if defined (FAILOVER_PROTOCOL)
|
#if defined (FAILOVER_PROTOCOL)
|
||||||
int lease_count;
|
int lease_count;
|
||||||
int local_leases;
|
int free_leases;
|
||||||
int peer_leases;
|
int backup_leases;
|
||||||
dhcp_failover_state_t *failover_peer;
|
dhcp_failover_state_t *failover_peer;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@ -1550,6 +1548,8 @@ extern u_int32_t fto_allowed [];
|
|||||||
extern int ft_sizes [];
|
extern int ft_sizes [];
|
||||||
extern const char *dhcp_flink_state_names [];
|
extern const char *dhcp_flink_state_names [];
|
||||||
#endif
|
#endif
|
||||||
|
extern const char *binding_state_names [];
|
||||||
|
|
||||||
extern struct universe agent_universe;
|
extern struct universe agent_universe;
|
||||||
extern struct option agent_options [256];
|
extern struct option agent_options [256];
|
||||||
extern struct universe server_universe;
|
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 destroy_client_lease PROTO ((struct client_lease *));
|
||||||
void rewrite_client_leases PROTO ((void));
|
void rewrite_client_leases PROTO ((void));
|
||||||
void write_client_lease PROTO ((struct client_state *,
|
int write_client_lease PROTO ((struct client_state *,
|
||||||
struct client_lease *, int));
|
struct client_lease *, int, int));
|
||||||
char *dhcp_option_ev_name PROTO ((struct option *));
|
char *dhcp_option_ev_name PROTO ((struct option *));
|
||||||
|
|
||||||
void script_init PROTO ((struct client_state *, const char *,
|
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));
|
int subnet_inner_than PROTO ((struct subnet *, struct subnet *, int));
|
||||||
void enter_subnet PROTO ((struct subnet *));
|
void enter_subnet PROTO ((struct subnet *));
|
||||||
void enter_lease PROTO ((struct lease *));
|
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));
|
int lease_copy PROTO ((struct lease **, struct lease *, const char *, int));
|
||||||
void release_lease PROTO ((struct lease *, struct packet *));
|
void release_lease PROTO ((struct lease *, struct packet *));
|
||||||
void abandon_lease PROTO ((struct lease *, const char *));
|
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_pool_check (struct pool *);
|
||||||
int dhcp_failover_state_pool_check (dhcp_failover_state_t *);
|
int dhcp_failover_state_pool_check (dhcp_failover_state_t *);
|
||||||
isc_result_t dhcp_failover_send_updates (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 *);
|
void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *, struct lease *);
|
||||||
isc_result_t dhcp_failover_state_set_value PROTO ((omapi_object_t *,
|
isc_result_t dhcp_failover_state_set_value PROTO ((omapi_object_t *,
|
||||||
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 *,
|
isc_result_t dhcp_failover_put_message (dhcp_failover_link_t *,
|
||||||
omapi_object_t *, int, ...);
|
omapi_object_t *, int, ...);
|
||||||
isc_result_t dhcp_failover_send_connect PROTO ((omapi_object_t *));
|
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 *,
|
isc_result_t dhcp_failover_send_disconnect PROTO ((omapi_object_t *,
|
||||||
int, const char *));
|
int, const char *));
|
||||||
isc_result_t dhcp_failover_send_bind_update (dhcp_failover_state_t *,
|
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 failover_print PROTO ((char *, unsigned *, unsigned, const char *));
|
||||||
void update_partner PROTO ((struct lease *));
|
void update_partner PROTO ((struct lease *));
|
||||||
int load_balance_mine (struct packet *, dhcp_failover_state_t *);
|
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,
|
OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_state, dhcp_failover_state_t,
|
||||||
dhcp_type_failover_state)
|
dhcp_type_failover_state)
|
||||||
OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_listener, dhcp_failover_listener_t,
|
OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_listener, dhcp_failover_listener_t,
|
||||||
|
@ -114,7 +114,6 @@ enum dhcp_token {
|
|||||||
EXPIRE = 308,
|
EXPIRE = 308,
|
||||||
UNKNOWN_CLIENTS = 309,
|
UNKNOWN_CLIENTS = 309,
|
||||||
ALLOW = 310,
|
ALLOW = 310,
|
||||||
BOOTP = 311,
|
|
||||||
DENY = 312,
|
DENY = 312,
|
||||||
BOOTING = 313,
|
BOOTING = 313,
|
||||||
DEFAULT = 314,
|
DEFAULT = 314,
|
||||||
@ -122,7 +121,7 @@ enum dhcp_token {
|
|||||||
MEDIUM = 316,
|
MEDIUM = 316,
|
||||||
ALIAS = 317,
|
ALIAS = 317,
|
||||||
REBOOT = 318,
|
REBOOT = 318,
|
||||||
ABANDONED = 319,
|
TOKEN_ABANDONED = 319,
|
||||||
BACKOFF_CUTOFF = 320,
|
BACKOFF_CUTOFF = 320,
|
||||||
INITIAL_INTERVAL = 321,
|
INITIAL_INTERVAL = 321,
|
||||||
NAMESERVER = 322,
|
NAMESERVER = 322,
|
||||||
@ -216,7 +215,7 @@ enum dhcp_token {
|
|||||||
STATIC = 414,
|
STATIC = 414,
|
||||||
NEVER = 415,
|
NEVER = 415,
|
||||||
INFINITE = 416,
|
INFINITE = 416,
|
||||||
DELETED = 417,
|
TOKEN_DELETED = 417,
|
||||||
UPDATED_DNS_RR = 418,
|
UPDATED_DNS_RR = 418,
|
||||||
DNS_DELETE = 419,
|
DNS_DELETE = 419,
|
||||||
DUPLICATES = 420,
|
DUPLICATES = 420,
|
||||||
@ -268,7 +267,17 @@ enum dhcp_token {
|
|||||||
STATE = 466,
|
STATE = 466,
|
||||||
UNKNOWN_STATE = 567,
|
UNKNOWN_STATE = 567,
|
||||||
CLTT = 568,
|
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 && \
|
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
|
||||||
|
@ -157,13 +157,17 @@ typedef struct {
|
|||||||
#define FTR_UNKNOWN 254
|
#define FTR_UNKNOWN 254
|
||||||
|
|
||||||
/* Lease states: */
|
/* Lease states: */
|
||||||
#define FTS_FREE 1
|
typedef enum {
|
||||||
#define FTS_ACTIVE 2
|
FTS_FREE = 1,
|
||||||
#define FTS_EXPIRED 3
|
FTS_ACTIVE = 2,
|
||||||
#define FTS_RELEASED 4
|
FTS_EXPIRED = 3,
|
||||||
#define FTS_ABANDONED 5
|
FTS_RELEASED = 4,
|
||||||
#define FTS_RESET 6
|
FTS_ABANDONED = 5,
|
||||||
#define FTS_BACKUP 7
|
FTS_RESET = 6,
|
||||||
|
FTS_BACKUP = 7,
|
||||||
|
FTS_RESERVED = 8,
|
||||||
|
FTS_BOOTP = 9
|
||||||
|
} binding_state_t;
|
||||||
|
|
||||||
#define DHCP_FAILOVER_MAX_MESSAGE_SIZE 2048
|
#define DHCP_FAILOVER_MAX_MESSAGE_SIZE 2048
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -711,6 +711,10 @@ void parse_failover_peer (cfile, group, type)
|
|||||||
|
|
||||||
case SECONDARY:
|
case SECONDARY:
|
||||||
peer -> i_am = secondary;
|
peer -> i_am = secondary;
|
||||||
|
if (peer -> hba)
|
||||||
|
parse_warn (cfile,
|
||||||
|
"secondary may not define %s",
|
||||||
|
"load balance settings.");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PEER:
|
case PEER:
|
||||||
@ -783,6 +787,10 @@ void parse_failover_peer (cfile, group, type)
|
|||||||
|
|
||||||
case HBA:
|
case HBA:
|
||||||
hba_len = 32;
|
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,
|
if (!parse_numeric_aggregate (cfile, hba, &hba_len,
|
||||||
COLON, 16, 8)) {
|
COLON, 16, 8)) {
|
||||||
skip_to_rbrace (cfile, 1);
|
skip_to_rbrace (cfile, 1);
|
||||||
@ -806,6 +814,10 @@ void parse_failover_peer (cfile, group, type)
|
|||||||
|
|
||||||
case SPLIT:
|
case SPLIT:
|
||||||
token = next_token (&val, cfile);
|
token = next_token (&val, cfile);
|
||||||
|
if (peer -> i_am == secondary)
|
||||||
|
parse_warn (cfile,
|
||||||
|
"secondary may not define %s",
|
||||||
|
"load balance settings.");
|
||||||
if (token != NUMBER) {
|
if (token != NUMBER) {
|
||||||
parse_warn (cfile, "expecting number");
|
parse_warn (cfile, "expecting number");
|
||||||
badsplit:
|
badsplit:
|
||||||
@ -868,6 +880,11 @@ void parse_failover_peer (cfile, group, type)
|
|||||||
}
|
}
|
||||||
} while (token != RBRACE);
|
} 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) {
|
if (type == SHARED_NET_DECL) {
|
||||||
group -> shared_network -> failover_peer = peer;
|
group -> shared_network -> failover_peer = peer;
|
||||||
}
|
}
|
||||||
@ -1175,7 +1192,7 @@ void parse_pool_statement (cfile, group, type)
|
|||||||
|
|
||||||
case DYNAMIC:
|
case DYNAMIC:
|
||||||
permit -> type = permit_dynamic_bootp_clients;
|
permit -> type = permit_dynamic_bootp_clients;
|
||||||
if (next_token (&val, cfile) != BOOTP) {
|
if (next_token (&val, cfile) != TOKEN_BOOTP) {
|
||||||
parse_warn (cfile,
|
parse_warn (cfile,
|
||||||
"expecting \"bootp\"");
|
"expecting \"bootp\"");
|
||||||
skip_to_semi (cfile);
|
skip_to_semi (cfile);
|
||||||
@ -1385,7 +1402,7 @@ void parse_host_declaration (cfile, group)
|
|||||||
}
|
}
|
||||||
/* If the host declaration was created by the server,
|
/* If the host declaration was created by the server,
|
||||||
remember to save it. */
|
remember to save it. */
|
||||||
if (token == DELETED) {
|
if (token == TOKEN_DELETED) {
|
||||||
deleted = 1;
|
deleted = 1;
|
||||||
token = next_token (&val, cfile);
|
token = next_token (&val, cfile);
|
||||||
if (!parse_semi (cfile))
|
if (!parse_semi (cfile))
|
||||||
@ -2071,7 +2088,7 @@ void parse_group_declaration (cfile, group)
|
|||||||
token = next_token (&val, cfile);
|
token = next_token (&val, cfile);
|
||||||
parse_warn (cfile, "unexpected end of file");
|
parse_warn (cfile, "unexpected end of file");
|
||||||
break;
|
break;
|
||||||
} else if (token == DELETED) {
|
} else if (token == TOKEN_DELETED) {
|
||||||
token = next_token (&val, cfile);
|
token = next_token (&val, cfile);
|
||||||
parse_semi (cfile);
|
parse_semi (cfile);
|
||||||
deletedp = 1;
|
deletedp = 1;
|
||||||
@ -2215,6 +2232,7 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile)
|
|||||||
int noequal, newbinding;
|
int noequal, newbinding;
|
||||||
struct binding *binding;
|
struct binding *binding;
|
||||||
isc_result_t status;
|
isc_result_t status;
|
||||||
|
binding_state_t *statep;
|
||||||
|
|
||||||
lease = (struct lease *)0;
|
lease = (struct lease *)0;
|
||||||
status = lease_allocate (&lease, MDL);
|
status = lease_allocate (&lease, MDL);
|
||||||
@ -2351,34 +2369,76 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DYNAMIC_BOOTP:
|
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;
|
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);
|
parse_semi (cfile);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2817,7 +2877,7 @@ int parse_allow_deny (oc, cfile, flag)
|
|||||||
|
|
||||||
token = next_token (&val, cfile);
|
token = next_token (&val, cfile);
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case BOOTP:
|
case TOKEN_BOOTP:
|
||||||
status = option_cache (oc, (struct data_string *)0, data,
|
status = option_cache (oc, (struct data_string *)0, data,
|
||||||
&server_options [SV_ALLOW_BOOTP]);
|
&server_options [SV_ALLOW_BOOTP]);
|
||||||
break;
|
break;
|
||||||
|
36
server/db.c
36
server/db.c
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -143,13 +143,19 @@ int write_lease (lease)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lease -> flags & PEER_IS_OWNER) {
|
fprintf (db_file, "\n binding state %s;",
|
||||||
errno = 0;
|
((lease -> binding_state > 0 &&
|
||||||
fprintf (db_file, "\n peer is owner;");
|
lease -> binding_state <= FTS_BOOTP)
|
||||||
if (errno) {
|
? binding_state_names [lease -> binding_state - 1]
|
||||||
++errors;
|
: "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,
|
/* If this lease is billed to a class and is still valid,
|
||||||
write it out. */
|
write it out. */
|
||||||
@ -190,20 +196,6 @@ int write_lease (lease)
|
|||||||
putc (';', db_file);
|
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) {
|
for (b = lease -> scope.bindings; b; b = b -> next) {
|
||||||
if (!b -> value)
|
if (!b -> value)
|
||||||
continue;
|
continue;
|
||||||
|
308
server/dhcp.c
308
server/dhcp.c
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -138,15 +138,10 @@ void dhcpdiscover (packet, ms_nulltp)
|
|||||||
: packet -> interface -> name);
|
: packet -> interface -> name);
|
||||||
|
|
||||||
#if defined (FAILOVER_PROTOCOL)
|
#if defined (FAILOVER_PROTOCOL)
|
||||||
if (lease && lease -> pool &&
|
if (lease && !lease_mine_to_extend (lease)) {
|
||||||
lease -> pool -> failover_peer) {
|
log_info ("%s: letting peer %s answer", msgbuf,
|
||||||
peer = lease -> pool -> failover_peer;
|
lease -> pool -> failover_peer -> name);
|
||||||
if ((lease -> flags & PEER_IS_OWNER) &&
|
goto out;
|
||||||
peer -> my_state == normal) {
|
|
||||||
log_info ("%s: letting peer %s respond.",
|
|
||||||
msgbuf, peer -> name);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -191,7 +186,7 @@ void dhcpdiscover (packet, ms_nulltp)
|
|||||||
if (allocatedp && lease && lease -> pool &&
|
if (allocatedp && lease && lease -> pool &&
|
||||||
lease -> pool -> failover_peer) {
|
lease -> pool -> failover_peer) {
|
||||||
peer = 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)) {
|
if (!load_balance_mine (packet, peer)) {
|
||||||
log_debug ("%s: load balance to peer %s",
|
log_debug ("%s: load balance to peer %s",
|
||||||
msgbuf, peer -> name);
|
msgbuf, peer -> name);
|
||||||
@ -256,6 +251,7 @@ void dhcprequest (packet, ms_nulltp)
|
|||||||
find_lease (&lease, packet,
|
find_lease (&lease, packet,
|
||||||
subnet -> shared_network, &ours, MDL);
|
subnet -> shared_network, &ours, MDL);
|
||||||
|
|
||||||
|
|
||||||
if (lease && lease -> client_hostname &&
|
if (lease && lease -> client_hostname &&
|
||||||
db_printable (lease -> client_hostname))
|
db_printable (lease -> client_hostname))
|
||||||
s = lease -> client_hostname;
|
s = lease -> client_hostname;
|
||||||
@ -278,6 +274,14 @@ void dhcprequest (packet, ms_nulltp)
|
|||||||
? inet_ntoa (packet -> raw -> giaddr)
|
? inet_ntoa (packet -> raw -> giaddr)
|
||||||
: packet -> interface -> name);
|
: 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
|
/* If a client on a given network REQUESTs a lease on an
|
||||||
address on a different network, NAK it. If the Requested
|
address on a different network, NAK it. If the Requested
|
||||||
Address option was used, the protocol says that it must
|
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
|
/* If we found a lease, but it belongs to a failover peer, and
|
||||||
the client is in the SELECTING state, ignore the request -
|
the client is in the SELECTING state, ignore the request -
|
||||||
it's not ours. */
|
it's not ours. */
|
||||||
@ -420,6 +424,7 @@ void dhcprelease (packet, ms_nulltp)
|
|||||||
struct option_cache *oc;
|
struct option_cache *oc;
|
||||||
struct data_string data;
|
struct data_string data;
|
||||||
char *s;
|
char *s;
|
||||||
|
char msgbuf [1024]; /* XXX */
|
||||||
|
|
||||||
/* DHCPRELEASE must not specify address in requested-address
|
/* DHCPRELEASE must not specify address in requested-address
|
||||||
option, but old protocol specs weren't explicit about this,
|
option, but old protocol specs weren't explicit about this,
|
||||||
@ -469,27 +474,44 @@ void dhcprelease (packet, ms_nulltp)
|
|||||||
s = (char *)0;
|
s = (char *)0;
|
||||||
|
|
||||||
/* Say what we're doing... */
|
/* Say what we're doing... */
|
||||||
log_info ("DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)",
|
sprintf (msgbuf,
|
||||||
inet_ntoa (packet -> raw -> ciaddr),
|
"DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)",
|
||||||
(packet -> raw -> htype
|
inet_ntoa (packet -> raw -> ciaddr),
|
||||||
? print_hw_addr (packet -> raw -> htype,
|
(packet -> raw -> htype
|
||||||
packet -> raw -> hlen,
|
? print_hw_addr (packet -> raw -> htype,
|
||||||
packet -> raw -> chaddr)
|
packet -> raw -> hlen,
|
||||||
: (lease
|
packet -> raw -> chaddr)
|
||||||
? print_hex_1 (lease -> uid_len, lease -> uid,
|
: (lease
|
||||||
lease -> uid_len)
|
? print_hex_1 (lease -> uid_len, lease -> uid,
|
||||||
: "<no identifier>")),
|
lease -> uid_len)
|
||||||
s ? "(" : "", s ? s : "", s ? ") " : "",
|
: "<no identifier>")),
|
||||||
packet -> raw -> giaddr.s_addr
|
s ? "(" : "", s ? s : "", s ? ") " : "",
|
||||||
? inet_ntoa (packet -> raw -> giaddr)
|
packet -> raw -> giaddr.s_addr
|
||||||
: packet -> interface -> name,
|
? inet_ntoa (packet -> raw -> giaddr)
|
||||||
lease ? "" : "not ");
|
: 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 we found a lease, release it. */
|
||||||
if (lease && lease -> ends > cur_time) {
|
if (lease && lease -> ends > cur_time) {
|
||||||
release_lease (lease, packet);
|
release_lease (lease, packet);
|
||||||
lease_dereference (&lease, MDL);
|
log_info ("%s", msgbuf);
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
if (lease)
|
||||||
|
lease_dereference (&lease, MDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dhcpdecline (packet, ms_nulltp)
|
void dhcpdecline (packet, ms_nulltp)
|
||||||
@ -505,6 +527,7 @@ void dhcpdecline (packet, ms_nulltp)
|
|||||||
int i;
|
int i;
|
||||||
const char *status;
|
const char *status;
|
||||||
char *s;
|
char *s;
|
||||||
|
char msgbuf [1024]; /* XXX */
|
||||||
|
|
||||||
/* DHCPDECLINE must specify address. */
|
/* DHCPDECLINE must specify address. */
|
||||||
if (!(oc = lookup_option (&dhcp_universe, packet -> options,
|
if (!(oc = lookup_option (&dhcp_universe, packet -> options,
|
||||||
@ -522,6 +545,36 @@ void dhcpdecline (packet, ms_nulltp)
|
|||||||
data_string_forget (&data, MDL);
|
data_string_forget (&data, MDL);
|
||||||
find_lease_by_ip_addr (&lease, cip, 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);
|
option_state_allocate (&options, MDL);
|
||||||
|
|
||||||
/* Execute statements in scope starting with the subnet scope. */
|
/* Execute statements in scope starting with the subnet scope. */
|
||||||
@ -549,38 +602,18 @@ void dhcpdecline (packet, ms_nulltp)
|
|||||||
/* If we found a lease, mark it as unusable and complain. */
|
/* If we found a lease, mark it as unusable and complain. */
|
||||||
if (lease) {
|
if (lease) {
|
||||||
abandon_lease (lease, "declined.");
|
abandon_lease (lease, "declined.");
|
||||||
status = "";
|
status = "abandoned";
|
||||||
}
|
}
|
||||||
status = " (not found)";
|
status = "not found";
|
||||||
} else
|
} else
|
||||||
status = " (ignored)";
|
status = "ignored";
|
||||||
|
|
||||||
if (!ignorep) {
|
if (!ignorep)
|
||||||
char *s;
|
log_info ("%s: %s", msgbuf, status);
|
||||||
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",
|
out:
|
||||||
piaddr (cip),
|
if (options)
|
||||||
(packet -> raw -> htype
|
option_state_dereference (&options, MDL);
|
||||||
? 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
option_state_dereference (&options, MDL);
|
|
||||||
if (lease)
|
if (lease)
|
||||||
lease_dereference (&lease, MDL);
|
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. */
|
/* Try to find a matching host declaration for this lease. */
|
||||||
if (!lease -> host) {
|
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
|
/* Try to find a host_decl that matches the client
|
||||||
identifier or hardware address on the packet, and
|
identifier or hardware address on the packet, and
|
||||||
@ -1371,26 +1405,26 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
|
|||||||
evaluate_option_cache (&d1, packet, lease,
|
evaluate_option_cache (&d1, packet, lease,
|
||||||
packet -> options, state -> options,
|
packet -> options, state -> options,
|
||||||
&lease -> scope, oc, MDL)) {
|
&lease -> scope, oc, MDL)) {
|
||||||
struct host_decl *h;
|
|
||||||
hp = (struct host_decl *)0;
|
|
||||||
find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
|
find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
|
||||||
data_string_forget (&d1, MDL);
|
data_string_forget (&d1, MDL);
|
||||||
if (!hp)
|
if (hp)
|
||||||
find_hosts_by_haddr (&hp,
|
host_reference (&lease -> host, hp, MDL);
|
||||||
packet -> raw -> htype,
|
}
|
||||||
packet -> raw -> chaddr,
|
if (!hp) {
|
||||||
packet -> raw -> hlen,
|
find_hosts_by_haddr (&hp,
|
||||||
MDL);
|
packet -> raw -> htype,
|
||||||
|
packet -> raw -> chaddr,
|
||||||
|
packet -> raw -> hlen,
|
||||||
|
MDL);
|
||||||
for (h = hp; h; h = h -> n_ipaddr) {
|
for (h = hp; h; h = h -> n_ipaddr) {
|
||||||
if (!h -> fixed_addr)
|
if (!h -> fixed_addr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (h)
|
if (h)
|
||||||
host_reference (&lease -> host, hp, MDL);
|
host_reference (&lease -> host, hp, MDL);
|
||||||
if (hp)
|
}
|
||||||
host_dereference (&hp, MDL);
|
if (hp)
|
||||||
} else
|
host_dereference (&hp, MDL);
|
||||||
lease -> host = (struct host_decl *)0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Drop the request if it's not allowed for this client. By
|
/* 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;
|
lt -> ends = when;
|
||||||
else
|
else
|
||||||
lt -> ends = state -> offered_expiry;
|
lt -> ends = state -> offered_expiry;
|
||||||
|
lt -> next_binding_state = FTS_ACTIVE;
|
||||||
} else {
|
} else {
|
||||||
lease_time = MAX_TIME - cur_time;
|
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 -> ends = state -> offered_expiry = cur_time + lease_time;
|
||||||
lt -> flags = BOOTP_LEASE;
|
lt -> next_binding_state = FTS_BOOTP;
|
||||||
}
|
}
|
||||||
|
|
||||||
lt -> timestamp = cur_time;
|
lt -> timestamp = cur_time;
|
||||||
@ -1752,29 +1787,13 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
|
|||||||
it) either. */
|
it) either. */
|
||||||
|
|
||||||
if (!(supersede_lease (lease, lt, !offer || offer == DHCPACK,
|
if (!(supersede_lease (lease, lt, !offer || offer == DHCPACK,
|
||||||
offer == DHCPACK)
|
offer == DHCPACK, offer == DHCPACK)
|
||||||
|| (offer && offer != DHCPACK))) {
|
|| (offer && offer != DHCPACK))) {
|
||||||
log_info ("%s: database update failed", msg);
|
log_info ("%s: database update failed", msg);
|
||||||
free_lease_state (state, MDL);
|
free_lease_state (state, MDL);
|
||||||
static_lease_dereference (lease, MDL);
|
static_lease_dereference (lease, MDL);
|
||||||
lease_dereference (<, MDL);
|
lease_dereference (<, MDL);
|
||||||
return;
|
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);
|
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
|
/* Toss ip_lease if it hasn't yet expired and doesn't belong to the
|
||||||
client. */
|
client. */
|
||||||
if (ip_lease &&
|
if (ip_lease &&
|
||||||
ip_lease -> ends >= cur_time &&
|
|
||||||
((ip_lease -> uid &&
|
((ip_lease -> uid &&
|
||||||
(!have_client_identifier ||
|
(!have_client_identifier ||
|
||||||
ip_lease -> uid_len != client_identifier.len ||
|
ip_lease -> uid_len != client_identifier.len ||
|
||||||
@ -2649,25 +2667,43 @@ int find_lease (struct lease **lp,
|
|||||||
memcmp (&ip_lease -> hardware_addr.hbuf [1],
|
memcmp (&ip_lease -> hardware_addr.hbuf [1],
|
||||||
packet -> raw -> chaddr,
|
packet -> raw -> chaddr,
|
||||||
(unsigned)(ip_lease -> hardware_addr.hlen - 1)))))) {
|
(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 defined (DEBUG_FIND_LEASE)
|
||||||
if (ip_lease)
|
|
||||||
log_info ("rejecting lease for requested address.");
|
log_info ("rejecting lease for requested address.");
|
||||||
#endif
|
#endif
|
||||||
lease_dereference (&ip_lease, MDL);
|
lease_dereference (&ip_lease, MDL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If for some reason the client has more than one lease
|
/* If for some reason the client has more than one lease
|
||||||
on the subnet that matches its uid, pick the one that
|
on the subnet that matches its uid, pick the one that
|
||||||
it asked for and (if we can) free the other. */
|
it asked for and (if we can) free the other. */
|
||||||
if (ip_lease &&
|
if (ip_lease &&
|
||||||
ip_lease -> ends >= cur_time &&
|
ip_lease -> binding_state == FTS_ACTIVE &&
|
||||||
ip_lease -> uid && ip_lease != uid_lease) {
|
ip_lease -> uid && ip_lease != uid_lease) {
|
||||||
if (have_client_identifier &&
|
if (have_client_identifier &&
|
||||||
(ip_lease -> uid_len == client_identifier.len) &&
|
(ip_lease -> uid_len == client_identifier.len) &&
|
||||||
!memcmp (client_identifier.data,
|
!memcmp (client_identifier.data,
|
||||||
ip_lease -> uid, ip_lease -> uid_len)) {
|
ip_lease -> uid, ip_lease -> uid_len)) {
|
||||||
if (uid_lease) {
|
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",
|
log_error ("client %s has duplicate%s on %s",
|
||||||
(print_hw_addr
|
(print_hw_addr
|
||||||
(packet -> raw -> htype,
|
(packet -> raw -> htype,
|
||||||
@ -2722,17 +2758,6 @@ int find_lease (struct lease **lp,
|
|||||||
if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
|
if (packet -> packet_type == DHCPREQUEST && fixed_lease && ip_lease)
|
||||||
goto db_conflict;
|
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... */
|
/* Toss extra pointers to the same lease... */
|
||||||
if (hw_lease && hw_lease == uid_lease) {
|
if (hw_lease && hw_lease == uid_lease) {
|
||||||
#if defined (DEBUG_FIND_LEASE)
|
#if defined (DEBUG_FIND_LEASE)
|
||||||
@ -2753,6 +2778,37 @@ int find_lease (struct lease **lp,
|
|||||||
#endif
|
#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
|
/* If we've already eliminated the lease, it wasn't there to
|
||||||
begin with. If we have come up with a matching lease,
|
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. */
|
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
|
requested, we assume that previous bugginess on the part
|
||||||
of the client, or a server database loss, caused the lease to
|
of the client, or a server database loss, caused the lease to
|
||||||
be abandoned, so we reclaim it and let the client have it. */
|
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) {
|
packet -> packet_type == DHCPREQUEST) {
|
||||||
log_error ("Reclaiming REQUESTed abandoned IP address %s.",
|
log_error ("Reclaiming REQUESTed abandoned IP address %s.",
|
||||||
piaddr (lease -> ip_addr));
|
piaddr (lease -> ip_addr));
|
||||||
lease -> flags &= ~ABANDONED_LEASE;
|
} else if (lease && (lease -> binding_state == FTS_ABANDONED)) {
|
||||||
} else if (lease && (lease -> flags & ABANDONED_LEASE)) {
|
|
||||||
/* Otherwise, if it's not the one the client requested, we do not
|
/* 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
|
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
|
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 -> hardware_addr = hp -> interface;
|
||||||
lease -> starts = lease -> timestamp = lease -> ends = MIN_TIME;
|
lease -> starts = lease -> timestamp = lease -> ends = MIN_TIME;
|
||||||
lease -> flags = STATIC_LEASE;
|
lease -> flags = STATIC_LEASE;
|
||||||
|
lease -> binding_state = FTS_FREE;
|
||||||
lease_reference (lp, lease, MDL);
|
lease_reference (lp, lease, MDL);
|
||||||
lease_dereference (&lease, MDL);
|
lease_dereference (&lease, MDL);
|
||||||
return 1;
|
return 1;
|
||||||
@ -2986,6 +3044,7 @@ int allocate_lease (struct lease **lp, struct packet *packet,
|
|||||||
struct pool *pool, int *peer_has_leases)
|
struct pool *pool, int *peer_has_leases)
|
||||||
{
|
{
|
||||||
struct lease *lease = (struct lease *)0;
|
struct lease *lease = (struct lease *)0;
|
||||||
|
struct lease **lq;
|
||||||
struct permit *permit;
|
struct permit *permit;
|
||||||
|
|
||||||
if (!pool)
|
if (!pool)
|
||||||
@ -2998,31 +3057,39 @@ int allocate_lease (struct lease **lp, struct packet *packet,
|
|||||||
return allocate_lease (lp, packet, pool -> next,
|
return allocate_lease (lp, packet, pool -> next,
|
||||||
peer_has_leases);
|
peer_has_leases);
|
||||||
|
|
||||||
lease = pool -> last_lease;
|
|
||||||
|
|
||||||
#if defined (FAILOVER_PROTOCOL)
|
#if defined (FAILOVER_PROTOCOL)
|
||||||
/* Peer_has_leases just says that we found at least one free lease.
|
/* 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
|
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
|
means the peer is hogging all the free leases, so we can print
|
||||||
a better error message. */
|
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 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 tstp if we're in, e.g., PARTNER_DOWN? Where do we deal with
|
||||||
XXX CONFLICT_DETECTED, et al? */
|
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
|
/* Skip to the most expired lease in the pool that is not owned by a
|
||||||
failover peer. */
|
failover peer. */
|
||||||
if (lease -> pool && lease -> pool -> failover_peer) {
|
if (pool -> failover_peer) {
|
||||||
while (lease &&
|
if (pool -> failover_peer -> i_am == primary) {
|
||||||
(lease -> flags & PEER_IS_OWNER) &&
|
if (pool -> backup)
|
||||||
(lease -> ends <=
|
*peer_has_leases = 1;
|
||||||
cur_time + lease -> pool -> failover_peer -> mclt))
|
lease = pool -> free;
|
||||||
lease = lease -> prev;
|
if (!lease)
|
||||||
/* We didn't find an unexpired lease that we own? */
|
lease = pool -> abandoned;
|
||||||
if (lease && lease -> flags & PEER_IS_OWNER)
|
} else {
|
||||||
lease = (struct lease *)0;
|
if (pool -> free)
|
||||||
|
*peer_has_leases = 1;
|
||||||
|
lease = pool -> backup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (pool -> free)
|
||||||
|
lease = pool -> free;
|
||||||
|
else
|
||||||
|
lease = pool -> abandoned;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If there are no leases in the pool that have
|
/* 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. */
|
better, take it. */
|
||||||
/* XXX what if there are non-abandoned leases that are younger
|
/* XXX what if there are non-abandoned leases that are younger
|
||||||
XXX than this? Shouldn't we hunt for those here? */
|
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
|
/* If we already have a non-abandoned lease that we didn't
|
||||||
love, but that's okay, don't reclaim the abandoned lease. */
|
love, but that's okay, don't reclaim the abandoned lease. */
|
||||||
if (*lp)
|
if (*lp)
|
||||||
@ -3045,7 +3112,6 @@ int allocate_lease (struct lease **lp, struct packet *packet,
|
|||||||
pool -> next, peer_has_leases)) {
|
pool -> next, peer_has_leases)) {
|
||||||
log_error ("Reclaiming abandoned IP address %s.",
|
log_error ("Reclaiming abandoned IP address %s.",
|
||||||
piaddr (lease -> ip_addr));
|
piaddr (lease -> ip_addr));
|
||||||
lease -> flags &= ~ABANDONED_LEASE;
|
|
||||||
lease_reference (lp, lease, MDL);
|
lease_reference (lp, lease, MDL);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1272,18 +1272,21 @@ override the use of the name in the host declaration.
|
|||||||
\fBnot authoritative;\fR
|
\fBnot authoritative;\fR
|
||||||
.PP
|
.PP
|
||||||
The DHCP server will normally assume that the configuration
|
The DHCP server will normally assume that the configuration
|
||||||
information about a given network segment is known to be correct and
|
information about a given network segment is not known to be correct
|
||||||
is authoritative. So if a client requests an IP address on a given
|
and is not authoritative. This is so that if a naive user installs a
|
||||||
network segment that the server knows is not valid for that segment,
|
DHCP server not fully understanding how to configure it, it does not
|
||||||
the server will respond with a DHCPNAK message, causing the client to
|
send spurious DHCPNAK messages to clients that have obtained addresses
|
||||||
forget its IP address and try to get a new one.
|
from a legitimate DHCP server on the network.
|
||||||
.PP
|
.PP
|
||||||
If a DHCP server is being configured by somebody who is not the
|
Network administrators setting up authoritative DHCP servers for their
|
||||||
network administrator and who therefore does not wish to assert this
|
networks should always write \fBauthoritative;\fR at the top of their
|
||||||
level of authority, then the statement "not authoritative" should be
|
configuration file to indicate that the DHCP server \fIshould\fR send
|
||||||
written in the appropriate scope in the configuration file.
|
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
|
.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
|
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
|
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
|
some networks for which it is not, it may be more appropriate to
|
||||||
|
@ -1478,39 +1478,39 @@ dhcpd.conf(5) dhcpd.conf(5)
|
|||||||
nnoott aauutthhoorriittaattiivvee;;
|
nnoott aauutthhoorriittaattiivvee;;
|
||||||
|
|
||||||
The DHCP server will normally assume that the configura
|
The DHCP server will normally assume that the configura
|
||||||
tion information about a given network segment is known to
|
tion information about a given network segment is not
|
||||||
be correct and is authoritative. So if a client requests
|
known to be correct and is not authoritative. This is so
|
||||||
an IP address on a given network segment that the server
|
that if a naive user installs a DHCP server not fully
|
||||||
knows is not valid for that segment, the server will
|
understanding how to configure it, it does not send spuri
|
||||||
respond with a DHCPNAK message, causing the client to for
|
ous DHCPNAK messages to clients that have obtained
|
||||||
get its IP address and try to get a new one.
|
addresses from a legitimate DHCP server on the network.
|
||||||
|
|
||||||
If a DHCP server is being configured by somebody who is
|
Network administrators setting up authoritative DHCP
|
||||||
not the network administrator and who therefore does not
|
servers for their networks should always write aauutthhoorriittaa
|
||||||
wish to assert this level of authority, then the statement
|
ttiivvee;; at the top of their configuration file to indicate
|
||||||
"not authoritative" should be written in the appropriate
|
that the DHCP server _s_h_o_u_l_d send DHCPNAK messages to mis
|
||||||
scope in the configuration file.
|
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
|
Usually, writing aauutthhoorriittaattiivvee;; at the top level of the
|
||||||
the file should be sufficient. However, if a DHCP server
|
file should be sufficient. However, if a DHCP server is
|
||||||
is to be set up so that it is aware of some networks for
|
to be set up so that it is aware of some networks for
|
||||||
which it is authoritative and some networks for which it
|
which it is authoritative and some networks for which it
|
||||||
is not, it may be more appropriate to declare authority on
|
is not, it may be more appropriate to declare authority on
|
||||||
a per-network-segment basis.
|
a per-network-segment basis.
|
||||||
|
|
||||||
Note that the most specific scope for which the concept of
|
Note that the most specific scope for which the concept of
|
||||||
authority makes any sense is the physical network segment
|
authority makes any sense is the physical network segment
|
||||||
- either a shared-network statement or a subnet statement
|
- either a shared-network statement or a subnet statement
|
||||||
that is not contained within a shared-network statement.
|
that is not contained within a shared-network statement.
|
||||||
It is not meaningful to specify that the server is author
|
It is not meaningful to specify that the server is author
|
||||||
itative for some subnets within a shared network, but not
|
itative for some subnets within a shared network, but not
|
||||||
authoritative for others, nor is it meaningful to specify
|
authoritative for others, nor is it meaningful to specify
|
||||||
that the server is authoritative for some host declara
|
that the server is authoritative for some host declara
|
||||||
tions and not others.
|
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
|
23
|
||||||
@ -1522,36 +1522,38 @@ dhcpd.conf(5) dhcpd.conf(5)
|
|||||||
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;;
|
aallwwaayyss--rreeppllyy--rrffcc11004488 _f_l_a_g;;
|
||||||
|
|
||||||
Some BOOTP clients expect RFC1048-style responses, but do
|
Some BOOTP clients expect RFC1048-style responses, but do
|
||||||
not follow RFC1048 when sending their requests. You can
|
not follow RFC1048 when sending their requests. You can
|
||||||
tell that a client is having this problem if it is not
|
tell that a client is having this problem if it is not
|
||||||
getting the options you have configured for it and if you
|
getting the options you have configured for it and if you
|
||||||
see in the server log the message "(non-rfc1048)" printed
|
see in the server log the message "(non-rfc1048)" printed
|
||||||
with each BOOTREQUEST that is logged.
|
with each BOOTREQUEST that is logged.
|
||||||
|
|
||||||
If you want to send rfc1048 options to such a client, you
|
If you want to send rfc1048 options to such a client, you
|
||||||
can set the aallwwaayyss--rreeppllyy--rrffcc11004488 option in that client's
|
can set the aallwwaayyss--rreeppllyy--rrffcc11004488 option in that client's
|
||||||
host declaration, and the DHCP server will respond with an
|
host declaration, and the DHCP server will respond with an
|
||||||
RFC-1048-style vendor options field. This flag can be
|
RFC-1048-style vendor options field. This flag can be
|
||||||
set in any scope, and will affect all clients covered by
|
set in any scope, and will affect all clients covered by
|
||||||
that scope.
|
that scope.
|
||||||
|
|
||||||
TThhee _a_l_w_a_y_s_-_b_r_o_a_d_c_a_s_t ssttaatteemmeenntt
|
TThhee _a_l_w_a_y_s_-_b_r_o_a_d_c_a_s_t ssttaatteemmeenntt
|
||||||
|
|
||||||
aallwwaayyss--bbrrooaaddccaasstt _f_l_a_g;;
|
aallwwaayyss--bbrrooaaddccaasstt _f_l_a_g;;
|
||||||
|
|
||||||
The DHCP and BOOTP protocols both require DHCP and BOOTP
|
The DHCP and BOOTP protocols both require DHCP and BOOTP
|
||||||
clients to set the broadcast bit in the flags field of the
|
clients to set the broadcast bit in the flags field of the
|
||||||
BOOTP message header. Unfortunately, some DHCP and BOOTP
|
BOOTP message header. Unfortunately, some DHCP and BOOTP
|
||||||
clients do not do this, and therefore may not receive
|
clients do not do this, and therefore may not receive
|
||||||
responses from the DHCP server. The DHCP server can be
|
responses from the DHCP server. The DHCP server can be
|
||||||
made to always broadcast its responses to clients by set
|
made to always broadcast its responses to clients by set
|
||||||
ting this flag to 'on' for the relevant scope. To avoid
|
ting this flag to 'on' for the relevant scope. To avoid
|
||||||
creating excess broadcast traffic on your network, we rec
|
creating excess broadcast traffic on your network, we rec
|
||||||
ommend that you restrict the use of this option to as few
|
ommend that you restrict the use of this option to as few
|
||||||
clients as possible. For example, the Microsoft DHCP
|
clients as possible. For example, the Microsoft DHCP
|
||||||
client is known not to have this problem, as are the Open
|
client is known not to have this problem, as are the Open
|
||||||
Transport and ISC DHCP clients.
|
Transport and ISC DHCP clients.
|
||||||
|
|
||||||
@ -1560,13 +1562,13 @@ dhcpd.conf(5) dhcpd.conf(5)
|
|||||||
oonnee--lleeaassee--ppeerr--cclliieenntt _f_l_a_g;;
|
oonnee--lleeaassee--ppeerr--cclliieenntt _f_l_a_g;;
|
||||||
|
|
||||||
If this flag is enabled, whenever a client sends a DHCPRE
|
If this flag is enabled, whenever a client sends a DHCPRE
|
||||||
QUEST for a particular lease, the server will automati
|
QUEST for a particular lease, the server will automati
|
||||||
cally free any other leases the client holds. This pre
|
cally free any other leases the client holds. This pre
|
||||||
sumes that when the client sends a DHCPREQUEST, it has
|
sumes that when the client sends a DHCPREQUEST, it has
|
||||||
forgotten any lease not mentioned in the DHCPREQUEST -
|
forgotten any lease not mentioned in the DHCPREQUEST -
|
||||||
i.e., the client has only a single network interface _a_n_d
|
i.e., the client has only a single network interface _a_n_d
|
||||||
it does not remember leases it's holding on networks to
|
it does not remember leases it's holding on networks to
|
||||||
which it is not currently attached. Neither of these
|
which it is not currently attached. Neither of these
|
||||||
assumptions are guaranteed or provable, so we urge caution
|
assumptions are guaranteed or provable, so we urge caution
|
||||||
in the use of this statement.
|
in the use of this statement.
|
||||||
|
|
||||||
@ -1574,8 +1576,6 @@ dhcpd.conf(5) dhcpd.conf(5)
|
|||||||
|
|
||||||
uussee--lleeaassee--aaddddrr--ffoorr--ddeeffaauulltt--rroouuttee _f_l_a_g;;
|
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,36 +1588,38 @@ dhcpd.conf(5) dhcpd.conf(5)
|
|||||||
dhcpd.conf(5) dhcpd.conf(5)
|
dhcpd.conf(5) dhcpd.conf(5)
|
||||||
|
|
||||||
|
|
||||||
specified in the routers option (or sending no value at
|
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
|
||||||
all), the IP address of the lease being assigned is sent
|
in a given scope, then instead of sending the value speci
|
||||||
to the client. This supposedly causes Win95 machines to
|
fied in the routers option (or sending no value at all),
|
||||||
ARP for all IP addresses, which can be helpful if your
|
the IP address of the lease being assigned is sent to the
|
||||||
router is configured for proxy ARP.
|
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
|
TThhee _s_e_r_v_e_r_-_i_d_e_n_t_i_f_i_e_r ssttaatteemmeenntt
|
||||||
|
|
||||||
sseerrvveerr--iiddeennttiiffiieerr _h_o_s_t_n_a_m_e;;
|
sseerrvveerr--iiddeennttiiffiieerr _h_o_s_t_n_a_m_e;;
|
||||||
|
|
||||||
The server-identifier statement can be used to define the
|
The server-identifier statement can be used to define the
|
||||||
value that is sent in the DHCP Server Identifier option
|
value that is sent in the DHCP Server Identifier option
|
||||||
for a given scope. The value specified mmuusstt be an IP
|
for a given scope. The value specified mmuusstt be an IP
|
||||||
address for the DHCP server, and must be reachable by all
|
address for the DHCP server, and must be reachable by all
|
||||||
clients served by a particular scope.
|
clients served by a particular scope.
|
||||||
|
|
||||||
The use of the server-identifier statement is not recom
|
The use of the server-identifier statement is not recom
|
||||||
mended - the only reason to use it is to force a value
|
mended - the only reason to use it is to force a value
|
||||||
other than the default value to be sent on occasions where
|
other than the default value to be sent on occasions where
|
||||||
the default value would be incorrect. The default value
|
the default value would be incorrect. The default value
|
||||||
is the first IP address associated with the physical net
|
is the first IP address associated with the physical net
|
||||||
work interface on which the request arrived.
|
work interface on which the request arrived.
|
||||||
|
|
||||||
The usual case where the _s_e_r_v_e_r_-_i_d_e_n_t_i_f_i_e_r statement needs
|
The usual case where the _s_e_r_v_e_r_-_i_d_e_n_t_i_f_i_e_r statement needs
|
||||||
to be sent is when a physical interface has more than one
|
to be sent is when a physical interface has more than one
|
||||||
IP address, and the one being sent by default isn't appro
|
IP address, and the one being sent by default isn't appro
|
||||||
priate for some or all clients served by that interface.
|
priate for some or all clients served by that interface.
|
||||||
Another common case is when an alias is defined for the
|
Another common case is when an alias is defined for the
|
||||||
purpose of having a consistent IP address for the DHCP
|
purpose of having a consistent IP address for the DHCP
|
||||||
server, and it is desired that the clients use this IP
|
server, and it is desired that the clients use this IP
|
||||||
address when contacting the server.
|
address when contacting the server.
|
||||||
|
|
||||||
Supplying a value for the dhcp-server-identifier option is
|
Supplying a value for the dhcp-server-identifier option is
|
||||||
@ -1627,21 +1629,19 @@ dhcpd.conf(5) dhcpd.conf(5)
|
|||||||
|
|
||||||
ddddnnss--uuppddaatteess _f_l_a_g;;
|
ddddnnss--uuppddaatteess _f_l_a_g;;
|
||||||
|
|
||||||
The _d_d_n_s_-_u_p_d_a_t_e_s parameter controls whether or not the
|
The _d_d_n_s_-_u_p_d_a_t_e_s parameter controls whether or not the
|
||||||
server will attempt to do a ddns update when a lease is
|
server will attempt to do a ddns update when a lease is
|
||||||
confirmed. Set this to _o_f_f if the server should not
|
confirmed. Set this to _o_f_f if the server should not
|
||||||
attempt to do updates within a certain scope. The _d_d_n_s_-
|
attempt to do updates within a certain scope. The _d_d_n_s_-
|
||||||
_u_p_d_a_t_e_s parameter is on by default.
|
_u_p_d_a_t_e_s parameter is on by default.
|
||||||
|
|
||||||
RREEFFEERREENNCCEE:: OOPPTTIIOONN SSTTAATTEEMMEENNTTSS
|
RREEFFEERREENNCCEE:: OOPPTTIIOONN SSTTAATTEEMMEENNTTSS
|
||||||
DHCP option statements are documented in the ddhhccpp--
|
DHCP option statements are documented in the ddhhccpp--
|
||||||
ooppttiioonnss((55)) manual page.
|
ooppttiioonnss((55)) manual page.
|
||||||
|
|
||||||
SSEEEE AALLSSOO
|
SSEEEE AALLSSOO
|
||||||
dhcpd.conf(5), dhcpd.leases(5), RFC2132, RFC2131.
|
dhcpd.conf(5), dhcpd.leases(5), RFC2132, RFC2131.
|
||||||
|
|
||||||
AAUUTTHHOORR
|
|
||||||
ddhhccppdd((88)) was written by Ted Lemon <mellon@vix.com> under a
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1654,9 +1654,11 @@ AAUUTTHHOORR
|
|||||||
dhcpd.conf(5) dhcpd.conf(5)
|
dhcpd.conf(5) dhcpd.conf(5)
|
||||||
|
|
||||||
|
|
||||||
contract with Vixie Labs. Funding for this project was
|
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
|
provided by the Internet Software Consortium. Information
|
||||||
about the Internet Software Consortium can be found at
|
about the Internet Software Consortium can be found at
|
||||||
hhttttpp::////wwwwww..iisscc..oorrgg//iisscc..
|
hhttttpp::////wwwwww..iisscc..oorrgg//iisscc..
|
||||||
|
|
||||||
|
|
||||||
@ -1706,8 +1708,6 @@ dhcpd.conf(5) dhcpd.conf(5)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -383,6 +383,8 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
|
|||||||
a state object. */
|
a state object. */
|
||||||
/* XXX this should be authenticated! */
|
/* XXX this should be authenticated! */
|
||||||
if (link -> imsg -> type == FTM_CONNECT) {
|
if (link -> imsg -> type == FTM_CONNECT) {
|
||||||
|
const char *errmsg;
|
||||||
|
int reason;
|
||||||
/* See if we can find a failover_state object that
|
/* See if we can find a failover_state object that
|
||||||
matches this connection. This message should only
|
matches this connection. This message should only
|
||||||
be received by a secondary from a primary. */
|
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
|
/* If we can't find a failover protocol state
|
||||||
for this remote host, drop the connection */
|
for this remote host, drop the connection */
|
||||||
if (!state) {
|
if (!state) {
|
||||||
|
errmsg = "unknown server";
|
||||||
|
reason = FTR_INVALID_PARTNER;
|
||||||
|
|
||||||
|
badconnect:
|
||||||
/* XXX Send a refusal message first?
|
/* XXX Send a refusal message first?
|
||||||
XXX Look in protocol spec for guidance. */
|
XXX Look in protocol spec for guidance. */
|
||||||
log_error ("Failover CONNECT from %s %d.%d.%d.%d",
|
log_error ("Failover CONNECT from %d.%d.%d.%d: %s",
|
||||||
"unknown server",
|
|
||||||
((u_int8_t *)
|
((u_int8_t *)
|
||||||
(&link -> imsg -> server_addr)) [0],
|
(&link -> imsg -> server_addr)) [0],
|
||||||
((u_int8_t *)
|
((u_int8_t *)
|
||||||
@ -407,15 +412,32 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
|
|||||||
((u_int8_t *)
|
((u_int8_t *)
|
||||||
(&link -> imsg -> server_addr)) [2],
|
(&link -> imsg -> server_addr)) [2],
|
||||||
((u_int8_t *)
|
((u_int8_t *)
|
||||||
(&link -> imsg -> server_addr)) [3]);
|
(&link -> imsg -> server_addr)) [3],
|
||||||
|
errmsg);
|
||||||
dhcp_failover_send_connectack
|
dhcp_failover_send_connectack
|
||||||
((omapi_object_t *)link,
|
((omapi_object_t *)link, state,
|
||||||
FTR_INVALID_PARTNER);
|
reason, errmsg);
|
||||||
omapi_disconnect (c, 0);
|
omapi_disconnect (c, 0);
|
||||||
link -> state = dhcp_flink_disconnected;
|
link -> state = dhcp_flink_disconnected;
|
||||||
return ISC_R_SUCCESS;
|
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)
|
if (!link -> state_object)
|
||||||
dhcp_failover_state_reference
|
dhcp_failover_state_reference
|
||||||
(&link -> state_object, state, MDL);
|
(&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) {
|
ft_options [option_code].type == FT_DDNS1) {
|
||||||
ddns_fqdn_t *ddns =
|
ddns_fqdn_t *ddns =
|
||||||
((ddns_fqdn_t *)
|
((ddns_fqdn_t *)
|
||||||
(((char *)&link -> imsg) +
|
(((char *)link -> imsg) +
|
||||||
ft_options [option_code].offset));
|
ft_options [option_code].offset));
|
||||||
|
|
||||||
op_count = (ft_options [option_code].type == FT_DDNS1
|
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;
|
op_count = option_len / op_size;
|
||||||
|
|
||||||
fo = ((failover_option_t *)
|
fo = ((failover_option_t *)
|
||||||
(((char *)&link -> imsg) +
|
(((char *)link -> imsg) +
|
||||||
ft_options [option_code].offset));
|
ft_options [option_code].offset));
|
||||||
|
|
||||||
fo -> count = op_count;
|
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,
|
dhcp_failover_link_reference (&state -> link_to_peer,
|
||||||
link, MDL);
|
link, MDL);
|
||||||
status = (dhcp_failover_send_connectack
|
status = (dhcp_failover_send_connectack
|
||||||
((omapi_object_t *)link, 0));
|
((omapi_object_t *)link, state, 0, 0));
|
||||||
if (status != ISC_R_SUCCESS) {
|
if (status != ISC_R_SUCCESS) {
|
||||||
dhcp_failover_link_dereference
|
dhcp_failover_link_dereference
|
||||||
(&state -> link_to_peer, MDL);
|
(&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");
|
dhcp_failover_state_transition (state, "connect");
|
||||||
} else if (link -> imsg -> type == FTM_CONNECTACK) {
|
} else if (link -> imsg -> type == FTM_CONNECTACK) {
|
||||||
|
const char *errmsg;
|
||||||
|
int reason;
|
||||||
if (link -> imsg -> reject_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 *)
|
((u_int8_t *)
|
||||||
(&link -> imsg -> server_addr)) [0],
|
(&link -> imsg -> server_addr)) [0],
|
||||||
((u_int8_t *)
|
((u_int8_t *)
|
||||||
@ -1074,6 +1098,7 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
|
|||||||
" rejected: ",
|
" rejected: ",
|
||||||
(dhcp_failover_reject_reason_print
|
(dhcp_failover_reject_reason_print
|
||||||
(link -> imsg -> reject_reason)));
|
(link -> imsg -> reject_reason)));
|
||||||
|
/* XXX print message from peer if peer sent message. */
|
||||||
omapi_disconnect (link -> outer, 1);
|
omapi_disconnect (link -> outer, 1);
|
||||||
return ISC_R_SUCCESS;
|
return ISC_R_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1082,8 +1107,10 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
|
|||||||
(state,
|
(state,
|
||||||
(u_int8_t *)&link -> imsg -> server_addr,
|
(u_int8_t *)&link -> imsg -> server_addr,
|
||||||
sizeof link -> imsg -> server_addr)) {
|
sizeof link -> imsg -> server_addr)) {
|
||||||
log_error ("Failover CONNECTACK from %s %d.%d.%d.%d",
|
errmsg = "unknown server";
|
||||||
"unknown server",
|
reason = FTR_INVALID_PARTNER;
|
||||||
|
badconnectack:
|
||||||
|
log_error ("Failover CONNECTACK from %d.%d.%d.%d: %s",
|
||||||
((u_int8_t *)
|
((u_int8_t *)
|
||||||
(&link -> imsg -> server_addr)) [0],
|
(&link -> imsg -> server_addr)) [0],
|
||||||
((u_int8_t *)
|
((u_int8_t *)
|
||||||
@ -1091,27 +1118,19 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
|
|||||||
((u_int8_t *)
|
((u_int8_t *)
|
||||||
(&link -> imsg -> server_addr)) [2],
|
(&link -> imsg -> server_addr)) [2],
|
||||||
((u_int8_t *)
|
((u_int8_t *)
|
||||||
(&link -> imsg -> server_addr)) [3]);
|
(&link -> imsg -> server_addr)) [3],
|
||||||
|
errmsg);
|
||||||
dhcp_failover_send_disconnect ((omapi_object_t *)link,
|
dhcp_failover_send_disconnect ((omapi_object_t *)link,
|
||||||
FTR_INVALID_PARTNER, 0);
|
reason, errmsg);
|
||||||
omapi_disconnect (link -> outer, 0);
|
omapi_disconnect (link -> outer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state -> link_to_peer) {
|
if (state -> link_to_peer) {
|
||||||
log_error ("Failover CONNECTACK %s %d.%d.%d.%d",
|
errmsg = "already connected";
|
||||||
"while already connected",
|
reason = FTR_DUP_CONNECTION;
|
||||||
((u_int8_t *)
|
goto badconnectack;
|
||||||
(&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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dhcp_failover_link_reference (&state -> link_to_peer,
|
dhcp_failover_link_reference (&state -> link_to_peer,
|
||||||
link, MDL);
|
link, MDL);
|
||||||
dhcp_failover_state_transition (state, "connect");
|
dhcp_failover_state_transition (state, "connect");
|
||||||
@ -1331,9 +1350,14 @@ int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state)
|
|||||||
{
|
{
|
||||||
int lts;
|
int lts;
|
||||||
int leases_queued = 0;
|
int leases_queued = 0;
|
||||||
struct lease *lp;
|
struct lease *lp = (struct lease *)0;
|
||||||
|
struct lease *next = (struct lease *)0;
|
||||||
struct shared_network *s;
|
struct shared_network *s;
|
||||||
struct pool *p;
|
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)
|
if (state -> my_state != normal || state -> i_am == secondary)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1342,32 +1366,59 @@ int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state)
|
|||||||
for (p = s -> pools; p; p = p -> next) {
|
for (p = s -> pools; p; p = p -> next) {
|
||||||
if (p -> failover_peer != state)
|
if (p -> failover_peer != state)
|
||||||
continue;
|
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,
|
(unsigned long)p, p -> lease_count,
|
||||||
p -> local_leases, p -> peer_leases);
|
p -> free_leases, p -> backup_leases);
|
||||||
|
|
||||||
lts = ((p -> local_leases +
|
/* Right now we're giving the peer half of the free leases.
|
||||||
p -> peer_leases) / 2) - p -> peer_leases;
|
If we have more leases than the peer (i.e., more than
|
||||||
if (lts > 1) {
|
half), then the number of leases we have, less the number
|
||||||
struct lease lt;
|
of leases the peer has, will be how many more leases we
|
||||||
|
have than the peer has. So if we send half that number
|
||||||
leases_queued += lts;
|
to the peer, we should be even. */
|
||||||
for (lp = p -> last_lease; lp && lts;
|
if (p -> failover_peer -> i_am == primary) {
|
||||||
lp = lp -> prev) {
|
lts = (p -> free_leases - p -> backup_leases) / 2;
|
||||||
if (!(lp -> flags & PEER_IS_OWNER)) {
|
peer_lease_state = FTS_BACKUP;
|
||||||
lp -> flags |= PEER_IS_OWNER;
|
my_lease_state = FTS_FREE;
|
||||||
lp -> tstp = cur_time;
|
lq = &p -> free;
|
||||||
if (!write_lease (lp) ||
|
} else {
|
||||||
!commit_leases () ||
|
lts = (p -> backup_leases - p -> free_leases) / 2;
|
||||||
!dhcp_failover_queue_update (lp)) {
|
peer_lease_state = FTS_FREE;
|
||||||
log_info ("%s lease %s on giveaway",
|
my_lease_state = FTS_BACKUP;
|
||||||
"unable to commit",
|
lq = &p -> backup;
|
||||||
piaddr (lp -> ip_addr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lts > 1) {
|
||||||
|
lease_reference (&lp, *lq, MDL);
|
||||||
|
|
||||||
|
while (lp && lts) {
|
||||||
|
/* Remember the next lease in the list. */
|
||||||
|
if (next)
|
||||||
|
lease_dereference (&next, MDL);
|
||||||
|
if (lp -> next)
|
||||||
|
lease_reference (&next, lp -> next, MDL);
|
||||||
|
|
||||||
|
--lts;
|
||||||
|
++leases_queued;
|
||||||
|
lp -> next_binding_state = peer_lease_state;
|
||||||
|
lp -> tstp = cur_time;
|
||||||
|
lp -> starts = cur_time;
|
||||||
|
if (!supersede_lease (lp, (struct lease *)0, 1, 1, 0))
|
||||||
|
{
|
||||||
|
log_info ("can't commit lease %s on giveaway",
|
||||||
|
piaddr (lp -> ip_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
lease_dereference (&lp, MDL);
|
||||||
|
if (next)
|
||||||
|
lease_reference (&lp, next, MDL);
|
||||||
|
}
|
||||||
|
if (next)
|
||||||
|
lease_dereference (&next, MDL);
|
||||||
|
if (lp)
|
||||||
|
lease_dereference (&lp, MDL);
|
||||||
|
|
||||||
|
}
|
||||||
if (lts > 1) {
|
if (lts > 1) {
|
||||||
log_info ("lease imbalance - lts = %d", lts);
|
log_info ("lease imbalance - lts = %d", lts);
|
||||||
leases_queued -= 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_poolresp (state, leases_queued);
|
||||||
|
dhcp_failover_send_updates (state);
|
||||||
return leases_queued;
|
return leases_queued;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1388,12 +1440,15 @@ int dhcp_failover_pool_check (struct pool *pool)
|
|||||||
pool -> failover_peer -> my_state != normal)
|
pool -> failover_peer -> my_state != normal)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
log_info ("pool %lx total %d local free %d peer free %d",
|
if (pool -> failover_peer -> i_am == primary)
|
||||||
(unsigned long)pool, pool -> lease_count,
|
lts = (pool -> backup_leases - pool -> free_leases) / 2;
|
||||||
pool -> local_leases, pool -> peer_leases);
|
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) {
|
if (lts > 1) {
|
||||||
/* XXX What about multiple pools? */
|
/* XXX What about multiple pools? */
|
||||||
dhcp_failover_send_poolreq (pool -> failover_peer);
|
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
|
not an error for this to be called on a lease for which there's no
|
||||||
failover peer. */
|
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;
|
dhcp_failover_state_t *state;
|
||||||
|
|
||||||
@ -1509,7 +1564,8 @@ int dhcp_failover_queue_update (struct lease *lease)
|
|||||||
}
|
}
|
||||||
lease_reference (&state -> update_queue_tail, lease, MDL);
|
lease_reference (&state -> update_queue_tail, lease, MDL);
|
||||||
lease -> flags |= ON_UPDATE_QUEUE;
|
lease -> flags |= ON_UPDATE_QUEUE;
|
||||||
dhcp_failover_send_updates (state);
|
if (immediate)
|
||||||
|
dhcp_failover_send_updates (state);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1530,7 +1586,7 @@ void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *state,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (lp = state -> ack_queue_head;
|
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) {
|
if (lp) {
|
||||||
lease_dereference (&lp -> next_pending, MDL);
|
lease_dereference (&lp -> next_pending, MDL);
|
||||||
@ -2140,7 +2196,8 @@ failover_option_t *dhcp_failover_option_printf (unsigned code,
|
|||||||
char *obuf,
|
char *obuf,
|
||||||
unsigned *obufix,
|
unsigned *obufix,
|
||||||
unsigned obufmax,
|
unsigned obufmax,
|
||||||
const char *fmt, ...) {
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
char tbuf [256];
|
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_link_t *link;
|
||||||
dhcp_failover_state_t *state;
|
dhcp_failover_state_t *state;
|
||||||
isc_result_t status;
|
isc_result_t status;
|
||||||
|
char hba [32];
|
||||||
#if defined (DEBUG_FAILOVER_MESSAGES)
|
#if defined (DEBUG_FAILOVER_MESSAGES)
|
||||||
char obuf [64];
|
char obuf [64];
|
||||||
unsigned obufix = 0;
|
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)
|
if (!l -> outer || l -> outer -> type != omapi_type_connection)
|
||||||
return ISC_R_INVALIDARG;
|
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
|
status = (dhcp_failover_put_message
|
||||||
(link, l -> outer,
|
(link, l -> outer,
|
||||||
FTM_CONNECT,
|
FTM_CONNECT,
|
||||||
@ -2507,7 +2571,9 @@ isc_result_t dhcp_failover_send_connect (omapi_object_t *l)
|
|||||||
0, 0),
|
0, 0),
|
||||||
dhcp_failover_make_option (FTO_MCLT, FMA,
|
dhcp_failover_make_option (FTO_MCLT, FMA,
|
||||||
state -> mclt),
|
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));
|
(failover_option_t *)0));
|
||||||
|
|
||||||
#if defined (DEBUG_FAILOVER_MESSAGES)
|
#if defined (DEBUG_FAILOVER_MESSAGES)
|
||||||
@ -2521,10 +2587,11 @@ isc_result_t dhcp_failover_send_connect (omapi_object_t *l)
|
|||||||
return status;
|
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_link_t *link;
|
||||||
dhcp_failover_state_t *state;
|
|
||||||
isc_result_t status;
|
isc_result_t status;
|
||||||
#if defined (DEBUG_FAILOVER_MESSAGES)
|
#if defined (DEBUG_FAILOVER_MESSAGES)
|
||||||
char obuf [64];
|
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)
|
if (!l || l -> type != dhcp_type_failover_link)
|
||||||
return ISC_R_INVALIDARG;
|
return ISC_R_INVALIDARG;
|
||||||
link = (dhcp_failover_link_t *)l;
|
link = (dhcp_failover_link_t *)l;
|
||||||
state = link -> state_object;
|
|
||||||
if (!l -> outer || l -> outer -> type != omapi_type_connection)
|
if (!l -> outer || l -> outer -> type != omapi_type_connection)
|
||||||
return ISC_R_INVALIDARG;
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
status = (dhcp_failover_put_message
|
status = (dhcp_failover_put_message
|
||||||
(link, l -> outer,
|
(link, l -> outer,
|
||||||
FTM_CONNECTACK,
|
FTM_CONNECTACK,
|
||||||
dhcp_failover_make_option (FTO_SERVER_ADDR, FMA,
|
(state
|
||||||
state -> server_identifier.len,
|
? (dhcp_failover_make_option
|
||||||
state -> server_identifier.data),
|
(FTO_SERVER_ADDR, FMA,
|
||||||
dhcp_failover_make_option (FTO_MAX_UNACKED, FMA,
|
state -> server_identifier.len,
|
||||||
state -> max_flying_updates),
|
state -> server_identifier.data))
|
||||||
dhcp_failover_make_option (FTO_RECEIVE_TIMER, FMA,
|
: &skip_failover_option),
|
||||||
state -> max_response_delay),
|
(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,
|
dhcp_failover_option_printf (FTO_VENDOR_CLASS, FMA,
|
||||||
"isc-%s", DHCP_VERSION),
|
"isc-%s", DHCP_VERSION),
|
||||||
dhcp_failover_make_option (FTO_PROTOCOL_VERSION, FMA,
|
dhcp_failover_make_option (FTO_PROTOCOL_VERSION, FMA,
|
||||||
@ -2563,7 +2636,11 @@ isc_result_t dhcp_failover_send_connectack (omapi_object_t *l, int reason)
|
|||||||
? dhcp_failover_make_option (FTO_REJECT_REASON,
|
? dhcp_failover_make_option (FTO_REJECT_REASON,
|
||||||
FMA, reason)
|
FMA, reason)
|
||||||
: &skip_failover_option),
|
: &skip_failover_option),
|
||||||
(failover_option_t *)0));
|
(errmsg
|
||||||
|
? dhcp_failover_make_option (FTO_MESSAGE, FMA,
|
||||||
|
strlen (errmsg), errmsg)
|
||||||
|
: &skip_failover_option),
|
||||||
|
(failover_option_t *)0));
|
||||||
|
|
||||||
#if defined (DEBUG_FAILOVER_MESSAGES)
|
#if defined (DEBUG_FAILOVER_MESSAGES)
|
||||||
if (status != ISC_R_SUCCESS)
|
if (status != ISC_R_SUCCESS)
|
||||||
@ -2635,7 +2712,6 @@ isc_result_t dhcp_failover_send_bind_update (dhcp_failover_state_t *state,
|
|||||||
#if defined (DEBUG_FAILOVER_MESSAGES)
|
#if defined (DEBUG_FAILOVER_MESSAGES)
|
||||||
char obuf [64];
|
char obuf [64];
|
||||||
unsigned obufix = 0;
|
unsigned obufix = 0;
|
||||||
int binding_status;
|
|
||||||
|
|
||||||
# define FMA obuf, &obufix, sizeof obuf
|
# define FMA obuf, &obufix, sizeof obuf
|
||||||
failover_print (FMA, "(bndupd");
|
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)
|
if (!link -> outer || link -> outer -> type != omapi_type_connection)
|
||||||
return ISC_R_INVALIDARG;
|
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. */
|
/* Send the update. */
|
||||||
status = (dhcp_failover_put_message
|
status = (dhcp_failover_put_message
|
||||||
(link, link -> outer,
|
(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.len,
|
||||||
lease -> ip_addr.iabuf),
|
lease -> ip_addr.iabuf),
|
||||||
dhcp_failover_make_option (FTO_BINDING_STATUS, FMA,
|
dhcp_failover_make_option (FTO_BINDING_STATUS, FMA,
|
||||||
binding_status),
|
lease -> binding_state),
|
||||||
lease -> uid_len
|
lease -> uid_len
|
||||||
? dhcp_failover_make_option (FTO_CLIENT_IDENTIFIER, FMA,
|
? dhcp_failover_make_option (FTO_CLIENT_IDENTIFIER, FMA,
|
||||||
lease -> uid_len,
|
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)
|
#if defined (DEBUG_FAILOVER_MESSAGES)
|
||||||
char obuf [64];
|
char obuf [64];
|
||||||
unsigned obufix = 0;
|
unsigned obufix = 0;
|
||||||
int binding_status;
|
|
||||||
|
|
||||||
# define FMA obuf, &obufix, sizeof obuf
|
# define FMA obuf, &obufix, sizeof obuf
|
||||||
failover_print (FMA, "(bndack");
|
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)
|
if (!link -> outer || link -> outer -> type != omapi_type_connection)
|
||||||
return ISC_R_INVALIDARG;
|
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)
|
if (!message && reason)
|
||||||
message = dhcp_failover_reject_reason_print (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.len,
|
||||||
lease -> ip_addr.iabuf),
|
lease -> ip_addr.iabuf),
|
||||||
dhcp_failover_make_option (FTO_BINDING_STATUS, FMA,
|
dhcp_failover_make_option (FTO_BINDING_STATUS, FMA,
|
||||||
binding_status),
|
lease -> binding_state),
|
||||||
lease -> uid_len
|
lease -> uid_len
|
||||||
? dhcp_failover_make_option (FTO_CLIENT_IDENTIFIER, FMA,
|
? dhcp_failover_make_option (FTO_CLIENT_IDENTIFIER, FMA,
|
||||||
lease -> uid_len,
|
lease -> uid_len,
|
||||||
@ -2864,7 +2899,7 @@ isc_result_t dhcp_failover_send_poolresp (dhcp_failover_state_t *state,
|
|||||||
unsigned obufix = 0;
|
unsigned obufix = 0;
|
||||||
|
|
||||||
# define FMA obuf, &obufix, sizeof obuf
|
# define FMA obuf, &obufix, sizeof obuf
|
||||||
failover_print (FMA, "(poolreq");
|
failover_print (FMA, "(poolresp");
|
||||||
#else
|
#else
|
||||||
# define FMA (unsigned char *)0, (unsigned *)0, 0
|
# define FMA (unsigned char *)0, (unsigned *)0, 0
|
||||||
#endif
|
#endif
|
||||||
@ -2902,6 +2937,7 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
|
|||||||
struct iaddr ia;
|
struct iaddr ia;
|
||||||
int reason = FTR_MISC_REJECT;
|
int reason = FTR_MISC_REJECT;
|
||||||
const char *message;
|
const char *message;
|
||||||
|
int new_binding_state;
|
||||||
|
|
||||||
ia.len = sizeof msg -> assigned_addr;
|
ia.len = sizeof msg -> assigned_addr;
|
||||||
memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
|
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 (msg -> options_present & FTB_BINDING_STATUS) {
|
||||||
if (state -> i_am == primary) {
|
/* Check the requested transition to make sure it's
|
||||||
if (msg -> binding_status == FTS_BACKUP)
|
valid. */
|
||||||
lease -> flags |= PEER_IS_OWNER;
|
new_binding_state = (binding_state_transition_check
|
||||||
else if (msg -> binding_status == FTS_FREE)
|
(lease, state, msg -> binding_status));
|
||||||
lease -> flags &= ~PEER_IS_OWNER;
|
if (new_binding_state != msg -> binding_status) {
|
||||||
} else {
|
dhcp_failover_send_bind_ack
|
||||||
if (msg -> binding_status == FTS_BACKUP)
|
(state, lease, msg, FTR_FATAL_CONFLICT,
|
||||||
lease -> flags &= PEER_IS_OWNER;
|
"invalid binding state transition");
|
||||||
else if (msg -> binding_status == FTS_FREE)
|
|
||||||
lease -> flags |= ~PEER_IS_OWNER;
|
|
||||||
}
|
}
|
||||||
|
lt -> next_binding_state = new_binding_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to install the new information. */
|
/* 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";
|
message = "database update failed";
|
||||||
bad:
|
bad:
|
||||||
dhcp_failover_send_bind_ack (state, lease, msg,
|
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. */
|
/* Try to install the new information. */
|
||||||
supersede_lease (lease, lt, 1, 0);
|
supersede_lease (lease, lt, 1, 0, 0);
|
||||||
|
|
||||||
state -> cur_unacked_updates--;
|
state -> cur_unacked_updates--;
|
||||||
dhcp_failover_ack_queue_remove (state, lease);
|
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;
|
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,
|
oc = lookup_option (&dhcp_universe, packet -> options,
|
||||||
DHO_DHCP_CLIENT_IDENTIFIER);
|
DHO_DHCP_CLIENT_IDENTIFIER);
|
||||||
memset (&ds, 0, sizeof ds);
|
memset (&ds, 0, sizeof ds);
|
||||||
@ -3139,6 +3179,195 @@ int load_balance_mine (struct packet *packet, dhcp_failover_state_t *state)
|
|||||||
return !hm;
|
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,
|
OMAPI_OBJECT_ALLOC (dhcp_failover_state, dhcp_failover_state_t,
|
||||||
dhcp_type_failover_state)
|
dhcp_type_failover_state)
|
||||||
OMAPI_OBJECT_ALLOC (dhcp_failover_listener, dhcp_failover_listener_t,
|
OMAPI_OBJECT_ALLOC (dhcp_failover_listener, dhcp_failover_listener_t,
|
||||||
|
772
server/mdb.c
772
server/mdb.c
@ -3,7 +3,7 @@
|
|||||||
Server-specific in-memory database support. */
|
Server-specific in-memory database support. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996-1999 Internet Software Consortium.
|
* Copyright (c) 1996-2000 Internet Software Consortium.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -498,45 +498,27 @@ void new_address_range (low, high, subnet, pool)
|
|||||||
subnet -> netmask,
|
subnet -> netmask,
|
||||||
i + min)),
|
i + min)),
|
||||||
isc_result_totext (status));
|
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
|
#endif
|
||||||
lp -> ip_addr = ip_addr (subnet -> net,
|
lp -> ip_addr = ip_addr (subnet -> net,
|
||||||
subnet -> netmask, i + min);
|
subnet -> netmask, i + min);
|
||||||
lp -> starts = lp -> timestamp = MIN_TIME;
|
lp -> starts = lp -> timestamp = MIN_TIME;
|
||||||
lp -> ends = MIN_TIME;
|
lp -> ends = MIN_TIME;
|
||||||
subnet_reference (&lp -> subnet, subnet, MDL);
|
subnet_reference (&lp -> subnet, subnet, MDL);
|
||||||
pool_reference (&lp -> pool, pool, MDL);
|
pool_reference (&lp -> pool, pool, MDL);
|
||||||
#if defined (FAILOVER_PROTOCOL)
|
lp -> binding_state = FTS_FREE;
|
||||||
if (pool -> failover_peer &&
|
lp -> next_binding_state = FTS_FREE;
|
||||||
pool -> failover_peer -> i_am == secondary)
|
lp -> flags = 0;
|
||||||
lp -> flags = PEER_IS_OWNER;
|
|
||||||
else
|
|
||||||
lp -> flags = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Link this entry into the list. */
|
/* Link this entry into the list. */
|
||||||
if (pool -> leases) {
|
if (pool -> free) {
|
||||||
lease_reference (&lp -> next, pool -> leases, MDL);
|
lease_reference (&lp -> next, pool -> free, MDL);
|
||||||
lease_dereference (&pool -> leases, MDL);
|
lease_dereference (&pool -> free, MDL);
|
||||||
}
|
}
|
||||||
lease_reference (&pool -> leases, lp, MDL);
|
lease_reference (&pool -> free, lp, MDL);
|
||||||
if (lp -> next)
|
|
||||||
lease_reference (&lp -> next -> prev,
|
|
||||||
pool -> leases, MDL);
|
|
||||||
lease_hash_add (lease_ip_addr_hash, lp -> ip_addr.iabuf,
|
lease_hash_add (lease_ip_addr_hash, lp -> ip_addr.iabuf,
|
||||||
lp -> ip_addr.len, lp, MDL);
|
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... */
|
/* Find out if any dangling leases are in range... */
|
||||||
plp = (struct lease *)0;
|
plp = (struct lease *)0;
|
||||||
for (lp = dangling_leases; lp; lp = lp -> next) {
|
for (lp = dangling_leases; lp; lp = lp -> next) {
|
||||||
@ -568,7 +550,7 @@ void new_address_range (low, high, subnet, pool)
|
|||||||
lp -> hostname = (char *)0;
|
lp -> hostname = (char *)0;
|
||||||
lt -> client_hostname = lp -> client_hostname;
|
lt -> client_hostname = lp -> client_hostname;
|
||||||
lp -> client_hostname = (char *)0;
|
lp -> client_hostname = (char *)0;
|
||||||
supersede_lease (lt, lp, 0, 0);
|
supersede_lease (lt, lp, 0, 0, 0);
|
||||||
lease_dereference (<, MDL);
|
lease_dereference (<, MDL);
|
||||||
}
|
}
|
||||||
lease_dereference (&lp, 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
|
/* If we don't have a place for this lease yet, save it for
|
||||||
later. */
|
later. */
|
||||||
if (!find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
|
if (!find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
|
||||||
if (comp -> next)
|
if (lease -> next)
|
||||||
lease_dereference (&comp -> next, MDL);
|
lease_dereference (&lease -> next, MDL);
|
||||||
if (dangling_leases)
|
if (dangling_leases)
|
||||||
lease_reference (&comp -> next, dangling_leases, MDL);
|
lease_reference (&lease -> next, dangling_leases, MDL);
|
||||||
lease_reference (&dangling_leases, comp, MDL);
|
lease_reference (&dangling_leases, lease, MDL);
|
||||||
if (comp -> prev)
|
|
||||||
lease_dereference (&comp -> prev, MDL);
|
|
||||||
} else {
|
} 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
|
list of leases by expiry time so that we can always find the oldest
|
||||||
lease. */
|
lease. */
|
||||||
|
|
||||||
int supersede_lease (comp, lease, commit, propogate)
|
int supersede_lease (comp, lease, commit, propogate, pimmediate)
|
||||||
struct lease *comp, *lease;
|
struct lease *comp, *lease;
|
||||||
int commit;
|
int commit;
|
||||||
int propogate;
|
int propogate;
|
||||||
|
int pimmediate;
|
||||||
{
|
{
|
||||||
int enter_uid = 0;
|
int enter_uid = 0;
|
||||||
int enter_hwaddr = 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... */
|
/* Static leases are not currently kept in the database... */
|
||||||
if (lease -> flags & STATIC_LEASE)
|
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
|
lease, then we allow that, in case a dynamic BOOTP lease is
|
||||||
requested *after* a DHCP lease has been assigned. */
|
requested *after* a DHCP lease has been assigned. */
|
||||||
|
|
||||||
if (!(lease -> flags & ABANDONED_LEASE) &&
|
if (lease -> binding_state != FTS_ABANDONED &&
|
||||||
comp -> ends > cur_time &&
|
(comp -> binding_state == FTS_ACTIVE ||
|
||||||
|
comp -> binding_state == FTS_RESERVED ||
|
||||||
|
comp -> binding_state == FTS_BOOTP) &&
|
||||||
(((comp -> uid && lease -> uid) &&
|
(((comp -> uid && lease -> uid) &&
|
||||||
(comp -> uid_len != lease -> uid_len ||
|
(comp -> uid_len != lease -> uid_len ||
|
||||||
memcmp (comp -> uid, lease -> uid, comp -> 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);
|
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)
|
#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 -> cltt = lease -> cltt;
|
||||||
comp -> tstp = lease -> tstp;
|
comp -> tstp = lease -> tstp;
|
||||||
comp -> tsfp = lease -> tsfp;
|
comp -> tsfp = lease -> tsfp;
|
||||||
#endif /* FAILOVER_PROTOCOL */
|
#endif /* FAILOVER_PROTOCOL */
|
||||||
comp -> ends = lease -> ends;
|
comp -> ends = lease -> ends;
|
||||||
|
comp -> next_binding_state = lease -> next_binding_state;
|
||||||
|
|
||||||
/* If there's an expiry event on this lease, process it or
|
just_move_it:
|
||||||
queue it. */
|
/* Figure out which queue it's on. */
|
||||||
#if !defined (FAILOVER_PROTOCOL)
|
switch (comp -> binding_state) {
|
||||||
if (comp -> on_expiry) {
|
case FTS_FREE:
|
||||||
#endif
|
lq = &comp -> pool -> free;
|
||||||
if (comp -> ends <= cur_time && commit) {
|
comp -> pool -> free_leases--;
|
||||||
if (comp -> on_expiry) {
|
break;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No sense releasing a lease after it's expired. */
|
case FTS_ACTIVE:
|
||||||
if (comp -> on_release)
|
case FTS_RESERVED:
|
||||||
executable_statement_dereference
|
case FTS_BOOTP:
|
||||||
(&comp -> on_release, MDL);
|
lq = &comp -> pool -> active;
|
||||||
} else {
|
break;
|
||||||
/* 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.
|
|
||||||
|
|
||||||
We do not actually set the timeout unless commit is
|
case FTS_EXPIRED:
|
||||||
true - we don't want to thrash the timer queue when
|
case FTS_RELEASED:
|
||||||
reading the lease database. Instead, the database
|
case FTS_RESET:
|
||||||
code calls the expiry event on each pool after
|
lq = &comp -> pool -> expired;
|
||||||
reading in the lease file, and the expiry code sets
|
break;
|
||||||
the timer if there's anything left to expire after
|
|
||||||
it's run any outstanding expiry events on the
|
case FTS_ABANDONED:
|
||||||
pool. */
|
lq = &comp -> pool -> abandoned;
|
||||||
if (comp -> pool) {
|
break;
|
||||||
if (!comp -> pool -> next_expiry ||
|
|
||||||
(comp -> ends <
|
case FTS_BACKUP:
|
||||||
comp -> pool -> next_expiry -> ends)) {
|
lq = &comp -> pool -> backup;
|
||||||
if (comp -> pool -> next_expiry)
|
comp -> pool -> backup_leases--;
|
||||||
lease_dereference
|
break;
|
||||||
(&comp -> pool -> next_expiry,
|
|
||||||
MDL);
|
default:
|
||||||
lease_reference
|
log_error ("Lease with bogus binding state: %d",
|
||||||
(&comp -> pool -> next_expiry,
|
comp -> binding_state);
|
||||||
comp, MDL);
|
return 0;
|
||||||
if (commit)
|
}
|
||||||
add_timeout (comp -> ends,
|
|
||||||
pool_timer,
|
/* Remove the lease from its current place in its current
|
||||||
comp -> pool,
|
timer sequence. */
|
||||||
(tvref_t)pool_reference,
|
prev = (struct lease *)0;
|
||||||
(tvunref_t)
|
for (lp = *lq; lp; lp = lp -> next) {
|
||||||
pool_dereference);
|
if (lp == comp)
|
||||||
} else if (comp -> ends ==
|
break;
|
||||||
comp -> pool -> next_expiry -> ends) {
|
prev = lp;
|
||||||
/* 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
|
if (!lp) {
|
||||||
last on the list that needs an expiry
|
log_error ("Lease with binding state %s not on its queue.",
|
||||||
event - otherwise we'll miss expiry
|
(comp -> binding_state < 1 &&
|
||||||
events until the server restarts. */
|
comp -> binding_state < FTS_BOOTP)
|
||||||
struct lease *foo;
|
? "unknown"
|
||||||
struct lease *install = comp;
|
: binding_state_names [comp -> binding_state - 1]);
|
||||||
for (foo = comp;
|
return 0;
|
||||||
foo && foo -> ends == comp -> ends;
|
}
|
||||||
foo = foo -> next) {
|
|
||||||
#if !defined (FAILOVER_PROTOCOL)
|
if (prev) {
|
||||||
if (foo -> on_expiry)
|
lease_dereference (&prev -> next, MDL);
|
||||||
#endif
|
if (comp -> next) {
|
||||||
install = foo;
|
lease_reference (&prev -> next, comp -> next, MDL);
|
||||||
}
|
lease_dereference (&comp -> next, MDL);
|
||||||
lease_dereference
|
}
|
||||||
(&comp -> pool -> next_expiry,
|
} else {
|
||||||
MDL);
|
lease_dereference (lq, MDL);
|
||||||
lease_reference
|
if (comp -> next) {
|
||||||
(&comp -> pool -> next_expiry,
|
lease_reference (lq, comp -> next, MDL);
|
||||||
install, MDL);
|
lease_dereference (&comp -> next, MDL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#if !defined (FAILOVER_PROTOCOL)
|
/* Make the state transition. */
|
||||||
|
if (commit)
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return zero if we didn't commit the lease to permanent storage;
|
/* Return zero if we didn't commit the lease to permanent storage;
|
||||||
nonzero if we did. */
|
nonzero if we did. */
|
||||||
return commit && write_lease (comp) && commit_leases ()
|
return commit && write_lease (comp) && commit_leases ()
|
||||||
#if defined (FAILOVER_PROTOCOL)
|
#if defined (FAILOVER_PROTOCOL)
|
||||||
&& (!propogate || dhcp_failover_queue_update (comp))
|
&& (!propogate ||
|
||||||
|
dhcp_failover_queue_update (comp, pimmediate))
|
||||||
#endif
|
#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
|
/* Copy the contents of one lease into another, correctly maintaining
|
||||||
reference counts. */
|
reference counts. */
|
||||||
int lease_copy (struct lease **lp,
|
int lease_copy (struct lease **lp,
|
||||||
@ -1242,6 +1190,8 @@ int lease_copy (struct lease **lp,
|
|||||||
lt -> tstp = lease -> tstp;
|
lt -> tstp = lease -> tstp;
|
||||||
lt -> tsfp = lease -> tsfp;
|
lt -> tsfp = lease -> tsfp;
|
||||||
lt -> cltt = lease -> cltt;
|
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);
|
status = lease_reference (lp, lt, file, line);
|
||||||
lease_dereference (<, MDL);
|
lease_dereference (<, MDL);
|
||||||
return status == ISC_R_SUCCESS;
|
return status == ISC_R_SUCCESS;
|
||||||
@ -1252,8 +1202,6 @@ void release_lease (lease, packet)
|
|||||||
struct lease *lease;
|
struct lease *lease;
|
||||||
struct packet *packet;
|
struct packet *packet;
|
||||||
{
|
{
|
||||||
struct lease *lt;
|
|
||||||
|
|
||||||
/* If there are statements to execute when the lease is
|
/* If there are statements to execute when the lease is
|
||||||
released, execute them. */
|
released, execute them. */
|
||||||
if (lease -> on_release) {
|
if (lease -> on_release) {
|
||||||
@ -1272,21 +1220,26 @@ void release_lease (lease, packet)
|
|||||||
executable_statement_dereference (&lease -> on_expiry, MDL);
|
executable_statement_dereference (&lease -> on_expiry, MDL);
|
||||||
|
|
||||||
if (lease -> ends > cur_time) {
|
if (lease -> ends > cur_time) {
|
||||||
if (!lease_copy (<, lease, MDL))
|
if (lease -> on_commit)
|
||||||
return;
|
executable_statement_dereference (&lease -> on_commit,
|
||||||
|
|
||||||
if (lt -> on_commit)
|
|
||||||
executable_statement_dereference (< -> on_commit,
|
|
||||||
MDL);
|
MDL);
|
||||||
|
|
||||||
/* Blow away any bindings. */
|
/* Blow away any bindings. */
|
||||||
lt -> scope.bindings = (struct binding *)0;
|
/* XXX free them?!? */
|
||||||
|
lease -> scope.bindings = (struct binding *)0;
|
||||||
lt -> ends = cur_time;
|
lease -> ends = cur_time;
|
||||||
if (lt -> billing_class)
|
#if defined (FAILOVER_PROTOCOL)
|
||||||
class_dereference (< -> billing_class, MDL);
|
if (lease -> pool && lease -> pool -> failover_peer) {
|
||||||
supersede_lease (lease, lt, 1, 1);
|
lease -> next_binding_state = FTS_RELEASED;
|
||||||
lease_dereference (<, MDL);
|
} 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;
|
struct lease *lt = (struct lease *)0;
|
||||||
|
|
||||||
lease -> flags |= ABANDONED_LEASE;
|
|
||||||
if (!lease_copy (<, lease, MDL))
|
if (!lease_copy (<, lease, MDL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1312,8 +1264,9 @@ void abandon_lease (lease, message)
|
|||||||
|
|
||||||
/* Blow away any bindings. */
|
/* Blow away any bindings. */
|
||||||
lt -> scope.bindings = (struct binding *)0;
|
lt -> scope.bindings = (struct binding *)0;
|
||||||
|
|
||||||
lt -> ends = cur_time; /* XXX */
|
lt -> ends = cur_time; /* XXX */
|
||||||
|
lt -> next_binding_state = FTS_ABANDONED;
|
||||||
|
|
||||||
log_error ("Abandoning IP address %s: %s",
|
log_error ("Abandoning IP address %s: %s",
|
||||||
piaddr (lease -> ip_addr), message);
|
piaddr (lease -> ip_addr), message);
|
||||||
lt -> hardware_addr.hlen = 0;
|
lt -> hardware_addr.hlen = 0;
|
||||||
@ -1324,7 +1277,7 @@ void abandon_lease (lease, message)
|
|||||||
lt -> uid_max = 0;
|
lt -> uid_max = 0;
|
||||||
if (lt -> billing_class)
|
if (lt -> billing_class)
|
||||||
class_dereference (< -> billing_class, MDL);
|
class_dereference (< -> billing_class, MDL);
|
||||||
supersede_lease (lease, lt, 1, 1);
|
supersede_lease (lease, lt, 1, 1, 1);
|
||||||
lease_dereference (<, MDL);
|
lease_dereference (<, MDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1349,6 +1302,15 @@ void dissociate_lease (lease)
|
|||||||
/* Blow away any bindings. */
|
/* Blow away any bindings. */
|
||||||
lt -> scope.bindings = (struct binding *)0;
|
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 -> ends = cur_time; /* XXX */
|
||||||
lt -> hardware_addr.hlen = 0;
|
lt -> hardware_addr.hlen = 0;
|
||||||
if (lt -> uid != lt -> uid_buf)
|
if (lt -> uid != lt -> uid_buf)
|
||||||
@ -1358,7 +1320,7 @@ void dissociate_lease (lease)
|
|||||||
lt -> uid_max = 0;
|
lt -> uid_max = 0;
|
||||||
if (lt -> billing_class)
|
if (lt -> billing_class)
|
||||||
class_dereference (< -> billing_class, MDL);
|
class_dereference (< -> billing_class, MDL);
|
||||||
supersede_lease (lease, lt, 1, 1);
|
supersede_lease (lease, lt, 1, 1, 1);
|
||||||
lease_dereference (<, MDL);
|
lease_dereference (<, MDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1367,72 +1329,75 @@ void pool_timer (vpool)
|
|||||||
void *vpool;
|
void *vpool;
|
||||||
{
|
{
|
||||||
struct pool *pool;
|
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;
|
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)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Skip entries that aren't set to expire. */
|
#define FREE_LEASES 0
|
||||||
if (lease -> on_expiry) {
|
lptr [FREE_LEASES] = &pool -> free;
|
||||||
/* Okay, the current lease needs to expire, so
|
#define ACTIVE_LEASES 1
|
||||||
do it. */
|
lptr [ACTIVE_LEASES] = &pool -> active;
|
||||||
execute_statements ((struct packet *)0, lease,
|
#define EXPIRED_LEASES 2
|
||||||
(struct option_state *)0,
|
lptr [EXPIRED_LEASES] = &pool -> expired;
|
||||||
(struct option_state *)0, /* XXX */
|
#define ABANDONED_LEASES 3
|
||||||
&lease -> scope,
|
lptr [ABANDONED_LEASES] = &pool -> abandoned;
|
||||||
lease -> on_expiry);
|
#define BACKUP_LEASES 4
|
||||||
if (lease -> on_expiry)
|
lptr [BACKUP_LEASES] = &pool -> backup;
|
||||||
executable_statement_dereference
|
|
||||||
(&lease -> on_expiry, MDL);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
lease_dereference (&lease, MDL);
|
||||||
|
if (next)
|
||||||
|
lease_reference (&lease, next, MDL);
|
||||||
}
|
}
|
||||||
|
if (next)
|
||||||
/* If there's an on_release event, blow it away. */
|
lease_dereference (&next, MDL);
|
||||||
if (lease -> on_release)
|
if (lease)
|
||||||
executable_statement_dereference (&lease -> on_release,
|
lease_dereference (&lease, MDL);
|
||||||
MDL);
|
|
||||||
|
|
||||||
/* 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));
|
|
||||||
}
|
|
||||||
if (!commit_leases ()) {
|
|
||||||
log_error ("Error committing after writing lease %s",
|
|
||||||
piaddr (lease -> ip_addr));
|
|
||||||
}
|
|
||||||
#if defined (FAILOVER_PROTOCOL)
|
|
||||||
if (lease -> flags & PEER_IS_OWNER)
|
|
||||||
pool -> peer_leases++;
|
|
||||||
else
|
|
||||||
pool -> local_leases++;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (pool -> next_expiry)
|
if (next_expiry != MAX_TIME) {
|
||||||
lease_dereference (&pool -> next_expiry, MDL);
|
pool -> next_event_time = next_expiry;
|
||||||
if (lease) {
|
add_timeout (pool -> next_event_time, pool_timer, pool,
|
||||||
lease_reference (&pool -> next_expiry, lease, MDL);
|
|
||||||
add_timeout (lease -> ends, pool_timer, pool,
|
|
||||||
(tvref_t)pool_reference,
|
(tvref_t)pool_reference,
|
||||||
(tvunref_t)pool_dereference);
|
(tvunref_t)pool_dereference);
|
||||||
}
|
} else
|
||||||
|
pool -> next_event_time = MIN_TIME;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locate the lease associated with a given IP address... */
|
/* Locate the lease associated with a given IP address... */
|
||||||
@ -1618,6 +1583,7 @@ void write_leases ()
|
|||||||
struct hash_bucket *hb;
|
struct hash_bucket *hb;
|
||||||
int i;
|
int i;
|
||||||
int num_written;
|
int num_written;
|
||||||
|
struct lease **lptr [5];
|
||||||
|
|
||||||
/* Write all the dynamically-created group declarations. */
|
/* Write all the dynamically-created group declarations. */
|
||||||
if (group_name_hash) {
|
if (group_name_hash) {
|
||||||
@ -1682,18 +1648,25 @@ void write_leases ()
|
|||||||
/* Write all the leases. */
|
/* Write all the leases. */
|
||||||
num_written = 0;
|
num_written = 0;
|
||||||
for (s = shared_networks; s; s = s -> next) {
|
for (s = shared_networks; s; s = s -> next) {
|
||||||
for (p = s -> pools; p; p = p -> next) {
|
for (p = s -> pools; p; p = p -> next) {
|
||||||
for (l = p -> leases; l; l = l -> next) {
|
lptr [FREE_LEASES] = &p -> free;
|
||||||
if (l -> hardware_addr.hlen ||
|
lptr [ACTIVE_LEASES] = &p -> active;
|
||||||
l -> uid_len ||
|
lptr [EXPIRED_LEASES] = &p -> expired;
|
||||||
(l -> flags & ABANDONED_LEASE)) {
|
lptr [ABANDONED_LEASES] = &p -> abandoned;
|
||||||
if (!write_lease (l))
|
lptr [BACKUP_LEASES] = &p -> backup;
|
||||||
log_fatal ("Can't rewrite %s",
|
|
||||||
"lease database");
|
for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
|
||||||
num_written++;
|
for (l = *(lptr [i]); l; l = l -> next) {
|
||||||
}
|
if (l -> hardware_addr.hlen ||
|
||||||
|
l -> uid_len ||
|
||||||
|
(l -> binding_state != FTS_FREE)) {
|
||||||
|
if (!write_lease (l))
|
||||||
|
log_fatal ("Can't rewrite lease database");
|
||||||
|
num_written++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log_info ("Wrote %d leases to leases file.", num_written);
|
log_info ("Wrote %d leases to leases file.", num_written);
|
||||||
if (!commit_leases ())
|
if (!commit_leases ())
|
||||||
@ -1712,6 +1685,7 @@ void expire_all_pools ()
|
|||||||
struct hash_bucket *hb;
|
struct hash_bucket *hb;
|
||||||
int i;
|
int i;
|
||||||
struct lease *l;
|
struct lease *l;
|
||||||
|
struct lease **lptr [5];
|
||||||
|
|
||||||
/* Loop through each pool in each shared network and call the
|
/* Loop through each pool in each shared network and call the
|
||||||
expiry routine on the pool. */
|
expiry routine on the pool. */
|
||||||
@ -1721,21 +1695,29 @@ void expire_all_pools ()
|
|||||||
|
|
||||||
#if defined (FAILOVER_PROTOCOL)
|
#if defined (FAILOVER_PROTOCOL)
|
||||||
p -> lease_count = 0;
|
p -> lease_count = 0;
|
||||||
p -> local_leases = 0;
|
p -> free_leases = 0;
|
||||||
p -> peer_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++;
|
p -> lease_count++;
|
||||||
if (l -> ends <= cur_time) {
|
if (l -> ends <= cur_time) {
|
||||||
if (l -> flags & PEER_IS_OWNER)
|
if (l -> binding_state == FTS_FREE)
|
||||||
p -> peer_leases++;
|
p -> free_leases++;
|
||||||
else
|
else if (l -> binding_state == FTS_BACKUP)
|
||||||
p -> local_leases++;
|
p -> backup_leases++;
|
||||||
}
|
}
|
||||||
if (p -> failover_peer &&
|
if (p -> failover_peer &&
|
||||||
l -> tstp > l -> tsfp &&
|
l -> tstp > l -> tsfp &&
|
||||||
!(l -> flags & ON_UPDATE_QUEUE))
|
!(l -> flags & ON_UPDATE_QUEUE))
|
||||||
dhcp_failover_queue_update (l);
|
dhcp_failover_queue_update (l, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1748,6 +1730,8 @@ void dump_subnets ()
|
|||||||
struct shared_network *s;
|
struct shared_network *s;
|
||||||
struct subnet *n;
|
struct subnet *n;
|
||||||
struct pool *p;
|
struct pool *p;
|
||||||
|
struct lease **lptr [5];
|
||||||
|
int i;
|
||||||
|
|
||||||
log_info ("Subnets:");
|
log_info ("Subnets:");
|
||||||
for (n = subnets; n; n = n -> next_subnet) {
|
for (n = subnets; n; n = n -> next_subnet) {
|
||||||
@ -1757,14 +1741,20 @@ void dump_subnets ()
|
|||||||
}
|
}
|
||||||
log_info ("Shared networks:");
|
log_info ("Shared networks:");
|
||||||
for (s = shared_networks; s; s = s -> next) {
|
for (s = shared_networks; s; s = s -> next) {
|
||||||
log_info (" %s", s -> name);
|
log_info (" %s", s -> name);
|
||||||
for (p = s -> pools; p; p = p -> next) {
|
for (p = s -> pools; p; p = p -> next) {
|
||||||
for (l = p -> leases; l; l = l -> next) {
|
lptr [FREE_LEASES] = &p -> free;
|
||||||
print_lease (l);
|
lptr [ACTIVE_LEASES] = &p -> active;
|
||||||
}
|
lptr [EXPIRED_LEASES] = &p -> expired;
|
||||||
log_debug ("Last Lease:");
|
lptr [ABANDONED_LEASES] = &p -> abandoned;
|
||||||
print_lease (p -> last_lease);
|
lptr [BACKUP_LEASES] = &p -> backup;
|
||||||
|
|
||||||
|
for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
|
||||||
|
for (l = *(lptr [i]); l; l = l -> next) {
|
||||||
|
print_lease (l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -179,27 +179,21 @@ isc_result_t dhcp_lease_set_value (omapi_object_t *h,
|
|||||||
lease = (struct lease *)h;
|
lease = (struct lease *)h;
|
||||||
|
|
||||||
/* We're skipping a lot of things it might be interesting to
|
/* We're skipping a lot of things it might be interesting to
|
||||||
set - for now, we just make it possible to whack the abandoned
|
set - for now, we just make it possible to whack the state. */
|
||||||
flag. */
|
if (!omapi_ds_strcmp (name, "state")) {
|
||||||
if (!omapi_ds_strcmp (name, "abandoned")) {
|
unsigned long bar;
|
||||||
int bar;
|
status = omapi_get_int_value (&bar, value);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
if (value -> type == omapi_datatype_int)
|
if (bar < 1 || bar > FTS_BOOTP)
|
||||||
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
|
|
||||||
return ISC_R_INVALIDARG;
|
return ISC_R_INVALIDARG;
|
||||||
|
if (lease -> binding_state != bar) {
|
||||||
foo = lease -> flags;
|
lease -> next_binding_state = bar;
|
||||||
if (bar)
|
if (supersede_lease (lease, 0, 1, 1, 1))
|
||||||
lease -> flags |= ABANDONED_LEASE;
|
return ISC_R_SUCCESS;
|
||||||
else
|
return ISC_R_IOERROR;
|
||||||
lease -> flags &= ~ABANDONED_LEASE;
|
}
|
||||||
if (foo != lease -> flags)
|
|
||||||
return ISC_R_SUCCESS;
|
|
||||||
return ISC_R_UNCHANGED;
|
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;
|
return ISC_R_INVALIDARG;
|
||||||
lease = (struct lease *)h;
|
lease = (struct lease *)h;
|
||||||
|
|
||||||
if (!omapi_ds_strcmp (name, "abandoned"))
|
if (!omapi_ds_strcmp (name, "state"))
|
||||||
return omapi_make_int_value (value, name,
|
return omapi_make_int_value (value, name,
|
||||||
(lease -> flags &
|
(int)lease -> binding_state, MDL);
|
||||||
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);
|
|
||||||
else if (!omapi_ds_strcmp (name, "ip-address"))
|
else if (!omapi_ds_strcmp (name, "ip-address"))
|
||||||
return omapi_make_const_value (value, name,
|
return omapi_make_const_value (value, name,
|
||||||
lease -> ip_addr.iabuf,
|
lease -> ip_addr.iabuf,
|
||||||
@ -362,7 +351,7 @@ isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
|
|||||||
return ISC_R_INVALIDARG;
|
return ISC_R_INVALIDARG;
|
||||||
if (!write_lease (lease) || !commit_leases ()
|
if (!write_lease (lease) || !commit_leases ()
|
||||||
#if defined (FAILOVER_PROTOCOL)
|
#if defined (FAILOVER_PROTOCOL)
|
||||||
|| !dhcp_failover_queue_update (lease)
|
|| !dhcp_failover_queue_update (lease, 1)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
return ISC_R_IOERROR;
|
return ISC_R_IOERROR;
|
||||||
@ -395,26 +384,13 @@ isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
|
|||||||
|
|
||||||
/* Write out all the values. */
|
/* Write out all the values. */
|
||||||
|
|
||||||
status = omapi_connection_put_name (c, "abandoned");
|
status = omapi_connection_put_name (c, "state");
|
||||||
if (status != ISC_R_SUCCESS)
|
if (status != ISC_R_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
status = omapi_connection_put_uint32 (c, sizeof (int));
|
status = omapi_connection_put_uint32 (c, sizeof (int));
|
||||||
if (status != ISC_R_SUCCESS)
|
if (status != ISC_R_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
status = omapi_connection_put_uint32 (c, (lease -> flags &
|
status = omapi_connection_put_uint32 (c, lease -> binding_state);
|
||||||
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)));
|
|
||||||
if (status != ISC_R_SUCCESS)
|
if (status != ISC_R_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -176,6 +176,12 @@ const char *dhcp_flink_state_names [] = {
|
|||||||
};
|
};
|
||||||
#endif /* FAILOVER_PROTOCOL */
|
#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 universe agent_universe;
|
||||||
struct option agent_options [256] = {
|
struct option agent_options [256] = {
|
||||||
{ "pad", "", &agent_universe, 0 },
|
{ "pad", "", &agent_universe, 0 },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user