xref: /minix/external/bsd/dhcp/dist/server/omapi.c (revision bb9622b5)
1 /*	$NetBSD: omapi.c,v 1.2 2014/07/12 12:09:38 spz Exp $	*/
2 /* omapi.c
3 
4    OMAPI object interfaces for the DHCP server. */
5 
6 /*
7  * Copyright (c) 2012-2014 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
9  * Copyright (c) 1999-2003 by Internet Software Consortium
10  *
11  * Permission to use, copy, modify, and distribute this software for any
12  * purpose with or without fee is hereby granted, provided that the above
13  * copyright notice and this permission notice appear in all copies.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
18  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  *   Internet Systems Consortium, Inc.
24  *   950 Charter Street
25  *   Redwood City, CA 94063
26  *   <info@isc.org>
27  *   https://www.isc.org/
28  *
29  */
30 
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: omapi.c,v 1.2 2014/07/12 12:09:38 spz Exp $");
33 
34 /* Many, many thanks to Brian Murrell and BCtel for this code - BCtel
35    provided the funding that resulted in this code and the entire
36    OMAPI support library being written, and Brian helped brainstorm
37    and refine the requirements.  To the extent that this code is
38    useful, you have Brian and BCtel to thank.  Any limitations in the
39    code are a result of mistakes on my part.  -- Ted Lemon */
40 
41 #include "dhcpd.h"
42 #include <omapip/omapip_p.h>
43 
44 static isc_result_t class_lookup (omapi_object_t **,
45 				  omapi_object_t *, omapi_object_t *,
46 				  omapi_object_type_t *);
47 
48 omapi_object_type_t *dhcp_type_lease;
49 omapi_object_type_t *dhcp_type_pool;
50 omapi_object_type_t *dhcp_type_class;
51 omapi_object_type_t *dhcp_type_subclass;
52 omapi_object_type_t *dhcp_type_host;
53 #if defined (FAILOVER_PROTOCOL)
54 omapi_object_type_t *dhcp_type_failover_state;
55 omapi_object_type_t *dhcp_type_failover_link;
56 omapi_object_type_t *dhcp_type_failover_listener;
57 #endif
58 
59 void dhcp_db_objects_setup ()
60 {
61 	isc_result_t status;
62 
63 	status = omapi_object_type_register (&dhcp_type_lease,
64 					     "lease",
65 					     dhcp_lease_set_value,
66 					     dhcp_lease_get_value,
67 					     dhcp_lease_destroy,
68 					     dhcp_lease_signal_handler,
69 					     dhcp_lease_stuff_values,
70 					     dhcp_lease_lookup,
71 					     dhcp_lease_create,
72 					     dhcp_lease_remove,
73 #if defined (COMPACT_LEASES)
74 					     dhcp_lease_free,
75 					     dhcp_lease_get,
76 #else
77 					     0, 0,
78 #endif
79 					     0,
80 					     sizeof (struct lease),
81 					     0, RC_LEASE);
82 	if (status != ISC_R_SUCCESS)
83 		log_fatal ("Can't register lease object type: %s",
84 			   isc_result_totext (status));
85 
86 	status = omapi_object_type_register (&dhcp_type_class,
87 					     "class",
88 					     dhcp_class_set_value,
89 					     dhcp_class_get_value,
90 					     dhcp_class_destroy,
91 					     dhcp_class_signal_handler,
92 					     dhcp_class_stuff_values,
93 					     dhcp_class_lookup,
94 					     dhcp_class_create,
95 					     dhcp_class_remove, 0, 0, 0,
96 					     sizeof (struct class), 0,
97 					     RC_MISC);
98 	if (status != ISC_R_SUCCESS)
99 		log_fatal ("Can't register class object type: %s",
100 			   isc_result_totext (status));
101 
102 	status = omapi_object_type_register (&dhcp_type_subclass,
103 					     "subclass",
104 					     dhcp_subclass_set_value,
105 					     dhcp_subclass_get_value,
106 					     dhcp_class_destroy,
107 					     dhcp_subclass_signal_handler,
108 					     dhcp_subclass_stuff_values,
109 					     dhcp_subclass_lookup,
110 					     dhcp_subclass_create,
111 					     dhcp_subclass_remove, 0, 0, 0,
112 					     sizeof (struct class), 0, RC_MISC);
113 	if (status != ISC_R_SUCCESS)
114 		log_fatal ("Can't register subclass object type: %s",
115 			   isc_result_totext (status));
116 
117 	status = omapi_object_type_register (&dhcp_type_pool,
118 					     "pool",
119 					     dhcp_pool_set_value,
120 					     dhcp_pool_get_value,
121 					     dhcp_pool_destroy,
122 					     dhcp_pool_signal_handler,
123 					     dhcp_pool_stuff_values,
124 					     dhcp_pool_lookup,
125 					     dhcp_pool_create,
126 					     dhcp_pool_remove, 0, 0, 0,
127 					     sizeof (struct pool), 0, RC_MISC);
128 
129 	if (status != ISC_R_SUCCESS)
130 		log_fatal ("Can't register pool object type: %s",
131 			   isc_result_totext (status));
132 
133 	status = omapi_object_type_register (&dhcp_type_host,
134 					     "host",
135 					     dhcp_host_set_value,
136 					     dhcp_host_get_value,
137 					     dhcp_host_destroy,
138 					     dhcp_host_signal_handler,
139 					     dhcp_host_stuff_values,
140 					     dhcp_host_lookup,
141 					     dhcp_host_create,
142 					     dhcp_host_remove, 0, 0, 0,
143 					     sizeof (struct host_decl),
144 					     0, RC_MISC);
145 
146 	if (status != ISC_R_SUCCESS)
147 		log_fatal ("Can't register host object type: %s",
148 			   isc_result_totext (status));
149 
150 #if defined (FAILOVER_PROTOCOL)
151 	status = omapi_object_type_register (&dhcp_type_failover_state,
152 					     "failover-state",
153 					     dhcp_failover_state_set_value,
154 					     dhcp_failover_state_get_value,
155 					     dhcp_failover_state_destroy,
156 					     dhcp_failover_state_signal,
157 					     dhcp_failover_state_stuff,
158 					     dhcp_failover_state_lookup,
159 					     dhcp_failover_state_create,
160 					     dhcp_failover_state_remove,
161 					     0, 0, 0,
162 					     sizeof (dhcp_failover_state_t),
163 					     0, RC_MISC);
164 
165 	if (status != ISC_R_SUCCESS)
166 		log_fatal ("Can't register failover state object type: %s",
167 			   isc_result_totext (status));
168 
169 	status = omapi_object_type_register (&dhcp_type_failover_link,
170 					     "failover-link",
171 					     dhcp_failover_link_set_value,
172 					     dhcp_failover_link_get_value,
173 					     dhcp_failover_link_destroy,
174 					     dhcp_failover_link_signal,
175 					     dhcp_failover_link_stuff_values,
176 					     0, 0, 0, 0, 0, 0,
177 					     sizeof (dhcp_failover_link_t), 0,
178 					     RC_MISC);
179 
180 	if (status != ISC_R_SUCCESS)
181 		log_fatal ("Can't register failover link object type: %s",
182 			   isc_result_totext (status));
183 
184 	status = omapi_object_type_register (&dhcp_type_failover_listener,
185 					     "failover-listener",
186 					     dhcp_failover_listener_set_value,
187 					     dhcp_failover_listener_get_value,
188 					     dhcp_failover_listener_destroy,
189 					     dhcp_failover_listener_signal,
190 					     dhcp_failover_listener_stuff,
191 					     0, 0, 0, 0, 0, 0,
192 					     sizeof
193 					     (dhcp_failover_listener_t), 0,
194 					     RC_MISC);
195 
196 	if (status != ISC_R_SUCCESS)
197 		log_fatal ("Can't register failover listener object type: %s",
198 			   isc_result_totext (status));
199 #endif /* FAILOVER_PROTOCOL */
200 }
201 
202 isc_result_t dhcp_lease_set_value  (omapi_object_t *h,
203 				    omapi_object_t *id,
204 				    omapi_data_string_t *name,
205 				    omapi_typed_data_t *value)
206 {
207 	struct lease *lease;
208 	isc_result_t status;
209 
210 	if (h -> type != dhcp_type_lease)
211 		return DHCP_R_INVALIDARG;
212 	lease = (struct lease *)h;
213 
214 	/* We're skipping a lot of things it might be interesting to
215 	   set - for now, we just make it possible to whack the state. */
216 	if (!omapi_ds_strcmp (name, "state")) {
217 	    unsigned long bar;
218 	    const char *ols, *nls;
219 	    status = omapi_get_int_value (&bar, value);
220 	    if (status != ISC_R_SUCCESS)
221 		return status;
222 
223 	    if (bar < 1 || bar > FTS_LAST)
224 		return DHCP_R_INVALIDARG;
225 	    nls = binding_state_names [bar - 1];
226 	    if (lease -> binding_state >= 1 &&
227 		lease -> binding_state <= FTS_LAST)
228 		ols = binding_state_names [lease -> binding_state - 1];
229 	    else
230 		ols = "unknown state";
231 
232 	    if (lease -> binding_state != bar) {
233 		lease -> next_binding_state = bar;
234 		if (supersede_lease (lease, 0, 1, 1, 1)) {
235 			log_info ("lease %s state changed from %s to %s",
236 				  piaddr(lease->ip_addr), ols, nls);
237 			return ISC_R_SUCCESS;
238 		}
239 		log_info ("lease %s state change from %s to %s failed.",
240 			  piaddr (lease -> ip_addr), ols, nls);
241 		return ISC_R_IOERROR;
242 	    }
243 	    return DHCP_R_UNCHANGED;
244 	} else if (!omapi_ds_strcmp (name, "ip-address")) {
245 	    return ISC_R_NOPERM;
246 	} else if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
247 	    return DHCP_R_UNCHANGED;	/* XXX take change. */
248 	} else if (!omapi_ds_strcmp (name, "hostname")) {
249 	    return DHCP_R_UNCHANGED;	/* XXX take change. */
250 	} else if (!omapi_ds_strcmp (name, "client-hostname")) {
251 	    return DHCP_R_UNCHANGED;	/* XXX take change. */
252 	} else if (!omapi_ds_strcmp (name, "host")) {
253 	    return DHCP_R_UNCHANGED;	/* XXX take change. */
254 	} else if (!omapi_ds_strcmp (name, "subnet")) {
255 	    return DHCP_R_INVALIDARG;
256 	} else if (!omapi_ds_strcmp (name, "pool")) {
257 	    return ISC_R_NOPERM;
258 	} else if (!omapi_ds_strcmp (name, "starts")) {
259 	    return ISC_R_NOPERM;
260 	} else if (!omapi_ds_strcmp (name, "ends")) {
261 	    unsigned long lease_end, old_lease_end;
262 	    status = omapi_get_int_value (&lease_end, value);
263 	    if (status != ISC_R_SUCCESS)
264 		return status;
265 	    old_lease_end = lease->ends;
266 	    lease->ends = lease_end;
267 	    if (supersede_lease (lease, 0, 1, 1, 1)) {
268 		log_info ("lease %s end changed from %lu to %lu",
269 			  piaddr(lease->ip_addr), old_lease_end, lease_end);
270 		return ISC_R_SUCCESS;
271 	    }
272 	    log_info ("lease %s end change from %lu to %lu failed",
273 		      piaddr(lease->ip_addr), old_lease_end, lease_end);
274 	    return ISC_R_IOERROR;
275 	} else if (!omapi_ds_strcmp(name, "flags")) {
276 	    u_int8_t oldflags;
277 
278 	    if (value->type != omapi_datatype_data)
279 		return DHCP_R_INVALIDARG;
280 
281 	    oldflags = lease->flags;
282 	    lease->flags = (value->u.buffer.value[0] & EPHEMERAL_FLAGS) |
283 			   (lease->flags & ~EPHEMERAL_FLAGS);
284 	    if(oldflags == lease->flags)
285 		return ISC_R_SUCCESS;
286 	    if (!supersede_lease(lease, NULL, 1, 1, 1)) {
287 		log_error("Failed to update flags for lease %s.",
288 			  piaddr(lease->ip_addr));
289 		return ISC_R_IOERROR;
290 	    }
291 	    return ISC_R_SUCCESS;
292 	} else if (!omapi_ds_strcmp (name, "billing-class")) {
293 	    return DHCP_R_UNCHANGED;	/* XXX carefully allow change. */
294 	} else if (!omapi_ds_strcmp (name, "hardware-address")) {
295 	    return DHCP_R_UNCHANGED;	/* XXX take change. */
296 	} else if (!omapi_ds_strcmp (name, "hardware-type")) {
297 	    return DHCP_R_UNCHANGED;	/* XXX take change. */
298 	} else if (lease -> scope) {
299 	    status = binding_scope_set_value (lease -> scope, 0, name, value);
300 	    if (status == ISC_R_SUCCESS) {
301 		    if (write_lease (lease) && commit_leases ())
302 			    return ISC_R_SUCCESS;
303 		    return ISC_R_IOERROR;
304 	    }
305 	}
306 
307 	/* Try to find some inner object that can take the value. */
308 	if (h -> inner && h -> inner -> type -> set_value) {
309 		status = ((*(h -> inner -> type -> set_value))
310 			  (h -> inner, id, name, value));
311 		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
312 			return status;
313 	}
314 
315 	if (!lease -> scope) {
316 		if (!binding_scope_allocate (&lease -> scope, MDL))
317 			return ISC_R_NOMEMORY;
318 	}
319 	status = binding_scope_set_value (lease -> scope, 1, name, value);
320 	if (status != ISC_R_SUCCESS)
321 		return status;
322 
323 	if (write_lease (lease) && commit_leases ())
324 		return ISC_R_SUCCESS;
325 	return ISC_R_IOERROR;
326 }
327 
328 
329 isc_result_t dhcp_lease_get_value (omapi_object_t *h, omapi_object_t *id,
330 				   omapi_data_string_t *name,
331 				   omapi_value_t **value)
332 {
333 	struct lease *lease;
334 	isc_result_t status;
335 
336 	if (h -> type != dhcp_type_lease)
337 		return DHCP_R_INVALIDARG;
338 	lease = (struct lease *)h;
339 
340 	if (!omapi_ds_strcmp (name, "state"))
341 		return omapi_make_int_value (value, name,
342 					     (int)lease -> binding_state, MDL);
343 	else if (!omapi_ds_strcmp (name, "ip-address"))
344 		return omapi_make_const_value (value, name,
345 					       lease -> ip_addr.iabuf,
346 					       lease -> ip_addr.len, MDL);
347 	else if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
348 		return omapi_make_const_value (value, name,
349 					       lease -> uid,
350 					       lease -> uid_len, MDL);
351 	} else if (!omapi_ds_strcmp (name, "client-hostname")) {
352 		if (lease -> client_hostname)
353 			return omapi_make_string_value
354 				(value, name, lease -> client_hostname, MDL);
355 		return ISC_R_NOTFOUND;
356 	} else if (!omapi_ds_strcmp (name, "host")) {
357 		if (lease -> host)
358 			return omapi_make_handle_value
359 				(value, name,
360 				 ((omapi_object_t *)lease -> host), MDL);
361 	} else if (!omapi_ds_strcmp (name, "subnet"))
362 		return omapi_make_handle_value (value, name,
363 						((omapi_object_t *)
364 						 lease -> subnet), MDL);
365 	else if (!omapi_ds_strcmp (name, "pool"))
366 		return omapi_make_handle_value (value, name,
367 						((omapi_object_t *)
368 						 lease -> pool), MDL);
369 	else if (!omapi_ds_strcmp (name, "billing-class")) {
370 		if (lease -> billing_class)
371 			return omapi_make_handle_value
372 				(value, name,
373 				 ((omapi_object_t *)lease -> billing_class),
374 				 MDL);
375 		return ISC_R_NOTFOUND;
376 	} else if (!omapi_ds_strcmp (name, "hardware-address")) {
377 		if (lease -> hardware_addr.hlen)
378 			return omapi_make_const_value
379 				(value, name, &lease -> hardware_addr.hbuf [1],
380 				 (unsigned)(lease -> hardware_addr.hlen - 1),
381 				 MDL);
382 		return ISC_R_NOTFOUND;
383 	} else if (!omapi_ds_strcmp (name, "hardware-type")) {
384 		if (lease -> hardware_addr.hlen)
385 			return omapi_make_int_value
386 				(value, name, lease -> hardware_addr.hbuf [0],
387 				 MDL);
388 		return ISC_R_NOTFOUND;
389 	} else if (lease -> scope) {
390 		status = binding_scope_get_value (value, lease -> scope, name);
391 		if (status != ISC_R_NOTFOUND)
392 			return status;
393 	}
394 
395 	/* Try to find some inner object that can take the value. */
396 	if (h -> inner && h -> inner -> type -> get_value) {
397 		status = ((*(h -> inner -> type -> get_value))
398 			  (h -> inner, id, name, value));
399 		if (status == ISC_R_SUCCESS)
400 			return status;
401 	}
402 	return DHCP_R_UNKNOWNATTRIBUTE;
403 }
404 
405 isc_result_t dhcp_lease_destroy (omapi_object_t *h, const char *file, int line)
406 {
407 	struct lease *lease;
408 
409 	if (h->type != dhcp_type_lease)
410 		return DHCP_R_INVALIDARG;
411 	lease = (struct lease *)h;
412 
413 	if (lease-> uid)
414 		uid_hash_delete (lease);
415 	hw_hash_delete (lease);
416 
417 	if (lease->on_star.on_release)
418 		executable_statement_dereference (&lease->on_star.on_release,
419 						  file, line);
420 	if (lease->on_star.on_expiry)
421 		executable_statement_dereference (&lease->on_star.on_expiry,
422 						  file, line);
423 	if (lease->on_star.on_commit)
424 		executable_statement_dereference (&lease->on_star.on_commit,
425 						  file, line);
426 	if (lease->scope)
427 		binding_scope_dereference (&lease->scope, file, line);
428 
429 	if (lease->agent_options)
430 		option_chain_head_dereference (&lease->agent_options,
431 					       file, line);
432 	if (lease->uid && lease->uid != lease->uid_buf) {
433 		dfree (lease->uid, MDL);
434 		lease->uid = &lease->uid_buf [0];
435 		lease->uid_len = 0;
436 	}
437 
438 	if (lease->client_hostname) {
439 		dfree (lease->client_hostname, MDL);
440 		lease->client_hostname = (char *)0;
441 	}
442 
443 	if (lease->host)
444 		host_dereference (&lease->host, file, line);
445 	if (lease->subnet)
446 		subnet_dereference (&lease->subnet, file, line);
447 	if (lease->pool)
448 		pool_dereference (&lease->pool, file, line);
449 
450 	if (lease->state) {
451 		free_lease_state (lease->state, file, line);
452 		lease->state = (struct lease_state *)0;
453 
454 		cancel_timeout (lease_ping_timeout, lease);
455 		--outstanding_pings; /* XXX */
456 	}
457 
458 	if (lease->billing_class)
459 		class_dereference
460 			(&lease->billing_class, file, line);
461 
462 #if defined (DEBUG_MEMORY_LEAKAGE) || \
463 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
464 	/* XXX we should never be destroying a lease with a next
465 	   XXX pointer except on exit... */
466 	if (lease->next)
467 		lease_dereference (&lease->next, file, line);
468 	if (lease->n_hw)
469 		lease_dereference (&lease->n_hw, file, line);
470 	if (lease->n_uid)
471 		lease_dereference (&lease->n_uid, file, line);
472 	if (lease->next_pending)
473 		lease_dereference (&lease->next_pending, file, line);
474 #endif
475 
476 	return ISC_R_SUCCESS;
477 }
478 
479 isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
480 					const char *name, va_list ap)
481 {
482 	/* h should point to (struct lease *) */
483 	isc_result_t status;
484 
485 	if (h -> type != dhcp_type_lease)
486 		return DHCP_R_INVALIDARG;
487 
488 	if (!strcmp (name, "updated"))
489 		return ISC_R_SUCCESS;
490 
491 	/* Try to find some inner object that can take the value. */
492 	if (h -> inner && h -> inner -> type -> signal_handler) {
493 		status = ((*(h -> inner -> type -> signal_handler))
494 			  (h -> inner, name, ap));
495 		if (status == ISC_R_SUCCESS)
496 			return status;
497 	}
498 	return ISC_R_NOTFOUND;
499 }
500 
501 isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
502 				      omapi_object_t *id,
503 				      omapi_object_t *h)
504 {
505 	u_int32_t bouncer;
506 	struct lease *lease;
507 	isc_result_t status;
508 	u_int8_t flagbuf;
509 
510 	if (h -> type != dhcp_type_lease)
511 		return DHCP_R_INVALIDARG;
512 	lease = (struct lease *)h;
513 
514 	/* Write out all the values. */
515 
516 	status = omapi_connection_put_named_uint32(c, "state",
517 						   lease->binding_state);
518 	if (status != ISC_R_SUCCESS)
519 		return (status);
520 
521 	status = omapi_connection_put_name (c, "ip-address");
522 	if (status != ISC_R_SUCCESS)
523 		return status;
524 	status = omapi_connection_put_uint32 (c, lease -> ip_addr.len);
525 	if (status != ISC_R_SUCCESS)
526 		return status;
527 	status = omapi_connection_copyin (c, lease -> ip_addr.iabuf,
528 					  lease -> ip_addr.len);
529 	if (status != ISC_R_SUCCESS)
530 		return status;
531 
532 	if (lease -> uid_len) {
533 		status = omapi_connection_put_name (c,
534 						    "dhcp-client-identifier");
535 		if (status != ISC_R_SUCCESS)
536 			return status;
537 		status = omapi_connection_put_uint32 (c, lease -> uid_len);
538 		if (status != ISC_R_SUCCESS)
539 			return status;
540 		if (lease -> uid_len) {
541 			status = omapi_connection_copyin (c, lease -> uid,
542 							  lease -> uid_len);
543 			if (status != ISC_R_SUCCESS)
544 				return status;
545 		}
546 	}
547 
548 	if (lease -> client_hostname) {
549 		status = omapi_connection_put_name (c, "client-hostname");
550 		if (status != ISC_R_SUCCESS)
551 			return status;
552 		status =
553 			omapi_connection_put_string (c,
554 						     lease -> client_hostname);
555 		if (status != ISC_R_SUCCESS)
556 			return status;
557 	}
558 
559 	if (lease -> host) {
560 		status = omapi_connection_put_name (c, "host");
561 		if (status != ISC_R_SUCCESS)
562 			return status;
563 		status = omapi_connection_put_handle (c,
564 						      (omapi_object_t *)
565 						      lease -> host);
566 		if (status != ISC_R_SUCCESS)
567 			return status;
568 	}
569 
570 	status = omapi_connection_put_name (c, "subnet");
571 	if (status != ISC_R_SUCCESS)
572 		return status;
573 	status = omapi_connection_put_handle
574 		(c, (omapi_object_t *)lease -> subnet);
575 	if (status != ISC_R_SUCCESS)
576 		return status;
577 
578 	status = omapi_connection_put_name (c, "pool");
579 	if (status != ISC_R_SUCCESS)
580 		return status;
581 	status = omapi_connection_put_handle (c,
582 					      (omapi_object_t *)lease -> pool);
583 	if (status != ISC_R_SUCCESS)
584 		return status;
585 
586 	if (lease -> billing_class) {
587 		status = omapi_connection_put_name (c, "billing-class");
588 		if (status != ISC_R_SUCCESS)
589 			return status;
590 		status = omapi_connection_put_handle
591 			(c, (omapi_object_t *)lease -> billing_class);
592 		if (status != ISC_R_SUCCESS)
593 			return status;
594 	}
595 
596 	if (lease -> hardware_addr.hlen) {
597 		status = omapi_connection_put_name (c, "hardware-address");
598 		if (status != ISC_R_SUCCESS)
599 			return status;
600 		status = (omapi_connection_put_uint32
601 			  (c,
602 			   (unsigned long)(lease -> hardware_addr.hlen - 1)));
603 		if (status != ISC_R_SUCCESS)
604 			return status;
605 		status = (omapi_connection_copyin
606 			  (c, &lease -> hardware_addr.hbuf [1],
607 			   (unsigned long)(lease -> hardware_addr.hlen - 1)));
608 
609 		if (status != ISC_R_SUCCESS)
610 			return status;
611 
612 		status = omapi_connection_put_named_uint32(c, "hardware-type",
613 						lease->hardware_addr.hbuf[0]);
614 		if (status != ISC_R_SUCCESS)
615 			return (status);
616 	}
617 
618 	/* TIME values may be 64-bit, depending on system architecture.
619 	 * OMAPI must be system independent, both in terms of transmitting
620 	 * bytes on the wire in network byte order, and in terms of being
621 	 * readable and usable by both systems.
622 	 *
623 	 * XXX: In a future feature release, a put_int64() should be made
624 	 * to exist, and perhaps a put_time() wrapper that selects which
625 	 * to use based upon sizeof(TIME).  In the meantime, use existing,
626 	 * 32-bit, code.
627 	 */
628 	bouncer = (u_int32_t)lease->ends;
629 	status = omapi_connection_put_named_uint32(c, "ends", bouncer);
630 	if (status != ISC_R_SUCCESS)
631 		return (status);
632 
633 	bouncer = (u_int32_t)lease->starts;
634 	status = omapi_connection_put_named_uint32(c, "starts", bouncer);
635 	if (status != ISC_R_SUCCESS)
636 		return (status);
637 
638 	bouncer = (u_int32_t)lease->tstp;
639 	status = omapi_connection_put_named_uint32(c, "tstp", bouncer);
640 	if (status != ISC_R_SUCCESS)
641 		return (status);
642 
643 	bouncer = (u_int32_t)lease->tsfp;
644 	status = omapi_connection_put_named_uint32(c, "tsfp", bouncer);
645 	if (status != ISC_R_SUCCESS)
646 		return status;
647 
648 	bouncer = (u_int32_t)lease->atsfp;
649 	status = omapi_connection_put_named_uint32(c, "atsfp", bouncer);
650 	if (status != ISC_R_SUCCESS)
651 		return status;
652 
653 	bouncer = (u_int32_t)lease->cltt;
654 	status = omapi_connection_put_named_uint32(c, "cltt", bouncer);
655 	if (status != ISC_R_SUCCESS)
656 		return status;
657 
658 	status = omapi_connection_put_name (c, "flags");
659 	if (status != ISC_R_SUCCESS)
660 		return status;
661 	status = omapi_connection_put_uint32(c, sizeof(flagbuf));
662 	if (status != ISC_R_SUCCESS)
663 		return status;
664 	flagbuf = lease->flags & EPHEMERAL_FLAGS;
665 	status = omapi_connection_copyin(c, &flagbuf, sizeof(flagbuf));
666 	if (status != ISC_R_SUCCESS)
667 		return status;
668 
669 	if (lease -> scope) {
670 		status = binding_scope_stuff_values (c, lease -> scope);
671 		if (status != ISC_R_SUCCESS)
672 			return status;
673 	}
674 
675 	/* Write out the inner object, if any. */
676 	if (h -> inner && h -> inner -> type -> stuff_values) {
677 		status = ((*(h -> inner -> type -> stuff_values))
678 			  (c, id, h -> inner));
679 		if (status == ISC_R_SUCCESS)
680 			return status;
681 	}
682 
683 	return ISC_R_SUCCESS;
684 }
685 
686 isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
687 				omapi_object_t *id, omapi_object_t *ref)
688 {
689 	omapi_value_t *tv = (omapi_value_t *)0;
690 	isc_result_t status;
691 	struct lease *lease;
692 
693 	if (!ref)
694 		return DHCP_R_NOKEYS;
695 
696 	/* First see if we were sent a handle. */
697 	status = omapi_get_value_str (ref, id, "handle", &tv);
698 	if (status == ISC_R_SUCCESS) {
699 		status = omapi_handle_td_lookup (lp, tv -> value);
700 
701 		omapi_value_dereference (&tv, MDL);
702 		if (status != ISC_R_SUCCESS)
703 			return status;
704 
705 		/* Don't return the object if the type is wrong. */
706 		if ((*lp) -> type != dhcp_type_lease) {
707 			omapi_object_dereference (lp, MDL);
708 			return DHCP_R_INVALIDARG;
709 		}
710 	}
711 
712 	/* Now look for an IP address. */
713 	status = omapi_get_value_str (ref, id, "ip-address", &tv);
714 	if (status == ISC_R_SUCCESS) {
715 		lease = (struct lease *)0;
716 		lease_ip_hash_lookup(&lease, lease_ip_addr_hash,
717 				     tv->value->u.buffer.value,
718 				     tv->value->u.buffer.len, MDL);
719 
720 		omapi_value_dereference (&tv, MDL);
721 
722 		/* If we already have a lease, and it's not the same one,
723 		   then the query was invalid. */
724 		if (*lp && *lp != (omapi_object_t *)lease) {
725 			omapi_object_dereference (lp, MDL);
726 			lease_dereference (&lease, MDL);
727 			return DHCP_R_KEYCONFLICT;
728 		} else if (!lease) {
729 			if (*lp)
730 				omapi_object_dereference (lp, MDL);
731 			return ISC_R_NOTFOUND;
732 		} else if (!*lp) {
733 			/* XXX fix so that hash lookup itself creates
734 			   XXX the reference. */
735 			omapi_object_reference (lp,
736 						(omapi_object_t *)lease, MDL);
737 			lease_dereference (&lease, MDL);
738 		}
739 	}
740 
741 	/* Now look for a client identifier. */
742 	status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
743 	if (status == ISC_R_SUCCESS) {
744 		lease = (struct lease *)0;
745 		lease_id_hash_lookup(&lease, lease_uid_hash,
746 				     tv->value->u.buffer.value,
747 				     tv->value->u.buffer.len, MDL);
748 		omapi_value_dereference (&tv, MDL);
749 
750 		if (*lp && *lp != (omapi_object_t *)lease) {
751 			omapi_object_dereference (lp, MDL);
752 			lease_dereference (&lease, MDL);
753 			return DHCP_R_KEYCONFLICT;
754 		} else if (!lease) {
755 			if (*lp)
756 			    omapi_object_dereference (lp, MDL);
757 			return ISC_R_NOTFOUND;
758 		} else if (lease -> n_uid) {
759 			if (*lp)
760 			    omapi_object_dereference (lp, MDL);
761 			return DHCP_R_MULTIPLE;
762 		} else if (!*lp) {
763 			/* XXX fix so that hash lookup itself creates
764 			   XXX the reference. */
765 			omapi_object_reference (lp,
766 						(omapi_object_t *)lease, MDL);
767 			lease_dereference (&lease, MDL);
768 		}
769 	}
770 
771 	/* Now look for a hardware address. */
772 	status = omapi_get_value_str (ref, id, "hardware-address", &tv);
773 	if (status == ISC_R_SUCCESS) {
774 		unsigned char *haddr;
775 		unsigned int len;
776 
777 		len = tv -> value -> u.buffer.len + 1;
778 		haddr = dmalloc (len, MDL);
779 		if (!haddr) {
780 			omapi_value_dereference (&tv, MDL);
781 			return ISC_R_NOMEMORY;
782 		}
783 
784 		memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
785 		omapi_value_dereference (&tv, MDL);
786 
787 		status = omapi_get_value_str (ref, id, "hardware-type", &tv);
788 		if (status == ISC_R_SUCCESS) {
789 			if (tv -> value -> type == omapi_datatype_data) {
790 				if ((tv -> value -> u.buffer.len != 4) ||
791 				    (tv -> value -> u.buffer.value[0] != 0) ||
792 				    (tv -> value -> u.buffer.value[1] != 0) ||
793 				    (tv -> value -> u.buffer.value[2] != 0)) {
794 					omapi_value_dereference (&tv, MDL);
795 					dfree (haddr, MDL);
796 					return DHCP_R_INVALIDARG;
797 				}
798 
799 				haddr[0] = tv -> value -> u.buffer.value[3];
800 			} else if (tv -> value -> type == omapi_datatype_int) {
801 				haddr[0] = (unsigned char)
802 					tv -> value -> u.integer;
803 			} else {
804 				omapi_value_dereference (&tv, MDL);
805 				dfree (haddr, MDL);
806 				return DHCP_R_INVALIDARG;
807 			}
808 
809 			omapi_value_dereference (&tv, MDL);
810 		} else {
811 			/* If no hardware-type is specified, default to
812 			   ethernet.  This may or may not be a good idea,
813 			   but Telus is currently relying on this behavior.
814 			   - DPN */
815 			haddr[0] = HTYPE_ETHER;
816 		}
817 
818 		lease = (struct lease *)0;
819 		lease_id_hash_lookup(&lease, lease_hw_addr_hash, haddr, len,
820 				     MDL);
821 		dfree (haddr, MDL);
822 
823 		if (*lp && *lp != (omapi_object_t *)lease) {
824 			omapi_object_dereference (lp, MDL);
825 			lease_dereference (&lease, MDL);
826 			return DHCP_R_KEYCONFLICT;
827 		} else if (!lease) {
828 			if (*lp)
829 			    omapi_object_dereference (lp, MDL);
830 			return ISC_R_NOTFOUND;
831 		} else if (lease -> n_hw) {
832 			if (*lp)
833 			    omapi_object_dereference (lp, MDL);
834 			lease_dereference (&lease, MDL);
835 			return DHCP_R_MULTIPLE;
836 		} else if (!*lp) {
837 			/* XXX fix so that hash lookup itself creates
838 			   XXX the reference. */
839 			omapi_object_reference (lp,
840 						(omapi_object_t *)lease, MDL);
841 			lease_dereference (&lease, MDL);
842 		}
843 	}
844 
845 	/* If we get to here without finding a lease, no valid key was
846 	   specified. */
847 	if (!*lp)
848 		return DHCP_R_NOKEYS;
849 	return ISC_R_SUCCESS;
850 }
851 
852 isc_result_t dhcp_lease_create (omapi_object_t **lp,
853 				omapi_object_t *id)
854 {
855 	return ISC_R_NOTIMPLEMENTED;
856 }
857 
858 isc_result_t dhcp_lease_remove (omapi_object_t *lp,
859 				omapi_object_t *id)
860 {
861 	return ISC_R_NOTIMPLEMENTED;
862 }
863 
864 isc_result_t dhcp_host_set_value  (omapi_object_t *h,
865 				   omapi_object_t *id,
866 				   omapi_data_string_t *name,
867 				   omapi_typed_data_t *value)
868 {
869 	struct host_decl *host;
870 	isc_result_t status;
871 
872 	if (h -> type != dhcp_type_host)
873 		return DHCP_R_INVALIDARG;
874 	host = (struct host_decl *)h;
875 
876 	/* XXX For now, we can only set these values on new host objects.
877 	   XXX Soon, we need to be able to update host objects. */
878 	if (!omapi_ds_strcmp (name, "name")) {
879 		if (host -> name)
880 			return ISC_R_EXISTS;
881 		if (value && (value -> type == omapi_datatype_data ||
882 			      value -> type == omapi_datatype_string)) {
883 			host -> name = dmalloc (value -> u.buffer.len + 1,
884 						MDL);
885 			if (!host -> name)
886 				return ISC_R_NOMEMORY;
887 			memcpy (host -> name,
888 				value -> u.buffer.value,
889 				value -> u.buffer.len);
890 			host -> name [value -> u.buffer.len] = 0;
891 		} else
892 			return DHCP_R_INVALIDARG;
893 		return ISC_R_SUCCESS;
894 	}
895 
896 	if (!omapi_ds_strcmp (name, "group")) {
897 		if (value && (value -> type == omapi_datatype_data ||
898 			      value -> type == omapi_datatype_string)) {
899 			struct group_object *group;
900 			group = (struct group_object *)0;
901 			group_hash_lookup (&group, group_name_hash,
902 					   (char *)value -> u.buffer.value,
903 					   value -> u.buffer.len, MDL);
904 			if (!group || (group -> flags & GROUP_OBJECT_DELETED))
905 				return ISC_R_NOTFOUND;
906 			if (host -> group)
907 				group_dereference (&host -> group, MDL);
908 			group_reference (&host -> group, group -> group, MDL);
909 			if (host -> named_group)
910 				group_object_dereference (&host -> named_group,
911 							  MDL);
912 			group_object_reference (&host -> named_group,
913 						group, MDL);
914 			group_object_dereference (&group, MDL);
915 		} else
916 			return DHCP_R_INVALIDARG;
917 		return ISC_R_SUCCESS;
918 	}
919 
920 	if (!omapi_ds_strcmp (name, "hardware-address")) {
921 		if (host -> interface.hlen)
922 			return ISC_R_EXISTS;
923 		if (value && (value -> type == omapi_datatype_data ||
924 			      value -> type == omapi_datatype_string)) {
925 			if (value -> u.buffer.len >
926 			    (sizeof host -> interface.hbuf) - 1)
927 				return DHCP_R_INVALIDARG;
928 			memcpy (&host -> interface.hbuf [1],
929 				value -> u.buffer.value,
930 				value -> u.buffer.len);
931 			host -> interface.hlen = value -> u.buffer.len + 1;
932 		} else
933 			return DHCP_R_INVALIDARG;
934 		return ISC_R_SUCCESS;
935 	}
936 
937 	if (!omapi_ds_strcmp (name, "hardware-type")) {
938 		int type;
939 		if ((value != NULL) &&
940 		    ((value->type == omapi_datatype_data) &&
941 		     (value->u.buffer.len == sizeof(type)))) {
942 			if (value->u.buffer.len > sizeof(type))
943 				return (DHCP_R_INVALIDARG);
944 			memcpy(&type, value->u.buffer.value,
945 			       value->u.buffer.len);
946 			type = ntohl(type);
947 		} else if ((value != NULL) &&
948 			   (value->type == omapi_datatype_int))
949 			type = value->u.integer;
950 		else
951 			return (DHCP_R_INVALIDARG);
952 		host->interface.hbuf[0] = type;
953 		return (ISC_R_SUCCESS);
954 	}
955 
956 	if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
957 		if (host -> client_identifier.data)
958 			return ISC_R_EXISTS;
959 		if (value && (value -> type == omapi_datatype_data ||
960 			      value -> type == omapi_datatype_string)) {
961 		    if (!buffer_allocate (&host -> client_identifier.buffer,
962 					  value -> u.buffer.len, MDL))
963 			    return ISC_R_NOMEMORY;
964 		    host -> client_identifier.data =
965 			    &host -> client_identifier.buffer -> data [0];
966 		    memcpy (host -> client_identifier.buffer -> data,
967 			    value -> u.buffer.value,
968 			    value -> u.buffer.len);
969 		    host -> client_identifier.len = value -> u.buffer.len;
970 		} else
971 		    return DHCP_R_INVALIDARG;
972 		return ISC_R_SUCCESS;
973 	}
974 
975 	if (!omapi_ds_strcmp (name, "ip-address")) {
976 		if (host -> fixed_addr)
977 			option_cache_dereference (&host -> fixed_addr, MDL);
978 		if (!value)
979 			return ISC_R_SUCCESS;
980 		if (value && (value -> type == omapi_datatype_data ||
981 			      value -> type == omapi_datatype_string)) {
982 			struct data_string ds;
983 			memset (&ds, 0, sizeof ds);
984 			ds.len = value -> u.buffer.len;
985 			if (!buffer_allocate (&ds.buffer, ds.len, MDL))
986 				return ISC_R_NOMEMORY;
987 			ds.data = (&ds.buffer -> data [0]);
988 			memcpy (ds.buffer -> data,
989 				value -> u.buffer.value, ds.len);
990 			if (!option_cache (&host -> fixed_addr,
991 					   &ds, (struct expression *)0,
992 					   (struct option *)0, MDL)) {
993 				data_string_forget (&ds, MDL);
994 				return ISC_R_NOMEMORY;
995 			}
996 			data_string_forget (&ds, MDL);
997 		} else
998 			return DHCP_R_INVALIDARG;
999 		return ISC_R_SUCCESS;
1000 	}
1001 
1002 	if (!omapi_ds_strcmp (name, "statements")) {
1003 		if (!host -> group) {
1004 			if (!clone_group (&host -> group, root_group, MDL))
1005 				return ISC_R_NOMEMORY;
1006 		} else {
1007 			if (host -> group -> statements &&
1008 			    (!host -> named_group ||
1009 			     host -> group != host -> named_group -> group) &&
1010 			    host -> group != root_group)
1011 				return ISC_R_EXISTS;
1012 			if (!clone_group (&host -> group, host -> group, MDL))
1013 				return ISC_R_NOMEMORY;
1014 		}
1015 		if (!host -> group)
1016 			return ISC_R_NOMEMORY;
1017 		if (value && (value -> type == omapi_datatype_data ||
1018 			      value -> type == omapi_datatype_string)) {
1019 			struct parse *parse;
1020 			int lose = 0;
1021 			parse = (struct parse *)0;
1022 			status = new_parse(&parse, -1,
1023 					    (char *) value->u.buffer.value,
1024 					    value->u.buffer.len,
1025 					    "network client", 0);
1026 			if (status != ISC_R_SUCCESS || parse == NULL)
1027 				return status;
1028 
1029 			if (!(parse_executable_statements
1030 			      (&host -> group -> statements, parse, &lose,
1031 			       context_any))) {
1032 				end_parse (&parse);
1033 				return DHCP_R_BADPARSE;
1034 			}
1035 			end_parse (&parse);
1036 		} else
1037 			return DHCP_R_INVALIDARG;
1038 		return ISC_R_SUCCESS;
1039 	}
1040 
1041 	/* The "known" flag isn't supported in the database yet, but it's
1042 	   legitimate. */
1043 	if (!omapi_ds_strcmp (name, "known")) {
1044 		return ISC_R_SUCCESS;
1045 	}
1046 
1047 	/* Try to find some inner object that can take the value. */
1048 	if (h -> inner && h -> inner -> type -> set_value) {
1049 		status = ((*(h -> inner -> type -> set_value))
1050 			  (h -> inner, id, name, value));
1051 		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
1052 			return status;
1053 	}
1054 
1055 	return DHCP_R_UNKNOWNATTRIBUTE;
1056 }
1057 
1058 
1059 isc_result_t dhcp_host_get_value (omapi_object_t *h, omapi_object_t *id,
1060 				   omapi_data_string_t *name,
1061 				   omapi_value_t **value)
1062 {
1063 	struct host_decl *host;
1064 	isc_result_t status;
1065 	struct data_string ip_addrs;
1066 
1067 	if (h -> type != dhcp_type_host)
1068 		return DHCP_R_INVALIDARG;
1069 	host = (struct host_decl *)h;
1070 
1071 	if (!omapi_ds_strcmp (name, "ip-addresses")) {
1072 	    memset (&ip_addrs, 0, sizeof ip_addrs);
1073 	    if (host -> fixed_addr &&
1074 		evaluate_option_cache (&ip_addrs, (struct packet *)0,
1075 				       (struct lease *)0,
1076 				       (struct client_state *)0,
1077 				       (struct option_state *)0,
1078 				       (struct option_state *)0,
1079 				       &global_scope,
1080 				       host -> fixed_addr, MDL)) {
1081 		    status = omapi_make_const_value (value, name,
1082 						     ip_addrs.data,
1083 						     ip_addrs.len, MDL);
1084 		    data_string_forget (&ip_addrs, MDL);
1085 		    return status;
1086 	    }
1087 	    return ISC_R_NOTFOUND;
1088 	}
1089 
1090 	if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
1091 		if (!host -> client_identifier.len)
1092 			return ISC_R_NOTFOUND;
1093 		return omapi_make_const_value (value, name,
1094 					       host -> client_identifier.data,
1095 					       host -> client_identifier.len,
1096 					       MDL);
1097 	}
1098 
1099 	if (!omapi_ds_strcmp (name, "name"))
1100 		return omapi_make_string_value (value, name, host -> name,
1101 						MDL);
1102 
1103 	if (!omapi_ds_strcmp (name, "hardware-address")) {
1104 		if (!host -> interface.hlen)
1105 			return ISC_R_NOTFOUND;
1106 		return (omapi_make_const_value
1107 			(value, name, &host -> interface.hbuf [1],
1108 			 (unsigned long)(host -> interface.hlen - 1), MDL));
1109 	}
1110 
1111 	if (!omapi_ds_strcmp (name, "hardware-type")) {
1112 		if (!host -> interface.hlen)
1113 			return ISC_R_NOTFOUND;
1114 		return omapi_make_int_value (value, name,
1115 					     host -> interface.hbuf [0], MDL);
1116 	}
1117 
1118 	/* Try to find some inner object that can take the value. */
1119 	if (h -> inner && h -> inner -> type -> get_value) {
1120 		status = ((*(h -> inner -> type -> get_value))
1121 			  (h -> inner, id, name, value));
1122 		if (status == ISC_R_SUCCESS)
1123 			return status;
1124 	}
1125 	return DHCP_R_UNKNOWNATTRIBUTE;
1126 }
1127 
1128 isc_result_t dhcp_host_destroy (omapi_object_t *h, const char *file, int line)
1129 {
1130 
1131 	if (h -> type != dhcp_type_host)
1132 		return DHCP_R_INVALIDARG;
1133 
1134 #if defined (DEBUG_MEMORY_LEAKAGE) || \
1135 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1136 	struct host_decl *host = (struct host_decl *)h;
1137 	if (host -> n_ipaddr)
1138 		host_dereference (&host -> n_ipaddr, file, line);
1139 	if (host -> n_dynamic)
1140 		host_dereference (&host -> n_dynamic, file, line);
1141 	if (host -> name) {
1142 		dfree (host -> name, file, line);
1143 		host -> name = (char *)0;
1144 	}
1145 	data_string_forget (&host -> client_identifier, file, line);
1146 	if (host -> fixed_addr)
1147 		option_cache_dereference (&host -> fixed_addr, file, line);
1148 	if (host -> group)
1149 		group_dereference (&host -> group, file, line);
1150 	if (host -> named_group)
1151 		omapi_object_dereference ((omapi_object_t **)
1152 					  &host -> named_group, file, line);
1153 	data_string_forget (&host -> auth_key_id, file, line);
1154 #endif
1155 
1156 	return ISC_R_SUCCESS;
1157 }
1158 
1159 isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
1160 				       const char *name, va_list ap)
1161 {
1162 	struct host_decl *host;
1163 	isc_result_t status;
1164 	int updatep = 0;
1165 
1166 	if (h -> type != dhcp_type_host)
1167 		return DHCP_R_INVALIDARG;
1168 	host = (struct host_decl *)h;
1169 
1170 	if (!strcmp (name, "updated")) {
1171 		/* There must be a client identifier of some sort. */
1172 		if (host -> interface.hlen == 0 &&
1173 		    !host -> client_identifier.len)
1174 			return DHCP_R_INVALIDARG;
1175 
1176 		if (!host -> name) {
1177 			char hnbuf [64];
1178 			sprintf (hnbuf, "nh%08lx%08lx",
1179 				 (unsigned long)cur_time, (unsigned long)host);
1180 			host -> name = dmalloc (strlen (hnbuf) + 1, MDL);
1181 			if (!host -> name)
1182 				return ISC_R_NOMEMORY;
1183 			strcpy (host -> name, hnbuf);
1184 		}
1185 
1186 #ifdef DEBUG_OMAPI
1187 		log_debug ("OMAPI added host %s", host -> name);
1188 #endif
1189 		status = enter_host (host, 1, 1);
1190 		if (status != ISC_R_SUCCESS)
1191 			return status;
1192 		updatep = 1;
1193 	}
1194 
1195 	/* Try to find some inner object that can take the value. */
1196 	if (h -> inner && h -> inner -> type -> signal_handler) {
1197 		status = ((*(h -> inner -> type -> signal_handler))
1198 			  (h -> inner, name, ap));
1199 		if (status == ISC_R_SUCCESS)
1200 			return status;
1201 	}
1202 	if (updatep)
1203 		return ISC_R_SUCCESS;
1204 	return ISC_R_NOTFOUND;
1205 }
1206 
1207 isc_result_t dhcp_host_stuff_values (omapi_object_t *c,
1208 				      omapi_object_t *id,
1209 				      omapi_object_t *h)
1210 {
1211 	struct host_decl *host;
1212 	isc_result_t status;
1213 	struct data_string ip_addrs;
1214 
1215 	if (h -> type != dhcp_type_host)
1216 		return DHCP_R_INVALIDARG;
1217 	host = (struct host_decl *)h;
1218 
1219 	/* Write out all the values. */
1220 
1221 	memset (&ip_addrs, 0, sizeof ip_addrs);
1222 	if (host -> fixed_addr &&
1223 	    evaluate_option_cache (&ip_addrs, (struct packet *)0,
1224 				   (struct lease *)0,
1225 				   (struct client_state *)0,
1226 				   (struct option_state *)0,
1227 				   (struct option_state *)0,
1228 				   &global_scope,
1229 				   host -> fixed_addr, MDL)) {
1230 		status = omapi_connection_put_name (c, "ip-address");
1231 		if (status != ISC_R_SUCCESS)
1232 			return status;
1233 		status = omapi_connection_put_uint32 (c, ip_addrs.len);
1234 		if (status != ISC_R_SUCCESS)
1235 			return status;
1236 		status = omapi_connection_copyin (c,
1237 						  ip_addrs.data, ip_addrs.len);
1238 		if (status != ISC_R_SUCCESS)
1239 			return status;
1240 	}
1241 
1242 	if (host -> client_identifier.len) {
1243 		status = omapi_connection_put_name (c,
1244 						    "dhcp-client-identifier");
1245 		if (status != ISC_R_SUCCESS)
1246 			return status;
1247 		status = (omapi_connection_put_uint32
1248 			  (c, host -> client_identifier.len));
1249 		if (status != ISC_R_SUCCESS)
1250 			return status;
1251 		status = (omapi_connection_copyin
1252 			  (c,
1253 			   host -> client_identifier.data,
1254 			   host -> client_identifier.len));
1255 		if (status != ISC_R_SUCCESS)
1256 			return status;
1257 	}
1258 
1259 	if (host -> name) {
1260 		status = omapi_connection_put_name (c, "name");
1261 		if (status != ISC_R_SUCCESS)
1262 			return status;
1263 		status = omapi_connection_put_string (c, host -> name);
1264 		if (status != ISC_R_SUCCESS)
1265 			return status;
1266 	}
1267 
1268 	if (host -> interface.hlen) {
1269 		status = omapi_connection_put_name (c, "hardware-address");
1270 		if (status != ISC_R_SUCCESS)
1271 			return status;
1272 		status = (omapi_connection_put_uint32
1273 			  (c, (unsigned long)(host -> interface.hlen - 1)));
1274 		if (status != ISC_R_SUCCESS)
1275 			return status;
1276 		status = (omapi_connection_copyin
1277 			  (c, &host -> interface.hbuf [1],
1278 			   (unsigned long)(host -> interface.hlen - 1)));
1279 		if (status != ISC_R_SUCCESS)
1280 			return status;
1281 
1282 		status = omapi_connection_put_named_uint32(c, "hardware-type",
1283 							   host->interface.hbuf[0]);
1284 		if (status != ISC_R_SUCCESS)
1285 			return status;
1286 	}
1287 
1288 	/* Write out the inner object, if any. */
1289 	if (h -> inner && h -> inner -> type -> stuff_values) {
1290 		status = ((*(h -> inner -> type -> stuff_values))
1291 			  (c, id, h -> inner));
1292 		if (status == ISC_R_SUCCESS)
1293 			return status;
1294 	}
1295 
1296 	return ISC_R_SUCCESS;
1297 }
1298 
1299 isc_result_t dhcp_host_lookup (omapi_object_t **lp,
1300 			       omapi_object_t *id, omapi_object_t *ref)
1301 {
1302 	omapi_value_t *tv = (omapi_value_t *)0;
1303 	isc_result_t status;
1304 	struct host_decl *host;
1305 
1306 	if (!ref)
1307 		return DHCP_R_NOKEYS;
1308 
1309 	/* First see if we were sent a handle. */
1310 	status = omapi_get_value_str (ref, id, "handle", &tv);
1311 	if (status == ISC_R_SUCCESS) {
1312 		status = omapi_handle_td_lookup (lp, tv -> value);
1313 
1314 		omapi_value_dereference (&tv, MDL);
1315 		if (status != ISC_R_SUCCESS)
1316 			return status;
1317 
1318 		/* Don't return the object if the type is wrong. */
1319 		if ((*lp) -> type != dhcp_type_host) {
1320 			omapi_object_dereference (lp, MDL);
1321 			return DHCP_R_INVALIDARG;
1322 		}
1323 		if (((struct host_decl *)(*lp)) -> flags & HOST_DECL_DELETED) {
1324 			omapi_object_dereference (lp, MDL);
1325 		}
1326 	}
1327 
1328 	/* Now look for a client identifier. */
1329 	status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
1330 	if (status == ISC_R_SUCCESS) {
1331 		host = (struct host_decl *)0;
1332 		host_hash_lookup (&host, host_uid_hash,
1333 				  tv -> value -> u.buffer.value,
1334 				  tv -> value -> u.buffer.len, MDL);
1335 		omapi_value_dereference (&tv, MDL);
1336 
1337 		if (*lp && *lp != (omapi_object_t *)host) {
1338 			omapi_object_dereference (lp, MDL);
1339 			if (host)
1340 				host_dereference (&host, MDL);
1341 			return DHCP_R_KEYCONFLICT;
1342 		} else if (!host || (host -> flags & HOST_DECL_DELETED)) {
1343 			if (*lp)
1344 			    omapi_object_dereference (lp, MDL);
1345 			if (host)
1346 				host_dereference (&host, MDL);
1347 			return ISC_R_NOTFOUND;
1348 		} else if (!*lp) {
1349 			/* XXX fix so that hash lookup itself creates
1350 			   XXX the reference. */
1351 			omapi_object_reference (lp,
1352 						(omapi_object_t *)host, MDL);
1353 			host_dereference (&host, MDL);
1354 		}
1355 	}
1356 
1357 	/* Now look for a hardware address. */
1358 	status = omapi_get_value_str (ref, id, "hardware-address", &tv);
1359 	if (status == ISC_R_SUCCESS) {
1360 		unsigned char *haddr;
1361 		unsigned int len;
1362 
1363 		len = tv -> value -> u.buffer.len + 1;
1364 		haddr = dmalloc (len, MDL);
1365 		if (!haddr) {
1366 			omapi_value_dereference (&tv, MDL);
1367 			return ISC_R_NOMEMORY;
1368 		}
1369 
1370 		memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
1371 		omapi_value_dereference (&tv, MDL);
1372 
1373 		status = omapi_get_value_str (ref, id, "hardware-type", &tv);
1374 		if (status == ISC_R_SUCCESS) {
1375 			if (tv -> value -> type == omapi_datatype_data) {
1376 				if ((tv -> value -> u.buffer.len != 4) ||
1377 				    (tv -> value -> u.buffer.value[0] != 0) ||
1378 				    (tv -> value -> u.buffer.value[1] != 0) ||
1379 				    (tv -> value -> u.buffer.value[2] != 0)) {
1380 					omapi_value_dereference (&tv, MDL);
1381 					dfree (haddr, MDL);
1382 					return DHCP_R_INVALIDARG;
1383 				}
1384 
1385 				haddr[0] = tv -> value -> u.buffer.value[3];
1386 			} else if (tv -> value -> type == omapi_datatype_int) {
1387 				haddr[0] = (unsigned char)
1388 					tv -> value -> u.integer;
1389 			} else {
1390 				omapi_value_dereference (&tv, MDL);
1391 				dfree (haddr, MDL);
1392 				return DHCP_R_INVALIDARG;
1393 			}
1394 
1395 			omapi_value_dereference (&tv, MDL);
1396 		} else {
1397 			/* If no hardware-type is specified, default to
1398 			   ethernet.  This may or may not be a good idea,
1399 			   but Telus is currently relying on this behavior.
1400 			   - DPN */
1401 			haddr[0] = HTYPE_ETHER;
1402 		}
1403 
1404 		host = (struct host_decl *)0;
1405 		host_hash_lookup (&host, host_hw_addr_hash, haddr, len, MDL);
1406 		dfree (haddr, MDL);
1407 
1408 		if (*lp && *lp != (omapi_object_t *)host) {
1409 			omapi_object_dereference (lp, MDL);
1410 			if (host)
1411 				host_dereference (&host, MDL);
1412 			return DHCP_R_KEYCONFLICT;
1413 		} else if (!host || (host -> flags & HOST_DECL_DELETED)) {
1414 			if (*lp)
1415 			    omapi_object_dereference (lp, MDL);
1416 			if (host)
1417 				host_dereference (&host, MDL);
1418 			return ISC_R_NOTFOUND;
1419 		} else if (!*lp) {
1420 			/* XXX fix so that hash lookup itself creates
1421 			   XXX the reference. */
1422 			omapi_object_reference (lp,
1423 						(omapi_object_t *)host, MDL);
1424 			host_dereference (&host, MDL);
1425 		}
1426 	}
1427 
1428 	/* Now look for an ip address. */
1429 	status = omapi_get_value_str (ref, id, "ip-address", &tv);
1430 	if (status == ISC_R_SUCCESS) {
1431 		struct lease *l;
1432 
1433 		/* first find the lease for this ip address */
1434 		l = (struct lease *)0;
1435 		lease_ip_hash_lookup(&l, lease_ip_addr_hash,
1436 				     tv->value->u.buffer.value,
1437 				     tv->value->u.buffer.len, MDL);
1438 		omapi_value_dereference (&tv, MDL);
1439 
1440 		if (!l && !*lp)
1441 			return ISC_R_NOTFOUND;
1442 
1443 		if (l) {
1444 			/* now use that to get a host */
1445 			host = (struct host_decl *)0;
1446 			host_hash_lookup (&host, host_hw_addr_hash,
1447 					  l -> hardware_addr.hbuf,
1448 					  l -> hardware_addr.hlen, MDL);
1449 
1450 			if (host && *lp && *lp != (omapi_object_t *)host) {
1451 			    omapi_object_dereference (lp, MDL);
1452 			    if (host)
1453 				host_dereference (&host, MDL);
1454 			    return DHCP_R_KEYCONFLICT;
1455 			} else if (!host || (host -> flags &
1456 					     HOST_DECL_DELETED)) {
1457 			    if (host)
1458 				host_dereference (&host, MDL);
1459 			    if (!*lp)
1460 				    return ISC_R_NOTFOUND;
1461 			} else if (!*lp) {
1462 				/* XXX fix so that hash lookup itself creates
1463 				   XXX the reference. */
1464 			    omapi_object_reference (lp, (omapi_object_t *)host,
1465 						    MDL);
1466 			    host_dereference (&host, MDL);
1467 			}
1468 			lease_dereference (&l, MDL);
1469 		}
1470 	}
1471 
1472 	/* Now look for a name. */
1473 	status = omapi_get_value_str (ref, id, "name", &tv);
1474 	if (status == ISC_R_SUCCESS) {
1475 		host = (struct host_decl *)0;
1476 		host_hash_lookup (&host, host_name_hash,
1477 				  tv -> value -> u.buffer.value,
1478 				  tv -> value -> u.buffer.len, MDL);
1479 		omapi_value_dereference (&tv, MDL);
1480 
1481 		if (*lp && *lp != (omapi_object_t *)host) {
1482 			omapi_object_dereference (lp, MDL);
1483 			if (host)
1484 			    host_dereference (&host, MDL);
1485 			return DHCP_R_KEYCONFLICT;
1486 		} else if (!host || (host -> flags & HOST_DECL_DELETED)) {
1487 			if (host)
1488 			    host_dereference (&host, MDL);
1489 			return ISC_R_NOTFOUND;
1490 		} else if (!*lp) {
1491 			/* XXX fix so that hash lookup itself creates
1492 			   XXX the reference. */
1493 			omapi_object_reference (lp,
1494 						(omapi_object_t *)host, MDL);
1495 			host_dereference (&host, MDL);
1496 		}
1497 	}
1498 
1499 	/* If we get to here without finding a host, no valid key was
1500 	   specified. */
1501 	if (!*lp)
1502 		return DHCP_R_NOKEYS;
1503 	return ISC_R_SUCCESS;
1504 }
1505 
1506 isc_result_t dhcp_host_create (omapi_object_t **lp,
1507 			       omapi_object_t *id)
1508 {
1509 	struct host_decl *hp;
1510 	isc_result_t status;
1511 	hp = (struct host_decl *)0;
1512 	status = host_allocate (&hp, MDL);
1513 	if (status != ISC_R_SUCCESS)
1514 		return status;
1515 	group_reference (&hp -> group, root_group, MDL);
1516 	hp -> flags = HOST_DECL_DYNAMIC;
1517 	status = omapi_object_reference (lp, (omapi_object_t *)hp, MDL);
1518 	host_dereference (&hp, MDL);
1519 	return status;
1520 }
1521 
1522 isc_result_t dhcp_host_remove (omapi_object_t *lp,
1523 			       omapi_object_t *id)
1524 {
1525 	struct host_decl *hp;
1526 	if (lp -> type != dhcp_type_host)
1527 		return DHCP_R_INVALIDARG;
1528 	hp = (struct host_decl *)lp;
1529 
1530 #ifdef DEBUG_OMAPI
1531 	log_debug ("OMAPI delete host %s", hp -> name);
1532 #endif
1533 	delete_host (hp, 1);
1534 	return ISC_R_SUCCESS;
1535 }
1536 
1537 isc_result_t dhcp_pool_set_value  (omapi_object_t *h,
1538 				   omapi_object_t *id,
1539 				   omapi_data_string_t *name,
1540 				   omapi_typed_data_t *value)
1541 {
1542 	/* h should point to (struct pool *) */
1543 	isc_result_t status;
1544 
1545 	if (h -> type != dhcp_type_pool)
1546 		return DHCP_R_INVALIDARG;
1547 
1548 	/* No values to set yet. */
1549 
1550 	/* Try to find some inner object that can take the value. */
1551 	if (h -> inner && h -> inner -> type -> set_value) {
1552 		status = ((*(h -> inner -> type -> set_value))
1553 			  (h -> inner, id, name, value));
1554 		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
1555 			return status;
1556 	}
1557 
1558 	return DHCP_R_UNKNOWNATTRIBUTE;
1559 }
1560 
1561 
1562 isc_result_t dhcp_pool_get_value (omapi_object_t *h, omapi_object_t *id,
1563 				  omapi_data_string_t *name,
1564 				  omapi_value_t **value)
1565 {
1566 	/* h should point to (struct pool *) */
1567 	isc_result_t status;
1568 
1569 	if (h -> type != dhcp_type_pool)
1570 		return DHCP_R_INVALIDARG;
1571 
1572 	/* No values to get yet. */
1573 
1574 	/* Try to find some inner object that can provide the value. */
1575 	if (h -> inner && h -> inner -> type -> get_value) {
1576 		status = ((*(h -> inner -> type -> get_value))
1577 			  (h -> inner, id, name, value));
1578 		if (status == ISC_R_SUCCESS)
1579 			return status;
1580 	}
1581 	return DHCP_R_UNKNOWNATTRIBUTE;
1582 }
1583 
1584 isc_result_t dhcp_pool_destroy (omapi_object_t *h, const char *file, int line)
1585 {
1586 #if defined (DEBUG_MEMORY_LEAKAGE) || \
1587 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1588 	struct permit *pc, *pn;
1589 #endif
1590 
1591 	if (h -> type != dhcp_type_pool)
1592 		return DHCP_R_INVALIDARG;
1593 
1594 #if defined (DEBUG_MEMORY_LEAKAGE) || \
1595 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1596 	struct pool *pool = (struct pool *)h;
1597 	if (pool -> next)
1598 		pool_dereference (&pool -> next, file, line);
1599 	if (pool -> group)
1600 		group_dereference (&pool -> group, file, line);
1601 	if (pool -> shared_network)
1602 	    shared_network_dereference (&pool -> shared_network, file, line);
1603 	if (pool -> active)
1604 		lease_dereference (&pool -> active, file, line);
1605 	if (pool -> expired)
1606 		lease_dereference (&pool -> expired, file, line);
1607 	if (pool -> free)
1608 		lease_dereference (&pool -> free, file, line);
1609 	if (pool -> backup)
1610 		lease_dereference (&pool -> backup, file, line);
1611 	if (pool -> abandoned)
1612 		lease_dereference (&pool -> abandoned, file, line);
1613 #if defined (FAILOVER_PROTOCOL)
1614 	if (pool -> failover_peer)
1615 		dhcp_failover_state_dereference (&pool -> failover_peer,
1616 						 file, line);
1617 #endif
1618 	for (pc = pool -> permit_list; pc; pc = pn) {
1619 		pn = pc -> next;
1620 		free_permit (pc, file, line);
1621 	}
1622 	pool -> permit_list = (struct permit *)0;
1623 
1624 	for (pc = pool -> prohibit_list; pc; pc = pn) {
1625 		pn = pc -> next;
1626 		free_permit (pc, file, line);
1627 	}
1628 	pool -> prohibit_list = (struct permit *)0;
1629 #endif
1630 
1631 	return ISC_R_SUCCESS;
1632 }
1633 
1634 isc_result_t dhcp_pool_signal_handler (omapi_object_t *h,
1635 				       const char *name, va_list ap)
1636 {
1637 	/* h should point to (struct pool *) */
1638 	isc_result_t status;
1639 
1640 	if (h -> type != dhcp_type_pool)
1641 		return DHCP_R_INVALIDARG;
1642 
1643 	/* Can't write pools yet. */
1644 
1645 	/* Try to find some inner object that can take the value. */
1646 	if (h -> inner && h -> inner -> type -> signal_handler) {
1647 		status = ((*(h -> inner -> type -> signal_handler))
1648 			  (h -> inner, name, ap));
1649 		if (status == ISC_R_SUCCESS)
1650 			return status;
1651 	}
1652 
1653 	return ISC_R_NOTFOUND;
1654 }
1655 
1656 isc_result_t dhcp_pool_stuff_values (omapi_object_t *c,
1657 				     omapi_object_t *id,
1658 				     omapi_object_t *h)
1659 {
1660 	struct pool *pool;
1661 	isc_result_t status;
1662 
1663 	if (h->type != dhcp_type_pool)
1664 		return (DHCP_R_INVALIDARG);
1665 	pool = (struct pool *)h;
1666 
1667 	/*
1668 	 * I don't think we can actually find a pool yet
1669 	 * but include the output of interesting values
1670 	 * for when we do
1671 	 */
1672 	status = omapi_connection_put_named_uint32(c, "lease-count",
1673 						   ((u_int32_t)
1674 						    pool->lease_count));
1675 	if (status != ISC_R_SUCCESS)
1676 		return (status);
1677 
1678 	status = omapi_connection_put_named_uint32(c, "free-leases",
1679 						   ((u_int32_t)
1680 						    pool->free_leases));
1681 	if (status != ISC_R_SUCCESS)
1682 		return (status);
1683 
1684 	status = omapi_connection_put_named_uint32(c, "backup-leases",
1685 						   ((u_int32_t)
1686 						    pool->backup_leases));
1687 	if (status != ISC_R_SUCCESS)
1688 		return (status);
1689 	/* we could add time stamps but lets wait on those */
1690 
1691 	/* Write out the inner object, if any. */
1692 	if (h->inner && h->inner->type->stuff_values) {
1693 		status = ((*(h->inner->type->stuff_values))
1694 			  (c, id, h->inner));
1695 		if (status == ISC_R_SUCCESS)
1696 			return (status);
1697 	}
1698 
1699 	return (ISC_R_SUCCESS);
1700 }
1701 
1702 isc_result_t dhcp_pool_lookup (omapi_object_t **lp,
1703 			       omapi_object_t *id, omapi_object_t *ref)
1704 {
1705 	/* Can't look up pools yet. */
1706 
1707 	/* If we get to here without finding a pool, no valid key was
1708 	   specified. */
1709 	if (!*lp)
1710 		return DHCP_R_NOKEYS;
1711 	return ISC_R_SUCCESS;
1712 }
1713 
1714 isc_result_t dhcp_pool_create (omapi_object_t **lp,
1715 			       omapi_object_t *id)
1716 {
1717 	return ISC_R_NOTIMPLEMENTED;
1718 }
1719 
1720 isc_result_t dhcp_pool_remove (omapi_object_t *lp,
1721 			       omapi_object_t *id)
1722 {
1723 	return ISC_R_NOTIMPLEMENTED;
1724 }
1725 
1726 static isc_result_t
1727 class_set_value (omapi_object_t *h,
1728 		 omapi_object_t *id,
1729 		 omapi_data_string_t *name,
1730 		 omapi_typed_data_t *value)
1731 {
1732 	struct class *class;
1733 	struct class *superclass = 0;
1734 	isc_result_t status;
1735 	int issubclass = (h -> type == dhcp_type_subclass);
1736 
1737 	class = (struct class *)h;
1738 
1739 	if (!omapi_ds_strcmp(name, "name")) {
1740 		char *tname;
1741 
1742 		if (class->name)
1743 			return ISC_R_EXISTS;
1744 
1745 		if ((tname = dmalloc(value->u.buffer.len + 1, MDL)) == NULL) {
1746 			return ISC_R_NOMEMORY;
1747 		}
1748 
1749 		/* tname is null terminated from dmalloc() */
1750 		memcpy(tname, value->u.buffer.value, value->u.buffer.len);
1751 
1752 		if (issubclass) {
1753 			status = find_class(&superclass, tname, MDL);
1754 			dfree(tname, MDL);
1755 
1756 			if (status == ISC_R_NOTFOUND)
1757 				return status;
1758 
1759 			if (class->superclass != NULL)
1760 				class_dereference(&class->superclass, MDL);
1761 			class_reference(&class->superclass, superclass, MDL);
1762 
1763 			if (class->group != NULL)
1764 				group_dereference(&class->group, MDL);
1765 			group_reference(&class->group, superclass->group, MDL);
1766 
1767 			class->lease_limit = superclass->lease_limit;
1768 			if (class->lease_limit != 0) {
1769 				class->billed_leases =
1770 					dmalloc(class->lease_limit *
1771 						sizeof(struct lease *),
1772 						MDL);
1773 				if (class->billed_leases == NULL) {
1774 					return ISC_R_NOMEMORY;
1775 				}
1776 			}
1777 
1778 		} else if (value->type == omapi_datatype_data ||
1779 			   value->type == omapi_datatype_string) {
1780 			class->name = dmalloc(value->u.buffer.len + 1, MDL);
1781 			if (!class->name)
1782 				return ISC_R_NOMEMORY;
1783 
1784 			/* class->name is null-terminated from dmalloc() */
1785 			memcpy(class->name, value->u.buffer.value,
1786 			       value->u.buffer.len);
1787 		} else
1788 			return DHCP_R_INVALIDARG;
1789 
1790 		return ISC_R_SUCCESS;
1791 	}
1792 
1793 
1794 	if (issubclass && !omapi_ds_strcmp(name, "hashstring")) {
1795 		if (class->hash_string.data)
1796 			return ISC_R_EXISTS;
1797 
1798 		if (value->type == omapi_datatype_data ||
1799 		    value->type == omapi_datatype_string) {
1800 			if (!buffer_allocate(&class->hash_string.buffer,
1801 					     value->u.buffer.len, MDL))
1802 				return ISC_R_NOMEMORY;
1803 			class->hash_string.data =
1804 					class->hash_string.buffer->data;
1805 			memcpy(class->hash_string.buffer->data,
1806 			       value->u.buffer.value, value->u.buffer.len);
1807 			class->hash_string.len = value->u.buffer.len;
1808 		} else
1809 			return DHCP_R_INVALIDARG;
1810 
1811 		return ISC_R_SUCCESS;
1812 	}
1813 
1814 	if (!omapi_ds_strcmp(name, "group")) {
1815 		if (value->type == omapi_datatype_data ||
1816 		    value->type == omapi_datatype_string) {
1817 			struct group_object *group = NULL;
1818 
1819 			group_hash_lookup(&group, group_name_hash,
1820 					  (char *)value->u.buffer.value,
1821 					  value->u.buffer.len, MDL);
1822 			if (!group || (group->flags & GROUP_OBJECT_DELETED))
1823 				return ISC_R_NOTFOUND;
1824 			if (class->group)
1825 				group_dereference(&class->group, MDL);
1826 			group_reference(&class->group, group->group, MDL);
1827 			group_object_dereference(&group, MDL);
1828 		} else
1829 			return DHCP_R_INVALIDARG;
1830 
1831 		return ISC_R_SUCCESS;
1832 	}
1833 
1834 
1835 	/* note we do not support full expressions via omapi because the
1836 	   expressions parser needs to be re-done to support parsing from
1837 	   strings and not just files. */
1838 
1839 	if (!omapi_ds_strcmp(name, "match")) {
1840 		if (value->type == omapi_datatype_data ||
1841 		    value->type == omapi_datatype_string) {
1842 			unsigned minlen = (value->u.buffer.len > 8 ?
1843 						8 : value->u.buffer.len);
1844 
1845 			if (!strncmp("hardware",
1846 				     (char *)value->u.buffer.value, minlen))
1847 			{
1848 				if (!expression_allocate(&class->submatch, MDL))
1849 					return ISC_R_NOMEMORY;
1850 
1851 				class->submatch->op = expr_hardware;
1852 			} else
1853 				return DHCP_R_INVALIDARG;
1854 		} else
1855 			return DHCP_R_INVALIDARG;
1856 
1857 		return ISC_R_SUCCESS;
1858 	}
1859 
1860 
1861 	if (!omapi_ds_strcmp(name, "option")) {
1862 		if (value->type == omapi_datatype_data ||
1863 		    value->type == omapi_datatype_string) {
1864 			/* XXXJAB support 'options' here. */
1865 			/* XXXJAB specifically 'bootfile-name' */
1866 			return DHCP_R_INVALIDARG; /* XXX tmp */
1867 		} else
1868 			return DHCP_R_INVALIDARG;
1869 
1870 		/*
1871 		 * Currently no way to get here, if we update the above
1872 		 * code so that we do get here this return needs to be
1873 		 * uncommented.
1874 		 * return ISC_R_SUCCESS;
1875 		 */
1876 	}
1877 
1878 
1879 	/* Try to find some inner object that can take the value. */
1880 	if (h->inner && h->inner->type->set_value) {
1881 		status = ((*(h->inner->type->set_value))
1882 			  (h->inner, id, name, value));
1883 		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
1884 			return status;
1885 	}
1886 
1887 	return DHCP_R_UNKNOWNATTRIBUTE;
1888 }
1889 
1890 
1891 
1892 isc_result_t dhcp_class_set_value  (omapi_object_t *h,
1893 				    omapi_object_t *id,
1894 				    omapi_data_string_t *name,
1895 				    omapi_typed_data_t *value)
1896 {
1897 	if (h -> type != dhcp_type_class)
1898 		return DHCP_R_INVALIDARG;
1899 
1900 	return class_set_value(h, id, name, value);
1901 }
1902 
1903 isc_result_t dhcp_class_get_value (omapi_object_t *h, omapi_object_t *id,
1904 				   omapi_data_string_t *name,
1905 				   omapi_value_t **value)
1906 {
1907 	struct class *class;
1908 	isc_result_t status;
1909 
1910 	if (h -> type != dhcp_type_class)
1911 		return DHCP_R_INVALIDARG;
1912 	class = (struct class *)h;
1913 
1914 	if (!omapi_ds_strcmp (name, "name"))
1915 		return omapi_make_string_value (value, name, class -> name,
1916 						MDL);
1917 
1918 	/* Try to find some inner object that can provide the value. */
1919 	if (h -> inner && h -> inner -> type -> get_value) {
1920 		status = ((*(h -> inner -> type -> get_value))
1921 			  (h -> inner, id, name, value));
1922 		if (status == ISC_R_SUCCESS)
1923 			return status;
1924 	}
1925 	return DHCP_R_UNKNOWNATTRIBUTE;
1926 }
1927 
1928 isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
1929 {
1930 
1931 	if (h -> type != dhcp_type_class && h -> type != dhcp_type_subclass)
1932 		return DHCP_R_INVALIDARG;
1933 	struct class *class = (struct class *)h;
1934 
1935 	if (class -> nic)
1936 		class_dereference (&class -> nic, file, line);
1937 	if (class -> superclass)
1938 		class_dereference (&class -> superclass, file, line);
1939 	if (class -> name) {
1940 		dfree (class -> name, file, line);
1941 		class -> name = (char *)0;
1942 	}
1943 	if (class -> billed_leases) {
1944 		int i;
1945 		for (i = 0; i < class -> lease_limit; i++) {
1946 			if (class -> billed_leases [i]) {
1947 				lease_dereference (&class -> billed_leases [i],
1948 						   file, line);
1949 			}
1950 		}
1951 		dfree (class -> billed_leases, file, line);
1952 		class -> billed_leases = (struct lease **)0;
1953 	}
1954 	if (class -> hash) {
1955 		class_free_hash_table (&class -> hash, file, line);
1956 		class -> hash = (class_hash_t *)0;
1957 	}
1958 	data_string_forget (&class -> hash_string, file, line);
1959 
1960 	if (class -> expr)
1961 		expression_dereference (&class -> expr, file, line);
1962 	if (class -> submatch)
1963 		expression_dereference (&class -> submatch, file, line);
1964 	if (class -> group)
1965 		group_dereference (&class -> group, file, line);
1966 	if (class -> statements)
1967 		executable_statement_dereference (&class -> statements,
1968 						  file, line);
1969 	if (class -> superclass)
1970 		class_dereference (&class -> superclass, file, line);
1971 
1972 	return ISC_R_SUCCESS;
1973 }
1974 
1975 static isc_result_t
1976 class_signal_handler(omapi_object_t *h,
1977 		     const char *name, va_list ap)
1978 {
1979 	struct class *class = (struct class *)h;
1980 	isc_result_t status;
1981 	int updatep = 0;
1982 	int issubclass;
1983 
1984 	issubclass = (h->type == dhcp_type_subclass);
1985 
1986 	if (!strcmp (name, "updated")) {
1987 
1988 		if (!issubclass) {
1989 			if (class->name == 0 || strlen(class->name) == 0) {
1990 				return DHCP_R_INVALIDARG;
1991 			}
1992 		} else {
1993 			if (class->superclass == 0) {
1994 				return DHCP_R_INVALIDARG; /* didn't give name */
1995 			}
1996 
1997 			if (class->hash_string.data == NULL) {
1998 				return DHCP_R_INVALIDARG;
1999 			}
2000 		}
2001 
2002 
2003 		if (issubclass) {
2004 			if (!class->superclass->hash)
2005 				class_new_hash(&class->superclass->hash,
2006 					       SCLASS_HASH_SIZE, MDL);
2007 
2008 			class_hash_add(class->superclass->hash,
2009 				       (const char *)class->hash_string.data,
2010 				       class->hash_string.len,
2011 				       (void *)class, MDL);
2012 		}
2013 
2014 #ifdef DEBUG_OMAPI
2015 		if (issubclass) {
2016 			log_debug ("OMAPI added subclass %s",
2017 				   class->superclass->name);
2018 		} else {
2019 			log_debug ("OMAPI added class %s", class->name);
2020 		}
2021 #endif
2022 
2023 		status = enter_class (class, 1, 1);
2024 		if (status != ISC_R_SUCCESS)
2025 			return status;
2026 		updatep = 1;
2027 	}
2028 
2029 	/* Try to find some inner object that can take the value. */
2030 	if (h->inner && h->inner->type->signal_handler) {
2031 		status = ((*(h->inner->type->signal_handler))
2032 			  (h->inner, name, ap));
2033 		if (status == ISC_R_SUCCESS)
2034 			return status;
2035 	}
2036 
2037 	if (updatep)
2038 		return ISC_R_SUCCESS;
2039 
2040 	return ISC_R_NOTFOUND;
2041 }
2042 
2043 
2044 isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
2045 					const char *name, va_list ap)
2046 {
2047 	if (h -> type != dhcp_type_class)
2048 		return DHCP_R_INVALIDARG;
2049 
2050 	return class_signal_handler(h, name, ap);
2051 }
2052 
2053 
2054 /*
2055  * Routine to put out generic class & subclass information
2056  */
2057 static isc_result_t class_stuff_values (omapi_object_t *c,
2058 				 omapi_object_t *id,
2059 				 omapi_object_t *h)
2060 {
2061 	struct class *class;
2062 	isc_result_t status;
2063 
2064 	class = (struct class *)h;
2065 
2066 	status = omapi_connection_put_named_uint32(c, "lease-limit",
2067 						   ((u_int32_t)
2068 						    class->lease_limit));
2069 	if (status != ISC_R_SUCCESS)
2070 		return (status);
2071 
2072 	status = omapi_connection_put_named_uint32(c, "leases-used",
2073 						   ((u_int32_t)
2074 						    class->leases_consumed));
2075 	if (status != ISC_R_SUCCESS)
2076 		return (status);
2077 
2078 	/* Write out the inner object, if any. */
2079 	if (h->inner && h->inner->type->stuff_values) {
2080 		status = ((*(h->inner->type->stuff_values))
2081 			  (c, id, h->inner));
2082 		if (status == ISC_R_SUCCESS)
2083 			return (status);
2084 	}
2085 
2086 	return (ISC_R_SUCCESS);
2087 }
2088 
2089 
2090 isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
2091 				      omapi_object_t *id,
2092 				      omapi_object_t *h)
2093 {
2094 	if (h->type != dhcp_type_class)
2095 		return (DHCP_R_INVALIDARG);
2096 
2097 	/* add any class specific items here */
2098 
2099 	return (class_stuff_values(c, id, h));
2100 }
2101 
2102 static isc_result_t class_lookup (omapi_object_t **lp,
2103 				  omapi_object_t *id, omapi_object_t *ref,
2104 				  omapi_object_type_t *typewanted)
2105 {
2106 	omapi_value_t *nv = NULL;
2107 	omapi_value_t *hv = NULL;
2108 	isc_result_t status;
2109 	struct class *class = 0;
2110 	struct class *subclass = 0;
2111 
2112 	*lp = NULL;
2113 
2114 	if (ref == NULL)
2115 		return (DHCP_R_NOKEYS);
2116 
2117 	/* see if we have a name */
2118 	status = omapi_get_value_str(ref, id, "name", &nv);
2119 	if (status == ISC_R_SUCCESS) {
2120 		char *name = dmalloc(nv->value->u.buffer.len + 1, MDL);
2121 		memcpy (name,
2122 			nv->value->u.buffer.value,
2123 			nv->value->u.buffer.len);
2124 
2125 		omapi_value_dereference(&nv, MDL);
2126 
2127 		find_class(&class, name, MDL);
2128 
2129 		dfree(name, MDL);
2130 
2131 		if (class == NULL) {
2132 			return (ISC_R_NOTFOUND);
2133 		}
2134 
2135 		if (typewanted == dhcp_type_subclass) {
2136 			status = omapi_get_value_str(ref, id,
2137 						     "hashstring", &hv);
2138 			if (status != ISC_R_SUCCESS) {
2139 				class_dereference(&class, MDL);
2140 				return (DHCP_R_NOKEYS);
2141 			}
2142 
2143 			if (hv->value->type != omapi_datatype_data &&
2144 			    hv->value->type != omapi_datatype_string) {
2145 				class_dereference(&class, MDL);
2146 				omapi_value_dereference(&hv, MDL);
2147 				return (DHCP_R_NOKEYS);
2148 			}
2149 
2150 			class_hash_lookup(&subclass, class->hash,
2151 					  (const char *)
2152 					  hv->value->u.buffer.value,
2153 					  hv->value->u.buffer.len, MDL);
2154 
2155 			omapi_value_dereference(&hv, MDL);
2156 
2157 			class_dereference(&class, MDL);
2158 
2159 			if (subclass == NULL) {
2160 				return (ISC_R_NOTFOUND);
2161 			}
2162 
2163 			class_reference(&class, subclass, MDL);
2164 			class_dereference(&subclass, MDL);
2165 		}
2166 
2167 		/* Don't return the object if the type is wrong. */
2168 		if (class->type != typewanted) {
2169 			class_dereference(&class, MDL);
2170 			return (DHCP_R_INVALIDARG);
2171 		}
2172 
2173 		if (class->flags & CLASS_DECL_DELETED) {
2174 			class_dereference(&class, MDL);
2175 			return (ISC_R_NOTFOUND);
2176 		}
2177 
2178 		omapi_object_reference(lp, (omapi_object_t *)class, MDL);
2179 		class_dereference(&class, MDL);
2180 
2181 		return (ISC_R_SUCCESS);
2182 	}
2183 
2184 	return (DHCP_R_NOKEYS);
2185 }
2186 
2187 
2188 isc_result_t dhcp_class_lookup (omapi_object_t **lp,
2189 				omapi_object_t *id, omapi_object_t *ref)
2190 {
2191 	return class_lookup(lp, id, ref, dhcp_type_class);
2192 }
2193 
2194 isc_result_t dhcp_class_create (omapi_object_t **lp,
2195 				omapi_object_t *id)
2196 {
2197 	struct class *cp = 0;
2198 	isc_result_t status;
2199 
2200 	status = class_allocate(&cp, MDL);
2201 	if (status != ISC_R_SUCCESS)
2202 		return (status);
2203 
2204 	clone_group(&cp->group, root_group, MDL);
2205 	cp->flags = CLASS_DECL_DYNAMIC;
2206 	status = omapi_object_reference(lp, (omapi_object_t *)cp, MDL);
2207 	class_dereference(&cp, MDL);
2208 	return (status);
2209 }
2210 
2211 isc_result_t dhcp_class_remove (omapi_object_t *lp,
2212 				omapi_object_t *id)
2213 {
2214 	struct class *cp;
2215 	if (lp -> type != dhcp_type_class)
2216 		return DHCP_R_INVALIDARG;
2217 	cp = (struct class *)lp;
2218 
2219 #ifdef DEBUG_OMAPI
2220 	log_debug ("OMAPI delete class %s", cp -> name);
2221 #endif
2222 
2223 	delete_class (cp, 1);
2224 	return ISC_R_SUCCESS;
2225 }
2226 
2227 isc_result_t dhcp_subclass_set_value  (omapi_object_t *h,
2228 				       omapi_object_t *id,
2229 				       omapi_data_string_t *name,
2230 				       omapi_typed_data_t *value)
2231 {
2232 	if (h -> type != dhcp_type_subclass)
2233 		return DHCP_R_INVALIDARG;
2234 
2235 	return class_set_value(h, id, name, value);
2236 }
2237 
2238 
2239 isc_result_t dhcp_subclass_get_value (omapi_object_t *h, omapi_object_t *id,
2240 				      omapi_data_string_t *name,
2241 				      omapi_value_t **value)
2242 {
2243 	struct class *subclass;
2244 	isc_result_t status;
2245 
2246 	if (h -> type != dhcp_type_class)
2247 		return DHCP_R_INVALIDARG;
2248 	subclass = (struct class *)h;
2249 	if (subclass -> name != 0)
2250 		return DHCP_R_INVALIDARG;
2251 
2252 	/* XXXJAB No values to get yet. */
2253 
2254 	/* Try to find some inner object that can provide the value. */
2255 	if (h -> inner && h -> inner -> type -> get_value) {
2256 		status = ((*(h -> inner -> type -> get_value))
2257 			  (h -> inner, id, name, value));
2258 		if (status == ISC_R_SUCCESS)
2259 			return status;
2260 	}
2261 	return DHCP_R_UNKNOWNATTRIBUTE;
2262 }
2263 
2264 isc_result_t dhcp_subclass_signal_handler (omapi_object_t *h,
2265 					   const char *name, va_list ap)
2266 {
2267 	if (h -> type != dhcp_type_subclass)
2268 		return DHCP_R_INVALIDARG;
2269 
2270 	return class_signal_handler(h, name, ap);
2271 }
2272 
2273 
2274 isc_result_t dhcp_subclass_stuff_values (omapi_object_t *c,
2275 					 omapi_object_t *id,
2276 					 omapi_object_t *h)
2277 {
2278 	struct class *subclass;
2279 
2280 	if (h->type != dhcp_type_subclass)
2281 		return (DHCP_R_INVALIDARG);
2282 	subclass = (struct class *)h;
2283 	if (subclass->name != 0)
2284 		return (DHCP_R_INVALIDARG);
2285 
2286 	/* add any subclass specific items here */
2287 
2288 	return (class_stuff_values(c, id, h));
2289 }
2290 
2291 isc_result_t dhcp_subclass_lookup (omapi_object_t **lp,
2292 				   omapi_object_t *id, omapi_object_t *ref)
2293 {
2294 	return class_lookup(lp, id, ref, dhcp_type_subclass);
2295 }
2296 
2297 
2298 
2299 
2300 isc_result_t dhcp_subclass_create (omapi_object_t **lp,
2301 				   omapi_object_t *id)
2302 {
2303 	struct class *cp = 0;
2304 	isc_result_t status;
2305 
2306 	status = subclass_allocate(&cp, MDL);
2307 	if (status != ISC_R_SUCCESS)
2308 		return status;
2309 	group_reference (&cp->group, root_group, MDL);
2310 
2311 	cp->flags = CLASS_DECL_DYNAMIC;
2312 
2313 	status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
2314 	subclass_dereference (&cp, MDL);
2315 	return status;
2316 }
2317 
2318 isc_result_t dhcp_subclass_remove (omapi_object_t *lp,
2319 				   omapi_object_t *id)
2320 {
2321 	struct class *cp;
2322 	if (lp -> type != dhcp_type_subclass)
2323 		return DHCP_R_INVALIDARG;
2324 	cp = (struct class *)lp;
2325 
2326 #ifdef DEBUG_OMAPI
2327 	log_debug ("OMAPI delete subclass %s", cp -> name);
2328 #endif
2329 
2330 	delete_class (cp, 1);
2331 
2332 	return ISC_R_SUCCESS;
2333 }
2334 
2335 isc_result_t binding_scope_set_value (struct binding_scope *scope, int createp,
2336 				      omapi_data_string_t *name,
2337 				      omapi_typed_data_t *value)
2338 {
2339 	struct binding *bp;
2340 	char *nname;
2341 	struct binding_value *nv;
2342 	nname = dmalloc (name -> len + 1, MDL);
2343 	if (!nname)
2344 		return ISC_R_NOMEMORY;
2345 	memcpy (nname, name -> value, name -> len);
2346 	nname [name -> len] = 0;
2347 	bp = find_binding (scope, nname);
2348 	if (!bp && !createp) {
2349 		dfree (nname, MDL);
2350 		return DHCP_R_UNKNOWNATTRIBUTE;
2351 	}
2352 	if (!value) {
2353 		dfree (nname, MDL);
2354 		if (!bp)
2355 			return DHCP_R_UNKNOWNATTRIBUTE;
2356 		binding_value_dereference (&bp -> value, MDL);
2357 		return ISC_R_SUCCESS;
2358 	}
2359 
2360 	nv = (struct binding_value *)0;
2361 	if (!binding_value_allocate (&nv, MDL)) {
2362 		dfree (nname, MDL);
2363 		return ISC_R_NOMEMORY;
2364 	}
2365 	switch (value -> type) {
2366 	      case omapi_datatype_int:
2367 		nv -> type = binding_numeric;
2368 		nv -> value.intval = value -> u.integer;
2369 		break;
2370 
2371 	      case omapi_datatype_string:
2372 	      case omapi_datatype_data:
2373 		if (!buffer_allocate (&nv -> value.data.buffer,
2374 				      value -> u.buffer.len, MDL)) {
2375 			binding_value_dereference (&nv, MDL);
2376 			dfree (nname, MDL);
2377 			return ISC_R_NOMEMORY;
2378 		}
2379 		memcpy (&nv -> value.data.buffer -> data [1],
2380 			value -> u.buffer.value, value -> u.buffer.len);
2381 		nv -> value.data.len = value -> u.buffer.len;
2382 		break;
2383 
2384 	      case omapi_datatype_object:
2385 		binding_value_dereference (&nv, MDL);
2386 		dfree (nname, MDL);
2387 		return DHCP_R_INVALIDARG;
2388 	}
2389 
2390 	if (!bp) {
2391 		bp = dmalloc (sizeof *bp, MDL);
2392 		if (!bp) {
2393 			binding_value_dereference (&nv, MDL);
2394 			dfree (nname, MDL);
2395 			return ISC_R_NOMEMORY;
2396 		}
2397 		memset (bp, 0, sizeof *bp);
2398 		bp -> name = nname;
2399 		bp -> next = scope -> bindings;
2400 		scope -> bindings = bp;
2401 	} else {
2402 		if (bp -> value)
2403 			binding_value_dereference (&bp -> value, MDL);
2404 		dfree (nname, MDL);
2405 	}
2406 	binding_value_reference (&bp -> value, nv, MDL);
2407 	binding_value_dereference (&nv, MDL);
2408 	return ISC_R_SUCCESS;
2409 }
2410 
2411 isc_result_t binding_scope_get_value (omapi_value_t **value,
2412 				      struct binding_scope *scope,
2413 				      omapi_data_string_t *name)
2414 {
2415 	struct binding *bp;
2416 	omapi_typed_data_t *td;
2417 	isc_result_t status;
2418 	char *nname;
2419 	nname = dmalloc (name -> len + 1, MDL);
2420 	if (!nname)
2421 		return ISC_R_NOMEMORY;
2422 	memcpy (nname, name -> value, name -> len);
2423 	nname [name -> len] = 0;
2424 	bp = find_binding (scope, nname);
2425 	dfree (nname, MDL);
2426 	if (!bp)
2427 		return DHCP_R_UNKNOWNATTRIBUTE;
2428 	if (!bp -> value)
2429 		return DHCP_R_UNKNOWNATTRIBUTE;
2430 
2431 	switch (bp -> value -> type) {
2432 	      case binding_boolean:
2433 		td = (omapi_typed_data_t *)0;
2434 		status = omapi_typed_data_new (MDL, &td, omapi_datatype_int,
2435 					       bp -> value -> value.boolean);
2436 		break;
2437 
2438 	      case binding_numeric:
2439 		td = (omapi_typed_data_t *)0;
2440 		status = omapi_typed_data_new (MDL, &td, omapi_datatype_int,
2441 					       (int)
2442 					       bp -> value -> value.intval);
2443 		break;
2444 
2445 	      case binding_data:
2446 		td = (omapi_typed_data_t *)0;
2447 		status = omapi_typed_data_new (MDL, &td, omapi_datatype_data,
2448 					       bp -> value -> value.data.len);
2449 		if (status != ISC_R_SUCCESS)
2450 			return status;
2451 		memcpy (&td -> u.buffer.value [0],
2452 			bp -> value -> value.data.data,
2453 			bp -> value -> value.data.len);
2454 		break;
2455 
2456 		/* Can't return values for these two (yet?). */
2457 	      case binding_dns:
2458 	      case binding_function:
2459 		return DHCP_R_INVALIDARG;
2460 
2461 	      default:
2462 		log_fatal ("Impossible case at %s:%d.", MDL);
2463 		return ISC_R_FAILURE;
2464 	}
2465 
2466 	if (status != ISC_R_SUCCESS)
2467 		return status;
2468 	status = omapi_value_new (value, MDL);
2469 	if (status != ISC_R_SUCCESS) {
2470 		omapi_typed_data_dereference (&td, MDL);
2471 		return status;
2472 	}
2473 
2474 	omapi_data_string_reference (&(*value) -> name, name, MDL);
2475 	omapi_typed_data_reference (&(*value) -> value, td, MDL);
2476 	omapi_typed_data_dereference (&td, MDL);
2477 
2478 	return ISC_R_SUCCESS;
2479 }
2480 
2481 isc_result_t binding_scope_stuff_values (omapi_object_t *c,
2482 					 struct binding_scope *scope)
2483 {
2484 	struct binding *bp;
2485 	unsigned len;
2486 	isc_result_t status;
2487 
2488 	for (bp = scope -> bindings; bp; bp = bp -> next) {
2489 	    if (bp -> value) {
2490 		if (bp -> value -> type == binding_dns ||
2491 		    bp -> value -> type == binding_function)
2492 			continue;
2493 
2494 		/* Stuff the name. */
2495 		len = strlen (bp -> name);
2496 		status = omapi_connection_put_uint16 (c, len);
2497 		if (status != ISC_R_SUCCESS)
2498 		    return status;
2499 		status = omapi_connection_copyin (c,
2500 						  (unsigned char *)bp -> name,
2501 						  len);
2502 		if (status != ISC_R_SUCCESS)
2503 			return status;
2504 
2505 		switch (bp -> value -> type) {
2506 		  case binding_boolean:
2507 		    status = omapi_connection_put_uint32 (c,
2508 							  sizeof (u_int32_t));
2509 		    if (status != ISC_R_SUCCESS)
2510 			return status;
2511 		    status = (omapi_connection_put_uint32
2512 			      (c,
2513 			       ((u_int32_t)(bp -> value -> value.boolean))));
2514 		    if (status != ISC_R_SUCCESS)
2515 			    return status;
2516 		    break;
2517 
2518 		  case binding_data:
2519 		    status = (omapi_connection_put_uint32
2520 			      (c, bp -> value -> value.data.len));
2521 		    if (status != ISC_R_SUCCESS)
2522 			return status;
2523 		    if (bp -> value -> value.data.len) {
2524 			status = (omapi_connection_copyin
2525 				  (c, bp -> value -> value.data.data,
2526 				   bp -> value -> value.data.len));
2527 			if (status != ISC_R_SUCCESS)
2528 			    return status;
2529 		    }
2530 		    break;
2531 
2532 		  case binding_numeric:
2533 		    status = (omapi_connection_put_uint32
2534 			      (c, sizeof (u_int32_t)));
2535 		    if (status != ISC_R_SUCCESS)
2536 			    return status;
2537 		    status = (omapi_connection_put_uint32
2538 			      (c, ((u_int32_t)
2539 				   (bp -> value -> value.intval))));
2540 		    if (status != ISC_R_SUCCESS)
2541 			    return status;
2542 		    break;
2543 
2544 
2545 		    /* NOTREACHED */
2546 		  case binding_dns:
2547 		  case binding_function:
2548 		    break;
2549 		}
2550 	    }
2551 	}
2552 	return ISC_R_SUCCESS;
2553 }
2554 
2555 /* vim: set tabstop=8: */
2556