Commit 20916cae authored by Ted Lemon's avatar Ted Lemon
Browse files

- Fix all the OMAPI objects in the DHCP server and client that weren't

  being correctly reference-counted.
- Make and use object-specific allocators.
- Add reference/dereference support to hash functions and to timeout
  functions.
parent 7deff076
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: clparse.c,v 1.43 2000/04/06 22:31:16 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n"; "$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";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
...@@ -97,11 +97,11 @@ isc_result_t read_client_conf () ...@@ -97,11 +97,11 @@ isc_result_t read_client_conf ()
top_level_config.script_name = "/etc/dhclient-script"; top_level_config.script_name = "/etc/dhclient-script";
top_level_config.requested_options = default_requested_options; top_level_config.requested_options = default_requested_options;
top_level_config.on_receipt = new_group (MDL); group_allocate (&top_level_config.on_receipt, MDL);
if (!top_level_config.on_receipt) if (!top_level_config.on_receipt)
log_fatal ("no memory for top-level on_receipt group"); log_fatal ("no memory for top-level on_receipt group");
top_level_config.on_transmission = new_group (MDL); group_allocate (&top_level_config.on_transmission, MDL);
if (!top_level_config.on_transmission) if (!top_level_config.on_transmission)
log_fatal ("no memory for top-level on_transmission group"); log_fatal ("no memory for top-level on_transmission group");
...@@ -642,7 +642,7 @@ void parse_interface_declaration (cfile, outer_config, name) ...@@ -642,7 +642,7 @@ void parse_interface_declaration (cfile, outer_config, name)
return; return;
} }
ip = interface_or_dummy (val); interface_or_dummy (&ip, val);
/* If we were given a name, this is a pseudo-interface. */ /* If we were given a name, this is a pseudo-interface. */
if (name) { if (name) {
...@@ -687,37 +687,49 @@ void parse_interface_declaration (cfile, outer_config, name) ...@@ -687,37 +687,49 @@ void parse_interface_declaration (cfile, outer_config, name)
token = next_token (&val, cfile); token = next_token (&val, cfile);
} }
struct interface_info *interface_or_dummy (name) int interface_or_dummy (struct interface_info **pi, const char *name)
const char *name;
{ {
struct interface_info *ip; struct interface_info *i;
struct interface_info *ip = (struct interface_info *)0;
/* Find the interface (if any) that matches the name. */ /* Find the interface (if any) that matches the name. */
for (ip = interfaces; ip; ip = ip -> next) { for (i = interfaces; i; i = i -> next) {
if (!strcmp (ip -> name, name)) if (!strcmp (i -> name, name)) {
interface_reference (&ip, i, MDL);
break; break;
}
} }
/* If it's not a real interface, see if it's on the dummy list. */ /* If it's not a real interface, see if it's on the dummy list. */
if (!ip) { if (!ip) {
for (ip = dummy_interfaces; ip; ip = ip -> next) { for (ip = dummy_interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, name)) if (!strcmp (ip -> name, name)) {
interface_reference (&ip, i, MDL);
break; break;
}
} }
} }
/* If we didn't find an interface, make a dummy interface as /* If we didn't find an interface, make a dummy interface as
a placeholder. */ a placeholder. */
if (!ip) { if (!ip) {
ip = (struct interface_info *)dmalloc (sizeof *ip, MDL); isc_result_t status;
if (!ip) status = interface_allocate (&ip, MDL);
log_fatal ("No memory to record interface %s", name); if (status != ISC_R_SUCCESS)
memset (ip, 0, sizeof *ip); log_fatal ("Can't record interface %s: %s",
name, isc_result_totext (status));
strcpy (ip -> name, name); strcpy (ip -> name, name);
ip -> next = dummy_interfaces; if (dummy_interfaces) {
dummy_interfaces = ip; interface_reference (&ip -> next,
dummy_interfaces, MDL);
interface_dereference (&dummy_interfaces, MDL);
}
interface_reference (&dummy_interfaces, ip, MDL);
} }
return ip; if (pi)
interface_reference (pi, ip, MDL);
interface_dereference (&ip, MDL);
return 1;
} }
void make_client_state (state) void make_client_state (state)
...@@ -738,10 +750,11 @@ void make_client_config (client, config) ...@@ -738,10 +750,11 @@ void make_client_config (client, config)
if (!client -> config) if (!client -> config)
log_fatal ("no memory for client config\n"); log_fatal ("no memory for client config\n");
memcpy (client -> config, config, sizeof *config); memcpy (client -> config, config, sizeof *config);
client -> config -> on_receipt = if (!clone_group (&client -> config -> on_receipt,
clone_group (config -> on_receipt, MDL); config -> on_receipt, MDL) ||
client -> config -> on_transmission = !clone_group (&client -> config -> on_transmission,
clone_group (config -> on_transmission, MDL); config -> on_transmission, MDL))
log_fatal ("no memory for client state groups.");
} }
/* client-lease-statement :== /* client-lease-statement :==
...@@ -918,8 +931,7 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp) ...@@ -918,8 +931,7 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp)
skip_to_semi (cfile); skip_to_semi (cfile);
break; break;
} }
ip = interface_or_dummy (val); interface_or_dummy (ipp, val);
*ipp = ip;
break; break;
case NAME: case NAME:
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of The Internet Software Consortium nor the names * 3. Neither the name of Internet Software Consortium nor the names
* of its contributors may be used to endorse or promote products derived * of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission. * from this software without specific prior written permission.
* *
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#ifndef lint #ifndef lint
static char ocopyright[] = static char ocopyright[] =
"$Id: dhclient.c,v 1.101 2000/05/01 17:15:23 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; "$Id: dhclient.c,v 1.102 2000/05/16 23:01:58 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"
...@@ -71,8 +71,7 @@ struct binding_scope global_scope; ...@@ -71,8 +71,7 @@ struct binding_scope global_scope;
assert (state_is == state_shouldbe). */ assert (state_is == state_shouldbe). */
#define ASSERT_STATE(state_is, state_shouldbe) {} #define ASSERT_STATE(state_is, state_shouldbe) {}
static char copyright[] = static char copyright[] = "Copyright 1995-2000 Internet Software Consortium.";
"Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.";
static char arr [] = "All rights reserved."; static char arr [] = "All rights reserved.";
static char message [] = "Internet Software Consortium DHCP Client"; static char message [] = "Internet Software Consortium DHCP Client";
static char contrib [] = "\nPlease contribute if you find this software useful."; static char contrib [] = "\nPlease contribute if you find this software useful.";
...@@ -162,17 +161,20 @@ int main (argc, argv, envp) ...@@ -162,17 +161,20 @@ int main (argc, argv, envp)
} else if (argv [i][0] == '-') { } else if (argv [i][0] == '-') {
usage (); usage ();
} else { } else {
struct interface_info *tmp = ((struct interface_info *) struct interface_info *tmp = (struct interface_info *)0;
dmalloc (sizeof *tmp, MDL)); status = interface_allocate (&tmp, MDL);
if (!tmp) if (status != ISC_R_SUCCESS)
log_fatal ("Insufficient memory to %s %s", log_fatal ("Can't record interface %s:%s",
"record interface", argv [i]); argv [i], isc_result_totext (status));
memset (tmp, 0, sizeof *tmp);
strcpy (tmp -> name, argv [i]); strcpy (tmp -> name, argv [i]);
tmp -> next = interfaces; if (interfaces) {
interface_reference (&tmp -> next,
interfaces, MDL);
interface_dereference (&interfaces, MDL);
}
interface_reference (&interfaces, tmp, MDL);
tmp -> flags = INTERFACE_REQUESTED; tmp -> flags = INTERFACE_REQUESTED;
interfaces_requested = 1; interfaces_requested = 1;
interfaces = tmp;
} }
} }
...@@ -267,7 +269,10 @@ int main (argc, argv, envp) ...@@ -267,7 +269,10 @@ int main (argc, argv, envp)
/* Set up the OMAPI wrappers for various server database internal /* Set up the OMAPI wrappers for various server database internal
objects. */ objects. */
dhclient_db_objects_setup (); dhcp_common_objects_setup ();
dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
/* Discover all the network interfaces. */ /* Discover all the network interfaces. */
discover_interfaces (DISCOVER_UNCONFIGURED); discover_interfaces (DISCOVER_UNCONFIGURED);
...@@ -353,7 +358,7 @@ int main (argc, argv, envp) ...@@ -353,7 +358,7 @@ int main (argc, argv, envp)
/* Set up a timeout to start the initialization /* Set up a timeout to start the initialization
process. */ process. */
add_timeout (cur_time + random () % 5, add_timeout (cur_time + random () % 5,
state_reboot, client); state_reboot, client, 0, 0);
} }
} }
} }
...@@ -391,10 +396,10 @@ static void usage () ...@@ -391,10 +396,10 @@ static void usage ()
"[-cf config-file] [interface]"); "[-cf config-file] [interface]");
} }
struct class *find_class (s) isc_result_t find_class (struct class **c,
const char *s; const char *s, const char *file, int line)
{ {
return (struct class *)0; return 0;
} }
int check_collection (packet, lease, collection) int check_collection (packet, lease, collection)
...@@ -418,10 +423,10 @@ int unbill_class (lease, class) ...@@ -418,10 +423,10 @@ int unbill_class (lease, class)
return 0; return 0;
} }
struct subnet *find_subnet (addr) int find_subnet (struct subnet **sp,
struct iaddr addr; struct iaddr addr, const char *file, int line)
{ {
return (struct subnet *)0; return 0;
} }
/* Individual States: /* Individual States:
...@@ -781,7 +786,7 @@ void bind_lease (client) ...@@ -781,7 +786,7 @@ void bind_lease (client)
/* Set up a timeout to start the renewal process. */ /* Set up a timeout to start the renewal process. */
add_timeout (client -> active -> renewal, add_timeout (client -> active -> renewal,
state_bound, client); state_bound, client, 0, 0);
log_info ("bound to %s -- renewal in %ld seconds.", log_info ("bound to %s -- renewal in %ld seconds.",
piaddr (client -> active -> address), piaddr (client -> active -> address),
...@@ -1025,7 +1030,7 @@ void dhcpoffer (packet) ...@@ -1025,7 +1030,7 @@ void dhcpoffer (packet)
if (stop_selecting <= 0) if (stop_selecting <= 0)
state_selecting (ip); state_selecting (ip);
else { else {
add_timeout (stop_selecting, state_selecting, client); add_timeout (stop_selecting, state_selecting, client, 0, 0);
cancel_timeout (send_discover, client); cancel_timeout (send_discover, client);
} }
} }
...@@ -1269,7 +1274,8 @@ void send_discover (cpp) ...@@ -1269,7 +1274,8 @@ void send_discover (cpp)
inaddr_any, &sockaddr_broadcast, inaddr_any, &sockaddr_broadcast,
(struct hardware *)0); (struct hardware *)0);
add_timeout (cur_time + client -> interval, send_discover, client); add_timeout (cur_time + client -> interval,
send_discover, client, 0, 0);
} }
/* state_panic gets called if we haven't received any offers in a preset /* state_panic gets called if we haven't received any offers in a preset
...@@ -1317,7 +1323,7 @@ void state_panic (cpp) ...@@ -1317,7 +1323,7 @@ void state_panic (cpp)
(long)(client -> active -> renewal - (long)(client -> active -> renewal -
cur_time), "seconds"); cur_time), "seconds");
add_timeout (client -> active -> renewal, add_timeout (client -> active -> renewal,
state_bound, client); state_bound, client, 0, 0);
} else { } else {
client -> state = S_BOUND; client -> state = S_BOUND;
log_info ("bound: immediate renewal."); log_info ("bound: immediate renewal.");
...@@ -1369,7 +1375,7 @@ void state_panic (cpp) ...@@ -1369,7 +1375,7 @@ void state_panic (cpp)
add_timeout (cur_time + add_timeout (cur_time +
((client -> config -> retry_interval + 1) / 2 + ((client -> config -> retry_interval + 1) / 2 +
(random () % client -> config -> retry_interval)), (random () % client -> config -> retry_interval)),
state_init, client); state_init, client, 0, 0);
go_daemon (); go_daemon ();
} }
...@@ -1523,7 +1529,7 @@ void send_request (cpp) ...@@ -1523,7 +1529,7 @@ void send_request (cpp)
(struct hardware *)0); (struct hardware *)0);
add_timeout (cur_time + client -> interval, add_timeout (cur_time + client -> interval,
send_request, client); send_request, client, 0, 0);
} }
void send_decline (cpp) void send_decline (cpp)
...@@ -2383,7 +2389,54 @@ void do_release(client) ...@@ -2383,7 +2389,54 @@ void do_release(client)
} }
} }
int dhclient_interface_shutdown_hook (struct interface_info *interface)
{
do_release (interface -> client);
return 1;
}
int dhclient_interface_discovery_hook (struct interface_info *tmp)
{
struct interface_info *last, *ip;
/* See if we can find the client from dummy_interfaces */
last = 0;
for (ip = dummy_interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, tmp -> name)) {
/* Remove from dummy_interfaces */
if (last) {
ip = (struct interface_info *)0;
interface_reference (&ip, last -> next, MDL);
interface_dereference (&last -> next, MDL);
if (ip -> next) {
interface_reference (&last -> next,
ip -> next, MDL);
interface_dereference (&ip -> next,
MDL);
}
} else {
ip = (struct interface_info *)0;
interface_reference (&ip,
dummy_interfaces, MDL);
interface_dereference (&dummy_interfaces, MDL);
if (ip -> next) {
interface_reference (&dummy_interfaces,
ip -> next, MDL);
interface_dereference (&ip -> next,
MDL);
}
}
/* Copy "client" to tmp */
if (ip -> client) {
tmp -> client = ip -> client;
tmp -> client -> interface = tmp;
}
interface_dereference (&ip, MDL);
break;
}
last = ip;
}
return 1;
}
/* The client should never receive a relay agent information option, /* The client should never receive a relay agent information option,
so if it does, log it and discard it. */ so if it does, log it and discard it. */
......
...@@ -43,286 +43,8 @@ ...@@ -43,286 +43,8 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: omapi.c,v 1.4 2000/03/17 03:58:56 mellon Exp $ Copyright (c) 2000 The Internet Software Consortium. All rights reserved.\n"; "$Id: omapi.c,v 1.5 2000/05/16 23:02:00 mellon Exp $ Copyright (c) 2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
#include <omapip/omapip_p.h> #include <omapip/omapip_p.h>
void dhclient_db_objects_setup ()
{
isc_result_t status;
status = omapi_object_type_register (&dhcp_type_interface,
"interface",
dhclient_interface_set_value,
dhclient_interface_get_value,
dhclient_interface_destroy,
dhclient_interface_signal_handler,
dhclient_interface_stuff_values,
dhclient_interface_lookup,
dhclient_interface_create,
dhclient_interface_remove);
if (status != ISC_R_SUCCESS)
log_fatal ("Can't register interface object type: %s",
isc_result_totext (status));
}
isc_result_t dhclient_interface_set_value (omapi_object_t *h,
omapi_object_t *id,
omapi_data_string_t *name,
omapi_typed_data_t *value)
{
struct interface_info *interface;
isc_result_t status;
int foo;
if (h -> type != dhcp_type_interface)
return ISC_R_INVALIDARG;
interface = (struct interface_info *)h;
if (!omapi_ds_strcmp (name, "name")) {
if (value -> type == omapi_datatype_data ||
value -> type == omapi_datatype_string) {
memcpy (interface -> name,
value -> u.buffer.value,
value -> u.buffer.len);
interface -> name [value -> u.buffer.len] = 0;
} else
return ISC_R_INVALIDARG;
return ISC_R_SUCCESS;
}
/* Try to find some inner object that can take the value. */
if (h -> inner && h -> inner -> type -> set_value) {
status = ((*(h -> inner -> type -> set_value))
(h -> inner, id, name, value));
if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
return status;
}
return ISC_R_NOTFOUND;
}
isc_result_t dhclient_interface_get_value (omapi_object_t *h,
omapi_object_t *id,
omapi_data_string_t *name,
omapi_value_t **value)
{
return ISC_R_NOTIMPLEMENTED;
}
isc_result_t dhclient_interface_destroy (omapi_object_t *h,
const char *file, int line)
{
struct interface_info *interface;
isc_result_t status;
if (h -> type != dhcp_type_interface)
return ISC_R_INVALIDARG;
interface = (struct interface_info *)h;
if (interface -> ifp)
free (interface -> ifp);
dfree (interface, file, line);
return ISC_R_SUCCESS;
}
isc_result_t dhclient_interface_signal_handler (omapi_object_t *h,
const char *name, va_list ap)
{
struct interface_info *ip, *interface;
struct client_config *config;
struct client_state *client;
if (h -> type != dhcp_type_interface)
return ISC_R_INVALIDARG;
interface = (struct interface_info *)h;
interface -> next = interfaces;
interfaces = interface;
discover_interfaces (DISCOVER_UNCONFIGURED);
for (ip = interfaces; ip; ip = ip -> next) {
/* If interfaces were specified, don't configure
interfaces that weren't specified! */
if (ip -> flags & INTERFACE_RUNNING ||
(ip -> flags & (INTERFACE_REQUESTED |
INTERFACE_AUTOMATIC)) !=
INTERFACE_REQUESTED)
continue;
script_init (ip -> client,
"PREINIT", (struct string_list *)0);
if (ip -> client -> alias)
script_write_params (ip -> client, "alias_",
ip -> client -> alias);
script_go (ip -> client);
}
discover_interfaces (interfaces_requested
? DISCOVER_REQUESTED
: DISCOVER_RUNNING);
for (ip = interfaces; ip; ip = ip -> next) {
if (ip -> flags & INTERFACE_RUNNING)
continue;
ip -> flags |= INTERFACE_RUNNING;
for (client = ip -> client; client; client = client -> next) {
client -> state = S_INIT;
/* Set up a timeout to start the initialization
process. */
add_timeout (cur_time + random () % 5,
state_reboot, client);
}
}
return ISC_R_SUCCESS;
}
isc_result_t dhclient_interface_stuff_values (omapi_object_t *c,
omapi_object_t *id,
omapi_object_t *h)
{
struct interface_info *interface;
isc_result_t status;
if (h -> type != dhcp_type_interface)
return ISC_R_INVALIDARG;
interface = (struct interface_info *)h;
/* Write out all the values. */
status = omapi_connection_put_name (c, "state");
if (status != ISC_R_SUCCESS)
return status;
if (interface -> flags && INTERFACE_REQUESTED)
status = omapi_connection_put_string (c, "up");
else
status = omapi_connection_put_string (c, "down");
if (status != ISC_R_SUCCESS)
return status;