Flesh out BUF_CMD_FLUSH support.
[dragonfly.git] / contrib / dhcp-3.0 / common / comapi.c
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
43 static char copyright[] =
44 "$Id: comapi.c,v 1.9.2.7 2004/06/10 17:59:14 dhankins 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
50 OMAPI_OBJECT_ALLOC (subnet, struct subnet, dhcp_type_subnet)
51 OMAPI_OBJECT_ALLOC (shared_network, struct shared_network,
52                     dhcp_type_shared_network)
53 OMAPI_OBJECT_ALLOC (group_object, struct group_object, dhcp_type_group)
54 OMAPI_OBJECT_ALLOC (dhcp_control, dhcp_control_object_t, dhcp_type_control)
55
56 omapi_object_type_t *dhcp_type_interface;
57 omapi_object_type_t *dhcp_type_group;
58 omapi_object_type_t *dhcp_type_shared_network;
59 omapi_object_type_t *dhcp_type_subnet;
60 omapi_object_type_t *dhcp_type_control;
61 dhcp_control_object_t *dhcp_control_object;
62
63 void 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
139 isc_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         int foo;
147
148         if (h -> type != dhcp_type_group)
149                 return ISC_R_INVALIDARG;
150         group = (struct group_object *)h;
151
152         /* XXX For now, we can only set these values on new group objects. 
153            XXX Soon, we need to be able to update group objects. */
154         if (!omapi_ds_strcmp (name, "name")) {
155                 if (group -> name)
156                         return ISC_R_EXISTS;
157                 if (value -> type == omapi_datatype_data ||
158                     value -> type == omapi_datatype_string) {
159                         group -> name = dmalloc (value -> u.buffer.len + 1,
160                                                  MDL);
161                         if (!group -> name)
162                                 return ISC_R_NOMEMORY;
163                         memcpy (group -> name,
164                                 value -> u.buffer.value,
165                                 value -> u.buffer.len);
166                         group -> name [value -> u.buffer.len] = 0;
167                 } else
168                         return ISC_R_INVALIDARG;
169                 return ISC_R_SUCCESS;
170         }
171
172         if (!omapi_ds_strcmp (name, "statements")) {
173                 if (group -> group && group -> group -> statements)
174                         return ISC_R_EXISTS;
175                 if (!group -> group) {
176                         if (!clone_group (&group -> group, root_group, MDL))
177                                 return ISC_R_NOMEMORY;
178                 }
179                 if (value -> type == omapi_datatype_data ||
180                     value -> type == omapi_datatype_string) {
181                         struct parse *parse;
182                         int lose = 0;
183                         parse = (struct parse *)0;
184                         status = new_parse (&parse, -1,
185                                             (char *)value -> u.buffer.value,
186                                             value -> u.buffer.len,
187                                             "network client", 0);
188                         if (status != ISC_R_SUCCESS)
189                                 return status;
190                         if (!(parse_executable_statements
191                               (&group -> group -> statements, parse, &lose,
192                                context_any))) {
193                                 end_parse (&parse);
194                                 return ISC_R_BADPARSE;
195                         }
196                         end_parse (&parse);
197                         return ISC_R_SUCCESS;
198                 } else
199                         return ISC_R_INVALIDARG;
200         }
201
202         /* Try to find some inner object that can take the value. */
203         if (h -> inner && h -> inner -> type -> set_value) {
204                 status = ((*(h -> inner -> type -> set_value))
205                           (h -> inner, id, name, value));
206                 if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
207                         return status;
208         }
209                           
210         return ISC_R_NOTFOUND;
211 }
212
213
214 isc_result_t dhcp_group_get_value (omapi_object_t *h, omapi_object_t *id,
215                                    omapi_data_string_t *name,
216                                    omapi_value_t **value)
217 {
218         struct group_object *group;
219         isc_result_t status;
220         struct data_string ip_addrs;
221
222         if (h -> type != dhcp_type_group)
223                 return ISC_R_INVALIDARG;
224         group = (struct group_object *)h;
225
226         if (!omapi_ds_strcmp (name, "name"))
227                 return omapi_make_string_value (value,
228                                                 name, group -> name, MDL);
229
230         /* Try to find some inner object that can take the value. */
231         if (h -> inner && h -> inner -> type -> get_value) {
232                 status = ((*(h -> inner -> type -> get_value))
233                           (h -> inner, id, name, value));
234                 if (status == ISC_R_SUCCESS)
235                         return status;
236         }
237         return ISC_R_NOTFOUND;
238 }
239
240 isc_result_t dhcp_group_destroy (omapi_object_t *h, const char *file, int line)
241 {
242         struct group_object *group, *t;
243         isc_result_t status;
244
245         if (h -> type != dhcp_type_group)
246                 return ISC_R_INVALIDARG;
247         group = (struct group_object *)h;
248
249         if (group -> name) {
250                 if (group_name_hash) {
251                         t = (struct group_object *)0;
252                         if (group_hash_lookup (&t, group_name_hash,
253                                                group -> name,
254                                                strlen (group -> name), MDL)) {
255                                 group_hash_delete (group_name_hash,
256                                                    group -> name,
257                                                    strlen (group -> name),
258                                                    MDL);
259                                 group_object_dereference (&t, MDL);
260                         }
261                 }
262                 dfree (group -> name, file, line);
263                 group -> name = (char *)0;
264         }
265         if (group -> group)
266                 group_dereference (&group -> group, MDL);
267
268         return ISC_R_SUCCESS;
269 }
270
271 isc_result_t dhcp_group_signal_handler (omapi_object_t *h,
272                                         const char *name, va_list ap)
273 {
274         struct group_object *group, *t;
275         isc_result_t status;
276         int updatep = 0;
277
278         if (h -> type != dhcp_type_group)
279                 return ISC_R_INVALIDARG;
280         group = (struct group_object *)h;
281
282         if (!strcmp (name, "updated")) {
283                 /* A group object isn't valid if a subgroup hasn't yet been
284                    associated with it. */
285                 if (!group -> group)
286                         return ISC_R_INVALIDARG;
287
288                 /* Group objects always have to have names. */
289                 if (!group -> name) {
290                         char hnbuf [64];
291                         sprintf (hnbuf, "ng%08lx%08lx",
292                                  (unsigned long)cur_time,
293                                  (unsigned long)group);
294                         group -> name = dmalloc (strlen (hnbuf) + 1, MDL);
295                         if (!group -> name)
296                                 return ISC_R_NOMEMORY;
297                         strcpy (group -> name, hnbuf);
298                 }
299
300                 supersede_group (group, 1);
301                 updatep = 1;
302         }
303
304         /* Try to find some inner object that can take the value. */
305         if (h -> inner && h -> inner -> type -> get_value) {
306                 status = ((*(h -> inner -> type -> signal_handler))
307                           (h -> inner, name, ap));
308                 if (status == ISC_R_SUCCESS)
309                         return status;
310         }
311         if (updatep)
312                 return ISC_R_SUCCESS;
313         return ISC_R_NOTFOUND;
314 }
315
316 isc_result_t dhcp_group_stuff_values (omapi_object_t *c,
317                                       omapi_object_t *id,
318                                       omapi_object_t *h)
319 {
320         struct group_object *group;
321         isc_result_t status;
322
323         if (h -> type != dhcp_type_group)
324                 return ISC_R_INVALIDARG;
325         group = (struct group_object *)h;
326
327         /* Write out all the values. */
328         if (group -> name) {
329                 status = omapi_connection_put_name (c, "name");
330                 if (status != ISC_R_SUCCESS)
331                         return status;
332                 status = omapi_connection_put_string (c, group -> name);
333                 if (status != ISC_R_SUCCESS)
334                         return status;
335         }
336
337         /* Write out the inner object, if any. */
338         if (h -> inner && h -> inner -> type -> stuff_values) {
339                 status = ((*(h -> inner -> type -> stuff_values))
340                           (c, id, h -> inner));
341                 if (status == ISC_R_SUCCESS)
342                         return status;
343         }
344
345         return ISC_R_SUCCESS;
346 }
347
348 isc_result_t dhcp_group_lookup (omapi_object_t **lp,
349                                 omapi_object_t *id, omapi_object_t *ref)
350 {
351         omapi_value_t *tv = (omapi_value_t *)0;
352         isc_result_t status;
353         struct group_object *group;
354
355         if (!ref)
356                 return ISC_R_NOKEYS;
357
358         /* First see if we were sent a handle. */
359         status = omapi_get_value_str (ref, id, "handle", &tv);
360         if (status == ISC_R_SUCCESS) {
361                 status = omapi_handle_td_lookup (lp, tv -> value);
362
363                 omapi_value_dereference (&tv, MDL);
364                 if (status != ISC_R_SUCCESS)
365                         return status;
366
367                 /* Don't return the object if the type is wrong. */
368                 if ((*lp) -> type != dhcp_type_group) {
369                         omapi_object_dereference (lp, MDL);
370                         return ISC_R_INVALIDARG;
371                 }
372         }
373
374         /* Now look for a name. */
375         status = omapi_get_value_str (ref, id, "name", &tv);
376         if (status == ISC_R_SUCCESS) {
377                 group = (struct group_object *)0;
378                 if (group_name_hash &&
379                     group_hash_lookup (&group, group_name_hash,
380                                        (const char *)
381                                        tv -> value -> u.buffer.value,
382                                        tv -> value -> u.buffer.len, MDL)) {
383                         omapi_value_dereference (&tv, MDL);
384
385                         if (*lp && *lp != (omapi_object_t *)group) {
386                             group_object_dereference (&group, MDL);
387                             omapi_object_dereference (lp, MDL);
388                             return ISC_R_KEYCONFLICT;
389                         } else if (!*lp) {
390                             /* XXX fix so that hash lookup itself creates
391                                XXX the reference. */
392                             omapi_object_reference (lp,
393                                                     (omapi_object_t *)group,
394                                                     MDL);
395                             group_object_dereference (&group, MDL);
396                         }
397                 } else if (!*lp)
398                         return ISC_R_NOTFOUND;
399         }
400
401         /* If we get to here without finding a group, no valid key was
402            specified. */
403         if (!*lp)
404                 return ISC_R_NOKEYS;
405
406         if (((struct group_object *)(*lp)) -> flags & GROUP_OBJECT_DELETED) {
407                 omapi_object_dereference (lp, MDL);
408                 return ISC_R_NOTFOUND;
409         }
410         return ISC_R_SUCCESS;
411 }
412
413 isc_result_t dhcp_group_create (omapi_object_t **lp,
414                                omapi_object_t *id)
415 {
416         struct group_object *group;
417         isc_result_t status;
418         group = (struct group_object *)0;
419
420         status = group_object_allocate (&group, MDL);
421         if (status != ISC_R_SUCCESS)
422                 return status;
423         group -> flags = GROUP_OBJECT_DYNAMIC;
424         status = omapi_object_reference (lp, (omapi_object_t *)group, MDL);
425         group_object_dereference (&group, MDL);
426         return status;
427 }
428
429 isc_result_t dhcp_group_remove (omapi_object_t *lp,
430                                 omapi_object_t *id)
431 {
432         struct group_object *group;
433         isc_result_t status;
434         if (lp -> type != dhcp_type_group)
435                 return ISC_R_INVALIDARG;
436         group = (struct group_object *)lp;
437
438         group -> flags |= GROUP_OBJECT_DELETED;
439         if (group_write_hook) {
440                 if (!(*group_write_hook) (group))
441                         return ISC_R_IOERROR;
442         }
443
444         status = dhcp_group_destroy ((omapi_object_t *)group, MDL);
445
446         return ISC_R_SUCCESS;
447 }
448
449 isc_result_t dhcp_control_set_value  (omapi_object_t *h,
450                                       omapi_object_t *id,
451                                       omapi_data_string_t *name,
452                                       omapi_typed_data_t *value)
453 {
454         dhcp_control_object_t *control;
455         isc_result_t status;
456         int foo;
457         unsigned long newstate;
458
459         if (h -> type != dhcp_type_control)
460                 return ISC_R_INVALIDARG;
461         control = (dhcp_control_object_t *)h;
462
463         if (!omapi_ds_strcmp (name, "state")) {
464                 status = omapi_get_int_value (&newstate, value);
465                 if (status != ISC_R_SUCCESS)
466                         return status;
467                 status = dhcp_set_control_state (control -> state, newstate);
468                 if (status == ISC_R_SUCCESS)
469                         control -> state = value -> u.integer;
470                 return status;
471         }
472
473         /* Try to find some inner object that can take the value. */
474         if (h -> inner && h -> inner -> type -> set_value) {
475                 status = ((*(h -> inner -> type -> set_value))
476                           (h -> inner, id, name, value));
477                 if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
478                         return status;
479         }
480                           
481         return ISC_R_NOTFOUND;
482 }
483
484
485 isc_result_t dhcp_control_get_value (omapi_object_t *h, omapi_object_t *id,
486                                    omapi_data_string_t *name,
487                                    omapi_value_t **value)
488 {
489         dhcp_control_object_t *control;
490         isc_result_t status;
491         struct data_string ip_addrs;
492
493         if (h -> type != dhcp_type_control)
494                 return ISC_R_INVALIDARG;
495         control = (dhcp_control_object_t *)h;
496
497         if (!omapi_ds_strcmp (name, "state"))
498                 return omapi_make_int_value (value,
499                                              name, (int)control -> state, MDL);
500
501         /* Try to find some inner object that can take the value. */
502         if (h -> inner && h -> inner -> type -> get_value) {
503                 status = ((*(h -> inner -> type -> get_value))
504                           (h -> inner, id, name, value));
505                 if (status == ISC_R_SUCCESS)
506                         return status;
507         }
508         return ISC_R_NOTFOUND;
509 }
510
511 isc_result_t dhcp_control_destroy (omapi_object_t *h,
512                                    const char *file, int line)
513 {
514         dhcp_control_object_t *control, *t;
515         isc_result_t status;
516
517         if (h -> type != dhcp_type_control)
518                 return ISC_R_INVALIDARG;
519
520         /* Can't destroy the control object. */
521         return ISC_R_NOPERM;
522 }
523
524 isc_result_t dhcp_control_signal_handler (omapi_object_t *h,
525                                         const char *name, va_list ap)
526 {
527         dhcp_control_object_t *control, *t;
528         isc_result_t status;
529         int updatep = 0;
530
531         if (h -> type != dhcp_type_control)
532                 return ISC_R_INVALIDARG;
533         control = (dhcp_control_object_t *)h;
534
535         /* Try to find some inner object that can take the value. */
536         if (h -> inner && h -> inner -> type -> get_value) {
537                 status = ((*(h -> inner -> type -> signal_handler))
538                           (h -> inner, name, ap));
539                 if (status == ISC_R_SUCCESS)
540                         return status;
541         }
542         return ISC_R_NOTFOUND;
543 }
544
545 isc_result_t dhcp_control_stuff_values (omapi_object_t *c,
546                                         omapi_object_t *id,
547                                         omapi_object_t *h)
548 {
549         dhcp_control_object_t *control;
550         isc_result_t status;
551
552         if (h -> type != dhcp_type_control)
553                 return ISC_R_INVALIDARG;
554         control = (dhcp_control_object_t *)h;
555
556         /* Write out all the values. */
557         status = omapi_connection_put_name (c, "state");
558         if (status != ISC_R_SUCCESS)
559                 return status;
560         status = omapi_connection_put_uint32 (c, sizeof (u_int32_t));
561         if (status != ISC_R_SUCCESS)
562                 return status;
563         status = omapi_connection_put_uint32 (c, control -> state);
564         if (status != ISC_R_SUCCESS)
565                 return status;
566
567         /* Write out the inner object, if any. */
568         if (h -> inner && h -> inner -> type -> stuff_values) {
569                 status = ((*(h -> inner -> type -> stuff_values))
570                           (c, id, h -> inner));
571                 if (status == ISC_R_SUCCESS)
572                         return status;
573         }
574
575         return ISC_R_SUCCESS;
576 }
577
578 isc_result_t dhcp_control_lookup (omapi_object_t **lp,
579                                   omapi_object_t *id, omapi_object_t *ref)
580 {
581         omapi_value_t *tv = (omapi_value_t *)0;
582         isc_result_t status;
583         dhcp_control_object_t *control;
584
585         /* First see if we were sent a handle. */
586         if (ref) {
587                 status = omapi_get_value_str (ref, id, "handle", &tv);
588                 if (status == ISC_R_SUCCESS) {
589                         status = omapi_handle_td_lookup (lp, tv -> value);
590                         
591                         omapi_value_dereference (&tv, MDL);
592                         if (status != ISC_R_SUCCESS)
593                                 return status;
594                         
595                         /* Don't return the object if the type is wrong. */
596                         if ((*lp) -> type != dhcp_type_control) {
597                                 omapi_object_dereference (lp, MDL);
598                                 return ISC_R_INVALIDARG;
599                         }
600                 }
601         }
602
603         /* Otherwise, stop playing coy - there's only one control object,
604            so we can just return it. */
605         dhcp_control_reference ((dhcp_control_object_t **)lp,
606                                 dhcp_control_object, MDL);
607         return ISC_R_SUCCESS;
608 }
609
610 isc_result_t dhcp_control_create (omapi_object_t **lp,
611                                   omapi_object_t *id)
612 {
613         /* Can't create a control object - there can be only one. */
614         return ISC_R_NOPERM;
615 }
616
617 isc_result_t dhcp_control_remove (omapi_object_t *lp,
618                                 omapi_object_t *id)
619 {
620         /* Form is emptiness; emptiness form.   The control object
621            cannot go out of existance. */
622         return ISC_R_NOPERM;
623 }
624
625 isc_result_t dhcp_subnet_set_value  (omapi_object_t *h,
626                                      omapi_object_t *id,
627                                      omapi_data_string_t *name,
628                                      omapi_typed_data_t *value)
629 {
630         struct subnet *subnet;
631         isc_result_t status;
632         int foo;
633
634         if (h -> type != dhcp_type_subnet)
635                 return ISC_R_INVALIDARG;
636         subnet = (struct subnet *)h;
637
638         /* No values to set yet. */
639
640         /* Try to find some inner object that can take the value. */
641         if (h -> inner && h -> inner -> type -> set_value) {
642                 status = ((*(h -> inner -> type -> set_value))
643                           (h -> inner, id, name, value));
644                 if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
645                         return status;
646         }
647                           
648         return ISC_R_NOTFOUND;
649 }
650
651
652 isc_result_t dhcp_subnet_get_value (omapi_object_t *h, omapi_object_t *id,
653                                     omapi_data_string_t *name,
654                                     omapi_value_t **value)
655 {
656         struct subnet *subnet;
657         isc_result_t status;
658
659         if (h -> type != dhcp_type_subnet)
660                 return ISC_R_INVALIDARG;
661         subnet = (struct subnet *)h;
662
663         /* No values to get yet. */
664
665         /* Try to find some inner object that can provide the value. */
666         if (h -> inner && h -> inner -> type -> get_value) {
667                 status = ((*(h -> inner -> type -> get_value))
668                           (h -> inner, id, name, value));
669                 if (status == ISC_R_SUCCESS)
670                         return status;
671         }
672         return ISC_R_NOTFOUND;
673 }
674
675 isc_result_t dhcp_subnet_destroy (omapi_object_t *h, const char *file, int line)
676 {
677         struct subnet *subnet;
678         isc_result_t status;
679
680         if (h -> type != dhcp_type_subnet)
681                 return ISC_R_INVALIDARG;
682         subnet = (struct subnet *)h;
683
684 #if defined (DEBUG_MEMORY_LEAKAGE) || \
685                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
686         if (subnet -> next_subnet)
687                 subnet_dereference (&subnet -> next_subnet, file, line);
688         if (subnet -> next_sibling)
689                 subnet_dereference (&subnet -> next_sibling, file, line);
690         if (subnet -> shared_network)
691                 shared_network_dereference (&subnet -> shared_network,
692                                             file, line);
693         if (subnet -> interface)
694                 interface_dereference (&subnet -> interface, file, line);
695         if (subnet -> group)
696                 group_dereference (&subnet -> group, file, line);
697 #endif
698
699         return ISC_R_SUCCESS;
700 }
701
702 isc_result_t dhcp_subnet_signal_handler (omapi_object_t *h,
703                                          const char *name, va_list ap)
704 {
705         struct subnet *subnet;
706         isc_result_t status;
707         int updatep = 0;
708
709         if (h -> type != dhcp_type_subnet)
710                 return ISC_R_INVALIDARG;
711         subnet = (struct subnet *)h;
712
713         /* Can't write subnets yet. */
714
715         /* Try to find some inner object that can take the value. */
716         if (h -> inner && h -> inner -> type -> get_value) {
717                 status = ((*(h -> inner -> type -> signal_handler))
718                           (h -> inner, name, ap));
719                 if (status == ISC_R_SUCCESS)
720                         return status;
721         }
722         if (updatep)
723                 return ISC_R_SUCCESS;
724         return ISC_R_NOTFOUND;
725 }
726
727 isc_result_t dhcp_subnet_stuff_values (omapi_object_t *c,
728                                        omapi_object_t *id,
729                                        omapi_object_t *h)
730 {
731         struct subnet *subnet;
732         isc_result_t status;
733
734         if (h -> type != dhcp_type_subnet)
735                 return ISC_R_INVALIDARG;
736         subnet = (struct subnet *)h;
737
738         /* Can't stuff subnet values yet. */
739
740         /* Write out the inner object, if any. */
741         if (h -> inner && h -> inner -> type -> stuff_values) {
742                 status = ((*(h -> inner -> type -> stuff_values))
743                           (c, id, h -> inner));
744                 if (status == ISC_R_SUCCESS)
745                         return status;
746         }
747
748         return ISC_R_SUCCESS;
749 }
750
751 isc_result_t dhcp_subnet_lookup (omapi_object_t **lp,
752                                  omapi_object_t *id,
753                                  omapi_object_t *ref)
754 {
755         omapi_value_t *tv = (omapi_value_t *)0;
756         isc_result_t status;
757         struct subnet *subnet;
758
759         /* Can't look up subnets yet. */
760
761         /* If we get to here without finding a subnet, no valid key was
762            specified. */
763         if (!*lp)
764                 return ISC_R_NOKEYS;
765         return ISC_R_SUCCESS;
766 }
767
768 isc_result_t dhcp_subnet_create (omapi_object_t **lp,
769                                  omapi_object_t *id)
770 {
771         return ISC_R_NOTIMPLEMENTED;
772 }
773
774 isc_result_t dhcp_subnet_remove (omapi_object_t *lp,
775                                omapi_object_t *id)
776 {
777         return ISC_R_NOTIMPLEMENTED;
778 }
779
780 isc_result_t dhcp_shared_network_set_value  (omapi_object_t *h,
781                                              omapi_object_t *id,
782                                              omapi_data_string_t *name,
783                                              omapi_typed_data_t *value)
784 {
785         struct shared_network *shared_network;
786         isc_result_t status;
787         int foo;
788
789         if (h -> type != dhcp_type_shared_network)
790                 return ISC_R_INVALIDARG;
791         shared_network = (struct shared_network *)h;
792
793         /* No values to set yet. */
794
795         /* Try to find some inner object that can take the value. */
796         if (h -> inner && h -> inner -> type -> set_value) {
797                 status = ((*(h -> inner -> type -> set_value))
798                           (h -> inner, id, name, value));
799                 if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
800                         return status;
801         }
802                           
803         return ISC_R_NOTFOUND;
804 }
805
806
807 isc_result_t dhcp_shared_network_get_value (omapi_object_t *h,
808                                             omapi_object_t *id,
809                                             omapi_data_string_t *name,
810                                             omapi_value_t **value)
811 {
812         struct shared_network *shared_network;
813         isc_result_t status;
814
815         if (h -> type != dhcp_type_shared_network)
816                 return ISC_R_INVALIDARG;
817         shared_network = (struct shared_network *)h;
818
819         /* No values to get yet. */
820
821         /* Try to find some inner object that can provide the value. */
822         if (h -> inner && h -> inner -> type -> get_value) {
823                 status = ((*(h -> inner -> type -> get_value))
824                           (h -> inner, id, name, value));
825                 if (status == ISC_R_SUCCESS)
826                         return status;
827         }
828         return ISC_R_NOTFOUND;
829 }
830
831 isc_result_t dhcp_shared_network_destroy (omapi_object_t *h,
832                                           const char *file, int line)
833 {
834         struct shared_network *shared_network;
835         isc_result_t status;
836
837         if (h -> type != dhcp_type_shared_network)
838                 return ISC_R_INVALIDARG;
839         shared_network = (struct shared_network *)h;
840
841 #if defined (DEBUG_MEMORY_LEAKAGE) || \
842                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
843         if (shared_network -> next)
844                 shared_network_dereference (&shared_network -> next,
845                                             file, line);
846         if (shared_network -> name) {
847                 dfree (shared_network -> name, file, line);
848                 shared_network -> name = 0;
849         }
850         if (shared_network -> subnets)
851                 subnet_dereference (&shared_network -> subnets, file, line);
852         if (shared_network -> interface)
853                 interface_dereference (&shared_network -> interface,
854                                        file, line);
855         if (shared_network -> pools)
856             omapi_object_dereference ((omapi_object_t **)
857                                       &shared_network -> pools, file, line);
858         if (shared_network -> group)
859                 group_dereference (&shared_network -> group, file, line);
860 #if defined (FAILOVER_PROTOCOL)
861         if (shared_network -> failover_peer)
862             omapi_object_dereference ((omapi_object_t **)
863                                       &shared_network -> failover_peer,
864                                       file, line);
865 #endif
866 #endif /* DEBUG_MEMORY_LEAKAGE */
867
868         return ISC_R_SUCCESS;
869 }
870
871 isc_result_t dhcp_shared_network_signal_handler (omapi_object_t *h,
872                                                  const char *name,
873                                                  va_list ap)
874 {
875         struct shared_network *shared_network;
876         isc_result_t status;
877         int updatep = 0;
878
879         if (h -> type != dhcp_type_shared_network)
880                 return ISC_R_INVALIDARG;
881         shared_network = (struct shared_network *)h;
882
883         /* Can't write shared_networks yet. */
884
885         /* Try to find some inner object that can take the value. */
886         if (h -> inner && h -> inner -> type -> get_value) {
887                 status = ((*(h -> inner -> type -> signal_handler))
888                           (h -> inner, name, ap));
889                 if (status == ISC_R_SUCCESS)
890                         return status;
891         }
892         if (updatep)
893                 return ISC_R_SUCCESS;
894         return ISC_R_NOTFOUND;
895 }
896
897 isc_result_t dhcp_shared_network_stuff_values (omapi_object_t *c,
898                                                omapi_object_t *id,
899                                                omapi_object_t *h)
900 {
901         struct shared_network *shared_network;
902         isc_result_t status;
903
904         if (h -> type != dhcp_type_shared_network)
905                 return ISC_R_INVALIDARG;
906         shared_network = (struct shared_network *)h;
907
908         /* Can't stuff shared_network values yet. */
909
910         /* Write out the inner object, if any. */
911         if (h -> inner && h -> inner -> type -> stuff_values) {
912                 status = ((*(h -> inner -> type -> stuff_values))
913                           (c, id, h -> inner));
914                 if (status == ISC_R_SUCCESS)
915                         return status;
916         }
917
918         return ISC_R_SUCCESS;
919 }
920
921 isc_result_t dhcp_shared_network_lookup (omapi_object_t **lp,
922                                          omapi_object_t *id,
923                                          omapi_object_t *ref)
924 {
925         omapi_value_t *tv = (omapi_value_t *)0;
926         isc_result_t status;
927         struct shared_network *shared_network;
928
929         /* Can't look up shared_networks yet. */
930
931         /* If we get to here without finding a shared_network, no valid key was
932            specified. */
933         if (!*lp)
934                 return ISC_R_NOKEYS;
935         return ISC_R_SUCCESS;
936 }
937
938 isc_result_t dhcp_shared_network_create (omapi_object_t **lp,
939                                          omapi_object_t *id)
940 {
941         return ISC_R_NOTIMPLEMENTED;
942 }
943
944 isc_result_t dhcp_shared_network_remove (omapi_object_t *lp,
945                                          omapi_object_t *id)
946 {
947         return ISC_R_NOTIMPLEMENTED;
948 }
949