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

- 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 @@
#ifndef lint
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 */
#include "dhcpd.h"
......@@ -97,11 +97,11 @@ isc_result_t read_client_conf ()
top_level_config.script_name = "/etc/dhclient-script";
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)
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)
log_fatal ("no memory for top-level on_transmission group");
......@@ -642,7 +642,7 @@ void parse_interface_declaration (cfile, outer_config, name)
return;
}
ip = interface_or_dummy (val);
interface_or_dummy (&ip, val);
/* If we were given a name, this is a pseudo-interface. */
if (name) {
......@@ -687,37 +687,49 @@ void parse_interface_declaration (cfile, outer_config, name)
token = next_token (&val, cfile);
}
struct interface_info *interface_or_dummy (name)
const char *name;
int interface_or_dummy (struct interface_info **pi, 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. */
for (ip = interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, name))
for (i = interfaces; i; i = i -> next) {
if (!strcmp (i -> name, name)) {
interface_reference (&ip, i, MDL);
break;
}
}
/* If it's not a real interface, see if it's on the dummy list. */
if (!ip) {
for (ip = dummy_interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, name))
if (!strcmp (ip -> name, name)) {
interface_reference (&ip, i, MDL);
break;
}
}
}
/* If we didn't find an interface, make a dummy interface as
a placeholder. */
if (!ip) {
ip = (struct interface_info *)dmalloc (sizeof *ip, MDL);
if (!ip)
log_fatal ("No memory to record interface %s", name);
memset (ip, 0, sizeof *ip);
isc_result_t status;
status = interface_allocate (&ip, MDL);
if (status != ISC_R_SUCCESS)
log_fatal ("Can't record interface %s: %s",
name, isc_result_totext (status));
strcpy (ip -> name, name);
ip -> next = dummy_interfaces;
dummy_interfaces = ip;
if (dummy_interfaces) {
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)
......@@ -738,10 +750,11 @@ void make_client_config (client, config)
if (!client -> config)
log_fatal ("no memory for client config\n");
memcpy (client -> config, config, sizeof *config);
client -> config -> on_receipt =
clone_group (config -> on_receipt, MDL);
client -> config -> on_transmission =
clone_group (config -> on_transmission, MDL);
if (!clone_group (&client -> config -> on_receipt,
config -> on_receipt, MDL) ||
!clone_group (&client -> config -> on_transmission,
config -> on_transmission, MDL))
log_fatal ("no memory for client state groups.");
}
/* client-lease-statement :==
......@@ -918,8 +931,7 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp)
skip_to_semi (cfile);
break;
}
ip = interface_or_dummy (val);
*ipp = ip;
interface_or_dummy (ipp, val);
break;
case NAME:
......
......@@ -15,7 +15,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 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
* from this software without specific prior written permission.
*
......@@ -41,7 +41,7 @@
#ifndef lint
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 */
#include "dhcpd.h"
......@@ -71,8 +71,7 @@ struct binding_scope global_scope;
assert (state_is == state_shouldbe). */
#define ASSERT_STATE(state_is, state_shouldbe) {}
static char copyright[] =
"Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.";
static char copyright[] = "Copyright 1995-2000 Internet Software Consortium.";
static char arr [] = "All rights reserved.";
static char message [] = "Internet Software Consortium DHCP Client";
static char contrib [] = "\nPlease contribute if you find this software useful.";
......@@ -162,17 +161,20 @@ int main (argc, argv, envp)
} else if (argv [i][0] == '-') {
usage ();
} else {
struct interface_info *tmp = ((struct interface_info *)
dmalloc (sizeof *tmp, MDL));
if (!tmp)
log_fatal ("Insufficient memory to %s %s",
"record interface", argv [i]);
memset (tmp, 0, sizeof *tmp);
struct interface_info *tmp = (struct interface_info *)0;
status = interface_allocate (&tmp, MDL);
if (status != ISC_R_SUCCESS)
log_fatal ("Can't record interface %s:%s",
argv [i], isc_result_totext (status));
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;
interfaces_requested = 1;
interfaces = tmp;
}
}
......@@ -267,7 +269,10 @@ int main (argc, argv, envp)
/* Set up the OMAPI wrappers for various server database internal
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_interfaces (DISCOVER_UNCONFIGURED);
......@@ -353,7 +358,7 @@ int main (argc, argv, envp)
/* Set up a timeout to start the initialization
process. */
add_timeout (cur_time + random () % 5,
state_reboot, client);
state_reboot, client, 0, 0);
}
}
}
......@@ -391,10 +396,10 @@ static void usage ()
"[-cf config-file] [interface]");
}
struct class *find_class (s)
const char *s;
isc_result_t find_class (struct class **c,
const char *s, const char *file, int line)
{
return (struct class *)0;
return 0;
}
int check_collection (packet, lease, collection)
......@@ -418,10 +423,10 @@ int unbill_class (lease, class)
return 0;
}
struct subnet *find_subnet (addr)
struct iaddr addr;
int find_subnet (struct subnet **sp,
struct iaddr addr, const char *file, int line)
{
return (struct subnet *)0;
return 0;
}
/* Individual States:
......@@ -781,7 +786,7 @@ void bind_lease (client)
/* Set up a timeout to start the renewal process. */
add_timeout (client -> active -> renewal,
state_bound, client);
state_bound, client, 0, 0);
log_info ("bound to %s -- renewal in %ld seconds.",
piaddr (client -> active -> address),
......@@ -1025,7 +1030,7 @@ void dhcpoffer (packet)
if (stop_selecting <= 0)
state_selecting (ip);
else {
add_timeout (stop_selecting, state_selecting, client);
add_timeout (stop_selecting, state_selecting, client, 0, 0);
cancel_timeout (send_discover, client);
}
}
......@@ -1269,7 +1274,8 @@ void send_discover (cpp)
inaddr_any, &sockaddr_broadcast,
(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
......@@ -1317,7 +1323,7 @@ void state_panic (cpp)
(long)(client -> active -> renewal -
cur_time), "seconds");
add_timeout (client -> active -> renewal,
state_bound, client);
state_bound, client, 0, 0);
} else {
client -> state = S_BOUND;
log_info ("bound: immediate renewal.");
......@@ -1369,7 +1375,7 @@ void state_panic (cpp)
add_timeout (cur_time +
((client -> config -> retry_interval + 1) / 2 +
(random () % client -> config -> retry_interval)),
state_init, client);
state_init, client, 0, 0);
go_daemon ();
}
......@@ -1523,7 +1529,7 @@ void send_request (cpp)
(struct hardware *)0);
add_timeout (cur_time + client -> interval,
send_request, client);
send_request, client, 0, 0);
}
void send_decline (cpp)
......@@ -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,
so if it does, log it and discard it. */
......
......@@ -43,286 +43,8 @@
#ifndef lint
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 */
#include "dhcpd.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;
/* Write out the inner object, if any. */
if (h -> inner && h -> inner -> type -> stuff_values) {
status = ((*(h -> inner -> type -> stuff_values))
(c, id, h -> inner));
if (status == ISC_R_SUCCESS)
return status;
}
return ISC_R_SUCCESS;
}
isc_result_t dhclient_interface_lookup (omapi_object_t **ip,
omapi_object_t *id,
omapi_object_t *ref)
{
omapi_value_t *tv = (omapi_value_t *)0;
isc_result_t status;
struct interface_info *interface;
/* First see if we were sent a handle. */
status = omapi_get_value_str (ref, id, "handle", &tv);
if (status == ISC_R_SUCCESS) {
status = omapi_handle_td_lookup (ip, tv -> value);
omapi_value_dereference (&tv, MDL);
if (status != ISC_R_SUCCESS)
return status;
/* Don't return the object if the type is wrong. */
if ((*ip) -> type != dhcp_type_interface) {
omapi_object_dereference (ip, MDL);
return ISC_R_INVALIDARG;
}
}
/* Now look for an interface name. */
status = omapi_get_value_str (ref, id, "name", &tv);
if (status == ISC_R_SUCCESS) {
for (interface = interfaces; interface;
interface = interface -> next) {
if (strncmp (interface -> name,
(char *)tv -> value -> u.buffer.value,
tv -> value -> u.buffer.len) == 0)
break;
}
omapi_value_dereference (&tv, MDL);
if (*ip && *ip != (omapi_object_t *)interface) {
omapi_object_dereference (ip, MDL);
return ISC_R_KEYCONFLICT;
} else if (!interface) {
if (*ip)
omapi_object_dereference (ip, MDL);
return ISC_R_NOTFOUND;
} else if (!*ip)
/* XXX fix so that hash lookup itself creates
XXX the reference. */
omapi_object_reference (ip,
(omapi_object_t *)interface,
MDL);
}
/* If we get to here without finding an interface, no valid key was
specified. */
if (!*ip)
return ISC_R_NOKEYS;
return ISC_R_SUCCESS;
}
/* actually just go discover the interface */
isc_result_t dhclient_interface_create (omapi_object_t **lp,
omapi_object_t *id)
{
struct interface_info *hp;
hp = (struct interface_info *)dmalloc (sizeof (struct interface_info),
MDL);
if (!hp)
return ISC_R_NOMEMORY;
memset (hp, 0, sizeof *hp);
hp -> refcnt = 0;
hp -> type = dhcp_type_interface;
hp -> flags = INTERFACE_REQUESTED;
return omapi_object_reference (lp, (omapi_object_t *)hp, MDL);
}
isc_result_t dhclient_interface_remove (omapi_object_t *lp,
omapi_object_t *id)
{
struct interface_info *interface, *ip, *last;
interface = (struct interface_info *)lp;
/* remove from interfaces */
last = 0;
for (ip = interfaces; ip; ip = ip -> next) {
if (!strcmp (ip -> name, interface -> name)) {
if (last)
last -> next = ip -> next;
else
interfaces = ip -> next;
break;
}
last = ip;
}
/* add the interface to the dummy_interface list */
interface -> next = dummy_interfaces;
dummy_interfaces = interface;
/* do a DHCPRELEASE */
do_release (interface -> client);
/* remove the io object */
omapi_io_destroy (interface -> outer, MDL);
if_deregister_send (interface);
if_deregister_receive (interface);
return ISC_R_SUCCESS;
}
......@@ -22,11 +22,11 @@ SEDMANPAGES = dhcp-options.man5 dhcp-contrib.man5 dhcp-eval.man5
SRC = raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c socket.c \
lpf.c dlpi.c packet.c tr.c ethernet.c memory.c print.c options.c \
inet.c convert.c tree.c tables.c hash.c alloc.c fddi.c \
inet_addr.c dns.c resolv.c execute.c discover.c auth.c
inet_addr.c dns.c resolv.c execute.c discover.c comapi.c
OBJ = raw.o parse.o nit.o icmp.o dispatch.o conflex.o upf.o bpf.o socket.o \
lpf.o dlpi.o packet.o tr.o ethernet.o memory.o print.o options.o \
inet.o convert.o tree.o tables.o hash.o alloc.o fddi.o \
inet_addr.o dns.o resolv.o execute.o discover.o auth.o
inet_addr.o dns.o resolv.o execute.o discover.o comapi.o
MAN = dhcp-options.5 dhcp-contrib.5 dhcp-eval.5
DEBUG = -g
......
......@@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =