예제 #1
0
isc_result_t omapi_connection_connect (omapi_object_t *h)
{
	isc_result_t status;

	/*
	 * We use the INPROGRESS status to indicate that
	 * we want more from the socket.  In this case we
	 * have now connected and are trying to write to
	 * the socket for the first time.  For the signaling
	 * code this is the same as a SUCCESS so we don't
	 * pass it on as a signal.
	 */
	status = omapi_connection_connect_internal (h);
	if (status == ISC_R_INPROGRESS) 
		return ISC_R_INPROGRESS;

	if (status != ISC_R_SUCCESS)
		omapi_signal (h, "status", status);

	return ISC_R_SUCCESS;
}
예제 #2
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;
}