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