예제 #1
0
파일: buffer.c 프로젝트: inibir/daemongroup
static void trace_connection_input_input (trace_type_t *ttype,
					  unsigned length, char *buf)
{
	unsigned left, taken, cc = 0;
	char *s;
	int32_t connect_index;
	isc_result_t status;
	omapi_connection_object_t *c = (omapi_connection_object_t *)0;

	memcpy (&connect_index, buf, sizeof connect_index);
	connect_index = ntohl (connect_index);

	omapi_array_foreach_begin (omapi_connections,
				   omapi_connection_object_t, lp) {
		if (lp -> index == ntohl (connect_index)) {
			omapi_connection_reference (&c, lp, MDL);
			omapi_connection_dereference (&lp, MDL);
			break;
		}
	} omapi_array_foreach_end (omapi_connections,
				   omapi_connection_object_t, lp);

	if (!c) {
		log_error ("trace connection input: no connection index %ld",
			   (long int)connect_index);
		return;
	}

	s = buf + sizeof connect_index;
	left = length - sizeof connect_index;

	while (left) {
		taken = 0;
		status = omapi_connection_reader_trace ((omapi_object_t *)c,
							left, s, &taken);
		if (status != ISC_R_SUCCESS) {
			log_error ("trace connection input: %s",
				   isc_result_totext (status));
			break;
		}
		if (!taken) {
			if (cc > 0) {
				log_error ("trace connection_input: %s",
					   "input is not being consumed.");
				break;
			}
			cc++;
		} else {
			cc = 0;
			left -= taken;
		}
	}
	omapi_connection_dereference (&c, MDL);
}
예제 #2
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;
}
예제 #3
0
isc_result_t omapi_listener_connect (omapi_connection_object_t **obj,
				     omapi_listener_object_t *listener,
				     int socket,
				     struct sockaddr_in *remote_addr)
{
	isc_result_t status;
	omapi_object_t *h = (omapi_object_t *)listener;
	omapi_addr_t addr;

#ifdef DEBUG_PROTOCOL
	log_debug ("omapi_accept()");
#endif
	
	/* Get the handle. */
	status = omapi_connection_allocate (obj, MDL);
	if (status != ISC_R_SUCCESS)
		return status;

	(*obj) -> state = omapi_connection_connected;
	(*obj) -> remote_addr = *remote_addr;
	(*obj) -> socket = socket;

	/* Verify that this host is allowed to connect. */
	if (listener -> verify_addr) {
		addr.addrtype = AF_INET;
		addr.addrlen = sizeof (remote_addr -> sin_addr);
		memcpy (addr.address, &remote_addr -> sin_addr,
			sizeof (remote_addr -> sin_addr));
		addr.port = ntohs(remote_addr -> sin_port);

		status = (listener -> verify_addr) (h, &addr);
		if (status != ISC_R_SUCCESS) {
			omapi_disconnect ((omapi_object_t *)(*obj), 1);
			omapi_connection_dereference (obj, MDL);
			return status;
		}
	}

	omapi_listener_reference (&(*obj) -> listener, listener, MDL);
#if defined (TRACING)
	omapi_connection_register (*obj, MDL);
#endif
	status = omapi_signal (h, "connect", (*obj));
	return status;
}
예제 #4
0
	/* Find the matching connect object, if there is one. */
	omapi_array_foreach_begin (omapi_connections,
				   omapi_connection_object_t, lp) {
	    for (i = 0; (lp -> connect_list &&
			 i < lp -> connect_list -> count); i++) {
		    if (!memcmp (&remote.sin_addr,
				 &lp -> connect_list -> addresses [i].address,
				 sizeof remote.sin_addr) &&
			(ntohs (remote.sin_port) ==
			 lp -> connect_list -> addresses [i].port))
			lp -> state = omapi_connection_connected;
			lp -> remote_addr = remote;
			lp -> remote_addr.sin_family = AF_INET;
			omapi_addr_list_dereference (&lp -> connect_list, MDL);
			lp -> index = connect_index;
			status = omapi_signal_in ((omapi_object_t *)lp,
						  "connect");
			omapi_connection_dereference (&lp, MDL);
			return;
		}
	} omapi_array_foreach_end (omapi_connections,
예제 #5
0
static void trace_connect_input (trace_type_t *ttype,
				 unsigned length, char *buf)
{
	struct sockaddr_in remote, local;
	int32_t connect_index, listener_index;
	char *s = buf;
	omapi_connection_object_t *obj;
	isc_result_t status;
	int i;

	if (length != ((sizeof connect_index) +
		       (sizeof remote.sin_port) +
		       (sizeof remote.sin_addr)) * 2) {
		log_error ("Trace connect: invalid length %d", length);
		return;
	}

	memset (&remote, 0, sizeof remote);
	memset (&local, 0, sizeof local);
	memcpy (&connect_index, s, sizeof connect_index);
	s += sizeof connect_index;
	memcpy (&listener_index, s, sizeof listener_index);
	s += sizeof listener_index;
	memcpy (&remote.sin_port, s, sizeof remote.sin_port);
	s += sizeof remote.sin_port;
	memcpy (&local.sin_port, s, sizeof local.sin_port);
	s += sizeof local.sin_port;
	memcpy (&remote.sin_addr, s, sizeof remote.sin_addr);
	s += sizeof remote.sin_addr;
	memcpy (&local.sin_addr, s, sizeof local.sin_addr);
	s += sizeof local.sin_addr;

	connect_index = ntohl (connect_index);
	listener_index = ntohl (listener_index);

	/* If this was a connect to a listener, then we just slap together
	   a new connection. */
	if (listener_index != -1) {
		omapi_listener_object_t *listener;
		listener = (omapi_listener_object_t *)0;
		omapi_array_foreach_begin (trace_listeners,
					   omapi_listener_object_t, lp) {
			if (lp -> address.sin_port == local.sin_port) {
				omapi_listener_reference (&listener, lp, MDL);
				omapi_listener_dereference (&lp, MDL);
				break;
			} 
		} omapi_array_foreach_end (trace_listeners,
					   omapi_listener_object_t, lp);
		if (!listener) {
			log_error ("%s%ld, addr %s, port %d",
				   "Spurious traced listener connect - index ",
				   (long int)listener_index,
				   inet_ntoa (local.sin_addr),
				   ntohs (local.sin_port));
			return;
		}
		obj = (omapi_connection_object_t *)0;
		status = omapi_listener_connect (&obj, listener, -1, &remote);
		if (status != ISC_R_SUCCESS) {
			log_error ("traced listener connect: %s",
				   isc_result_totext (status));
		}
		if (obj)
			omapi_connection_dereference (&obj, MDL);
		omapi_listener_dereference (&listener, MDL);
		return;
	}
예제 #6
0
isc_result_t omapi_connect_list (omapi_object_t *c,
				 omapi_addr_list_t *remote_addrs,
				 omapi_addr_t *local_addr)
{
	isc_result_t status;
	omapi_connection_object_t *obj;
	int flag;
	struct sockaddr_in local_sin;

	obj = (omapi_connection_object_t *)0;
	status = omapi_connection_allocate (&obj, MDL);
	if (status != ISC_R_SUCCESS)
		return status;

	status = omapi_object_reference (&c -> outer, (omapi_object_t *)obj,
					 MDL);
	if (status != ISC_R_SUCCESS) {
		omapi_connection_dereference (&obj, MDL);
		return status;
	}
	status = omapi_object_reference (&obj -> inner, c, MDL);
	if (status != ISC_R_SUCCESS) {
		omapi_connection_dereference (&obj, MDL);
		return status;
	}

	/* Store the address list on the object. */
	omapi_addr_list_reference (&obj -> connect_list, remote_addrs, MDL);
	obj -> cptr = 0;
	obj -> state = omapi_connection_unconnected;

#if defined (TRACING)
	/* If we're playing back, don't actually try to connect - just leave
	   the object available for a subsequent connect or disconnect. */
	if (!trace_playback ()) {
#endif
		/* Create a socket on which to communicate. */
		obj -> socket =
			socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (obj -> socket < 0) {
			omapi_connection_dereference (&obj, MDL);
			if (errno == EMFILE || errno == ENFILE
			    || errno == ENOBUFS)
				return ISC_R_NORESOURCES;
			return ISC_R_UNEXPECTED;
		}

		/* Set up the local address, if any. */
		if (local_addr) {
			/* Only do TCPv4 so far. */
			if (local_addr -> addrtype != AF_INET) {
				omapi_connection_dereference (&obj, MDL);
				return DHCP_R_INVALIDARG;
			}
			local_sin.sin_port = htons (local_addr -> port);
			memcpy (&local_sin.sin_addr,
				local_addr -> address,
				local_addr -> addrlen);
#if defined (HAVE_SA_LEN)
			local_sin.sin_len = sizeof local_addr;
#endif
			local_sin.sin_family = AF_INET;
			memset (&local_sin.sin_zero, 0,
				sizeof local_sin.sin_zero);
			
			if (bind (obj -> socket, (struct sockaddr *)&local_sin,
				  sizeof local_sin) < 0) {
				omapi_connection_object_t **objp = &obj;
				omapi_object_t **o = (omapi_object_t **)objp;
				omapi_object_dereference(o, MDL);
				if (errno == EADDRINUSE)
					return ISC_R_ADDRINUSE;
				if (errno == EADDRNOTAVAIL)
					return ISC_R_ADDRNOTAVAIL;
				if (errno == EACCES)
					return ISC_R_NOPERM;
				return ISC_R_UNEXPECTED;
			}
			obj -> local_addr = local_sin;
		}

#if defined(F_SETFD)
		if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
			close (obj -> socket);
			omapi_connection_dereference (&obj, MDL);
			return ISC_R_UNEXPECTED;
		}
#endif

		/* Set the SO_REUSEADDR flag (this should not fail). */
		flag = 1;
		if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
				(char *)&flag, sizeof flag) < 0) {
			omapi_connection_dereference (&obj, MDL);
			return ISC_R_UNEXPECTED;
		}
	
		/* Set the file to nonblocking mode. */
		if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
			omapi_connection_dereference (&obj, MDL);
			return ISC_R_UNEXPECTED;
		}

		status = (omapi_register_io_object
			  ((omapi_object_t *)obj,
			   0, omapi_connection_writefd,
			   0, omapi_connection_connect,
			   omapi_connection_reaper));
		if (status != ISC_R_SUCCESS)
			goto out;
		status = omapi_connection_connect_internal ((omapi_object_t *)
							    obj);
#if defined (TRACING)
	}
	omapi_connection_register (obj, MDL);
#endif

      out:
	omapi_connection_dereference (&obj, MDL);
	return status;
}