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