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