Home | History | Annotate | Line # | Download | only in omapip
connection.c revision 1.2.2.2
      1  1.2.2.2  pgoyette /*	$NetBSD: connection.c,v 1.2.2.2 2018/04/16 01:59:48 pgoyette Exp $	*/
      2  1.2.2.2  pgoyette 
      3  1.2.2.2  pgoyette /* connection.c
      4  1.2.2.2  pgoyette 
      5  1.2.2.2  pgoyette    Subroutines for dealing with connections. */
      6  1.2.2.2  pgoyette 
      7  1.2.2.2  pgoyette /*
      8  1.2.2.2  pgoyette  * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
      9  1.2.2.2  pgoyette  * Copyright (c) 1999-2003 by Internet Software Consortium
     10  1.2.2.2  pgoyette  *
     11  1.2.2.2  pgoyette  * This Source Code Form is subject to the terms of the Mozilla Public
     12  1.2.2.2  pgoyette  * License, v. 2.0. If a copy of the MPL was not distributed with this
     13  1.2.2.2  pgoyette  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     14  1.2.2.2  pgoyette  *
     15  1.2.2.2  pgoyette  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     16  1.2.2.2  pgoyette  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     17  1.2.2.2  pgoyette  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     18  1.2.2.2  pgoyette  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19  1.2.2.2  pgoyette  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     20  1.2.2.2  pgoyette  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     21  1.2.2.2  pgoyette  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22  1.2.2.2  pgoyette  *
     23  1.2.2.2  pgoyette  *   Internet Systems Consortium, Inc.
     24  1.2.2.2  pgoyette  *   950 Charter Street
     25  1.2.2.2  pgoyette  *   Redwood City, CA 94063
     26  1.2.2.2  pgoyette  *   <info (at) isc.org>
     27  1.2.2.2  pgoyette  *   https://www.isc.org/
     28  1.2.2.2  pgoyette  *
     29  1.2.2.2  pgoyette  */
     30  1.2.2.2  pgoyette 
     31  1.2.2.2  pgoyette #include <sys/cdefs.h>
     32  1.2.2.2  pgoyette __RCSID("$NetBSD: connection.c,v 1.2.2.2 2018/04/16 01:59:48 pgoyette Exp $");
     33  1.2.2.2  pgoyette 
     34  1.2.2.2  pgoyette #include "dhcpd.h"
     35  1.2.2.2  pgoyette #include <isc/util.h>
     36  1.2.2.2  pgoyette #include <omapip/omapip_p.h>
     37  1.2.2.2  pgoyette #include <arpa/inet.h>
     38  1.2.2.2  pgoyette #include <arpa/nameser.h>
     39  1.2.2.2  pgoyette #include <errno.h>
     40  1.2.2.2  pgoyette 
     41  1.2.2.2  pgoyette #if defined (TRACING)
     42  1.2.2.2  pgoyette static void trace_connect_input (trace_type_t *, unsigned, char *);
     43  1.2.2.2  pgoyette static void trace_connect_stop (trace_type_t *);
     44  1.2.2.2  pgoyette static void trace_disconnect_input (trace_type_t *, unsigned, char *);
     45  1.2.2.2  pgoyette static void trace_disconnect_stop (trace_type_t *);
     46  1.2.2.2  pgoyette trace_type_t *trace_connect;
     47  1.2.2.2  pgoyette trace_type_t *trace_disconnect;
     48  1.2.2.2  pgoyette extern omapi_array_t *trace_listeners;
     49  1.2.2.2  pgoyette #endif
     50  1.2.2.2  pgoyette static isc_result_t omapi_connection_connect_internal (omapi_object_t *);
     51  1.2.2.2  pgoyette 
     52  1.2.2.2  pgoyette OMAPI_OBJECT_ALLOC (omapi_connection,
     53  1.2.2.2  pgoyette 		    omapi_connection_object_t, omapi_type_connection)
     54  1.2.2.2  pgoyette 
     55  1.2.2.2  pgoyette isc_result_t omapi_connect (omapi_object_t *c,
     56  1.2.2.2  pgoyette 			    const char *server_name,
     57  1.2.2.2  pgoyette 			    unsigned port)
     58  1.2.2.2  pgoyette {
     59  1.2.2.2  pgoyette 	struct hostent *he;
     60  1.2.2.2  pgoyette 	unsigned i, hix;
     61  1.2.2.2  pgoyette 	omapi_addr_list_t *addrs = (omapi_addr_list_t *)0;
     62  1.2.2.2  pgoyette 	struct in_addr foo;
     63  1.2.2.2  pgoyette 	isc_result_t status;
     64  1.2.2.2  pgoyette 
     65  1.2.2.2  pgoyette #ifdef DEBUG_PROTOCOL
     66  1.2.2.2  pgoyette 	log_debug ("omapi_connect(%s, port=%d)", server_name, port);
     67  1.2.2.2  pgoyette #endif
     68  1.2.2.2  pgoyette 
     69  1.2.2.2  pgoyette 	if (!inet_aton (server_name, &foo)) {
     70  1.2.2.2  pgoyette 		/* If we didn't get a numeric address, try for a domain
     71  1.2.2.2  pgoyette 		   name.  It's okay for this call to block. */
     72  1.2.2.2  pgoyette 		he = gethostbyname (server_name);
     73  1.2.2.2  pgoyette 		if (!he)
     74  1.2.2.2  pgoyette 			return DHCP_R_HOSTUNKNOWN;
     75  1.2.2.2  pgoyette 		for (i = 0; he -> h_addr_list [i]; i++)
     76  1.2.2.2  pgoyette 			;
     77  1.2.2.2  pgoyette 		if (i == 0)
     78  1.2.2.2  pgoyette 			return DHCP_R_HOSTUNKNOWN;
     79  1.2.2.2  pgoyette 		hix = i;
     80  1.2.2.2  pgoyette 
     81  1.2.2.2  pgoyette 		status = omapi_addr_list_new (&addrs, hix, MDL);
     82  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS)
     83  1.2.2.2  pgoyette 			return status;
     84  1.2.2.2  pgoyette 		for (i = 0; i < hix; i++) {
     85  1.2.2.2  pgoyette 			addrs -> addresses [i].addrtype = he -> h_addrtype;
     86  1.2.2.2  pgoyette 			addrs -> addresses [i].addrlen = he -> h_length;
     87  1.2.2.2  pgoyette 			memcpy (addrs -> addresses [i].address,
     88  1.2.2.2  pgoyette 				he -> h_addr_list [i],
     89  1.2.2.2  pgoyette 				(unsigned)he -> h_length);
     90  1.2.2.2  pgoyette 			addrs -> addresses [i].port = port;
     91  1.2.2.2  pgoyette 		}
     92  1.2.2.2  pgoyette 	} else {
     93  1.2.2.2  pgoyette 		status = omapi_addr_list_new (&addrs, 1, MDL);
     94  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS)
     95  1.2.2.2  pgoyette 			return status;
     96  1.2.2.2  pgoyette 		addrs -> addresses [0].addrtype = AF_INET;
     97  1.2.2.2  pgoyette 		addrs -> addresses [0].addrlen = sizeof foo;
     98  1.2.2.2  pgoyette 		memcpy (addrs -> addresses [0].address, &foo, sizeof foo);
     99  1.2.2.2  pgoyette 		addrs -> addresses [0].port = port;
    100  1.2.2.2  pgoyette 	}
    101  1.2.2.2  pgoyette 	status = omapi_connect_list (c, addrs, (omapi_addr_t *)0);
    102  1.2.2.2  pgoyette 	omapi_addr_list_dereference (&addrs, MDL);
    103  1.2.2.2  pgoyette 	return status;
    104  1.2.2.2  pgoyette }
    105  1.2.2.2  pgoyette 
    106  1.2.2.2  pgoyette isc_result_t omapi_connect_list (omapi_object_t *c,
    107  1.2.2.2  pgoyette 				 omapi_addr_list_t *remote_addrs,
    108  1.2.2.2  pgoyette 				 omapi_addr_t *local_addr)
    109  1.2.2.2  pgoyette {
    110  1.2.2.2  pgoyette 	isc_result_t status;
    111  1.2.2.2  pgoyette 	omapi_connection_object_t *obj;
    112  1.2.2.2  pgoyette 	int flag;
    113  1.2.2.2  pgoyette 	struct sockaddr_in local_sin;
    114  1.2.2.2  pgoyette 
    115  1.2.2.2  pgoyette 	obj = (omapi_connection_object_t *)0;
    116  1.2.2.2  pgoyette 	status = omapi_connection_allocate (&obj, MDL);
    117  1.2.2.2  pgoyette 	if (status != ISC_R_SUCCESS)
    118  1.2.2.2  pgoyette 		return status;
    119  1.2.2.2  pgoyette 
    120  1.2.2.2  pgoyette 	status = omapi_object_reference (&c -> outer, (omapi_object_t *)obj,
    121  1.2.2.2  pgoyette 					 MDL);
    122  1.2.2.2  pgoyette 	if (status != ISC_R_SUCCESS) {
    123  1.2.2.2  pgoyette 		omapi_connection_dereference (&obj, MDL);
    124  1.2.2.2  pgoyette 		return status;
    125  1.2.2.2  pgoyette 	}
    126  1.2.2.2  pgoyette 	status = omapi_object_reference (&obj -> inner, c, MDL);
    127  1.2.2.2  pgoyette 	if (status != ISC_R_SUCCESS) {
    128  1.2.2.2  pgoyette 		omapi_connection_dereference (&obj, MDL);
    129  1.2.2.2  pgoyette 		return status;
    130  1.2.2.2  pgoyette 	}
    131  1.2.2.2  pgoyette 
    132  1.2.2.2  pgoyette 	/* Store the address list on the object. */
    133  1.2.2.2  pgoyette 	omapi_addr_list_reference (&obj -> connect_list, remote_addrs, MDL);
    134  1.2.2.2  pgoyette 	obj -> cptr = 0;
    135  1.2.2.2  pgoyette 	obj -> state = omapi_connection_unconnected;
    136  1.2.2.2  pgoyette 
    137  1.2.2.2  pgoyette #if defined (TRACING)
    138  1.2.2.2  pgoyette 	/* If we're playing back, don't actually try to connect - just leave
    139  1.2.2.2  pgoyette 	   the object available for a subsequent connect or disconnect. */
    140  1.2.2.2  pgoyette 	if (!trace_playback ()) {
    141  1.2.2.2  pgoyette #endif
    142  1.2.2.2  pgoyette 		/* Create a socket on which to communicate. */
    143  1.2.2.2  pgoyette 		obj -> socket =
    144  1.2.2.2  pgoyette 			socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
    145  1.2.2.2  pgoyette 		if (obj -> socket < 0) {
    146  1.2.2.2  pgoyette 			omapi_connection_dereference (&obj, MDL);
    147  1.2.2.2  pgoyette 			if (errno == EMFILE || errno == ENFILE
    148  1.2.2.2  pgoyette 			    || errno == ENOBUFS)
    149  1.2.2.2  pgoyette 				return ISC_R_NORESOURCES;
    150  1.2.2.2  pgoyette 			return ISC_R_UNEXPECTED;
    151  1.2.2.2  pgoyette 		}
    152  1.2.2.2  pgoyette 
    153  1.2.2.2  pgoyette 		/* Set up the local address, if any. */
    154  1.2.2.2  pgoyette 		if (local_addr) {
    155  1.2.2.2  pgoyette 			/* Only do TCPv4 so far. */
    156  1.2.2.2  pgoyette 			if (local_addr -> addrtype != AF_INET) {
    157  1.2.2.2  pgoyette 				close(obj->socket);
    158  1.2.2.2  pgoyette 				omapi_connection_dereference (&obj, MDL);
    159  1.2.2.2  pgoyette 				return DHCP_R_INVALIDARG;
    160  1.2.2.2  pgoyette 			}
    161  1.2.2.2  pgoyette 			local_sin.sin_port = htons (local_addr -> port);
    162  1.2.2.2  pgoyette 			memcpy (&local_sin.sin_addr,
    163  1.2.2.2  pgoyette 				local_addr -> address,
    164  1.2.2.2  pgoyette 				local_addr -> addrlen);
    165  1.2.2.2  pgoyette #if defined (HAVE_SA_LEN)
    166  1.2.2.2  pgoyette 			local_sin.sin_len = sizeof local_addr;
    167  1.2.2.2  pgoyette #endif
    168  1.2.2.2  pgoyette 			local_sin.sin_family = AF_INET;
    169  1.2.2.2  pgoyette 			memset (&local_sin.sin_zero, 0,
    170  1.2.2.2  pgoyette 				sizeof local_sin.sin_zero);
    171  1.2.2.2  pgoyette 
    172  1.2.2.2  pgoyette 			if (bind (obj -> socket, (struct sockaddr *)&local_sin,
    173  1.2.2.2  pgoyette 				  sizeof local_sin) < 0) {
    174  1.2.2.2  pgoyette 				omapi_connection_object_t **objp = &obj;
    175  1.2.2.2  pgoyette 				omapi_object_t **o = (omapi_object_t **)objp;
    176  1.2.2.2  pgoyette 				close(obj->socket);
    177  1.2.2.2  pgoyette 				omapi_object_dereference(o, MDL);
    178  1.2.2.2  pgoyette 				if (errno == EADDRINUSE)
    179  1.2.2.2  pgoyette 					return ISC_R_ADDRINUSE;
    180  1.2.2.2  pgoyette 				if (errno == EADDRNOTAVAIL)
    181  1.2.2.2  pgoyette 					return ISC_R_ADDRNOTAVAIL;
    182  1.2.2.2  pgoyette 				if (errno == EACCES)
    183  1.2.2.2  pgoyette 					return ISC_R_NOPERM;
    184  1.2.2.2  pgoyette 				return ISC_R_UNEXPECTED;
    185  1.2.2.2  pgoyette 			}
    186  1.2.2.2  pgoyette 			obj -> local_addr = local_sin;
    187  1.2.2.2  pgoyette 		}
    188  1.2.2.2  pgoyette 
    189  1.2.2.2  pgoyette #if defined(F_SETFD)
    190  1.2.2.2  pgoyette 		if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
    191  1.2.2.2  pgoyette 			close (obj -> socket);
    192  1.2.2.2  pgoyette 			omapi_connection_dereference (&obj, MDL);
    193  1.2.2.2  pgoyette 			return ISC_R_UNEXPECTED;
    194  1.2.2.2  pgoyette 		}
    195  1.2.2.2  pgoyette #endif
    196  1.2.2.2  pgoyette 
    197  1.2.2.2  pgoyette 		/* Set the SO_REUSEADDR flag (this should not fail). */
    198  1.2.2.2  pgoyette 		flag = 1;
    199  1.2.2.2  pgoyette 		if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
    200  1.2.2.2  pgoyette 				(char *)&flag, sizeof flag) < 0) {
    201  1.2.2.2  pgoyette 			omapi_connection_dereference (&obj, MDL);
    202  1.2.2.2  pgoyette 			return ISC_R_UNEXPECTED;
    203  1.2.2.2  pgoyette 		}
    204  1.2.2.2  pgoyette 
    205  1.2.2.2  pgoyette 		/* Set the file to nonblocking mode. */
    206  1.2.2.2  pgoyette 		if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
    207  1.2.2.2  pgoyette 			omapi_connection_dereference (&obj, MDL);
    208  1.2.2.2  pgoyette 			return ISC_R_UNEXPECTED;
    209  1.2.2.2  pgoyette 		}
    210  1.2.2.2  pgoyette 
    211  1.2.2.2  pgoyette #ifdef SO_NOSIGPIPE
    212  1.2.2.2  pgoyette 		/*
    213  1.2.2.2  pgoyette 		 * If available stop the OS from killing our
    214  1.2.2.2  pgoyette 		 * program on a SIGPIPE failure
    215  1.2.2.2  pgoyette 		 */
    216  1.2.2.2  pgoyette 		flag = 1;
    217  1.2.2.2  pgoyette 		if (setsockopt(obj->socket, SOL_SOCKET, SO_NOSIGPIPE,
    218  1.2.2.2  pgoyette 			       (char *)&flag, sizeof(flag)) < 0) {
    219  1.2.2.2  pgoyette 			omapi_connection_dereference (&obj, MDL);
    220  1.2.2.2  pgoyette 			return ISC_R_UNEXPECTED;
    221  1.2.2.2  pgoyette 		}
    222  1.2.2.2  pgoyette #endif
    223  1.2.2.2  pgoyette 
    224  1.2.2.2  pgoyette 		status = (omapi_register_io_object
    225  1.2.2.2  pgoyette 			  ((omapi_object_t *)obj,
    226  1.2.2.2  pgoyette 			   0, omapi_connection_writefd,
    227  1.2.2.2  pgoyette 			   0, omapi_connection_connect,
    228  1.2.2.2  pgoyette 			   omapi_connection_reaper));
    229  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS)
    230  1.2.2.2  pgoyette 			goto out;
    231  1.2.2.2  pgoyette 		status = omapi_connection_connect_internal ((omapi_object_t *)
    232  1.2.2.2  pgoyette 							    obj);
    233  1.2.2.2  pgoyette 		/*
    234  1.2.2.2  pgoyette 		 * inprogress is the same as success but used
    235  1.2.2.2  pgoyette 		 * to indicate to the dispatch code that we should
    236  1.2.2.2  pgoyette 		 * mark the socket as requiring more attention.
    237  1.2.2.2  pgoyette 		 * Routines calling this function should handle
    238  1.2.2.2  pgoyette 		 * success properly.
    239  1.2.2.2  pgoyette 		 */
    240  1.2.2.2  pgoyette 		if (status == ISC_R_INPROGRESS) {
    241  1.2.2.2  pgoyette 			status = ISC_R_SUCCESS;
    242  1.2.2.2  pgoyette 		}
    243  1.2.2.2  pgoyette #if defined (TRACING)
    244  1.2.2.2  pgoyette 	}
    245  1.2.2.2  pgoyette 	omapi_connection_register (obj, MDL);
    246  1.2.2.2  pgoyette #endif
    247  1.2.2.2  pgoyette 
    248  1.2.2.2  pgoyette       out:
    249  1.2.2.2  pgoyette 	omapi_connection_dereference (&obj, MDL);
    250  1.2.2.2  pgoyette 	return status;
    251  1.2.2.2  pgoyette }
    252  1.2.2.2  pgoyette 
    253  1.2.2.2  pgoyette #if defined (TRACING)
    254  1.2.2.2  pgoyette omapi_array_t *omapi_connections;
    255  1.2.2.2  pgoyette 
    256  1.2.2.2  pgoyette OMAPI_ARRAY_TYPE(omapi_connection, omapi_connection_object_t)
    257  1.2.2.2  pgoyette 
    258  1.2.2.2  pgoyette void omapi_connection_trace_setup (void) {
    259  1.2.2.2  pgoyette 	trace_connect = trace_type_register ("connect", (void *)0,
    260  1.2.2.2  pgoyette 					     trace_connect_input,
    261  1.2.2.2  pgoyette 					     trace_connect_stop, MDL);
    262  1.2.2.2  pgoyette 	trace_disconnect = trace_type_register ("disconnect", (void *)0,
    263  1.2.2.2  pgoyette 						trace_disconnect_input,
    264  1.2.2.2  pgoyette 						trace_disconnect_stop, MDL);
    265  1.2.2.2  pgoyette }
    266  1.2.2.2  pgoyette 
    267  1.2.2.2  pgoyette void omapi_connection_register (omapi_connection_object_t *obj,
    268  1.2.2.2  pgoyette 				const char *file, int line)
    269  1.2.2.2  pgoyette {
    270  1.2.2.2  pgoyette 	isc_result_t status;
    271  1.2.2.2  pgoyette 	trace_iov_t iov [6];
    272  1.2.2.2  pgoyette 	int iov_count = 0;
    273  1.2.2.2  pgoyette 	int32_t connect_index, listener_index;
    274  1.2.2.2  pgoyette 	static int32_t index;
    275  1.2.2.2  pgoyette 
    276  1.2.2.2  pgoyette 	if (!omapi_connections) {
    277  1.2.2.2  pgoyette 		status = omapi_connection_array_allocate (&omapi_connections,
    278  1.2.2.2  pgoyette 							  file, line);
    279  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS)
    280  1.2.2.2  pgoyette 			return;
    281  1.2.2.2  pgoyette 	}
    282  1.2.2.2  pgoyette 
    283  1.2.2.2  pgoyette 	status = omapi_connection_array_extend (omapi_connections, obj,
    284  1.2.2.2  pgoyette 						(int *)0, file, line);
    285  1.2.2.2  pgoyette 	if (status != ISC_R_SUCCESS) {
    286  1.2.2.2  pgoyette 		obj -> index = -1;
    287  1.2.2.2  pgoyette 		return;
    288  1.2.2.2  pgoyette 	}
    289  1.2.2.2  pgoyette 
    290  1.2.2.2  pgoyette #if defined (TRACING)
    291  1.2.2.2  pgoyette 	if (trace_record ()) {
    292  1.2.2.2  pgoyette 		/* Connection registration packet:
    293  1.2.2.2  pgoyette 
    294  1.2.2.2  pgoyette 		     int32_t index
    295  1.2.2.2  pgoyette 		     int32_t listener_index [-1 means no listener]
    296  1.2.2.2  pgoyette 		   u_int16_t remote_port
    297  1.2.2.2  pgoyette 		   u_int16_t local_port
    298  1.2.2.2  pgoyette 		   u_int32_t remote_addr
    299  1.2.2.2  pgoyette 		   u_int32_t local_addr */
    300  1.2.2.2  pgoyette 
    301  1.2.2.2  pgoyette 		connect_index = htonl (index);
    302  1.2.2.2  pgoyette 		index++;
    303  1.2.2.2  pgoyette 		if (obj -> listener)
    304  1.2.2.2  pgoyette 			listener_index = htonl (obj -> listener -> index);
    305  1.2.2.2  pgoyette 		else
    306  1.2.2.2  pgoyette 			listener_index = htonl (-1);
    307  1.2.2.2  pgoyette 		iov [iov_count].buf = (char *)&connect_index;
    308  1.2.2.2  pgoyette 		iov [iov_count++].len = sizeof connect_index;
    309  1.2.2.2  pgoyette 		iov [iov_count].buf = (char *)&listener_index;
    310  1.2.2.2  pgoyette 		iov [iov_count++].len = sizeof listener_index;
    311  1.2.2.2  pgoyette 		iov [iov_count].buf = (char *)&obj -> remote_addr.sin_port;
    312  1.2.2.2  pgoyette 		iov [iov_count++].len = sizeof obj -> remote_addr.sin_port;
    313  1.2.2.2  pgoyette 		iov [iov_count].buf = (char *)&obj -> local_addr.sin_port;
    314  1.2.2.2  pgoyette 		iov [iov_count++].len = sizeof obj -> local_addr.sin_port;
    315  1.2.2.2  pgoyette 		iov [iov_count].buf = (char *)&obj -> remote_addr.sin_addr;
    316  1.2.2.2  pgoyette 		iov [iov_count++].len = sizeof obj -> remote_addr.sin_addr;
    317  1.2.2.2  pgoyette 		iov [iov_count].buf = (char *)&obj -> local_addr.sin_addr;
    318  1.2.2.2  pgoyette 		iov [iov_count++].len = sizeof obj -> local_addr.sin_addr;
    319  1.2.2.2  pgoyette 
    320  1.2.2.2  pgoyette 		status = trace_write_packet_iov (trace_connect,
    321  1.2.2.2  pgoyette 						 iov_count, iov, file, line);
    322  1.2.2.2  pgoyette 	}
    323  1.2.2.2  pgoyette #endif
    324  1.2.2.2  pgoyette }
    325  1.2.2.2  pgoyette 
    326  1.2.2.2  pgoyette static void trace_connect_input (trace_type_t *ttype,
    327  1.2.2.2  pgoyette 				 unsigned length, char *buf)
    328  1.2.2.2  pgoyette {
    329  1.2.2.2  pgoyette 	struct sockaddr_in remote, local;
    330  1.2.2.2  pgoyette 	int32_t connect_index, listener_index;
    331  1.2.2.2  pgoyette 	char *s = buf;
    332  1.2.2.2  pgoyette 	omapi_connection_object_t *obj;
    333  1.2.2.2  pgoyette 	isc_result_t status;
    334  1.2.2.2  pgoyette 	int i;
    335  1.2.2.2  pgoyette 
    336  1.2.2.2  pgoyette 	if (length != ((sizeof connect_index) +
    337  1.2.2.2  pgoyette 		       (sizeof remote.sin_port) +
    338  1.2.2.2  pgoyette 		       (sizeof remote.sin_addr)) * 2) {
    339  1.2.2.2  pgoyette 		log_error ("Trace connect: invalid length %d", length);
    340  1.2.2.2  pgoyette 		return;
    341  1.2.2.2  pgoyette 	}
    342  1.2.2.2  pgoyette 
    343  1.2.2.2  pgoyette 	memset (&remote, 0, sizeof remote);
    344  1.2.2.2  pgoyette 	memset (&local, 0, sizeof local);
    345  1.2.2.2  pgoyette 	memcpy (&connect_index, s, sizeof connect_index);
    346  1.2.2.2  pgoyette 	s += sizeof connect_index;
    347  1.2.2.2  pgoyette 	memcpy (&listener_index, s, sizeof listener_index);
    348  1.2.2.2  pgoyette 	s += sizeof listener_index;
    349  1.2.2.2  pgoyette 	memcpy (&remote.sin_port, s, sizeof remote.sin_port);
    350  1.2.2.2  pgoyette 	s += sizeof remote.sin_port;
    351  1.2.2.2  pgoyette 	memcpy (&local.sin_port, s, sizeof local.sin_port);
    352  1.2.2.2  pgoyette 	s += sizeof local.sin_port;
    353  1.2.2.2  pgoyette 	memcpy (&remote.sin_addr, s, sizeof remote.sin_addr);
    354  1.2.2.2  pgoyette 	s += sizeof remote.sin_addr;
    355  1.2.2.2  pgoyette 	memcpy (&local.sin_addr, s, sizeof local.sin_addr);
    356  1.2.2.2  pgoyette 	s += sizeof local.sin_addr;
    357  1.2.2.2  pgoyette 	POST(s);
    358  1.2.2.2  pgoyette 
    359  1.2.2.2  pgoyette 	connect_index = ntohl (connect_index);
    360  1.2.2.2  pgoyette 	listener_index = ntohl (listener_index);
    361  1.2.2.2  pgoyette 
    362  1.2.2.2  pgoyette 	/* If this was a connect to a listener, then we just slap together
    363  1.2.2.2  pgoyette 	   a new connection. */
    364  1.2.2.2  pgoyette 	if (listener_index != -1) {
    365  1.2.2.2  pgoyette 		omapi_listener_object_t *listener;
    366  1.2.2.2  pgoyette 		listener = (omapi_listener_object_t *)0;
    367  1.2.2.2  pgoyette 		omapi_array_foreach_begin (trace_listeners,
    368  1.2.2.2  pgoyette 					   omapi_listener_object_t, lp) {
    369  1.2.2.2  pgoyette 			if (lp -> address.sin_port == local.sin_port) {
    370  1.2.2.2  pgoyette 				omapi_listener_reference (&listener, lp, MDL);
    371  1.2.2.2  pgoyette 				omapi_listener_dereference (&lp, MDL);
    372  1.2.2.2  pgoyette 				break;
    373  1.2.2.2  pgoyette 			}
    374  1.2.2.2  pgoyette 		} omapi_array_foreach_end (trace_listeners,
    375  1.2.2.2  pgoyette 					   omapi_listener_object_t, lp);
    376  1.2.2.2  pgoyette 		if (!listener) {
    377  1.2.2.2  pgoyette 			log_error ("%s%ld, addr %s, port %d",
    378  1.2.2.2  pgoyette 				   "Spurious traced listener connect - index ",
    379  1.2.2.2  pgoyette 				   (long int)listener_index,
    380  1.2.2.2  pgoyette 				   inet_ntoa (local.sin_addr),
    381  1.2.2.2  pgoyette 				   ntohs (local.sin_port));
    382  1.2.2.2  pgoyette 			return;
    383  1.2.2.2  pgoyette 		}
    384  1.2.2.2  pgoyette 		obj = (omapi_connection_object_t *)0;
    385  1.2.2.2  pgoyette 		status = omapi_listener_connect (&obj, listener, -1, &remote);
    386  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS) {
    387  1.2.2.2  pgoyette 			log_error ("traced listener connect: %s",
    388  1.2.2.2  pgoyette 				   isc_result_totext (status));
    389  1.2.2.2  pgoyette 		}
    390  1.2.2.2  pgoyette 		if (obj)
    391  1.2.2.2  pgoyette 			omapi_connection_dereference (&obj, MDL);
    392  1.2.2.2  pgoyette 		omapi_listener_dereference (&listener, MDL);
    393  1.2.2.2  pgoyette 		return;
    394  1.2.2.2  pgoyette 	}
    395  1.2.2.2  pgoyette 
    396  1.2.2.2  pgoyette 	/* Find the matching connect object, if there is one. */
    397  1.2.2.2  pgoyette 	omapi_array_foreach_begin (omapi_connections,
    398  1.2.2.2  pgoyette 				   omapi_connection_object_t, lp) {
    399  1.2.2.2  pgoyette 	    for (i = 0; (lp->connect_list &&
    400  1.2.2.2  pgoyette 			 i < lp->connect_list->count); i++) {
    401  1.2.2.2  pgoyette 		    if (!memcmp (&remote.sin_addr,
    402  1.2.2.2  pgoyette 				 &lp->connect_list->addresses[i].address,
    403  1.2.2.2  pgoyette 				 sizeof remote.sin_addr) &&
    404  1.2.2.2  pgoyette 			(ntohs (remote.sin_port) ==
    405  1.2.2.2  pgoyette 			 lp->connect_list->addresses[i].port)) {
    406  1.2.2.2  pgoyette 			    lp->state = omapi_connection_connected;
    407  1.2.2.2  pgoyette 			    lp->remote_addr = remote;
    408  1.2.2.2  pgoyette 			    lp->remote_addr.sin_family = AF_INET;
    409  1.2.2.2  pgoyette 			    omapi_addr_list_dereference(&lp->connect_list, MDL);
    410  1.2.2.2  pgoyette 			    lp->index = connect_index;
    411  1.2.2.2  pgoyette 			    status = omapi_signal_in((omapi_object_t *)lp,
    412  1.2.2.2  pgoyette 						     "connect");
    413  1.2.2.2  pgoyette 			    omapi_connection_dereference (&lp, MDL);
    414  1.2.2.2  pgoyette 			    return;
    415  1.2.2.2  pgoyette 		    }
    416  1.2.2.2  pgoyette 		}
    417  1.2.2.2  pgoyette 	} omapi_array_foreach_end (omapi_connections,
    418  1.2.2.2  pgoyette 				   omapi_connection_object_t, lp);
    419  1.2.2.2  pgoyette 
    420  1.2.2.2  pgoyette 	log_error ("Spurious traced connect - index %ld, addr %s, port %d",
    421  1.2.2.2  pgoyette 		   (long int)connect_index, inet_ntoa (remote.sin_addr),
    422  1.2.2.2  pgoyette 		   ntohs (remote.sin_port));
    423  1.2.2.2  pgoyette 	return;
    424  1.2.2.2  pgoyette }
    425  1.2.2.2  pgoyette 
    426  1.2.2.2  pgoyette static void trace_connect_stop (trace_type_t *ttype) { }
    427  1.2.2.2  pgoyette 
    428  1.2.2.2  pgoyette static void trace_disconnect_input (trace_type_t *ttype,
    429  1.2.2.2  pgoyette 				    unsigned length, char *buf)
    430  1.2.2.2  pgoyette {
    431  1.2.2.2  pgoyette 	int32_t *index;
    432  1.2.2.2  pgoyette 	if (length != sizeof *index) {
    433  1.2.2.2  pgoyette 		log_error ("trace disconnect: wrong length %d", length);
    434  1.2.2.2  pgoyette 		return;
    435  1.2.2.2  pgoyette 	}
    436  1.2.2.2  pgoyette 
    437  1.2.2.2  pgoyette 	index = (int32_t *)buf;
    438  1.2.2.2  pgoyette 
    439  1.2.2.2  pgoyette 	omapi_array_foreach_begin (omapi_connections,
    440  1.2.2.2  pgoyette 				   omapi_connection_object_t, lp) {
    441  1.2.2.2  pgoyette 		if (lp -> index == ntohl (*index)) {
    442  1.2.2.2  pgoyette 			omapi_disconnect ((omapi_object_t *)lp, 1);
    443  1.2.2.2  pgoyette 			omapi_connection_dereference (&lp, MDL);
    444  1.2.2.2  pgoyette 			return;
    445  1.2.2.2  pgoyette 		}
    446  1.2.2.2  pgoyette 	} omapi_array_foreach_end (omapi_connections,
    447  1.2.2.2  pgoyette 				   omapi_connection_object_t, lp);
    448  1.2.2.2  pgoyette 
    449  1.2.2.2  pgoyette 	log_error ("trace disconnect: no connection matching index %ld",
    450  1.2.2.2  pgoyette 		   (long int)ntohl (*index));
    451  1.2.2.2  pgoyette }
    452  1.2.2.2  pgoyette 
    453  1.2.2.2  pgoyette static void trace_disconnect_stop (trace_type_t *ttype) { }
    454  1.2.2.2  pgoyette #endif
    455  1.2.2.2  pgoyette 
    456  1.2.2.2  pgoyette /* Disconnect a connection object from the remote end.   If force is nonzero,
    457  1.2.2.2  pgoyette    close the connection immediately.   Otherwise, shut down the receiving end
    458  1.2.2.2  pgoyette    but allow any unsent data to be sent before actually closing the socket. */
    459  1.2.2.2  pgoyette 
    460  1.2.2.2  pgoyette isc_result_t omapi_disconnect (omapi_object_t *h,
    461  1.2.2.2  pgoyette 			       int force)
    462  1.2.2.2  pgoyette {
    463  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
    464  1.2.2.2  pgoyette 
    465  1.2.2.2  pgoyette #ifdef DEBUG_PROTOCOL
    466  1.2.2.2  pgoyette 	log_debug ("omapi_disconnect(%s)", force ? "force" : "");
    467  1.2.2.2  pgoyette #endif
    468  1.2.2.2  pgoyette 
    469  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)h;
    470  1.2.2.2  pgoyette 	if (c -> type != omapi_type_connection)
    471  1.2.2.2  pgoyette 		return DHCP_R_INVALIDARG;
    472  1.2.2.2  pgoyette 
    473  1.2.2.2  pgoyette #if defined (TRACING)
    474  1.2.2.2  pgoyette 	if (trace_record ()) {
    475  1.2.2.2  pgoyette 		isc_result_t status;
    476  1.2.2.2  pgoyette 		int32_t index;
    477  1.2.2.2  pgoyette 
    478  1.2.2.2  pgoyette 		index = htonl (c -> index);
    479  1.2.2.2  pgoyette 		status = trace_write_packet (trace_disconnect,
    480  1.2.2.2  pgoyette 					     sizeof index, (char *)&index,
    481  1.2.2.2  pgoyette 					     MDL);
    482  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS) {
    483  1.2.2.2  pgoyette 			trace_stop ();
    484  1.2.2.2  pgoyette 			log_error ("trace_write_packet: %s",
    485  1.2.2.2  pgoyette 				   isc_result_totext (status));
    486  1.2.2.2  pgoyette 		}
    487  1.2.2.2  pgoyette 	}
    488  1.2.2.2  pgoyette 	if (!trace_playback ()) {
    489  1.2.2.2  pgoyette #endif
    490  1.2.2.2  pgoyette 		if (!force) {
    491  1.2.2.2  pgoyette 			/* If we're already disconnecting, we don't have to do
    492  1.2.2.2  pgoyette 			   anything. */
    493  1.2.2.2  pgoyette 			if (c -> state == omapi_connection_disconnecting)
    494  1.2.2.2  pgoyette 				return ISC_R_SUCCESS;
    495  1.2.2.2  pgoyette 
    496  1.2.2.2  pgoyette 			/* Try to shut down the socket - this sends a FIN to
    497  1.2.2.2  pgoyette 			   the remote end, so that it won't send us any more
    498  1.2.2.2  pgoyette 			   data.   If the shutdown succeeds, and we still
    499  1.2.2.2  pgoyette 			   have bytes left to write, defer closing the socket
    500  1.2.2.2  pgoyette 			   until that's done. */
    501  1.2.2.2  pgoyette 			if (!shutdown (c -> socket, SHUT_RD)) {
    502  1.2.2.2  pgoyette 				if (c -> out_bytes > 0) {
    503  1.2.2.2  pgoyette 					c -> state =
    504  1.2.2.2  pgoyette 						omapi_connection_disconnecting;
    505  1.2.2.2  pgoyette 					return ISC_R_SUCCESS;
    506  1.2.2.2  pgoyette 				}
    507  1.2.2.2  pgoyette 			}
    508  1.2.2.2  pgoyette 		}
    509  1.2.2.2  pgoyette 		close (c -> socket);
    510  1.2.2.2  pgoyette #if defined (TRACING)
    511  1.2.2.2  pgoyette 	}
    512  1.2.2.2  pgoyette #endif
    513  1.2.2.2  pgoyette 	c -> state = omapi_connection_closed;
    514  1.2.2.2  pgoyette 
    515  1.2.2.2  pgoyette #if 0
    516  1.2.2.2  pgoyette 	/*
    517  1.2.2.2  pgoyette 	 * Disconnecting from the I/O object seems incorrect as it doesn't
    518  1.2.2.2  pgoyette 	 * cause the I/O object to be cleaned and released.  Previous to
    519  1.2.2.2  pgoyette 	 * using the isc socket library this wouldn't have caused a problem
    520  1.2.2.2  pgoyette 	 * with the socket library we would have a reference to a closed
    521  1.2.2.2  pgoyette 	 * socket.  Instead we now do an unregister to properly free the
    522  1.2.2.2  pgoyette 	 * I/O object.
    523  1.2.2.2  pgoyette 	 */
    524  1.2.2.2  pgoyette 
    525  1.2.2.2  pgoyette 	/* Disconnect from I/O object, if any. */
    526  1.2.2.2  pgoyette 	if (h -> outer) {
    527  1.2.2.2  pgoyette 		if (h -> outer -> inner)
    528  1.2.2.2  pgoyette 			omapi_object_dereference (&h -> outer -> inner, MDL);
    529  1.2.2.2  pgoyette 		omapi_object_dereference (&h -> outer, MDL);
    530  1.2.2.2  pgoyette 	}
    531  1.2.2.2  pgoyette #else
    532  1.2.2.2  pgoyette 	if (h->outer) {
    533  1.2.2.2  pgoyette 		omapi_unregister_io_object(h);
    534  1.2.2.2  pgoyette 	}
    535  1.2.2.2  pgoyette #endif
    536  1.2.2.2  pgoyette 
    537  1.2.2.2  pgoyette 	/* If whatever created us registered a signal handler, send it
    538  1.2.2.2  pgoyette 	   a disconnect signal. */
    539  1.2.2.2  pgoyette 	omapi_signal (h, "disconnect", h);
    540  1.2.2.2  pgoyette 
    541  1.2.2.2  pgoyette 	/* Disconnect from protocol object, if any. */
    542  1.2.2.2  pgoyette 	if (h->inner != NULL) {
    543  1.2.2.2  pgoyette 		if (h->inner->outer != NULL) {
    544  1.2.2.2  pgoyette 			omapi_object_dereference(&h->inner->outer, MDL);
    545  1.2.2.2  pgoyette 		}
    546  1.2.2.2  pgoyette 		omapi_object_dereference(&h->inner, MDL);
    547  1.2.2.2  pgoyette 	}
    548  1.2.2.2  pgoyette 
    549  1.2.2.2  pgoyette 	/* XXX: the code to free buffers should be in the dereference
    550  1.2.2.2  pgoyette 		function, but there is no special-purpose function to
    551  1.2.2.2  pgoyette 		dereference connections, so these just get leaked */
    552  1.2.2.2  pgoyette 	/* Free any buffers */
    553  1.2.2.2  pgoyette 	if (c->inbufs != NULL) {
    554  1.2.2.2  pgoyette 		omapi_buffer_dereference(&c->inbufs, MDL);
    555  1.2.2.2  pgoyette 	}
    556  1.2.2.2  pgoyette 	c->in_bytes = 0;
    557  1.2.2.2  pgoyette 	if (c->outbufs != NULL) {
    558  1.2.2.2  pgoyette 		omapi_buffer_dereference(&c->outbufs, MDL);
    559  1.2.2.2  pgoyette 	}
    560  1.2.2.2  pgoyette 	c->out_bytes = 0;
    561  1.2.2.2  pgoyette 
    562  1.2.2.2  pgoyette 	return ISC_R_SUCCESS;
    563  1.2.2.2  pgoyette }
    564  1.2.2.2  pgoyette 
    565  1.2.2.2  pgoyette isc_result_t omapi_connection_require (omapi_object_t *h, unsigned bytes)
    566  1.2.2.2  pgoyette {
    567  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
    568  1.2.2.2  pgoyette 
    569  1.2.2.2  pgoyette 	if (h -> type != omapi_type_connection)
    570  1.2.2.2  pgoyette 		return DHCP_R_INVALIDARG;
    571  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)h;
    572  1.2.2.2  pgoyette 
    573  1.2.2.2  pgoyette 	c -> bytes_needed = bytes;
    574  1.2.2.2  pgoyette 	if (c -> bytes_needed <= c -> in_bytes) {
    575  1.2.2.2  pgoyette 		return ISC_R_SUCCESS;
    576  1.2.2.2  pgoyette 	}
    577  1.2.2.2  pgoyette 	return DHCP_R_NOTYET;
    578  1.2.2.2  pgoyette }
    579  1.2.2.2  pgoyette 
    580  1.2.2.2  pgoyette /* Return the socket on which the dispatcher should wait for readiness
    581  1.2.2.2  pgoyette    to read, for a connection object.  */
    582  1.2.2.2  pgoyette int omapi_connection_readfd (omapi_object_t *h)
    583  1.2.2.2  pgoyette {
    584  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
    585  1.2.2.2  pgoyette 	if (h -> type != omapi_type_connection)
    586  1.2.2.2  pgoyette 		return -1;
    587  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)h;
    588  1.2.2.2  pgoyette 	if (c -> state != omapi_connection_connected)
    589  1.2.2.2  pgoyette 		return -1;
    590  1.2.2.2  pgoyette 	return c -> socket;
    591  1.2.2.2  pgoyette }
    592  1.2.2.2  pgoyette 
    593  1.2.2.2  pgoyette /*
    594  1.2.2.2  pgoyette  * Return the socket on which the dispatcher should wait for readiness
    595  1.2.2.2  pgoyette  * to write, for a connection object.  When bytes are buffered we should
    596  1.2.2.2  pgoyette  * also poke the dispatcher to tell it to start or re-start watching the
    597  1.2.2.2  pgoyette  * socket.
    598  1.2.2.2  pgoyette  */
    599  1.2.2.2  pgoyette int omapi_connection_writefd (omapi_object_t *h)
    600  1.2.2.2  pgoyette {
    601  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
    602  1.2.2.2  pgoyette 	if (h -> type != omapi_type_connection)
    603  1.2.2.2  pgoyette 		return -1;
    604  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)h;
    605  1.2.2.2  pgoyette 	return c->socket;
    606  1.2.2.2  pgoyette }
    607  1.2.2.2  pgoyette 
    608  1.2.2.2  pgoyette isc_result_t omapi_connection_connect (omapi_object_t *h)
    609  1.2.2.2  pgoyette {
    610  1.2.2.2  pgoyette 	isc_result_t status;
    611  1.2.2.2  pgoyette 
    612  1.2.2.2  pgoyette 	/*
    613  1.2.2.2  pgoyette 	 * We use the INPROGRESS status to indicate that
    614  1.2.2.2  pgoyette 	 * we want more from the socket.  In this case we
    615  1.2.2.2  pgoyette 	 * have now connected and are trying to write to
    616  1.2.2.2  pgoyette 	 * the socket for the first time.  For the signaling
    617  1.2.2.2  pgoyette 	 * code this is the same as a SUCCESS so we don't
    618  1.2.2.2  pgoyette 	 * pass it on as a signal.
    619  1.2.2.2  pgoyette 	 */
    620  1.2.2.2  pgoyette 	status = omapi_connection_connect_internal (h);
    621  1.2.2.2  pgoyette 	if (status == ISC_R_INPROGRESS)
    622  1.2.2.2  pgoyette 		return ISC_R_INPROGRESS;
    623  1.2.2.2  pgoyette 
    624  1.2.2.2  pgoyette 	if (status != ISC_R_SUCCESS)
    625  1.2.2.2  pgoyette 		omapi_signal (h, "status", status);
    626  1.2.2.2  pgoyette 
    627  1.2.2.2  pgoyette 	return ISC_R_SUCCESS;
    628  1.2.2.2  pgoyette }
    629  1.2.2.2  pgoyette 
    630  1.2.2.2  pgoyette static isc_result_t omapi_connection_connect_internal (omapi_object_t *h)
    631  1.2.2.2  pgoyette {
    632  1.2.2.2  pgoyette 	int error = 0;
    633  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
    634  1.2.2.2  pgoyette 	socklen_t sl;
    635  1.2.2.2  pgoyette 	isc_result_t status;
    636  1.2.2.2  pgoyette 
    637  1.2.2.2  pgoyette 	if (h -> type != omapi_type_connection)
    638  1.2.2.2  pgoyette 		return DHCP_R_INVALIDARG;
    639  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)h;
    640  1.2.2.2  pgoyette 
    641  1.2.2.2  pgoyette 	if (c -> state == omapi_connection_connecting) {
    642  1.2.2.2  pgoyette 		sl = sizeof error;
    643  1.2.2.2  pgoyette 		if (getsockopt (c -> socket, SOL_SOCKET, SO_ERROR,
    644  1.2.2.2  pgoyette 				(char *)&error, &sl) < 0) {
    645  1.2.2.2  pgoyette 			omapi_disconnect (h, 1);
    646  1.2.2.2  pgoyette 			return ISC_R_SUCCESS;
    647  1.2.2.2  pgoyette 		}
    648  1.2.2.2  pgoyette 		if (!error)
    649  1.2.2.2  pgoyette 			c -> state = omapi_connection_connected;
    650  1.2.2.2  pgoyette 	}
    651  1.2.2.2  pgoyette 	if (c -> state == omapi_connection_connecting ||
    652  1.2.2.2  pgoyette 	    c -> state == omapi_connection_unconnected) {
    653  1.2.2.2  pgoyette 		if (c -> cptr >= c -> connect_list -> count) {
    654  1.2.2.2  pgoyette 			switch (error) {
    655  1.2.2.2  pgoyette 			      case ECONNREFUSED:
    656  1.2.2.2  pgoyette 				status = ISC_R_CONNREFUSED;
    657  1.2.2.2  pgoyette 				break;
    658  1.2.2.2  pgoyette 			      case ENETUNREACH:
    659  1.2.2.2  pgoyette 				status = ISC_R_NETUNREACH;
    660  1.2.2.2  pgoyette 				break;
    661  1.2.2.2  pgoyette 			      default:
    662  1.2.2.2  pgoyette 				status = uerr2isc (error);
    663  1.2.2.2  pgoyette 				break;
    664  1.2.2.2  pgoyette 			}
    665  1.2.2.2  pgoyette 			omapi_disconnect (h, 1);
    666  1.2.2.2  pgoyette 			return status;
    667  1.2.2.2  pgoyette 		}
    668  1.2.2.2  pgoyette 
    669  1.2.2.2  pgoyette 		if (c -> connect_list -> addresses [c -> cptr].addrtype !=
    670  1.2.2.2  pgoyette 		    AF_INET) {
    671  1.2.2.2  pgoyette 			omapi_disconnect (h, 1);
    672  1.2.2.2  pgoyette 			return DHCP_R_INVALIDARG;
    673  1.2.2.2  pgoyette 		}
    674  1.2.2.2  pgoyette 
    675  1.2.2.2  pgoyette 		memcpy (&c -> remote_addr.sin_addr,
    676  1.2.2.2  pgoyette 			&c -> connect_list -> addresses [c -> cptr].address,
    677  1.2.2.2  pgoyette 			sizeof c -> remote_addr.sin_addr);
    678  1.2.2.2  pgoyette 		c -> remote_addr.sin_family = AF_INET;
    679  1.2.2.2  pgoyette 		c -> remote_addr.sin_port =
    680  1.2.2.2  pgoyette 		       htons (c -> connect_list -> addresses [c -> cptr].port);
    681  1.2.2.2  pgoyette #if defined (HAVE_SA_LEN)
    682  1.2.2.2  pgoyette 		c -> remote_addr.sin_len = sizeof c -> remote_addr;
    683  1.2.2.2  pgoyette #endif
    684  1.2.2.2  pgoyette 		memset (&c -> remote_addr.sin_zero, 0,
    685  1.2.2.2  pgoyette 			sizeof c -> remote_addr.sin_zero);
    686  1.2.2.2  pgoyette 		++c -> cptr;
    687  1.2.2.2  pgoyette 
    688  1.2.2.2  pgoyette 		error = connect (c -> socket,
    689  1.2.2.2  pgoyette 				 (struct sockaddr *)&c -> remote_addr,
    690  1.2.2.2  pgoyette 				 sizeof c -> remote_addr);
    691  1.2.2.2  pgoyette 		if (error < 0) {
    692  1.2.2.2  pgoyette 			error = errno;
    693  1.2.2.2  pgoyette 			if (error != EINPROGRESS) {
    694  1.2.2.2  pgoyette 				omapi_disconnect (h, 1);
    695  1.2.2.2  pgoyette 				switch (error) {
    696  1.2.2.2  pgoyette 				      case ECONNREFUSED:
    697  1.2.2.2  pgoyette 					status = ISC_R_CONNREFUSED;
    698  1.2.2.2  pgoyette 					break;
    699  1.2.2.2  pgoyette 				      case ENETUNREACH:
    700  1.2.2.2  pgoyette 					status = ISC_R_NETUNREACH;
    701  1.2.2.2  pgoyette 					break;
    702  1.2.2.2  pgoyette 				      default:
    703  1.2.2.2  pgoyette 					status = uerr2isc (error);
    704  1.2.2.2  pgoyette 					break;
    705  1.2.2.2  pgoyette 				}
    706  1.2.2.2  pgoyette 				return status;
    707  1.2.2.2  pgoyette 			}
    708  1.2.2.2  pgoyette 			c -> state = omapi_connection_connecting;
    709  1.2.2.2  pgoyette 			return DHCP_R_INCOMPLETE;
    710  1.2.2.2  pgoyette 		}
    711  1.2.2.2  pgoyette 		c -> state = omapi_connection_connected;
    712  1.2.2.2  pgoyette 	}
    713  1.2.2.2  pgoyette 
    714  1.2.2.2  pgoyette 	/* I don't know why this would fail, so I'm tempted not to test
    715  1.2.2.2  pgoyette 	   the return value. */
    716  1.2.2.2  pgoyette 	sl = sizeof (c -> local_addr);
    717  1.2.2.2  pgoyette 	if (getsockname (c -> socket,
    718  1.2.2.2  pgoyette 			 (struct sockaddr *)&c -> local_addr, &sl) < 0) {
    719  1.2.2.2  pgoyette 	}
    720  1.2.2.2  pgoyette 
    721  1.2.2.2  pgoyette 	/* Reregister with the I/O object.  If we don't already have an
    722  1.2.2.2  pgoyette 	   I/O object this turns into a register call, otherwise we simply
    723  1.2.2.2  pgoyette 	   modify the pointers in the I/O object. */
    724  1.2.2.2  pgoyette 
    725  1.2.2.2  pgoyette 	status = omapi_reregister_io_object (h,
    726  1.2.2.2  pgoyette 					     omapi_connection_readfd,
    727  1.2.2.2  pgoyette 					     omapi_connection_writefd,
    728  1.2.2.2  pgoyette 					     omapi_connection_reader,
    729  1.2.2.2  pgoyette 					     omapi_connection_writer,
    730  1.2.2.2  pgoyette 					     omapi_connection_reaper);
    731  1.2.2.2  pgoyette 
    732  1.2.2.2  pgoyette 	if (status != ISC_R_SUCCESS) {
    733  1.2.2.2  pgoyette 		omapi_disconnect (h, 1);
    734  1.2.2.2  pgoyette 		return status;
    735  1.2.2.2  pgoyette 	}
    736  1.2.2.2  pgoyette 
    737  1.2.2.2  pgoyette 	omapi_signal_in (h, "connect");
    738  1.2.2.2  pgoyette 	omapi_addr_list_dereference (&c -> connect_list, MDL);
    739  1.2.2.2  pgoyette 	return ISC_R_INPROGRESS;
    740  1.2.2.2  pgoyette }
    741  1.2.2.2  pgoyette 
    742  1.2.2.2  pgoyette /* Reaper function for connection - if the connection is completely closed,
    743  1.2.2.2  pgoyette    reap it.   If it's in the disconnecting state, there were bytes left
    744  1.2.2.2  pgoyette    to write when the user closed it, so if there are now no bytes left to
    745  1.2.2.2  pgoyette    write, we can close it. */
    746  1.2.2.2  pgoyette isc_result_t omapi_connection_reaper (omapi_object_t *h)
    747  1.2.2.2  pgoyette {
    748  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
    749  1.2.2.2  pgoyette 
    750  1.2.2.2  pgoyette 	if (h -> type != omapi_type_connection)
    751  1.2.2.2  pgoyette 		return DHCP_R_INVALIDARG;
    752  1.2.2.2  pgoyette 
    753  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)h;
    754  1.2.2.2  pgoyette 	if (c -> state == omapi_connection_disconnecting &&
    755  1.2.2.2  pgoyette 	    c -> out_bytes == 0) {
    756  1.2.2.2  pgoyette #ifdef DEBUG_PROTOCOL
    757  1.2.2.2  pgoyette 		log_debug ("omapi_connection_reaper(): disconnect");
    758  1.2.2.2  pgoyette #endif
    759  1.2.2.2  pgoyette 		omapi_disconnect (h, 1);
    760  1.2.2.2  pgoyette 	}
    761  1.2.2.2  pgoyette 	if (c -> state == omapi_connection_closed) {
    762  1.2.2.2  pgoyette #ifdef DEBUG_PROTOCOL
    763  1.2.2.2  pgoyette 		log_debug ("omapi_connection_reaper(): closed");
    764  1.2.2.2  pgoyette #endif
    765  1.2.2.2  pgoyette 		return ISC_R_NOTCONNECTED;
    766  1.2.2.2  pgoyette 	}
    767  1.2.2.2  pgoyette 	return ISC_R_SUCCESS;
    768  1.2.2.2  pgoyette }
    769  1.2.2.2  pgoyette 
    770  1.2.2.2  pgoyette static isc_result_t make_dst_key (dst_key_t **dst_key, omapi_object_t *a) {
    771  1.2.2.2  pgoyette 	omapi_value_t *name      = (omapi_value_t *)0;
    772  1.2.2.2  pgoyette 	omapi_value_t *algorithm = (omapi_value_t *)0;
    773  1.2.2.2  pgoyette 	omapi_value_t *key       = (omapi_value_t *)0;
    774  1.2.2.2  pgoyette 	char *name_str = NULL;
    775  1.2.2.2  pgoyette 	isc_result_t status = ISC_R_SUCCESS;
    776  1.2.2.2  pgoyette 
    777  1.2.2.2  pgoyette 	if (status == ISC_R_SUCCESS)
    778  1.2.2.2  pgoyette 		status = omapi_get_value_str
    779  1.2.2.2  pgoyette 			(a, (omapi_object_t *)0, "name", &name);
    780  1.2.2.2  pgoyette 
    781  1.2.2.2  pgoyette 	if (status == ISC_R_SUCCESS)
    782  1.2.2.2  pgoyette 		status = omapi_get_value_str
    783  1.2.2.2  pgoyette 			(a, (omapi_object_t *)0, "algorithm", &algorithm);
    784  1.2.2.2  pgoyette 
    785  1.2.2.2  pgoyette 	if (status == ISC_R_SUCCESS)
    786  1.2.2.2  pgoyette 		status = omapi_get_value_str
    787  1.2.2.2  pgoyette 			(a, (omapi_object_t *)0, "key", &key);
    788  1.2.2.2  pgoyette 
    789  1.2.2.2  pgoyette 	if (status == ISC_R_SUCCESS) {
    790  1.2.2.2  pgoyette 		if ((algorithm->value->type != omapi_datatype_data &&
    791  1.2.2.2  pgoyette 		     algorithm->value->type != omapi_datatype_string) ||
    792  1.2.2.2  pgoyette 		    strncasecmp((char *)algorithm->value->u.buffer.value,
    793  1.2.2.2  pgoyette 				NS_TSIG_ALG_HMAC_MD5 ".",
    794  1.2.2.2  pgoyette 				algorithm->value->u.buffer.len) != 0) {
    795  1.2.2.2  pgoyette 			status = DHCP_R_INVALIDARG;
    796  1.2.2.2  pgoyette 		}
    797  1.2.2.2  pgoyette 	}
    798  1.2.2.2  pgoyette 
    799  1.2.2.2  pgoyette 	if (status == ISC_R_SUCCESS) {
    800  1.2.2.2  pgoyette 		name_str = dmalloc (name -> value -> u.buffer.len + 1, MDL);
    801  1.2.2.2  pgoyette 		if (!name_str)
    802  1.2.2.2  pgoyette 			status = ISC_R_NOMEMORY;
    803  1.2.2.2  pgoyette 	}
    804  1.2.2.2  pgoyette 
    805  1.2.2.2  pgoyette 	if (status == ISC_R_SUCCESS) {
    806  1.2.2.2  pgoyette 		memcpy (name_str,
    807  1.2.2.2  pgoyette 			name -> value -> u.buffer.value,
    808  1.2.2.2  pgoyette 			name -> value -> u.buffer.len);
    809  1.2.2.2  pgoyette 		name_str [name -> value -> u.buffer.len] = 0;
    810  1.2.2.2  pgoyette 
    811  1.2.2.2  pgoyette 		status = isclib_make_dst_key(name_str,
    812  1.2.2.2  pgoyette 					     DHCP_HMAC_MD5_NAME,
    813  1.2.2.2  pgoyette 					     key->value->u.buffer.value,
    814  1.2.2.2  pgoyette 					     key->value->u.buffer.len,
    815  1.2.2.2  pgoyette 					     dst_key);
    816  1.2.2.2  pgoyette 
    817  1.2.2.2  pgoyette 		if (*dst_key == NULL)
    818  1.2.2.2  pgoyette 			status = ISC_R_NOMEMORY;
    819  1.2.2.2  pgoyette 	}
    820  1.2.2.2  pgoyette 
    821  1.2.2.2  pgoyette 	if (name_str)
    822  1.2.2.2  pgoyette 		dfree (name_str, MDL);
    823  1.2.2.2  pgoyette 	if (key)
    824  1.2.2.2  pgoyette 		omapi_value_dereference (&key, MDL);
    825  1.2.2.2  pgoyette 	if (algorithm)
    826  1.2.2.2  pgoyette 		omapi_value_dereference (&algorithm, MDL);
    827  1.2.2.2  pgoyette 	if (name)
    828  1.2.2.2  pgoyette 		omapi_value_dereference (&name, MDL);
    829  1.2.2.2  pgoyette 
    830  1.2.2.2  pgoyette 	return status;
    831  1.2.2.2  pgoyette }
    832  1.2.2.2  pgoyette 
    833  1.2.2.2  pgoyette isc_result_t omapi_connection_sign_data (int mode,
    834  1.2.2.2  pgoyette 					 dst_key_t *key,
    835  1.2.2.2  pgoyette 					 void **context,
    836  1.2.2.2  pgoyette 					 const unsigned char *data,
    837  1.2.2.2  pgoyette 					 const unsigned len,
    838  1.2.2.2  pgoyette 					 omapi_typed_data_t **result)
    839  1.2.2.2  pgoyette {
    840  1.2.2.2  pgoyette 	omapi_typed_data_t *td = (omapi_typed_data_t *)0;
    841  1.2.2.2  pgoyette 	isc_result_t status;
    842  1.2.2.2  pgoyette 	dst_context_t **dctx = (dst_context_t **)context;
    843  1.2.2.2  pgoyette 
    844  1.2.2.2  pgoyette 	/* Create the context for the dst module */
    845  1.2.2.2  pgoyette 	if (mode & SIG_MODE_INIT) {
    846  1.2.2.2  pgoyette 		status = dst_context_create(key, dhcp_gbl_ctx.mctx, dctx);
    847  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS) {
    848  1.2.2.2  pgoyette 			return status;
    849  1.2.2.2  pgoyette 		}
    850  1.2.2.2  pgoyette 	}
    851  1.2.2.2  pgoyette 
    852  1.2.2.2  pgoyette 	/* If we have any data add it to the context */
    853  1.2.2.2  pgoyette 	if (len != 0) {
    854  1.2.2.2  pgoyette 		isc_region_t region;
    855  1.2.2.2  pgoyette 		region.base   = (unsigned char *)data;
    856  1.2.2.2  pgoyette 		region.length = len;
    857  1.2.2.2  pgoyette 		dst_context_adddata(*dctx, &region);
    858  1.2.2.2  pgoyette 	}
    859  1.2.2.2  pgoyette 
    860  1.2.2.2  pgoyette 	/* Finish the signature and clean up the context */
    861  1.2.2.2  pgoyette 	if (mode & SIG_MODE_FINAL) {
    862  1.2.2.2  pgoyette 		unsigned int sigsize;
    863  1.2.2.2  pgoyette 		isc_buffer_t sigbuf;
    864  1.2.2.2  pgoyette 
    865  1.2.2.2  pgoyette 		status = dst_key_sigsize(key, &sigsize);
    866  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS) {
    867  1.2.2.2  pgoyette 			goto cleanup;
    868  1.2.2.2  pgoyette 		}
    869  1.2.2.2  pgoyette 
    870  1.2.2.2  pgoyette 		status = omapi_typed_data_new (MDL, &td,
    871  1.2.2.2  pgoyette 					       omapi_datatype_data,
    872  1.2.2.2  pgoyette 					       sigsize);
    873  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS) {
    874  1.2.2.2  pgoyette 			goto cleanup;
    875  1.2.2.2  pgoyette 		}
    876  1.2.2.2  pgoyette 
    877  1.2.2.2  pgoyette 		isc_buffer_init(&sigbuf, td->u.buffer.value, td->u.buffer.len);
    878  1.2.2.2  pgoyette 		status = dst_context_sign(*dctx, &sigbuf);
    879  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS) {
    880  1.2.2.2  pgoyette 			goto cleanup;
    881  1.2.2.2  pgoyette 		}
    882  1.2.2.2  pgoyette 
    883  1.2.2.2  pgoyette 		if (result) {
    884  1.2.2.2  pgoyette 			omapi_typed_data_reference (result, td, MDL);
    885  1.2.2.2  pgoyette 		}
    886  1.2.2.2  pgoyette 
    887  1.2.2.2  pgoyette 	cleanup:
    888  1.2.2.2  pgoyette 		/* We are done with the context and the td.  On success
    889  1.2.2.2  pgoyette 		 * the td is now referenced from result, on failure we
    890  1.2.2.2  pgoyette 		 * don't need it any more */
    891  1.2.2.2  pgoyette 		if (td) {
    892  1.2.2.2  pgoyette 			omapi_typed_data_dereference (&td, MDL);
    893  1.2.2.2  pgoyette 		}
    894  1.2.2.2  pgoyette 		dst_context_destroy(dctx);
    895  1.2.2.2  pgoyette 		return status;
    896  1.2.2.2  pgoyette 	}
    897  1.2.2.2  pgoyette 
    898  1.2.2.2  pgoyette 	return ISC_R_SUCCESS;
    899  1.2.2.2  pgoyette }
    900  1.2.2.2  pgoyette 
    901  1.2.2.2  pgoyette isc_result_t omapi_connection_output_auth_length (omapi_object_t *h,
    902  1.2.2.2  pgoyette 						  unsigned *l)
    903  1.2.2.2  pgoyette {
    904  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
    905  1.2.2.2  pgoyette 
    906  1.2.2.2  pgoyette 	if (h->type != omapi_type_connection)
    907  1.2.2.2  pgoyette 		return DHCP_R_INVALIDARG;
    908  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)h;
    909  1.2.2.2  pgoyette 
    910  1.2.2.2  pgoyette 	if (c->out_key == NULL)
    911  1.2.2.2  pgoyette 		return ISC_R_NOTFOUND;
    912  1.2.2.2  pgoyette 
    913  1.2.2.2  pgoyette 	return(dst_key_sigsize(c->out_key, l));
    914  1.2.2.2  pgoyette }
    915  1.2.2.2  pgoyette 
    916  1.2.2.2  pgoyette isc_result_t omapi_connection_set_value (omapi_object_t *h,
    917  1.2.2.2  pgoyette 					 omapi_object_t *id,
    918  1.2.2.2  pgoyette 					 omapi_data_string_t *name,
    919  1.2.2.2  pgoyette 					 omapi_typed_data_t *value)
    920  1.2.2.2  pgoyette {
    921  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
    922  1.2.2.2  pgoyette 	isc_result_t status;
    923  1.2.2.2  pgoyette 
    924  1.2.2.2  pgoyette 	if (h -> type != omapi_type_connection)
    925  1.2.2.2  pgoyette 		return DHCP_R_INVALIDARG;
    926  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)h;
    927  1.2.2.2  pgoyette 
    928  1.2.2.2  pgoyette 	if (omapi_ds_strcmp (name, "input-authenticator") == 0) {
    929  1.2.2.2  pgoyette 		if (value && value -> type != omapi_datatype_object)
    930  1.2.2.2  pgoyette 			return DHCP_R_INVALIDARG;
    931  1.2.2.2  pgoyette 
    932  1.2.2.2  pgoyette 		if (c -> in_context) {
    933  1.2.2.2  pgoyette 			omapi_connection_sign_data (SIG_MODE_FINAL,
    934  1.2.2.2  pgoyette 						    c -> in_key,
    935  1.2.2.2  pgoyette 						    &c -> in_context,
    936  1.2.2.2  pgoyette 						    0, 0,
    937  1.2.2.2  pgoyette 						    (omapi_typed_data_t **) 0);
    938  1.2.2.2  pgoyette 		}
    939  1.2.2.2  pgoyette 
    940  1.2.2.2  pgoyette 		if (c->in_key != NULL) {
    941  1.2.2.2  pgoyette 			dst_key_free(&c->in_key);
    942  1.2.2.2  pgoyette 		}
    943  1.2.2.2  pgoyette 
    944  1.2.2.2  pgoyette 		if (value) {
    945  1.2.2.2  pgoyette 			status = make_dst_key (&c -> in_key,
    946  1.2.2.2  pgoyette 					       value -> u.object);
    947  1.2.2.2  pgoyette 			if (status != ISC_R_SUCCESS)
    948  1.2.2.2  pgoyette 				return status;
    949  1.2.2.2  pgoyette 		}
    950  1.2.2.2  pgoyette 
    951  1.2.2.2  pgoyette 		return ISC_R_SUCCESS;
    952  1.2.2.2  pgoyette 	}
    953  1.2.2.2  pgoyette 	else if (omapi_ds_strcmp (name, "output-authenticator") == 0) {
    954  1.2.2.2  pgoyette 		if (value && value -> type != omapi_datatype_object)
    955  1.2.2.2  pgoyette 			return DHCP_R_INVALIDARG;
    956  1.2.2.2  pgoyette 
    957  1.2.2.2  pgoyette 		if (c -> out_context) {
    958  1.2.2.2  pgoyette 			omapi_connection_sign_data (SIG_MODE_FINAL,
    959  1.2.2.2  pgoyette 						    c -> out_key,
    960  1.2.2.2  pgoyette 						    &c -> out_context,
    961  1.2.2.2  pgoyette 						    0, 0,
    962  1.2.2.2  pgoyette 						    (omapi_typed_data_t **) 0);
    963  1.2.2.2  pgoyette 		}
    964  1.2.2.2  pgoyette 
    965  1.2.2.2  pgoyette 		if (c->out_key != NULL) {
    966  1.2.2.2  pgoyette 			dst_key_free(&c->out_key);
    967  1.2.2.2  pgoyette 		}
    968  1.2.2.2  pgoyette 
    969  1.2.2.2  pgoyette 		if (value) {
    970  1.2.2.2  pgoyette 			status = make_dst_key (&c -> out_key,
    971  1.2.2.2  pgoyette 					       value -> u.object);
    972  1.2.2.2  pgoyette 			if (status != ISC_R_SUCCESS)
    973  1.2.2.2  pgoyette 				return status;
    974  1.2.2.2  pgoyette 		}
    975  1.2.2.2  pgoyette 
    976  1.2.2.2  pgoyette 		return ISC_R_SUCCESS;
    977  1.2.2.2  pgoyette 	}
    978  1.2.2.2  pgoyette 
    979  1.2.2.2  pgoyette 	if (h -> inner && h -> inner -> type -> set_value)
    980  1.2.2.2  pgoyette 		return (*(h -> inner -> type -> set_value))
    981  1.2.2.2  pgoyette 			(h -> inner, id, name, value);
    982  1.2.2.2  pgoyette 	return ISC_R_NOTFOUND;
    983  1.2.2.2  pgoyette }
    984  1.2.2.2  pgoyette 
    985  1.2.2.2  pgoyette isc_result_t omapi_connection_get_value (omapi_object_t *h,
    986  1.2.2.2  pgoyette 					 omapi_object_t *id,
    987  1.2.2.2  pgoyette 					 omapi_data_string_t *name,
    988  1.2.2.2  pgoyette 					 omapi_value_t **value)
    989  1.2.2.2  pgoyette {
    990  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
    991  1.2.2.2  pgoyette 	omapi_typed_data_t *td = (omapi_typed_data_t *)0;
    992  1.2.2.2  pgoyette 	isc_result_t status;
    993  1.2.2.2  pgoyette 	unsigned int sigsize;
    994  1.2.2.2  pgoyette 
    995  1.2.2.2  pgoyette 	if (h -> type != omapi_type_connection)
    996  1.2.2.2  pgoyette 		return DHCP_R_INVALIDARG;
    997  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)h;
    998  1.2.2.2  pgoyette 
    999  1.2.2.2  pgoyette 	if (omapi_ds_strcmp (name, "input-signature") == 0) {
   1000  1.2.2.2  pgoyette 		if (!c -> in_key || !c -> in_context)
   1001  1.2.2.2  pgoyette 			return ISC_R_NOTFOUND;
   1002  1.2.2.2  pgoyette 
   1003  1.2.2.2  pgoyette 		status = omapi_connection_sign_data (SIG_MODE_FINAL,
   1004  1.2.2.2  pgoyette 						     c -> in_key,
   1005  1.2.2.2  pgoyette 						     &c -> in_context,
   1006  1.2.2.2  pgoyette 						     0, 0, &td);
   1007  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS)
   1008  1.2.2.2  pgoyette 			return status;
   1009  1.2.2.2  pgoyette 
   1010  1.2.2.2  pgoyette 		status = omapi_make_value (value, name, td, MDL);
   1011  1.2.2.2  pgoyette 		omapi_typed_data_dereference (&td, MDL);
   1012  1.2.2.2  pgoyette 		return status;
   1013  1.2.2.2  pgoyette 
   1014  1.2.2.2  pgoyette 	} else if (omapi_ds_strcmp (name, "input-signature-size") == 0) {
   1015  1.2.2.2  pgoyette 		if (c->in_key == NULL)
   1016  1.2.2.2  pgoyette 			return ISC_R_NOTFOUND;
   1017  1.2.2.2  pgoyette 
   1018  1.2.2.2  pgoyette 		status = dst_key_sigsize(c->in_key, &sigsize);
   1019  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS) {
   1020  1.2.2.2  pgoyette 			return(status);
   1021  1.2.2.2  pgoyette 		}
   1022  1.2.2.2  pgoyette 
   1023  1.2.2.2  pgoyette 		return omapi_make_int_value(value, name, sigsize, MDL);
   1024  1.2.2.2  pgoyette 
   1025  1.2.2.2  pgoyette 	} else if (omapi_ds_strcmp (name, "output-signature") == 0) {
   1026  1.2.2.2  pgoyette 		if (!c -> out_key || !c -> out_context)
   1027  1.2.2.2  pgoyette 			return ISC_R_NOTFOUND;
   1028  1.2.2.2  pgoyette 
   1029  1.2.2.2  pgoyette 		status = omapi_connection_sign_data (SIG_MODE_FINAL,
   1030  1.2.2.2  pgoyette 						     c -> out_key,
   1031  1.2.2.2  pgoyette 						     &c -> out_context,
   1032  1.2.2.2  pgoyette 						     0, 0, &td);
   1033  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS)
   1034  1.2.2.2  pgoyette 			return status;
   1035  1.2.2.2  pgoyette 
   1036  1.2.2.2  pgoyette 		status = omapi_make_value (value, name, td, MDL);
   1037  1.2.2.2  pgoyette 		omapi_typed_data_dereference (&td, MDL);
   1038  1.2.2.2  pgoyette 		return status;
   1039  1.2.2.2  pgoyette 
   1040  1.2.2.2  pgoyette 	} else if (omapi_ds_strcmp (name, "output-signature-size") == 0) {
   1041  1.2.2.2  pgoyette 		if (c->out_key == NULL)
   1042  1.2.2.2  pgoyette 			return ISC_R_NOTFOUND;
   1043  1.2.2.2  pgoyette 
   1044  1.2.2.2  pgoyette 
   1045  1.2.2.2  pgoyette 		status = dst_key_sigsize(c->out_key, &sigsize);
   1046  1.2.2.2  pgoyette 		if (status != ISC_R_SUCCESS) {
   1047  1.2.2.2  pgoyette 			return(status);
   1048  1.2.2.2  pgoyette 		}
   1049  1.2.2.2  pgoyette 
   1050  1.2.2.2  pgoyette 		return omapi_make_int_value(value, name, sigsize, MDL);
   1051  1.2.2.2  pgoyette 	}
   1052  1.2.2.2  pgoyette 
   1053  1.2.2.2  pgoyette 	if (h -> inner && h -> inner -> type -> get_value)
   1054  1.2.2.2  pgoyette 		return (*(h -> inner -> type -> get_value))
   1055  1.2.2.2  pgoyette 			(h -> inner, id, name, value);
   1056  1.2.2.2  pgoyette 	return ISC_R_NOTFOUND;
   1057  1.2.2.2  pgoyette }
   1058  1.2.2.2  pgoyette 
   1059  1.2.2.2  pgoyette isc_result_t omapi_connection_destroy (omapi_object_t *h,
   1060  1.2.2.2  pgoyette 				       const char *file, int line)
   1061  1.2.2.2  pgoyette {
   1062  1.2.2.2  pgoyette 	omapi_connection_object_t *c;
   1063  1.2.2.2  pgoyette 
   1064  1.2.2.2  pgoyette #ifdef DEBUG_PROTOCOL
   1065  1.2.2.2  pgoyette 	log_debug ("omapi_connection_destroy()");
   1066  1.2.2.2  pgoyette #endif
   1067  1.2.2.2  pgoyette 
   1068  1.2.2.2  pgoyette 	if (h -> type != omapi_type_connection)
   1069  1.2.2.2  pgoyette 		return ISC_R_UNEXPECTED;
   1070  1.2.2.2  pgoyette 	c = (omapi_connection_object_t *)(h);
   1071  1.2.2.2  pgoyette 	if (c -> state == omapi_connection_connected)
   1072  1.2.2.2  pgoyette 		omapi_disconnect (h, 1);
   1073  1.2.2.2  pgoyette 	if (c -> listener)
   1074  1.2.2.2  pgoyette 		omapi_listener_dereference (&c -> listener, file, line);
   1075  1.2.2.2  pgoyette 	if (c -> connect_list)
   1076  1.2.2.2  pgoyette 		omapi_addr_list_dereference (&c -> connect_list, file, line);
   1077  1.2.2.2  pgoyette 	return ISC_R_SUCCESS;
   1078  1.2.2.2  pgoyette }
   1079  1.2.2.2  pgoyette 
   1080  1.2.2.2  pgoyette isc_result_t omapi_connection_signal_handler (omapi_object_t *h,
   1081  1.2.2.2  pgoyette 					      const char *name, va_list ap)
   1082  1.2.2.2  pgoyette {
   1083  1.2.2.2  pgoyette 	if (h -> type != omapi_type_connection)
   1084  1.2.2.2  pgoyette 		return DHCP_R_INVALIDARG;
   1085  1.2.2.2  pgoyette 
   1086  1.2.2.2  pgoyette #ifdef DEBUG_PROTOCOL
   1087  1.2.2.2  pgoyette 	log_debug ("omapi_connection_signal_handler(%s)", name);
   1088  1.2.2.2  pgoyette #endif
   1089  1.2.2.2  pgoyette 
   1090  1.2.2.2  pgoyette 	if (h -> inner && h -> inner -> type -> signal_handler)
   1091  1.2.2.2  pgoyette 		return (*(h -> inner -> type -> signal_handler)) (h -> inner,
   1092  1.2.2.2  pgoyette 								  name, ap);
   1093  1.2.2.2  pgoyette 	return ISC_R_NOTFOUND;
   1094  1.2.2.2  pgoyette }
   1095  1.2.2.2  pgoyette 
   1096  1.2.2.2  pgoyette /* Write all the published values associated with the object through the
   1097  1.2.2.2  pgoyette    specified connection. */
   1098  1.2.2.2  pgoyette 
   1099  1.2.2.2  pgoyette isc_result_t omapi_connection_stuff_values (omapi_object_t *c,
   1100  1.2.2.2  pgoyette 					    omapi_object_t *id,
   1101  1.2.2.2  pgoyette 					    omapi_object_t *m)
   1102  1.2.2.2  pgoyette {
   1103  1.2.2.2  pgoyette 	if (m -> type != omapi_type_connection)
   1104  1.2.2.2  pgoyette 		return DHCP_R_INVALIDARG;
   1105  1.2.2.2  pgoyette 
   1106  1.2.2.2  pgoyette 	if (m -> inner && m -> inner -> type -> stuff_values)
   1107  1.2.2.2  pgoyette 		return (*(m -> inner -> type -> stuff_values)) (c, id,
   1108  1.2.2.2  pgoyette 								m -> inner);
   1109  1.2.2.2  pgoyette 	return ISC_R_SUCCESS;
   1110  1.2.2.2  pgoyette }
   1111