3 Subroutines for dealing with connections. */
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1999-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #include <omapip/omapip_p.h>
36 #include <arpa/inet.h>
37 #include <arpa/nameser.h>
41 static void trace_connect_input (trace_type_t *, unsigned, char *);
42 static void trace_connect_stop (trace_type_t *);
43 static void trace_disconnect_input (trace_type_t *, unsigned, char *);
44 static void trace_disconnect_stop (trace_type_t *);
45 trace_type_t *trace_connect;
46 trace_type_t *trace_disconnect;
47 extern omapi_array_t *trace_listeners;
49 static isc_result_t omapi_connection_connect_internal (omapi_object_t *);
51 OMAPI_OBJECT_ALLOC (omapi_connection,
52 omapi_connection_object_t, omapi_type_connection)
54 isc_result_t omapi_connect (omapi_object_t *c,
55 const char *server_name,
60 omapi_addr_list_t *addrs = (omapi_addr_list_t *)0;
65 log_debug ("omapi_connect(%s, port=%d)", server_name, port);
68 if (!inet_aton (server_name, &foo)) {
69 /* If we didn't get a numeric address, try for a domain
70 name. It's okay for this call to block. */
71 he = gethostbyname (server_name);
73 return ISC_R_HOSTUNKNOWN;
74 for (i = 0; he -> h_addr_list [i]; i++)
77 return ISC_R_HOSTUNKNOWN;
80 status = omapi_addr_list_new (&addrs, hix, MDL);
81 if (status != ISC_R_SUCCESS)
83 for (i = 0; i < hix; i++) {
84 addrs -> addresses [i].addrtype = he -> h_addrtype;
85 addrs -> addresses [i].addrlen = he -> h_length;
86 memcpy (addrs -> addresses [i].address,
87 he -> h_addr_list [i],
88 (unsigned)he -> h_length);
89 addrs -> addresses [i].port = port;
92 status = omapi_addr_list_new (&addrs, 1, MDL);
93 if (status != ISC_R_SUCCESS)
95 addrs -> addresses [0].addrtype = AF_INET;
96 addrs -> addresses [0].addrlen = sizeof foo;
97 memcpy (addrs -> addresses [0].address, &foo, sizeof foo);
98 addrs -> addresses [0].port = port;
101 status = omapi_connect_list (c, addrs, (omapi_addr_t *)0);
102 omapi_addr_list_dereference (&addrs, MDL);
106 isc_result_t omapi_connect_list (omapi_object_t *c,
107 omapi_addr_list_t *remote_addrs,
108 omapi_addr_t *local_addr)
111 omapi_connection_object_t *obj;
113 struct sockaddr_in local_sin;
114 #if defined (TRACING)
119 obj = (omapi_connection_object_t *)0;
120 status = omapi_connection_allocate (&obj, MDL);
121 if (status != ISC_R_SUCCESS)
124 status = omapi_object_reference (&c -> outer, (omapi_object_t *)obj,
126 if (status != ISC_R_SUCCESS) {
127 omapi_connection_dereference (&obj, MDL);
130 status = omapi_object_reference (&obj -> inner, c, MDL);
131 if (status != ISC_R_SUCCESS) {
132 omapi_connection_dereference (&obj, MDL);
136 /* Store the address list on the object. */
137 omapi_addr_list_reference (&obj -> connect_list, remote_addrs, MDL);
139 obj -> state = omapi_connection_unconnected;
141 #if defined (TRACING)
142 /* If we're playing back, don't actually try to connect - just leave
143 the object available for a subsequent connect or disconnect. */
144 if (!trace_playback ()) {
146 /* Create a socket on which to communicate. */
148 socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
149 if (obj -> socket < 0) {
150 omapi_connection_dereference (&obj, MDL);
151 if (errno == EMFILE || errno == ENFILE
153 return ISC_R_NORESOURCES;
154 return ISC_R_UNEXPECTED;
157 /* Set up the local address, if any. */
159 /* Only do TCPv4 so far. */
160 if (local_addr -> addrtype != AF_INET) {
161 omapi_connection_dereference (&obj, MDL);
162 return ISC_R_INVALIDARG;
164 local_sin.sin_port = htons (local_addr -> port);
165 memcpy (&local_sin.sin_addr,
166 local_addr -> address,
167 local_addr -> addrlen);
168 #if defined (HAVE_SA_LEN)
169 local_sin.sin_len = sizeof local_addr;
171 local_sin.sin_family = AF_INET;
172 memset (&local_sin.sin_zero, 0,
173 sizeof local_sin.sin_zero);
175 if (bind (obj -> socket, (struct sockaddr *)&local_sin,
176 sizeof local_sin) < 0) {
177 omapi_object_dereference ((omapi_object_t **)
179 if (errno == EADDRINUSE)
180 return ISC_R_ADDRINUSE;
181 if (errno == EADDRNOTAVAIL)
182 return ISC_R_ADDRNOTAVAIL;
185 return ISC_R_UNEXPECTED;
187 obj -> local_addr = local_sin;
190 #if defined (HAVE_SETFD)
191 if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
192 close (obj -> socket);
193 omapi_connection_dereference (&obj, MDL);
194 return ISC_R_UNEXPECTED;
198 /* Set the SO_REUSEADDR flag (this should not fail). */
200 if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
201 (char *)&flag, sizeof flag) < 0) {
202 omapi_connection_dereference (&obj, MDL);
203 return ISC_R_UNEXPECTED;
206 /* Set the file to nonblocking mode. */
207 if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
208 omapi_connection_dereference (&obj, MDL);
209 return ISC_R_UNEXPECTED;
212 status = (omapi_register_io_object
213 ((omapi_object_t *)obj,
214 0, omapi_connection_writefd,
215 0, omapi_connection_connect,
216 omapi_connection_reaper));
217 if (status != ISC_R_SUCCESS)
219 status = omapi_connection_connect_internal ((omapi_object_t *)
221 #if defined (TRACING)
223 omapi_connection_register (obj, MDL);
227 omapi_connection_dereference (&obj, MDL);
231 #if defined (TRACING)
232 omapi_array_t *omapi_connections;
234 OMAPI_ARRAY_TYPE(omapi_connection, omapi_connection_object_t)
236 void omapi_connection_trace_setup (void) {
237 trace_connect = trace_type_register ("connect", (void *)0,
239 trace_connect_stop, MDL);
240 trace_disconnect = trace_type_register ("disconnect", (void *)0,
241 trace_disconnect_input,
242 trace_disconnect_stop, MDL);
245 void omapi_connection_register (omapi_connection_object_t *obj,
246 const char *file, int line)
251 int32_t connect_index, listener_index;
252 static int32_t index;
254 if (!omapi_connections) {
255 status = omapi_connection_array_allocate (&omapi_connections,
257 if (status != ISC_R_SUCCESS)
261 status = omapi_connection_array_extend (omapi_connections, obj,
262 (int *)0, file, line);
263 if (status != ISC_R_SUCCESS) {
268 #if defined (TRACING)
269 if (trace_record ()) {
270 /* Connection registration packet:
273 int32_t listener_index [-1 means no listener]
274 u_int16_t remote_port
276 u_int32_t remote_addr
277 u_int32_t local_addr */
279 connect_index = htonl (index);
282 listener_index = htonl (obj -> listener -> index);
284 listener_index = htonl (-1);
285 iov [iov_count].buf = (char *)&connect_index;
286 iov [iov_count++].len = sizeof connect_index;
287 iov [iov_count].buf = (char *)&listener_index;
288 iov [iov_count++].len = sizeof listener_index;
289 iov [iov_count].buf = (char *)&obj -> remote_addr.sin_port;
290 iov [iov_count++].len = sizeof obj -> remote_addr.sin_port;
291 iov [iov_count].buf = (char *)&obj -> local_addr.sin_port;
292 iov [iov_count++].len = sizeof obj -> local_addr.sin_port;
293 iov [iov_count].buf = (char *)&obj -> remote_addr.sin_addr;
294 iov [iov_count++].len = sizeof obj -> remote_addr.sin_addr;
295 iov [iov_count].buf = (char *)&obj -> local_addr.sin_addr;
296 iov [iov_count++].len = sizeof obj -> local_addr.sin_addr;
298 status = trace_write_packet_iov (trace_connect,
299 iov_count, iov, file, line);
304 static void trace_connect_input (trace_type_t *ttype,
305 unsigned length, char *buf)
307 struct sockaddr_in remote, local;
308 int32_t connect_index, listener_index;
310 omapi_connection_object_t *obj;
314 if (length != ((sizeof connect_index) +
315 (sizeof remote.sin_port) +
316 (sizeof remote.sin_addr)) * 2) {
317 log_error ("Trace connect: invalid length %d", length);
321 memset (&remote, 0, sizeof remote);
322 memset (&local, 0, sizeof local);
323 memcpy (&connect_index, s, sizeof connect_index);
324 s += sizeof connect_index;
325 memcpy (&listener_index, s, sizeof listener_index);
326 s += sizeof listener_index;
327 memcpy (&remote.sin_port, s, sizeof remote.sin_port);
328 s += sizeof remote.sin_port;
329 memcpy (&local.sin_port, s, sizeof local.sin_port);
330 s += sizeof local.sin_port;
331 memcpy (&remote.sin_addr, s, sizeof remote.sin_addr);
332 s += sizeof remote.sin_addr;
333 memcpy (&local.sin_addr, s, sizeof local.sin_addr);
334 s += sizeof local.sin_addr;
336 connect_index = ntohl (connect_index);
337 listener_index = ntohl (listener_index);
339 /* If this was a connect to a listener, then we just slap together
341 if (listener_index != -1) {
342 omapi_listener_object_t *listener;
343 listener = (omapi_listener_object_t *)0;
344 omapi_array_foreach_begin (trace_listeners,
345 omapi_listener_object_t, lp) {
346 if (lp -> address.sin_port == local.sin_port) {
347 omapi_listener_reference (&listener, lp, MDL);
348 omapi_listener_dereference (&lp, MDL);
351 } omapi_array_foreach_end (trace_listeners,
352 omapi_listener_object_t, lp);
354 log_error ("%s%ld, addr %s, port %d",
355 "Spurious traced listener connect - index ",
356 (long int)listener_index,
357 inet_ntoa (local.sin_addr),
358 ntohs (local.sin_port));
361 obj = (omapi_connection_object_t *)0;
362 status = omapi_listener_connect (&obj, listener, -1, &remote);
363 if (status != ISC_R_SUCCESS) {
364 log_error ("traced listener connect: %s",
365 isc_result_totext (status));
368 omapi_connection_dereference (&obj, MDL);
369 omapi_listener_dereference (&listener, MDL);
373 /* Find the matching connect object, if there is one. */
374 omapi_array_foreach_begin (omapi_connections,
375 omapi_connection_object_t, lp) {
376 for (i = 0; (lp -> connect_list &&
377 i < lp -> connect_list -> count); i++) {
378 if (!memcmp (&remote.sin_addr,
379 &lp -> connect_list -> addresses [i].address,
380 sizeof remote.sin_addr) &&
381 (ntohs (remote.sin_port) ==
382 lp -> connect_list -> addresses [i].port))
383 lp -> state = omapi_connection_connected;
384 lp -> remote_addr = remote;
385 lp -> remote_addr.sin_family = AF_INET;
386 #if defined (HAVE_SIN_LEN)
387 lp -> remote_addr.sin_len = sizeof remote;
389 omapi_addr_list_dereference (&lp -> connect_list, MDL);
390 lp -> index = connect_index;
391 status = omapi_signal_in ((omapi_object_t *)lp,
393 omapi_connection_dereference (&lp, MDL);
396 } omapi_array_foreach_end (omapi_connections,
397 omapi_connection_object_t, lp);
399 log_error ("Spurious traced connect - index %ld, addr %s, port %d",
400 (long int)connect_index, inet_ntoa (remote.sin_addr),
401 ntohs (remote.sin_port));
405 static void trace_connect_stop (trace_type_t *ttype) { }
407 static void trace_disconnect_input (trace_type_t *ttype,
408 unsigned length, char *buf)
411 if (length != sizeof *index) {
412 log_error ("trace disconnect: wrong length %d", length);
416 index = (int32_t *)buf;
418 omapi_array_foreach_begin (omapi_connections,
419 omapi_connection_object_t, lp) {
420 if (lp -> index == ntohl (*index)) {
421 omapi_disconnect ((omapi_object_t *)lp, 1);
422 omapi_connection_dereference (&lp, MDL);
425 } omapi_array_foreach_end (omapi_connections,
426 omapi_connection_object_t, lp);
428 log_error ("trace disconnect: no connection matching index %ld",
429 (long int)ntohl (*index));
432 static void trace_disconnect_stop (trace_type_t *ttype) { }
435 /* Disconnect a connection object from the remote end. If force is nonzero,
436 close the connection immediately. Otherwise, shut down the receiving end
437 but allow any unsent data to be sent before actually closing the socket. */
439 isc_result_t omapi_disconnect (omapi_object_t *h,
442 omapi_connection_object_t *c;
445 #ifdef DEBUG_PROTOCOL
446 log_debug ("omapi_disconnect(%s)", force ? "force" : "");
449 c = (omapi_connection_object_t *)h;
450 if (c -> type != omapi_type_connection)
451 return ISC_R_INVALIDARG;
453 #if defined (TRACING)
454 if (trace_record ()) {
457 index = htonl (c -> index);
458 status = trace_write_packet (trace_disconnect,
459 sizeof index, (char *)&index,
461 if (status != ISC_R_SUCCESS) {
463 log_error ("trace_write_packet: %s",
464 isc_result_totext (status));
467 if (!trace_playback ()) {
470 /* If we're already disconnecting, we don't have to do
472 if (c -> state == omapi_connection_disconnecting)
473 return ISC_R_SUCCESS;
475 /* Try to shut down the socket - this sends a FIN to
476 the remote end, so that it won't send us any more
477 data. If the shutdown succeeds, and we still
478 have bytes left to write, defer closing the socket
479 until that's done. */
480 if (!shutdown (c -> socket, SHUT_RD)) {
481 if (c -> out_bytes > 0) {
483 omapi_connection_disconnecting;
484 return ISC_R_SUCCESS;
489 #if defined (TRACING)
492 c -> state = omapi_connection_closed;
494 /* Disconnect from I/O object, if any. */
496 if (h -> outer -> inner)
497 omapi_object_dereference (&h -> outer -> inner, MDL);
498 omapi_object_dereference (&h -> outer, MDL);
501 /* If whatever created us registered a signal handler, send it
502 a disconnect signal. */
503 omapi_signal (h, "disconnect", h);
504 return ISC_R_SUCCESS;
507 isc_result_t omapi_connection_require (omapi_object_t *h, unsigned bytes)
509 omapi_connection_object_t *c;
511 if (h -> type != omapi_type_connection)
512 return ISC_R_INVALIDARG;
513 c = (omapi_connection_object_t *)h;
515 c -> bytes_needed = bytes;
516 if (c -> bytes_needed <= c -> in_bytes) {
517 return ISC_R_SUCCESS;
522 /* Return the socket on which the dispatcher should wait for readiness
523 to read, for a connection object. If we already have more bytes than
524 we need to do the next thing, and we have at least a single full input
525 buffer, then don't indicate that we're ready to read. */
526 int omapi_connection_readfd (omapi_object_t *h)
528 omapi_connection_object_t *c;
529 if (h -> type != omapi_type_connection)
531 c = (omapi_connection_object_t *)h;
532 if (c -> state != omapi_connection_connected)
534 if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
535 c -> in_bytes > c -> bytes_needed)
540 /* Return the socket on which the dispatcher should wait for readiness
541 to write, for a connection object. If there are no bytes buffered
542 for writing, then don't indicate that we're ready to write. */
543 int omapi_connection_writefd (omapi_object_t *h)
545 omapi_connection_object_t *c;
546 if (h -> type != omapi_type_connection)
548 c = (omapi_connection_object_t *)h;
549 if (c -> state == omapi_connection_connecting)
557 isc_result_t omapi_connection_connect (omapi_object_t *h)
561 status = omapi_connection_connect_internal (h);
562 if (status != ISC_R_SUCCESS)
563 omapi_signal (h, "status", status);
564 return ISC_R_SUCCESS;
567 static isc_result_t omapi_connection_connect_internal (omapi_object_t *h)
570 omapi_connection_object_t *c;
574 if (h -> type != omapi_type_connection)
575 return ISC_R_INVALIDARG;
576 c = (omapi_connection_object_t *)h;
578 if (c -> state == omapi_connection_connecting) {
580 if (getsockopt (c -> socket, SOL_SOCKET, SO_ERROR,
581 (char *)&error, &sl) < 0) {
582 omapi_disconnect (h, 1);
583 return ISC_R_SUCCESS;
586 c -> state = omapi_connection_connected;
588 if (c -> state == omapi_connection_connecting ||
589 c -> state == omapi_connection_unconnected) {
590 if (c -> cptr >= c -> connect_list -> count) {
593 status = ISC_R_CONNREFUSED;
596 status = ISC_R_NETUNREACH;
599 status = uerr2isc (error);
602 omapi_disconnect (h, 1);
606 if (c -> connect_list -> addresses [c -> cptr].addrtype !=
608 omapi_disconnect (h, 1);
609 return ISC_R_INVALIDARG;
612 memcpy (&c -> remote_addr.sin_addr,
613 &c -> connect_list -> addresses [c -> cptr].address,
614 sizeof c -> remote_addr.sin_addr);
615 c -> remote_addr.sin_family = AF_INET;
616 c -> remote_addr.sin_port =
617 htons (c -> connect_list -> addresses [c -> cptr].port);
618 #if defined (HAVE_SA_LEN)
619 c -> remote_addr.sin_len = sizeof c -> remote_addr;
621 memset (&c -> remote_addr.sin_zero, 0,
622 sizeof c -> remote_addr.sin_zero);
625 error = connect (c -> socket,
626 (struct sockaddr *)&c -> remote_addr,
627 sizeof c -> remote_addr);
630 if (error != EINPROGRESS) {
631 omapi_disconnect (h, 1);
634 status = ISC_R_CONNREFUSED;
637 status = ISC_R_NETUNREACH;
640 status = uerr2isc (error);
645 c -> state = omapi_connection_connecting;
646 return ISC_R_INCOMPLETE;
648 c -> state = omapi_connection_connected;
651 /* I don't know why this would fail, so I'm tempted not to test
653 sl = sizeof (c -> local_addr);
654 if (getsockname (c -> socket,
655 (struct sockaddr *)&c -> local_addr, &sl) < 0) {
658 /* Disconnect from I/O object, if any. */
660 omapi_unregister_io_object (h);
662 status = omapi_register_io_object (h,
663 omapi_connection_readfd,
664 omapi_connection_writefd,
665 omapi_connection_reader,
666 omapi_connection_writer,
667 omapi_connection_reaper);
669 if (status != ISC_R_SUCCESS) {
670 omapi_disconnect (h, 1);
674 omapi_signal_in (h, "connect");
675 omapi_addr_list_dereference (&c -> connect_list, MDL);
676 return ISC_R_SUCCESS;
679 /* Reaper function for connection - if the connection is completely closed,
680 reap it. If it's in the disconnecting state, there were bytes left
681 to write when the user closed it, so if there are now no bytes left to
682 write, we can close it. */
683 isc_result_t omapi_connection_reaper (omapi_object_t *h)
685 omapi_connection_object_t *c;
687 if (h -> type != omapi_type_connection)
688 return ISC_R_INVALIDARG;
690 c = (omapi_connection_object_t *)h;
691 if (c -> state == omapi_connection_disconnecting &&
692 c -> out_bytes == 0) {
693 #ifdef DEBUG_PROTOCOL
694 log_debug ("omapi_connection_reaper(): disconnect");
696 omapi_disconnect (h, 1);
698 if (c -> state == omapi_connection_closed) {
699 #ifdef DEBUG_PROTOCOL
700 log_debug ("omapi_connection_reaper(): closed");
702 return ISC_R_NOTCONNECTED;
704 return ISC_R_SUCCESS;
707 static isc_result_t make_dst_key (DST_KEY **dst_key, omapi_object_t *a) {
708 omapi_value_t *name = (omapi_value_t *)0;
709 omapi_value_t *algorithm = (omapi_value_t *)0;
710 omapi_value_t *key = (omapi_value_t *)0;
711 int algorithm_id = UNKNOWN_KEYALG;
712 char *name_str = NULL;
713 isc_result_t status = ISC_R_SUCCESS;
715 if (status == ISC_R_SUCCESS)
716 status = omapi_get_value_str
717 (a, (omapi_object_t *)0, "name", &name);
719 if (status == ISC_R_SUCCESS)
720 status = omapi_get_value_str
721 (a, (omapi_object_t *)0, "algorithm", &algorithm);
723 if (status == ISC_R_SUCCESS)
724 status = omapi_get_value_str
725 (a, (omapi_object_t *)0, "key", &key);
727 if (status == ISC_R_SUCCESS) {
728 if ((algorithm -> value -> type == omapi_datatype_data ||
729 algorithm -> value -> type == omapi_datatype_string) &&
730 strncasecmp ((char *)algorithm -> value -> u.buffer.value,
731 NS_TSIG_ALG_HMAC_MD5 ".",
732 algorithm -> value -> u.buffer.len) == 0) {
733 algorithm_id = KEY_HMAC_MD5;
735 status = ISC_R_INVALIDARG;
739 if (status == ISC_R_SUCCESS) {
740 name_str = dmalloc (name -> value -> u.buffer.len + 1, MDL);
742 status = ISC_R_NOMEMORY;
745 if (status == ISC_R_SUCCESS) {
747 name -> value -> u.buffer.value,
748 name -> value -> u.buffer.len);
749 name_str [name -> value -> u.buffer.len] = 0;
751 *dst_key = dst_buffer_to_key (name_str, algorithm_id, 0, 0,
752 key -> value -> u.buffer.value,
753 key -> value -> u.buffer.len);
755 status = ISC_R_NOMEMORY;
759 dfree (name_str, MDL);
761 omapi_value_dereference (&key, MDL);
763 omapi_value_dereference (&algorithm, MDL);
765 omapi_value_dereference (&name, MDL);
770 isc_result_t omapi_connection_sign_data (int mode,
773 const unsigned char *data,
775 omapi_typed_data_t **result)
777 omapi_typed_data_t *td = (omapi_typed_data_t *)0;
781 if (mode & SIG_MODE_FINAL) {
782 status = omapi_typed_data_new (MDL, &td,
785 if (status != ISC_R_SUCCESS)
789 r = dst_sign_data (mode, key, context, data, len,
790 td ? td -> u.buffer.value : (u_char *)0,
791 td ? td -> u.buffer.len : 0);
793 /* dst_sign_data() really should do this for us, shouldn't it? */
794 if (mode & SIG_MODE_FINAL)
795 *context = (void *)0;
799 omapi_typed_data_dereference (&td, MDL);
800 return ISC_R_INVALIDKEY;
804 omapi_typed_data_reference (result, td, MDL);
808 omapi_typed_data_dereference (&td, MDL);
810 return ISC_R_SUCCESS;
813 isc_result_t omapi_connection_output_auth_length (omapi_object_t *h,
816 omapi_connection_object_t *c;
818 if (h -> type != omapi_type_connection)
819 return ISC_R_INVALIDARG;
820 c = (omapi_connection_object_t *)h;
823 return ISC_R_NOTFOUND;
825 *l = dst_sig_size (c -> out_key);
826 return ISC_R_SUCCESS;
829 isc_result_t omapi_connection_set_value (omapi_object_t *h,
831 omapi_data_string_t *name,
832 omapi_typed_data_t *value)
834 omapi_connection_object_t *c;
837 if (h -> type != omapi_type_connection)
838 return ISC_R_INVALIDARG;
839 c = (omapi_connection_object_t *)h;
841 if (omapi_ds_strcmp (name, "input-authenticator") == 0) {
842 if (value && value -> type != omapi_datatype_object)
843 return ISC_R_INVALIDARG;
845 if (c -> in_context) {
846 omapi_connection_sign_data (SIG_MODE_FINAL,
850 (omapi_typed_data_t **) 0);
854 dst_free_key (c -> in_key);
855 c -> in_key = (DST_KEY *)0;
859 status = make_dst_key (&c -> in_key,
861 if (status != ISC_R_SUCCESS)
865 return ISC_R_SUCCESS;
867 else if (omapi_ds_strcmp (name, "output-authenticator") == 0) {
868 if (value && value -> type != omapi_datatype_object)
869 return ISC_R_INVALIDARG;
871 if (c -> out_context) {
872 omapi_connection_sign_data (SIG_MODE_FINAL,
876 (omapi_typed_data_t **) 0);
880 dst_free_key (c -> out_key);
881 c -> out_key = (DST_KEY *)0;
885 status = make_dst_key (&c -> out_key,
887 if (status != ISC_R_SUCCESS)
891 return ISC_R_SUCCESS;
894 if (h -> inner && h -> inner -> type -> set_value)
895 return (*(h -> inner -> type -> set_value))
896 (h -> inner, id, name, value);
897 return ISC_R_NOTFOUND;
900 isc_result_t omapi_connection_get_value (omapi_object_t *h,
902 omapi_data_string_t *name,
903 omapi_value_t **value)
905 omapi_connection_object_t *c;
906 omapi_typed_data_t *td = (omapi_typed_data_t *)0;
909 if (h -> type != omapi_type_connection)
910 return ISC_R_INVALIDARG;
911 c = (omapi_connection_object_t *)h;
913 if (omapi_ds_strcmp (name, "input-signature") == 0) {
914 if (!c -> in_key || !c -> in_context)
915 return ISC_R_NOTFOUND;
917 status = omapi_connection_sign_data (SIG_MODE_FINAL,
921 if (status != ISC_R_SUCCESS)
924 status = omapi_make_value (value, name, td, MDL);
925 omapi_typed_data_dereference (&td, MDL);
928 } else if (omapi_ds_strcmp (name, "input-signature-size") == 0) {
930 return ISC_R_NOTFOUND;
932 return omapi_make_int_value (value, name,
933 dst_sig_size (c -> in_key), MDL);
935 } else if (omapi_ds_strcmp (name, "output-signature") == 0) {
936 if (!c -> out_key || !c -> out_context)
937 return ISC_R_NOTFOUND;
939 status = omapi_connection_sign_data (SIG_MODE_FINAL,
943 if (status != ISC_R_SUCCESS)
946 status = omapi_make_value (value, name, td, MDL);
947 omapi_typed_data_dereference (&td, MDL);
950 } else if (omapi_ds_strcmp (name, "output-signature-size") == 0) {
952 return ISC_R_NOTFOUND;
954 return omapi_make_int_value (value, name,
955 dst_sig_size (c -> out_key), MDL);
958 if (h -> inner && h -> inner -> type -> get_value)
959 return (*(h -> inner -> type -> get_value))
960 (h -> inner, id, name, value);
961 return ISC_R_NOTFOUND;
964 isc_result_t omapi_connection_destroy (omapi_object_t *h,
965 const char *file, int line)
967 omapi_connection_object_t *c;
969 #ifdef DEBUG_PROTOCOL
970 log_debug ("omapi_connection_destroy()");
973 if (h -> type != omapi_type_connection)
974 return ISC_R_UNEXPECTED;
975 c = (omapi_connection_object_t *)(h);
976 if (c -> state == omapi_connection_connected)
977 omapi_disconnect (h, 1);
979 omapi_listener_dereference (&c -> listener, file, line);
980 if (c -> connect_list)
981 omapi_addr_list_dereference (&c -> connect_list, file, line);
982 return ISC_R_SUCCESS;
985 isc_result_t omapi_connection_signal_handler (omapi_object_t *h,
986 const char *name, va_list ap)
988 if (h -> type != omapi_type_connection)
989 return ISC_R_INVALIDARG;
991 #ifdef DEBUG_PROTOCOL
992 log_debug ("omapi_connection_signal_handler(%s)", name);
995 if (h -> inner && h -> inner -> type -> signal_handler)
996 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
998 return ISC_R_NOTFOUND;
1001 /* Write all the published values associated with the object through the
1002 specified connection. */
1004 isc_result_t omapi_connection_stuff_values (omapi_object_t *c,
1010 if (m -> type != omapi_type_connection)
1011 return ISC_R_INVALIDARG;
1013 if (m -> inner && m -> inner -> type -> stuff_values)
1014 return (*(m -> inner -> type -> stuff_values)) (c, id,
1016 return ISC_R_SUCCESS;