Remove building with NOCRYPTO option
[minix.git] / external / bsd / dhcp / dist / server / omapi.c
blob97bafa1a20cec9e3c58f888e995001b599c24967
1 /* $NetBSD: omapi.c,v 1.2 2014/07/12 12:09:38 spz Exp $ */
2 /* omapi.c
4 OMAPI object interfaces for the DHCP server. */
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
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.
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.
23 * Internet Systems Consortium, Inc.
24 * 950 Charter Street
25 * Redwood City, CA 94063
26 * <info@isc.org>
27 * https://www.isc.org/
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: omapi.c,v 1.2 2014/07/12 12:09:38 spz Exp $");
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 */
41 #include "dhcpd.h"
42 #include <omapip/omapip_p.h>
44 static isc_result_t class_lookup (omapi_object_t **,
45 omapi_object_t *, omapi_object_t *,
46 omapi_object_type_t *);
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
59 void dhcp_db_objects_setup ()
61 isc_result_t status;
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
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));
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));
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));
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);
129 if (status != ISC_R_SUCCESS)
130 log_fatal ("Can't register pool object type: %s",
131 isc_result_totext (status));
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);
146 if (status != ISC_R_SUCCESS)
147 log_fatal ("Can't register host object type: %s",
148 isc_result_totext (status));
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);
165 if (status != ISC_R_SUCCESS)
166 log_fatal ("Can't register failover state object type: %s",
167 isc_result_totext (status));
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);
180 if (status != ISC_R_SUCCESS)
181 log_fatal ("Can't register failover link object type: %s",
182 isc_result_totext (status));
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);
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 */
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)
207 struct lease *lease;
208 isc_result_t status;
210 if (h -> type != dhcp_type_lease)
211 return DHCP_R_INVALIDARG;
212 lease = (struct lease *)h;
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;
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";
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;
239 log_info ("lease %s state change from %s to %s failed.",
240 piaddr (lease -> ip_addr), ols, nls);
241 return ISC_R_IOERROR;
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;
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;
278 if (value->type != omapi_datatype_data)
279 return DHCP_R_INVALIDARG;
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;
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;
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;
315 if (!lease -> scope) {
316 if (!binding_scope_allocate (&lease -> scope, MDL))
317 return ISC_R_NOMEMORY;
319 status = binding_scope_set_value (lease -> scope, 1, name, value);
320 if (status != ISC_R_SUCCESS)
321 return status;
323 if (write_lease (lease) && commit_leases ())
324 return ISC_R_SUCCESS;
325 return ISC_R_IOERROR;
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)
333 struct lease *lease;
334 isc_result_t status;
336 if (h -> type != dhcp_type_lease)
337 return DHCP_R_INVALIDARG;
338 lease = (struct lease *)h;
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;
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;
402 return DHCP_R_UNKNOWNATTRIBUTE;
405 isc_result_t dhcp_lease_destroy (omapi_object_t *h, const char *file, int line)
407 struct lease *lease;
409 if (h->type != dhcp_type_lease)
410 return DHCP_R_INVALIDARG;
411 lease = (struct lease *)h;
413 if (lease-> uid)
414 uid_hash_delete (lease);
415 hw_hash_delete (lease);
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);
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;
438 if (lease->client_hostname) {
439 dfree (lease->client_hostname, MDL);
440 lease->client_hostname = (char *)0;
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);
450 if (lease->state) {
451 free_lease_state (lease->state, file, line);
452 lease->state = (struct lease_state *)0;
454 cancel_timeout (lease_ping_timeout, lease);
455 --outstanding_pings; /* XXX */
458 if (lease->billing_class)
459 class_dereference
460 (&lease->billing_class, file, line);
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
476 return ISC_R_SUCCESS;
479 isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
480 const char *name, va_list ap)
482 /* h should point to (struct lease *) */
483 isc_result_t status;
485 if (h -> type != dhcp_type_lease)
486 return DHCP_R_INVALIDARG;
488 if (!strcmp (name, "updated"))
489 return ISC_R_SUCCESS;
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;
498 return ISC_R_NOTFOUND;
501 isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
502 omapi_object_t *id,
503 omapi_object_t *h)
505 u_int32_t bouncer;
506 struct lease *lease;
507 isc_result_t status;
508 u_int8_t flagbuf;
510 if (h -> type != dhcp_type_lease)
511 return DHCP_R_INVALIDARG;
512 lease = (struct lease *)h;
514 /* Write out all the values. */
516 status = omapi_connection_put_named_uint32(c, "state",
517 lease->binding_state);
518 if (status != ISC_R_SUCCESS)
519 return (status);
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;
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;
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;
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;
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;
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;
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;
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
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)));
609 if (status != ISC_R_SUCCESS)
610 return status;
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);
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.
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.
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);
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);
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);
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;
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;
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;
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;
669 if (lease -> scope) {
670 status = binding_scope_stuff_values (c, lease -> scope);
671 if (status != ISC_R_SUCCESS)
672 return status;
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;
683 return ISC_R_SUCCESS;
686 isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
687 omapi_object_t *id, omapi_object_t *ref)
689 omapi_value_t *tv = (omapi_value_t *)0;
690 isc_result_t status;
691 struct lease *lease;
693 if (!ref)
694 return DHCP_R_NOKEYS;
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);
701 omapi_value_dereference (&tv, MDL);
702 if (status != ISC_R_SUCCESS)
703 return status;
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;
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);
720 omapi_value_dereference (&tv, MDL);
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);
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);
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);
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;
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;
784 memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
785 omapi_value_dereference (&tv, MDL);
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;
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;
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;
818 lease = (struct lease *)0;
819 lease_id_hash_lookup(&lease, lease_hw_addr_hash, haddr, len,
820 MDL);
821 dfree (haddr, MDL);
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);
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;
852 isc_result_t dhcp_lease_create (omapi_object_t **lp,
853 omapi_object_t *id)
855 return ISC_R_NOTIMPLEMENTED;
858 isc_result_t dhcp_lease_remove (omapi_object_t *lp,
859 omapi_object_t *id)
861 return ISC_R_NOTIMPLEMENTED;
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)
869 struct host_decl *host;
870 isc_result_t status;
872 if (h -> type != dhcp_type_host)
873 return DHCP_R_INVALIDARG;
874 host = (struct host_decl *)h;
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;
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;
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;
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);
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;
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;
996 data_string_forget (&ds, MDL);
997 } else
998 return DHCP_R_INVALIDARG;
999 return ISC_R_SUCCESS;
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;
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;
1029 if (!(parse_executable_statements
1030 (&host -> group -> statements, parse, &lose,
1031 context_any))) {
1032 end_parse (&parse);
1033 return DHCP_R_BADPARSE;
1035 end_parse (&parse);
1036 } else
1037 return DHCP_R_INVALIDARG;
1038 return ISC_R_SUCCESS;
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;
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;
1055 return DHCP_R_UNKNOWNATTRIBUTE;
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)
1063 struct host_decl *host;
1064 isc_result_t status;
1065 struct data_string ip_addrs;
1067 if (h -> type != dhcp_type_host)
1068 return DHCP_R_INVALIDARG;
1069 host = (struct host_decl *)h;
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;
1087 return ISC_R_NOTFOUND;
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);
1099 if (!omapi_ds_strcmp (name, "name"))
1100 return omapi_make_string_value (value, name, host -> name,
1101 MDL);
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));
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);
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;
1125 return DHCP_R_UNKNOWNATTRIBUTE;
1128 isc_result_t dhcp_host_destroy (omapi_object_t *h, const char *file, int line)
1131 if (h -> type != dhcp_type_host)
1132 return DHCP_R_INVALIDARG;
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;
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
1156 return ISC_R_SUCCESS;
1159 isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
1160 const char *name, va_list ap)
1162 struct host_decl *host;
1163 isc_result_t status;
1164 int updatep = 0;
1166 if (h -> type != dhcp_type_host)
1167 return DHCP_R_INVALIDARG;
1168 host = (struct host_decl *)h;
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;
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);
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;
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;
1202 if (updatep)
1203 return ISC_R_SUCCESS;
1204 return ISC_R_NOTFOUND;
1207 isc_result_t dhcp_host_stuff_values (omapi_object_t *c,
1208 omapi_object_t *id,
1209 omapi_object_t *h)
1211 struct host_decl *host;
1212 isc_result_t status;
1213 struct data_string ip_addrs;
1215 if (h -> type != dhcp_type_host)
1216 return DHCP_R_INVALIDARG;
1217 host = (struct host_decl *)h;
1219 /* Write out all the values. */
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;
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
1253 host -> client_identifier.data,
1254 host -> client_identifier.len));
1255 if (status != ISC_R_SUCCESS)
1256 return status;
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;
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;
1282 status = omapi_connection_put_named_uint32(c, "hardware-type",
1283 host->interface.hbuf[0]);
1284 if (status != ISC_R_SUCCESS)
1285 return status;
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;
1296 return ISC_R_SUCCESS;
1299 isc_result_t dhcp_host_lookup (omapi_object_t **lp,
1300 omapi_object_t *id, omapi_object_t *ref)
1302 omapi_value_t *tv = (omapi_value_t *)0;
1303 isc_result_t status;
1304 struct host_decl *host;
1306 if (!ref)
1307 return DHCP_R_NOKEYS;
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);
1314 omapi_value_dereference (&tv, MDL);
1315 if (status != ISC_R_SUCCESS)
1316 return status;
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;
1323 if (((struct host_decl *)(*lp)) -> flags & HOST_DECL_DELETED) {
1324 omapi_object_dereference (lp, MDL);
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);
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);
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;
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;
1370 memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
1371 omapi_value_dereference (&tv, MDL);
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;
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;
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;
1404 host = (struct host_decl *)0;
1405 host_hash_lookup (&host, host_hw_addr_hash, haddr, len, MDL);
1406 dfree (haddr, MDL);
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);
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;
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);
1440 if (!l && !*lp)
1441 return ISC_R_NOTFOUND;
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);
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);
1468 lease_dereference (&l, MDL);
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);
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);
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;
1506 isc_result_t dhcp_host_create (omapi_object_t **lp,
1507 omapi_object_t *id)
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;
1522 isc_result_t dhcp_host_remove (omapi_object_t *lp,
1523 omapi_object_t *id)
1525 struct host_decl *hp;
1526 if (lp -> type != dhcp_type_host)
1527 return DHCP_R_INVALIDARG;
1528 hp = (struct host_decl *)lp;
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;
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)
1542 /* h should point to (struct pool *) */
1543 isc_result_t status;
1545 if (h -> type != dhcp_type_pool)
1546 return DHCP_R_INVALIDARG;
1548 /* No values to set yet. */
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;
1558 return DHCP_R_UNKNOWNATTRIBUTE;
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)
1566 /* h should point to (struct pool *) */
1567 isc_result_t status;
1569 if (h -> type != dhcp_type_pool)
1570 return DHCP_R_INVALIDARG;
1572 /* No values to get yet. */
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;
1581 return DHCP_R_UNKNOWNATTRIBUTE;
1584 isc_result_t dhcp_pool_destroy (omapi_object_t *h, const char *file, int line)
1586 #if defined (DEBUG_MEMORY_LEAKAGE) || \
1587 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1588 struct permit *pc, *pn;
1589 #endif
1591 if (h -> type != dhcp_type_pool)
1592 return DHCP_R_INVALIDARG;
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);
1622 pool -> permit_list = (struct permit *)0;
1624 for (pc = pool -> prohibit_list; pc; pc = pn) {
1625 pn = pc -> next;
1626 free_permit (pc, file, line);
1628 pool -> prohibit_list = (struct permit *)0;
1629 #endif
1631 return ISC_R_SUCCESS;
1634 isc_result_t dhcp_pool_signal_handler (omapi_object_t *h,
1635 const char *name, va_list ap)
1637 /* h should point to (struct pool *) */
1638 isc_result_t status;
1640 if (h -> type != dhcp_type_pool)
1641 return DHCP_R_INVALIDARG;
1643 /* Can't write pools yet. */
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;
1653 return ISC_R_NOTFOUND;
1656 isc_result_t dhcp_pool_stuff_values (omapi_object_t *c,
1657 omapi_object_t *id,
1658 omapi_object_t *h)
1660 struct pool *pool;
1661 isc_result_t status;
1663 if (h->type != dhcp_type_pool)
1664 return (DHCP_R_INVALIDARG);
1665 pool = (struct pool *)h;
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
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);
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);
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 */
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);
1699 return (ISC_R_SUCCESS);
1702 isc_result_t dhcp_pool_lookup (omapi_object_t **lp,
1703 omapi_object_t *id, omapi_object_t *ref)
1705 /* Can't look up pools yet. */
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;
1714 isc_result_t dhcp_pool_create (omapi_object_t **lp,
1715 omapi_object_t *id)
1717 return ISC_R_NOTIMPLEMENTED;
1720 isc_result_t dhcp_pool_remove (omapi_object_t *lp,
1721 omapi_object_t *id)
1723 return ISC_R_NOTIMPLEMENTED;
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)
1732 struct class *class;
1733 struct class *superclass = 0;
1734 isc_result_t status;
1735 int issubclass = (h -> type == dhcp_type_subclass);
1737 class = (struct class *)h;
1739 if (!omapi_ds_strcmp(name, "name")) {
1740 char *tname;
1742 if (class->name)
1743 return ISC_R_EXISTS;
1745 if ((tname = dmalloc(value->u.buffer.len + 1, MDL)) == NULL) {
1746 return ISC_R_NOMEMORY;
1749 /* tname is null terminated from dmalloc() */
1750 memcpy(tname, value->u.buffer.value, value->u.buffer.len);
1752 if (issubclass) {
1753 status = find_class(&superclass, tname, MDL);
1754 dfree(tname, MDL);
1756 if (status == ISC_R_NOTFOUND)
1757 return status;
1759 if (class->superclass != NULL)
1760 class_dereference(&class->superclass, MDL);
1761 class_reference(&class->superclass, superclass, MDL);
1763 if (class->group != NULL)
1764 group_dereference(&class->group, MDL);
1765 group_reference(&class->group, superclass->group, MDL);
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;
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;
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;
1790 return ISC_R_SUCCESS;
1794 if (issubclass && !omapi_ds_strcmp(name, "hashstring")) {
1795 if (class->hash_string.data)
1796 return ISC_R_EXISTS;
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;
1811 return ISC_R_SUCCESS;
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;
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;
1831 return ISC_R_SUCCESS;
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. */
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);
1845 if (!strncmp("hardware",
1846 (char *)value->u.buffer.value, minlen))
1848 if (!expression_allocate(&class->submatch, MDL))
1849 return ISC_R_NOMEMORY;
1851 class->submatch->op = expr_hardware;
1852 } else
1853 return DHCP_R_INVALIDARG;
1854 } else
1855 return DHCP_R_INVALIDARG;
1857 return ISC_R_SUCCESS;
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;
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;
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;
1887 return DHCP_R_UNKNOWNATTRIBUTE;
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)
1897 if (h -> type != dhcp_type_class)
1898 return DHCP_R_INVALIDARG;
1900 return class_set_value(h, id, name, value);
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)
1907 struct class *class;
1908 isc_result_t status;
1910 if (h -> type != dhcp_type_class)
1911 return DHCP_R_INVALIDARG;
1912 class = (struct class *)h;
1914 if (!omapi_ds_strcmp (name, "name"))
1915 return omapi_make_string_value (value, name, class -> name,
1916 MDL);
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;
1925 return DHCP_R_UNKNOWNATTRIBUTE;
1928 isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
1931 if (h -> type != dhcp_type_class && h -> type != dhcp_type_subclass)
1932 return DHCP_R_INVALIDARG;
1933 struct class *class = (struct class *)h;
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;
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);
1951 dfree (class -> billed_leases, file, line);
1952 class -> billed_leases = (struct lease **)0;
1954 if (class -> hash) {
1955 class_free_hash_table (&class -> hash, file, line);
1956 class -> hash = (class_hash_t *)0;
1958 data_string_forget (&class -> hash_string, file, line);
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);
1972 return ISC_R_SUCCESS;
1975 static isc_result_t
1976 class_signal_handler(omapi_object_t *h,
1977 const char *name, va_list ap)
1979 struct class *class = (struct class *)h;
1980 isc_result_t status;
1981 int updatep = 0;
1982 int issubclass;
1984 issubclass = (h->type == dhcp_type_subclass);
1986 if (!strcmp (name, "updated")) {
1988 if (!issubclass) {
1989 if (class->name == 0 || strlen(class->name) == 0) {
1990 return DHCP_R_INVALIDARG;
1992 } else {
1993 if (class->superclass == 0) {
1994 return DHCP_R_INVALIDARG; /* didn't give name */
1997 if (class->hash_string.data == NULL) {
1998 return DHCP_R_INVALIDARG;
2003 if (issubclass) {
2004 if (!class->superclass->hash)
2005 class_new_hash(&class->superclass->hash,
2006 SCLASS_HASH_SIZE, MDL);
2008 class_hash_add(class->superclass->hash,
2009 (const char *)class->hash_string.data,
2010 class->hash_string.len,
2011 (void *)class, MDL);
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);
2021 #endif
2023 status = enter_class (class, 1, 1);
2024 if (status != ISC_R_SUCCESS)
2025 return status;
2026 updatep = 1;
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;
2037 if (updatep)
2038 return ISC_R_SUCCESS;
2040 return ISC_R_NOTFOUND;
2044 isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
2045 const char *name, va_list ap)
2047 if (h -> type != dhcp_type_class)
2048 return DHCP_R_INVALIDARG;
2050 return class_signal_handler(h, name, ap);
2055 * Routine to put out generic class & subclass information
2057 static isc_result_t class_stuff_values (omapi_object_t *c,
2058 omapi_object_t *id,
2059 omapi_object_t *h)
2061 struct class *class;
2062 isc_result_t status;
2064 class = (struct class *)h;
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);
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);
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);
2086 return (ISC_R_SUCCESS);
2090 isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
2091 omapi_object_t *id,
2092 omapi_object_t *h)
2094 if (h->type != dhcp_type_class)
2095 return (DHCP_R_INVALIDARG);
2097 /* add any class specific items here */
2099 return (class_stuff_values(c, id, h));
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)
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;
2112 *lp = NULL;
2114 if (ref == NULL)
2115 return (DHCP_R_NOKEYS);
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);
2125 omapi_value_dereference(&nv, MDL);
2127 find_class(&class, name, MDL);
2129 dfree(name, MDL);
2131 if (class == NULL) {
2132 return (ISC_R_NOTFOUND);
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);
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);
2150 class_hash_lookup(&subclass, class->hash,
2151 (const char *)
2152 hv->value->u.buffer.value,
2153 hv->value->u.buffer.len, MDL);
2155 omapi_value_dereference(&hv, MDL);
2157 class_dereference(&class, MDL);
2159 if (subclass == NULL) {
2160 return (ISC_R_NOTFOUND);
2163 class_reference(&class, subclass, MDL);
2164 class_dereference(&subclass, MDL);
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);
2173 if (class->flags & CLASS_DECL_DELETED) {
2174 class_dereference(&class, MDL);
2175 return (ISC_R_NOTFOUND);
2178 omapi_object_reference(lp, (omapi_object_t *)class, MDL);
2179 class_dereference(&class, MDL);
2181 return (ISC_R_SUCCESS);
2184 return (DHCP_R_NOKEYS);
2188 isc_result_t dhcp_class_lookup (omapi_object_t **lp,
2189 omapi_object_t *id, omapi_object_t *ref)
2191 return class_lookup(lp, id, ref, dhcp_type_class);
2194 isc_result_t dhcp_class_create (omapi_object_t **lp,
2195 omapi_object_t *id)
2197 struct class *cp = 0;
2198 isc_result_t status;
2200 status = class_allocate(&cp, MDL);
2201 if (status != ISC_R_SUCCESS)
2202 return (status);
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);
2211 isc_result_t dhcp_class_remove (omapi_object_t *lp,
2212 omapi_object_t *id)
2214 struct class *cp;
2215 if (lp -> type != dhcp_type_class)
2216 return DHCP_R_INVALIDARG;
2217 cp = (struct class *)lp;
2219 #ifdef DEBUG_OMAPI
2220 log_debug ("OMAPI delete class %s", cp -> name);
2221 #endif
2223 delete_class (cp, 1);
2224 return ISC_R_SUCCESS;
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)
2232 if (h -> type != dhcp_type_subclass)
2233 return DHCP_R_INVALIDARG;
2235 return class_set_value(h, id, name, value);
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)
2243 struct class *subclass;
2244 isc_result_t status;
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;
2252 /* XXXJAB No values to get yet. */
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;
2261 return DHCP_R_UNKNOWNATTRIBUTE;
2264 isc_result_t dhcp_subclass_signal_handler (omapi_object_t *h,
2265 const char *name, va_list ap)
2267 if (h -> type != dhcp_type_subclass)
2268 return DHCP_R_INVALIDARG;
2270 return class_signal_handler(h, name, ap);
2274 isc_result_t dhcp_subclass_stuff_values (omapi_object_t *c,
2275 omapi_object_t *id,
2276 omapi_object_t *h)
2278 struct class *subclass;
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);
2286 /* add any subclass specific items here */
2288 return (class_stuff_values(c, id, h));
2291 isc_result_t dhcp_subclass_lookup (omapi_object_t **lp,
2292 omapi_object_t *id, omapi_object_t *ref)
2294 return class_lookup(lp, id, ref, dhcp_type_subclass);
2300 isc_result_t dhcp_subclass_create (omapi_object_t **lp,
2301 omapi_object_t *id)
2303 struct class *cp = 0;
2304 isc_result_t status;
2306 status = subclass_allocate(&cp, MDL);
2307 if (status != ISC_R_SUCCESS)
2308 return status;
2309 group_reference (&cp->group, root_group, MDL);
2311 cp->flags = CLASS_DECL_DYNAMIC;
2313 status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
2314 subclass_dereference (&cp, MDL);
2315 return status;
2318 isc_result_t dhcp_subclass_remove (omapi_object_t *lp,
2319 omapi_object_t *id)
2321 struct class *cp;
2322 if (lp -> type != dhcp_type_subclass)
2323 return DHCP_R_INVALIDARG;
2324 cp = (struct class *)lp;
2326 #ifdef DEBUG_OMAPI
2327 log_debug ("OMAPI delete subclass %s", cp -> name);
2328 #endif
2330 delete_class (cp, 1);
2332 return ISC_R_SUCCESS;
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)
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;
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;
2360 nv = (struct binding_value *)0;
2361 if (!binding_value_allocate (&nv, MDL)) {
2362 dfree (nname, MDL);
2363 return ISC_R_NOMEMORY;
2365 switch (value -> type) {
2366 case omapi_datatype_int:
2367 nv -> type = binding_numeric;
2368 nv -> value.intval = value -> u.integer;
2369 break;
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;
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;
2384 case omapi_datatype_object:
2385 binding_value_dereference (&nv, MDL);
2386 dfree (nname, MDL);
2387 return DHCP_R_INVALIDARG;
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;
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);
2406 binding_value_reference (&bp -> value, nv, MDL);
2407 binding_value_dereference (&nv, MDL);
2408 return ISC_R_SUCCESS;
2411 isc_result_t binding_scope_get_value (omapi_value_t **value,
2412 struct binding_scope *scope,
2413 omapi_data_string_t *name)
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;
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;
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;
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;
2456 /* Can't return values for these two (yet?). */
2457 case binding_dns:
2458 case binding_function:
2459 return DHCP_R_INVALIDARG;
2461 default:
2462 log_fatal ("Impossible case at %s:%d.", MDL);
2463 return ISC_R_FAILURE;
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;
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);
2478 return ISC_R_SUCCESS;
2481 isc_result_t binding_scope_stuff_values (omapi_object_t *c,
2482 struct binding_scope *scope)
2484 struct binding *bp;
2485 unsigned len;
2486 isc_result_t status;
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;
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;
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
2513 ((u_int32_t)(bp -> value -> value.boolean))));
2514 if (status != ISC_R_SUCCESS)
2515 return status;
2516 break;
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;
2530 break;
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;
2545 /* NOTREACHED */
2546 case binding_dns:
2547 case binding_function:
2548 break;
2552 return ISC_R_SUCCESS;
2555 /* vim: set tabstop=8: */