Home | History | Annotate | Line # | Download | only in common
      1  1.2  christos /*	$NetBSD: comapi.c,v 1.3 2022/04/03 01:10:58 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /* omapi.c
      4  1.1  christos 
      5  1.1  christos    OMAPI object interfaces for the DHCP server. */
      6  1.1  christos 
      7  1.1  christos /*
      8  1.3  christos  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
      9  1.1  christos  * Copyright (c) 1999-2003 by Internet Software Consortium
     10  1.1  christos  *
     11  1.1  christos  * This Source Code Form is subject to the terms of the Mozilla Public
     12  1.1  christos  * License, v. 2.0. If a copy of the MPL was not distributed with this
     13  1.1  christos  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     14  1.1  christos  *
     15  1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     16  1.1  christos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     17  1.1  christos  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     18  1.1  christos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19  1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     20  1.1  christos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     21  1.1  christos  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22  1.1  christos  *
     23  1.1  christos  *   Internet Systems Consortium, Inc.
     24  1.3  christos  *   PO Box 360
     25  1.3  christos  *   Newmarket, NH 03857 USA
     26  1.1  christos  *   <info (at) isc.org>
     27  1.1  christos  *   https://www.isc.org/
     28  1.1  christos  *
     29  1.1  christos  */
     30  1.1  christos 
     31  1.1  christos #include <sys/cdefs.h>
     32  1.2  christos __RCSID("$NetBSD: comapi.c,v 1.3 2022/04/03 01:10:58 christos Exp $");
     33  1.1  christos 
     34  1.1  christos /* Many, many thanks to Brian Murrell and BCtel for this code - BCtel
     35  1.1  christos    provided the funding that resulted in this code and the entire
     36  1.1  christos    OMAPI support library being written, and Brian helped brainstorm
     37  1.1  christos    and refine the requirements.  To the extent that this code is
     38  1.1  christos    useful, you have Brian and BCtel to thank.  Any limitations in the
     39  1.1  christos    code are a result of mistakes on my part.  -- Ted Lemon */
     40  1.1  christos 
     41  1.1  christos #include "dhcpd.h"
     42  1.1  christos #include <omapip/omapip_p.h>
     43  1.1  christos 
     44  1.1  christos OMAPI_OBJECT_ALLOC (subnet, struct subnet, dhcp_type_subnet)
     45  1.1  christos OMAPI_OBJECT_ALLOC (shared_network, struct shared_network,
     46  1.1  christos 		    dhcp_type_shared_network)
     47  1.1  christos OMAPI_OBJECT_ALLOC (group_object, struct group_object, dhcp_type_group)
     48  1.1  christos OMAPI_OBJECT_ALLOC (dhcp_control, dhcp_control_object_t, dhcp_type_control)
     49  1.1  christos 
     50  1.1  christos omapi_object_type_t *dhcp_type_group;
     51  1.1  christos omapi_object_type_t *dhcp_type_shared_network;
     52  1.1  christos omapi_object_type_t *dhcp_type_subnet;
     53  1.1  christos omapi_object_type_t *dhcp_type_control;
     54  1.1  christos dhcp_control_object_t *dhcp_control_object;
     55  1.1  christos 
     56  1.1  christos void dhcp_common_objects_setup ()
     57  1.1  christos {
     58  1.1  christos 	isc_result_t status;
     59  1.1  christos 
     60  1.1  christos 	status = omapi_object_type_register (&dhcp_type_control,
     61  1.1  christos 					     "control",
     62  1.1  christos 					     dhcp_control_set_value,
     63  1.1  christos 					     dhcp_control_get_value,
     64  1.1  christos 					     dhcp_control_destroy,
     65  1.1  christos 					     dhcp_control_signal_handler,
     66  1.1  christos 					     dhcp_control_stuff_values,
     67  1.3  christos 					     dhcp_control_lookup,
     68  1.1  christos 					     dhcp_control_create,
     69  1.1  christos 					     dhcp_control_remove, 0, 0, 0,
     70  1.1  christos 					     sizeof (dhcp_control_object_t),
     71  1.1  christos 					     0, RC_MISC);
     72  1.1  christos 	if (status != ISC_R_SUCCESS)
     73  1.1  christos 		log_fatal ("Can't register control object type: %s",
     74  1.1  christos 			   isc_result_totext (status));
     75  1.1  christos 	status = dhcp_control_allocate (&dhcp_control_object, MDL);
     76  1.1  christos 	if (status != ISC_R_SUCCESS)
     77  1.1  christos 		log_fatal ("Can't make initial control object: %s",
     78  1.1  christos 			   isc_result_totext (status));
     79  1.1  christos 	dhcp_control_object -> state = server_startup;
     80  1.1  christos 
     81  1.1  christos 	status = omapi_object_type_register (&dhcp_type_group,
     82  1.1  christos 					     "group",
     83  1.1  christos 					     dhcp_group_set_value,
     84  1.1  christos 					     dhcp_group_get_value,
     85  1.1  christos 					     dhcp_group_destroy,
     86  1.1  christos 					     dhcp_group_signal_handler,
     87  1.1  christos 					     dhcp_group_stuff_values,
     88  1.3  christos 					     dhcp_group_lookup,
     89  1.1  christos 					     dhcp_group_create,
     90  1.1  christos 					     dhcp_group_remove, 0, 0, 0,
     91  1.1  christos 					     sizeof (struct group_object), 0,
     92  1.1  christos 					     RC_MISC);
     93  1.1  christos 	if (status != ISC_R_SUCCESS)
     94  1.1  christos 		log_fatal ("Can't register group object type: %s",
     95  1.1  christos 			   isc_result_totext (status));
     96  1.1  christos 
     97  1.1  christos 	status = omapi_object_type_register (&dhcp_type_subnet,
     98  1.1  christos 					     "subnet",
     99  1.1  christos 					     dhcp_subnet_set_value,
    100  1.1  christos 					     dhcp_subnet_get_value,
    101  1.1  christos 					     dhcp_subnet_destroy,
    102  1.1  christos 					     dhcp_subnet_signal_handler,
    103  1.1  christos 					     dhcp_subnet_stuff_values,
    104  1.3  christos 					     dhcp_subnet_lookup,
    105  1.1  christos 					     dhcp_subnet_create,
    106  1.1  christos 					     dhcp_subnet_remove, 0, 0, 0,
    107  1.1  christos 					     sizeof (struct subnet), 0,
    108  1.1  christos 					     RC_MISC);
    109  1.1  christos 	if (status != ISC_R_SUCCESS)
    110  1.1  christos 		log_fatal ("Can't register subnet object type: %s",
    111  1.1  christos 			   isc_result_totext (status));
    112  1.1  christos 
    113  1.1  christos 	status = omapi_object_type_register
    114  1.1  christos 		(&dhcp_type_shared_network,
    115  1.1  christos 		 "shared-network",
    116  1.1  christos 		 dhcp_shared_network_set_value,
    117  1.1  christos 		 dhcp_shared_network_get_value,
    118  1.1  christos 		 dhcp_shared_network_destroy,
    119  1.1  christos 		 dhcp_shared_network_signal_handler,
    120  1.1  christos 		 dhcp_shared_network_stuff_values,
    121  1.3  christos 		 dhcp_shared_network_lookup,
    122  1.1  christos 		 dhcp_shared_network_create,
    123  1.1  christos 		 dhcp_shared_network_remove, 0, 0, 0,
    124  1.1  christos 		 sizeof (struct shared_network), 0, RC_MISC);
    125  1.1  christos 	if (status != ISC_R_SUCCESS)
    126  1.1  christos 		log_fatal ("Can't register shared network object type: %s",
    127  1.1  christos 			   isc_result_totext (status));
    128  1.1  christos 
    129  1.1  christos 	interface_setup ();
    130  1.1  christos }
    131  1.1  christos 
    132  1.1  christos isc_result_t dhcp_group_set_value  (omapi_object_t *h,
    133  1.1  christos 				    omapi_object_t *id,
    134  1.1  christos 				    omapi_data_string_t *name,
    135  1.1  christos 				    omapi_typed_data_t *value)
    136  1.1  christos {
    137  1.1  christos 	struct group_object *group;
    138  1.1  christos 	isc_result_t status;
    139  1.1  christos 
    140  1.1  christos 	if (h -> type != dhcp_type_group)
    141  1.1  christos 		return DHCP_R_INVALIDARG;
    142  1.1  christos 	group = (struct group_object *)h;
    143  1.1  christos 
    144  1.3  christos 	/* XXX For now, we can only set these values on new group objects.
    145  1.1  christos 	   XXX Soon, we need to be able to update group objects. */
    146  1.1  christos 	if (!omapi_ds_strcmp (name, "name")) {
    147  1.1  christos 		if (group -> name)
    148  1.1  christos 			return ISC_R_EXISTS;
    149  1.1  christos 		if (value -> type == omapi_datatype_data ||
    150  1.1  christos 		    value -> type == omapi_datatype_string) {
    151  1.1  christos 			group -> name = dmalloc (value -> u.buffer.len + 1,
    152  1.1  christos 						 MDL);
    153  1.1  christos 			if (!group -> name)
    154  1.1  christos 				return ISC_R_NOMEMORY;
    155  1.1  christos 			memcpy (group -> name,
    156  1.1  christos 				value -> u.buffer.value,
    157  1.1  christos 				value -> u.buffer.len);
    158  1.1  christos 			group -> name [value -> u.buffer.len] = 0;
    159  1.1  christos 		} else
    160  1.1  christos 			return DHCP_R_INVALIDARG;
    161  1.1  christos 		return ISC_R_SUCCESS;
    162  1.1  christos 	}
    163  1.1  christos 
    164  1.1  christos 	if (!omapi_ds_strcmp (name, "statements")) {
    165  1.1  christos 		if (group -> group && group -> group -> statements)
    166  1.1  christos 			return ISC_R_EXISTS;
    167  1.1  christos 		if (!group -> group) {
    168  1.1  christos 			if (!clone_group (&group -> group, root_group, MDL))
    169  1.1  christos 				return ISC_R_NOMEMORY;
    170  1.1  christos 		}
    171  1.1  christos 		if (value -> type == omapi_datatype_data ||
    172  1.1  christos 		    value -> type == omapi_datatype_string) {
    173  1.1  christos 			struct parse *parse;
    174  1.1  christos 			int lose = 0;
    175  1.1  christos 			parse = NULL;
    176  1.1  christos 			status = new_parse(&parse, -1,
    177  1.1  christos 					    (char *) value->u.buffer.value,
    178  1.1  christos 					    value->u.buffer.len,
    179  1.1  christos 					    "network client", 0);
    180  1.1  christos 			if (status != ISC_R_SUCCESS || parse == NULL)
    181  1.1  christos 				return status;
    182  1.1  christos 			if (!(parse_executable_statements
    183  1.1  christos 			      (&group -> group -> statements, parse, &lose,
    184  1.1  christos 			       context_any))) {
    185  1.1  christos 				end_parse (&parse);
    186  1.1  christos 				return DHCP_R_BADPARSE;
    187  1.1  christos 			}
    188  1.1  christos 			end_parse (&parse);
    189  1.1  christos 			return ISC_R_SUCCESS;
    190  1.1  christos 		} else
    191  1.1  christos 			return DHCP_R_INVALIDARG;
    192  1.1  christos 	}
    193  1.1  christos 
    194  1.1  christos 	/* Try to find some inner object that can take the value. */
    195  1.1  christos 	if (h -> inner && h -> inner -> type -> set_value) {
    196  1.1  christos 		status = ((*(h -> inner -> type -> set_value))
    197  1.1  christos 			  (h -> inner, id, name, value));
    198  1.1  christos 		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
    199  1.1  christos 			return status;
    200  1.1  christos 	}
    201  1.3  christos 
    202  1.1  christos 	return ISC_R_NOTFOUND;
    203  1.1  christos }
    204  1.1  christos 
    205  1.1  christos 
    206  1.1  christos isc_result_t dhcp_group_get_value (omapi_object_t *h, omapi_object_t *id,
    207  1.1  christos 				   omapi_data_string_t *name,
    208  1.1  christos 				   omapi_value_t **value)
    209  1.1  christos {
    210  1.1  christos 	struct group_object *group;
    211  1.1  christos 	isc_result_t status;
    212  1.1  christos 
    213  1.1  christos 	if (h -> type != dhcp_type_group)
    214  1.1  christos 		return DHCP_R_INVALIDARG;
    215  1.1  christos 	group = (struct group_object *)h;
    216  1.1  christos 
    217  1.1  christos 	if (!omapi_ds_strcmp (name, "name"))
    218  1.1  christos 		return omapi_make_string_value (value,
    219  1.1  christos 						name, group -> name, MDL);
    220  1.1  christos 
    221  1.1  christos 	/* Try to find some inner object that can take the value. */
    222  1.1  christos 	if (h -> inner && h -> inner -> type -> get_value) {
    223  1.1  christos 		status = ((*(h -> inner -> type -> get_value))
    224  1.1  christos 			  (h -> inner, id, name, value));
    225  1.1  christos 		if (status == ISC_R_SUCCESS)
    226  1.1  christos 			return status;
    227  1.1  christos 	}
    228  1.1  christos 	return ISC_R_NOTFOUND;
    229  1.1  christos }
    230  1.1  christos 
    231  1.1  christos isc_result_t dhcp_group_destroy (omapi_object_t *h, const char *file, int line)
    232  1.1  christos {
    233  1.1  christos 	struct group_object *group, *t;
    234  1.1  christos 
    235  1.1  christos 	if (h -> type != dhcp_type_group)
    236  1.1  christos 		return DHCP_R_INVALIDARG;
    237  1.1  christos 	group = (struct group_object *)h;
    238  1.1  christos 
    239  1.1  christos 	if (group -> name) {
    240  1.1  christos 		if (group_name_hash) {
    241  1.1  christos 			t = (struct group_object *)0;
    242  1.1  christos 			if (group_hash_lookup (&t, group_name_hash,
    243  1.1  christos 					       group -> name,
    244  1.1  christos 					       strlen (group -> name), MDL)) {
    245  1.1  christos 				group_hash_delete (group_name_hash,
    246  1.1  christos 						   group -> name,
    247  1.1  christos 						   strlen (group -> name),
    248  1.1  christos 						   MDL);
    249  1.1  christos 				group_object_dereference (&t, MDL);
    250  1.1  christos 			}
    251  1.1  christos 		}
    252  1.1  christos 		dfree (group -> name, file, line);
    253  1.1  christos 		group -> name = (char *)0;
    254  1.1  christos 	}
    255  1.1  christos 	if (group -> group)
    256  1.1  christos 		group_dereference (&group -> group, MDL);
    257  1.1  christos 
    258  1.1  christos 	return ISC_R_SUCCESS;
    259  1.1  christos }
    260  1.1  christos 
    261  1.1  christos isc_result_t dhcp_group_signal_handler (omapi_object_t *h,
    262  1.1  christos 					const char *name, va_list ap)
    263  1.1  christos {
    264  1.1  christos 	struct group_object *group;
    265  1.1  christos 	isc_result_t status;
    266  1.1  christos 	int updatep = 0;
    267  1.1  christos 
    268  1.1  christos 	if (h -> type != dhcp_type_group)
    269  1.1  christos 		return DHCP_R_INVALIDARG;
    270  1.1  christos 	group = (struct group_object *)h;
    271  1.1  christos 
    272  1.1  christos 	if (!strcmp (name, "updated")) {
    273  1.1  christos 		/* A group object isn't valid if a subgroup hasn't yet been
    274  1.1  christos 		   associated with it. */
    275  1.1  christos 		if (!group -> group)
    276  1.1  christos 			return DHCP_R_INVALIDARG;
    277  1.1  christos 
    278  1.1  christos 		/* Group objects always have to have names. */
    279  1.1  christos 		if (!group -> name) {
    280  1.1  christos 			char hnbuf [64];
    281  1.1  christos 			sprintf (hnbuf, "ng%08lx%08lx",
    282  1.1  christos 				 (unsigned long)cur_time,
    283  1.1  christos 				 (unsigned long)group);
    284  1.1  christos 			group -> name = dmalloc (strlen (hnbuf) + 1, MDL);
    285  1.1  christos 			if (!group -> name)
    286  1.1  christos 				return ISC_R_NOMEMORY;
    287  1.1  christos 			strcpy (group -> name, hnbuf);
    288  1.1  christos 		}
    289  1.1  christos 
    290  1.1  christos 		supersede_group (group, 1);
    291  1.1  christos 		updatep = 1;
    292  1.1  christos 	}
    293  1.1  christos 
    294  1.1  christos 	/* Try to find some inner object that can take the value. */
    295  1.1  christos 	if (h -> inner && h -> inner -> type -> get_value) {
    296  1.1  christos 		status = ((*(h -> inner -> type -> signal_handler))
    297  1.1  christos 			  (h -> inner, name, ap));
    298  1.1  christos 		if (status == ISC_R_SUCCESS)
    299  1.1  christos 			return status;
    300  1.1  christos 	}
    301  1.1  christos 	if (updatep)
    302  1.1  christos 		return ISC_R_SUCCESS;
    303  1.1  christos 	return ISC_R_NOTFOUND;
    304  1.1  christos }
    305  1.1  christos 
    306  1.1  christos isc_result_t dhcp_group_stuff_values (omapi_object_t *c,
    307  1.1  christos 				      omapi_object_t *id,
    308  1.1  christos 				      omapi_object_t *h)
    309  1.1  christos {
    310  1.1  christos 	struct group_object *group;
    311  1.1  christos 	isc_result_t status;
    312  1.1  christos 
    313  1.1  christos 	if (h -> type != dhcp_type_group)
    314  1.1  christos 		return DHCP_R_INVALIDARG;
    315  1.1  christos 	group = (struct group_object *)h;
    316  1.1  christos 
    317  1.1  christos 	/* Write out all the values. */
    318  1.1  christos 	if (group -> name) {
    319  1.1  christos 		status = omapi_connection_put_name (c, "name");
    320  1.1  christos 		if (status != ISC_R_SUCCESS)
    321  1.1  christos 			return status;
    322  1.1  christos 		status = omapi_connection_put_string (c, group -> name);
    323  1.1  christos 		if (status != ISC_R_SUCCESS)
    324  1.1  christos 			return status;
    325  1.1  christos 	}
    326  1.1  christos 
    327  1.1  christos 	/* Write out the inner object, if any. */
    328  1.1  christos 	if (h -> inner && h -> inner -> type -> stuff_values) {
    329  1.1  christos 		status = ((*(h -> inner -> type -> stuff_values))
    330  1.1  christos 			  (c, id, h -> inner));
    331  1.1  christos 		if (status == ISC_R_SUCCESS)
    332  1.1  christos 			return status;
    333  1.1  christos 	}
    334  1.1  christos 
    335  1.1  christos 	return ISC_R_SUCCESS;
    336  1.1  christos }
    337  1.1  christos 
    338  1.1  christos isc_result_t dhcp_group_lookup (omapi_object_t **lp,
    339  1.1  christos 				omapi_object_t *id, omapi_object_t *ref)
    340  1.1  christos {
    341  1.1  christos 	omapi_value_t *tv = (omapi_value_t *)0;
    342  1.1  christos 	isc_result_t status;
    343  1.1  christos 	struct group_object *group;
    344  1.1  christos 
    345  1.1  christos 	if (!ref)
    346  1.1  christos 		return DHCP_R_NOKEYS;
    347  1.1  christos 
    348  1.1  christos 	/* First see if we were sent a handle. */
    349  1.1  christos 	status = omapi_get_value_str (ref, id, "handle", &tv);
    350  1.1  christos 	if (status == ISC_R_SUCCESS) {
    351  1.1  christos 		status = omapi_handle_td_lookup (lp, tv -> value);
    352  1.1  christos 
    353  1.1  christos 		omapi_value_dereference (&tv, MDL);
    354  1.1  christos 		if (status != ISC_R_SUCCESS)
    355  1.1  christos 			return status;
    356  1.1  christos 
    357  1.1  christos 		/* Don't return the object if the type is wrong. */
    358  1.1  christos 		if ((*lp) -> type != dhcp_type_group) {
    359  1.1  christos 			omapi_object_dereference (lp, MDL);
    360  1.1  christos 			return DHCP_R_INVALIDARG;
    361  1.1  christos 		}
    362  1.1  christos 	}
    363  1.1  christos 
    364  1.1  christos 	/* Now look for a name. */
    365  1.1  christos 	status = omapi_get_value_str (ref, id, "name", &tv);
    366  1.1  christos 	if (status == ISC_R_SUCCESS) {
    367  1.1  christos 		group = (struct group_object *)0;
    368  1.1  christos 		if (group_name_hash &&
    369  1.1  christos 		    group_hash_lookup (&group, group_name_hash,
    370  1.1  christos 				       (const char *)
    371  1.1  christos 				       tv -> value -> u.buffer.value,
    372  1.1  christos 				       tv -> value -> u.buffer.len, MDL)) {
    373  1.1  christos 			omapi_value_dereference (&tv, MDL);
    374  1.1  christos 
    375  1.1  christos 			if (*lp && *lp != (omapi_object_t *)group) {
    376  1.1  christos 			    group_object_dereference (&group, MDL);
    377  1.1  christos 			    omapi_object_dereference (lp, MDL);
    378  1.1  christos 			    return DHCP_R_KEYCONFLICT;
    379  1.1  christos 			} else if (!*lp) {
    380  1.1  christos 			    /* XXX fix so that hash lookup itself creates
    381  1.1  christos 			       XXX the reference. */
    382  1.1  christos 			    omapi_object_reference (lp,
    383  1.1  christos 						    (omapi_object_t *)group,
    384  1.1  christos 						    MDL);
    385  1.1  christos 			    group_object_dereference (&group, MDL);
    386  1.1  christos 			}
    387  1.1  christos 		} else if (!*lp)
    388  1.1  christos 			return ISC_R_NOTFOUND;
    389  1.1  christos 	}
    390  1.1  christos 
    391  1.1  christos 	/* If we get to here without finding a group, no valid key was
    392  1.1  christos 	   specified. */
    393  1.1  christos 	if (!*lp)
    394  1.1  christos 		return DHCP_R_NOKEYS;
    395  1.1  christos 
    396  1.1  christos 	if (((struct group_object *)(*lp)) -> flags & GROUP_OBJECT_DELETED) {
    397  1.1  christos 		omapi_object_dereference (lp, MDL);
    398  1.1  christos 		return ISC_R_NOTFOUND;
    399  1.1  christos 	}
    400  1.1  christos 	return ISC_R_SUCCESS;
    401  1.1  christos }
    402  1.1  christos 
    403  1.1  christos isc_result_t dhcp_group_create (omapi_object_t **lp,
    404  1.1  christos 			       omapi_object_t *id)
    405  1.1  christos {
    406  1.1  christos 	struct group_object *group;
    407  1.1  christos 	isc_result_t status;
    408  1.1  christos 	group = (struct group_object *)0;
    409  1.1  christos 
    410  1.1  christos 	status = group_object_allocate (&group, MDL);
    411  1.1  christos 	if (status != ISC_R_SUCCESS)
    412  1.1  christos 		return status;
    413  1.1  christos 	group -> flags = GROUP_OBJECT_DYNAMIC;
    414  1.1  christos 	status = omapi_object_reference (lp, (omapi_object_t *)group, MDL);
    415  1.1  christos 	group_object_dereference (&group, MDL);
    416  1.1  christos 	return status;
    417  1.1  christos }
    418  1.1  christos 
    419  1.1  christos isc_result_t dhcp_group_remove (omapi_object_t *lp,
    420  1.1  christos 				omapi_object_t *id)
    421  1.1  christos {
    422  1.1  christos 	struct group_object *group;
    423  1.1  christos 	isc_result_t status;
    424  1.1  christos 	if (lp -> type != dhcp_type_group)
    425  1.1  christos 		return DHCP_R_INVALIDARG;
    426  1.1  christos 	group = (struct group_object *)lp;
    427  1.1  christos 
    428  1.1  christos 	group -> flags |= GROUP_OBJECT_DELETED;
    429  1.1  christos 	if (group_write_hook) {
    430  1.1  christos 		if (!(*group_write_hook) (group))
    431  1.1  christos 			return ISC_R_IOERROR;
    432  1.1  christos 	}
    433  1.1  christos 
    434  1.1  christos 	status = dhcp_group_destroy ((omapi_object_t *)group, MDL);
    435  1.1  christos 
    436  1.1  christos 	return status;
    437  1.1  christos }
    438  1.1  christos 
    439  1.1  christos isc_result_t dhcp_control_set_value  (omapi_object_t *h,
    440  1.1  christos 				      omapi_object_t *id,
    441  1.1  christos 				      omapi_data_string_t *name,
    442  1.1  christos 				      omapi_typed_data_t *value)
    443  1.1  christos {
    444  1.1  christos 	dhcp_control_object_t *control;
    445  1.1  christos 	isc_result_t status;
    446  1.1  christos 	unsigned long newstate;
    447  1.1  christos 
    448  1.1  christos 	if (h -> type != dhcp_type_control)
    449  1.1  christos 		return DHCP_R_INVALIDARG;
    450  1.1  christos 	control = (dhcp_control_object_t *)h;
    451  1.1  christos 
    452  1.1  christos 	if (!omapi_ds_strcmp (name, "state")) {
    453  1.1  christos 		status = omapi_get_int_value (&newstate, value);
    454  1.1  christos 		if (status != ISC_R_SUCCESS)
    455  1.1  christos 			return status;
    456  1.2  christos 		status = libdhcp_callbacks.dhcp_set_control_state
    457  1.2  christos 				(control -> state, newstate);
    458  1.1  christos 		if (status == ISC_R_SUCCESS)
    459  1.1  christos 			control -> state = value -> u.integer;
    460  1.1  christos 		return status;
    461  1.1  christos 	}
    462  1.1  christos 
    463  1.1  christos 	/* Try to find some inner object that can take the value. */
    464  1.1  christos 	if (h -> inner && h -> inner -> type -> set_value) {
    465  1.1  christos 		status = ((*(h -> inner -> type -> set_value))
    466  1.1  christos 			  (h -> inner, id, name, value));
    467  1.1  christos 		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
    468  1.1  christos 			return status;
    469  1.1  christos 	}
    470  1.3  christos 
    471  1.1  christos 	return ISC_R_NOTFOUND;
    472  1.1  christos }
    473  1.1  christos 
    474  1.1  christos 
    475  1.1  christos isc_result_t dhcp_control_get_value (omapi_object_t *h, omapi_object_t *id,
    476  1.1  christos 				   omapi_data_string_t *name,
    477  1.1  christos 				   omapi_value_t **value)
    478  1.1  christos {
    479  1.1  christos 	dhcp_control_object_t *control;
    480  1.1  christos 	isc_result_t status;
    481  1.1  christos 
    482  1.1  christos 	if (h -> type != dhcp_type_control)
    483  1.1  christos 		return DHCP_R_INVALIDARG;
    484  1.1  christos 	control = (dhcp_control_object_t *)h;
    485  1.1  christos 
    486  1.1  christos 	if (!omapi_ds_strcmp (name, "state"))
    487  1.1  christos 		return omapi_make_int_value (value,
    488  1.1  christos 					     name, (int)control -> state, MDL);
    489  1.1  christos 
    490  1.1  christos 	/* Try to find some inner object that can take the value. */
    491  1.1  christos 	if (h -> inner && h -> inner -> type -> get_value) {
    492  1.1  christos 		status = ((*(h -> inner -> type -> get_value))
    493  1.1  christos 			  (h -> inner, id, name, value));
    494  1.1  christos 		if (status == ISC_R_SUCCESS)
    495  1.1  christos 			return status;
    496  1.1  christos 	}
    497  1.1  christos 	return ISC_R_NOTFOUND;
    498  1.1  christos }
    499  1.1  christos 
    500  1.1  christos isc_result_t dhcp_control_destroy (omapi_object_t *h,
    501  1.1  christos 				   const char *file, int line)
    502  1.1  christos {
    503  1.1  christos 	if (h -> type != dhcp_type_control)
    504  1.1  christos 		return DHCP_R_INVALIDARG;
    505  1.1  christos 
    506  1.1  christos 	/* Can't destroy the control object. */
    507  1.1  christos 	return ISC_R_NOPERM;
    508  1.1  christos }
    509  1.1  christos 
    510  1.1  christos isc_result_t dhcp_control_signal_handler (omapi_object_t *h,
    511  1.1  christos 					const char *name, va_list ap)
    512  1.1  christos {
    513  1.1  christos 	/* In this function h should be a (dhcp_control_object_t *) */
    514  1.1  christos 
    515  1.1  christos 	isc_result_t status;
    516  1.1  christos 
    517  1.1  christos 	if (h -> type != dhcp_type_control)
    518  1.1  christos 		return DHCP_R_INVALIDARG;
    519  1.1  christos 
    520  1.1  christos 	/* Try to find some inner object that can take the value. */
    521  1.1  christos 	if (h -> inner && h -> inner -> type -> get_value) {
    522  1.1  christos 		status = ((*(h -> inner -> type -> signal_handler))
    523  1.1  christos 			  (h -> inner, name, ap));
    524  1.1  christos 		if (status == ISC_R_SUCCESS)
    525  1.1  christos 			return status;
    526  1.1  christos 	}
    527  1.1  christos 	return ISC_R_NOTFOUND;
    528  1.1  christos }
    529  1.1  christos 
    530  1.1  christos isc_result_t dhcp_control_stuff_values (omapi_object_t *c,
    531  1.1  christos 					omapi_object_t *id,
    532  1.1  christos 					omapi_object_t *h)
    533  1.1  christos {
    534  1.1  christos 	dhcp_control_object_t *control;
    535  1.1  christos 	isc_result_t status;
    536  1.1  christos 
    537  1.1  christos 	if (h -> type != dhcp_type_control)
    538  1.1  christos 		return DHCP_R_INVALIDARG;
    539  1.1  christos 	control = (dhcp_control_object_t *)h;
    540  1.1  christos 
    541  1.1  christos 	/* Write out all the values. */
    542  1.1  christos 	status = omapi_connection_put_name (c, "state");
    543  1.1  christos 	if (status != ISC_R_SUCCESS)
    544  1.1  christos 		return status;
    545  1.1  christos 	status = omapi_connection_put_uint32 (c, sizeof (u_int32_t));
    546  1.1  christos 	if (status != ISC_R_SUCCESS)
    547  1.1  christos 		return status;
    548  1.1  christos 	status = omapi_connection_put_uint32 (c, control -> state);
    549  1.1  christos 	if (status != ISC_R_SUCCESS)
    550  1.1  christos 		return status;
    551  1.1  christos 
    552  1.1  christos 	/* Write out the inner object, if any. */
    553  1.1  christos 	if (h -> inner && h -> inner -> type -> stuff_values) {
    554  1.1  christos 		status = ((*(h -> inner -> type -> stuff_values))
    555  1.1  christos 			  (c, id, h -> inner));
    556  1.1  christos 		if (status == ISC_R_SUCCESS)
    557  1.1  christos 			return status;
    558  1.1  christos 	}
    559  1.1  christos 
    560  1.1  christos 	return ISC_R_SUCCESS;
    561  1.1  christos }
    562  1.1  christos 
    563  1.1  christos isc_result_t dhcp_control_lookup (omapi_object_t **lp,
    564  1.1  christos 				  omapi_object_t *id, omapi_object_t *ref)
    565  1.1  christos {
    566  1.1  christos 	omapi_value_t *tv = (omapi_value_t *)0;
    567  1.1  christos 	isc_result_t status;
    568  1.1  christos 
    569  1.1  christos 	/* First see if we were sent a handle. */
    570  1.1  christos 	if (ref) {
    571  1.1  christos 		status = omapi_get_value_str (ref, id, "handle", &tv);
    572  1.1  christos 		if (status == ISC_R_SUCCESS) {
    573  1.1  christos 			status = omapi_handle_td_lookup (lp, tv -> value);
    574  1.1  christos 
    575  1.1  christos 			omapi_value_dereference (&tv, MDL);
    576  1.1  christos 			if (status != ISC_R_SUCCESS)
    577  1.1  christos 				return status;
    578  1.1  christos 
    579  1.1  christos 			/* Don't return the object if the type is wrong. */
    580  1.1  christos 			if ((*lp) -> type != dhcp_type_control) {
    581  1.1  christos 				omapi_object_dereference (lp, MDL);
    582  1.1  christos 				return DHCP_R_INVALIDARG;
    583  1.1  christos 			}
    584  1.1  christos 		}
    585  1.1  christos 	}
    586  1.1  christos 
    587  1.1  christos 	/* Otherwise, stop playing coy - there's only one control object,
    588  1.1  christos 	   so we can just return it. */
    589  1.1  christos 	dhcp_control_reference ((dhcp_control_object_t **)lp,
    590  1.1  christos 				dhcp_control_object, MDL);
    591  1.1  christos 	return ISC_R_SUCCESS;
    592  1.1  christos }
    593  1.1  christos 
    594  1.1  christos isc_result_t dhcp_control_create (omapi_object_t **lp,
    595  1.1  christos 				  omapi_object_t *id)
    596  1.1  christos {
    597  1.1  christos 	/* Can't create a control object - there can be only one. */
    598  1.1  christos 	return ISC_R_NOPERM;
    599  1.1  christos }
    600  1.1  christos 
    601  1.1  christos isc_result_t dhcp_control_remove (omapi_object_t *lp,
    602  1.1  christos 				omapi_object_t *id)
    603  1.1  christos {
    604  1.1  christos 	/* Form is emptiness; emptiness form.   The control object
    605  1.1  christos 	   cannot go out of existance. */
    606  1.1  christos 	return ISC_R_NOPERM;
    607  1.1  christos }
    608  1.1  christos 
    609  1.1  christos isc_result_t dhcp_subnet_set_value  (omapi_object_t *h,
    610  1.1  christos 				     omapi_object_t *id,
    611  1.1  christos 				     omapi_data_string_t *name,
    612  1.1  christos 				     omapi_typed_data_t *value)
    613  1.1  christos {
    614  1.1  christos 	/* In this function h should be a (struct subnet *) */
    615  1.1  christos 
    616  1.1  christos 	isc_result_t status;
    617  1.1  christos 
    618  1.1  christos 	if (h -> type != dhcp_type_subnet)
    619  1.1  christos 		return DHCP_R_INVALIDARG;
    620  1.1  christos 
    621  1.1  christos 	/* No values to set yet. */
    622  1.1  christos 
    623  1.1  christos 	/* Try to find some inner object that can take the value. */
    624  1.1  christos 	if (h -> inner && h -> inner -> type -> set_value) {
    625  1.1  christos 		status = ((*(h -> inner -> type -> set_value))
    626  1.1  christos 			  (h -> inner, id, name, value));
    627  1.1  christos 		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
    628  1.1  christos 			return status;
    629  1.1  christos 	}
    630  1.1  christos 
    631  1.1  christos 	return ISC_R_NOTFOUND;
    632  1.1  christos }
    633  1.1  christos 
    634  1.1  christos 
    635  1.1  christos isc_result_t dhcp_subnet_get_value (omapi_object_t *h, omapi_object_t *id,
    636  1.1  christos 				    omapi_data_string_t *name,
    637  1.1  christos 				    omapi_value_t **value)
    638  1.1  christos {
    639  1.1  christos 	/* In this function h should be a (struct subnet *) */
    640  1.1  christos 
    641  1.1  christos 	isc_result_t status;
    642  1.1  christos 
    643  1.1  christos 	if (h -> type != dhcp_type_subnet)
    644  1.1  christos 		return DHCP_R_INVALIDARG;
    645  1.1  christos 
    646  1.1  christos 	/* No values to get yet. */
    647  1.1  christos 
    648  1.1  christos 	/* Try to find some inner object that can provide the value. */
    649  1.1  christos 	if (h -> inner && h -> inner -> type -> get_value) {
    650  1.1  christos 		status = ((*(h -> inner -> type -> get_value))
    651  1.1  christos 			  (h -> inner, id, name, value));
    652  1.1  christos 		if (status == ISC_R_SUCCESS)
    653  1.1  christos 			return status;
    654  1.1  christos 	}
    655  1.1  christos 	return ISC_R_NOTFOUND;
    656  1.1  christos }
    657  1.1  christos 
    658  1.1  christos isc_result_t dhcp_subnet_destroy (omapi_object_t *h, const char *file, int line)
    659  1.1  christos {
    660  1.1  christos 	struct subnet *subnet;
    661  1.1  christos 
    662  1.1  christos 	if (h -> type != dhcp_type_subnet)
    663  1.1  christos 		return DHCP_R_INVALIDARG;
    664  1.1  christos 
    665  1.1  christos 	subnet = (struct subnet *)h;
    666  1.1  christos 	if (subnet -> next_subnet)
    667  1.1  christos 		subnet_dereference (&subnet -> next_subnet, file, line);
    668  1.1  christos 	if (subnet -> next_sibling)
    669  1.1  christos 		subnet_dereference (&subnet -> next_sibling, file, line);
    670  1.1  christos 	if (subnet -> shared_network)
    671  1.1  christos 		shared_network_dereference (&subnet -> shared_network,
    672  1.1  christos 					    file, line);
    673  1.1  christos 	if (subnet -> interface)
    674  1.1  christos 		interface_dereference (&subnet -> interface, file, line);
    675  1.1  christos 	if (subnet -> group)
    676  1.1  christos 		group_dereference (&subnet -> group, file, line);
    677  1.1  christos 
    678  1.1  christos 	return ISC_R_SUCCESS;
    679  1.1  christos }
    680  1.1  christos 
    681  1.1  christos isc_result_t dhcp_subnet_signal_handler (omapi_object_t *h,
    682  1.1  christos 					 const char *name, va_list ap)
    683  1.1  christos {
    684  1.1  christos 	/* In this function h should be a (struct subnet *) */
    685  1.1  christos 
    686  1.1  christos 	isc_result_t status;
    687  1.1  christos 
    688  1.1  christos 	if (h -> type != dhcp_type_subnet)
    689  1.1  christos 		return DHCP_R_INVALIDARG;
    690  1.1  christos 
    691  1.1  christos 	/* Can't write subnets yet. */
    692  1.1  christos 
    693  1.1  christos 	/* Try to find some inner object that can take the value. */
    694  1.1  christos 	if (h -> inner && h -> inner -> type -> get_value) {
    695  1.1  christos 		status = ((*(h -> inner -> type -> signal_handler))
    696  1.1  christos 			  (h -> inner, name, ap));
    697  1.1  christos 		if (status == ISC_R_SUCCESS)
    698  1.1  christos 			return status;
    699  1.1  christos 	}
    700  1.1  christos 
    701  1.1  christos 	return ISC_R_NOTFOUND;
    702  1.1  christos }
    703  1.1  christos 
    704  1.1  christos isc_result_t dhcp_subnet_stuff_values (omapi_object_t *c,
    705  1.1  christos 				       omapi_object_t *id,
    706  1.1  christos 				       omapi_object_t *h)
    707  1.1  christos {
    708  1.1  christos 	/* In this function h should be a (struct subnet *) */
    709  1.1  christos 
    710  1.1  christos 	isc_result_t status;
    711  1.1  christos 
    712  1.1  christos 	if (h -> type != dhcp_type_subnet)
    713  1.1  christos 		return DHCP_R_INVALIDARG;
    714  1.1  christos 
    715  1.1  christos 	/* Can't stuff subnet values yet. */
    716  1.1  christos 
    717  1.1  christos 	/* Write out the inner object, if any. */
    718  1.1  christos 	if (h -> inner && h -> inner -> type -> stuff_values) {
    719  1.1  christos 		status = ((*(h -> inner -> type -> stuff_values))
    720  1.1  christos 			  (c, id, h -> inner));
    721  1.1  christos 		if (status == ISC_R_SUCCESS)
    722  1.1  christos 			return status;
    723  1.1  christos 	}
    724  1.1  christos 
    725  1.1  christos 	return ISC_R_SUCCESS;
    726  1.1  christos }
    727  1.1  christos 
    728  1.1  christos isc_result_t dhcp_subnet_lookup (omapi_object_t **lp,
    729  1.1  christos 				 omapi_object_t *id,
    730  1.1  christos 				 omapi_object_t *ref)
    731  1.1  christos {
    732  1.1  christos 	/* Can't look up subnets yet. */
    733  1.1  christos 
    734  1.1  christos 	/* If we get to here without finding a subnet, no valid key was
    735  1.1  christos 	   specified. */
    736  1.1  christos 	if (!*lp)
    737  1.1  christos 		return DHCP_R_NOKEYS;
    738  1.1  christos 	return ISC_R_SUCCESS;
    739  1.1  christos }
    740  1.1  christos 
    741  1.1  christos isc_result_t dhcp_subnet_create (omapi_object_t **lp,
    742  1.1  christos 				 omapi_object_t *id)
    743  1.1  christos {
    744  1.1  christos 	return ISC_R_NOTIMPLEMENTED;
    745  1.1  christos }
    746  1.1  christos 
    747  1.1  christos isc_result_t dhcp_subnet_remove (omapi_object_t *lp,
    748  1.1  christos 			       omapi_object_t *id)
    749  1.1  christos {
    750  1.1  christos 	return ISC_R_NOTIMPLEMENTED;
    751  1.1  christos }
    752  1.1  christos 
    753  1.1  christos isc_result_t dhcp_shared_network_set_value  (omapi_object_t *h,
    754  1.1  christos 					     omapi_object_t *id,
    755  1.1  christos 					     omapi_data_string_t *name,
    756  1.1  christos 					     omapi_typed_data_t *value)
    757  1.1  christos {
    758  1.1  christos 	/* In this function h should be a (struct shared_network *) */
    759  1.1  christos 
    760  1.1  christos 	isc_result_t status;
    761  1.1  christos 
    762  1.1  christos 	if (h -> type != dhcp_type_shared_network)
    763  1.1  christos 		return DHCP_R_INVALIDARG;
    764  1.1  christos 
    765  1.1  christos 	/* No values to set yet. */
    766  1.1  christos 
    767  1.1  christos 	/* Try to find some inner object that can take the value. */
    768  1.1  christos 	if (h -> inner && h -> inner -> type -> set_value) {
    769  1.1  christos 		status = ((*(h -> inner -> type -> set_value))
    770  1.1  christos 			  (h -> inner, id, name, value));
    771  1.1  christos 		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
    772  1.1  christos 			return status;
    773  1.1  christos 	}
    774  1.1  christos 
    775  1.1  christos 	return ISC_R_NOTFOUND;
    776  1.1  christos }
    777  1.1  christos 
    778  1.1  christos 
    779  1.1  christos isc_result_t dhcp_shared_network_get_value (omapi_object_t *h,
    780  1.1  christos 					    omapi_object_t *id,
    781  1.1  christos 					    omapi_data_string_t *name,
    782  1.1  christos 					    omapi_value_t **value)
    783  1.1  christos {
    784  1.1  christos 	/* In this function h should be a (struct shared_network *) */
    785  1.1  christos 
    786  1.1  christos 	isc_result_t status;
    787  1.1  christos 
    788  1.1  christos 	if (h -> type != dhcp_type_shared_network)
    789  1.1  christos 		return DHCP_R_INVALIDARG;
    790  1.1  christos 
    791  1.1  christos 	/* No values to get yet. */
    792  1.1  christos 
    793  1.1  christos 	/* Try to find some inner object that can provide the value. */
    794  1.1  christos 	if (h -> inner && h -> inner -> type -> get_value) {
    795  1.1  christos 		status = ((*(h -> inner -> type -> get_value))
    796  1.1  christos 			  (h -> inner, id, name, value));
    797  1.1  christos 		if (status == ISC_R_SUCCESS)
    798  1.1  christos 			return status;
    799  1.1  christos 	}
    800  1.1  christos 	return ISC_R_NOTFOUND;
    801  1.1  christos }
    802  1.1  christos 
    803  1.1  christos isc_result_t dhcp_shared_network_destroy (omapi_object_t *h,
    804  1.1  christos 					  const char *file, int line)
    805  1.1  christos {
    806  1.1  christos 	/* In this function h should be a (struct shared_network *) */
    807  1.1  christos 
    808  1.1  christos 	struct shared_network *shared_network;
    809  1.1  christos 
    810  1.1  christos 	if (h -> type != dhcp_type_shared_network)
    811  1.1  christos 		return DHCP_R_INVALIDARG;
    812  1.1  christos 
    813  1.1  christos 	shared_network = (struct shared_network *)h;
    814  1.1  christos 	if (shared_network -> next)
    815  1.1  christos 		shared_network_dereference (&shared_network -> next,
    816  1.1  christos 					    file, line);
    817  1.1  christos 	if (shared_network -> name) {
    818  1.1  christos 		dfree (shared_network -> name, file, line);
    819  1.1  christos 		shared_network -> name = 0;
    820  1.1  christos 	}
    821  1.1  christos 	if (shared_network -> subnets)
    822  1.1  christos 		subnet_dereference (&shared_network -> subnets, file, line);
    823  1.1  christos 	if (shared_network -> interface)
    824  1.1  christos 		interface_dereference (&shared_network -> interface,
    825  1.1  christos 				       file, line);
    826  1.1  christos 	if (shared_network -> pools)
    827  1.1  christos 	    omapi_object_dereference ((omapi_object_t **)
    828  1.1  christos 				      &shared_network -> pools, file, line);
    829  1.1  christos 	if (shared_network -> group)
    830  1.1  christos 		group_dereference (&shared_network -> group, file, line);
    831  1.1  christos #if defined (FAILOVER_PROTOCOL)
    832  1.1  christos 	if (shared_network -> failover_peer)
    833  1.1  christos 	    omapi_object_dereference ((omapi_object_t **)
    834  1.1  christos 				      &shared_network -> failover_peer,
    835  1.1  christos 				      file, line);
    836  1.1  christos #endif
    837  1.1  christos 
    838  1.1  christos 	return ISC_R_SUCCESS;
    839  1.1  christos }
    840  1.1  christos 
    841  1.1  christos isc_result_t dhcp_shared_network_signal_handler (omapi_object_t *h,
    842  1.1  christos 						 const char *name,
    843  1.1  christos 						 va_list ap)
    844  1.1  christos {
    845  1.1  christos 	/* In this function h should be a (struct shared_network *) */
    846  1.1  christos 
    847  1.1  christos 	isc_result_t status;
    848  1.1  christos 
    849  1.1  christos 	if (h -> type != dhcp_type_shared_network)
    850  1.1  christos 		return DHCP_R_INVALIDARG;
    851  1.1  christos 
    852  1.1  christos 	/* Can't write shared_networks yet. */
    853  1.1  christos 
    854  1.1  christos 	/* Try to find some inner object that can take the value. */
    855  1.1  christos 	if (h -> inner && h -> inner -> type -> get_value) {
    856  1.1  christos 		status = ((*(h -> inner -> type -> signal_handler))
    857  1.1  christos 			  (h -> inner, name, ap));
    858  1.1  christos 		if (status == ISC_R_SUCCESS)
    859  1.1  christos 			return status;
    860  1.1  christos 	}
    861  1.1  christos 
    862  1.1  christos 	return ISC_R_NOTFOUND;
    863  1.1  christos }
    864  1.1  christos 
    865  1.1  christos isc_result_t dhcp_shared_network_stuff_values (omapi_object_t *c,
    866  1.1  christos 					       omapi_object_t *id,
    867  1.1  christos 					       omapi_object_t *h)
    868  1.1  christos {
    869  1.1  christos 	/* In this function h should be a (struct shared_network *) */
    870  1.1  christos 
    871  1.1  christos 	isc_result_t status;
    872  1.1  christos 
    873  1.1  christos 	if (h -> type != dhcp_type_shared_network)
    874  1.1  christos 		return DHCP_R_INVALIDARG;
    875  1.1  christos 
    876  1.1  christos 	/* Can't stuff shared_network values yet. */
    877  1.1  christos 
    878  1.1  christos 	/* Write out the inner object, if any. */
    879  1.1  christos 	if (h -> inner && h -> inner -> type -> stuff_values) {
    880  1.1  christos 		status = ((*(h -> inner -> type -> stuff_values))
    881  1.1  christos 			  (c, id, h -> inner));
    882  1.1  christos 		if (status == ISC_R_SUCCESS)
    883  1.1  christos 			return status;
    884  1.1  christos 	}
    885  1.1  christos 
    886  1.1  christos 	return ISC_R_SUCCESS;
    887  1.1  christos }
    888  1.1  christos 
    889  1.1  christos isc_result_t dhcp_shared_network_lookup (omapi_object_t **lp,
    890  1.1  christos 					 omapi_object_t *id,
    891  1.1  christos 					 omapi_object_t *ref)
    892  1.1  christos {
    893  1.1  christos 	/* Can't look up shared_networks yet. */
    894  1.1  christos 
    895  1.1  christos 	/* If we get to here without finding a shared_network, no valid key was
    896  1.1  christos 	   specified. */
    897  1.1  christos 	if (!*lp)
    898  1.1  christos 		return DHCP_R_NOKEYS;
    899  1.1  christos 	return ISC_R_SUCCESS;
    900  1.1  christos }
    901  1.1  christos 
    902  1.1  christos isc_result_t dhcp_shared_network_create (omapi_object_t **lp,
    903  1.1  christos 					 omapi_object_t *id)
    904  1.1  christos {
    905  1.1  christos 	return ISC_R_NOTIMPLEMENTED;
    906  1.1  christos }
    907  1.1  christos 
    908  1.1  christos isc_result_t dhcp_shared_network_remove (omapi_object_t *lp,
    909  1.1  christos 					 omapi_object_t *id)
    910  1.1  christos {
    911  1.1  christos 	return ISC_R_NOTIMPLEMENTED;
    912  1.1  christos }
    913