]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Add some support for tracing connections.
authorTed Lemon <source@isc.org>
Mon, 12 Feb 2001 20:49:54 +0000 (20:49 +0000)
committerTed Lemon <source@isc.org>
Mon, 12 Feb 2001 20:49:54 +0000 (20:49 +0000)
omapip/connection.c
omapip/listener.c
omapip/support.c

index 55c91d145573a53d241c8b937c77032de7d750bc..f3908eac1617c46d89505513e27fdf5c6a1fd0d6 100644 (file)
@@ -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;
                }
index 325e01cac91975482ec9547788997eef85d4be87..5a0a38b22953552d2933a9a059b9324bd6bca23a 100644 (file)
@@ -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
 
 #include <omapip/omapip_p.h>
 
+#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 *,
index 7552f885e16a70aac6d781de44e77d9d0ab77056..0a7509e282386d5dc17c04f1172fc132572dfa2f 100644 (file)
@@ -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;
 }