1 /* $NetBSD: buffer.c,v 1.2 2018/04/07 22:37:30 christos Exp $ */ 2 3 /* buffer.c 4 5 Buffer access functions for the object management protocol... */ 6 7 /* 8 * Copyright (c) 2004-2017 by 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 * 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: buffer.c,v 1.2 2018/04/07 22:37:30 christos Exp $"); 33 34 #include "dhcpd.h" 35 36 #include <omapip/omapip_p.h> 37 #include <errno.h> 38 39 #if defined (TRACING) 40 static void trace_connection_input_input (trace_type_t *, unsigned, char *); 41 static void trace_connection_input_stop (trace_type_t *); 42 static void trace_connection_output_input (trace_type_t *, unsigned, char *); 43 static void trace_connection_output_stop (trace_type_t *); 44 static trace_type_t *trace_connection_input; 45 static trace_type_t *trace_connection_output; 46 static isc_result_t omapi_connection_reader_trace (omapi_object_t *, 47 unsigned, char *, 48 unsigned *); 49 extern omapi_array_t *omapi_connections; 50 51 void omapi_buffer_trace_setup () 52 { 53 trace_connection_input = 54 trace_type_register ("connection-input", 55 (void *)0, 56 trace_connection_input_input, 57 trace_connection_input_stop, MDL); 58 trace_connection_output = 59 trace_type_register ("connection-output", 60 (void *)0, 61 trace_connection_output_input, 62 trace_connection_output_stop, MDL); 63 } 64 65 static void trace_connection_input_input (trace_type_t *ttype, 66 unsigned length, char *buf) 67 { 68 unsigned left, taken, cc = 0; 69 char *s; 70 int32_t connect_index; 71 isc_result_t status; 72 omapi_connection_object_t *c = (omapi_connection_object_t *)0; 73 74 memcpy (&connect_index, buf, sizeof connect_index); 75 connect_index = ntohl (connect_index); 76 77 omapi_array_foreach_begin (omapi_connections, 78 omapi_connection_object_t, lp) { 79 if (lp -> index == ntohl (connect_index)) { 80 omapi_connection_reference (&c, lp, MDL); 81 omapi_connection_dereference (&lp, MDL); 82 break; 83 } 84 } omapi_array_foreach_end (omapi_connections, 85 omapi_connection_object_t, lp); 86 87 if (!c) { 88 log_error ("trace connection input: no connection index %ld", 89 (long int)connect_index); 90 return; 91 } 92 93 s = buf + sizeof connect_index; 94 left = length - sizeof connect_index; 95 96 while (left) { 97 taken = 0; 98 status = omapi_connection_reader_trace ((omapi_object_t *)c, 99 left, s, &taken); 100 if (status != ISC_R_SUCCESS) { 101 log_error ("trace connection input: %s", 102 isc_result_totext (status)); 103 break; 104 } 105 if (!taken) { 106 if (cc > 0) { 107 log_error ("trace connection_input: %s", 108 "input is not being consumed."); 109 break; 110 } 111 cc++; 112 } else { 113 cc = 0; 114 left -= taken; 115 } 116 } 117 omapi_connection_dereference (&c, MDL); 118 } 119 120 static void trace_connection_input_stop (trace_type_t *ttype) { } 121 122 static void trace_connection_output_input (trace_type_t *ttype, 123 unsigned length, char *buf) 124 { 125 /* We *could* check to see if the output is correct, but for now 126 we aren't going to do that. */ 127 } 128 129 static void trace_connection_output_stop (trace_type_t *ttype) { } 130 131 #endif 132 133 /* Make sure that at least len bytes are in the input buffer, and if not, 134 read enough bytes to make up the difference. */ 135 136 isc_result_t omapi_connection_reader (omapi_object_t *h) 137 { 138 #if defined (TRACING) 139 return omapi_connection_reader_trace (h, 0, (char *)0, (unsigned *)0); 140 } 141 142 static isc_result_t omapi_connection_reader_trace (omapi_object_t *h, 143 unsigned stuff_len, 144 char *stuff_buf, 145 unsigned *stuff_taken) 146 { 147 #endif 148 omapi_buffer_t *buffer; 149 isc_result_t status; 150 unsigned read_len; 151 int read_status; 152 omapi_connection_object_t *c; 153 unsigned bytes_to_read; 154 155 if (!h || h -> type != omapi_type_connection) 156 return DHCP_R_INVALIDARG; 157 c = (omapi_connection_object_t *)h; 158 159 /* See if there are enough bytes. */ 160 if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 && 161 c -> in_bytes > c -> bytes_needed) 162 return ISC_R_SUCCESS; 163 164 165 if (c -> inbufs) { 166 for (buffer = c -> inbufs; buffer -> next; 167 buffer = buffer -> next) 168 ; 169 if (!BUFFER_BYTES_FREE (buffer)) { 170 status = omapi_buffer_new (&buffer -> next, MDL); 171 if (status != ISC_R_SUCCESS) 172 return status; 173 buffer = buffer -> next; 174 } 175 } else { 176 status = omapi_buffer_new (&c -> inbufs, MDL); 177 if (status != ISC_R_SUCCESS) 178 return status; 179 buffer = c -> inbufs; 180 } 181 182 bytes_to_read = BUFFER_BYTES_FREE (buffer); 183 184 while (bytes_to_read) { 185 if (buffer -> tail > buffer -> head) 186 read_len = sizeof (buffer -> buf) - buffer -> tail; 187 else 188 read_len = buffer -> head - buffer -> tail; 189 190 #if defined (TRACING) 191 if (trace_playback()) { 192 if (stuff_len) { 193 if (read_len > stuff_len) 194 read_len = stuff_len; 195 if (stuff_taken) 196 *stuff_taken += read_len; 197 memcpy (&buffer -> buf [buffer -> tail], 198 stuff_buf, read_len); 199 stuff_len -= read_len; 200 stuff_buf += read_len; 201 read_status = read_len; 202 } else { 203 break; 204 } 205 } else 206 #endif 207 { 208 read_status = read (c -> socket, 209 &buffer -> buf [buffer -> tail], 210 read_len); 211 } 212 if (read_status < 0) { 213 if (errno == EWOULDBLOCK) 214 break; 215 else if (errno == EIO) 216 return ISC_R_IOERROR; 217 else if (errno == EINVAL) 218 return DHCP_R_INVALIDARG; 219 else if (errno == ECONNRESET) { 220 omapi_disconnect (h, 1); 221 return ISC_R_SHUTTINGDOWN; 222 } else 223 return ISC_R_UNEXPECTED; 224 } 225 226 /* If we got a zero-length read, as opposed to EWOULDBLOCK, 227 the remote end closed the connection. */ 228 if (read_status == 0) { 229 omapi_disconnect (h, 0); 230 return ISC_R_SHUTTINGDOWN; 231 } 232 #if defined (TRACING) 233 if (trace_record ()) { 234 trace_iov_t iov [2]; 235 int32_t connect_index; 236 237 connect_index = htonl (c -> index); 238 239 iov [0].buf = (char *)&connect_index; 240 iov [0].len = sizeof connect_index; 241 iov [1].buf = &buffer -> buf [buffer -> tail]; 242 iov [1].len = read_status; 243 244 status = (trace_write_packet_iov 245 (trace_connection_input, 2, iov, MDL)); 246 if (status != ISC_R_SUCCESS) { 247 trace_stop (); 248 log_error ("trace connection input: %s", 249 isc_result_totext (status)); 250 } 251 } 252 #endif 253 buffer -> tail += read_status; 254 c -> in_bytes += read_status; 255 if (buffer -> tail == sizeof buffer -> buf) 256 buffer -> tail = 0; 257 if (read_status < read_len) 258 break; 259 bytes_to_read -= read_status; 260 } 261 262 if (c -> bytes_needed <= c -> in_bytes) { 263 omapi_signal (h, "ready", c); 264 } 265 return ISC_R_SUCCESS; 266 } 267 268 /* Put some bytes into the output buffer for a connection. */ 269 270 isc_result_t omapi_connection_copyin (omapi_object_t *h, 271 const unsigned char *bufp, 272 unsigned len) 273 { 274 omapi_buffer_t *buffer; 275 isc_result_t status; 276 int bytes_copied = 0; 277 unsigned copy_len; 278 int sig_flags = SIG_MODE_UPDATE; 279 omapi_connection_object_t *c; 280 281 /* no need to verify len as it's unsigned */ 282 if (!h || h -> type != omapi_type_connection) 283 return DHCP_R_INVALIDARG; 284 c = (omapi_connection_object_t *)h; 285 286 /* If the connection is closed, return an error if the caller 287 tries to copy in. */ 288 if (c -> state == omapi_connection_disconnecting || 289 c -> state == omapi_connection_closed) 290 return ISC_R_NOTCONNECTED; 291 292 if (c -> outbufs) { 293 for (buffer = c -> outbufs; 294 buffer -> next; buffer = buffer -> next) 295 ; 296 } else { 297 status = omapi_buffer_new (&c -> outbufs, MDL); 298 if (status != ISC_R_SUCCESS) 299 goto leave; 300 buffer = c -> outbufs; 301 } 302 303 while (bytes_copied < len) { 304 /* If there is no space available in this buffer, 305 allocate a new one. */ 306 if (!BUFFER_BYTES_FREE (buffer)) { 307 status = (omapi_buffer_new (&buffer -> next, MDL)); 308 if (status != ISC_R_SUCCESS) 309 goto leave; 310 buffer = buffer -> next; 311 } 312 313 if (buffer -> tail > buffer -> head) 314 copy_len = sizeof (buffer -> buf) - buffer -> tail; 315 else 316 copy_len = buffer -> head - buffer -> tail; 317 318 if (copy_len > (len - bytes_copied)) 319 copy_len = len - bytes_copied; 320 321 if (c -> out_key) { 322 if (!c -> out_context) 323 sig_flags |= SIG_MODE_INIT; 324 status = omapi_connection_sign_data 325 (sig_flags, c -> out_key, &c -> out_context, 326 &bufp [bytes_copied], copy_len, 327 (omapi_typed_data_t **)0); 328 if (status != ISC_R_SUCCESS) 329 goto leave; 330 } 331 332 memcpy (&buffer -> buf [buffer -> tail], 333 &bufp [bytes_copied], copy_len); 334 buffer -> tail += copy_len; 335 c -> out_bytes += copy_len; 336 bytes_copied += copy_len; 337 if (buffer -> tail == sizeof buffer -> buf) 338 buffer -> tail = 0; 339 } 340 341 status = ISC_R_SUCCESS; 342 343 leave: 344 /* 345 * If we have any bytes to send and we have a proper io object 346 * inform the socket code that we would like to know when we 347 * can send more bytes. 348 */ 349 if (c->out_bytes != 0) { 350 if ((c->outer != NULL) && 351 (c->outer->type == omapi_type_io_object)) { 352 omapi_io_object_t *io = (omapi_io_object_t *)c->outer; 353 isc_socket_fdwatchpoke(io->fd, 354 ISC_SOCKFDWATCH_WRITE); 355 } 356 } 357 358 return (status); 359 } 360 361 /* Copy some bytes from the input buffer, and advance the input buffer 362 pointer beyond the bytes copied out. */ 363 364 isc_result_t omapi_connection_copyout (unsigned char *buf, 365 omapi_object_t *h, 366 unsigned size) 367 { 368 unsigned bytes_remaining; 369 unsigned bytes_this_copy; 370 unsigned first_byte; 371 omapi_buffer_t *buffer; 372 unsigned char *bufp; 373 int sig_flags = SIG_MODE_UPDATE; 374 omapi_connection_object_t *c; 375 isc_result_t status; 376 377 if (!h || h -> type != omapi_type_connection) 378 return DHCP_R_INVALIDARG; 379 c = (omapi_connection_object_t *)h; 380 381 if (size > c -> in_bytes) 382 return ISC_R_NOMORE; 383 bufp = buf; 384 bytes_remaining = size; 385 buffer = c -> inbufs; 386 387 while (bytes_remaining) { 388 if (!buffer) 389 return ISC_R_UNEXPECTED; 390 if (BYTES_IN_BUFFER (buffer)) { 391 if (buffer -> head == (sizeof buffer -> buf) - 1) 392 first_byte = 0; 393 else 394 first_byte = buffer -> head + 1; 395 396 if (first_byte > buffer -> tail) { 397 bytes_this_copy = (sizeof buffer -> buf - 398 first_byte); 399 } else { 400 bytes_this_copy = 401 buffer -> tail - first_byte; 402 } 403 if (bytes_this_copy > bytes_remaining) 404 bytes_this_copy = bytes_remaining; 405 if (bufp) { 406 if (c -> in_key) { 407 if (!c -> in_context) 408 sig_flags |= SIG_MODE_INIT; 409 status = omapi_connection_sign_data 410 (sig_flags, 411 c -> in_key, 412 &c -> in_context, 413 (unsigned char *) 414 &buffer -> buf [first_byte], 415 bytes_this_copy, 416 (omapi_typed_data_t **)0); 417 if (status != ISC_R_SUCCESS) 418 return status; 419 } 420 421 memcpy (bufp, &buffer -> buf [first_byte], 422 bytes_this_copy); 423 bufp += bytes_this_copy; 424 } 425 bytes_remaining -= bytes_this_copy; 426 buffer -> head = first_byte + bytes_this_copy - 1; 427 c -> in_bytes -= bytes_this_copy; 428 } 429 430 if (!BYTES_IN_BUFFER (buffer)) 431 buffer = buffer -> next; 432 } 433 434 /* Get rid of any input buffers that we emptied. */ 435 buffer = (omapi_buffer_t *)0; 436 while (c -> inbufs && 437 !BYTES_IN_BUFFER (c -> inbufs)) { 438 if (c -> inbufs -> next) { 439 omapi_buffer_reference (&buffer, 440 c -> inbufs -> next, MDL); 441 omapi_buffer_dereference (&c -> inbufs -> next, MDL); 442 } 443 omapi_buffer_dereference (&c -> inbufs, MDL); 444 if (buffer) { 445 omapi_buffer_reference 446 (&c -> inbufs, buffer, MDL); 447 omapi_buffer_dereference (&buffer, MDL); 448 } 449 } 450 return ISC_R_SUCCESS; 451 } 452 453 isc_result_t omapi_connection_writer (omapi_object_t *h) 454 { 455 unsigned bytes_this_write; 456 int bytes_written; 457 unsigned first_byte; 458 omapi_buffer_t *buffer; 459 omapi_connection_object_t *c; 460 461 if (!h || h -> type != omapi_type_connection) 462 return DHCP_R_INVALIDARG; 463 c = (omapi_connection_object_t *)h; 464 465 /* Already flushed... */ 466 if (!c -> out_bytes) 467 return ISC_R_SUCCESS; 468 469 buffer = c -> outbufs; 470 471 while (c -> out_bytes) { 472 if (!buffer) 473 return ISC_R_UNEXPECTED; 474 if (BYTES_IN_BUFFER (buffer)) { 475 if (buffer -> head == (sizeof buffer -> buf) - 1) 476 first_byte = 0; 477 else 478 first_byte = buffer -> head + 1; 479 480 if (first_byte > buffer -> tail) { 481 bytes_this_write = (sizeof buffer -> buf - 482 first_byte); 483 } else { 484 bytes_this_write = 485 buffer -> tail - first_byte; 486 } 487 bytes_written = write (c -> socket, 488 &buffer -> buf [first_byte], 489 bytes_this_write); 490 /* If the write failed with EWOULDBLOCK or we wrote 491 zero bytes, a further write would block, so we have 492 flushed as much as we can for now. Other errors 493 are really errors. */ 494 if (bytes_written < 0) { 495 if (errno == EWOULDBLOCK || errno == EAGAIN) 496 return ISC_R_INPROGRESS; 497 else if (errno == EPIPE) 498 return ISC_R_NOCONN; 499 #ifdef EDQUOT 500 else if (errno == EFBIG || errno == EDQUOT) 501 #else 502 else if (errno == EFBIG) 503 #endif 504 return ISC_R_NORESOURCES; 505 else if (errno == ENOSPC) 506 return ISC_R_NOSPACE; 507 else if (errno == EIO) 508 return ISC_R_IOERROR; 509 else if (errno == EINVAL) 510 return DHCP_R_INVALIDARG; 511 else if (errno == ECONNRESET) 512 return ISC_R_SHUTTINGDOWN; 513 else 514 return ISC_R_UNEXPECTED; 515 } 516 if (bytes_written == 0) 517 return ISC_R_INPROGRESS; 518 519 #if defined (TRACING) 520 if (trace_record ()) { 521 isc_result_t status; 522 trace_iov_t iov [2]; 523 int32_t connect_index; 524 525 connect_index = htonl (c -> index); 526 527 iov [0].buf = (char *)&connect_index; 528 iov [0].len = sizeof connect_index; 529 iov [1].buf = &buffer -> buf [buffer -> tail]; 530 iov [1].len = bytes_written; 531 532 status = (trace_write_packet_iov 533 (trace_connection_input, 2, iov, 534 MDL)); 535 if (status != ISC_R_SUCCESS) { 536 trace_stop (); 537 log_error ("trace %s output: %s", 538 "connection", 539 isc_result_totext (status)); 540 } 541 } 542 #endif 543 544 buffer -> head = first_byte + bytes_written - 1; 545 c -> out_bytes -= bytes_written; 546 547 /* If we didn't finish out the write, we filled the 548 O.S. output buffer and a further write would block, 549 so stop trying to flush now. */ 550 if (bytes_written != bytes_this_write) 551 return ISC_R_INPROGRESS; 552 } 553 554 if (!BYTES_IN_BUFFER (buffer)) 555 buffer = buffer -> next; 556 } 557 558 /* Get rid of any output buffers we emptied. */ 559 buffer = (omapi_buffer_t *)0; 560 while (c -> outbufs && 561 !BYTES_IN_BUFFER (c -> outbufs)) { 562 if (c -> outbufs -> next) { 563 omapi_buffer_reference (&buffer, 564 c -> outbufs -> next, MDL); 565 omapi_buffer_dereference (&c -> outbufs -> next, MDL); 566 } 567 omapi_buffer_dereference (&c -> outbufs, MDL); 568 if (buffer) { 569 omapi_buffer_reference (&c -> outbufs, buffer, MDL); 570 omapi_buffer_dereference (&buffer, MDL); 571 } 572 } 573 574 /* If we had data left to write when we're told to disconnect, 575 * we need recall disconnect, now that we're done writing. 576 * See rt46767. */ 577 if (c->out_bytes == 0 && c->state == omapi_connection_disconnecting) { 578 omapi_disconnect (h, 1); 579 return ISC_R_SHUTTINGDOWN; 580 } 581 582 return ISC_R_SUCCESS; 583 } 584 585 isc_result_t omapi_connection_get_uint32 (omapi_object_t *c, 586 u_int32_t *result) 587 { 588 u_int32_t inbuf; 589 isc_result_t status; 590 591 status = omapi_connection_copyout ((unsigned char *)&inbuf, 592 c, sizeof inbuf); 593 if (status != ISC_R_SUCCESS) 594 return status; 595 596 *result = ntohl (inbuf); 597 return ISC_R_SUCCESS; 598 } 599 600 isc_result_t omapi_connection_put_uint32 (omapi_object_t *c, 601 u_int32_t value) 602 { 603 u_int32_t inbuf; 604 605 inbuf = htonl (value); 606 607 return omapi_connection_copyin (c, (unsigned char *)&inbuf, 608 sizeof inbuf); 609 } 610 611 isc_result_t omapi_connection_get_uint16 (omapi_object_t *c, 612 u_int16_t *result) 613 { 614 u_int16_t inbuf; 615 isc_result_t status; 616 617 status = omapi_connection_copyout ((unsigned char *)&inbuf, 618 c, sizeof inbuf); 619 if (status != ISC_R_SUCCESS) 620 return status; 621 622 *result = ntohs (inbuf); 623 return ISC_R_SUCCESS; 624 } 625 626 isc_result_t omapi_connection_put_uint16 (omapi_object_t *c, 627 u_int32_t value) 628 { 629 u_int16_t inbuf; 630 631 inbuf = htons (value); 632 633 return omapi_connection_copyin (c, (unsigned char *)&inbuf, 634 sizeof inbuf); 635 } 636 637 isc_result_t omapi_connection_write_typed_data (omapi_object_t *c, 638 omapi_typed_data_t *data) 639 { 640 isc_result_t status; 641 omapi_handle_t handle; 642 643 /* Null data is valid. */ 644 if (!data) 645 return omapi_connection_put_uint32 (c, 0); 646 647 switch (data -> type) { 648 case omapi_datatype_int: 649 status = omapi_connection_put_uint32 (c, sizeof (u_int32_t)); 650 if (status != ISC_R_SUCCESS) 651 return status; 652 return omapi_connection_put_uint32 (c, ((u_int32_t) 653 (data -> u.integer))); 654 655 case omapi_datatype_string: 656 case omapi_datatype_data: 657 status = omapi_connection_put_uint32 (c, data -> u.buffer.len); 658 if (status != ISC_R_SUCCESS) 659 return status; 660 if (data -> u.buffer.len) 661 return omapi_connection_copyin 662 (c, data -> u.buffer.value, 663 data -> u.buffer.len); 664 return ISC_R_SUCCESS; 665 666 case omapi_datatype_object: 667 if (data -> u.object) { 668 status = omapi_object_handle (&handle, 669 data -> u.object); 670 if (status != ISC_R_SUCCESS) 671 return status; 672 } else 673 handle = 0; 674 status = omapi_connection_put_uint32 (c, sizeof handle); 675 if (status != ISC_R_SUCCESS) 676 return status; 677 return omapi_connection_put_uint32 (c, handle); 678 679 } 680 return DHCP_R_INVALIDARG; 681 } 682 683 isc_result_t omapi_connection_put_name (omapi_object_t *c, const char *name) 684 { 685 isc_result_t status; 686 unsigned len = strlen (name); 687 688 status = omapi_connection_put_uint16 (c, len); 689 if (status != ISC_R_SUCCESS) 690 return status; 691 return omapi_connection_copyin (c, (const unsigned char *)name, len); 692 } 693 694 isc_result_t omapi_connection_put_string (omapi_object_t *c, 695 const char *string) 696 { 697 isc_result_t status; 698 unsigned len; 699 700 if (string) 701 len = strlen (string); 702 else 703 len = 0; 704 705 status = omapi_connection_put_uint32 (c, len); 706 if (status != ISC_R_SUCCESS) 707 return status; 708 if (len) 709 return omapi_connection_copyin 710 (c, (const unsigned char *)string, len); 711 return ISC_R_SUCCESS; 712 } 713 714 isc_result_t omapi_connection_put_handle (omapi_object_t *c, omapi_object_t *h) 715 { 716 isc_result_t status; 717 omapi_handle_t handle; 718 719 if (h) { 720 status = omapi_object_handle (&handle, h); 721 if (status != ISC_R_SUCCESS) 722 return status; 723 } else 724 handle = 0; /* The null handle. */ 725 status = omapi_connection_put_uint32 (c, sizeof handle); 726 if (status != ISC_R_SUCCESS) 727 return status; 728 return omapi_connection_put_uint32 (c, handle); 729 } 730 731 isc_result_t omapi_connection_put_named_uint32 (omapi_object_t *c, 732 const char *name, 733 u_int32_t value) 734 { 735 isc_result_t status; 736 737 status = omapi_connection_put_name(c, name); 738 if (status != ISC_R_SUCCESS) 739 return (status); 740 741 status = omapi_connection_put_uint32(c, sizeof(u_int32_t)); 742 if (status != ISC_R_SUCCESS) 743 return (status); 744 745 status = omapi_connection_put_uint32(c, value); 746 return (status); 747 } 748 749