3 Subroutines providing general support for objects. */
6 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1999-2003 by Internet Software Consortium
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
31 #include <omapip/omapip_p.h>
33 omapi_object_type_t
*omapi_type_connection
;
34 omapi_object_type_t
*omapi_type_listener
;
35 omapi_object_type_t
*omapi_type_io_object
;
36 omapi_object_type_t
*omapi_type_datagram
;
37 omapi_object_type_t
*omapi_type_generic
;
38 omapi_object_type_t
*omapi_type_protocol
;
39 omapi_object_type_t
*omapi_type_protocol_listener
;
40 omapi_object_type_t
*omapi_type_waiter
;
41 omapi_object_type_t
*omapi_type_remote
;
42 omapi_object_type_t
*omapi_type_message
;
43 omapi_object_type_t
*omapi_type_auth_key
;
45 omapi_object_type_t
*omapi_object_types
;
46 int omapi_object_type_count
;
48 #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
49 void omapi_type_relinquish ()
51 omapi_object_type_t
*t
, *n
;
53 for (t
= omapi_object_types
; t
; t
= n
) {
57 omapi_object_types
= (omapi_object_type_t
*)0;
61 isc_result_t
omapi_init (void)
65 /* Register all the standard object types... */
66 status
= omapi_object_type_register (&omapi_type_connection
,
68 omapi_connection_set_value
,
69 omapi_connection_get_value
,
70 omapi_connection_destroy
,
71 omapi_connection_signal_handler
,
72 omapi_connection_stuff_values
,
75 (omapi_connection_object_t
), 0,
77 if (status
!= ISC_R_SUCCESS
)
80 status
= omapi_object_type_register (&omapi_type_listener
,
82 omapi_listener_set_value
,
83 omapi_listener_get_value
,
84 omapi_listener_destroy
,
85 omapi_listener_signal_handler
,
86 omapi_listener_stuff_values
,
88 sizeof (omapi_listener_object_t
),
90 if (status
!= ISC_R_SUCCESS
)
93 status
= omapi_object_type_register (&omapi_type_io_object
,
98 omapi_io_signal_handler
,
99 omapi_io_stuff_values
,
101 sizeof (omapi_io_object_t
),
103 if (status
!= ISC_R_SUCCESS
)
106 status
= omapi_object_type_register (&omapi_type_generic
,
108 omapi_generic_set_value
,
109 omapi_generic_get_value
,
110 omapi_generic_destroy
,
111 omapi_generic_signal_handler
,
112 omapi_generic_stuff_values
,
114 sizeof (omapi_generic_object_t
),
116 if (status
!= ISC_R_SUCCESS
)
119 status
= omapi_object_type_register (&omapi_type_protocol
,
121 omapi_protocol_set_value
,
122 omapi_protocol_get_value
,
123 omapi_protocol_destroy
,
124 omapi_protocol_signal_handler
,
125 omapi_protocol_stuff_values
,
127 sizeof (omapi_protocol_object_t
),
129 if (status
!= ISC_R_SUCCESS
)
132 status
= (omapi_object_type_register
133 (&omapi_type_protocol_listener
, "protocol-listener",
134 omapi_protocol_listener_set_value
,
135 omapi_protocol_listener_get_value
,
136 omapi_protocol_listener_destroy
,
137 omapi_protocol_listener_signal
,
138 omapi_protocol_listener_stuff
,
140 sizeof (omapi_protocol_listener_object_t
), 0, RC_MISC
));
141 if (status
!= ISC_R_SUCCESS
)
144 status
= omapi_object_type_register (&omapi_type_message
,
146 omapi_message_set_value
,
147 omapi_message_get_value
,
148 omapi_message_destroy
,
149 omapi_message_signal_handler
,
150 omapi_message_stuff_values
,
152 sizeof (omapi_message_object_t
),
154 if (status
!= ISC_R_SUCCESS
)
157 status
= omapi_object_type_register (&omapi_type_waiter
,
162 omapi_waiter_signal_handler
, 0,
164 sizeof (omapi_waiter_object_t
),
166 if (status
!= ISC_R_SUCCESS
)
169 status
= omapi_object_type_register (&omapi_type_auth_key
,
172 omapi_auth_key_get_value
,
173 omapi_auth_key_destroy
,
175 omapi_auth_key_stuff_values
,
176 omapi_auth_key_lookup
,
178 sizeof (omapi_auth_key_t
), 0,
180 if (status
!= ISC_R_SUCCESS
)
183 #if defined (TRACING)
184 omapi_listener_trace_setup ();
185 omapi_connection_trace_setup ();
186 omapi_buffer_trace_setup ();
189 /* This seems silly, but leave it. */
190 return ISC_R_SUCCESS
;
193 isc_result_t
omapi_object_type_register (omapi_object_type_t
**type
,
195 isc_result_t (*set_value
)
198 omapi_data_string_t
*,
199 omapi_typed_data_t
*),
200 isc_result_t (*get_value
)
203 omapi_data_string_t
*,
205 isc_result_t (*destroy
)
208 isc_result_t (*signal_handler
)
210 const char *, va_list),
211 isc_result_t (*stuff_values
)
215 isc_result_t (*lookup
)
219 isc_result_t (*create
)
222 isc_result_t (*remove
)
225 isc_result_t (*freer
)
228 isc_result_t (*allocator
)
231 isc_result_t (*sizer
) (size_t),
233 isc_result_t (*initialize
)
238 omapi_object_type_t
*t
;
240 t
= dmalloc (sizeof *t
, MDL
);
242 return ISC_R_NOMEMORY
;
243 memset (t
, 0, sizeof *t
);
246 t
-> set_value
= set_value
;
247 t
-> get_value
= get_value
;
248 t
-> destroy
= destroy
;
249 t
-> signal_handler
= signal_handler
;
250 t
-> stuff_values
= stuff_values
;
251 t
-> lookup
= lookup
;
252 t
-> create
= create
;
253 t
-> remove
= remove
;
254 t
-> next
= omapi_object_types
;
258 t
-> allocator
= allocator
;
259 t
-> initialize
= initialize
;
260 t
-> rc_flag
= rc_flag
;
261 omapi_object_types
= t
;
264 return ISC_R_SUCCESS
;
267 isc_result_t
omapi_signal (omapi_object_t
*handle
, const char *name
, ...)
270 omapi_object_t
*outer
;
274 for (outer
= handle
; outer
-> outer
; outer
= outer
-> outer
)
276 if (outer
-> type
-> signal_handler
)
277 status
= (*(outer
-> type
-> signal_handler
)) (outer
,
280 status
= ISC_R_NOTFOUND
;
285 isc_result_t
omapi_signal_in (omapi_object_t
*handle
, const char *name
, ...)
291 return ISC_R_NOTFOUND
;
294 if (handle
-> type
-> signal_handler
)
295 status
= (*(handle
-> type
-> signal_handler
)) (handle
,
298 status
= ISC_R_NOTFOUND
;
303 isc_result_t
omapi_set_value (omapi_object_t
*h
,
305 omapi_data_string_t
*name
,
306 omapi_typed_data_t
*value
)
308 omapi_object_t
*outer
;
313 log_info ("omapi_set_value (%.*s, NULL)",
314 (int)name
-> len
, name
-> value
);
315 } else if (value
-> type
== omapi_datatype_int
) {
316 log_info ("omapi_set_value (%.*s, %ld)",
317 (int)name
-> len
, name
-> value
,
318 (long)value
-> u
.integer
);
319 } else if (value
-> type
== omapi_datatype_string
) {
320 log_info ("omapi_set_value (%.*s, %.*s)",
321 (int)name
-> len
, name
-> value
,
322 (int)value
-> u
.buffer
.len
, value
-> u
.buffer
.value
);
323 } else if (value
-> type
== omapi_datatype_data
) {
324 log_info ("omapi_set_value (%.*s, %ld %lx)",
325 (int)name
-> len
, name
-> value
,
326 (long)value
-> u
.buffer
.len
,
327 (unsigned long)value
-> u
.buffer
.value
);
328 } else if (value
-> type
== omapi_datatype_object
) {
329 log_info ("omapi_set_value (%.*s, %s)",
330 (int)name
-> len
, name
-> value
,
332 ? (value
-> u
.object
-> type
333 ? value
-> u
.object
-> type
-> name
334 : "(unknown object)")
335 : "(unknown object)");
339 for (outer
= h
; outer
-> outer
; outer
= outer
-> outer
)
341 if (outer
-> type
-> set_value
)
342 status
= (*(outer
-> type
-> set_value
)) (outer
,
345 status
= ISC_R_NOTFOUND
;
347 log_info (" ==> %s", isc_result_totext (status
));
352 isc_result_t
omapi_set_value_str (omapi_object_t
*h
,
355 omapi_typed_data_t
*value
)
357 omapi_data_string_t
*nds
;
360 nds
= (omapi_data_string_t
*)0;
361 status
= omapi_data_string_new (&nds
, strlen (name
), MDL
);
362 if (status
!= ISC_R_SUCCESS
)
364 memcpy (nds
-> value
, name
, strlen (name
));
366 status
= omapi_set_value (h
, id
, nds
, value
);
367 omapi_data_string_dereference (&nds
, MDL
);
371 isc_result_t
omapi_set_boolean_value (omapi_object_t
*h
, omapi_object_t
*id
,
372 const char *name
, int value
)
375 omapi_typed_data_t
*tv
= (omapi_typed_data_t
*)0;
376 omapi_data_string_t
*n
= (omapi_data_string_t
*)0;
378 status
= omapi_data_string_new (&n
, strlen (name
), MDL
);
379 if (status
!= ISC_R_SUCCESS
)
381 memcpy (n
-> value
, name
, strlen (name
));
383 status
= omapi_typed_data_new (MDL
, &tv
, omapi_datatype_int
, value
);
384 if (status
!= ISC_R_SUCCESS
) {
385 omapi_data_string_dereference (&n
, MDL
);
389 status
= omapi_set_value (h
, id
, n
, tv
);
390 omapi_data_string_dereference (&n
, MDL
);
391 omapi_typed_data_dereference (&tv
, MDL
);
395 isc_result_t
omapi_set_int_value (omapi_object_t
*h
, omapi_object_t
*id
,
396 const char *name
, int value
)
399 omapi_typed_data_t
*tv
= (omapi_typed_data_t
*)0;
400 omapi_data_string_t
*n
= (omapi_data_string_t
*)0;
402 status
= omapi_data_string_new (&n
, strlen (name
), MDL
);
403 if (status
!= ISC_R_SUCCESS
)
405 memcpy (n
-> value
, name
, strlen (name
));
407 status
= omapi_typed_data_new (MDL
, &tv
, omapi_datatype_int
, value
);
408 if (status
!= ISC_R_SUCCESS
) {
409 omapi_data_string_dereference (&n
, MDL
);
413 status
= omapi_set_value (h
, id
, n
, tv
);
414 omapi_data_string_dereference (&n
, MDL
);
415 omapi_typed_data_dereference (&tv
, MDL
);
419 isc_result_t
omapi_set_object_value (omapi_object_t
*h
, omapi_object_t
*id
,
420 const char *name
, omapi_object_t
*value
)
423 omapi_typed_data_t
*tv
= (omapi_typed_data_t
*)0;
424 omapi_data_string_t
*n
= (omapi_data_string_t
*)0;
426 status
= omapi_data_string_new (&n
, strlen (name
), MDL
);
427 if (status
!= ISC_R_SUCCESS
)
429 memcpy (n
-> value
, name
, strlen (name
));
431 status
= omapi_typed_data_new (MDL
, &tv
, omapi_datatype_object
, value
);
432 if (status
!= ISC_R_SUCCESS
) {
433 omapi_data_string_dereference (&n
, MDL
);
437 status
= omapi_set_value (h
, id
, n
, tv
);
438 omapi_data_string_dereference (&n
, MDL
);
439 omapi_typed_data_dereference (&tv
, MDL
);
443 isc_result_t
omapi_set_string_value (omapi_object_t
*h
, omapi_object_t
*id
,
444 const char *name
, const char *value
)
447 omapi_typed_data_t
*tv
= (omapi_typed_data_t
*)0;
448 omapi_data_string_t
*n
= (omapi_data_string_t
*)0;
450 status
= omapi_data_string_new (&n
, strlen (name
), MDL
);
451 if (status
!= ISC_R_SUCCESS
)
453 memcpy (n
-> value
, name
, strlen (name
));
455 status
= omapi_typed_data_new (MDL
, &tv
, omapi_datatype_string
, value
);
456 if (status
!= ISC_R_SUCCESS
) {
457 omapi_data_string_dereference (&n
, MDL
);
461 status
= omapi_set_value (h
, id
, n
, tv
);
462 omapi_data_string_dereference (&n
, MDL
);
463 omapi_typed_data_dereference (&tv
, MDL
);
467 isc_result_t
omapi_get_value (omapi_object_t
*h
,
469 omapi_data_string_t
*name
,
470 omapi_value_t
**value
)
472 omapi_object_t
*outer
;
474 for (outer
= h
; outer
-> outer
; outer
= outer
-> outer
)
476 if (outer
-> type
-> get_value
)
477 return (*(outer
-> type
-> get_value
)) (outer
,
479 return ISC_R_NOTFOUND
;
482 isc_result_t
omapi_get_value_str (omapi_object_t
*h
,
485 omapi_value_t
**value
)
487 omapi_object_t
*outer
;
488 omapi_data_string_t
*nds
;
491 nds
= (omapi_data_string_t
*)0;
492 status
= omapi_data_string_new (&nds
, strlen (name
), MDL
);
493 if (status
!= ISC_R_SUCCESS
)
495 memcpy (nds
-> value
, name
, strlen (name
));
497 for (outer
= h
; outer
-> outer
; outer
= outer
-> outer
)
499 if (outer
-> type
-> get_value
)
500 status
= (*(outer
-> type
-> get_value
)) (outer
,
503 status
= ISC_R_NOTFOUND
;
504 omapi_data_string_dereference (&nds
, MDL
);
508 isc_result_t
omapi_stuff_values (omapi_object_t
*c
,
512 omapi_object_t
*outer
;
514 for (outer
= o
; outer
-> outer
; outer
= outer
-> outer
)
516 if (outer
-> type
-> stuff_values
)
517 return (*(outer
-> type
-> stuff_values
)) (c
, id
, outer
);
518 return ISC_R_NOTFOUND
;
521 isc_result_t
omapi_object_create (omapi_object_t
**obj
, omapi_object_t
*id
,
522 omapi_object_type_t
*type
)
525 return ISC_R_NOTIMPLEMENTED
;
526 return (*(type
-> create
)) (obj
, id
);
529 isc_result_t
omapi_object_update (omapi_object_t
*obj
, omapi_object_t
*id
,
530 omapi_object_t
*src
, omapi_handle_t handle
)
532 omapi_generic_object_t
*gsrc
;
537 return DHCP_R_INVALIDARG
;
538 if (src
-> type
!= omapi_type_generic
)
539 return ISC_R_NOTIMPLEMENTED
;
540 gsrc
= (omapi_generic_object_t
*)src
;
541 for (i
= 0; i
< gsrc
-> nvalues
; i
++) {
542 status
= omapi_set_value (obj
, id
,
543 gsrc
-> values
[i
] -> name
,
544 gsrc
-> values
[i
] -> value
);
545 if (status
!= ISC_R_SUCCESS
&& status
!= DHCP_R_UNCHANGED
)
550 * For now ignore the return value. I'm not sure if we want to
551 * generate an error if we can't set the handle value. If we
552 * do add a check we probably should allow unchanged and notfound
555 (void) omapi_set_int_value (obj
, id
, "remote-handle", (int)handle
);
556 status
= omapi_signal (obj
, "updated");
557 if (status
!= ISC_R_NOTFOUND
)
559 return ISC_R_SUCCESS
;
562 int omapi_data_string_cmp (omapi_data_string_t
*s1
, omapi_data_string_t
*s2
)
567 if (s1
-> len
> s2
-> len
)
571 rv
= memcmp (s1
-> value
, s2
-> value
, len
);
574 if (s1
-> len
> s2
-> len
)
576 else if (s1
-> len
< s2
-> len
)
581 int omapi_ds_strcmp (omapi_data_string_t
*s1
, const char *s2
)
587 if (slen
> s1
-> len
)
591 rv
= memcmp (s1
-> value
, s2
, len
);
594 if (s1
-> len
> slen
)
596 else if (s1
-> len
< slen
)
601 int omapi_td_strcmp (omapi_typed_data_t
*s1
, const char *s2
)
606 /* If the data type is not compatible, never equal. */
607 if (s1
-> type
!= omapi_datatype_data
&&
608 s1
-> type
!= omapi_datatype_string
)
612 if (slen
> s1
-> u
.buffer
.len
)
613 len
= s1
-> u
.buffer
.len
;
616 rv
= memcmp (s1
-> u
.buffer
.value
, s2
, len
);
619 if (s1
-> u
.buffer
.len
> slen
)
621 else if (s1
-> u
.buffer
.len
< slen
)
626 int omapi_td_strcasecmp (omapi_typed_data_t
*s1
, const char *s2
)
631 /* If the data type is not compatible, never equal. */
632 if (s1
-> type
!= omapi_datatype_data
&&
633 s1
-> type
!= omapi_datatype_string
)
637 if (slen
> s1
-> u
.buffer
.len
)
638 len
= s1
-> u
.buffer
.len
;
641 rv
= casecmp (s1
-> u
.buffer
.value
, s2
, len
);
644 if (s1
-> u
.buffer
.len
> slen
)
646 else if (s1
-> u
.buffer
.len
< slen
)
651 isc_result_t
omapi_make_value (omapi_value_t
**vp
,
652 omapi_data_string_t
*name
,
653 omapi_typed_data_t
*value
,
654 const char *file
, int line
)
658 status
= omapi_value_new (vp
, file
, line
);
659 if (status
!= ISC_R_SUCCESS
)
662 status
= omapi_data_string_reference (&(*vp
) -> name
,
664 if (status
!= ISC_R_SUCCESS
) {
665 omapi_value_dereference (vp
, file
, line
);
669 status
= omapi_typed_data_reference (&(*vp
) -> value
,
671 if (status
!= ISC_R_SUCCESS
) {
672 omapi_value_dereference (vp
, file
, line
);
676 return ISC_R_SUCCESS
;
679 isc_result_t
omapi_make_const_value (omapi_value_t
**vp
,
680 omapi_data_string_t
*name
,
681 const unsigned char *value
,
683 const char *file
, int line
)
687 status
= omapi_value_new (vp
, file
, line
);
688 if (status
!= ISC_R_SUCCESS
)
691 status
= omapi_data_string_reference (&(*vp
) -> name
,
693 if (status
!= ISC_R_SUCCESS
) {
694 omapi_value_dereference (vp
, file
, line
);
698 status
= omapi_typed_data_new (file
, line
, &(*vp
) -> value
,
699 omapi_datatype_data
, len
);
700 if (status
!= ISC_R_SUCCESS
) {
701 omapi_value_dereference (vp
, file
, line
);
704 memcpy ((*vp
) -> value
-> u
.buffer
.value
, value
, len
);
706 return ISC_R_SUCCESS
;
709 isc_result_t
omapi_make_int_value (omapi_value_t
**vp
,
710 omapi_data_string_t
*name
,
711 int value
, const char *file
, int line
)
715 status
= omapi_value_new (vp
, file
, line
);
716 if (status
!= ISC_R_SUCCESS
)
719 status
= omapi_data_string_reference (&(*vp
) -> name
,
721 if (status
!= ISC_R_SUCCESS
) {
722 omapi_value_dereference (vp
, file
, line
);
725 status
= omapi_typed_data_new (file
, line
, &(*vp
) -> value
,
726 omapi_datatype_int
, value
);
727 if (status
!= ISC_R_SUCCESS
) {
728 omapi_value_dereference (vp
, file
, line
);
731 return ISC_R_SUCCESS
;
734 isc_result_t
omapi_make_uint_value (omapi_value_t
**vp
,
735 omapi_data_string_t
*name
,
737 const char *file
, int line
)
739 return omapi_make_int_value (vp
, name
, (int)value
, file
, line
);
742 isc_result_t
omapi_make_object_value (omapi_value_t
**vp
,
743 omapi_data_string_t
*name
,
744 omapi_object_t
*value
,
745 const char *file
, int line
)
749 status
= omapi_value_new (vp
, file
, line
);
750 if (status
!= ISC_R_SUCCESS
)
753 status
= omapi_data_string_reference (&(*vp
) -> name
,
755 if (status
!= ISC_R_SUCCESS
) {
756 omapi_value_dereference (vp
, file
, line
);
761 status
= omapi_typed_data_new (file
, line
, &(*vp
) -> value
,
762 omapi_datatype_object
, value
);
763 if (status
!= ISC_R_SUCCESS
) {
764 omapi_value_dereference (vp
, file
, line
);
769 return ISC_R_SUCCESS
;
772 isc_result_t
omapi_make_handle_value (omapi_value_t
**vp
,
773 omapi_data_string_t
*name
,
774 omapi_object_t
*value
,
775 const char *file
, int line
)
779 status
= omapi_value_new (vp
, file
, line
);
780 if (status
!= ISC_R_SUCCESS
)
783 status
= omapi_data_string_reference (&(*vp
) -> name
,
785 if (status
!= ISC_R_SUCCESS
) {
786 omapi_value_dereference (vp
, file
, line
);
790 status
= omapi_typed_data_new (file
, line
, &(*vp
) -> value
,
792 if (status
!= ISC_R_SUCCESS
) {
793 omapi_value_dereference (vp
, file
, line
);
796 status
= (omapi_object_handle
797 ((omapi_handle_t
*)&(*vp
) -> value
-> u
.integer
,
799 if (status
!= ISC_R_SUCCESS
) {
800 omapi_value_dereference (vp
, file
, line
);
804 return ISC_R_SUCCESS
;
807 isc_result_t
omapi_make_string_value (omapi_value_t
**vp
,
808 omapi_data_string_t
*name
,
810 const char *file
, int line
)
814 status
= omapi_value_new (vp
, file
, line
);
815 if (status
!= ISC_R_SUCCESS
)
818 status
= omapi_data_string_reference (&(*vp
) -> name
,
820 if (status
!= ISC_R_SUCCESS
) {
821 omapi_value_dereference (vp
, file
, line
);
825 status
= omapi_typed_data_new (file
, line
, &(*vp
) -> value
,
826 omapi_datatype_string
, value
);
827 if (status
!= ISC_R_SUCCESS
) {
828 omapi_value_dereference (vp
, file
, line
);
832 return ISC_R_SUCCESS
;
835 isc_result_t
omapi_get_int_value (unsigned long *v
, omapi_typed_data_t
*t
)
839 if (t
-> type
== omapi_datatype_int
) {
841 return ISC_R_SUCCESS
;
842 } else if (t
-> type
== omapi_datatype_string
||
843 t
-> type
== omapi_datatype_data
) {
844 if (t
-> u
.buffer
.len
!= sizeof (rv
))
845 return DHCP_R_INVALIDARG
;
846 memcpy (&rv
, t
-> u
.buffer
.value
, sizeof rv
);
848 return ISC_R_SUCCESS
;
850 return DHCP_R_INVALIDARG
;