From: Ted Lemon Date: Wed, 8 Sep 1999 01:36:05 +0000 (+0000) Subject: OMAPI interface for ISC DHCP server objects. X-Git-Tag: V3-BETA-1-PATCH-2~5^2~136 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c5222526f01f24a1ab6372c044963add70250bb;p=thirdparty%2Fdhcp.git OMAPI interface for ISC DHCP server objects. --- diff --git a/server/omapi.c b/server/omapi.c new file mode 100644 index 000000000..4ae380191 --- /dev/null +++ b/server/omapi.c @@ -0,0 +1,1147 @@ +/* omapi.c + + OMAPI object interfaces for the DHCP server. */ + +/* + * Copyright (c) 1996-1999 Internet Software Consortium. + * Use is subject to license terms which appear in the file named + * ISC-LICENSE that should have accompanied this file when you + * received it. If a file named ISC-LICENSE did not accompany this + * file, or you are not sure the one you have is correct, you may + * obtain an applicable copy of the license at: + * + * http://www.isc.org/isc-license-1.0.html. + * + * This file is part of the ISC DHCP distribution. The documentation + * associated with this file is listed in the file DOCUMENTATION, + * included in the top-level directory of this release. + * + * Support and other services are available for ISC products - see + * http://www.isc.org for more information. + */ + +/* Many, many thanks to Brian Murrell and BCtel for this code - BCtel + provided the funding that resulted in this code and the entire + OMAPI support library being written, and Brian helped brainstorm + and refine the requirements. To the extent that this code is + useful, you have Brian and BCtel to thank. Any limitations in the + code are a result of mistakes on my part. -- Ted Lemon */ + +#ifndef lint +static char copyright[] = +"$Id: omapi.c,v 1.1 1999/09/08 01:36:05 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; +#endif /* not lint */ + +#include "dhcpd.h" + +omapi_object_type_t *dhcp_type_lease; +omapi_object_type_t *dhcp_type_group; +omapi_object_type_t *dhcp_type_host; +omapi_object_type_t *dhcp_type_pool; +omapi_object_type_t *dhcp_type_shared_network; +omapi_object_type_t *dhcp_type_subnet; +omapi_object_type_t *dhcp_type_class; + +void dhcp_db_objects_setup () +{ + isc_result_t status; + + status = omapi_object_type_register (&dhcp_type_lease, + "lease", + dhcp_lease_set_value, + dhcp_lease_get_value, + dhcp_lease_destroy, + dhcp_lease_signal_handler, + dhcp_lease_stuff_values, + dhcp_lease_lookup, + dhcp_lease_create); + if (status != ISC_R_SUCCESS) + log_fatal ("Can't register lease object type: %s", + isc_result_totext (status)); + + status = omapi_object_type_register (&dhcp_type_host, + "host", + dhcp_host_set_value, + dhcp_host_get_value, + dhcp_host_destroy, + dhcp_host_signal_handler, + dhcp_host_stuff_values, + dhcp_host_lookup, + dhcp_host_create); + if (status != ISC_R_SUCCESS) + log_fatal ("Can't register host object type: %s", + isc_result_totext (status)); + + status = omapi_object_type_register (&dhcp_type_pool, + "pool", + dhcp_pool_set_value, + dhcp_pool_get_value, + dhcp_pool_destroy, + dhcp_pool_signal_handler, + dhcp_pool_stuff_values, + dhcp_pool_lookup, + dhcp_pool_create); + if (status != ISC_R_SUCCESS) + log_fatal ("Can't register pool object type: %s", + isc_result_totext (status)); +} + +isc_result_t dhcp_lease_set_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_typed_data_t *value) +{ + struct lease *lease; + isc_result_t status; + int foo; + + if (h -> type != omapi_type_message) + return ISC_R_INVALIDARG; + lease = (struct lease *)h; + + /* We're skipping a lot of things it might be interesting to + set - for now, we just make it possible to whack the abandoned + flag. */ + if (!omapi_ds_strcmp (name, "abandoned")) { + int bar; + + if (value -> type == omapi_datatype_int) + 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; + + foo = lease -> flags; + if (bar) + lease -> flags |= ABANDONED_LEASE; + else + lease -> flags &= ~ABANDONED_LEASE; + if (foo != lease -> flags) + return ISC_R_SUCCESS; + return ISC_R_UNCHANGED; + } + + /* 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_lease_get_value (omapi_object_t *h, omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + struct lease *lease; + isc_result_t status; + + if (h -> type != dhcp_type_lease) + return ISC_R_INVALIDARG; + lease = (struct lease *)h; + + if (!omapi_ds_strcmp (name, "abandoned")) + return omapi_make_int_value (value, name, + (lease -> flags & + ABANDONED_LEASE) ? 1 : 0, + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "bootpp")) + return omapi_make_int_value (value, name, + (lease -> flags & + BOOTP_LEASE) ? 1 : 0, + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "ip-address")) + return omapi_make_const_value (value, name, + lease -> ip_addr.iabuf, + lease -> ip_addr.len, + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) + return omapi_make_const_value (value, name, + lease -> uid, + lease -> uid_len, + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "hostname")) + return omapi_make_string_value (value, name, + lease -> hostname, + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "client-hostname")) + return omapi_make_string_value (value, name, + lease -> client_hostname, + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "ddns-fwd-name")) + return omapi_make_string_value (value, name, + lease -> ddns_fwd_name, + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "ddns-rev-name")) + return omapi_make_string_value (value, name, + lease -> ddns_rev_name, + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "host")) + return omapi_make_handle_value (value, name, + ((omapi_object_t *) + lease -> host), + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "subnet")) + return omapi_make_handle_value (value, name, + ((omapi_object_t *) + lease -> subnet), + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "pool")) + return omapi_make_handle_value (value, name, + ((omapi_object_t *) + lease -> pool), + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "billing-class")) + return omapi_make_handle_value (value, name, + ((omapi_object_t *) + lease -> billing_class), + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "hardware-address")) + return omapi_make_const_value (value, name, + lease -> hardware_addr.haddr, + lease -> hardware_addr.hlen, + "dhcp_lease_get_value"); + else if (!omapi_ds_strcmp (name, "hardware-type")) + return omapi_make_int_value (value, name, + lease -> hardware_addr.htype, + "dhcp_lease_get_value"); + + /* Try to find some inner object that can take the value. */ + if (h -> inner && h -> inner -> type -> get_value) { + status = ((*(h -> inner -> type -> get_value)) + (h -> inner, id, name, value)); + if (status == ISC_R_SUCCESS) + return status; + } + return ISC_R_NOTFOUND; +} + +isc_result_t dhcp_lease_destroy (omapi_object_t *h, char *name) +{ + struct lease *lease; + isc_result_t status; + + if (h -> type != dhcp_type_lease) + return ISC_R_INVALIDARG; + lease = (struct lease *)h; + + uid_hash_delete (lease); + hw_hash_delete (lease); + if (lease -> billing_class) + omapi_object_dereference + ((omapi_object_t **)&lease -> billing_class, name); + if (lease -> uid && lease -> uid != &lease -> uid_buf [0]) { + free (lease -> uid); + lease -> uid = &lease -> uid_buf [0]; + lease -> uid_len = 0; + } + if (lease -> hostname) { + free (lease -> hostname); + lease -> hostname = (char *)0; + } + if (lease -> client_hostname) { + free (lease -> client_hostname); + lease -> hostname = (char *)0; + } + if (lease -> ddns_fwd_name) { + free (lease -> ddns_fwd_name); + lease -> ddns_fwd_name = (char *)0; + } + if (lease -> ddns_rev_name) { + free (lease -> ddns_rev_name); + lease -> ddns_rev_name = (char *)0; + } + if (lease -> host) + omapi_object_dereference ((omapi_object_t **)&lease -> host, + name); + if (lease -> subnet) + omapi_object_dereference ((omapi_object_t **)&lease -> subnet, + name); + if (lease -> pool) + omapi_object_dereference ((omapi_object_t **)&lease -> pool, + name); + if (lease -> on_expiry) + executable_statement_dereference (&lease -> on_expiry, name); + if (lease -> on_commit) + executable_statement_dereference (&lease -> on_commit, name); + if (lease -> on_release) + executable_statement_dereference (&lease -> on_release, name); + if (lease -> state) { + data_string_forget (&lease -> state -> parameter_request_list, + name); + free_lease_state (lease -> state, name); + lease -> state = (struct lease_state *)0; + + cancel_timeout (lease_ping_timeout, lease); + --outstanding_pings; /* XXX */ + } + return ISC_R_SUCCESS; +} + +isc_result_t dhcp_lease_signal_handler (omapi_object_t *h, + char *name, va_list ap) +{ + struct lease *lease; + isc_result_t status; + + if (h -> type != dhcp_type_lease) + return ISC_R_INVALIDARG; + lease = (struct lease *)h; + + if (!strcmp (name, "updated")) { + if (!write_lease (lease)) + return ISC_R_IOERROR; + } + + /* 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_lease_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *h) +{ + struct lease *lease; + isc_result_t status; + + if (h -> type != dhcp_type_lease) + return ISC_R_INVALIDARG; + lease = (struct lease *)h; + + /* Write out all the values. */ + + status = omapi_connection_put_name (c, "abandoned"); + 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, (lease -> flags & + ABANDONED_LEASE) ? 1 : 0); + 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, (lease -> flags & + BOOTP_LEASE) ? 1 : 0); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "ip-address"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_uint32 (c, lease -> ip_addr.len); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_copyin (c, lease -> ip_addr.iabuf, + lease -> ip_addr.len); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "dhcp-client-identifier"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_uint32 (c, lease -> uid_len); + if (status != ISC_R_SUCCESS) + return status; + if (lease -> uid_len) { + status = omapi_connection_copyin (c, lease -> uid, + lease -> uid_len); + if (status != ISC_R_SUCCESS) + return status; + } + + status = omapi_connection_put_name (c, "hostname"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_string (c, lease -> hostname); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "client-hostname"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_string (c, lease -> client_hostname); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "ddns-fwd-name"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_string (c, lease -> ddns_fwd_name); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "ddns-rev-name"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_string (c, lease -> ddns_rev_name); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "host"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_handle (c, + (omapi_object_t *)lease -> host); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "subnet"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_handle + (c, (omapi_object_t *)lease -> subnet); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "pool"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_handle (c, + (omapi_object_t *)lease -> pool); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "billing-class"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_handle + (c, (omapi_object_t *)lease -> billing_class); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "hardware-address"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_uint32 (c, lease -> hardware_addr.hlen); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_copyin (c, lease -> hardware_addr.haddr, + lease -> hardware_addr.hlen); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "hardware-type"); + 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, lease -> hardware_addr.htype); + 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_lease_lookup (omapi_object_t **lp, + omapi_object_t *id, omapi_object_t *ref) +{ + omapi_value_t *tv = (omapi_value_t *)0; + isc_result_t status; + struct lease *lease; + + /* 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 (lp, tv -> value); + + omapi_value_dereference (&tv, "dhcp_lease_lookup"); + if (status != ISC_R_SUCCESS) + return status; + + /* Don't return the object if the type is wrong. */ + if ((*lp) -> type != dhcp_type_lease) { + omapi_object_dereference (lp, "dhcp_lease_lookup"); + return ISC_R_INVALIDARG; + } + } + + /* Now look for an IP address. */ + status = omapi_get_value_str (ref, id, "handle", &tv); + if (status == ISC_R_SUCCESS) { + /* If we already have a value, flag an error - only one + key can be used for lookups at a time. */ + if (*lp) { + omapi_object_dereference (lp, "dhcp_lease_lookup"); + omapi_value_dereference (&tv, "dhcp_lease_lookup"); + return ISC_R_INVALIDARG; + } + + lease = ((struct lease *) + hash_lookup (lease_ip_addr_hash, + tv -> value -> u.buffer.value, + tv -> value -> u.buffer.len)); + + omapi_value_dereference (&tv, "dhcp_lease_lookup"); + + if (!lease) + return ISC_R_NOTFOUND; + + /* XXX fix so that hash lookup itself creates + XXX the reference. */ + omapi_object_reference (lp, (omapi_object_t *)lease, + "dhcp_lease_lookup"); + } + + /* Now look for a client identifier. */ + status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv); + if (status == ISC_R_SUCCESS) { + if (*lp) { + omapi_object_dereference (lp, "dhcp_lease_lookup"); + omapi_value_dereference (&tv, "dhcp_lease_lookup"); + return ISC_R_INVALIDARG; + } + + lease = ((struct lease *) + hash_lookup (lease_uid_hash, + tv -> value -> u.buffer.value, + tv -> value -> u.buffer.len)); + omapi_value_dereference (&tv, "dhcp_lease_lookup"); + + if (!lease) + return ISC_R_NOTFOUND; + if (lease -> n_uid) + return ISC_R_MULTIPLE; + + /* XXX fix so that hash lookup itself creates + XXX the reference. */ + omapi_object_reference (lp, (omapi_object_t *)lease, + "dhcp_lease_lookup"); + } + + /* Now look for a hardware address. */ + status = omapi_get_value_str (ref, id, "hardware-address", &tv); + if (status == ISC_R_SUCCESS) { + if (*lp) { + omapi_object_dereference (lp, "dhcp_lease_lookup"); + omapi_value_dereference (&tv, "dhcp_lease_lookup"); + return ISC_R_INVALIDARG; + } + + lease = ((struct lease *) + hash_lookup (lease_uid_hash, + tv -> value -> u.buffer.value, + tv -> value -> u.buffer.len)); + omapi_value_dereference (&tv, "dhcp_lease_lookup"); + + if (!lease) + return ISC_R_NOTFOUND; + if (lease -> n_hw) + return ISC_R_MULTIPLE; + + /* XXX fix so that hash lookup itself creates + XXX the reference. */ + omapi_object_reference (lp, (omapi_object_t *)lease, + "dhcp_lease_lookup"); + } + + /* If we get to here without finding a lease, no valid key was + specified. */ + if (!*lp) + return ISC_R_INVALIDARG; + return ISC_R_SUCCESS; +} + +isc_result_t dhcp_lease_create (omapi_object_t **lp, + omapi_object_t *id) +{ + return ISC_R_NOTIMPLEMENTED; +} + +#if 0 +isc_result_t dhcp_group_set_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_typed_data_t *); +isc_result_t dhcp_group_get_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_value_t **); +isc_result_t dhcp_group_destroy (omapi_object_t *, char *); +isc_result_t dhcp_group_signal_handler (omapi_object_t *, char *, va_list); +isc_result_t dhcp_group_stuff_values (omapi_object_t *, + omapi_object_t *, + omapi_object_t *); +isc_result_t dhcp_group_lookup (omapi_object_t **, + omapi_object_t *, omapi_object_t *); +#endif + +isc_result_t dhcp_host_set_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_typed_data_t *value) +{ + struct host_decl *host; + isc_result_t status; + int foo; + + if (h -> type != omapi_type_message) + return ISC_R_INVALIDARG; + host = (struct host_decl *)h; + + /* XXX For now, we can only set these values on new host objects. + XXX Soon, we need to be able to update host objects. */ + if (!omapi_ds_strcmp (name, "name")) { + if (host -> name) + return ISC_R_EXISTS; + if (value -> type == omapi_datatype_data || + value -> type == omapi_datatype_string) { + host -> name = malloc (value -> u.buffer.len + 1); + if (!host -> name) + return ISC_R_NOMEMORY; + memcpy (host -> name, + value -> u.buffer.value, + value -> u.buffer.len); + host -> name [value -> u.buffer.len] = 0; + } else + return ISC_R_INVALIDARG; + return ISC_R_SUCCESS; + } + + if (!omapi_ds_strcmp (name, "hardware-address")) { + if (host -> interface.hlen) + return ISC_R_EXISTS; + if (value -> type == omapi_datatype_data || + value -> type == omapi_datatype_string) { + if (value -> u.buffer.len > + sizeof host -> interface.haddr) + return ISC_R_INVALIDARG; + memcpy (host -> interface.haddr, + value -> u.buffer.value, + value -> u.buffer.len); + host -> interface.hlen = value -> u.buffer.len; + } else + return ISC_R_INVALIDARG; + return ISC_R_SUCCESS; + } + + if (!omapi_ds_strcmp (name, "hardware-type")) { + int type; + if (value -> type == omapi_datatype_data && + value -> u.buffer.len == sizeof type) { + if (value -> u.buffer.len > + sizeof host -> interface.haddr) + return ISC_R_INVALIDARG; + memcpy (&type, + value -> u.buffer.value, + value -> u.buffer.len); + } else if (value -> type == omapi_datatype_int) + type = value -> u.integer; + else + return ISC_R_INVALIDARG; + host -> interface.htype = type; + return ISC_R_SUCCESS; + } + + if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) { + if (host -> client_identifier.data) + return ISC_R_EXISTS; + if (value -> type == omapi_datatype_data || + value -> type == omapi_datatype_string) { + host -> client_identifier.len = value -> u.buffer.len; + if (!buffer_allocate + (&host -> client_identifier.buffer, + host -> client_identifier.len, + "dhcp_host_set_value")) + return ISC_R_NOMEMORY; + host -> client_identifier.data = + &host -> client_identifier.buffer -> data [0]; + memcpy (host -> client_identifier.data, + value -> u.buffer.value, + host -> client_identifier.len); + } else + return ISC_R_INVALIDARG; + return ISC_R_SUCCESS; + } + + if (!omapi_ds_strcmp (name, "ip-address")) { + if (host -> fixed_addr) + return ISC_R_EXISTS; + if (value -> type == omapi_datatype_data || + value -> type == omapi_datatype_string) { + struct data_string ds; + memset (&ds, 0, sizeof ds); + ds.len = value -> u.buffer.len; + if (!buffer_allocate (&ds.buffer, ds.len, + "dhcp_host_set_value")) + return ISC_R_NOMEMORY; + ds.data = (&host -> client_identifier.buffer -> + data [0]); + memcpy (ds.data, value -> u.buffer.value, ds.len); + if (!option_cache (&host -> fixed_addr, + &ds, (struct expression *)0, + (struct option *)0)) { + data_string_forget (&ds, + "dhcp_host_set_value"); + return ISC_R_NOMEMORY; + } + data_string_forget (&ds, "dhcp_host_set_value"); + } 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_host_get_value (omapi_object_t *h, omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + struct host_decl *host; + isc_result_t status; + struct data_string ip_addrs; + + if (h -> type != dhcp_type_host) + return ISC_R_INVALIDARG; + host = (struct host_decl *)h; + + if (!omapi_ds_strcmp (name, "ip-addresses")) { + memset (&ip_addrs, 0, sizeof ip_addrs); + if (host -> fixed_addr && + evaluate_option_cache (&ip_addrs, (struct packet *)0, + (struct lease *)0, + (struct option_state *)0, + (struct option_state *)0, + host -> fixed_addr)) { + status = (omapi_make_const_value + (value, name, ip_addrs.data, ip_addrs.len, + "dhcp_host_get_value")); + data_string_forget (&ip_addrs, "dhcp_host_get_value"); + return status; + } + return ISC_R_NOTFOUND; + } + + if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) { + if (!host -> client_identifier.len) + return ISC_R_NOTFOUND; + return omapi_make_const_value (value, name, + host -> client_identifier.data, + host -> client_identifier.len, + "dhcp_host_get_value"); + } + + if (!omapi_ds_strcmp (name, "name")) + return omapi_make_string_value (value, name, host -> name, + "dhcp_host_get_value"); + + if (!omapi_ds_strcmp (name, "hardware-address")) { + if (!host -> interface.hlen) + return ISC_R_NOTFOUND; + return omapi_make_const_value (value, name, + host -> interface.haddr, + host -> interface.hlen, + "dhcp_host_get_value"); + } + + if (!omapi_ds_strcmp (name, "hardware-type")) { + if (!host -> interface.hlen) + return ISC_R_NOTFOUND; + return omapi_make_int_value (value, name, + host -> interface.htype, + "dhcp_host_get_value"); + } + + /* Try to find some inner object that can take the value. */ + if (h -> inner && h -> inner -> type -> get_value) { + status = ((*(h -> inner -> type -> get_value)) + (h -> inner, id, name, value)); + if (status == ISC_R_SUCCESS) + return status; + } + return ISC_R_NOTFOUND; +} + +isc_result_t dhcp_host_destroy (omapi_object_t *h, char *name) +{ + struct host_decl *host; + isc_result_t status; + + if (h -> type != dhcp_type_host) + return ISC_R_INVALIDARG; + host = (struct host_decl *)h; + + /* Currently, this is completely hopeless - have to complete + reference counting support for server OMAPI objects. */ + + return ISC_R_SUCCESS; +} + +isc_result_t dhcp_host_signal_handler (omapi_object_t *h, + char *name, va_list ap) +{ + struct host_decl *host; + isc_result_t status; + + if (h -> type != dhcp_type_host) + return ISC_R_INVALIDARG; + host = (struct host_decl *)h; + + if (!strcmp (name, "updated")) { + if (!host -> name) { + char hnbuf [64]; + sprintf (hnbuf, "nh%08lx%08x", + cur_time, (u_int32_t)host); + host -> name = malloc (strlen (hnbuf) + 1); + if (!host -> name) + return ISC_R_NOMEMORY; + strcpy (host -> name, hnbuf); + } + enter_host (host, 1); + if (!write_host (host)) + return ISC_R_IOERROR; + } + + /* 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_host_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *h) +{ + struct host_decl *host; + isc_result_t status; + struct data_string ip_addrs; + + if (h -> type != dhcp_type_host) + return ISC_R_INVALIDARG; + host = (struct host_decl *)h; + + /* Write out all the values. */ + + memset (&ip_addrs, 0, sizeof ip_addrs); + if (host -> fixed_addr && + evaluate_option_cache (&ip_addrs, (struct packet *)0, + (struct lease *)0, + (struct option_state *)0, + (struct option_state *)0, + host -> fixed_addr)) { + status = omapi_connection_put_name (c, "ip-address"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_uint32 (c, ip_addrs.len); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_copyin (c, + ip_addrs.data, ip_addrs.len); + if (status != ISC_R_SUCCESS) + return status; + } + + if (host -> client_identifier.len) { + status = omapi_connection_put_name (c, + "dhcp-client-identifier"); + if (status != ISC_R_SUCCESS) + return status; + status = (omapi_connection_put_uint32 + (c, host -> client_identifier.len)); + if (status != ISC_R_SUCCESS) + return status; + } + + status = omapi_connection_put_name (c, "name"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_string (c, host -> name); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "hardware-address"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_uint32 (c, host -> interface.hlen); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_copyin (c, host -> interface.haddr, + host -> interface.hlen); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_connection_put_name (c, "hardware-type"); + 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, host -> interface.htype); + 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_host_lookup (omapi_object_t **lp, + omapi_object_t *id, omapi_object_t *ref) +{ + omapi_value_t *tv = (omapi_value_t *)0; + isc_result_t status; + struct host_decl *host; + + /* 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 (lp, tv -> value); + + omapi_value_dereference (&tv, "dhcp_host_lookup"); + if (status != ISC_R_SUCCESS) + return status; + + /* Don't return the object if the type is wrong. */ + if ((*lp) -> type != dhcp_type_host) { + omapi_object_dereference (lp, "dhcp_host_lookup"); + return ISC_R_INVALIDARG; + } + } + + /* Now look for a client identifier. */ + status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv); + if (status == ISC_R_SUCCESS) { + if (*lp) { + omapi_object_dereference (lp, "dhcp_host_lookup"); + omapi_value_dereference (&tv, "dhcp_host_lookup"); + return ISC_R_INVALIDARG; + } + + host = ((struct host_decl *) + hash_lookup (host_uid_hash, + tv -> value -> u.buffer.value, + tv -> value -> u.buffer.len)); + omapi_value_dereference (&tv, "dhcp_host_lookup"); + + if (!host) + return ISC_R_NOTFOUND; + + /* XXX fix so that hash lookup itself creates + XXX the reference. */ + omapi_object_reference (lp, (omapi_object_t *)host, + "dhcp_host_lookup"); + } + + /* Now look for a hardware address. */ + status = omapi_get_value_str (ref, id, "hardware-address", &tv); + if (status == ISC_R_SUCCESS) { + if (*lp) { + omapi_object_dereference (lp, "dhcp_host_lookup"); + omapi_value_dereference (&tv, "dhcp_host_lookup"); + return ISC_R_INVALIDARG; + } + + host = ((struct host_decl *) + hash_lookup (host_hw_addr_hash, + tv -> value -> u.buffer.value, + tv -> value -> u.buffer.len)); + omapi_value_dereference (&tv, "dhcp_host_lookup"); + + if (!host) + return ISC_R_NOTFOUND; + + /* XXX fix so that hash lookup itself creates + XXX the reference. */ + omapi_object_reference (lp, (omapi_object_t *)host, + "dhcp_host_lookup"); + } + + /* If we get to here without finding a host, no valid key was + specified. */ + if (!*lp) + return ISC_R_INVALIDARG; + return ISC_R_SUCCESS; +} + +isc_result_t dhcp_host_create (omapi_object_t **lp, + omapi_object_t *id) +{ + struct host_decl *hp; + hp = (struct host_decl *)dmalloc (sizeof (struct host_decl), + "dhcp_host_create"); + if (!hp) + return ISC_R_NOMEMORY; + memset (hp, 0, sizeof *hp); + hp -> refcnt = 0; + return omapi_object_reference (lp, (omapi_object_t *)hp, + "dhcp_host_create"); +} + +isc_result_t dhcp_pool_set_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_typed_data_t *value) +{ + struct pool *pool; + isc_result_t status; + int foo; + + if (h -> type != omapi_type_message) + return ISC_R_INVALIDARG; + pool = (struct pool *)h; + + /* No values to set yet. */ + + /* 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_pool_get_value (omapi_object_t *h, omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + struct pool *pool; + isc_result_t status; + + if (h -> type != dhcp_type_pool) + return ISC_R_INVALIDARG; + pool = (struct pool *)h; + + /* No values to get yet. */ + + /* Try to find some inner object that can provide the value. */ + if (h -> inner && h -> inner -> type -> get_value) { + status = ((*(h -> inner -> type -> get_value)) + (h -> inner, id, name, value)); + if (status == ISC_R_SUCCESS) + return status; + } + return ISC_R_NOTFOUND; +} + +isc_result_t dhcp_pool_destroy (omapi_object_t *h, char *name) +{ + struct pool *pool; + isc_result_t status; + + if (h -> type != dhcp_type_pool) + return ISC_R_INVALIDARG; + pool = (struct pool *)h; + + /* Can't destroy pools yet. */ + + return ISC_R_SUCCESS; +} + +isc_result_t dhcp_pool_signal_handler (omapi_object_t *h, + char *name, va_list ap) +{ + struct pool *pool; + isc_result_t status; + + if (h -> type != dhcp_type_pool) + return ISC_R_INVALIDARG; + pool = (struct pool *)h; + + /* Can't write pools yet. */ + + /* 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_pool_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *h) +{ + struct pool *pool; + isc_result_t status; + + if (h -> type != dhcp_type_pool) + return ISC_R_INVALIDARG; + pool = (struct pool *)h; + + /* Can't stuff pool values yet. */ + + /* 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_pool_lookup (omapi_object_t **lp, + omapi_object_t *id, omapi_object_t *ref) +{ + omapi_value_t *tv = (omapi_value_t *)0; + isc_result_t status; + struct pool *pool; + + /* Can't look up pools yet. */ + + /* If we get to here without finding a pool, no valid key was + specified. */ + if (!*lp) + return ISC_R_INVALIDARG; + return ISC_R_SUCCESS; +} + +isc_result_t dhcp_pool_create (omapi_object_t **lp, + omapi_object_t *id) +{ + return ISC_R_NOTIMPLEMENTED; +} +