void trace_mr_read_record (struct sockaddr_in *from, void *buf, ssize_t rv) { trace_iov_t iov [4]; u_int32_t result; int iolen = 0; static char zero [4] = { 0, 0, 0, 0 }; if (rv < 0) result = htonl (errno); /* XXX */ else result = 0; iov [iolen].buf = (char *)&result; iov [iolen++].len = sizeof result; if (rv > 0) { if (from) { iov [iolen].buf = (char *)&from -> sin_addr; iov [iolen++].len = sizeof from -> sin_addr; iov [iolen].buf = (char *)&from -> sin_port; iov [iolen++].len = sizeof from -> sin_port; } else { iov [iolen].buf = zero; iov [iolen++].len = sizeof from -> sin_addr; iov [iolen].buf = zero; iov [iolen++].len = sizeof from -> sin_port; } iov [iolen].buf = buf; iov [iolen++].len = rv; } trace_write_packet_iov (trace_mr_input, iolen, iov, MDL); }
void trace_inpacket_stash (struct interface_info *interface, struct dhcp_packet *packet, unsigned len, unsigned int from_port, struct iaddr from, struct hardware *hfrom) { trace_inpacket_t tip; trace_iov_t iov [2]; if (!trace_record ()) return; tip.from_port = from_port; tip.from = from; tip.from.len = htonl (tip.from.len); if (hfrom) { tip.hfrom = *hfrom; tip.havehfrom = 1; } else { memset (&tip.hfrom, 0, sizeof tip.hfrom); tip.havehfrom = 0; } tip.index = htonl (interface -> index); iov [0].buf = (char *)&tip; iov [0].len = sizeof tip; iov [1].buf = (char *)packet; iov [1].len = len; trace_write_packet_iov (inpacket_trace, 2, iov, MDL); }
/* Reader callback for a listener object. Accept an incoming connection. */ isc_result_t omapi_accept (omapi_object_t *h) { isc_result_t status; socklen_t len; omapi_connection_object_t *obj; omapi_listener_object_t *listener; struct sockaddr_in addr; int socket; if (h -> type != omapi_type_listener) return ISC_R_INVALIDARG; listener = (omapi_listener_object_t *)h; /* Accept the connection. */ len = sizeof addr; socket = accept (listener -> socket, ((struct sockaddr *)&(addr)), &len); if (socket < 0) { if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS) return ISC_R_NORESOURCES; return ISC_R_UNEXPECTED; } #if defined (TRACING) /* If we're recording a trace, remember the connection. */ if (trace_record ()) { trace_iov_t iov [3]; iov [0].buf = (char *)&addr.sin_port; iov [0].len = sizeof addr.sin_port; iov [1].buf = (char *)&addr.sin_addr; iov [1].len = sizeof addr.sin_addr; iov [2].buf = (char *)&listener -> address.sin_port; iov [2].len = sizeof listener -> address.sin_port; trace_write_packet_iov (trace_listener_accept, 3, iov, MDL); } #endif obj = (omapi_connection_object_t *)0; status = omapi_listener_connect (&obj, listener, socket, &addr); if (status != ISC_R_SUCCESS) { close (socket); return status; } status = omapi_register_io_object ((omapi_object_t *)obj, omapi_connection_readfd, omapi_connection_writefd, omapi_connection_reader, omapi_connection_writer, omapi_connection_reaper); /* Lose our reference to the connection, so it'll be gc'd when it's reaped. */ omapi_connection_dereference (&obj, MDL); if (status != ISC_R_SUCCESS) omapi_disconnect ((omapi_object_t *)(obj), 1); return status; }
void omapi_connection_register (omapi_connection_object_t *obj, const char *file, int line) { isc_result_t status; trace_iov_t iov [6]; int iov_count = 0; int32_t connect_index, listener_index; static int32_t index; if (!omapi_connections) { status = omapi_connection_array_allocate (&omapi_connections, file, line); if (status != ISC_R_SUCCESS) return; } status = omapi_connection_array_extend (omapi_connections, obj, (int *)0, file, line); if (status != ISC_R_SUCCESS) { obj -> index = -1; return; } #if defined (TRACING) if (trace_record ()) { /* Connection registration packet: int32_t index int32_t listener_index [-1 means no listener] u_int16_t remote_port u_int16_t local_port u_int32_t remote_addr u_int32_t local_addr */ connect_index = htonl (index); index++; if (obj -> listener) listener_index = htonl (obj -> listener -> index); else listener_index = htonl (-1); iov [iov_count].buf = (char *)&connect_index; iov [iov_count++].len = sizeof connect_index; iov [iov_count].buf = (char *)&listener_index; iov [iov_count++].len = sizeof listener_index; iov [iov_count].buf = (char *)&obj -> remote_addr.sin_port; iov [iov_count++].len = sizeof obj -> remote_addr.sin_port; iov [iov_count].buf = (char *)&obj -> local_addr.sin_port; iov [iov_count++].len = sizeof obj -> local_addr.sin_port; iov [iov_count].buf = (char *)&obj -> remote_addr.sin_addr; iov [iov_count++].len = sizeof obj -> remote_addr.sin_addr; iov [iov_count].buf = (char *)&obj -> local_addr.sin_addr; iov [iov_count++].len = sizeof obj -> local_addr.sin_addr; status = trace_write_packet_iov (trace_connect, iov_count, iov, file, line); } #endif }
void trace_mr_statp_setup (res_state statp) { unsigned buflen = 0; char *buf = (char *)0; isc_result_t status; int i; if (trace_playback ()) { int nscount; status = trace_get_packet (&trace_mr_statp, &buflen, &buf); if (status != ISC_R_SUCCESS) { log_error ("trace_mr_statp: no statp packet found."); return; } nscount = buflen / sizeof (struct in_addr); if (nscount * (sizeof (struct in_addr)) != buflen || nscount < 1) { log_error ("trace_mr_statp: bogus length: %d", buflen); return; } if (nscount > MAXNS) nscount = MAXNS; for (i = 0; i < nscount; i++) { #if defined (HAVE_SA_LEN) statp -> nsaddr_list [i].sin_len = sizeof (struct sockaddr_in); #endif memset (&statp -> nsaddr_list [i].sin_zero, 0, sizeof statp -> nsaddr_list [i].sin_zero); statp -> nsaddr_list [i].sin_port = htons (53); /*XXX*/ statp -> nsaddr_list [i].sin_family = AF_INET; memcpy (&statp -> nsaddr_list [i].sin_addr, (buf + i * (sizeof (struct in_addr))), sizeof (struct in_addr)); } statp -> nscount = nscount; dfree (buf, MDL); buf = (char *)0; } if (trace_record ()) { trace_iov_t *iov; iov = dmalloc ((statp -> nscount * sizeof (trace_iov_t)), MDL); if (!iov) { trace_stop (); log_error ("No memory for statp iov."); return; } for (i = 0; i < statp -> nscount; i++) { iov [i].buf = (char *)&statp -> nsaddr_list [i].sin_addr; iov [i].len = sizeof (struct in_addr); } trace_write_packet_iov (trace_mr_statp, i, iov, MDL); dfree (iov, MDL); } }
isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length, const char *buf, const char *file, int line) { trace_iov_t iov; iov.buf = buf; iov.len = length; return trace_write_packet_iov (ttype, 1, &iov, file, line); }
ssize_t trace_mr_send (int fd, void *msg, size_t len, int flags) { ssize_t rv; #if defined (TRACING) isc_result_t status; unsigned buflen = 0; char *inbuf = (char *)0; u_int32_t result; u_int32_t sflags; if (trace_playback()) { status = trace_get_packet (&trace_mr_output, &buflen, &inbuf); if (status != ISC_R_SUCCESS) { log_error ("trace_mr_recvfrom: no input found."); errno = ECONNREFUSED; return -1; } if (buflen < sizeof result) { log_error ("trace_mr_recvfrom: data too short."); errno = ECONNREFUSED; dfree (inbuf, MDL); return -1; } memcpy (&result, inbuf, sizeof result); rv = ntohl (result); dfree (inbuf, MDL); } else #endif rv = send (fd, msg, len, flags); #if defined (TRACING) if (trace_record ()) { trace_iov_t iov [3]; result = htonl (rv); sflags = htonl (flags); iov [0].len = sizeof result; iov [0].buf = (char *)&result; iov [1].len = sizeof sflags; iov [1].buf = (char *)&flags; iov [2].len = len; iov [2].buf = msg; trace_write_packet_iov (trace_mr_output, 3, iov, MDL); } #endif return rv; }
ssize_t trace_packet_send (struct interface_info *interface, struct packet *packet, struct dhcp_packet *raw, size_t len, struct in_addr from, struct sockaddr_in *to, struct hardware *hto) { trace_outpacket_t tip; trace_iov_t iov [2]; if (trace_record ()) { if (hto) { tip.hto = *hto; tip.havehto = 1; } else { memset (&tip.hto, 0, sizeof tip.hto); tip.havehto = 0; } tip.from.len = 4; memcpy (tip.from.iabuf, &from, 4); tip.to.len = 4; memcpy (tip.to.iabuf, &to -> sin_addr, 4); tip.to_port = to -> sin_port; tip.index = htonl (interface -> index); iov [0].buf = (char *)&tip; iov [0].len = sizeof tip; iov [1].buf = (char *)raw; iov [1].len = len; trace_write_packet_iov (outpacket_trace, 2, iov, MDL); } if (!trace_playback ()) { return send_packet (interface, packet, raw, len, from, to, hto); } return len; }
isc_result_t omapi_connection_writer (omapi_object_t *h) { unsigned bytes_this_write; int bytes_written; unsigned first_byte; omapi_buffer_t *buffer; omapi_connection_object_t *c; if (!h || h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; /* Already flushed... */ if (!c -> out_bytes) return ISC_R_SUCCESS; buffer = c -> outbufs; while (c -> out_bytes) { if (!buffer) return ISC_R_UNEXPECTED; if (BYTES_IN_BUFFER (buffer)) { if (buffer -> head == (sizeof buffer -> buf) - 1) first_byte = 0; else first_byte = buffer -> head + 1; if (first_byte > buffer -> tail) { bytes_this_write = (sizeof buffer -> buf - first_byte); } else { bytes_this_write = buffer -> tail - first_byte; } bytes_written = write (c -> socket, &buffer -> buf [first_byte], bytes_this_write); /* If the write failed with EWOULDBLOCK or we wrote zero bytes, a further write would block, so we have flushed as much as we can for now. Other errors are really errors. */ if (bytes_written < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) return ISC_R_SUCCESS; else if (errno == EPIPE) return ISC_R_NOCONN; #ifdef EDQUOT else if (errno == EFBIG || errno == EDQUOT) #else else if (errno == EFBIG) #endif return ISC_R_NORESOURCES; else if (errno == ENOSPC) return ISC_R_NOSPACE; else if (errno == EIO) return ISC_R_IOERROR; else if (errno == EINVAL) return ISC_R_INVALIDARG; else if (errno == ECONNRESET) return ISC_R_SHUTTINGDOWN; else return ISC_R_UNEXPECTED; } if (bytes_written == 0) return ISC_R_SUCCESS; #if defined (TRACING) if (trace_record ()) { isc_result_t status; trace_iov_t iov [2]; int32_t connect_index; connect_index = htonl (c -> index); iov [0].buf = (char *)&connect_index; iov [0].len = sizeof connect_index; iov [1].buf = &buffer -> buf [buffer -> tail]; iov [1].len = bytes_written; status = (trace_write_packet_iov (trace_connection_input, 2, iov, MDL)); if (status != ISC_R_SUCCESS) { trace_stop (); log_error ("trace %s output: %s", "connection", isc_result_totext (status)); } } #endif buffer -> head = first_byte + bytes_written - 1; c -> out_bytes -= bytes_written; /* If we didn't finish out the write, we filled the O.S. output buffer and a further write would block, so stop trying to flush now. */ if (bytes_written != bytes_this_write) return ISC_R_SUCCESS; } if (!BYTES_IN_BUFFER (buffer)) buffer = buffer -> next; } /* Get rid of any output buffers we emptied. */ buffer = (omapi_buffer_t *)0; while (c -> outbufs && !BYTES_IN_BUFFER (c -> outbufs)) { if (c -> outbufs -> next) { omapi_buffer_reference (&buffer, c -> outbufs -> next, MDL); omapi_buffer_dereference (&c -> outbufs -> next, MDL); } omapi_buffer_dereference (&c -> outbufs, MDL); if (buffer) { omapi_buffer_reference (&c -> outbufs, buffer, MDL); omapi_buffer_dereference (&buffer, MDL); } } return ISC_R_SUCCESS; }
static isc_result_t omapi_connection_reader_trace (omapi_object_t *h, unsigned stuff_len, char *stuff_buf, unsigned *stuff_taken) { #endif omapi_buffer_t *buffer; isc_result_t status; unsigned read_len; int read_status; omapi_connection_object_t *c; unsigned bytes_to_read; if (!h || h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; /* See if there are enough bytes. */ if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 && c -> in_bytes > c -> bytes_needed) return ISC_R_SUCCESS; if (c -> inbufs) { for (buffer = c -> inbufs; buffer -> next; buffer = buffer -> next) ; if (!BUFFER_BYTES_FREE (buffer)) { status = omapi_buffer_new (&buffer -> next, MDL); if (status != ISC_R_SUCCESS) return status; buffer = buffer -> next; } } else { status = omapi_buffer_new (&c -> inbufs, MDL); if (status != ISC_R_SUCCESS) return status; buffer = c -> inbufs; } bytes_to_read = BUFFER_BYTES_FREE (buffer); while (bytes_to_read) { if (buffer -> tail > buffer -> head) read_len = sizeof (buffer -> buf) - buffer -> tail; else read_len = buffer -> head - buffer -> tail; #if defined (TRACING) if (trace_playback()) { if (stuff_len) { if (read_len > stuff_len) read_len = stuff_len; if (stuff_taken) *stuff_taken += read_len; memcpy (&buffer -> buf [buffer -> tail], stuff_buf, read_len); stuff_len -= read_len; stuff_buf += read_len; read_status = read_len; } else { break; } } else #endif { read_status = read (c -> socket, &buffer -> buf [buffer -> tail], read_len); } if (read_status < 0) { if (errno == EWOULDBLOCK) break; else if (errno == EIO) return ISC_R_IOERROR; else if (errno == EINVAL) return ISC_R_INVALIDARG; else if (errno == ECONNRESET) { omapi_disconnect (h, 1); return ISC_R_SHUTTINGDOWN; } else return ISC_R_UNEXPECTED; } /* If we got a zero-length read, as opposed to EWOULDBLOCK, the remote end closed the connection. */ if (read_status == 0) { omapi_disconnect (h, 0); return ISC_R_SHUTTINGDOWN; } #if defined (TRACING) if (trace_record ()) { trace_iov_t iov [2]; int32_t connect_index; connect_index = htonl (c -> index); iov [0].buf = (char *)&connect_index; iov [0].len = sizeof connect_index; iov [1].buf = &buffer -> buf [buffer -> tail]; iov [1].len = read_status; status = (trace_write_packet_iov (trace_connection_input, 2, iov, MDL)); if (status != ISC_R_SUCCESS) { trace_stop (); log_error ("trace connection input: %s", isc_result_totext (status)); } } #endif buffer -> tail += read_status; c -> in_bytes += read_status; if (buffer -> tail == sizeof buffer -> buf) buffer -> tail = 0; if (read_status < read_len) break; bytes_to_read -= read_status; } if (c -> bytes_needed <= c -> in_bytes) { omapi_signal (h, "ready", c); } return ISC_R_SUCCESS; }