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
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);
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. */
}
return status;
}
-printf("EINPROGRESS\n");
c -> state = omapi_connection_connecting;
return ISC_R_INCOMPLETE;
}
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)
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;
}
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 *,