Home | History | Annotate | Line # | Download | only in omapip
      1 /*	$NetBSD: support.c,v 1.3 2022/04/03 01:10:59 christos Exp $	*/
      2 
      3 /* support.c
      4 
      5    Subroutines providing general support for objects. */
      6 
      7 /*
      8  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
      9  * Copyright (c) 1999-2003 by Internet Software Consortium
     10  *
     11  * This Source Code Form is subject to the terms of the Mozilla Public
     12  * License, v. 2.0. If a copy of the MPL was not distributed with this
     13  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     16  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     17  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     18  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     20  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     21  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22  *
     23  *   Internet Systems Consortium, Inc.
     24  *   PO Box 360
     25  *   Newmarket, NH 03857 USA
     26  *   <info (at) isc.org>
     27  *   https://www.isc.org/
     28  *
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: support.c,v 1.3 2022/04/03 01:10:59 christos Exp $");
     33 
     34 #include "dhcpd.h"
     35 
     36 #include <omapip/omapip_p.h>
     37 
     38 omapi_object_type_t *omapi_type_connection;
     39 omapi_object_type_t *omapi_type_listener;
     40 omapi_object_type_t *omapi_type_io_object;
     41 omapi_object_type_t *omapi_type_datagram;
     42 omapi_object_type_t *omapi_type_generic;
     43 omapi_object_type_t *omapi_type_protocol;
     44 omapi_object_type_t *omapi_type_protocol_listener;
     45 omapi_object_type_t *omapi_type_waiter;
     46 omapi_object_type_t *omapi_type_remote;
     47 omapi_object_type_t *omapi_type_message;
     48 omapi_object_type_t *omapi_type_auth_key;
     49 
     50 omapi_object_type_t *omapi_object_types;
     51 int omapi_object_type_count;
     52 
     53 #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
     54 void omapi_type_relinquish ()
     55 {
     56 	omapi_object_type_t *t, *n;
     57 
     58 	for (t = omapi_object_types; t; t = n) {
     59 		n = t -> next;
     60 		dfree (t, MDL);
     61 	}
     62 	omapi_object_types = (omapi_object_type_t *)0;
     63 }
     64 #endif
     65 
     66 isc_result_t omapi_init (void)
     67 {
     68 	isc_result_t status;
     69 
     70 	/* Register all the standard object types... */
     71 	status = omapi_object_type_register (&omapi_type_connection,
     72 					     "connection",
     73 					     omapi_connection_set_value,
     74 					     omapi_connection_get_value,
     75 					     omapi_connection_destroy,
     76 					     omapi_connection_signal_handler,
     77 					     omapi_connection_stuff_values,
     78 					     0, 0, 0, 0, 0, 0,
     79 					     sizeof
     80 					     (omapi_connection_object_t), 0,
     81 					     RC_MISC);
     82 	if (status != ISC_R_SUCCESS)
     83 		return status;
     84 
     85 	status = omapi_object_type_register (&omapi_type_listener,
     86 					     "listener",
     87 					     omapi_listener_set_value,
     88 					     omapi_listener_get_value,
     89 					     omapi_listener_destroy,
     90 					     omapi_listener_signal_handler,
     91 					     omapi_listener_stuff_values,
     92 					     0, 0, 0, 0, 0, 0,
     93 					     sizeof (omapi_listener_object_t),
     94 					     0, RC_MISC);
     95 	if (status != ISC_R_SUCCESS)
     96 		return status;
     97 
     98 	status = omapi_object_type_register (&omapi_type_io_object,
     99 					     "io",
    100 					     omapi_io_set_value,
    101 					     omapi_io_get_value,
    102 					     omapi_io_destroy,
    103 					     omapi_io_signal_handler,
    104 					     omapi_io_stuff_values,
    105 					     0, 0, 0, 0, 0, 0,
    106 					     sizeof (omapi_io_object_t),
    107 					     0, RC_MISC);
    108 	if (status != ISC_R_SUCCESS)
    109 		return status;
    110 
    111 	status = omapi_object_type_register (&omapi_type_generic,
    112 					     "generic",
    113 					     omapi_generic_set_value,
    114 					     omapi_generic_get_value,
    115 					     omapi_generic_destroy,
    116 					     omapi_generic_signal_handler,
    117 					     omapi_generic_stuff_values,
    118 					     0, 0, 0, 0, 0, 0,
    119 					     sizeof (omapi_generic_object_t),
    120 					     0, RC_MISC);
    121 	if (status != ISC_R_SUCCESS)
    122 		return status;
    123 
    124 	status = omapi_object_type_register (&omapi_type_protocol,
    125 					     "protocol",
    126 					     omapi_protocol_set_value,
    127 					     omapi_protocol_get_value,
    128 					     omapi_protocol_destroy,
    129 					     omapi_protocol_signal_handler,
    130 					     omapi_protocol_stuff_values,
    131 					     0, 0, 0, 0, 0, 0,
    132 					     sizeof (omapi_protocol_object_t),
    133 					     0, RC_MISC);
    134 	if (status != ISC_R_SUCCESS)
    135 		return status;
    136 
    137 	status = (omapi_object_type_register
    138 		  (&omapi_type_protocol_listener, "protocol-listener",
    139 		   omapi_protocol_listener_set_value,
    140 		   omapi_protocol_listener_get_value,
    141 		   omapi_protocol_listener_destroy,
    142 		   omapi_protocol_listener_signal,
    143 		   omapi_protocol_listener_stuff,
    144 		   0, 0, 0, 0, 0, 0,
    145 		   sizeof (omapi_protocol_listener_object_t), 0, RC_MISC));
    146 	if (status != ISC_R_SUCCESS)
    147 		return status;
    148 
    149 	status = omapi_object_type_register (&omapi_type_message,
    150 					     "message",
    151 					     omapi_message_set_value,
    152 					     omapi_message_get_value,
    153 					     omapi_message_destroy,
    154 					     omapi_message_signal_handler,
    155 					     omapi_message_stuff_values,
    156 					     0, 0, 0, 0, 0, 0,
    157 					     sizeof (omapi_message_object_t),
    158 					     0, RC_MISC);
    159 	if (status != ISC_R_SUCCESS)
    160 		return status;
    161 
    162 	status = omapi_object_type_register (&omapi_type_waiter,
    163 					     "waiter",
    164 					     0,
    165 					     0,
    166 					     0,
    167 					     omapi_waiter_signal_handler, 0,
    168 					     0, 0, 0, 0, 0, 0,
    169 					     sizeof (omapi_waiter_object_t),
    170 					     0, RC_MISC);
    171 	if (status != ISC_R_SUCCESS)
    172 		return status;
    173 
    174 	status = omapi_object_type_register (&omapi_type_auth_key,
    175 					     "authenticator",
    176 					     0,
    177 					     omapi_auth_key_get_value,
    178 					     omapi_auth_key_destroy,
    179 					     0,
    180 					     omapi_auth_key_stuff_values,
    181 					     omapi_auth_key_lookup,
    182 					     0, 0, 0, 0, 0,
    183 					     sizeof (omapi_auth_key_t), 0,
    184 					     RC_MISC);
    185 	if (status != ISC_R_SUCCESS)
    186 		return status;
    187 
    188 #if defined (TRACING)
    189 	omapi_listener_trace_setup ();
    190 	omapi_connection_trace_setup ();
    191 	omapi_buffer_trace_setup ();
    192 #endif
    193 
    194 	/* This seems silly, but leave it. */
    195 	return ISC_R_SUCCESS;
    196 }
    197 
    198 isc_result_t omapi_object_type_register (omapi_object_type_t **type,
    199 					 const char *name,
    200 					 isc_result_t (*set_value)
    201 						 (omapi_object_t *,
    202 						  omapi_object_t *,
    203 						  omapi_data_string_t *,
    204 						  omapi_typed_data_t *),
    205 					 isc_result_t (*get_value)
    206 						(omapi_object_t *,
    207 						 omapi_object_t *,
    208 						 omapi_data_string_t *,
    209 						 omapi_value_t **),
    210 					 isc_result_t (*destroy)
    211 						(omapi_object_t *,
    212 						 const char *, int),
    213 					 isc_result_t (*signal_handler)
    214 						 (omapi_object_t *,
    215 						  const char *, va_list),
    216 					 isc_result_t (*stuff_values)
    217 						(omapi_object_t *,
    218 						 omapi_object_t *,
    219 						 omapi_object_t *),
    220 					 isc_result_t (*lookup)
    221 						(omapi_object_t **,
    222 						 omapi_object_t *,
    223 						 omapi_object_t *),
    224 					 isc_result_t (*create)
    225 						(omapi_object_t **,
    226 						 omapi_object_t *),
    227 					 isc_result_t (*remove)
    228 						(omapi_object_t *,
    229 						 omapi_object_t *),
    230 					 isc_result_t (*freer)
    231 						(omapi_object_t *,
    232 						 const char *, int),
    233 					 isc_result_t (*allocator)
    234 						(omapi_object_t **,
    235 						 const char *, int),
    236 					 isc_result_t (*sizer) (size_t),
    237 					 size_t size,
    238 					 isc_result_t (*initialize)
    239 						(omapi_object_t *,
    240 						 const char *, int),
    241 					 int rc_flag)
    242 {
    243 	omapi_object_type_t *t;
    244 
    245 	t = dmalloc (sizeof *t, MDL);
    246 	if (!t)
    247 		return ISC_R_NOMEMORY;
    248 	memset (t, 0, sizeof *t);
    249 
    250 	t -> name = name;
    251 	t -> set_value = set_value;
    252 	t -> get_value = get_value;
    253 	t -> destroy = destroy;
    254 	t -> signal_handler = signal_handler;
    255 	t -> stuff_values = stuff_values;
    256 	t -> lookup = lookup;
    257 	t -> create = create;
    258 	t -> remove = remove;
    259 	t -> next = omapi_object_types;
    260 	t -> sizer = sizer;
    261 	t -> size = size;
    262 	t -> freer = freer;
    263 	t -> allocator = allocator;
    264 	t -> initialize = initialize;
    265 	t -> rc_flag = rc_flag;
    266 	omapi_object_types = t;
    267 	if (type)
    268 		*type = t;
    269 	return ISC_R_SUCCESS;
    270 }
    271 
    272 isc_result_t omapi_signal (omapi_object_t *handle, const char *name, ...)
    273 {
    274 	va_list ap;
    275 	omapi_object_t *outer;
    276 	isc_result_t status;
    277 
    278 	va_start (ap, name);
    279 	for (outer = handle; outer -> outer; outer = outer -> outer)
    280 		;
    281 	if (outer -> type -> signal_handler)
    282 		status = (*(outer -> type -> signal_handler)) (outer,
    283 							       name, ap);
    284 	else
    285 		status = ISC_R_NOTFOUND;
    286 	va_end (ap);
    287 	return status;
    288 }
    289 
    290 isc_result_t omapi_signal_in (omapi_object_t *handle, const char *name, ...)
    291 {
    292 	va_list ap;
    293 	isc_result_t status;
    294 
    295 	if (!handle)
    296 		return ISC_R_NOTFOUND;
    297 	va_start (ap, name);
    298 
    299 	if (handle -> type -> signal_handler)
    300 		status = (*(handle -> type -> signal_handler)) (handle,
    301 								name, ap);
    302 	else
    303 		status = ISC_R_NOTFOUND;
    304 	va_end (ap);
    305 	return status;
    306 }
    307 
    308 isc_result_t omapi_set_value (omapi_object_t *h,
    309 			      omapi_object_t *id,
    310 			      omapi_data_string_t *name,
    311 			      omapi_typed_data_t *value)
    312 {
    313 	omapi_object_t *outer;
    314 	isc_result_t status;
    315 
    316 #if defined (DEBUG_PROTOCOL)
    317 	if (!value) {
    318 		log_info ("omapi_set_value (%.*s, NULL)",
    319 			  (int)name -> len, name -> value);
    320 	} else if (value -> type == omapi_datatype_int) {
    321 		log_info ("omapi_set_value (%.*s, %ld)",
    322 			  (int)name -> len, name -> value,
    323 			  (long)value -> u.integer);
    324 	} else if (value -> type == omapi_datatype_string) {
    325 		log_info ("omapi_set_value (%.*s, %.*s)",
    326 			  (int)name -> len, name -> value,
    327 			  (int)value -> u.buffer.len, value -> u.buffer.value);
    328 	} else if (value -> type == omapi_datatype_data) {
    329 		log_info ("omapi_set_value (%.*s, %ld %lx)",
    330 			  (int)name -> len, name -> value,
    331 			  (long)value -> u.buffer.len,
    332 			  (unsigned long)value -> u.buffer.value);
    333 	} else if (value -> type == omapi_datatype_object) {
    334 		log_info ("omapi_set_value (%.*s, %s)",
    335 			  (int)name -> len, name -> value,
    336 			  value -> u.object
    337 			  ? (value -> u.object -> type
    338 			     ? value -> u.object -> type -> name
    339 			     : "(unknown object)")
    340 			  : "(unknown object)");
    341 	}
    342 #endif
    343 
    344 	for (outer = h; outer -> outer; outer = outer -> outer)
    345 		;
    346 	if (outer -> type -> set_value)
    347 		status = (*(outer -> type -> set_value)) (outer,
    348 							  id, name, value);
    349 	else
    350 		status = ISC_R_NOTFOUND;
    351 #if defined (DEBUG_PROTOCOL)
    352 	log_info (" ==> %s", isc_result_totext (status));
    353 #endif
    354 	return status;
    355 }
    356 
    357 isc_result_t omapi_set_value_str (omapi_object_t *h,
    358 				  omapi_object_t *id,
    359 				  const char *name,
    360 				  omapi_typed_data_t *value)
    361 {
    362 	omapi_data_string_t *nds;
    363 	isc_result_t status;
    364 
    365 	nds = (omapi_data_string_t *)0;
    366 	status = omapi_data_string_new (&nds, strlen (name), MDL);
    367 	if (status != ISC_R_SUCCESS)
    368 		return status;
    369 	memcpy (nds -> value, name, strlen (name));
    370 
    371 	status = omapi_set_value (h, id, nds, value);
    372 	omapi_data_string_dereference (&nds, MDL);
    373 	return status;
    374 }
    375 
    376 isc_result_t omapi_set_boolean_value (omapi_object_t *h, omapi_object_t *id,
    377 				      const char *name, int value)
    378 {
    379 	isc_result_t status;
    380 	omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
    381 	omapi_data_string_t *n = (omapi_data_string_t *)0;
    382 
    383 	status = omapi_data_string_new (&n, strlen (name), MDL);
    384 	if (status != ISC_R_SUCCESS)
    385 		return status;
    386 	memcpy (n -> value, name, strlen (name));
    387 
    388 	status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
    389 	if (status != ISC_R_SUCCESS) {
    390 		omapi_data_string_dereference (&n, MDL);
    391 		return status;
    392 	}
    393 
    394 	status = omapi_set_value (h, id, n, tv);
    395 	omapi_data_string_dereference (&n, MDL);
    396 	omapi_typed_data_dereference (&tv, MDL);
    397 	return status;
    398 }
    399 
    400 isc_result_t omapi_set_int_value (omapi_object_t *h, omapi_object_t *id,
    401 				  const char *name, int value)
    402 {
    403 	isc_result_t status;
    404 	omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
    405 	omapi_data_string_t *n = (omapi_data_string_t *)0;
    406 
    407 	status = omapi_data_string_new (&n, strlen (name), MDL);
    408 	if (status != ISC_R_SUCCESS)
    409 		return status;
    410 	memcpy (n -> value, name, strlen (name));
    411 
    412 	status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
    413 	if (status != ISC_R_SUCCESS) {
    414 		omapi_data_string_dereference (&n, MDL);
    415 		return status;
    416 	}
    417 
    418 	status = omapi_set_value (h, id, n, tv);
    419 	omapi_data_string_dereference (&n, MDL);
    420 	omapi_typed_data_dereference (&tv, MDL);
    421 	return status;
    422 }
    423 
    424 isc_result_t omapi_set_object_value (omapi_object_t *h, omapi_object_t *id,
    425 				     const char *name, omapi_object_t *value)
    426 {
    427 	isc_result_t status;
    428 	omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
    429 	omapi_data_string_t *n = (omapi_data_string_t *)0;
    430 
    431 	status = omapi_data_string_new (&n, strlen (name), MDL);
    432 	if (status != ISC_R_SUCCESS)
    433 		return status;
    434 	memcpy (n -> value, name, strlen (name));
    435 
    436 	status = omapi_typed_data_new (MDL, &tv, omapi_datatype_object, value);
    437 	if (status != ISC_R_SUCCESS) {
    438 		omapi_data_string_dereference (&n, MDL);
    439 		return status;
    440 	}
    441 
    442 	status = omapi_set_value (h, id, n, tv);
    443 	omapi_data_string_dereference (&n, MDL);
    444 	omapi_typed_data_dereference (&tv, MDL);
    445 	return status;
    446 }
    447 
    448 isc_result_t omapi_set_string_value (omapi_object_t *h, omapi_object_t *id,
    449 				     const char *name, const char *value)
    450 {
    451 	isc_result_t status;
    452 	omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
    453 	omapi_data_string_t *n = (omapi_data_string_t *)0;
    454 
    455 	status = omapi_data_string_new (&n, strlen (name), MDL);
    456 	if (status != ISC_R_SUCCESS)
    457 		return status;
    458 	memcpy (n -> value, name, strlen (name));
    459 
    460 	status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value);
    461 	if (status != ISC_R_SUCCESS) {
    462 		omapi_data_string_dereference (&n, MDL);
    463 		return status;
    464 	}
    465 
    466 	status = omapi_set_value (h, id, n, tv);
    467 	omapi_data_string_dereference (&n, MDL);
    468 	omapi_typed_data_dereference (&tv, MDL);
    469 	return status;
    470 }
    471 
    472 isc_result_t omapi_get_value (omapi_object_t *h,
    473 			      omapi_object_t *id,
    474 			      omapi_data_string_t *name,
    475 			      omapi_value_t **value)
    476 {
    477 	omapi_object_t *outer;
    478 
    479 	for (outer = h; outer -> outer; outer = outer -> outer)
    480 		;
    481 	if (outer -> type -> get_value)
    482 		return (*(outer -> type -> get_value)) (outer,
    483 							id, name, value);
    484 	return ISC_R_NOTFOUND;
    485 }
    486 
    487 isc_result_t omapi_get_value_str (omapi_object_t *h,
    488 				  omapi_object_t *id,
    489 				  const char *name,
    490 				  omapi_value_t **value)
    491 {
    492 	omapi_object_t *outer;
    493 	omapi_data_string_t *nds;
    494 	isc_result_t status;
    495 
    496 	nds = (omapi_data_string_t *)0;
    497 	status = omapi_data_string_new (&nds, strlen (name), MDL);
    498 	if (status != ISC_R_SUCCESS)
    499 		return status;
    500 	memcpy (nds -> value, name, strlen (name));
    501 
    502 	for (outer = h; outer -> outer; outer = outer -> outer)
    503 		;
    504 	if (outer -> type -> get_value)
    505 		status = (*(outer -> type -> get_value)) (outer,
    506 							  id, nds, value);
    507 	else
    508 		status = ISC_R_NOTFOUND;
    509 	omapi_data_string_dereference (&nds, MDL);
    510 	return status;
    511 }
    512 
    513 isc_result_t omapi_stuff_values (omapi_object_t *c,
    514 				 omapi_object_t *id,
    515 				 omapi_object_t *o)
    516 {
    517 	omapi_object_t *outer;
    518 
    519 	for (outer = o; outer -> outer; outer = outer -> outer)
    520 		;
    521 	if (outer -> type -> stuff_values)
    522 		return (*(outer -> type -> stuff_values)) (c, id, outer);
    523 	return ISC_R_NOTFOUND;
    524 }
    525 
    526 isc_result_t omapi_object_create (omapi_object_t **obj, omapi_object_t *id,
    527 				  omapi_object_type_t *type)
    528 {
    529 	if (!type -> create)
    530 		return ISC_R_NOTIMPLEMENTED;
    531 	return (*(type -> create)) (obj, id);
    532 }
    533 
    534 isc_result_t omapi_object_update (omapi_object_t *obj, omapi_object_t *id,
    535 				  omapi_object_t *src, omapi_handle_t handle)
    536 {
    537 	omapi_generic_object_t *gsrc;
    538 	isc_result_t status;
    539 	int i;
    540 
    541 	if (!src)
    542 		return DHCP_R_INVALIDARG;
    543 	if (src -> type != omapi_type_generic)
    544 		return ISC_R_NOTIMPLEMENTED;
    545 	gsrc = (omapi_generic_object_t *)src;
    546 	for (i = 0; i < gsrc -> nvalues; i++) {
    547 		status = omapi_set_value (obj, id,
    548 					  gsrc -> values [i] -> name,
    549 					  gsrc -> values [i] -> value);
    550 		if (status != ISC_R_SUCCESS && status != DHCP_R_UNCHANGED)
    551 			return status;
    552 	}
    553 
    554 	/*
    555 	 * For now ignore the return value.  I'm not sure if we want to
    556 	 * generate an error if we can't set the handle value.  If we
    557 	 * do add a check we probably should allow unchanged and notfound
    558 	 */
    559 	if (handle)
    560 		(void) omapi_set_int_value (obj, id, "remote-handle", (int)handle);
    561 	status = omapi_signal (obj, "updated");
    562 	if (status != ISC_R_NOTFOUND)
    563 		return status;
    564 	return ISC_R_SUCCESS;
    565 }
    566 
    567 int omapi_data_string_cmp (omapi_data_string_t *s1, omapi_data_string_t *s2)
    568 {
    569 	unsigned len;
    570 	int rv;
    571 
    572 	if (s1 -> len > s2 -> len)
    573 		len = s2 -> len;
    574 	else
    575 		len = s1 -> len;
    576 	rv = memcmp (s1 -> value, s2 -> value, len);
    577 	if (rv)
    578 		return rv;
    579 	if (s1 -> len > s2 -> len)
    580 		return 1;
    581 	else if (s1 -> len < s2 -> len)
    582 		return -1;
    583 	return 0;
    584 }
    585 
    586 int omapi_ds_strcmp (omapi_data_string_t *s1, const char *s2)
    587 {
    588 	unsigned len, slen;
    589 	int rv;
    590 
    591 	slen = strlen (s2);
    592 	if (slen > s1 -> len)
    593 		len = s1 -> len;
    594 	else
    595 		len = slen;
    596 	rv = memcmp (s1 -> value, s2, len);
    597 	if (rv)
    598 		return rv;
    599 	if (s1 -> len > slen)
    600 		return 1;
    601 	else if (s1 -> len < slen)
    602 		return -1;
    603 	return 0;
    604 }
    605 
    606 int omapi_td_strcmp (omapi_typed_data_t *s1, const char *s2)
    607 {
    608 	unsigned len, slen;
    609 	int rv;
    610 
    611 	/* If the data type is not compatible, never equal. */
    612 	if (s1 -> type != omapi_datatype_data &&
    613 	    s1 -> type != omapi_datatype_string)
    614 		return -1;
    615 
    616 	slen = strlen (s2);
    617 	if (slen > s1 -> u.buffer.len)
    618 		len = s1 -> u.buffer.len;
    619 	else
    620 		len = slen;
    621 	rv = memcmp (s1 -> u.buffer.value, s2, len);
    622 	if (rv)
    623 		return rv;
    624 	if (s1 -> u.buffer.len > slen)
    625 		return 1;
    626 	else if (s1 -> u.buffer.len < slen)
    627 		return -1;
    628 	return 0;
    629 }
    630 
    631 int omapi_td_strcasecmp (omapi_typed_data_t *s1, const char *s2)
    632 {
    633 	unsigned len, slen;
    634 	int rv;
    635 
    636 	/* If the data type is not compatible, never equal. */
    637 	if (s1 -> type != omapi_datatype_data &&
    638 	    s1 -> type != omapi_datatype_string)
    639 		return -1;
    640 
    641 	slen = strlen (s2);
    642 	if (slen > s1 -> u.buffer.len)
    643 		len = s1 -> u.buffer.len;
    644 	else
    645 		len = slen;
    646 	rv = casecmp (s1 -> u.buffer.value, s2, len);
    647 	if (rv)
    648 		return rv;
    649 	if (s1 -> u.buffer.len > slen)
    650 		return 1;
    651 	else if (s1 -> u.buffer.len < slen)
    652 		return -1;
    653 	return 0;
    654 }
    655 
    656 isc_result_t omapi_make_value (omapi_value_t **vp,
    657 			       omapi_data_string_t *name,
    658 			       omapi_typed_data_t *value,
    659 			       const char *file, int line)
    660 {
    661 	isc_result_t status;
    662 
    663 	status = omapi_value_new (vp, file, line);
    664 	if (status != ISC_R_SUCCESS)
    665 		return status;
    666 
    667 	status = omapi_data_string_reference (&(*vp) -> name,
    668 					      name, file, line);
    669 	if (status != ISC_R_SUCCESS) {
    670 		omapi_value_dereference (vp, file, line);
    671 		return status;
    672 	}
    673 	if (value) {
    674 		status = omapi_typed_data_reference (&(*vp) -> value,
    675 						     value, file, line);
    676 		if (status != ISC_R_SUCCESS) {
    677 			omapi_value_dereference (vp, file, line);
    678 			return status;
    679 		}
    680 	}
    681 	return ISC_R_SUCCESS;
    682 }
    683 
    684 isc_result_t omapi_make_const_value (omapi_value_t **vp,
    685 				     omapi_data_string_t *name,
    686 				     const unsigned char *value,
    687 				     unsigned len,
    688 				     const char *file, int line)
    689 {
    690 	isc_result_t status;
    691 
    692 	status = omapi_value_new (vp, file, line);
    693 	if (status != ISC_R_SUCCESS)
    694 		return status;
    695 
    696 	status = omapi_data_string_reference (&(*vp) -> name,
    697 					      name, file, line);
    698 	if (status != ISC_R_SUCCESS) {
    699 		omapi_value_dereference (vp, file, line);
    700 		return status;
    701 	}
    702 	if (value) {
    703 		status = omapi_typed_data_new (file, line, &(*vp) -> value,
    704 					       omapi_datatype_data, len);
    705 		if (status != ISC_R_SUCCESS) {
    706 			omapi_value_dereference (vp, file, line);
    707 			return status;
    708 		}
    709 		memcpy ((*vp) -> value -> u.buffer.value, value, len);
    710 	}
    711 	return ISC_R_SUCCESS;
    712 }
    713 
    714 isc_result_t omapi_make_int_value (omapi_value_t **vp,
    715 				   omapi_data_string_t *name,
    716 				   int value, const char *file, int line)
    717 {
    718 	isc_result_t status;
    719 
    720 	status = omapi_value_new (vp, file, line);
    721 	if (status != ISC_R_SUCCESS)
    722 		return status;
    723 
    724 	status = omapi_data_string_reference (&(*vp) -> name,
    725 					      name, file, line);
    726 	if (status != ISC_R_SUCCESS) {
    727 		omapi_value_dereference (vp, file, line);
    728 		return status;
    729 	}
    730 	status = omapi_typed_data_new (file, line, &(*vp) -> value,
    731 				       omapi_datatype_int, value);
    732 	if (status != ISC_R_SUCCESS) {
    733 		omapi_value_dereference (vp, file, line);
    734 		return status;
    735 	}
    736 	return ISC_R_SUCCESS;
    737 }
    738 
    739 isc_result_t omapi_make_uint_value (omapi_value_t **vp,
    740 				    omapi_data_string_t *name,
    741 				    unsigned int value,
    742 				    const char *file, int line)
    743 {
    744 	return omapi_make_int_value (vp, name, (int)value, file, line);
    745 }
    746 
    747 isc_result_t omapi_make_object_value (omapi_value_t **vp,
    748 				      omapi_data_string_t *name,
    749 				      omapi_object_t *value,
    750 				      const char *file, int line)
    751 {
    752 	isc_result_t status;
    753 
    754 	status = omapi_value_new (vp, file, line);
    755 	if (status != ISC_R_SUCCESS)
    756 		return status;
    757 
    758 	status = omapi_data_string_reference (&(*vp) -> name,
    759                                               name, file, line);
    760 	if (status != ISC_R_SUCCESS) {
    761 		omapi_value_dereference (vp, file, line);
    762 		return status;
    763 	}
    764 
    765 	if (value) {
    766 		status = omapi_typed_data_new (file, line, &(*vp) -> value,
    767 					       omapi_datatype_object, value);
    768 		if (status != ISC_R_SUCCESS) {
    769 			omapi_value_dereference (vp, file, line);
    770 			return status;
    771 		}
    772 	}
    773 
    774 	return ISC_R_SUCCESS;
    775 }
    776 
    777 isc_result_t omapi_make_handle_value (omapi_value_t **vp,
    778 				      omapi_data_string_t *name,
    779 				      omapi_object_t *value,
    780 				      const char *file, int line)
    781 {
    782 	isc_result_t status;
    783 
    784 	status = omapi_value_new (vp, file, line);
    785 	if (status != ISC_R_SUCCESS)
    786 		return status;
    787 
    788 	status = omapi_data_string_reference (&(*vp) -> name,
    789 					      name, file, line);
    790 	if (status != ISC_R_SUCCESS) {
    791 		omapi_value_dereference (vp, file, line);
    792 		return status;
    793 	}
    794 	if (value) {
    795 		status = omapi_typed_data_new (file, line, &(*vp) -> value,
    796 					       omapi_datatype_int);
    797 		if (status != ISC_R_SUCCESS) {
    798 			omapi_value_dereference (vp, file, line);
    799 			return status;
    800 		}
    801 		status = (omapi_object_handle
    802 			  ((omapi_handle_t *)&(*vp) -> value -> u.integer,
    803 			   value));
    804 		if (status != ISC_R_SUCCESS) {
    805 			omapi_value_dereference (vp, file, line);
    806 			return status;
    807 		}
    808 	}
    809 	return ISC_R_SUCCESS;
    810 }
    811 
    812 isc_result_t omapi_make_string_value (omapi_value_t **vp,
    813 				      omapi_data_string_t *name,
    814 				      const char *value,
    815 				      const char *file, int line)
    816 {
    817 	isc_result_t status;
    818 
    819 	status = omapi_value_new (vp, file, line);
    820 	if (status != ISC_R_SUCCESS)
    821 		return status;
    822 
    823 	status = omapi_data_string_reference (&(*vp) -> name,
    824 					      name, file, line);
    825 	if (status != ISC_R_SUCCESS) {
    826 		omapi_value_dereference (vp, file, line);
    827 		return status;
    828 	}
    829 	if (value) {
    830 		status = omapi_typed_data_new (file, line, &(*vp) -> value,
    831 					       omapi_datatype_string, value);
    832 		if (status != ISC_R_SUCCESS) {
    833 			omapi_value_dereference (vp, file, line);
    834 			return status;
    835 		}
    836 	}
    837 	return ISC_R_SUCCESS;
    838 }
    839 
    840 isc_result_t omapi_get_int_value (unsigned long *v, omapi_typed_data_t *t)
    841 {
    842 	u_int32_t rv;
    843 
    844 	if (t -> type == omapi_datatype_int) {
    845 		*v = t -> u.integer;
    846 		return ISC_R_SUCCESS;
    847 	} else if (t -> type == omapi_datatype_string ||
    848 		   t -> type == omapi_datatype_data) {
    849 		if (t -> u.buffer.len != sizeof (rv))
    850 			return DHCP_R_INVALIDARG;
    851 		memcpy (&rv, t -> u.buffer.value, sizeof rv);
    852 		*v = ntohl (rv);
    853 		return ISC_R_SUCCESS;
    854 	}
    855 	return DHCP_R_INVALIDARG;
    856 }
    857