1 /* $NetBSD: dhcpctl.c,v 1.3 2022/04/03 01:10:58 christos Exp $ */ 2 3 /* dhcpctl.c 4 5 Subroutines providing general support for objects. */ 6 7 /* 8 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC") 9 * Copyright (c) 1999-2003 by Internet Software Consortium 10 * 11 * This Source Code Form is subject to the terms of the Mozilla Public 12 * License, v. 2.0. If a copy of the MPL was not distributed with this 13 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 * 23 * Internet Systems Consortium, Inc. 24 * PO Box 360 25 * Newmarket, NH 03857 USA 26 * <info@isc.org> 27 * https://www.isc.org/ 28 * 29 */ 30 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: dhcpctl.c,v 1.3 2022/04/03 01:10:58 christos Exp $"); 33 34 #include "dhcpd.h" 35 #include <omapip/omapip_p.h> 36 #include "dhcpctl.h" 37 #include <sys/time.h> 38 39 /* #define DEBUG_DHCPCTL 1 */ 40 41 omapi_object_type_t *dhcpctl_callback_type; 42 omapi_object_type_t *dhcpctl_remote_type; 43 44 /* dhcpctl_initialize () 45 46 Must be called before any other dhcpctl function. */ 47 48 dhcpctl_status dhcpctl_initialize () 49 { 50 isc_result_t status; 51 52 /* Set up the isc and dns library managers */ 53 status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB, 54 NULL, NULL); 55 if (status != ISC_R_SUCCESS) 56 return status; 57 58 status = omapi_init(); 59 if (status != ISC_R_SUCCESS) 60 return status; 61 62 status = omapi_object_type_register (&dhcpctl_callback_type, 63 "dhcpctl-callback", 64 dhcpctl_callback_set_value, 65 dhcpctl_callback_get_value, 66 dhcpctl_callback_destroy, 67 dhcpctl_callback_signal_handler, 68 dhcpctl_callback_stuff_values, 69 0, 0, 0, 0, 0, 0, 70 sizeof 71 (dhcpctl_callback_object_t), 0, 72 RC_MISC); 73 if (status != ISC_R_SUCCESS) 74 return status; 75 76 status = omapi_object_type_register (&dhcpctl_remote_type, 77 "dhcpctl-remote", 78 dhcpctl_remote_set_value, 79 dhcpctl_remote_get_value, 80 dhcpctl_remote_destroy, 81 dhcpctl_remote_signal_handler, 82 dhcpctl_remote_stuff_values, 83 0, 0, 0, 0, 0, 0, 84 sizeof (dhcpctl_remote_object_t), 85 0, RC_MISC); 86 if (status != ISC_R_SUCCESS) 87 return status; 88 89 return ISC_R_SUCCESS; 90 } 91 92 /* dhcpctl_connect 93 94 synchronous 95 returns nonzero status code if it didn't connect, zero otherwise 96 stores connection handle through connection, which can be used 97 for subsequent access to the specified server. 98 server_name is the name of the server, and port is the TCP 99 port on which it is listening. 100 authinfo is the handle to an object containing authentication 101 information. */ 102 103 dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection, 104 const char *server_name, int port, 105 dhcpctl_handle authinfo) 106 { 107 isc_result_t status; 108 #ifdef DEBUG_DHCPCTL 109 log_debug("dhcpctl_connect(%s:%d)", server_name, port); 110 #endif 111 112 status = omapi_generic_new (connection, MDL); 113 if (status != ISC_R_SUCCESS) { 114 return status; 115 } 116 117 status = omapi_protocol_connect (*connection, server_name, 118 (unsigned)port, authinfo); 119 if (status == ISC_R_SUCCESS) { 120 #ifdef DEBUG_DHCPCTL 121 log_debug("dhcpctl_connect success"); 122 #endif 123 return status; 124 } 125 126 if (status != DHCP_R_INCOMPLETE) { 127 omapi_object_dereference (connection, MDL); 128 #ifdef DEBUG_DHCPCTL 129 log_debug("dhcpctl_connect failed:%s", 130 isc_result_totext (status)); 131 #endif 132 return status; 133 } 134 135 status = omapi_wait_for_completion (*connection, 0); 136 if (status != ISC_R_SUCCESS) { 137 omapi_object_dereference (connection, MDL); 138 #ifdef DEBUG_DHCPCTL 139 log_debug("dhcpctl_connect, wait failed:%s", 140 isc_result_totext (status)); 141 #endif 142 return status; 143 } 144 145 #ifdef DEBUG_DHCPCTL 146 log_debug("dhcpctl_connect success"); 147 #endif 148 return status; 149 } 150 151 /* dhcpctl_timed_connect 152 153 synchronous 154 returns nonzero status code if it didn't connect, zero otherwise 155 stores connection handle through connection, which can be used 156 for subsequent access to the specified server. 157 server_name is the name of the server, and port is the TCP 158 port on which it is listening. 159 authinfo is the handle to an object containing authentication 160 information. 161 How long the function waits for the connection to complete is 162 dictated by the value of the parameter, t. If the value is nul, 163 it will wait indefinitely. Otherwise it will wait for the amount 164 of time specified by t (tv_sec:tv_usec). Values of zero for both 165 fields are valid but not recommended. */ 166 dhcpctl_status dhcpctl_timed_connect (dhcpctl_handle *connection, 167 const char *server_name, int port, 168 dhcpctl_handle authinfo, 169 struct timeval *t) 170 { 171 isc_result_t status; 172 #ifdef DEBUG_DHCPCTL 173 log_debug("dhcpctl_timed_connect(%s:%d)", server_name, port); 174 #endif 175 status = omapi_generic_new (connection, MDL); 176 if (status != ISC_R_SUCCESS) { 177 return status; 178 } 179 180 status = omapi_protocol_connect (*connection, server_name, 181 (unsigned)port, authinfo); 182 183 if (status == ISC_R_SUCCESS) { 184 return status; 185 } 186 187 if (status == DHCP_R_INCOMPLETE) { 188 isc_result_t wait_status = ISC_R_SUCCESS; 189 190 /* Wait for it to complete */ 191 status = dhcpctl_timed_wait_for_completion(*connection, 192 &wait_status, t); 193 if (status == ISC_R_SUCCESS) { 194 status = wait_status; 195 } 196 } 197 198 if (status != ISC_R_SUCCESS) { 199 omapi_object_dereference (connection, MDL); 200 } 201 return status; 202 } 203 204 /* dhcpctl_wait_for_completion 205 206 synchronous 207 returns zero if the callback completes, a nonzero status if 208 there was some problem relating to the wait operation. The 209 status of the queued request will be stored through s, and 210 will also be either zero for success or nonzero for some kind 211 of failure. Never returns until completion or until the 212 connection to the server is lost. This performs the same 213 function as dhcpctl_set_callback and the subsequent callback, 214 for programs that want to do inline execution instead of using 215 callbacks. */ 216 217 dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h, 218 dhcpctl_status *s) 219 { 220 #ifdef DEBUG_DHCPCTL 221 log_debug("dhcpctl_wait_for_completion"); 222 #endif 223 isc_result_t status; 224 status = omapi_wait_for_completion (h, 0); 225 if (status != ISC_R_SUCCESS) { 226 return status; 227 } 228 if (h -> type == dhcpctl_remote_type) 229 *s = ((dhcpctl_remote_object_t *)h) -> waitstatus; 230 231 return ISC_R_SUCCESS; 232 } 233 234 /* dhcpctl_timed_wait_for_completion 235 236 synchronous 237 returns zero if the callback completes, a nonzero status if 238 there was some problem relating to the wait operation. The 239 status of the queued request will be stored through s, and 240 will also be either zero for success or nonzero for some kind 241 of failure. How long the function waits for a response is 242 dictated by the value of the parameter, t. If the value is nul, 243 it will wait indefinitely or until the connection is lost. 244 Otherwise it will wait for the amount of time specified by t 245 (tv_sec:tv_usec). Values of zero for both fields are valid 246 but not recommended. The result of the request as processed on the 247 server is returned via the parameter, s. This performs the same 248 function as dhcpctl_set_callback and the subsequent callback, 249 for programs that want to do inline execution instead of using 250 callbacks. */ 251 252 dhcpctl_status dhcpctl_timed_wait_for_completion (dhcpctl_handle h, 253 dhcpctl_status *s, 254 struct timeval *t) 255 { 256 isc_result_t status; 257 struct timeval adjusted_t; 258 259 #ifdef DEBUG_DHCPCTL 260 if (t) { 261 log_debug ("dhcpctl_timed_wait_for_completion" 262 "(%u.%u secs.usecs)", 263 (unsigned int)(t->tv_sec), 264 (unsigned int)(t->tv_usec)); 265 } else { 266 log_debug ("dhcpctl_timed_wait_for_completion(no timeout)"); 267 } 268 #endif 269 270 if (t) { 271 struct timeval now; 272 gettimeofday (&now, (struct timezone *)0); 273 adjusted_t.tv_sec = now.tv_sec + t->tv_sec; 274 adjusted_t.tv_usec = now.tv_usec + t->tv_usec; 275 } 276 277 status = omapi_wait_for_completion (h, (t ? &adjusted_t : 0)); 278 if (status != ISC_R_SUCCESS) { 279 return status; 280 } 281 282 if (h->type == dhcpctl_remote_type) { 283 *s = ((dhcpctl_remote_object_t *)h)->waitstatus; 284 } 285 286 return ISC_R_SUCCESS; 287 } 288 289 290 /* dhcpctl_get_value 291 292 synchronous 293 returns zero if the call succeeded, a nonzero status code if 294 it didn't. 295 result is the address of an empty data string (initialized 296 with bzero or cleared with data_string_forget). On 297 successful completion, the addressed data string will contain 298 the value that was fetched. 299 dhcpctl_handle refers to some dhcpctl item 300 value_name refers to some value related to that item - e.g., 301 for a handle associated with a completed host lookup, value 302 could be one of "hardware-address", "dhcp-client-identifier", 303 "known" or "client-hostname". */ 304 305 dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result, 306 dhcpctl_handle h, const char *value_name) 307 { 308 isc_result_t status; 309 omapi_value_t *tv = (omapi_value_t *)0; 310 unsigned len; 311 int ip; 312 #ifdef DEBUG_DHCPCTL 313 log_debug("dhcpctl_get_value(%s)", value_name); 314 #endif 315 316 status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv); 317 if (status != ISC_R_SUCCESS) 318 return status; 319 320 switch (tv -> value -> type) { 321 case omapi_datatype_int: 322 len = sizeof (int); 323 break; 324 325 case omapi_datatype_string: 326 case omapi_datatype_data: 327 len = tv -> value -> u.buffer.len; 328 break; 329 330 case omapi_datatype_object: 331 len = sizeof (omapi_handle_t); 332 break; 333 334 default: 335 omapi_typed_data_dereference (&tv -> value, MDL); 336 return ISC_R_UNEXPECTED; 337 } 338 339 status = omapi_data_string_new (result, len, MDL); 340 if (status != ISC_R_SUCCESS) { 341 omapi_typed_data_dereference (&tv -> value, MDL); 342 return status; 343 } 344 345 switch (tv -> value -> type) { 346 case omapi_datatype_int: 347 ip = htonl (tv -> value -> u.integer); 348 memcpy ((*result) -> value, &ip, sizeof ip); 349 break; 350 351 case omapi_datatype_string: 352 case omapi_datatype_data: 353 memcpy ((*result) -> value, 354 tv -> value -> u.buffer.value, 355 tv -> value -> u.buffer.len); 356 break; 357 358 case omapi_datatype_object: 359 ip = htonl (tv -> value -> u.object -> handle); 360 memcpy ((*result) -> value, &ip, sizeof ip); 361 break; 362 } 363 364 omapi_value_dereference (&tv, MDL); 365 return ISC_R_SUCCESS; 366 } 367 368 /* dhcpctl_get_boolean 369 370 like dhcpctl_get_value, but more convenient for boolean 371 values, since no data_string needs to be dealt with. */ 372 373 dhcpctl_status dhcpctl_get_boolean (int *result, 374 dhcpctl_handle h, const char *value_name) 375 { 376 isc_result_t status; 377 dhcpctl_data_string data = (dhcpctl_data_string)0; 378 int rv; 379 380 #ifdef DEBUG_DHCPCTL 381 log_debug("dhcpctl_get_boolean(%s)", value_name); 382 #endif 383 384 status = dhcpctl_get_value (&data, h, value_name); 385 if (status != ISC_R_SUCCESS) 386 return status; 387 if (data -> len != sizeof rv) { 388 omapi_data_string_dereference (&data, MDL); 389 return ISC_R_UNEXPECTED; 390 } 391 memcpy (&rv, data -> value, sizeof rv); 392 *result = ntohl (rv); 393 omapi_data_string_dereference (&data, MDL); 394 return ISC_R_SUCCESS; 395 } 396 397 /* dhcpctl_set_value 398 399 Sets a value on an object referred to by a dhcpctl_handle. 400 The opposite of dhcpctl_get_value. Does not update the 401 server - just sets the value on the handle. */ 402 403 dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, dhcpctl_data_string value, 404 const char *value_name) 405 { 406 isc_result_t status; 407 omapi_typed_data_t *tv = (omapi_typed_data_t *)0; 408 omapi_data_string_t *name = (omapi_data_string_t *)0; 409 #ifdef DEBUG_DHCPCTL 410 log_debug("dhcpctl_set_value(%s)", value_name); 411 #endif 412 413 status = omapi_data_string_new (&name, strlen (value_name), MDL); 414 if (status != ISC_R_SUCCESS) 415 return status; 416 memcpy (name -> value, value_name, strlen (value_name)); 417 418 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data, 419 value -> len); 420 if (status != ISC_R_SUCCESS) { 421 omapi_data_string_dereference (&name, MDL); 422 return status; 423 } 424 memcpy (tv -> u.buffer.value, value -> value, value -> len); 425 426 status = omapi_set_value (h, (omapi_object_t *)0, name, tv); 427 omapi_data_string_dereference (&name, MDL); 428 omapi_typed_data_dereference (&tv, MDL); 429 return status; 430 } 431 432 /* dhcpctl_set_string_value 433 434 Sets a NUL-terminated ASCII value on an object referred to by 435 a dhcpctl_handle. like dhcpctl_set_value, but saves the 436 trouble of creating a data_string for a NUL-terminated string. 437 Does not update the server - just sets the value on the handle. */ 438 439 dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, const char *value, 440 const char *value_name) 441 { 442 isc_result_t status; 443 omapi_typed_data_t *tv = (omapi_typed_data_t *)0; 444 omapi_data_string_t *name = (omapi_data_string_t *)0; 445 #ifdef DEBUG_DHCPCTL 446 log_debug("dhcpctl_set_string_value(%s)", value_name); 447 #endif 448 449 status = omapi_data_string_new (&name, strlen (value_name), MDL); 450 if (status != ISC_R_SUCCESS) 451 return status; 452 memcpy (name -> value, value_name, strlen (value_name)); 453 454 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value); 455 if (status != ISC_R_SUCCESS) { 456 omapi_data_string_dereference (&name, MDL); 457 return status; 458 } 459 460 status = omapi_set_value (h, (omapi_object_t *)0, name, tv); 461 omapi_data_string_dereference (&name, MDL); 462 omapi_typed_data_dereference (&tv, MDL); 463 return status; 464 } 465 466 /* dhcpctl_set_buffer_value 467 468 Sets a value on an object referred to by a dhcpctl_handle. like 469 dhcpctl_set_value, but saves the trouble of creating a data_string 470 for string for which we have a buffer and length. Does not update 471 the server - just sets the value on the handle. */ 472 473 dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h, 474 const char *value, unsigned len, 475 const char *value_name) 476 { 477 isc_result_t status; 478 omapi_typed_data_t *tv = (omapi_typed_data_t *)0; 479 omapi_data_string_t *name = (omapi_data_string_t *)0; 480 unsigned ll; 481 #ifdef DEBUG_DHCPCTL 482 log_debug("dhcpctl_set_data_value(%s)", value_name); 483 #endif 484 485 ll = strlen (value_name); 486 status = omapi_data_string_new (&name, ll, MDL); 487 if (status != ISC_R_SUCCESS) 488 return status; 489 memcpy (name -> value, value_name, ll); 490 491 status = omapi_typed_data_new (MDL, &tv, 492 omapi_datatype_data, len, value); 493 if (status != ISC_R_SUCCESS) { 494 omapi_data_string_dereference (&name, MDL); 495 return status; 496 } 497 memcpy (tv -> u.buffer.value, value, len); 498 499 status = omapi_set_value (h, (omapi_object_t *)0, name, tv); 500 omapi_data_string_dereference (&name, MDL); 501 omapi_typed_data_dereference (&tv, MDL); 502 return status; 503 } 504 505 /* dhcpctl_set_null_value 506 507 Sets a null value on an object referred to by a dhcpctl_handle. */ 508 509 dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h, 510 const char *value_name) 511 { 512 isc_result_t status; 513 omapi_data_string_t *name = (omapi_data_string_t *)0; 514 unsigned ll; 515 #ifdef DEBUG_DHCPCTL 516 log_debug("dhcpctl_set_null_value(%s)", value_name); 517 #endif 518 519 ll = strlen (value_name); 520 status = omapi_data_string_new (&name, ll, MDL); 521 if (status != ISC_R_SUCCESS) 522 return status; 523 memcpy (name -> value, value_name, ll); 524 525 status = omapi_set_value (h, (omapi_object_t *)0, name, 526 (omapi_typed_data_t *)0); 527 omapi_data_string_dereference (&name, MDL); 528 return status; 529 } 530 531 /* dhcpctl_set_boolean_value 532 533 Sets a boolean value on an object - like dhcpctl_set_value, 534 only more convenient for booleans. */ 535 536 dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle h, int value, 537 const char *value_name) 538 { 539 isc_result_t status; 540 omapi_typed_data_t *tv = (omapi_typed_data_t *)0; 541 omapi_data_string_t *name = (omapi_data_string_t *)0; 542 #ifdef DEBUG_DHCPCTL 543 log_debug("dhcpctl_set_boolean_value(%s)", value_name); 544 #endif 545 546 status = omapi_data_string_new (&name, strlen (value_name), MDL); 547 if (status != ISC_R_SUCCESS) 548 return status; 549 memcpy (name -> value, value_name, strlen (value_name)); 550 551 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value); 552 if (status != ISC_R_SUCCESS) { 553 omapi_data_string_dereference (&name, MDL); 554 return status; 555 } 556 557 status = omapi_set_value (h, (omapi_object_t *)0, name, tv); 558 omapi_data_string_dereference (&name, MDL); 559 omapi_typed_data_dereference (&tv, MDL); 560 return status; 561 } 562 563 /* dhcpctl_set_int_value 564 565 Sets a boolean value on an object - like dhcpctl_set_value, 566 only more convenient for booleans. */ 567 568 dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value, 569 const char *value_name) 570 { 571 isc_result_t status; 572 omapi_typed_data_t *tv = (omapi_typed_data_t *)0; 573 omapi_data_string_t *name = (omapi_data_string_t *)0; 574 #ifdef DEBUG_DHCPCTL 575 log_debug("dhcpctl_set_int_value(%s)", value_name); 576 #endif 577 578 status = omapi_data_string_new (&name, strlen (value_name), MDL); 579 if (status != ISC_R_SUCCESS) 580 return status; 581 memcpy (name -> value, value_name, strlen (value_name)); 582 583 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value); 584 if (status != ISC_R_SUCCESS) { 585 omapi_data_string_dereference (&name, MDL); 586 return status; 587 } 588 589 status = omapi_set_value (h, (omapi_object_t *)0, name, tv); 590 omapi_data_string_dereference (&name, MDL); 591 omapi_typed_data_dereference (&tv, MDL); 592 return status; 593 } 594 595 /* dhcpctl_object_update 596 597 Queues an update on the object referenced by the handle (there 598 can't be any other work in progress on the handle). An 599 update means local parameters will be sent to the server. */ 600 601 dhcpctl_status dhcpctl_object_update (dhcpctl_handle connection, 602 dhcpctl_handle h) 603 { 604 isc_result_t status; 605 omapi_object_t *message = (omapi_object_t *)0; 606 dhcpctl_remote_object_t *ro; 607 #ifdef DEBUG_DHCPCTL 608 log_debug("dhcpctl_object_update"); 609 #endif 610 611 if (h -> type != dhcpctl_remote_type) 612 return DHCP_R_INVALIDARG; 613 ro = (dhcpctl_remote_object_t *)h; 614 615 status = omapi_message_new (&message, MDL); 616 if (status != ISC_R_SUCCESS) { 617 omapi_object_dereference (&message, MDL); 618 return status; 619 } 620 status = omapi_set_int_value (message, (omapi_object_t *)0, 621 "op", OMAPI_OP_UPDATE); 622 if (status != ISC_R_SUCCESS) { 623 omapi_object_dereference (&message, MDL); 624 return status; 625 } 626 627 status = omapi_set_object_value (message, (omapi_object_t *)0, 628 "object", h); 629 if (status != ISC_R_SUCCESS) { 630 omapi_object_dereference (&message, MDL); 631 return status; 632 } 633 634 status = omapi_set_int_value (message, (omapi_object_t *)0, "handle", 635 (int)(ro -> remote_handle)); 636 if (status != ISC_R_SUCCESS) { 637 omapi_object_dereference (&message, MDL); 638 return status; 639 } 640 641 omapi_message_register (message); 642 status = omapi_protocol_send_message (connection -> outer, 643 (omapi_object_t *)0, 644 message, (omapi_object_t *)0); 645 omapi_object_dereference (&message, MDL); 646 return status; 647 } 648 649 /* Requests a refresh on the object referenced by the handle (there 650 can't be any other work in progress on the handle). A 651 refresh means local parameters are updated from the server. */ 652 653 dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle connection, 654 dhcpctl_handle h) 655 { 656 isc_result_t status; 657 omapi_object_t *message = (omapi_object_t *)0; 658 dhcpctl_remote_object_t *ro; 659 #ifdef DEBUG_DHCPCTL 660 log_debug("dhcpctl_object_refresh"); 661 #endif 662 663 if (h -> type != dhcpctl_remote_type) 664 return DHCP_R_INVALIDARG; 665 ro = (dhcpctl_remote_object_t *)h; 666 667 status = omapi_message_new (&message, MDL); 668 if (status != ISC_R_SUCCESS) { 669 omapi_object_dereference (&message, MDL); 670 return status; 671 } 672 status = omapi_set_int_value (message, (omapi_object_t *)0, 673 "op", OMAPI_OP_REFRESH); 674 if (status != ISC_R_SUCCESS) { 675 omapi_object_dereference (&message, MDL); 676 return status; 677 } 678 status = omapi_set_int_value (message, (omapi_object_t *)0, 679 "handle", (int)(ro -> remote_handle)); 680 if (status != ISC_R_SUCCESS) { 681 omapi_object_dereference (&message, MDL); 682 return status; 683 } 684 685 omapi_message_register (message); 686 status = omapi_protocol_send_message (connection -> outer, 687 (omapi_object_t *)0, 688 message, (omapi_object_t *)0); 689 690 /* We don't want to send the contents of the object down the 691 wire, but we do need to reference it so that we know what 692 to do with the update. */ 693 status = omapi_set_object_value (message, (omapi_object_t *)0, 694 "object", h); 695 if (status != ISC_R_SUCCESS) { 696 omapi_object_dereference (&message, MDL); 697 return status; 698 } 699 700 omapi_object_dereference (&message, MDL); 701 return status; 702 } 703 704 /* Requests the removal of the object referenced by the handle (there 705 can't be any other work in progress on the handle). A 706 removal means that all searchable references to the object on the 707 server are deleted. */ 708 709 dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection, 710 dhcpctl_handle h) 711 { 712 isc_result_t status; 713 omapi_object_t *message = (omapi_object_t *)0; 714 dhcpctl_remote_object_t *ro; 715 #ifdef DEBUG_DHCPCTL 716 log_debug("dhcpctl_object_remove"); 717 #endif 718 719 if (h -> type != dhcpctl_remote_type) 720 return DHCP_R_INVALIDARG; 721 ro = (dhcpctl_remote_object_t *)h; 722 723 status = omapi_message_new (&message, MDL); 724 if (status != ISC_R_SUCCESS) { 725 omapi_object_dereference (&message, MDL); 726 return status; 727 } 728 status = omapi_set_int_value (message, (omapi_object_t *)0, 729 "op", OMAPI_OP_DELETE); 730 if (status != ISC_R_SUCCESS) { 731 omapi_object_dereference (&message, MDL); 732 return status; 733 } 734 735 status = omapi_set_int_value (message, (omapi_object_t *)0, "handle", 736 (int)(ro -> remote_handle)); 737 if (status != ISC_R_SUCCESS) { 738 omapi_object_dereference (&message, MDL); 739 return status; 740 } 741 742 status = omapi_set_object_value (message, (omapi_object_t *)0, 743 "notify-object", h); 744 if (status != ISC_R_SUCCESS) { 745 omapi_object_dereference (&message, MDL); 746 return status; 747 } 748 749 omapi_message_register (message); 750 status = omapi_protocol_send_message (connection -> outer, 751 (omapi_object_t *)0, 752 message, (omapi_object_t *)0); 753 omapi_object_dereference (&message, MDL); 754 return status; 755 } 756 757 isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *vp, 758 const char *file, int line) 759 { 760 #ifdef DEBUG_DHCPCTL 761 log_debug("dhcpctl_data_string_dereference"); 762 #endif 763 return omapi_data_string_dereference (vp, file, line); 764 } 765 766 dhcpctl_status dhcpctl_disconnect (dhcpctl_handle *connection, 767 int force) 768 { 769 isc_result_t status; 770 #ifdef DEBUG_DHCPCTL 771 log_debug("dhcpctl_disconnect()"); 772 #endif 773 if (!connection || !((*connection)->outer) || 774 !((*connection)->outer->type) || 775 ((*connection)->outer->type != omapi_type_protocol) || 776 !((*connection)->outer->outer)) { 777 log_debug("dhcpctl_disconnect detected invalid arg"); 778 return DHCP_R_INVALIDARG; 779 } 780 781 status = omapi_disconnect ((*connection)->outer->outer, force); 782 if (status == ISC_R_SUCCESS) { 783 #ifdef DEBUG_DHCPCTL 784 log_debug("dhcpctl_disconnect success"); 785 #endif 786 omapi_object_dereference (connection, MDL); 787 return status; 788 } 789 790 #ifdef DEBUG_DHCPCTL 791 log_debug("dhcpctl_disconnect failed:%s", 792 isc_result_totext (status)); 793 #endif 794 return status; 795 } 796 797