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); }
/* 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; }
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; }
/* 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,
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; }
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; }