00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "dhcpd.h"
00031
00032 #include <omapip/omapip_p.h>
00033 #include <errno.h>
00034
00035 #if defined (TRACING)
00036 static void trace_connection_input_input (trace_type_t *, unsigned, char *);
00037 static void trace_connection_input_stop (trace_type_t *);
00038 static void trace_connection_output_input (trace_type_t *, unsigned, char *);
00039 static void trace_connection_output_stop (trace_type_t *);
00040 static trace_type_t *trace_connection_input;
00041 static trace_type_t *trace_connection_output;
00042 static isc_result_t omapi_connection_reader_trace (omapi_object_t *,
00043 unsigned, char *,
00044 unsigned *);
00045 extern omapi_array_t *omapi_connections;
00046
00047 void omapi_buffer_trace_setup ()
00048 {
00049 trace_connection_input =
00050 trace_type_register ("connection-input",
00051 (void *)0,
00052 trace_connection_input_input,
00053 trace_connection_input_stop, MDL);
00054 trace_connection_output =
00055 trace_type_register ("connection-output",
00056 (void *)0,
00057 trace_connection_output_input,
00058 trace_connection_output_stop, MDL);
00059 }
00060
00061 static void trace_connection_input_input (trace_type_t *ttype,
00062 unsigned length, char *buf)
00063 {
00064 unsigned left, taken, cc = 0;
00065 char *s;
00066 int32_t connect_index;
00067 isc_result_t status;
00068 omapi_connection_object_t *c = (omapi_connection_object_t *)0;
00069
00070 memcpy (&connect_index, buf, sizeof connect_index);
00071 connect_index = ntohl (connect_index);
00072
00073 omapi_array_foreach_begin (omapi_connections,
00074 omapi_connection_object_t, lp) {
00075 if (lp -> index == ntohl (connect_index)) {
00076 omapi_connection_reference (&c, lp, MDL);
00077 omapi_connection_dereference (&lp, MDL);
00078 break;
00079 }
00080 } omapi_array_foreach_end (omapi_connections,
00081 omapi_connection_object_t, lp);
00082
00083 if (!c) {
00084 log_error ("trace connection input: no connection index %ld",
00085 (long int)connect_index);
00086 return;
00087 }
00088
00089 s = buf + sizeof connect_index;
00090 left = length - sizeof connect_index;
00091
00092 while (left) {
00093 taken = 0;
00094 status = omapi_connection_reader_trace ((omapi_object_t *)c,
00095 left, s, &taken);
00096 if (status != ISC_R_SUCCESS) {
00097 log_error ("trace connection input: %s",
00098 isc_result_totext (status));
00099 break;
00100 }
00101 if (!taken) {
00102 if (cc > 0) {
00103 log_error ("trace connection_input: %s",
00104 "input is not being consumed.");
00105 break;
00106 }
00107 cc++;
00108 } else {
00109 cc = 0;
00110 left -= taken;
00111 }
00112 }
00113 omapi_connection_dereference (&c, MDL);
00114 }
00115
00116 static void trace_connection_input_stop (trace_type_t *ttype) { }
00117
00118 static void trace_connection_output_input (trace_type_t *ttype,
00119 unsigned length, char *buf)
00120 {
00121
00122
00123 }
00124
00125 static void trace_connection_output_stop (trace_type_t *ttype) { }
00126
00127 #endif
00128
00129
00130
00131
00132 isc_result_t omapi_connection_reader (omapi_object_t *h)
00133 {
00134 #if defined (TRACING)
00135 return omapi_connection_reader_trace (h, 0, (char *)0, (unsigned *)0);
00136 }
00137
00138 static isc_result_t omapi_connection_reader_trace (omapi_object_t *h,
00139 unsigned stuff_len,
00140 char *stuff_buf,
00141 unsigned *stuff_taken)
00142 {
00143 #endif
00144 omapi_buffer_t *buffer;
00145 isc_result_t status;
00146 unsigned read_len;
00147 int read_status;
00148 omapi_connection_object_t *c;
00149 unsigned bytes_to_read;
00150
00151 if (!h || h -> type != omapi_type_connection)
00152 return DHCP_R_INVALIDARG;
00153 c = (omapi_connection_object_t *)h;
00154
00155
00156 if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
00157 c -> in_bytes > c -> bytes_needed)
00158 return ISC_R_SUCCESS;
00159
00160
00161 if (c -> inbufs) {
00162 for (buffer = c -> inbufs; buffer -> next;
00163 buffer = buffer -> next)
00164 ;
00165 if (!BUFFER_BYTES_FREE (buffer)) {
00166 status = omapi_buffer_new (&buffer -> next, MDL);
00167 if (status != ISC_R_SUCCESS)
00168 return status;
00169 buffer = buffer -> next;
00170 }
00171 } else {
00172 status = omapi_buffer_new (&c -> inbufs, MDL);
00173 if (status != ISC_R_SUCCESS)
00174 return status;
00175 buffer = c -> inbufs;
00176 }
00177
00178 bytes_to_read = BUFFER_BYTES_FREE (buffer);
00179
00180 while (bytes_to_read) {
00181 if (buffer -> tail > buffer -> head)
00182 read_len = sizeof (buffer -> buf) - buffer -> tail;
00183 else
00184 read_len = buffer -> head - buffer -> tail;
00185
00186 #if defined (TRACING)
00187 if (trace_playback()) {
00188 if (stuff_len) {
00189 if (read_len > stuff_len)
00190 read_len = stuff_len;
00191 if (stuff_taken)
00192 *stuff_taken += read_len;
00193 memcpy (&buffer -> buf [buffer -> tail],
00194 stuff_buf, read_len);
00195 stuff_len -= read_len;
00196 stuff_buf += read_len;
00197 read_status = read_len;
00198 } else {
00199 break;
00200 }
00201 } else
00202 #endif
00203 {
00204 read_status = read (c -> socket,
00205 &buffer -> buf [buffer -> tail],
00206 read_len);
00207 }
00208 if (read_status < 0) {
00209 if (errno == EWOULDBLOCK)
00210 break;
00211 else if (errno == EIO)
00212 return ISC_R_IOERROR;
00213 else if (errno == EINVAL)
00214 return DHCP_R_INVALIDARG;
00215 else if (errno == ECONNRESET) {
00216 omapi_disconnect (h, 1);
00217 return ISC_R_SHUTTINGDOWN;
00218 } else
00219 return ISC_R_UNEXPECTED;
00220 }
00221
00222
00223
00224 if (read_status == 0) {
00225 omapi_disconnect (h, 0);
00226 return ISC_R_SHUTTINGDOWN;
00227 }
00228 #if defined (TRACING)
00229 if (trace_record ()) {
00230 trace_iov_t iov [2];
00231 int32_t connect_index;
00232
00233 connect_index = htonl (c -> index);
00234
00235 iov [0].buf = (char *)&connect_index;
00236 iov [0].len = sizeof connect_index;
00237 iov [1].buf = &buffer -> buf [buffer -> tail];
00238 iov [1].len = read_status;
00239
00240 status = (trace_write_packet_iov
00241 (trace_connection_input, 2, iov, MDL));
00242 if (status != ISC_R_SUCCESS) {
00243 trace_stop ();
00244 log_error ("trace connection input: %s",
00245 isc_result_totext (status));
00246 }
00247 }
00248 #endif
00249 buffer -> tail += read_status;
00250 c -> in_bytes += read_status;
00251 if (buffer -> tail == sizeof buffer -> buf)
00252 buffer -> tail = 0;
00253 if (read_status < read_len)
00254 break;
00255 bytes_to_read -= read_status;
00256 }
00257
00258 if (c -> bytes_needed <= c -> in_bytes) {
00259 omapi_signal (h, "ready", c);
00260 }
00261 return ISC_R_SUCCESS;
00262 }
00263
00264
00265
00266 isc_result_t omapi_connection_copyin (omapi_object_t *h,
00267 const unsigned char *bufp,
00268 unsigned len)
00269 {
00270 omapi_buffer_t *buffer;
00271 isc_result_t status;
00272 int bytes_copied = 0;
00273 unsigned copy_len;
00274 int sig_flags = SIG_MODE_UPDATE;
00275 omapi_connection_object_t *c;
00276
00277
00278 if (!h || h -> type != omapi_type_connection)
00279 return DHCP_R_INVALIDARG;
00280 c = (omapi_connection_object_t *)h;
00281
00282
00283
00284 if (c -> state == omapi_connection_disconnecting ||
00285 c -> state == omapi_connection_closed)
00286 return ISC_R_NOTCONNECTED;
00287
00288 if (c -> outbufs) {
00289 for (buffer = c -> outbufs;
00290 buffer -> next; buffer = buffer -> next)
00291 ;
00292 } else {
00293 status = omapi_buffer_new (&c -> outbufs, MDL);
00294 if (status != ISC_R_SUCCESS)
00295 goto leave;
00296 buffer = c -> outbufs;
00297 }
00298
00299 while (bytes_copied < len) {
00300
00301
00302 if (!BUFFER_BYTES_FREE (buffer)) {
00303 status = (omapi_buffer_new (&buffer -> next, MDL));
00304 if (status != ISC_R_SUCCESS)
00305 goto leave;
00306 buffer = buffer -> next;
00307 }
00308
00309 if (buffer -> tail > buffer -> head)
00310 copy_len = sizeof (buffer -> buf) - buffer -> tail;
00311 else
00312 copy_len = buffer -> head - buffer -> tail;
00313
00314 if (copy_len > (len - bytes_copied))
00315 copy_len = len - bytes_copied;
00316
00317 if (c -> out_key) {
00318 if (!c -> out_context)
00319 sig_flags |= SIG_MODE_INIT;
00320 status = omapi_connection_sign_data
00321 (sig_flags, c -> out_key, &c -> out_context,
00322 &bufp [bytes_copied], copy_len,
00323 (omapi_typed_data_t **)0);
00324 if (status != ISC_R_SUCCESS)
00325 goto leave;
00326 }
00327
00328 memcpy (&buffer -> buf [buffer -> tail],
00329 &bufp [bytes_copied], copy_len);
00330 buffer -> tail += copy_len;
00331 c -> out_bytes += copy_len;
00332 bytes_copied += copy_len;
00333 if (buffer -> tail == sizeof buffer -> buf)
00334 buffer -> tail = 0;
00335 }
00336
00337 status = ISC_R_SUCCESS;
00338
00339 leave:
00340
00341
00342
00343
00344
00345 if (c->out_bytes != 0) {
00346 if ((c->outer != NULL) &&
00347 (c->outer->type == omapi_type_io_object)) {
00348 omapi_io_object_t *io = (omapi_io_object_t *)c->outer;
00349 isc_socket_fdwatchpoke(io->fd,
00350 ISC_SOCKFDWATCH_WRITE);
00351 }
00352 }
00353
00354 return (status);
00355 }
00356
00357
00358
00359
00360 isc_result_t omapi_connection_copyout (unsigned char *buf,
00361 omapi_object_t *h,
00362 unsigned size)
00363 {
00364 unsigned bytes_remaining;
00365 unsigned bytes_this_copy;
00366 unsigned first_byte;
00367 omapi_buffer_t *buffer;
00368 unsigned char *bufp;
00369 int sig_flags = SIG_MODE_UPDATE;
00370 omapi_connection_object_t *c;
00371 isc_result_t status;
00372
00373 if (!h || h -> type != omapi_type_connection)
00374 return DHCP_R_INVALIDARG;
00375 c = (omapi_connection_object_t *)h;
00376
00377 if (size > c -> in_bytes)
00378 return ISC_R_NOMORE;
00379 bufp = buf;
00380 bytes_remaining = size;
00381 buffer = c -> inbufs;
00382
00383 while (bytes_remaining) {
00384 if (!buffer)
00385 return ISC_R_UNEXPECTED;
00386 if (BYTES_IN_BUFFER (buffer)) {
00387 if (buffer -> head == (sizeof buffer -> buf) - 1)
00388 first_byte = 0;
00389 else
00390 first_byte = buffer -> head + 1;
00391
00392 if (first_byte > buffer -> tail) {
00393 bytes_this_copy = (sizeof buffer -> buf -
00394 first_byte);
00395 } else {
00396 bytes_this_copy =
00397 buffer -> tail - first_byte;
00398 }
00399 if (bytes_this_copy > bytes_remaining)
00400 bytes_this_copy = bytes_remaining;
00401 if (bufp) {
00402 if (c -> in_key) {
00403 if (!c -> in_context)
00404 sig_flags |= SIG_MODE_INIT;
00405 status = omapi_connection_sign_data
00406 (sig_flags,
00407 c -> in_key,
00408 &c -> in_context,
00409 (unsigned char *)
00410 &buffer -> buf [first_byte],
00411 bytes_this_copy,
00412 (omapi_typed_data_t **)0);
00413 if (status != ISC_R_SUCCESS)
00414 return status;
00415 }
00416
00417 memcpy (bufp, &buffer -> buf [first_byte],
00418 bytes_this_copy);
00419 bufp += bytes_this_copy;
00420 }
00421 bytes_remaining -= bytes_this_copy;
00422 buffer -> head = first_byte + bytes_this_copy - 1;
00423 c -> in_bytes -= bytes_this_copy;
00424 }
00425
00426 if (!BYTES_IN_BUFFER (buffer))
00427 buffer = buffer -> next;
00428 }
00429
00430
00431 buffer = (omapi_buffer_t *)0;
00432 while (c -> inbufs &&
00433 !BYTES_IN_BUFFER (c -> inbufs)) {
00434 if (c -> inbufs -> next) {
00435 omapi_buffer_reference (&buffer,
00436 c -> inbufs -> next, MDL);
00437 omapi_buffer_dereference (&c -> inbufs -> next, MDL);
00438 }
00439 omapi_buffer_dereference (&c -> inbufs, MDL);
00440 if (buffer) {
00441 omapi_buffer_reference
00442 (&c -> inbufs, buffer, MDL);
00443 omapi_buffer_dereference (&buffer, MDL);
00444 }
00445 }
00446 return ISC_R_SUCCESS;
00447 }
00448
00449 isc_result_t omapi_connection_writer (omapi_object_t *h)
00450 {
00451 unsigned bytes_this_write;
00452 int bytes_written;
00453 unsigned first_byte;
00454 omapi_buffer_t *buffer;
00455 omapi_connection_object_t *c;
00456
00457 if (!h || h -> type != omapi_type_connection)
00458 return DHCP_R_INVALIDARG;
00459 c = (omapi_connection_object_t *)h;
00460
00461
00462 if (!c -> out_bytes)
00463 return ISC_R_SUCCESS;
00464
00465 buffer = c -> outbufs;
00466
00467 while (c -> out_bytes) {
00468 if (!buffer)
00469 return ISC_R_UNEXPECTED;
00470 if (BYTES_IN_BUFFER (buffer)) {
00471 if (buffer -> head == (sizeof buffer -> buf) - 1)
00472 first_byte = 0;
00473 else
00474 first_byte = buffer -> head + 1;
00475
00476 if (first_byte > buffer -> tail) {
00477 bytes_this_write = (sizeof buffer -> buf -
00478 first_byte);
00479 } else {
00480 bytes_this_write =
00481 buffer -> tail - first_byte;
00482 }
00483 bytes_written = write (c -> socket,
00484 &buffer -> buf [first_byte],
00485 bytes_this_write);
00486
00487
00488
00489
00490 if (bytes_written < 0) {
00491 if (errno == EWOULDBLOCK || errno == EAGAIN)
00492 return ISC_R_INPROGRESS;
00493 else if (errno == EPIPE)
00494 return ISC_R_NOCONN;
00495 #ifdef EDQUOT
00496 else if (errno == EFBIG || errno == EDQUOT)
00497 #else
00498 else if (errno == EFBIG)
00499 #endif
00500 return ISC_R_NORESOURCES;
00501 else if (errno == ENOSPC)
00502 return ISC_R_NOSPACE;
00503 else if (errno == EIO)
00504 return ISC_R_IOERROR;
00505 else if (errno == EINVAL)
00506 return DHCP_R_INVALIDARG;
00507 else if (errno == ECONNRESET)
00508 return ISC_R_SHUTTINGDOWN;
00509 else
00510 return ISC_R_UNEXPECTED;
00511 }
00512 if (bytes_written == 0)
00513 return ISC_R_INPROGRESS;
00514
00515 #if defined (TRACING)
00516 if (trace_record ()) {
00517 isc_result_t status;
00518 trace_iov_t iov [2];
00519 int32_t connect_index;
00520
00521 connect_index = htonl (c -> index);
00522
00523 iov [0].buf = (char *)&connect_index;
00524 iov [0].len = sizeof connect_index;
00525 iov [1].buf = &buffer -> buf [buffer -> tail];
00526 iov [1].len = bytes_written;
00527
00528 status = (trace_write_packet_iov
00529 (trace_connection_input, 2, iov,
00530 MDL));
00531 if (status != ISC_R_SUCCESS) {
00532 trace_stop ();
00533 log_error ("trace %s output: %s",
00534 "connection",
00535 isc_result_totext (status));
00536 }
00537 }
00538 #endif
00539
00540 buffer -> head = first_byte + bytes_written - 1;
00541 c -> out_bytes -= bytes_written;
00542
00543
00544
00545
00546 if (bytes_written != bytes_this_write)
00547 return ISC_R_INPROGRESS;
00548 }
00549
00550 if (!BYTES_IN_BUFFER (buffer))
00551 buffer = buffer -> next;
00552 }
00553
00554
00555 buffer = (omapi_buffer_t *)0;
00556 while (c -> outbufs &&
00557 !BYTES_IN_BUFFER (c -> outbufs)) {
00558 if (c -> outbufs -> next) {
00559 omapi_buffer_reference (&buffer,
00560 c -> outbufs -> next, MDL);
00561 omapi_buffer_dereference (&c -> outbufs -> next, MDL);
00562 }
00563 omapi_buffer_dereference (&c -> outbufs, MDL);
00564 if (buffer) {
00565 omapi_buffer_reference (&c -> outbufs, buffer, MDL);
00566 omapi_buffer_dereference (&buffer, MDL);
00567 }
00568 }
00569 return ISC_R_SUCCESS;
00570 }
00571
00572 isc_result_t omapi_connection_get_uint32 (omapi_object_t *c,
00573 u_int32_t *result)
00574 {
00575 u_int32_t inbuf;
00576 isc_result_t status;
00577
00578 status = omapi_connection_copyout ((unsigned char *)&inbuf,
00579 c, sizeof inbuf);
00580 if (status != ISC_R_SUCCESS)
00581 return status;
00582
00583 *result = ntohl (inbuf);
00584 return ISC_R_SUCCESS;
00585 }
00586
00587 isc_result_t omapi_connection_put_uint32 (omapi_object_t *c,
00588 u_int32_t value)
00589 {
00590 u_int32_t inbuf;
00591
00592 inbuf = htonl (value);
00593
00594 return omapi_connection_copyin (c, (unsigned char *)&inbuf,
00595 sizeof inbuf);
00596 }
00597
00598 isc_result_t omapi_connection_get_uint16 (omapi_object_t *c,
00599 u_int16_t *result)
00600 {
00601 u_int16_t inbuf;
00602 isc_result_t status;
00603
00604 status = omapi_connection_copyout ((unsigned char *)&inbuf,
00605 c, sizeof inbuf);
00606 if (status != ISC_R_SUCCESS)
00607 return status;
00608
00609 *result = ntohs (inbuf);
00610 return ISC_R_SUCCESS;
00611 }
00612
00613 isc_result_t omapi_connection_put_uint16 (omapi_object_t *c,
00614 u_int32_t value)
00615 {
00616 u_int16_t inbuf;
00617
00618 inbuf = htons (value);
00619
00620 return omapi_connection_copyin (c, (unsigned char *)&inbuf,
00621 sizeof inbuf);
00622 }
00623
00624 isc_result_t omapi_connection_write_typed_data (omapi_object_t *c,
00625 omapi_typed_data_t *data)
00626 {
00627 isc_result_t status;
00628 omapi_handle_t handle;
00629
00630
00631 if (!data)
00632 return omapi_connection_put_uint32 (c, 0);
00633
00634 switch (data -> type) {
00635 case omapi_datatype_int:
00636 status = omapi_connection_put_uint32 (c, sizeof (u_int32_t));
00637 if (status != ISC_R_SUCCESS)
00638 return status;
00639 return omapi_connection_put_uint32 (c, ((u_int32_t)
00640 (data -> u.integer)));
00641
00642 case omapi_datatype_string:
00643 case omapi_datatype_data:
00644 status = omapi_connection_put_uint32 (c, data -> u.buffer.len);
00645 if (status != ISC_R_SUCCESS)
00646 return status;
00647 if (data -> u.buffer.len)
00648 return omapi_connection_copyin
00649 (c, data -> u.buffer.value,
00650 data -> u.buffer.len);
00651 return ISC_R_SUCCESS;
00652
00653 case omapi_datatype_object:
00654 if (data -> u.object) {
00655 status = omapi_object_handle (&handle,
00656 data -> u.object);
00657 if (status != ISC_R_SUCCESS)
00658 return status;
00659 } else
00660 handle = 0;
00661 status = omapi_connection_put_uint32 (c, sizeof handle);
00662 if (status != ISC_R_SUCCESS)
00663 return status;
00664 return omapi_connection_put_uint32 (c, handle);
00665
00666 }
00667 return DHCP_R_INVALIDARG;
00668 }
00669
00670 isc_result_t omapi_connection_put_name (omapi_object_t *c, const char *name)
00671 {
00672 isc_result_t status;
00673 unsigned len = strlen (name);
00674
00675 status = omapi_connection_put_uint16 (c, len);
00676 if (status != ISC_R_SUCCESS)
00677 return status;
00678 return omapi_connection_copyin (c, (const unsigned char *)name, len);
00679 }
00680
00681 isc_result_t omapi_connection_put_string (omapi_object_t *c,
00682 const char *string)
00683 {
00684 isc_result_t status;
00685 unsigned len;
00686
00687 if (string)
00688 len = strlen (string);
00689 else
00690 len = 0;
00691
00692 status = omapi_connection_put_uint32 (c, len);
00693 if (status != ISC_R_SUCCESS)
00694 return status;
00695 if (len)
00696 return omapi_connection_copyin
00697 (c, (const unsigned char *)string, len);
00698 return ISC_R_SUCCESS;
00699 }
00700
00701 isc_result_t omapi_connection_put_handle (omapi_object_t *c, omapi_object_t *h)
00702 {
00703 isc_result_t status;
00704 omapi_handle_t handle;
00705
00706 if (h) {
00707 status = omapi_object_handle (&handle, h);
00708 if (status != ISC_R_SUCCESS)
00709 return status;
00710 } else
00711 handle = 0;
00712 status = omapi_connection_put_uint32 (c, sizeof handle);
00713 if (status != ISC_R_SUCCESS)
00714 return status;
00715 return omapi_connection_put_uint32 (c, handle);
00716 }
00717
00718 isc_result_t omapi_connection_put_named_uint32 (omapi_object_t *c,
00719 const char *name,
00720 u_int32_t value)
00721 {
00722 isc_result_t status;
00723
00724 status = omapi_connection_put_name(c, name);
00725 if (status != ISC_R_SUCCESS)
00726 return (status);
00727
00728 status = omapi_connection_put_uint32(c, sizeof(u_int32_t));
00729 if (status != ISC_R_SUCCESS)
00730 return (status);
00731
00732 status = omapi_connection_put_uint32(c, value);
00733 return (status);
00734 }
00735