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