#include <arpa/inet.h>
#include <arpa/nameser.h>
+
+#if defined (TRACING)
+static void trace_connect_input (trace_type_t *, unsigned, char *);
+static void trace_connect_stop (trace_type_t *);
+static void trace_disconnect_input (trace_type_t *, unsigned, char *);
+static void trace_disconnect_stop (trace_type_t *);
+trace_type_t *trace_connect;
+trace_type_t *trace_disconnect;
+extern omapi_array_t *trace_listeners;
+#endif
+
OMAPI_OBJECT_ALLOC (omapi_connection,
omapi_connection_object_t, omapi_type_connection)
}
#if defined (TRACING)
-static omapi_array_t *omapi_connections;
+omapi_array_t *omapi_connections;
OMAPI_ARRAY_TYPE(omapi_connection, omapi_connection_object_t);
+void omapi_connection_trace_setup (void) {
+ trace_connect = trace_type_register ("connect", (void *)0,
+ trace_connect_input,
+ trace_connect_stop, MDL);
+ trace_disconnect = trace_type_register ("disconnect", (void *)0,
+ trace_disconnect_input,
+ trace_disconnect_stop, MDL);
+}
+
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,
return;
}
+ status = omapi_connection_array_extend (omapi_connections, obj,
+ (u_int32_t *)0, file, line);
+ if (status != ISC_R_SUCCESS) {
+ obj -> index = -1;
+ return;
+ }
+
+ 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);
+ }
+}
+
+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;
+
+ 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, buf, sizeof connect_index);
+ s += sizeof connect_index;
+ memcpy (&listener_index, buf, 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%d, addr %s, port %d",
+ "Spurious traced listener connect - index ",
+ 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;
+ }
+
+ /* Find the matching connect object, if there is one. */
+ omapi_array_foreach_begin (omapi_connections,
+ omapi_connection_object_t, lp) {
+ if (lp -> local_addr.sin_port == local.sin_port &&
+ (lp -> local_addr.sin_addr.s_addr == htonl (INADDR_ANY) ||
+ (lp -> local_addr.sin_addr.s_addr ==
+ local.sin_addr.s_addr))) {
+ 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,
+ omapi_connection_object_t, lp);
+
+ log_error ("Spurious traced connect - index %d, addr %s, port %d",
+ connect_index, inet_ntoa (remote.sin_addr),
+ ntohs (remote.sin_port));
+ return;
+}
+
+static void trace_connect_stop (trace_type_t *ttype) { }
+
+static void trace_disconnect_input (trace_type_t *ttype,
+ unsigned length, char *buf)
+{
+ int32_t *index;
+ if (length != sizeof *index) {
+ log_error ("trace disconnect: wrong length %d", length);
+ return;
+ }
+
+ index = (int32_t *)buf;
+
+ omapi_array_foreach_begin (omapi_connections,
+ omapi_connection_object_t, lp) {
+ if (lp -> index == ntohl (*index)) {
+ omapi_disconnect ((omapi_object_t *)lp, 1);
+ omapi_connection_dereference (&lp, MDL);
+ return;
+ }
+ } omapi_array_foreach_end (omapi_connections,
+ omapi_connection_object_t, lp);
+
+ log_error ("trace disconnect: no connection matching index %d",
+ ntohl (*index));
}
+
+static void trace_disconnect_stop (trace_type_t *ttype) { }
#endif
/* Disconnect a connection object from the remote end. If force is nonzero,
int force)
{
omapi_connection_object_t *c;
+ isc_result_t status;
#ifdef DEBUG_PROTOCOL
log_debug ("omapi_disconnect(%s)", force ? "force" : "");
if (c -> type != omapi_type_connection)
return ISC_R_INVALIDARG;
- if (!force) {
- /* If we're already disconnecting, we don't have to do
- anything. */
- if (c -> state == omapi_connection_disconnecting)
- return ISC_R_SUCCESS;
-
- /* Try to shut down the socket - this sends a FIN to the
- remote end, so that it won't send us any more data. If
- the shutdown succeeds, and we still have bytes left to
- write, defer closing the socket until that's done. */
- if (!shutdown (c -> socket, SHUT_RD)) {
- if (c -> out_bytes > 0) {
- c -> state = omapi_connection_disconnecting;
+#if defined (TRACING)
+ if (trace_record ()) {
+ int32_t index;
+
+ index = htonl (c -> index);
+ status = trace_write_packet (trace_disconnect,
+ sizeof index, (char *)&index,
+ MDL);
+ if (status != ISC_R_SUCCESS) {
+ trace_stop ();
+ log_error ("trace_write_packet: %s",
+ isc_result_totext (status));
+ }
+ }
+ if (!trace_playback ()) {
+#endif
+ if (!force) {
+ /* If we're already disconnecting, we don't have to do
+ anything. */
+ if (c -> state == omapi_connection_disconnecting)
return ISC_R_SUCCESS;
+
+ /* Try to shut down the socket - this sends a FIN to
+ the remote end, so that it won't send us any more
+ data. If the shutdown succeeds, and we still
+ have bytes left to write, defer closing the socket
+ until that's done. */
+ if (!shutdown (c -> socket, SHUT_RD)) {
+ if (c -> out_bytes > 0) {
+ c -> state =
+ omapi_connection_disconnecting;
+ return ISC_R_SUCCESS;
+ }
}
}
+ close (c -> socket);
+#if defined (TRACING)
}
- close (c -> socket);
+#endif
c -> state = omapi_connection_closed;
/* Disconnect from I/O object, if any. */