From a034015fac06a1d1fcf0811fd4f9300a2f52bee0 Mon Sep 17 00:00:00 2001 From: Ted Lemon Date: Thu, 28 Dec 2000 23:14:46 +0000 Subject: [PATCH] Move interface code so that it doesn't pollute the relay agent. --- common/comapi.c | 310 +---------------------------------------- common/discover.c | 343 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 293 insertions(+), 360 deletions(-) diff --git a/common/comapi.c b/common/comapi.c index ff95f1c28..405769ba3 100644 --- a/common/comapi.c +++ b/common/comapi.c @@ -50,14 +50,12 @@ #ifndef lint static char copyright[] = -"$Id: comapi.c,v 1.6 2000/10/10 22:04:31 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: comapi.c,v 1.7 2000/12/28 23:14:05 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include -int (*dhcp_interface_shutdown_hook) (struct interface_info *); - omapi_object_type_t *dhcp_type_interface; omapi_object_type_t *dhcp_type_group; omapi_object_type_t *dhcp_type_shared_network; @@ -113,22 +111,7 @@ void dhcp_common_objects_setup () log_fatal ("Can't register shared network object type: %s", isc_result_totext (status)); - status = omapi_object_type_register (&dhcp_type_interface, - "interface", - dhcp_interface_set_value, - dhcp_interface_get_value, - dhcp_interface_destroy, - dhcp_interface_signal_handler, - dhcp_interface_stuff_values, - dhcp_interface_lookup, - dhcp_interface_create, - dhcp_interface_remove, - 0, 0, 0, - sizeof (struct interface_info), - 0); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't register interface object type: %s", - isc_result_totext (status)); + interface_setup (); } isc_result_t dhcp_group_set_value (omapi_object_t *h, @@ -724,292 +707,3 @@ isc_result_t dhcp_shared_network_remove (omapi_object_t *lp, return ISC_R_NOTIMPLEMENTED; } -isc_result_t dhcp_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) && - value -> u.buffer.len < sizeof interface -> name) { - 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 dhcp_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 dhcp_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) - dfree (interface -> ifp, file, line); - return ISC_R_SUCCESS; -} - -isc_result_t dhcp_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; - isc_result_t status; - - if (h -> type != dhcp_type_interface) - return ISC_R_INVALIDARG; - - /* This code needs some rethinking. It doesn't test against - a signal name, and it just kind of bulls into doing something - that may or may not be appropriate. */ -#if 0 - interface = (struct interface_info *)h; - - if (interfaces) { - interface_reference (&interface -> next, interfaces, MDL); - interface_dereference (&interfaces, MDL); - } - interface_reference (&interfaces, interface, MDL); - - 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, 0, 0); - } - } - return ISC_R_SUCCESS; -#endif - /* Try to find some inner object that can take the value. */ - if (h -> inner && h -> inner -> type -> get_value) { - status = ((*(h -> inner -> type -> signal_handler)) - (h -> inner, name, ap)); - if (status == ISC_R_SUCCESS) - return status; - } - return ISC_R_NOTFOUND; -} - -isc_result_t dhcp_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 dhcp_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 dhcp_interface_create (omapi_object_t **lp, - omapi_object_t *id) -{ - struct interface_info *hp; - isc_result_t status; - - hp = (struct interface_info *)0; - status = interface_allocate (&hp, MDL); - if (status != ISC_R_SUCCESS) - return status; - hp -> flags = INTERFACE_REQUESTED; - status = interface_reference ((struct interface_info **)lp, hp, MDL); - interface_dereference (&hp, MDL); - return status; -} - -isc_result_t dhcp_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 (ip == interface) { - if (last) { - interface_dereference (&last -> next, MDL); - if (ip -> next) - interface_reference (&last -> next, - ip -> next, MDL); - } else { - interface_dereference (&interfaces, MDL); - if (ip -> next) - interface_reference (&interfaces, - ip -> next, MDL); - } - if (ip -> next) - interface_dereference (&ip -> next, MDL); - break; - } - last = ip; - } - if (!ip) - return ISC_R_NOTFOUND; - - /* add the interface to the dummy_interface list */ - if (dummy_interfaces) { - interface_reference (&interface -> next, - dummy_interfaces, MDL); - interface_dereference (&dummy_interfaces, MDL); - } - interface_reference (&dummy_interfaces, interface, MDL); - - /* do a DHCPRELEASE */ - if (dhcp_interface_shutdown_hook) - (*dhcp_interface_shutdown_hook) (interface); - - /* remove the io object */ - omapi_unregister_io_object ((omapi_object_t *)interface); - - if_deregister_send (interface); - if_deregister_receive (interface); - - return ISC_R_SUCCESS; -} diff --git a/common/discover.c b/common/discover.c index 67e9997bc..0bc73f641 100644 --- a/common/discover.c +++ b/common/discover.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: discover.c,v 1.34 2000/10/10 22:31:41 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: discover.c,v 1.35 2000/12/28 23:14:46 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -56,6 +56,7 @@ u_int16_t local_port; u_int16_t remote_port; int (*dhcp_interface_setup_hook) (struct interface_info *, struct iaddr *); int (*dhcp_interface_discovery_hook) (struct interface_info *); +int (*dhcp_interface_shutdown_hook) (struct interface_info *); struct in_addr limited_broadcast; struct in_addr local_address; @@ -69,6 +70,28 @@ omapi_object_type_t *dhcp_type_interface; OMAPI_OBJECT_ALLOC (interface, struct interface_info, dhcp_type_interface) +isc_result_t interface_setup () +{ + isc_result_t status; + status = omapi_object_type_register (&dhcp_type_interface, + "interface", + dhcp_interface_set_value, + dhcp_interface_get_value, + dhcp_interface_destroy, + dhcp_interface_signal_handler, + dhcp_interface_stuff_values, + dhcp_interface_lookup, + dhcp_interface_create, + dhcp_interface_remove, + 0, 0, 0, + sizeof (struct interface_info), + 0); + if (status != ISC_R_SUCCESS) + log_fatal ("Can't register interface object type: %s", + isc_result_totext (status)); + return status; +} + isc_result_t interface_initialize (omapi_object_t *ipo, const char *file, int line) { @@ -105,19 +128,6 @@ void discover_interfaces (state) static int setup_fallback = 0; int wifcount = 0; - if (!dhcp_type_interface) { - status = omapi_object_type_register - (&dhcp_type_interface, "interface", - interface_set_value, interface_get_value, - interface_destroy, interface_signal_handler, - interface_stuff_values, 0, 0, 0, 0, 0, 0, - sizeof (struct interface_info), - interface_initialize); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't create interface object type: %s", - isc_result_totext (status)); - } - /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) log_fatal ("Can't create addrlist socket"); @@ -673,6 +683,7 @@ isc_result_t got_one (h) return ISC_R_INVALIDARG; ip = (struct interface_info *)h; + again: if ((result = receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)) < 0) { log_error ("receive_packet failed on %s: %m", ip -> name); @@ -696,72 +707,300 @@ isc_result_t got_one (h) (*bootp_packet_handler) (ip, &u.packet, (unsigned)result, from.sin_port, ifrom, &hfrom); } + + /* If there is buffered data, read again. This is for, e.g., + bpf, which may return two packets at once. */ + if (ip -> rbuf_offset != ip -> rbuf_len) + goto again; return ISC_R_SUCCESS; } -isc_result_t interface_set_value (omapi_object_t *h, - omapi_object_t *id, - omapi_data_string_t *name, - omapi_typed_data_t *value) +isc_result_t dhcp_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; - - if (h -> inner && h -> inner -> type -> set_value) - return (*(h -> inner -> type -> set_value)) - (h -> inner, id, name, value); + interface = (struct interface_info *)h; + + if (!omapi_ds_strcmp (name, "name")) { + if ((value -> type == omapi_datatype_data || + value -> type == omapi_datatype_string) && + value -> u.buffer.len < sizeof interface -> name) { + 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 interface_get_value (omapi_object_t *h, - omapi_object_t *id, - omapi_data_string_t *name, - omapi_value_t **value) + +isc_result_t dhcp_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 dhcp_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; - - if (h -> inner && h -> inner -> type -> get_value) - return (*(h -> inner -> type -> get_value)) - (h -> inner, id, name, value); - return ISC_R_NOTFOUND; + interface = (struct interface_info *)h; + + if (interface -> ifp) + dfree (interface -> ifp, file, line); + return ISC_R_SUCCESS; } -isc_result_t interface_stuff_values (omapi_object_t *c, - omapi_object_t *id, - omapi_object_t *m) +isc_result_t dhcp_interface_signal_handler (omapi_object_t *h, + const char *name, va_list ap) { - if (m -> type != dhcp_type_interface) + struct interface_info *ip, *interface; + struct client_config *config; + struct client_state *client; + isc_result_t status; + + if (h -> type != dhcp_type_interface) return ISC_R_INVALIDARG; + + /* This code needs some rethinking. It doesn't test against + a signal name, and it just kind of bulls into doing something + that may or may not be appropriate. */ +#if 0 + interface = (struct interface_info *)h; + + if (interfaces) { + interface_reference (&interface -> next, interfaces, MDL); + interface_dereference (&interfaces, MDL); + } + interface_reference (&interfaces, interface, MDL); + + 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); + } - if (m -> inner && m -> inner -> type -> stuff_values) - return (*(m -> inner -> type -> stuff_values)) (c, id, - m -> inner); + 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, 0, 0); + } + } + return ISC_R_SUCCESS; +#endif + /* Try to find some inner object that can take the value. */ + if (h -> inner && h -> inner -> type -> get_value) { + status = ((*(h -> inner -> type -> signal_handler)) + (h -> inner, name, ap)); + if (status == ISC_R_SUCCESS) + return status; + } return ISC_R_NOTFOUND; } -isc_result_t interface_destroy (omapi_object_t *h, const char *file, int line) +isc_result_t dhcp_interface_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *h) { - int i; + struct interface_info *interface; + isc_result_t status; - struct interface_info *p; if (h -> type != dhcp_type_interface) return ISC_R_INVALIDARG; - /* Nothing to do yet, AFAIK - interfaces should never be - destroyed. Revisit this later when we handle interface - detection/deletion on the fly. */ + 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 interface_signal_handler (omapi_object_t *h, - const char *name, va_list ap) +isc_result_t dhcp_interface_lookup (omapi_object_t **ip, + omapi_object_t *id, + omapi_object_t *ref) { - if (h -> type != dhcp_type_interface) - return ISC_R_INVALIDARG; + 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 dhcp_interface_create (omapi_object_t **lp, + omapi_object_t *id) +{ + struct interface_info *hp; + isc_result_t status; - if (h -> inner && h -> inner -> type -> signal_handler) - return (*(h -> inner -> type -> signal_handler)) (h -> inner, - name, ap); - return ISC_R_NOTFOUND; + hp = (struct interface_info *)0; + status = interface_allocate (&hp, MDL); + if (status != ISC_R_SUCCESS) + return status; + hp -> flags = INTERFACE_REQUESTED; + status = interface_reference ((struct interface_info **)lp, hp, MDL); + interface_dereference (&hp, MDL); + return status; } +isc_result_t dhcp_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 (ip == interface) { + if (last) { + interface_dereference (&last -> next, MDL); + if (ip -> next) + interface_reference (&last -> next, + ip -> next, MDL); + } else { + interface_dereference (&interfaces, MDL); + if (ip -> next) + interface_reference (&interfaces, + ip -> next, MDL); + } + if (ip -> next) + interface_dereference (&ip -> next, MDL); + break; + } + last = ip; + } + if (!ip) + return ISC_R_NOTFOUND; + + /* add the interface to the dummy_interface list */ + if (dummy_interfaces) { + interface_reference (&interface -> next, + dummy_interfaces, MDL); + interface_dereference (&dummy_interfaces, MDL); + } + interface_reference (&dummy_interfaces, interface, MDL); + + /* do a DHCPRELEASE */ + if (dhcp_interface_shutdown_hook) + (*dhcp_interface_shutdown_hook) (interface); + + /* remove the io object */ + omapi_unregister_io_object ((omapi_object_t *)interface); + + if_deregister_send (interface); + if_deregister_receive (interface); + + return ISC_R_SUCCESS; +} -- 2.47.3