From: Ted Lemon Date: Mon, 12 Feb 2001 20:49:54 +0000 (+0000) Subject: Add some support for tracing connections. X-Git-Tag: V3-BETA-2-PATCH-18~63 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3ce5a42015a0837842950b5e384548e17f085efe;p=thirdparty%2Fdhcp.git Add some support for tracing connections. --- diff --git a/omapip/connection.c b/omapip/connection.c index 55c91d145..f3908eac1 100644 --- a/omapip/connection.c +++ b/omapip/connection.c @@ -3,7 +3,7 @@ Subroutines for dealing with connections. */ /* - * Copyright (c) 1999-2000 Internet Software Consortium. + * Copyright (c) 1999-2001 Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,6 +108,10 @@ isc_result_t omapi_connect_list (omapi_object_t *c, omapi_connection_object_t *obj; int flag; struct sockaddr_in local_sin; +#if defined (TRACING) + trace_addr_t *addrs; + u_int16_t naddrs; +#endif obj = (omapi_connection_object_t *)0; status = omapi_connection_allocate (&obj, MDL); @@ -126,87 +130,119 @@ isc_result_t omapi_connect_list (omapi_object_t *c, return status; } - /* 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; - } + /* 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; - /* Set up the local address, if any. */ - if (local_addr) { - /* Only do TCPv4 so far. */ - if (local_addr -> addrtype != AF_INET) { +#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); - return ISC_R_INVALIDARG; + if (errno == EMFILE || errno == ENFILE + || errno == ENOBUFS) + return ISC_R_NORESOURCES; + return ISC_R_UNEXPECTED; } - local_sin.sin_port = htons (local_addr -> port); - memcpy (&local_sin.sin_addr, - local_addr -> address, - local_addr -> addrlen); + + /* 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 ISC_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; + 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_object_dereference ((omapi_object_t **)&obj, - 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; + 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_object_dereference ((omapi_object_t **) + &obj, 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; + } } - } #if defined (HAVE_SETFD) - if (fcntl (obj -> socket, F_SETFD, 1) < 0) { - close (obj -> socket); - omapi_connection_dereference (&obj, MDL); - return ISC_R_UNEXPECTED; - } + 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 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; - } + /* Set the file to nonblocking mode. */ + if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) { + omapi_connection_dereference (&obj, MDL); + return ISC_R_UNEXPECTED; + } - /* Store the address list on the object. */ - omapi_addr_list_reference (&obj -> connect_list, remote_addrs, MDL); - obj -> cptr = 0; + 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 ((omapi_object_t *)obj); +#if defined (TRACING) + } + omapi_connection_register (obj, MDL); +#endif - 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; - obj -> state = omapi_connection_unconnected; - status = omapi_connection_connect ((omapi_object_t *)obj); out: omapi_connection_dereference (&obj, MDL); return status; } +#if defined (TRACING) +static omapi_array_t *omapi_connections; + +OMAPI_ARRAY_TYPE(omapi_connection, omapi_connection_object_t); + +void omapi_connection_register (omapi_connection_object_t *obj, + const char *file, int line) +{ + isc_result_t status; + + if (!omapi_connections) { + status = omapi_connection_array_allocate (&omapi_connections, + file, line); + if (status != ISC_R_SUCCESS) + return; + } + +} +#endif + /* Disconnect a connection object from the remote end. If force is nonzero, close the connection immediately. Otherwise, shut down the receiving end but allow any unsent data to be sent before actually closing the socket. */ @@ -374,7 +410,6 @@ isc_result_t omapi_connection_connect (omapi_object_t *h) } return status; } -printf("EINPROGRESS\n"); c -> state = omapi_connection_connecting; return ISC_R_INCOMPLETE; } diff --git a/omapip/listener.c b/omapip/listener.c index 325e01cac..5a0a38b22 100644 --- a/omapip/listener.c +++ b/omapip/listener.c @@ -3,7 +3,7 @@ Subroutines that support the generic listener object. */ /* - * Copyright (c) 1999-2000 Internet Software Consortium. + * Copyright (c) 1999-2001 Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,6 +43,15 @@ #include +#if defined (TRACING) +static omapi_array_t *trace_listeners; +static void trace_listener_accept_input (trace_type_t *, unsigned, char *); +static void trace_listener_remember (omapi_listener_object_t *, + const char *, int); +static void trace_listener_accept_stop (trace_type_t *); +trace_type_t *trace_listener_accept; +#endif + OMAPI_OBJECT_ALLOC (omapi_listener, omapi_listener_object_t, omapi_type_listener) @@ -110,61 +119,72 @@ isc_result_t omapi_listen_addr (omapi_object_t *h, memset (&(obj -> address.sin_zero), 0, sizeof obj -> address.sin_zero); - /* Create a socket on which to listen. */ - obj -> socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (!obj -> socket) { - omapi_listener_dereference (&obj, MDL); - if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS) - return ISC_R_NORESOURCES; - return ISC_R_UNEXPECTED; - } +#if defined (TRACING) + /* If we're playing back a trace file, we remember the object + on the trace listener queue. */ + if (trace_playback ()) { + trace_listener_remember (obj, MDL); + } else { +#endif + /* Create a socket on which to listen. */ + obj -> socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (!obj -> socket) { + omapi_listener_dereference (&obj, MDL); + if (errno == EMFILE + || errno == ENFILE || errno == ENOBUFS) + return ISC_R_NORESOURCES; + return ISC_R_UNEXPECTED; + } #if defined (HAVE_SETFD) - if (fcntl (obj -> socket, F_SETFD, 1) < 0) { - close (obj -> socket); - omapi_listener_dereference (&obj, MDL); - return ISC_R_UNEXPECTED; - } + if (fcntl (obj -> socket, F_SETFD, 1) < 0) { + close (obj -> socket); + omapi_listener_dereference (&obj, MDL); + return ISC_R_UNEXPECTED; + } #endif - /* Set the REUSEADDR option so that we don't fail to start if - we're being restarted. */ - i = 1; - if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR, - (char *)&i, sizeof i) < 0) { - close (obj -> socket); - omapi_listener_dereference (&obj, MDL); - return ISC_R_UNEXPECTED; - } + /* Set the REUSEADDR option so that we don't fail to start if + we're being restarted. */ + i = 1; + if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR, + (char *)&i, sizeof i) < 0) { + close (obj -> socket); + omapi_listener_dereference (&obj, MDL); + return ISC_R_UNEXPECTED; + } + /* Try to bind to the wildcard address using the port number + we were given. */ + i = bind (obj -> socket, + (struct sockaddr *)&obj -> address, + sizeof obj -> address); + if (i < 0) { + omapi_listener_dereference (&obj, MDL); + if (errno == EADDRINUSE) + return ISC_R_ADDRNOTAVAIL; + if (errno == EPERM) + return ISC_R_NOPERM; + return ISC_R_UNEXPECTED; + } - /* Try to bind to the wildcard address using the port number - we were given. */ - i = bind (obj -> socket, - (struct sockaddr *)&obj -> address, sizeof obj -> address); - if (i < 0) { - omapi_listener_dereference (&obj, MDL); - if (errno == EADDRINUSE) - return ISC_R_ADDRNOTAVAIL; - if (errno == EPERM) - return ISC_R_NOPERM; - return ISC_R_UNEXPECTED; - } + /* Now tell the kernel to listen for connections. */ + if (listen (obj -> socket, max)) { + omapi_listener_dereference (&obj, MDL); + return ISC_R_UNEXPECTED; + } - /* Now tell the kernel to listen for connections. */ - if (listen (obj -> socket, max)) { - omapi_listener_dereference (&obj, MDL); - return ISC_R_UNEXPECTED; - } + if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) { + omapi_listener_dereference (&obj, MDL); + return ISC_R_UNEXPECTED; + } - if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) { - omapi_listener_dereference (&obj, MDL); - return ISC_R_UNEXPECTED; + status = omapi_register_io_object ((omapi_object_t *)obj, + omapi_listener_readfd, 0, + omapi_accept, 0, 0); +#if defined (TRACING) } - - status = omapi_register_io_object ((omapi_object_t *)obj, - omapi_listener_readfd, 0, - omapi_accept, 0, 0); +#endif omapi_listener_dereference (&obj, MDL); return status; } @@ -189,74 +209,177 @@ isc_result_t omapi_accept (omapi_object_t *h) SOCKLEN_T len; omapi_connection_object_t *obj; omapi_listener_object_t *listener; - omapi_addr_t addr; + omapi_addr_t remote_addr; int i; + 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]; + u_int32_t lsock; + 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. */ - obj = (omapi_connection_object_t *)0; - status = omapi_connection_allocate (&obj, MDL); + status = omapi_connection_allocate (obj, MDL); if (status != ISC_R_SUCCESS) return status; - /* Accept the connection. */ - len = sizeof obj -> remote_addr; - obj -> socket = - accept (listener -> socket, - ((struct sockaddr *) - &(obj -> remote_addr)), &len); - if (obj -> socket < 0) { - omapi_connection_dereference (&obj, MDL); - if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS) - return ISC_R_NORESOURCES; - return ISC_R_UNEXPECTED; - } - - obj -> state = omapi_connection_connected; + (*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 (obj -> remote_addr.sin_addr); - memcpy (addr.address, &obj -> remote_addr.sin_addr, - sizeof (obj -> remote_addr.sin_addr)); - addr.port = ntohs(obj -> remote_addr.sin_port); + 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_disconnect ((omapi_object_t *)(*obj), 1); + omapi_connection_dereference (obj, MDL); 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); - if (status != ISC_R_SUCCESS) { - 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; +} - omapi_listener_reference (&obj -> listener, listener, MDL); +#if defined (TRACING) +OMAPI_ARRAY_TYPE(omapi_listener, omapi_listener_object_t); - status = omapi_signal (h, "connect", obj); +void omapi_listener_trace_setup (void) { + trace_listener_accept = + trace_type_register ("listener_accept", (void *)0, + trace_listener_accept_input, + trace_listener_accept_stop, MDL); +} - /* Lose our reference to the connection, so it'll be gc'd when it's - reaped. */ - omapi_connection_dereference (&obj, MDL); - return status; +static void trace_listener_remember (omapi_listener_object_t *obj, + const char *file, int line) +{ + isc_result_t status; + if (!trace_listeners) { + status = omapi_listener_array_allocate (&trace_listeners, + file, line); + if (status != ISC_R_SUCCESS) { + foo: + log_error ("trace_listener_remember: %s", + isc_result_totext (status)); + return; + } + } + status = omapi_listener_array_extend (trace_listeners, + obj, (int *)0, MDL); + if (status != ISC_R_SUCCESS) + goto foo; } +static void trace_listener_accept_input (trace_type_t *ttype, + unsigned length, char *buf) +{ + struct in_addr *addr; + u_int16_t *remote_port; + u_int16_t *local_port; + omapi_connection_object_t *obj; + isc_result_t status; + struct sockaddr_in remote_addr; + + addr = (struct in_addr *)buf; + remote_port = (u_int16_t *)(addr + 1); + local_port = remote_port + 1; + + memset (&remote_addr, 0, sizeof remote_addr); + remote_addr.sin_addr = *addr; + remote_addr.sin_port = *remote_port; + + omapi_array_foreach_begin (trace_listeners, + omapi_listener_object_t, lp) { + if (lp -> address.sin_port == *local_port) { + obj = (omapi_connection_object_t *)0; + status = omapi_listener_connect (&obj, + lp, 0, &remote_addr); + return; + } + } omapi_array_foreach_end (trace_listeners, + omapi_listener_object_t, lp); + log_error ("trace_listener_accept: %s from %s/%d to port %d", + "unexpected connect", + inet_ntoa (*addr), *remote_port, *local_port); +} + +static void trace_listener_accept_stop (trace_type_t *ttype) { } + + +#endif + isc_result_t omapi_listener_configure_security (omapi_object_t *h, isc_result_t (*verify_addr) (omapi_object_t *, diff --git a/omapip/support.c b/omapip/support.c index 7552f885e..0a7509e28 100644 --- a/omapip/support.c +++ b/omapip/support.c @@ -3,7 +3,7 @@ Subroutines providing general support for objects. */ /* - * Copyright (c) 1999-2000 Internet Software Consortium. + * Copyright (c) 1999-2001 Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -180,6 +180,10 @@ isc_result_t omapi_init (void) if (status != ISC_R_SUCCESS) return status; +#if defined (TRACING) + omapi_listener_trace_setup (); +#endif + /* This seems silly, but leave it. */ return ISC_R_SUCCESS; }