Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
0
/* 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;
}
Пример #4
0
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
}
Пример #5
0
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);
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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;
}