3 Subroutines for dealing with connections. */
6 * Copyright (c) 2004,2007 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''.
37 #include <omapip/omapip_p.h>
38 #include <arpa/inet.h>
39 #include <arpa/nameser.h>
44 static void trace_connect_input (trace_type_t
*, unsigned, char *);
45 static void trace_connect_stop (trace_type_t
*);
46 static void trace_disconnect_input (trace_type_t
*, unsigned, char *);
47 static void trace_disconnect_stop (trace_type_t
*);
48 trace_type_t
*trace_connect
;
49 trace_type_t
*trace_disconnect
;
50 extern omapi_array_t
*trace_listeners
;
52 static isc_result_t
omapi_connection_connect_internal (omapi_object_t
*);
54 OMAPI_OBJECT_ALLOC (omapi_connection
,
55 omapi_connection_object_t
, omapi_type_connection
)
57 isc_result_t
omapi_connect (omapi_object_t
*c
,
58 const char *server_name
,
63 omapi_addr_list_t
*addrs
= (omapi_addr_list_t
*)0;
68 log_debug ("omapi_connect(%s, port=%d)", server_name
, port
);
71 if (!inet_aton (server_name
, &foo
)) {
72 /* If we didn't get a numeric address, try for a domain
73 name. It's okay for this call to block. */
74 he
= gethostbyname (server_name
);
76 return ISC_R_HOSTUNKNOWN
;
77 for (i
= 0; he
-> h_addr_list
[i
]; i
++)
80 return ISC_R_HOSTUNKNOWN
;
83 status
= omapi_addr_list_new (&addrs
, hix
, MDL
);
84 if (status
!= ISC_R_SUCCESS
)
86 for (i
= 0; i
< hix
; i
++) {
87 addrs
-> addresses
[i
].addrtype
= he
-> h_addrtype
;
88 addrs
-> addresses
[i
].addrlen
= he
-> h_length
;
89 memcpy (addrs
-> addresses
[i
].address
,
90 he
-> h_addr_list
[i
],
91 (unsigned)he
-> h_length
);
92 addrs
-> addresses
[i
].port
= port
;
95 status
= omapi_addr_list_new (&addrs
, 1, MDL
);
96 if (status
!= ISC_R_SUCCESS
)
98 addrs
-> addresses
[0].addrtype
= AF_INET
;
99 addrs
-> addresses
[0].addrlen
= sizeof foo
;
100 memcpy (addrs
-> addresses
[0].address
, &foo
, sizeof foo
);
101 addrs
-> addresses
[0].port
= port
;
104 status
= omapi_connect_list (c
, addrs
, (omapi_addr_t
*)0);
105 omapi_addr_list_dereference (&addrs
, MDL
);
109 isc_result_t
omapi_connect_list (omapi_object_t
*c
,
110 omapi_addr_list_t
*remote_addrs
,
111 omapi_addr_t
*local_addr
)
114 omapi_connection_object_t
*obj
;
116 struct sockaddr_in local_sin
;
118 obj
= (omapi_connection_object_t
*)0;
119 status
= omapi_connection_allocate (&obj
, MDL
);
120 if (status
!= ISC_R_SUCCESS
)
123 status
= omapi_object_reference (&c
-> outer
, (omapi_object_t
*)obj
,
125 if (status
!= ISC_R_SUCCESS
) {
126 omapi_connection_dereference (&obj
, MDL
);
129 status
= omapi_object_reference (&obj
-> inner
, c
, MDL
);
130 if (status
!= ISC_R_SUCCESS
) {
131 omapi_connection_dereference (&obj
, MDL
);
135 /* Store the address list on the object. */
136 omapi_addr_list_reference (&obj
-> connect_list
, remote_addrs
, MDL
);
138 obj
-> state
= omapi_connection_unconnected
;
140 #if defined (TRACING)
141 /* If we're playing back, don't actually try to connect - just leave
142 the object available for a subsequent connect or disconnect. */
143 if (!trace_playback ()) {
145 /* Create a socket on which to communicate. */
147 socket (PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
148 if (obj
-> socket
< 0) {
149 omapi_connection_dereference (&obj
, MDL
);
150 if (errno
== EMFILE
|| errno
== ENFILE
152 return ISC_R_NORESOURCES
;
153 return ISC_R_UNEXPECTED
;
156 /* Set up the local address, if any. */
158 /* Only do TCPv4 so far. */
159 if (local_addr
-> addrtype
!= AF_INET
) {
160 omapi_connection_dereference (&obj
, MDL
);
161 return ISC_R_INVALIDARG
;
163 local_sin
.sin_port
= htons (local_addr
-> port
);
164 memcpy (&local_sin
.sin_addr
,
165 local_addr
-> address
,
166 local_addr
-> addrlen
);
167 #if defined (HAVE_SA_LEN)
168 local_sin
.sin_len
= sizeof local_addr
;
170 local_sin
.sin_family
= AF_INET
;
171 memset (&local_sin
.sin_zero
, 0,
172 sizeof local_sin
.sin_zero
);
174 if (bind (obj
-> socket
, (struct sockaddr
*)&local_sin
,
175 sizeof local_sin
) < 0) {
176 omapi_object_dereference ((omapi_object_t
**)
178 if (errno
== EADDRINUSE
)
179 return ISC_R_ADDRINUSE
;
180 if (errno
== EADDRNOTAVAIL
)
181 return ISC_R_ADDRNOTAVAIL
;
184 return ISC_R_UNEXPECTED
;
186 obj
-> local_addr
= local_sin
;
190 if (fcntl (obj
-> socket
, F_SETFD
, 1) < 0) {
191 close (obj
-> socket
);
192 omapi_connection_dereference (&obj
, MDL
);
193 return ISC_R_UNEXPECTED
;
197 /* Set the SO_REUSEADDR flag (this should not fail). */
199 if (setsockopt (obj
-> socket
, SOL_SOCKET
, SO_REUSEADDR
,
200 (char *)&flag
, sizeof flag
) < 0) {
201 omapi_connection_dereference (&obj
, MDL
);
202 return ISC_R_UNEXPECTED
;
205 /* Set the file to nonblocking mode. */
206 if (fcntl (obj
-> socket
, F_SETFL
, O_NONBLOCK
) < 0) {
207 omapi_connection_dereference (&obj
, MDL
);
208 return ISC_R_UNEXPECTED
;
211 status
= (omapi_register_io_object
212 ((omapi_object_t
*)obj
,
213 0, omapi_connection_writefd
,
214 0, omapi_connection_connect
,
215 omapi_connection_reaper
));
216 if (status
!= ISC_R_SUCCESS
)
218 status
= omapi_connection_connect_internal ((omapi_object_t
*)
220 #if defined (TRACING)
222 omapi_connection_register (obj
, MDL
);
226 omapi_connection_dereference (&obj
, MDL
);
230 #if defined (TRACING)
231 omapi_array_t
*omapi_connections
;
233 OMAPI_ARRAY_TYPE(omapi_connection
, omapi_connection_object_t
)
235 void omapi_connection_trace_setup (void) {
236 trace_connect
= trace_type_register ("connect", (void *)0,
238 trace_connect_stop
, MDL
);
239 trace_disconnect
= trace_type_register ("disconnect", (void *)0,
240 trace_disconnect_input
,
241 trace_disconnect_stop
, MDL
);
244 void omapi_connection_register (omapi_connection_object_t
*obj
,
245 const char *file
, int line
)
250 int32_t connect_index
, listener_index
;
251 static int32_t index
;
253 if (!omapi_connections
) {
254 status
= omapi_connection_array_allocate (&omapi_connections
,
256 if (status
!= ISC_R_SUCCESS
)
260 status
= omapi_connection_array_extend (omapi_connections
, obj
,
261 (int *)0, file
, line
);
262 if (status
!= ISC_R_SUCCESS
) {
267 #if defined (TRACING)
268 if (trace_record ()) {
269 /* Connection registration packet:
272 int32_t listener_index [-1 means no listener]
273 u_int16_t remote_port
275 u_int32_t remote_addr
276 u_int32_t local_addr */
278 connect_index
= htonl (index
);
281 listener_index
= htonl (obj
-> listener
-> index
);
283 listener_index
= htonl (-1);
284 iov
[iov_count
].buf
= (char *)&connect_index
;
285 iov
[iov_count
++].len
= sizeof connect_index
;
286 iov
[iov_count
].buf
= (char *)&listener_index
;
287 iov
[iov_count
++].len
= sizeof listener_index
;
288 iov
[iov_count
].buf
= (char *)&obj
-> remote_addr
.sin_port
;
289 iov
[iov_count
++].len
= sizeof obj
-> remote_addr
.sin_port
;
290 iov
[iov_count
].buf
= (char *)&obj
-> local_addr
.sin_port
;
291 iov
[iov_count
++].len
= sizeof obj
-> local_addr
.sin_port
;
292 iov
[iov_count
].buf
= (char *)&obj
-> remote_addr
.sin_addr
;
293 iov
[iov_count
++].len
= sizeof obj
-> remote_addr
.sin_addr
;
294 iov
[iov_count
].buf
= (char *)&obj
-> local_addr
.sin_addr
;
295 iov
[iov_count
++].len
= sizeof obj
-> local_addr
.sin_addr
;
297 status
= trace_write_packet_iov (trace_connect
,
298 iov_count
, iov
, file
, line
);
303 static void trace_connect_input (trace_type_t
*ttype
,
304 unsigned length
, char *buf
)
306 struct sockaddr_in remote
, local
;
307 int32_t connect_index
, listener_index
;
309 omapi_connection_object_t
*obj
;
313 if (length
!= ((sizeof connect_index
) +
314 (sizeof remote
.sin_port
) +
315 (sizeof remote
.sin_addr
)) * 2) {
316 log_error ("Trace connect: invalid length %d", length
);
320 memset (&remote
, 0, sizeof remote
);
321 memset (&local
, 0, sizeof local
);
322 memcpy (&connect_index
, s
, sizeof connect_index
);
323 s
+= sizeof connect_index
;
324 memcpy (&listener_index
, s
, sizeof listener_index
);
325 s
+= sizeof listener_index
;
326 memcpy (&remote
.sin_port
, s
, sizeof remote
.sin_port
);
327 s
+= sizeof remote
.sin_port
;
328 memcpy (&local
.sin_port
, s
, sizeof local
.sin_port
);
329 s
+= sizeof local
.sin_port
;
330 memcpy (&remote
.sin_addr
, s
, sizeof remote
.sin_addr
);
331 s
+= sizeof remote
.sin_addr
;
332 memcpy (&local
.sin_addr
, s
, sizeof local
.sin_addr
);
333 s
+= sizeof local
.sin_addr
;
335 connect_index
= ntohl (connect_index
);
336 listener_index
= ntohl (listener_index
);
338 /* If this was a connect to a listener, then we just slap together
340 if (listener_index
!= -1) {
341 omapi_listener_object_t
*listener
;
342 listener
= (omapi_listener_object_t
*)0;
343 omapi_array_foreach_begin (trace_listeners
,
344 omapi_listener_object_t
, lp
) {
345 if (lp
-> address
.sin_port
== local
.sin_port
) {
346 omapi_listener_reference (&listener
, lp
, MDL
);
347 omapi_listener_dereference (&lp
, MDL
);
350 } omapi_array_foreach_end (trace_listeners
,
351 omapi_listener_object_t
, lp
);
353 log_error ("%s%ld, addr %s, port %d",
354 "Spurious traced listener connect - index ",
355 (long int)listener_index
,
356 inet_ntoa (local
.sin_addr
),
357 ntohs (local
.sin_port
));
360 obj
= (omapi_connection_object_t
*)0;
361 status
= omapi_listener_connect (&obj
, listener
, -1, &remote
);
362 if (status
!= ISC_R_SUCCESS
) {
363 log_error ("traced listener connect: %s",
364 isc_result_totext (status
));
367 omapi_connection_dereference (&obj
, MDL
);
368 omapi_listener_dereference (&listener
, MDL
);
372 /* Find the matching connect object, if there is one. */
373 omapi_array_foreach_begin (omapi_connections
,
374 omapi_connection_object_t
, lp
) {
375 for (i
= 0; (lp
-> connect_list
&&
376 i
< lp
-> connect_list
-> count
); i
++) {
377 if (!memcmp (&remote
.sin_addr
,
378 &lp
-> connect_list
-> addresses
[i
].address
,
379 sizeof remote
.sin_addr
) &&
380 (ntohs (remote
.sin_port
) ==
381 lp
-> connect_list
-> addresses
[i
].port
))
382 lp
-> state
= omapi_connection_connected
;
383 lp
-> remote_addr
= remote
;
384 lp
-> remote_addr
.sin_family
= AF_INET
;
385 omapi_addr_list_dereference (&lp
-> connect_list
, MDL
);
386 lp
-> index
= connect_index
;
387 status
= omapi_signal_in ((omapi_object_t
*)lp
,
389 omapi_connection_dereference (&lp
, MDL
);
392 } omapi_array_foreach_end (omapi_connections
,
393 omapi_connection_object_t
, lp
);
395 log_error ("Spurious traced connect - index %ld, addr %s, port %d",
396 (long int)connect_index
, inet_ntoa (remote
.sin_addr
),
397 ntohs (remote
.sin_port
));
401 static void trace_connect_stop (trace_type_t
*ttype
) { }
403 static void trace_disconnect_input (trace_type_t
*ttype
,
404 unsigned length
, char *buf
)
407 if (length
!= sizeof *index
) {
408 log_error ("trace disconnect: wrong length %d", length
);
412 index
= (int32_t *)buf
;
414 omapi_array_foreach_begin (omapi_connections
,
415 omapi_connection_object_t
, lp
) {
416 if (lp
-> index
== ntohl (*index
)) {
417 omapi_disconnect ((omapi_object_t
*)lp
, 1);
418 omapi_connection_dereference (&lp
, MDL
);
421 } omapi_array_foreach_end (omapi_connections
,
422 omapi_connection_object_t
, lp
);
424 log_error ("trace disconnect: no connection matching index %ld",
425 (long int)ntohl (*index
));
428 static void trace_disconnect_stop (trace_type_t
*ttype
) { }
431 /* Disconnect a connection object from the remote end. If force is nonzero,
432 close the connection immediately. Otherwise, shut down the receiving end
433 but allow any unsent data to be sent before actually closing the socket. */
435 isc_result_t
omapi_disconnect (omapi_object_t
*h
,
438 omapi_connection_object_t
*c
;
441 #ifdef DEBUG_PROTOCOL
442 log_debug ("omapi_disconnect(%s)", force
? "force" : "");
445 c
= (omapi_connection_object_t
*)h
;
446 if (c
-> type
!= omapi_type_connection
)
447 return ISC_R_INVALIDARG
;
449 #if defined (TRACING)
450 if (trace_record ()) {
453 index
= htonl (c
-> index
);
454 status
= trace_write_packet (trace_disconnect
,
455 sizeof index
, (char *)&index
,
457 if (status
!= ISC_R_SUCCESS
) {
459 log_error ("trace_write_packet: %s",
460 isc_result_totext (status
));
463 if (!trace_playback ()) {
466 /* If we're already disconnecting, we don't have to do
468 if (c
-> state
== omapi_connection_disconnecting
)
469 return ISC_R_SUCCESS
;
471 /* Try to shut down the socket - this sends a FIN to
472 the remote end, so that it won't send us any more
473 data. If the shutdown succeeds, and we still
474 have bytes left to write, defer closing the socket
475 until that's done. */
476 if (!shutdown (c
-> socket
, SHUT_RD
)) {
477 if (c
-> out_bytes
> 0) {
479 omapi_connection_disconnecting
;
480 return ISC_R_SUCCESS
;
485 #if defined (TRACING)
488 c
-> state
= omapi_connection_closed
;
490 /* Disconnect from I/O object, if any. */
492 if (h
-> outer
-> inner
)
493 omapi_object_dereference (&h
-> outer
-> inner
, MDL
);
494 omapi_object_dereference (&h
-> outer
, MDL
);
497 /* If whatever created us registered a signal handler, send it
498 a disconnect signal. */
499 omapi_signal (h
, "disconnect", h
);
500 return ISC_R_SUCCESS
;
503 isc_result_t
omapi_connection_require (omapi_object_t
*h
, unsigned bytes
)
505 omapi_connection_object_t
*c
;
507 if (h
-> type
!= omapi_type_connection
)
508 return ISC_R_INVALIDARG
;
509 c
= (omapi_connection_object_t
*)h
;
511 c
-> bytes_needed
= bytes
;
512 if (c
-> bytes_needed
<= c
-> in_bytes
) {
513 return ISC_R_SUCCESS
;
518 /* Return the socket on which the dispatcher should wait for readiness
519 to read, for a connection object. If we already have more bytes than
520 we need to do the next thing, and we have at least a single full input
521 buffer, then don't indicate that we're ready to read. */
522 int omapi_connection_readfd (omapi_object_t
*h
)
524 omapi_connection_object_t
*c
;
525 if (h
-> type
!= omapi_type_connection
)
527 c
= (omapi_connection_object_t
*)h
;
528 if (c
-> state
!= omapi_connection_connected
)
530 if (c
-> in_bytes
>= OMAPI_BUF_SIZE
- 1 &&
531 c
-> in_bytes
> c
-> bytes_needed
)
536 /* Return the socket on which the dispatcher should wait for readiness
537 to write, for a connection object. If there are no bytes buffered
538 for writing, then don't indicate that we're ready to write. */
539 int omapi_connection_writefd (omapi_object_t
*h
)
541 omapi_connection_object_t
*c
;
542 if (h
-> type
!= omapi_type_connection
)
544 c
= (omapi_connection_object_t
*)h
;
545 if (c
-> state
== omapi_connection_connecting
)
553 isc_result_t
omapi_connection_connect (omapi_object_t
*h
)
557 status
= omapi_connection_connect_internal (h
);
558 if (status
!= ISC_R_SUCCESS
)
559 omapi_signal (h
, "status", status
);
560 return ISC_R_SUCCESS
;
563 static isc_result_t
omapi_connection_connect_internal (omapi_object_t
*h
)
566 omapi_connection_object_t
*c
;
570 if (h
-> type
!= omapi_type_connection
)
571 return ISC_R_INVALIDARG
;
572 c
= (omapi_connection_object_t
*)h
;
574 if (c
-> state
== omapi_connection_connecting
) {
576 if (getsockopt (c
-> socket
, SOL_SOCKET
, SO_ERROR
,
577 (char *)&error
, &sl
) < 0) {
578 omapi_disconnect (h
, 1);
579 return ISC_R_SUCCESS
;
582 c
-> state
= omapi_connection_connected
;
584 if (c
-> state
== omapi_connection_connecting
||
585 c
-> state
== omapi_connection_unconnected
) {
586 if (c
-> cptr
>= c
-> connect_list
-> count
) {
589 status
= ISC_R_CONNREFUSED
;
592 status
= ISC_R_NETUNREACH
;
595 status
= uerr2isc (error
);
598 omapi_disconnect (h
, 1);
602 if (c
-> connect_list
-> addresses
[c
-> cptr
].addrtype
!=
604 omapi_disconnect (h
, 1);
605 return ISC_R_INVALIDARG
;
608 memcpy (&c
-> remote_addr
.sin_addr
,
609 &c
-> connect_list
-> addresses
[c
-> cptr
].address
,
610 sizeof c
-> remote_addr
.sin_addr
);
611 c
-> remote_addr
.sin_family
= AF_INET
;
612 c
-> remote_addr
.sin_port
=
613 htons (c
-> connect_list
-> addresses
[c
-> cptr
].port
);
614 #if defined (HAVE_SA_LEN)
615 c
-> remote_addr
.sin_len
= sizeof c
-> remote_addr
;
617 memset (&c
-> remote_addr
.sin_zero
, 0,
618 sizeof c
-> remote_addr
.sin_zero
);
621 error
= connect (c
-> socket
,
622 (struct sockaddr
*)&c
-> remote_addr
,
623 sizeof c
-> remote_addr
);
626 if (error
!= EINPROGRESS
) {
627 omapi_disconnect (h
, 1);
630 status
= ISC_R_CONNREFUSED
;
633 status
= ISC_R_NETUNREACH
;
636 status
= uerr2isc (error
);
641 c
-> state
= omapi_connection_connecting
;
642 return ISC_R_INCOMPLETE
;
644 c
-> state
= omapi_connection_connected
;
647 /* I don't know why this would fail, so I'm tempted not to test
649 sl
= sizeof (c
-> local_addr
);
650 if (getsockname (c
-> socket
,
651 (struct sockaddr
*)&c
-> local_addr
, &sl
) < 0) {
654 /* Disconnect from I/O object, if any. */
656 omapi_unregister_io_object (h
);
658 status
= omapi_register_io_object (h
,
659 omapi_connection_readfd
,
660 omapi_connection_writefd
,
661 omapi_connection_reader
,
662 omapi_connection_writer
,
663 omapi_connection_reaper
);
665 if (status
!= ISC_R_SUCCESS
) {
666 omapi_disconnect (h
, 1);
670 omapi_signal_in (h
, "connect");
671 omapi_addr_list_dereference (&c
-> connect_list
, MDL
);
672 return ISC_R_SUCCESS
;
675 /* Reaper function for connection - if the connection is completely closed,
676 reap it. If it's in the disconnecting state, there were bytes left
677 to write when the user closed it, so if there are now no bytes left to
678 write, we can close it. */
679 isc_result_t
omapi_connection_reaper (omapi_object_t
*h
)
681 omapi_connection_object_t
*c
;
683 if (h
-> type
!= omapi_type_connection
)
684 return ISC_R_INVALIDARG
;
686 c
= (omapi_connection_object_t
*)h
;
687 if (c
-> state
== omapi_connection_disconnecting
&&
688 c
-> out_bytes
== 0) {
689 #ifdef DEBUG_PROTOCOL
690 log_debug ("omapi_connection_reaper(): disconnect");
692 omapi_disconnect (h
, 1);
694 if (c
-> state
== omapi_connection_closed
) {
695 #ifdef DEBUG_PROTOCOL
696 log_debug ("omapi_connection_reaper(): closed");
698 return ISC_R_NOTCONNECTED
;
700 return ISC_R_SUCCESS
;
703 static isc_result_t
make_dst_key (DST_KEY
**dst_key
, omapi_object_t
*a
) {
704 omapi_value_t
*name
= (omapi_value_t
*)0;
705 omapi_value_t
*algorithm
= (omapi_value_t
*)0;
706 omapi_value_t
*key
= (omapi_value_t
*)0;
707 int algorithm_id
= UNKNOWN_KEYALG
;
708 char *name_str
= NULL
;
709 isc_result_t status
= ISC_R_SUCCESS
;
711 if (status
== ISC_R_SUCCESS
)
712 status
= omapi_get_value_str
713 (a
, (omapi_object_t
*)0, "name", &name
);
715 if (status
== ISC_R_SUCCESS
)
716 status
= omapi_get_value_str
717 (a
, (omapi_object_t
*)0, "algorithm", &algorithm
);
719 if (status
== ISC_R_SUCCESS
)
720 status
= omapi_get_value_str
721 (a
, (omapi_object_t
*)0, "key", &key
);
723 if (status
== ISC_R_SUCCESS
) {
724 if ((algorithm
-> value
-> type
== omapi_datatype_data
||
725 algorithm
-> value
-> type
== omapi_datatype_string
) &&
726 strncasecmp ((char *)algorithm
-> value
-> u
.buffer
.value
,
727 NS_TSIG_ALG_HMAC_MD5
".",
728 algorithm
-> value
-> u
.buffer
.len
) == 0) {
729 algorithm_id
= KEY_HMAC_MD5
;
731 status
= ISC_R_INVALIDARG
;
735 if (status
== ISC_R_SUCCESS
) {
736 name_str
= dmalloc (name
-> value
-> u
.buffer
.len
+ 1, MDL
);
738 status
= ISC_R_NOMEMORY
;
741 if (status
== ISC_R_SUCCESS
) {
743 name
-> value
-> u
.buffer
.value
,
744 name
-> value
-> u
.buffer
.len
);
745 name_str
[name
-> value
-> u
.buffer
.len
] = 0;
747 *dst_key
= dst_buffer_to_key (name_str
, algorithm_id
, 0, 0,
748 key
-> value
-> u
.buffer
.value
,
749 key
-> value
-> u
.buffer
.len
);
751 status
= ISC_R_NOMEMORY
;
755 dfree (name_str
, MDL
);
757 omapi_value_dereference (&key
, MDL
);
759 omapi_value_dereference (&algorithm
, MDL
);
761 omapi_value_dereference (&name
, MDL
);
766 isc_result_t
omapi_connection_sign_data (int mode
,
769 const unsigned char *data
,
771 omapi_typed_data_t
**result
)
773 omapi_typed_data_t
*td
= (omapi_typed_data_t
*)0;
777 if (mode
& SIG_MODE_FINAL
) {
778 status
= omapi_typed_data_new (MDL
, &td
,
781 if (status
!= ISC_R_SUCCESS
)
785 r
= dst_sign_data (mode
, key
, context
, data
, len
,
786 td
? td
-> u
.buffer
.value
: (u_char
*)0,
787 td
? td
-> u
.buffer
.len
: 0);
789 /* dst_sign_data() really should do this for us, shouldn't it? */
790 if (mode
& SIG_MODE_FINAL
)
791 *context
= (void *)0;
795 omapi_typed_data_dereference (&td
, MDL
);
796 return ISC_R_INVALIDKEY
;
800 omapi_typed_data_reference (result
, td
, MDL
);
804 omapi_typed_data_dereference (&td
, MDL
);
806 return ISC_R_SUCCESS
;
809 isc_result_t
omapi_connection_output_auth_length (omapi_object_t
*h
,
812 omapi_connection_object_t
*c
;
814 if (h
-> type
!= omapi_type_connection
)
815 return ISC_R_INVALIDARG
;
816 c
= (omapi_connection_object_t
*)h
;
819 return ISC_R_NOTFOUND
;
821 *l
= dst_sig_size (c
-> out_key
);
822 return ISC_R_SUCCESS
;
825 isc_result_t
omapi_connection_set_value (omapi_object_t
*h
,
827 omapi_data_string_t
*name
,
828 omapi_typed_data_t
*value
)
830 omapi_connection_object_t
*c
;
833 if (h
-> type
!= omapi_type_connection
)
834 return ISC_R_INVALIDARG
;
835 c
= (omapi_connection_object_t
*)h
;
837 if (omapi_ds_strcmp (name
, "input-authenticator") == 0) {
838 if (value
&& value
-> type
!= omapi_datatype_object
)
839 return ISC_R_INVALIDARG
;
841 if (c
-> in_context
) {
842 omapi_connection_sign_data (SIG_MODE_FINAL
,
846 (omapi_typed_data_t
**) 0);
850 dst_free_key (c
-> in_key
);
851 c
-> in_key
= (DST_KEY
*)0;
855 status
= make_dst_key (&c
-> in_key
,
857 if (status
!= ISC_R_SUCCESS
)
861 return ISC_R_SUCCESS
;
863 else if (omapi_ds_strcmp (name
, "output-authenticator") == 0) {
864 if (value
&& value
-> type
!= omapi_datatype_object
)
865 return ISC_R_INVALIDARG
;
867 if (c
-> out_context
) {
868 omapi_connection_sign_data (SIG_MODE_FINAL
,
872 (omapi_typed_data_t
**) 0);
876 dst_free_key (c
-> out_key
);
877 c
-> out_key
= (DST_KEY
*)0;
881 status
= make_dst_key (&c
-> out_key
,
883 if (status
!= ISC_R_SUCCESS
)
887 return ISC_R_SUCCESS
;
890 if (h
-> inner
&& h
-> inner
-> type
-> set_value
)
891 return (*(h
-> inner
-> type
-> set_value
))
892 (h
-> inner
, id
, name
, value
);
893 return ISC_R_NOTFOUND
;
896 isc_result_t
omapi_connection_get_value (omapi_object_t
*h
,
898 omapi_data_string_t
*name
,
899 omapi_value_t
**value
)
901 omapi_connection_object_t
*c
;
902 omapi_typed_data_t
*td
= (omapi_typed_data_t
*)0;
905 if (h
-> type
!= omapi_type_connection
)
906 return ISC_R_INVALIDARG
;
907 c
= (omapi_connection_object_t
*)h
;
909 if (omapi_ds_strcmp (name
, "input-signature") == 0) {
910 if (!c
-> in_key
|| !c
-> in_context
)
911 return ISC_R_NOTFOUND
;
913 status
= omapi_connection_sign_data (SIG_MODE_FINAL
,
917 if (status
!= ISC_R_SUCCESS
)
920 status
= omapi_make_value (value
, name
, td
, MDL
);
921 omapi_typed_data_dereference (&td
, MDL
);
924 } else if (omapi_ds_strcmp (name
, "input-signature-size") == 0) {
926 return ISC_R_NOTFOUND
;
928 return omapi_make_int_value (value
, name
,
929 dst_sig_size (c
-> in_key
), MDL
);
931 } else if (omapi_ds_strcmp (name
, "output-signature") == 0) {
932 if (!c
-> out_key
|| !c
-> out_context
)
933 return ISC_R_NOTFOUND
;
935 status
= omapi_connection_sign_data (SIG_MODE_FINAL
,
939 if (status
!= ISC_R_SUCCESS
)
942 status
= omapi_make_value (value
, name
, td
, MDL
);
943 omapi_typed_data_dereference (&td
, MDL
);
946 } else if (omapi_ds_strcmp (name
, "output-signature-size") == 0) {
948 return ISC_R_NOTFOUND
;
950 return omapi_make_int_value (value
, name
,
951 dst_sig_size (c
-> out_key
), MDL
);
954 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
955 return (*(h
-> inner
-> type
-> get_value
))
956 (h
-> inner
, id
, name
, value
);
957 return ISC_R_NOTFOUND
;
960 isc_result_t
omapi_connection_destroy (omapi_object_t
*h
,
961 const char *file
, int line
)
963 omapi_connection_object_t
*c
;
965 #ifdef DEBUG_PROTOCOL
966 log_debug ("omapi_connection_destroy()");
969 if (h
-> type
!= omapi_type_connection
)
970 return ISC_R_UNEXPECTED
;
971 c
= (omapi_connection_object_t
*)(h
);
972 if (c
-> state
== omapi_connection_connected
)
973 omapi_disconnect (h
, 1);
975 omapi_listener_dereference (&c
-> listener
, file
, line
);
976 if (c
-> connect_list
)
977 omapi_addr_list_dereference (&c
-> connect_list
, file
, line
);
978 return ISC_R_SUCCESS
;
981 isc_result_t
omapi_connection_signal_handler (omapi_object_t
*h
,
982 const char *name
, va_list ap
)
984 if (h
-> type
!= omapi_type_connection
)
985 return ISC_R_INVALIDARG
;
987 #ifdef DEBUG_PROTOCOL
988 log_debug ("omapi_connection_signal_handler(%s)", name
);
991 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
992 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
994 return ISC_R_NOTFOUND
;
997 /* Write all the published values associated with the object through the
998 specified connection. */
1000 isc_result_t
omapi_connection_stuff_values (omapi_object_t
*c
,
1004 if (m
-> type
!= omapi_type_connection
)
1005 return ISC_R_INVALIDARG
;
1007 if (m
-> inner
&& m
-> inner
-> type
-> stuff_values
)
1008 return (*(m
-> inner
-> type
-> stuff_values
)) (c
, id
,
1010 return ISC_R_SUCCESS
;