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