mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-01 23:05:29 +00:00
Add tracing support for OMAPI connects and disconnects.
This commit is contained in:
@@ -45,6 +45,17 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <arpa/nameser.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_OBJECT_ALLOC (omapi_connection,
|
||||||
omapi_connection_object_t, omapi_type_connection)
|
omapi_connection_object_t, omapi_type_connection)
|
||||||
|
|
||||||
@@ -224,14 +235,27 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined (TRACING)
|
#if defined (TRACING)
|
||||||
static omapi_array_t *omapi_connections;
|
omapi_array_t *omapi_connections;
|
||||||
|
|
||||||
OMAPI_ARRAY_TYPE(omapi_connection, omapi_connection_object_t);
|
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,
|
void omapi_connection_register (omapi_connection_object_t *obj,
|
||||||
const char *file, int line)
|
const char *file, int line)
|
||||||
{
|
{
|
||||||
isc_result_t status;
|
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) {
|
if (!omapi_connections) {
|
||||||
status = omapi_connection_array_allocate (&omapi_connections,
|
status = omapi_connection_array_allocate (&omapi_connections,
|
||||||
@@ -240,7 +264,168 @@ void omapi_connection_register (omapi_connection_object_t *obj,
|
|||||||
return;
|
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
|
#endif
|
||||||
|
|
||||||
/* Disconnect a connection object from the remote end. If force is nonzero,
|
/* Disconnect a connection object from the remote end. If force is nonzero,
|
||||||
@@ -251,6 +436,7 @@ isc_result_t omapi_disconnect (omapi_object_t *h,
|
|||||||
int force)
|
int force)
|
||||||
{
|
{
|
||||||
omapi_connection_object_t *c;
|
omapi_connection_object_t *c;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
#ifdef DEBUG_PROTOCOL
|
#ifdef DEBUG_PROTOCOL
|
||||||
log_debug ("omapi_disconnect(%s)", force ? "force" : "");
|
log_debug ("omapi_disconnect(%s)", force ? "force" : "");
|
||||||
@@ -260,24 +446,45 @@ isc_result_t omapi_disconnect (omapi_object_t *h,
|
|||||||
if (c -> type != omapi_type_connection)
|
if (c -> type != omapi_type_connection)
|
||||||
return ISC_R_INVALIDARG;
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
if (!force) {
|
#if defined (TRACING)
|
||||||
/* If we're already disconnecting, we don't have to do
|
if (trace_record ()) {
|
||||||
anything. */
|
int32_t index;
|
||||||
if (c -> state == omapi_connection_disconnecting)
|
|
||||||
return ISC_R_SUCCESS;
|
|
||||||
|
|
||||||
/* Try to shut down the socket - this sends a FIN to the
|
index = htonl (c -> index);
|
||||||
remote end, so that it won't send us any more data. If
|
status = trace_write_packet (trace_disconnect,
|
||||||
the shutdown succeeds, and we still have bytes left to
|
sizeof index, (char *)&index,
|
||||||
write, defer closing the socket until that's done. */
|
MDL);
|
||||||
if (!shutdown (c -> socket, SHUT_RD)) {
|
if (status != ISC_R_SUCCESS) {
|
||||||
if (c -> out_bytes > 0) {
|
trace_stop ();
|
||||||
c -> state = omapi_connection_disconnecting;
|
log_error ("trace_write_packet: %s",
|
||||||
return ISC_R_SUCCESS;
|
isc_result_totext (status));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close (c -> socket);
|
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)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
c -> state = omapi_connection_closed;
|
c -> state = omapi_connection_closed;
|
||||||
|
|
||||||
/* Disconnect from I/O object, if any. */
|
/* Disconnect from I/O object, if any. */
|
||||||
|
Reference in New Issue
Block a user