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)
115 // trace_addr_t *addrs;
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 #ifdef SOCKET_IS_NOT_A_FILE
208 if (IoctlSocket (obj
-> socket
, FIONBIO
, (char *)&flag
) < 0)
210 if (fcntl (obj
-> socket
, F_SETFL
, O_NONBLOCK
) < 0)
213 omapi_connection_dereference (&obj
, MDL
);
214 return ISC_R_UNEXPECTED
;
217 status
= (omapi_register_io_object
218 ((omapi_object_t
*)obj
,
219 0, omapi_connection_writefd
,
220 0, omapi_connection_connect
,
221 omapi_connection_reaper
));
222 if (status
!= ISC_R_SUCCESS
)
224 status
= omapi_connection_connect_internal ((omapi_object_t
*)
226 #if defined (TRACING)
228 omapi_connection_register (obj
, MDL
);
232 omapi_connection_dereference (&obj
, MDL
);
236 #if defined (TRACING)
237 omapi_array_t
*omapi_connections
;
239 OMAPI_ARRAY_TYPE(omapi_connection
, omapi_connection_object_t
)
241 void omapi_connection_trace_setup (void) {
242 trace_connect
= trace_type_register ("connect", (void *)0,
244 trace_connect_stop
, MDL
);
245 trace_disconnect
= trace_type_register ("disconnect", (void *)0,
246 trace_disconnect_input
,
247 trace_disconnect_stop
, MDL
);
250 void omapi_connection_register (omapi_connection_object_t
*obj
,
251 const char *file
, int line
)
256 int32_t connect_index
, listener_index
;
257 static int32_t index
;
259 if (!omapi_connections
) {
260 status
= omapi_connection_array_allocate (&omapi_connections
,
262 if (status
!= ISC_R_SUCCESS
)
266 status
= omapi_connection_array_extend (omapi_connections
, obj
,
267 (int *)0, file
, line
);
268 if (status
!= ISC_R_SUCCESS
) {
273 #if defined (TRACING)
274 if (trace_record ()) {
275 /* Connection registration packet:
278 int32_t listener_index [-1 means no listener]
279 u_int16_t remote_port
281 u_int32_t remote_addr
282 u_int32_t local_addr */
284 connect_index
= htonl (index
);
287 listener_index
= htonl (obj
-> listener
-> index
);
289 listener_index
= htonl (-1);
290 iov
[iov_count
].buf
= (char *)&connect_index
;
291 iov
[iov_count
++].len
= sizeof connect_index
;
292 iov
[iov_count
].buf
= (char *)&listener_index
;
293 iov
[iov_count
++].len
= sizeof listener_index
;
294 iov
[iov_count
].buf
= (char *)&obj
-> remote_addr
.sin_port
;
295 iov
[iov_count
++].len
= sizeof obj
-> remote_addr
.sin_port
;
296 iov
[iov_count
].buf
= (char *)&obj
-> local_addr
.sin_port
;
297 iov
[iov_count
++].len
= sizeof obj
-> local_addr
.sin_port
;
298 iov
[iov_count
].buf
= (char *)&obj
-> remote_addr
.sin_addr
;
299 iov
[iov_count
++].len
= sizeof obj
-> remote_addr
.sin_addr
;
300 iov
[iov_count
].buf
= (char *)&obj
-> local_addr
.sin_addr
;
301 iov
[iov_count
++].len
= sizeof obj
-> local_addr
.sin_addr
;
303 status
= trace_write_packet_iov (trace_connect
,
304 iov_count
, iov
, file
, line
);
309 static void trace_connect_input (trace_type_t
*ttype
,
310 unsigned length
, char *buf
)
312 struct sockaddr_in remote
, local
;
313 int32_t connect_index
, listener_index
;
315 omapi_connection_object_t
*obj
;
319 if (length
!= ((sizeof connect_index
) +
320 (sizeof remote
.sin_port
) +
321 (sizeof remote
.sin_addr
)) * 2) {
322 log_error ("Trace connect: invalid length %d", length
);
326 memset (&remote
, 0, sizeof remote
);
327 memset (&local
, 0, sizeof local
);
328 memcpy (&connect_index
, s
, sizeof connect_index
);
329 s
+= sizeof connect_index
;
330 memcpy (&listener_index
, s
, sizeof listener_index
);
331 s
+= sizeof listener_index
;
332 memcpy (&remote
.sin_port
, s
, sizeof remote
.sin_port
);
333 s
+= sizeof remote
.sin_port
;
334 memcpy (&local
.sin_port
, s
, sizeof local
.sin_port
);
335 s
+= sizeof local
.sin_port
;
336 memcpy (&remote
.sin_addr
, s
, sizeof remote
.sin_addr
);
337 s
+= sizeof remote
.sin_addr
;
338 memcpy (&local
.sin_addr
, s
, sizeof local
.sin_addr
);
339 s
+= sizeof local
.sin_addr
;
341 connect_index
= ntohl (connect_index
);
342 listener_index
= ntohl (listener_index
);
344 /* If this was a connect to a listener, then we just slap together
346 if (listener_index
!= -1) {
347 omapi_listener_object_t
*listener
;
348 listener
= (omapi_listener_object_t
*)0;
349 omapi_array_foreach_begin (trace_listeners
,
350 omapi_listener_object_t
, lp
) {
351 if (lp
-> address
.sin_port
== local
.sin_port
) {
352 omapi_listener_reference (&listener
, lp
, MDL
);
353 omapi_listener_dereference (&lp
, MDL
);
356 } omapi_array_foreach_end (trace_listeners
,
357 omapi_listener_object_t
, lp
);
359 log_error ("%s%ld, addr %s, port %d",
360 "Spurious traced listener connect - index ",
361 (long int)listener_index
,
362 inet_ntoa (local
.sin_addr
),
363 ntohs (local
.sin_port
));
366 obj
= (omapi_connection_object_t
*)0;
367 status
= omapi_listener_connect (&obj
, listener
, -1, &remote
);
368 if (status
!= ISC_R_SUCCESS
) {
369 log_error ("traced listener connect: %s",
370 isc_result_totext (status
));
373 omapi_connection_dereference (&obj
, MDL
);
374 omapi_listener_dereference (&listener
, MDL
);
378 /* Find the matching connect object, if there is one. */
379 omapi_array_foreach_begin (omapi_connections
,
380 omapi_connection_object_t
, lp
) {
381 for (i
= 0; (lp
-> connect_list
&&
382 i
< lp
-> connect_list
-> count
); i
++) {
383 if (!memcmp (&remote
.sin_addr
,
384 &lp
-> connect_list
-> addresses
[i
].address
,
385 sizeof remote
.sin_addr
) &&
386 (ntohs (remote
.sin_port
) ==
387 lp
-> connect_list
-> addresses
[i
].port
))
388 lp
-> state
= omapi_connection_connected
;
389 lp
-> remote_addr
= remote
;
390 lp
-> remote_addr
.sin_family
= AF_INET
;
391 #if defined (HAVE_SIN_LEN)
392 lp
-> remote_addr
.sin_len
= sizeof remote
;
394 omapi_addr_list_dereference (&lp
-> connect_list
, MDL
);
395 lp
-> index
= connect_index
;
396 status
= omapi_signal_in ((omapi_object_t
*)lp
,
398 omapi_connection_dereference (&lp
, MDL
);
401 } omapi_array_foreach_end (omapi_connections
,
402 omapi_connection_object_t
, lp
);
404 log_error ("Spurious traced connect - index %ld, addr %s, port %d",
405 (long int)connect_index
, inet_ntoa (remote
.sin_addr
),
406 ntohs (remote
.sin_port
));
410 static void trace_connect_stop (trace_type_t
*ttype
) { }
412 static void trace_disconnect_input (trace_type_t
*ttype
,
413 unsigned length
, char *buf
)
416 if (length
!= sizeof *index
) {
417 log_error ("trace disconnect: wrong length %d", length
);
421 index
= (int32_t *)buf
;
423 omapi_array_foreach_begin (omapi_connections
,
424 omapi_connection_object_t
, lp
) {
425 if (lp
-> index
== ntohl (*index
)) {
426 omapi_disconnect ((omapi_object_t
*)lp
, 1);
427 omapi_connection_dereference (&lp
, MDL
);
430 } omapi_array_foreach_end (omapi_connections
,
431 omapi_connection_object_t
, lp
);
433 log_error ("trace disconnect: no connection matching index %ld",
434 (long int)ntohl (*index
));
437 static void trace_disconnect_stop (trace_type_t
*ttype
) { }
440 /* Disconnect a connection object from the remote end. If force is nonzero,
441 close the connection immediately. Otherwise, shut down the receiving end
442 but allow any unsent data to be sent before actually closing the socket. */
444 isc_result_t
omapi_disconnect (omapi_object_t
*h
,
447 omapi_connection_object_t
*c
;
450 #ifdef DEBUG_PROTOCOL
451 log_debug ("omapi_disconnect(%s)", force
? "force" : "");
454 c
= (omapi_connection_object_t
*)h
;
455 if (c
-> type
!= omapi_type_connection
)
456 return ISC_R_INVALIDARG
;
458 #if defined (TRACING)
459 if (trace_record ()) {
462 index
= htonl (c
-> index
);
463 status
= trace_write_packet (trace_disconnect
,
464 sizeof index
, (char *)&index
,
466 if (status
!= ISC_R_SUCCESS
) {
468 log_error ("trace_write_packet: %s",
469 isc_result_totext (status
));
472 if (!trace_playback ()) {
475 /* If we're already disconnecting, we don't have to do
477 if (c
-> state
== omapi_connection_disconnecting
)
478 return ISC_R_SUCCESS
;
480 /* Try to shut down the socket - this sends a FIN to
481 the remote end, so that it won't send us any more
482 data. If the shutdown succeeds, and we still
483 have bytes left to write, defer closing the socket
484 until that's done. */
485 if (!shutdown (c
-> socket
, SHUT_RD
)) {
486 if (c
-> out_bytes
> 0) {
488 omapi_connection_disconnecting
;
489 return ISC_R_SUCCESS
;
493 #ifdef SOCKET_IS_NOT_A_FILE
494 CloseSocket (c
-> socket
);
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;
720 int algorithm_id
= UNKNOWN_KEYALG
;
721 char *name_str
= NULL
;
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
;