#ifndef lint
static char copyright[] =
-"$Id: conflex.c,v 1.92 2001/05/02 06:32:54 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
+"$Id: conflex.c,v 1.93 2001/05/17 19:03:43 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
return TOKEN_RESET;
if (!strcasecmp (atom + 1, "eserved"))
return TOKEN_RESERVED;
+ if (!strcasecmp (atom + 1, "emove"))
+ return REMOVE;
break;
case 's':
if (!strcasecmp (atom + 1, "tate"))
#ifndef lint
static char copyright[] =
-"$Id: discover.c,v 1.42 2001/05/02 06:36:54 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
+"$Id: discover.c,v 1.43 2001/05/17 19:03:44 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
if (i < 0)
log_fatal ("ioctl: SIOCGIFCONF: %m");
+#ifdef SIOCGIFCONF_ZERO_PROBE
+ /* Workaround for SIOCGIFCONF bug on some Linux versions. */
+ if (ic.ifc_ifcu.ifcu_buf == 0 && ic.ifc_len == 0) {
+ ic.ifc_len = sizeof buf;
+ ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
+ goto gifconf_again;
+ }
+#endif
+
/* If the SIOCGIFCONF resulted in more data than would fit in
a buffer, allocate a bigger buffer. */
if ((ic.ifc_ifcu.ifcu_buf == buf
#ifdef SIOCGIFCONF_ZERO_PROBE
} else if (ic.ifc_ifcu.ifcu_buf == 0) {
ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
- if.ifc_len = sizeof buf;
+ ic.ifc_len = sizeof buf;
goto gifconf_again;
#endif
}
return status;
}
+/* dhcpctl_set_buffer_value
+
+ Sets a NUL-terminated ASCII value on an object referred to by
+ a dhcpctl_handle. like dhcpctl_set_value, but saves the
+ trouble of creating a data_string for a NUL-terminated string.
+ Does not update the server - just sets the value on the handle. */
+
+dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h,
+ const char *value, unsigned len,
+ const char *value_name)
+{
+ isc_result_t status;
+ omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
+ omapi_data_string_t *name = (omapi_data_string_t *)0;
+ int ip;
+ unsigned ll;
+
+ ll = strlen (value_name);
+ status = omapi_data_string_new (&name, ll, MDL);
+ if (status != ISC_R_SUCCESS)
+ return status;
+ memcpy (name -> value, value_name, ll);
+
+ status = omapi_typed_data_new (MDL, &tv,
+ omapi_datatype_data, len, value);
+ if (status != ISC_R_SUCCESS) {
+ omapi_data_string_dereference (&name, MDL);
+ return status;
+ }
+ memcpy (tv -> u.buffer.value, value, len);
+
+ status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
+ omapi_data_string_dereference (&name, MDL);
+ omapi_typed_data_dereference (&tv, MDL);
+ return status;
+}
+
/* dhcpctl_set_boolean_value
Sets a boolean value on an object - like dhcpctl_set_value,
dhcpctl_data_string, const char *);
dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle, const char *,
const char *);
+dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle,
+ const char *, unsigned, const char *);
dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle, int, const char *);
dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle, int, const char *);
dhcpctl_status dhcpctl_object_update (dhcpctl_handle, dhcpctl_handle);
usage(argv[0]);
}
+ /* Initially, log errors to stderr as well as to syslogd. */
+#ifdef SYSLOG_4_2
+ openlog ("dhcpd", LOG_NDELAY);
+ log_priority = DHCPD_LOG_FACILITY;
+#else
+ openlog ("dhcpd", LOG_NDELAY, DHCPD_LOG_FACILITY);
+#endif
status = dhcpctl_initialize ();
if (status != ISC_R_SUCCESS) {
fprintf (stderr, "dhcpctl_initialize: %s\n",
if (se)
port = ntohs (se -> s_port);
else {
- printf ("unknown service name: %s", val);
+ printf ("unknown service name: %s\n", val);
break;
}
} else if (token == NUMBER) {
s = dmalloc (strlen (val) + 1, MDL);
if (!server) {
- printf ("no memory to store server name.");
+ printf ("no memory to store server name.\n");
skip_to_semi (cfile);
break;
}
case KEY:
token = next_token (&val, (unsigned *)0, cfile);
if (!is_identifier (token)) {
- printf ("usage: key <name> <value>");
+ printf ("usage: key <name> <value>\n");
skip_to_semi (cfile);
break;
}
s = dmalloc (strlen (val) + 1, MDL);
if (!s) {
- printf ("no memory for key name.");
+ printf ("no memory for key name.\n");
skip_to_semi (cfile);
break;
}
}
if (!connected) {
- printf ("not connected.");
+ printf ("not connected.\n");
skip_to_semi (cfile);
break;
}
}
if (!connected) {
- printf ("not connected.");
+ printf ("not connected.\n");
skip_to_semi (cfile);
break;
}
}
if (!connected) {
- printf ("not connected.");
+ printf ("not connected.\n");
skip_to_semi (cfile);
break;
}
switch (token) {
case STRING:
dhcpctl_set_string_value (oh, val, s1);
+ token = next_token (&val, (unsigned *)0, cfile);
break;
case NUMBER:
- dhcpctl_set_int_value (oh, atoi (val), s1);
+ strcpy (buf, val);
+ token = peek_token (&val, (unsigned *)0, cfile);
+ /* Colon-seperated hex list? */
+ if (token == COLON)
+ goto cshl;
+ else if (token == DOT) {
+ s = buf;
+ val = buf;
+ do {
+ int intval = atoi (val);
+ if (intval > 255) {
+ parse_warn (cfile,
+ "dotted octet > 255: %s",
+ val);
+ skip_to_semi (cfile);
+ goto badnum;
+ }
+ *s++ = intval;
+ token = next_token (&val,
+ (unsigned *)0, cfile);
+ if (token != DOT)
+ break;
+ token = next_token (&val,
+ (unsigned *)0, cfile);
+ } while (token == NUMBER);
+ dhcpctl_set_data_value (oh, buf,
+ (unsigned)(s - buf),
+ s1);
+ break;
+ }
+ dhcpctl_set_int_value (oh, atoi (buf), s1);
+ token = next_token (&val, (unsigned *)0, cfile);
+ badnum:
break;
+ case NUMBER_OR_NAME:
+ strcpy (buf, val);
+ cshl:
+ s = buf;
+ val = buf;
+ do {
+ convert_num (cfile, s, val, 16, 8);
+ ++s;
+ token = next_token (&val,
+ (unsigned *)0, cfile);
+ if (token != COLON)
+ break;
+ token = next_token (&val,
+ (unsigned *)0, cfile);
+ } while (token == NUMBER ||
+ token == NUMBER_OR_NAME);
+ dhcpctl_set_data_value (oh, buf,
+ (unsigned)(s - buf), s1);
+ break;
+
default:
printf ("invalid value.\n");
+ skip_to_semi (cfile);
}
- token = next_token (&val, (unsigned *)0, cfile);
if (token != END_OF_FILE && token != EOL)
goto set_usage;
break;
case TOKEN_CREATE:
case TOKEN_OPEN:
+ i = token;
token = next_token (&val, (unsigned *)0, cfile);
if (token != END_OF_FILE && token != EOL) {
printf ("usage: %s\n", val);
}
if (!connected) {
- printf ("not connected.");
+ printf ("not connected.\n");
skip_to_semi (cfile);
break;
}
- i = 0;
- if (token == TOKEN_CREATE)
+ if (!oh) {
+ printf ("you must make a new object first!\n");
+ skip_to_semi (cfile);
+ break;
+ }
+
+ if (i == TOKEN_CREATE)
i = DHCPCTL_CREATE | DHCPCTL_EXCL;
+ else
+ i = 0;
status = dhcpctl_open_object (oh, connection, i);
if (status == ISC_R_SUCCESS)
}
if (!connected) {
- printf ("not connected.");
+ printf ("not connected.\n");
skip_to_semi (cfile);
break;
}
break;
}
+ break;
+
+ case REMOVE:
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token != END_OF_FILE && token != EOL) {
+ printf ("usage: %s\n", val);
+ skip_to_semi (cfile);
+ break;
+ }
+
+ if (!connected) {
+ printf ("not connected.\n");
+ skip_to_semi (cfile);
+ break;
+ }
+
+ status = dhcpctl_object_remove(connection, oh);
+ if (status == ISC_R_SUCCESS)
+ status = dhcpctl_wait_for_completion
+ (oh, &waitstatus);
+ if (status == ISC_R_SUCCESS)
+ status = waitstatus;
+ if (status != ISC_R_SUCCESS) {
+ printf ("can't destroy object: %s\n",
+ isc_result_totext (status));
+ break;
+ }
+
break;
}
- } while (token != END_OF_FILE);
+ } while (1);
exit (0);
}
# define USE_LPF
# endif
# if !defined (__sparc__) /* XXX hopefully this will be fixed someday */
-# define SIOCGIFCONF_NULL_BUF_GIVES_CORRECT_LEN
+# define SIOCGIFCONF_ZERO_PROBE
# endif
# define LINUX_SLASHPROC_DISCOVERY
# define PROCDEV_DEVICE "/proc/net/dev"
int load_balance_mine (struct packet *, dhcp_failover_state_t *);
binding_state_t normal_binding_state_transition_check (struct lease *,
dhcp_failover_state_t *,
- binding_state_t);
+ binding_state_t,
+ u_int32_t);
binding_state_t
conflict_binding_state_transition_check (struct lease *,
dhcp_failover_state_t *,
- binding_state_t);
+ binding_state_t, u_int32_t);
int lease_mine_to_reallocate (struct lease *);
OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_state, dhcp_failover_state_t,
END_OF_FILE = 607,
RECOVER_WAIT = 608,
SERVER = 609,
- CONNECT = 610
+ CONNECT = 610,
+ REMOVE = 611
};
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
/* Current version of ISC DHCP Distribution. */
-#define DHCP_VERSION "V3.0rc4"
+#define DHCP_VERSION "V3.1-unreleased"
somewhere. */
if (dp -> file) {
#if defined (DEBUG_RC_HISTORY)
+ int i, count, inhistory = 0, noted = 0;
+
/* If we have the info, see if this is actually
new garbage. */
if (rc_history_count < RC_HISTORY_MAX) {
- int i, printit = 0, inhistory = 0, prefcnt = 0;
- i = rc_history_index - rc_history_count;
- if (i < 0)
- i += RC_HISTORY_MAX;
- do {
- if (rc_history [i].addr == dp + 1) {
- if (rc_history [i].refcnt == 1 &&
- prefcnt == 0 && !printit) {
- printit = 1;
- inhistory = 1;
- log_info (" %s(%d): %d",
- dp -> file,
- dp -> line,
- dp -> size);
- }
- prefcnt = rc_history [i].refcnt;
- if (printit)
- print_rc_hist_entry (i);
- }
- if (++i == RC_HISTORY_MAX)
- i = 0;
- } while (i != rc_history_index);
- if (!inhistory)
- log_info (" %s(%d): %d", dp -> file,
- dp -> line, dp -> size);
+ count = rc_history_count;
} else
+ count = RC_HISTORY_MAX;
+ i = rc_history_index - 1;
+ if (i < 0)
+ i += RC_HISTORY_MAX;
+
+ do {
+ if (rc_history [i].addr == dp + 1) {
+ inhistory = 1;
+ if (!noted) {
+ log_info (" %s(%d): %d", dp -> file,
+ dp -> line, dp -> size);
+ noted = 1;
+ }
+ print_rc_hist_entry (i);
+ if (!rc_history [i].refcnt)
+ break;
+ }
+ if (--i < 0)
+ i = RC_HISTORY_MAX - 1;
+ } while (count--);
+ if (!inhistory)
#endif
log_info (" %s(%d): %d",
dp -> file, dp -> line, dp -> size);
extra_references = 0;
for (p = (*h) -> inner;
p && !extra_references; p = p -> inner) {
- extra_references += p -> refcnt - 1;
- if (p -> inner)
+ extra_references += p -> refcnt;
+ if (p -> inner && p -> inner -> outer == p)
+ --extra_references;
+ if (p -> outer)
--extra_references;
if (p -> handle)
--extra_references;
}
for (p = (*h) -> outer;
p && !extra_references; p = p -> outer) {
- extra_references += p -> refcnt - 1;
- if (p -> outer)
+ extra_references += p -> refcnt;
+ if (p -> outer && p -> outer -> inner == p)
+ --extra_references;
+ if (p -> inner)
--extra_references;
if (p -> handle)
--extra_references;
((*h) -> type -> freer (*h, file, line));
else
dfree (*h, file, line);
+ } else {
+ (*h) -> refcnt--;
+ if (!(*h) -> type -> freer)
+ rc_register (file, line,
+ h, *h, (*h) -> refcnt);
}
} else {
(*h) -> refcnt--;
return;
}
+#if defined (TRACING)
if (trace_record ()) {
/* Connection registration packet:
status = trace_write_packet_iov (trace_connect,
iov_count, iov, file, line);
}
+#endif
}
static void trace_connect_input (trace_type_t *ttype,
Routines for manipulating hash tables... */
/*
- * Copyright (c) 1995-2000 Internet Software Consortium.
+ * Copyright (c) 1995-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#ifndef lint
static char copyright[] =
-"$Id: hash.c,v 1.1 2000/08/01 22:55:07 neild Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
+"$Id: hash.c,v 1.2 2001/05/17 19:03:57 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include <omapip/omapip_p.h>
omapi_object_t *g;
isc_result_t status;
- m = dmalloc (sizeof *m, file, line);
- if (!m)
- return ISC_R_NOMEMORY;
- memset (m, 0, sizeof *m);
- m -> type = omapi_type_message;
- rc_register (file, line, &m, m, m -> refcnt);
- m -> refcnt = 1;
+ m = (omapi_message_object_t *)0;
+ status = omapi_message_allocate (&m, file, line);
+ if (status != ISC_R_SUCCESS)
+ return status;
g = (omapi_object_t *)0;
status = omapi_generic_new (&g, file, line);
}
status = omapi_object_reference (o, (omapi_object_t *)m, file, line);
- omapi_object_dereference ((omapi_object_t **)&m, file, line);
+ omapi_message_dereference (&m, file, line);
omapi_object_dereference (&g, file, line);
if (status != ISC_R_SUCCESS)
return status;
}
#endif
+static isc_result_t
+omapi_message_process_internal (omapi_object_t *, omapi_object_t *);
+
isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
+{
+ isc_result_t status;
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ unsigned long previous_outstanding = dmalloc_outstanding;
+#endif
+
+ status = omapi_message_process_internal (mo, po);
+
+#if defined (DEBUG_MEMORY_LEAKAGE) && 0
+ log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
+ dmalloc_generation,
+ dmalloc_outstanding - previous_outstanding,
+ dmalloc_outstanding, dmalloc_longterm);
+#endif
+#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL)) && 0
+ dmalloc_dump_outstanding ();
+#endif
+#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY) && 0
+ dump_rc_history ();
+#endif
+
+ return status;
+}
+
+static isc_result_t
+omapi_message_process_internal (omapi_object_t *mo, omapi_object_t *po)
{
omapi_message_object_t *message, *m;
omapi_object_t *object = (omapi_object_t *)0;
u_int16_t nlen;
u_int32_t vlen;
u_int32_t th;
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ unsigned long previous_outstanding = 0xBEADCAFE;
+ unsigned long connect_outstanding = 0xBEADCAFE;
+#endif
if (h -> type != omapi_type_protocol) {
/* XXX shouldn't happen. Put an assert here? */
p = (omapi_protocol_object_t *)h;
if (!strcmp (name, "connect")) {
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ connect_outstanding = dmalloc_outstanding;
+#endif
/* Send the introductory message. */
status = omapi_protocol_send_intro
(h, OMAPI_PROTOCOL_VERSION,
}
}
+ /* If we get a disconnect, dump memory usage. */
+ if (!strcmp (name, "disconnect")
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ && connect_outstanding != 0xBEADCAFE
+#endif
+ ) {
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
+ dmalloc_generation,
+ dmalloc_outstanding - previous_outstanding,
+ dmalloc_outstanding, dmalloc_longterm, " long-term");
+#endif
+#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
+ dmalloc_dump_outstanding ();
+#endif
+#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
+ dump_rc_history ();
+#endif
+ }
+
/* Not a signal we recognize? */
if (strcmp (name, "ready")) {
if (p -> inner && p -> inner -> type -> signal_handler)
/* If we already have the data, fall through. */
case omapi_protocol_header_wait:
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ if (previous_outstanding != 0xBEADCAFE) {
+ log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
+ "generation", dmalloc_generation,
+ dmalloc_outstanding - previous_outstanding,
+ dmalloc_outstanding, dmalloc_longterm,
+ " long-term");
+#endif
+#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
+ dmalloc_dump_outstanding ();
+#endif
+#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
+ dump_rc_history ();
+#endif
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ }
+ previous_outstanding = dmalloc_outstanding;
+#endif
status = omapi_message_new ((omapi_object_t **)&p -> message,
MDL);
if (status != ISC_R_SUCCESS) {
}
omapi_message_dereference (&p -> message, MDL);
-
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
+ dmalloc_generation,
+ dmalloc_outstanding - previous_outstanding,
+ dmalloc_outstanding, dmalloc_longterm, " long-term");
+#endif
+#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
+ dmalloc_dump_outstanding ();
+#endif
+#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
+ dump_rc_history ();
+#endif
+#if defined (DEBUG_MEMORY_LEAKAGE)
+ previous_outstanding = 0xBEADCAFE;
+#endif
/* Now wait for the next message. */
goto to_header_wait;
return status;
memcpy (nds -> value, name, strlen (name));
- return omapi_set_value (h, id, nds, value);
+ status = omapi_set_value (h, id, nds, value);
+ omapi_data_string_dereference (&nds, MDL);
+ return status;
}
isc_result_t omapi_set_boolean_value (omapi_object_t *h, omapi_object_t *id,
for (outer = h; outer -> outer; outer = outer -> outer)
;
if (outer -> type -> get_value)
- return (*(outer -> type -> get_value)) (outer,
- id, nds, value);
- return ISC_R_NOTFOUND;
+ status = (*(outer -> type -> get_value)) (outer,
+ id, nds, value);
+ else
+ status = ISC_R_NOTFOUND;
+ omapi_data_string_dereference (&nds, MDL);
+ return status;
}
isc_result_t omapi_stuff_values (omapi_object_t *c,
#ifndef lint
static char copyright[] =
-"$Id: bootp.c,v 1.69 2001/02/12 20:51:26 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
+"$Id: bootp.c,v 1.70 2001/05/17 19:04:03 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
/* We're done with the option state. */
option_state_dereference (&options, MDL);
- static_lease_dereference (lease, MDL);
/* Set up the hardware destination address... */
hto.hbuf [0] = packet -> raw -> htype;
out:
if (options)
option_state_dereference (&options, MDL);
- if (lease) {
- static_lease_dereference (lease, MDL);
+ if (lease)
lease_dereference (&lease, MDL);
- }
if (hp)
host_dereference (&hp, MDL);
if (host)
#ifndef lint
static char copyright[] =
-"$Id: db.c,v 1.63 2001/03/15 23:21:25 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
+"$Id: db.c,v 1.64 2001/05/17 19:04:04 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
#include <ctype.h>
+#include "version.h"
FILE *db_file;
"confusing to you, we sincerely\n");
fprintf (db_file, "# apologize. Seriously, though - don't ask.\n");
fprintf (db_file, "# The format of this file is documented in the %s",
- "dhcpd.leases(5) manual page.\n\n");
+ "dhcpd.leases(5) manual page.\n");
+ fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
+ DHCP_VERSION);
/* Write out all the leases that we know of... */
counting = 0;
#ifndef lint
static char copyright[] =
-"$Id: dhcp.c,v 1.192 2001/05/03 18:22:58 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
+"$Id: dhcp.c,v 1.193 2001/05/17 19:04:05 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
goto out;
}
}
+
+ /* Don't let a client allocate a lease using DHCPREQUEST
+ if the lease isn't ours to allocate. */
+ if ((lease -> binding_state == FTS_FREE &&
+ peer -> i_am == secondary) ||
+ (lease -> binding_state == FTS_BACKUP &&
+ peer -> i_am == primary)) {
+ log_debug ("%s: expired", msgbuf);
+ goto out;
+ }
} else
peer = (dhcp_failover_state_t *)0;
#endif
d1.data [0]);
data_string_forget (&d1, MDL);
free_lease_state (state, MDL);
- static_lease_dereference (lease, MDL);
return;
}
data_string_forget (&d1, MDL);
if (!ignorep)
log_info ("%s: unknown client", msg);
free_lease_state (state, MDL);
- static_lease_dereference (lease, MDL);
return;
}
if (!ignorep)
log_info ("%s: bootp disallowed", msg);
free_lease_state (state, MDL);
- static_lease_dereference (lease, MDL);
return;
}
if (!ignorep)
log_info ("%s: booting disallowed", msg);
free_lease_state (state, MDL);
- static_lease_dereference (lease, MDL);
return;
}
msg);
free_lease_state (state, MDL);
/* XXX probably not necessary: */
- static_lease_dereference (lease, MDL);
return;
}
}
log_info ("%s: can't allocate temporary lease structure: %s",
msg, isc_result_totext (result));
free_lease_state (state, MDL);
- static_lease_dereference (lease, MDL);
return;
}
offer == DHCPACK, offer == DHCPACK)) {
log_info ("%s: database update failed", msg);
free_lease_state (state, MDL);
- static_lease_dereference (lease, MDL);
lease_dereference (<, MDL);
return;
}
++outstanding_pings;
} else {
lease -> timestamp = cur_time;
- static_lease_dereference (lease, MDL);
dhcp_reply (lease);
}
}
return 1;
}
-/* Dereference all dynamically-allocated information that may be dangling
- off of a static lease. Otherwise, once ack_lease returns, the information
- dangling from the lease will be lost, so reference counts will be screwed
- up and memory leaks will occur. */
-
-void static_lease_dereference (lease, file, line)
- struct lease *lease;
- const char *file;
- int line;
-{
- if (!(lease -> flags & STATIC_LEASE))
- return;
- if (lease -> on_release)
- executable_statement_dereference (&lease -> on_release,
- file, line);
- if (lease -> on_expiry)
- executable_statement_dereference (&lease -> on_expiry,
- file, line);
- if (lease -> on_commit)
- executable_statement_dereference (&lease -> on_commit,
- file, line);
- if (lease -> scope)
- binding_scope_dereference (&lease -> scope, file, line);
- if (lease -> agent_options)
- option_chain_head_dereference (&lease -> agent_options,
- file, line);
- if (lease -> uid != lease -> uid_buf) {
- dfree (lease -> uid, file, line);
- lease -> uid = (unsigned char *)0;
- }
-}
-
/* Look through all the pools in a list starting with the specified pool
for a free lease. We try to find a virgin lease if we can. If we
don't find a virgin lease, we try to find a non-virgin lease that's
#ifndef lint
static char copyright[] =
-"$Id: failover.c,v 1.53 2001/05/03 18:31:28 mellon Exp $ Copyright (c) 1999-2001 The Internet Software Consortium. All rights reserved.\n";
+"$Id: failover.c,v 1.54 2001/05/17 19:04:07 mellon Exp $ Copyright (c) 1999-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
case resolution_interrupted:
case partner_down:
case communications_interrupted:
+ case recover:
/* Already in the right state? */
if (state -> me.state == startup)
return (dhcp_failover_set_state
return dhcp_failover_set_state
(state, resolution_interrupted);
- case recover:
- /* XXX I don't think it makes sense to make a
- XXX transition from recover to communications-
- XXX interrupted, because then when the connect
- XXX occurred, we'd make a transition into
- XXX normal, not recover. */
- break; /* Kim says stay in recover. */
-
case normal:
return dhcp_failover_set_state
(state, communications_interrupted);
{
enum failover_state saved_state;
TIME saved_stos;
+ struct pool *p;
+ struct shared_network *s;
+ struct lease *l;
/* First make the transition out of the current state. */
switch (state -> me.state) {
dhcp_failover_send_update_request_all (state);
break;
+ case partner_down:
+ /* For every expired lease, set a timeout for it to become free. */
+ for (s = shared_networks; s; s = s -> next) {
+ for (p = s -> pools; p; p = p -> next) {
+ if (p -> failover_peer == state) {
+ for (l = p -> expired; l; l = l -> next)
+ l -> tsfp = state -> me.stos + state -> mclt;
+ if (p -> next_event_time >
+ state -> me.stos + state -> mclt) {
+ p -> next_event_time =
+ state -> me.stos + state -> mclt;
+ add_timeout (p -> next_event_time, pool_timer, p,
+ (tvref_t)pool_reference,
+ (tvunref_t)pool_dereference);
+ }
+ }
+ }
+ }
+ break;
+
+
default:
break;
}
(tvunref_t)dhcp_failover_state_dereference);
}
-
return 1;
}
if (state -> me.state == normal) {
new_binding_state =
(normal_binding_state_transition_check
- (lease, state,
- msg -> binding_status));
+ (lease, state, msg -> binding_status,
+ msg -> potential_expiry));
} else {
new_binding_state =
(conflict_binding_state_transition_check
- (lease, state,
- msg -> binding_status));
+ (lease, state, msg -> binding_status,
+ msg -> potential_expiry));
}
if (new_binding_state != msg -> binding_status) {
char outbuf [100];
if (msg -> options_present & FTB_POTENTIAL_EXPIRY) {
/* XXX it could be a problem to do this directly if the
XXX lease is sorted by tsfp. */
- lease -> tsfp = msg -> potential_expiry;
- write_lease (lease);
+ if (lease -> binding_state == FTS_EXPIRED) {
+ lease -> next_binding_state = FTS_FREE;
+ supersede_lease (lease, (struct lease *)0, 0, 1, 0);
+ write_lease (lease);
+ if (state -> me.state == normal)
+ commit_leases ();
+ } else {
+ lease -> tsfp = msg -> potential_expiry;
+ write_lease (lease);
+#if 0 /* XXX This might be needed. */
+ if (state -> me.state == normal)
+ commit_leases ();
+#endif
+ }
}
unqueue:
binding_state_t
normal_binding_state_transition_check (struct lease *lease,
dhcp_failover_state_t *state,
- binding_state_t binding_state)
+ binding_state_t binding_state,
+ u_int32_t tsfp)
{
binding_state_t new_state;
case FTS_BACKUP:
/* Can't set a lease to free or backup until the
peer agrees that it's expired. */
- /* XXX but have we updated tsfp yet? */
- if (lease -> tsfp > cur_time) {
+ if (tsfp > cur_time) {
new_state = lease -> binding_state;
goto out;
}
case FTS_BACKUP:
/* Can't set a lease to free or backup until the
peer agrees that it's expired. */
- /* XXX but have we updated tsfp yet? */
- if (lease -> tsfp > cur_time) {
+ if (tsfp > cur_time) {
new_state = lease -> binding_state;
goto out;
}
case FTS_BACKUP:
/* Can't set a lease to free or backup until the
peer agrees that it's expired. */
- /* XXX but have we updated tsfp yet? */
- if (lease -> tsfp > cur_time) {
+ if (tsfp > cur_time) {
new_state = lease -> binding_state;
goto out;
}
switch (binding_state) {
case FTS_FREE:
case FTS_BACKUP:
- /* XXX but have we updated tsfp yet? */
/* Can't set a lease to free or backup until the
peer agrees that it's expired. */
- if (lease -> tsfp > cur_time) {
+ if (tsfp > cur_time) {
new_state = lease -> binding_state;
goto out;
}
binding_state_t
conflict_binding_state_transition_check (struct lease *lease,
dhcp_failover_state_t *state,
- binding_state_t binding_state)
+ binding_state_t binding_state,
+ u_int32_t tsfp)
{
binding_state_t new_state;
#ifndef lint
static char copyright[] =
-"$Id: mdb.c,v 1.67 2001/05/02 07:09:36 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
+"$Id: mdb.c,v 1.68 2001/05/17 19:04:08 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
requested *after* a DHCP lease has been assigned. */
if (lease -> binding_state != FTS_ABANDONED &&
+ lease -> next_binding_state != FTS_ABANDONED &&
(comp -> binding_state == FTS_ACTIVE ||
comp -> binding_state == FTS_RESERVED ||
comp -> binding_state == FTS_BOOTP) &&
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 &&
+ if ((commit || !pimmediate) &&
comp -> sort_time != MIN_TIME &&
comp -> sort_time > cur_time &&
(comp -> sort_time < comp -> pool -> next_event_time ||
case FTS_ABANDONED:
case FTS_RESET:
lease -> next_binding_state = FTS_FREE;
+ /* If we are not in partner_down, leases don't go from
+ EXPIRED to FREE on a timeout - only on an update.
+ If we're in partner_down, they expire at mclt past
+ the time we entered partner_down. */
+ if (lease -> pool -> failover_peer &&
+ lease -> pool -> failover_peer -> me.state == partner_down)
+ lease -> tsfp =
+ (lease -> pool -> failover_peer -> me.stos +
+ lease -> pool -> failover_peer -> mclt);
break;
case FTS_FREE:
/* If there's nothing on the queue, skip it. */
if (!*(lptr [i]))
continue;
-
+
+#if defined (FAILOVER_PROTOCOL)
+ if (pool -> failover_peer &&
+ pool -> failover_peer -> me.state != partner_down) {
+ /* The secondary can't remove a lease from the
+ active state except in partner_down. */
+ if (i == ACTIVE_LEASES &&
+ pool -> failover_peer -> i_am == secondary)
+ continue;
+ /* Leases in an expired state don't move to
+ free because of a timeout unless we're in
+ partner_down. */
+ if (i == EXPIRED_LEASES)
+ continue;
+ }
+#endif
lease_reference (&lease, *(lptr [i]), MDL);
while (lease) {
OMAPI object interfaces for the DHCP server. */
/*
- * Copyright (c) 1999-2000 Internet Software Consortium.
+ * Copyright (c) 1999-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#ifndef lint
static char copyright[] =
-"$Id: omapi.c,v 1.46 2001/05/02 07:11:38 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n";
+"$Id: omapi.c,v 1.47 2001/05/17 19:04:09 mellon Exp $ Copyright (c) 1999-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
return ISC_R_INVALIDARG;
lease = (struct lease *)h;
- uid_hash_delete (lease);
+ if (lease -> uid)
+ uid_hash_delete (lease);
hw_hash_delete (lease);
- if (lease -> billing_class)
- class_dereference
- (&lease -> billing_class, file, line);
- if (lease -> uid && lease -> uid != &lease -> uid_buf [0]) {
+
+ if (lease -> on_release)
+ executable_statement_dereference (&lease -> on_release,
+ file, line);
+ if (lease -> on_expiry)
+ executable_statement_dereference (&lease -> on_expiry,
+ file, line);
+ if (lease -> on_commit)
+ executable_statement_dereference (&lease -> on_commit,
+ file, line);
+ if (lease -> scope)
+ binding_scope_dereference (&lease -> scope, file, line);
+
+ if (lease -> agent_options)
+ option_chain_head_dereference (&lease -> agent_options,
+ file, line);
+ if (lease -> uid && lease -> uid != lease -> uid_buf) {
dfree (lease -> uid, MDL);
lease -> uid = &lease -> uid_buf [0];
lease -> uid_len = 0;
}
+
if (lease -> client_hostname) {
dfree (lease -> client_hostname, MDL);
lease -> client_hostname = (char *)0;
}
+
if (lease -> host)
host_dereference (&lease -> host, file, line);
if (lease -> subnet)
subnet_dereference (&lease -> subnet, file, line);
if (lease -> pool)
pool_dereference (&lease -> pool, file, line);
- if (lease -> on_expiry)
- executable_statement_dereference (&lease -> on_expiry,
- file, line);
- if (lease -> on_commit)
- executable_statement_dereference (&lease -> on_commit,
- file, line);
- if (lease -> on_release)
- executable_statement_dereference (&lease -> on_release,
- file, line);
+
if (lease -> state) {
free_lease_state (lease -> state, file, line);
lease -> state = (struct lease_state *)0;
cancel_timeout (lease_ping_timeout, lease);
--outstanding_pings; /* XXX */
}
+
+ if (lease -> billing_class)
+ class_dereference
+ (&lease -> billing_class, file, line);
+
return ISC_R_SUCCESS;
}