3 Subroutines for dealing with connections. */
6 * Copyright (c) 1999-2001 Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
44 #include <omapip/omapip_p.h>
45 #include <arpa/inet.h>
46 #include <arpa/nameser.h>
50 static void trace_connect_input (trace_type_t *, unsigned, char *);
51 static void trace_connect_stop (trace_type_t *);
52 static void trace_disconnect_input (trace_type_t *, unsigned, char *);
53 static void trace_disconnect_stop (trace_type_t *);
54 trace_type_t *trace_connect;
55 trace_type_t *trace_disconnect;
56 extern omapi_array_t *trace_listeners;
58 static isc_result_t omapi_connection_connect_internal (omapi_object_t *);
60 OMAPI_OBJECT_ALLOC (omapi_connection,
61 omapi_connection_object_t, omapi_type_connection)
63 isc_result_t omapi_connect (omapi_object_t *c,
64 const char *server_name,
69 omapi_addr_list_t *addrs = (omapi_addr_list_t *)0;
74 log_debug ("omapi_connect(%s, port=%d)", server_name, port);
77 if (!inet_aton (server_name, &foo)) {
78 /* If we didn't get a numeric address, try for a domain
79 name. It's okay for this call to block. */
80 he = gethostbyname (server_name);
82 return ISC_R_HOSTUNKNOWN;
83 for (i = 0; he -> h_addr_list [i]; i++)
86 return ISC_R_HOSTUNKNOWN;
89 status = omapi_addr_list_new (&addrs, hix, MDL);
90 if (status != ISC_R_SUCCESS)
92 for (i = 0; i < hix; i++) {
93 addrs -> addresses [i].addrtype = he -> h_addrtype;
94 addrs -> addresses [i].addrlen = he -> h_length;
95 memcpy (addrs -> addresses [i].address,
96 he -> h_addr_list [i],
97 (unsigned)he -> h_length);
98 addrs -> addresses [i].port = port;
101 status = omapi_addr_list_new (&addrs, 1, MDL);
102 if (status != ISC_R_SUCCESS)
104 addrs -> addresses [0].addrtype = AF_INET;
105 addrs -> addresses [0].addrlen = sizeof foo;
106 memcpy (addrs -> addresses [0].address, &foo, sizeof foo);
107 addrs -> addresses [0].port = port;
110 status = omapi_connect_list (c, addrs, (omapi_addr_t *)0);
111 omapi_addr_list_dereference (&addrs, MDL);
115 isc_result_t omapi_connect_list (omapi_object_t *c,
116 omapi_addr_list_t *remote_addrs,
117 omapi_addr_t *local_addr)
120 omapi_connection_object_t *obj;
122 struct sockaddr_in local_sin;
123 #if defined (TRACING)
128 obj = (omapi_connection_object_t *)0;
129 status = omapi_connection_allocate (&obj, MDL);
130 if (status != ISC_R_SUCCESS)
133 status = omapi_object_reference (&c -> outer, (omapi_object_t *)obj,
135 if (status != ISC_R_SUCCESS) {
136 omapi_connection_dereference (&obj, MDL);
139 status = omapi_object_reference (&obj -> inner, c, MDL);
140 if (status != ISC_R_SUCCESS) {
141 omapi_connection_dereference (&obj, MDL);
145 /* Store the address list on the object. */
146 omapi_addr_list_reference (&obj -> connect_list, remote_addrs, MDL);
148 obj -> state = omapi_connection_unconnected;
150 #if defined (TRACING)
151 /* If we're playing back, don't actually try to connect - just leave
152 the object available for a subsequent connect or disconnect. */
153 if (!trace_playback ()) {
155 /* Create a socket on which to communicate. */
157 socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
158 if (obj -> socket < 0) {
159 omapi_connection_dereference (&obj, MDL);
160 if (errno == EMFILE || errno == ENFILE
162 return ISC_R_NORESOURCES;
163 return ISC_R_UNEXPECTED;
166 /* Set up the local address, if any. */
168 /* Only do TCPv4 so far. */
169 if (local_addr -> addrtype != AF_INET) {
170 omapi_connection_dereference (&obj, MDL);
171 return ISC_R_INVALIDARG;
173 local_sin.sin_port = htons (local_addr -> port);
174 memcpy (&local_sin.sin_addr,
175 local_addr -> address,
176 local_addr -> addrlen);
177 #if defined (HAVE_SA_LEN)
178 local_sin.sin_len = sizeof local_addr;
180 local_sin.sin_family = AF_INET;
181 memset (&local_sin.sin_zero, 0,
182 sizeof local_sin.sin_zero);
184 if (bind (obj -> socket, (struct sockaddr *)&local_sin,
185 sizeof local_sin) < 0) {
186 omapi_object_dereference ((omapi_object_t **)
188 if (errno == EADDRINUSE)
189 return ISC_R_ADDRINUSE;
190 if (errno == EADDRNOTAVAIL)
191 return ISC_R_ADDRNOTAVAIL;
194 return ISC_R_UNEXPECTED;
196 obj -> local_addr = local_sin;
199 #if defined (HAVE_SETFD)
200 if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
201 close (obj -> socket);
202 omapi_connection_dereference (&obj, MDL);
203 return ISC_R_UNEXPECTED;
207 /* Set the SO_REUSEADDR flag (this should not fail). */
209 if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
210 (char *)&flag, sizeof flag) < 0) {
211 omapi_connection_dereference (&obj, MDL);
212 return ISC_R_UNEXPECTED;
215 /* Set the file to nonblocking mode. */
216 if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
217 omapi_connection_dereference (&obj, MDL);
218 return ISC_R_UNEXPECTED;
221 status = (omapi_register_io_object
222 ((omapi_object_t *)obj,
223 0, omapi_connection_writefd,
224 0, omapi_connection_connect,
225 omapi_connection_reaper));
226 if (status != ISC_R_SUCCESS)
228 status = omapi_connection_connect_internal ((omapi_object_t *)
230 #if defined (TRACING)
232 omapi_connection_register (obj, MDL);
236 omapi_connection_dereference (&obj, MDL);
240 #if defined (TRACING)
241 omapi_array_t *omapi_connections;
243 OMAPI_ARRAY_TYPE(omapi_connection, omapi_connection_object_t)
245 void omapi_connection_trace_setup (void) {
246 trace_connect = trace_type_register ("connect", (void *)0,
248 trace_connect_stop, MDL);
249 trace_disconnect = trace_type_register ("disconnect", (void *)0,
250 trace_disconnect_input,
251 trace_disconnect_stop, MDL);
254 void omapi_connection_register (omapi_connection_object_t *obj,
255 const char *file, int line)
260 int32_t connect_index, listener_index;
261 static int32_t index;
263 if (!omapi_connections) {
264 status = omapi_connection_array_allocate (&omapi_connections,
266 if (status != ISC_R_SUCCESS)
270 status = omapi_connection_array_extend (omapi_connections, obj,
271 (int *)0, file, line);
272 if (status != ISC_R_SUCCESS) {
277 #if defined (TRACING)
278 if (trace_record ()) {
279 /* Connection registration packet:
282 int32_t listener_index [-1 means no listener]
283 u_int16_t remote_port
285 u_int32_t remote_addr
286 u_int32_t local_addr */
288 connect_index = htonl (index);
291 listener_index = htonl (obj -> listener -> index);
293 listener_index = htonl (-1);
294 iov [iov_count].buf = (char *)&connect_index;
295 iov [iov_count++].len = sizeof connect_index;
296 iov [iov_count].buf = (char *)&listener_index;
297 iov [iov_count++].len = sizeof listener_index;
298 iov [iov_count].buf = (char *)&obj -> remote_addr.sin_port;
299 iov [iov_count++].len = sizeof obj -> remote_addr.sin_port;
300 iov [iov_count].buf = (char *)&obj -> local_addr.sin_port;
301 iov [iov_count++].len = sizeof obj -> local_addr.sin_port;
302 iov [iov_count].buf = (char *)&obj -> remote_addr.sin_addr;
303 iov [iov_count++].len = sizeof obj -> remote_addr.sin_addr;
304 iov [iov_count].buf = (char *)&obj -> local_addr.sin_addr;
305 iov [iov_count++].len = sizeof obj -> local_addr.sin_addr;
307 status = trace_write_packet_iov (trace_connect,
308 iov_count, iov, file, line);
313 static void trace_connect_input (trace_type_t *ttype,
314 unsigned length, char *buf)
316 struct sockaddr_in remote, local;
317 int32_t connect_index, listener_index;
319 omapi_connection_object_t *obj;
323 if (length != ((sizeof connect_index) +
324 (sizeof remote.sin_port) +
325 (sizeof remote.sin_addr)) * 2) {
326 log_error ("Trace connect: invalid length %d", length);
330 memset (&remote, 0, sizeof remote);
331 memset (&local, 0, sizeof local);
332 memcpy (&connect_index, s, sizeof connect_index);
333 s += sizeof connect_index;
334 memcpy (&listener_index, s, sizeof listener_index);
335 s += sizeof listener_index;
336 memcpy (&remote.sin_port, s, sizeof remote.sin_port);
337 s += sizeof remote.sin_port;
338 memcpy (&local.sin_port, s, sizeof local.sin_port);
339 s += sizeof local.sin_port;
340 memcpy (&remote.sin_addr, s, sizeof remote.sin_addr);
341 s += sizeof remote.sin_addr;
342 memcpy (&local.sin_addr, s, sizeof local.sin_addr);
343 s += sizeof local.sin_addr;
345 connect_index = ntohl (connect_index);
346 listener_index = ntohl (listener_index);
348 /* If this was a connect to a listener, then we just slap together
350 if (listener_index != -1) {
351 omapi_listener_object_t *listener;
352 listener = (omapi_listener_object_t *)0;
353 omapi_array_foreach_begin (trace_listeners,
354 omapi_listener_object_t, lp) {
355 if (lp -> address.sin_port == local.sin_port) {
356 omapi_listener_reference (&listener, lp, MDL);
357 omapi_listener_dereference (&lp, MDL);
360 } omapi_array_foreach_end (trace_listeners,
361 omapi_listener_object_t, lp);
363 log_error ("%s%ld, addr %s, port %d",
364 "Spurious traced listener connect - index ",
365 (long int)listener_index,
366 inet_ntoa (local.sin_addr),
367 ntohs (local.sin_port));
370 obj = (omapi_connection_object_t *)0;
371 status = omapi_listener_connect (&obj, listener, -1, &remote);
372 if (status != ISC_R_SUCCESS) {
373 log_error ("traced listener connect: %s",
374 isc_result_totext (status));
377 omapi_connection_dereference (&obj, MDL);
378 omapi_listener_dereference (&listener, MDL);
382 /* Find the matching connect object, if there is one. */
383 omapi_array_foreach_begin (omapi_connections,
384 omapi_connection_object_t, lp) {
385 for (i = 0; (lp -> connect_list &&
386 i < lp -> connect_list -> count); i++) {
387 if (!memcmp (&remote.sin_addr,
388 &lp -> connect_list -> addresses [i].address,
389 sizeof remote.sin_addr) &&
390 (ntohs (remote.sin_port) ==
391 lp -> connect_list -> addresses [i].port))
392 lp -> state = omapi_connection_connected;
393 lp -> remote_addr = remote;
394 lp -> remote_addr.sin_family = AF_INET;
395 #if defined (HAVE_SIN_LEN)
396 lp -> remote_addr.sin_len = sizeof remote;
398 omapi_addr_list_dereference (&lp -> connect_list, MDL);
399 lp -> index = connect_index;
400 status = omapi_signal_in ((omapi_object_t *)lp,
402 omapi_connection_dereference (&lp, MDL);
405 } omapi_array_foreach_end (omapi_connections,
406 omapi_connection_object_t, lp);
408 log_error ("Spurious traced connect - index %ld, addr %s, port %d",
409 (long int)connect_index, inet_ntoa (remote.sin_addr),
410 ntohs (remote.sin_port));
414 static void trace_connect_stop (trace_type_t *ttype) { }
416 static void trace_disconnect_input (trace_type_t *ttype,
417 unsigned length, char *buf)
420 if (length != sizeof *index) {
421 log_error ("trace disconnect: wrong length %d", length);
425 index = (int32_t *)buf;
427 omapi_array_foreach_begin (omapi_connections,
428 omapi_connection_object_t, lp) {
429 if (lp -> index == ntohl (*index)) {
430 omapi_disconnect ((omapi_object_t *)lp, 1);
431 omapi_connection_dereference (&lp, MDL);
434 } omapi_array_foreach_end (omapi_connections,
435 omapi_connection_object_t, lp);
437 log_error ("trace disconnect: no connection matching index %ld",
438 (long int)ntohl (*index));
441 static void trace_disconnect_stop (trace_type_t *ttype) { }
444 /* Disconnect a connection object from the remote end. If force is nonzero,
445 close the connection immediately. Otherwise, shut down the receiving end
446 but allow any unsent data to be sent before actually closing the socket. */
448 isc_result_t omapi_disconnect (omapi_object_t *h,
451 omapi_connection_object_t *c;
454 #ifdef DEBUG_PROTOCOL
455 log_debug ("omapi_disconnect(%s)", force ? "force" : "");
458 c = (omapi_connection_object_t *)h;
459 if (c -> type != omapi_type_connection)
460 return ISC_R_INVALIDARG;
462 #if defined (TRACING)
463 if (trace_record ()) {
466 index = htonl (c -> index);
467 status = trace_write_packet (trace_disconnect,
468 sizeof index, (char *)&index,
470 if (status != ISC_R_SUCCESS) {
472 log_error ("trace_write_packet: %s",
473 isc_result_totext (status));
476 if (!trace_playback ()) {
479 /* If we're already disconnecting, we don't have to do
481 if (c -> state == omapi_connection_disconnecting)
482 return ISC_R_SUCCESS;
484 /* Try to shut down the socket - this sends a FIN to
485 the remote end, so that it won't send us any more
486 data. If the shutdown succeeds, and we still
487 have bytes left to write, defer closing the socket
488 until that's done. */
489 if (!shutdown (c -> socket, SHUT_RD)) {
490 if (c -> out_bytes > 0) {
492 omapi_connection_disconnecting;
493 return ISC_R_SUCCESS;
498 #if defined (TRACING)
501 c -> state = omapi_connection_closed;
503 /* Disconnect from I/O object, if any. */
505 if (h -> outer -> inner)
506 omapi_object_dereference (&h -> outer -> inner, MDL);
507 omapi_object_dereference (&h -> outer, MDL);
510 /* If whatever created us registered a signal handler, send it
511 a disconnect signal. */
512 omapi_signal (h, "disconnect", h);
513 return ISC_R_SUCCESS;
516 isc_result_t omapi_connection_require (omapi_object_t *h, unsigned bytes)
518 omapi_connection_object_t *c;
520 if (h -> type != omapi_type_connection)
521 return ISC_R_INVALIDARG;
522 c = (omapi_connection_object_t *)h;
524 c -> bytes_needed = bytes;
525 if (c -> bytes_needed <= c -> in_bytes) {
526 return ISC_R_SUCCESS;
531 /* Return the socket on which the dispatcher should wait for readiness
532 to read, for a connection object. If we already have more bytes than
533 we need to do the next thing, and we have at least a single full input
534 buffer, then don't indicate that we're ready to read. */
535 int omapi_connection_readfd (omapi_object_t *h)
537 omapi_connection_object_t *c;
538 if (h -> type != omapi_type_connection)
540 c = (omapi_connection_object_t *)h;
541 if (c -> state != omapi_connection_connected)
543 if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
544 c -> in_bytes > c -> bytes_needed)
549 /* Return the socket on which the dispatcher should wait for readiness
550 to write, for a connection object. If there are no bytes buffered
551 for writing, then don't indicate that we're ready to write. */
552 int omapi_connection_writefd (omapi_object_t *h)
554 omapi_connection_object_t *c;
555 if (h -> type != omapi_type_connection)
557 c = (omapi_connection_object_t *)h;
558 if (c -> state == omapi_connection_connecting)
566 isc_result_t omapi_connection_connect (omapi_object_t *h)
570 status = omapi_connection_connect_internal (h);
571 if (status != ISC_R_SUCCESS)
572 omapi_signal (h, "status", status);
573 return ISC_R_SUCCESS;
576 static isc_result_t omapi_connection_connect_internal (omapi_object_t *h)
579 omapi_connection_object_t *c;
583 if (h -> type != omapi_type_connection)
584 return ISC_R_INVALIDARG;
585 c = (omapi_connection_object_t *)h;
587 if (c -> state == omapi_connection_connecting) {
589 if (getsockopt (c -> socket, SOL_SOCKET, SO_ERROR,
590 (char *)&error, &sl) < 0) {
591 omapi_disconnect (h, 1);
592 return ISC_R_SUCCESS;
595 c -> state = omapi_connection_connected;
597 if (c -> state == omapi_connection_connecting ||
598 c -> state == omapi_connection_unconnected) {
599 if (c -> cptr >= c -> connect_list -> count) {
602 status = ISC_R_CONNREFUSED;
605 status = ISC_R_NETUNREACH;
608 status = uerr2isc (error);
611 omapi_disconnect (h, 1);
615 if (c -> connect_list -> addresses [c -> cptr].addrtype !=
617 omapi_disconnect (h, 1);
618 return ISC_R_INVALIDARG;
621 memcpy (&c -> remote_addr.sin_addr,
622 &c -> connect_list -> addresses [c -> cptr].address,
623 sizeof c -> remote_addr.sin_addr);
624 c -> remote_addr.sin_family = AF_INET;
625 c -> remote_addr.sin_port =
626 htons (c -> connect_list -> addresses [c -> cptr].port);
627 #if defined (HAVE_SA_LEN)
628 c -> remote_addr.sin_len = sizeof c -> remote_addr;
630 memset (&c -> remote_addr.sin_zero, 0,
631 sizeof c -> remote_addr.sin_zero);
634 error = connect (c -> socket,
635 (struct sockaddr *)&c -> remote_addr,
636 sizeof c -> remote_addr);
639 if (error != EINPROGRESS) {
640 omapi_disconnect (h, 1);
643 status = ISC_R_CONNREFUSED;
646 status = ISC_R_NETUNREACH;
649 status = uerr2isc (error);
654 c -> state = omapi_connection_connecting;
655 return ISC_R_INCOMPLETE;
657 c -> state = omapi_connection_connected;
660 /* I don't know why this would fail, so I'm tempted not to test
662 sl = sizeof (c -> local_addr);
663 if (getsockname (c -> socket,
664 (struct sockaddr *)&c -> local_addr, &sl) < 0) {
667 /* Disconnect from I/O object, if any. */
669 omapi_unregister_io_object (h);
671 status = omapi_register_io_object (h,
672 omapi_connection_readfd,
673 omapi_connection_writefd,
674 omapi_connection_reader,
675 omapi_connection_writer,
676 omapi_connection_reaper);
678 if (status != ISC_R_SUCCESS) {
679 omapi_disconnect (h, 1);
683 omapi_signal_in (h, "connect");
684 omapi_addr_list_dereference (&c -> connect_list, MDL);
685 return ISC_R_SUCCESS;
688 /* Reaper function for connection - if the connection is completely closed,
689 reap it. If it's in the disconnecting state, there were bytes left
690 to write when the user closed it, so if there are now no bytes left to
691 write, we can close it. */
692 isc_result_t omapi_connection_reaper (omapi_object_t *h)
694 omapi_connection_object_t *c;
696 if (h -> type != omapi_type_connection)
697 return ISC_R_INVALIDARG;
699 c = (omapi_connection_object_t *)h;
700 if (c -> state == omapi_connection_disconnecting &&
701 c -> out_bytes == 0) {
702 #ifdef DEBUG_PROTOCOL
703 log_debug ("omapi_connection_reaper(): disconnect");
705 omapi_disconnect (h, 1);
707 if (c -> state == omapi_connection_closed) {
708 #ifdef DEBUG_PROTOCOL
709 log_debug ("omapi_connection_reaper(): closed");
711 return ISC_R_NOTCONNECTED;
713 return ISC_R_SUCCESS;
716 static isc_result_t make_dst_key (DST_KEY **dst_key, omapi_object_t *a) {
717 omapi_value_t *name = (omapi_value_t *)0;
718 omapi_value_t *algorithm = (omapi_value_t *)0;
719 omapi_value_t *key = (omapi_value_t *)0;
722 isc_result_t status = ISC_R_SUCCESS;
724 if (status == ISC_R_SUCCESS)
725 status = omapi_get_value_str
726 (a, (omapi_object_t *)0, "name", &name);
728 if (status == ISC_R_SUCCESS)
729 status = omapi_get_value_str
730 (a, (omapi_object_t *)0, "algorithm", &algorithm);
732 if (status == ISC_R_SUCCESS)
733 status = omapi_get_value_str
734 (a, (omapi_object_t *)0, "key", &key);
736 if (status == ISC_R_SUCCESS) {
737 if ((algorithm -> value -> type == omapi_datatype_data ||
738 algorithm -> value -> type == omapi_datatype_string) &&
739 strncasecmp ((char *)algorithm -> value -> u.buffer.value,
740 NS_TSIG_ALG_HMAC_MD5 ".",
741 algorithm -> value -> u.buffer.len) == 0) {
742 algorithm_id = KEY_HMAC_MD5;
744 status = ISC_R_INVALIDARG;
748 if (status == ISC_R_SUCCESS) {
749 name_str = dmalloc (name -> value -> u.buffer.len + 1, MDL);
751 status = ISC_R_NOMEMORY;
754 if (status == ISC_R_SUCCESS) {
756 name -> value -> u.buffer.value,
757 name -> value -> u.buffer.len);
758 name_str [name -> value -> u.buffer.len] = 0;
760 *dst_key = dst_buffer_to_key (name_str, algorithm_id, 0, 0,
761 key -> value -> u.buffer.value,
762 key -> value -> u.buffer.len);
764 status = ISC_R_NOMEMORY;
768 dfree (name_str, MDL);
770 omapi_value_dereference (&key, MDL);
772 omapi_value_dereference (&algorithm, MDL);
774 omapi_value_dereference (&name, MDL);
779 isc_result_t omapi_connection_sign_data (int mode,
782 const unsigned char *data,
784 omapi_typed_data_t **result)
786 omapi_typed_data_t *td = (omapi_typed_data_t *)0;
790 if (mode & SIG_MODE_FINAL) {
791 status = omapi_typed_data_new (MDL, &td,
794 if (status != ISC_R_SUCCESS)
798 r = dst_sign_data (mode, key, context, data, len,
799 td ? td -> u.buffer.value : (u_char *)0,
800 td ? td -> u.buffer.len : 0);
802 /* dst_sign_data() really should do this for us, shouldn't it? */
803 if (mode & SIG_MODE_FINAL)
804 *context = (void *)0;
808 omapi_typed_data_dereference (&td, MDL);
809 return ISC_R_INVALIDKEY;
813 omapi_typed_data_reference (result, td, MDL);
817 omapi_typed_data_dereference (&td, MDL);
819 return ISC_R_SUCCESS;
822 isc_result_t omapi_connection_output_auth_length (omapi_object_t *h,
825 omapi_connection_object_t *c;
827 if (h -> type != omapi_type_connection)
828 return ISC_R_INVALIDARG;
829 c = (omapi_connection_object_t *)h;
832 return ISC_R_NOTFOUND;
834 *l = dst_sig_size (c -> out_key);
835 return ISC_R_SUCCESS;
838 isc_result_t omapi_connection_set_value (omapi_object_t *h,
840 omapi_data_string_t *name,
841 omapi_typed_data_t *value)
843 omapi_connection_object_t *c;
846 if (h -> type != omapi_type_connection)
847 return ISC_R_INVALIDARG;
848 c = (omapi_connection_object_t *)h;
850 if (omapi_ds_strcmp (name, "input-authenticator") == 0) {
851 if (value && value -> type != omapi_datatype_object)
852 return ISC_R_INVALIDARG;
854 if (c -> in_context) {
855 omapi_connection_sign_data (SIG_MODE_FINAL,
859 (omapi_typed_data_t **) 0);
863 dst_free_key (c -> in_key);
864 c -> in_key = (DST_KEY *)0;
868 status = make_dst_key (&c -> in_key,
870 if (status != ISC_R_SUCCESS)
874 return ISC_R_SUCCESS;
876 else if (omapi_ds_strcmp (name, "output-authenticator") == 0) {
877 if (value && value -> type != omapi_datatype_object)
878 return ISC_R_INVALIDARG;
880 if (c -> out_context) {
881 omapi_connection_sign_data (SIG_MODE_FINAL,
885 (omapi_typed_data_t **) 0);
889 dst_free_key (c -> out_key);
890 c -> out_key = (DST_KEY *)0;
894 status = make_dst_key (&c -> out_key,
896 if (status != ISC_R_SUCCESS)
900 return ISC_R_SUCCESS;
903 if (h -> inner && h -> inner -> type -> set_value)
904 return (*(h -> inner -> type -> set_value))
905 (h -> inner, id, name, value);
906 return ISC_R_NOTFOUND;
909 isc_result_t omapi_connection_get_value (omapi_object_t *h,
911 omapi_data_string_t *name,
912 omapi_value_t **value)
914 omapi_connection_object_t *c;
915 omapi_typed_data_t *td = (omapi_typed_data_t *)0;
918 if (h -> type != omapi_type_connection)
919 return ISC_R_INVALIDARG;
920 c = (omapi_connection_object_t *)h;
922 if (omapi_ds_strcmp (name, "input-signature") == 0) {
923 if (!c -> in_key || !c -> in_context)
924 return ISC_R_NOTFOUND;
926 status = omapi_connection_sign_data (SIG_MODE_FINAL,
930 if (status != ISC_R_SUCCESS)
933 status = omapi_make_value (value, name, td, MDL);
934 omapi_typed_data_dereference (&td, MDL);
937 } else if (omapi_ds_strcmp (name, "input-signature-size") == 0) {
939 return ISC_R_NOTFOUND;
941 return omapi_make_int_value (value, name,
942 dst_sig_size (c -> in_key), MDL);
944 } else if (omapi_ds_strcmp (name, "output-signature") == 0) {
945 if (!c -> out_key || !c -> out_context)
946 return ISC_R_NOTFOUND;
948 status = omapi_connection_sign_data (SIG_MODE_FINAL,
952 if (status != ISC_R_SUCCESS)
955 status = omapi_make_value (value, name, td, MDL);
956 omapi_typed_data_dereference (&td, MDL);
959 } else if (omapi_ds_strcmp (name, "output-signature-size") == 0) {
961 return ISC_R_NOTFOUND;
963 return omapi_make_int_value (value, name,
964 dst_sig_size (c -> out_key), MDL);
967 if (h -> inner && h -> inner -> type -> get_value)
968 return (*(h -> inner -> type -> get_value))
969 (h -> inner, id, name, value);
970 return ISC_R_NOTFOUND;
973 isc_result_t omapi_connection_destroy (omapi_object_t *h,
974 const char *file, int line)
976 omapi_connection_object_t *c;
978 #ifdef DEBUG_PROTOCOL
979 log_debug ("omapi_connection_destroy()");
982 if (h -> type != omapi_type_connection)
983 return ISC_R_UNEXPECTED;
984 c = (omapi_connection_object_t *)(h);
985 if (c -> state == omapi_connection_connected)
986 omapi_disconnect (h, 1);
988 omapi_listener_dereference (&c -> listener, file, line);
989 if (c -> connect_list)
990 omapi_addr_list_dereference (&c -> connect_list, file, line);
991 return ISC_R_SUCCESS;
994 isc_result_t omapi_connection_signal_handler (omapi_object_t *h,
995 const char *name, va_list ap)
997 if (h -> type != omapi_type_connection)
998 return ISC_R_INVALIDARG;
1000 #ifdef DEBUG_PROTOCOL
1001 log_debug ("omapi_connection_signal_handler(%s)", name);
1004 if (h -> inner && h -> inner -> type -> signal_handler)
1005 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
1007 return ISC_R_NOTFOUND;
1010 /* Write all the published values associated with the object through the
1011 specified connection. */
1013 isc_result_t omapi_connection_stuff_values (omapi_object_t *c,
1019 if (m -> type != omapi_type_connection)
1020 return ISC_R_INVALIDARG;
1022 if (m -> inner && m -> inner -> type -> stuff_values)
1023 return (*(m -> inner -> type -> stuff_values)) (c, id,
1025 return ISC_R_SUCCESS;