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