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
;
115 obj
= (omapi_connection_object_t
*)0;
116 status
= omapi_connection_allocate (&obj
, MDL
);
117 if (status
!= ISC_R_SUCCESS
)
120 status
= omapi_object_reference (&c
-> outer
, (omapi_object_t
*)obj
,
122 if (status
!= ISC_R_SUCCESS
) {
123 omapi_connection_dereference (&obj
, MDL
);
126 status
= omapi_object_reference (&obj
-> inner
, c
, MDL
);
127 if (status
!= ISC_R_SUCCESS
) {
128 omapi_connection_dereference (&obj
, MDL
);
132 /* Store the address list on the object. */
133 omapi_addr_list_reference (&obj
-> connect_list
, remote_addrs
, MDL
);
135 obj
-> state
= omapi_connection_unconnected
;
137 #if defined (TRACING)
138 /* If we're playing back, don't actually try to connect - just leave
139 the object available for a subsequent connect or disconnect. */
140 if (!trace_playback ()) {
142 /* Create a socket on which to communicate. */
144 socket (PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
145 if (obj
-> socket
< 0) {
146 omapi_connection_dereference (&obj
, MDL
);
147 if (errno
== EMFILE
|| errno
== ENFILE
149 return ISC_R_NORESOURCES
;
150 return ISC_R_UNEXPECTED
;
153 /* Set up the local address, if any. */
155 /* Only do TCPv4 so far. */
156 if (local_addr
-> addrtype
!= AF_INET
) {
157 omapi_connection_dereference (&obj
, MDL
);
158 return ISC_R_INVALIDARG
;
160 memset (&local_sin
, 0, sizeof local_sin
);
161 local_sin
.sin_port
= htons (local_addr
-> port
);
162 memcpy (&local_sin
.sin_addr
,
163 local_addr
-> address
,
164 local_addr
-> addrlen
);
165 #if defined (HAVE_SA_LEN)
166 local_sin
.sin_len
= sizeof local_addr
;
168 local_sin
.sin_family
= AF_INET
;
170 if (bind (obj
-> socket
, (struct sockaddr
*)&local_sin
,
171 sizeof local_sin
) < 0) {
172 omapi_object_dereference ((void *) &obj
, MDL
);
173 if (errno
== EADDRINUSE
)
174 return ISC_R_ADDRINUSE
;
175 if (errno
== EADDRNOTAVAIL
)
176 return ISC_R_ADDRNOTAVAIL
;
179 return ISC_R_UNEXPECTED
;
181 obj
-> local_addr
= local_sin
;
184 #if defined (HAVE_SETFD)
185 if (fcntl (obj
-> socket
, F_SETFD
, 1) < 0) {
186 close (obj
-> socket
);
187 omapi_connection_dereference (&obj
, MDL
);
188 return ISC_R_UNEXPECTED
;
192 /* Set the SO_REUSEADDR flag (this should not fail). */
194 if (setsockopt (obj
-> socket
, SOL_SOCKET
, SO_REUSEADDR
,
195 (char *)&flag
, sizeof flag
) < 0) {
196 omapi_connection_dereference (&obj
, MDL
);
197 return ISC_R_UNEXPECTED
;
200 /* Set the file to nonblocking mode. */
201 if (fcntl (obj
-> socket
, F_SETFL
, O_NONBLOCK
) < 0) {
202 omapi_connection_dereference (&obj
, MDL
);
203 return ISC_R_UNEXPECTED
;
206 status
= (omapi_register_io_object
207 ((omapi_object_t
*)obj
,
208 0, omapi_connection_writefd
,
209 0, omapi_connection_connect
,
210 omapi_connection_reaper
));
211 if (status
!= ISC_R_SUCCESS
)
213 status
= omapi_connection_connect_internal ((omapi_object_t
*)
215 #if defined (TRACING)
217 omapi_connection_register (obj
, MDL
);
221 omapi_connection_dereference (&obj
, MDL
);
225 #if defined (TRACING)
226 omapi_array_t
*omapi_connections
;
228 OMAPI_ARRAY_TYPE(omapi_connection
, omapi_connection_object_t
)
230 void omapi_connection_trace_setup (void) {
231 trace_connect
= trace_type_register ("connect", (void *)0,
233 trace_connect_stop
, MDL
);
234 trace_disconnect
= trace_type_register ("disconnect", (void *)0,
235 trace_disconnect_input
,
236 trace_disconnect_stop
, MDL
);
239 void omapi_connection_register (omapi_connection_object_t
*obj
,
240 const char *file
, int line
)
245 int32_t connect_index
, listener_index
;
246 static int32_t index
;
248 if (!omapi_connections
) {
249 status
= omapi_connection_array_allocate (&omapi_connections
,
251 if (status
!= ISC_R_SUCCESS
)
255 status
= omapi_connection_array_extend (omapi_connections
, obj
,
256 (int *)0, file
, line
);
257 if (status
!= ISC_R_SUCCESS
) {
262 #if defined (TRACING)
263 if (trace_record ()) {
264 /* Connection registration packet:
267 int32_t listener_index [-1 means no listener]
268 u_int16_t remote_port
270 u_int32_t remote_addr
271 u_int32_t local_addr */
273 connect_index
= htonl (index
);
276 listener_index
= htonl (obj
-> listener
-> index
);
278 listener_index
= htonl (-1);
279 iov
[iov_count
].buf
= (char *)&connect_index
;
280 iov
[iov_count
++].len
= sizeof connect_index
;
281 iov
[iov_count
].buf
= (char *)&listener_index
;
282 iov
[iov_count
++].len
= sizeof listener_index
;
283 iov
[iov_count
].buf
= (char *)&obj
-> remote_addr
.sin_port
;
284 iov
[iov_count
++].len
= sizeof obj
-> remote_addr
.sin_port
;
285 iov
[iov_count
].buf
= (char *)&obj
-> local_addr
.sin_port
;
286 iov
[iov_count
++].len
= sizeof obj
-> local_addr
.sin_port
;
287 iov
[iov_count
].buf
= (char *)&obj
-> remote_addr
.sin_addr
;
288 iov
[iov_count
++].len
= sizeof obj
-> remote_addr
.sin_addr
;
289 iov
[iov_count
].buf
= (char *)&obj
-> local_addr
.sin_addr
;
290 iov
[iov_count
++].len
= sizeof obj
-> local_addr
.sin_addr
;
292 status
= trace_write_packet_iov (trace_connect
,
293 iov_count
, iov
, file
, line
);
298 static void trace_connect_input (trace_type_t
*ttype
,
299 unsigned length
, char *buf
)
301 struct sockaddr_in remote
, local
;
302 int32_t connect_index
, listener_index
;
304 omapi_connection_object_t
*obj
;
308 if (length
!= ((sizeof connect_index
) +
309 (sizeof remote
.sin_port
) +
310 (sizeof remote
.sin_addr
)) * 2) {
311 log_error ("Trace connect: invalid length %d", length
);
315 memset (&remote
, 0, sizeof remote
);
316 memset (&local
, 0, sizeof local
);
317 memcpy (&connect_index
, s
, sizeof connect_index
);
318 s
+= sizeof connect_index
;
319 memcpy (&listener_index
, s
, sizeof listener_index
);
320 s
+= sizeof listener_index
;
321 memcpy (&remote
.sin_port
, s
, sizeof remote
.sin_port
);
322 s
+= sizeof remote
.sin_port
;
323 memcpy (&local
.sin_port
, s
, sizeof local
.sin_port
);
324 s
+= sizeof local
.sin_port
;
325 memcpy (&remote
.sin_addr
, s
, sizeof remote
.sin_addr
);
326 s
+= sizeof remote
.sin_addr
;
327 memcpy (&local
.sin_addr
, s
, sizeof local
.sin_addr
);
328 s
+= sizeof local
.sin_addr
;
330 connect_index
= ntohl (connect_index
);
331 listener_index
= ntohl (listener_index
);
333 /* If this was a connect to a listener, then we just slap together
335 if (listener_index
!= -1) {
336 omapi_listener_object_t
*listener
;
337 listener
= (omapi_listener_object_t
*)0;
338 omapi_array_foreach_begin (trace_listeners
,
339 omapi_listener_object_t
, lp
) {
340 if (lp
-> address
.sin_port
== local
.sin_port
) {
341 omapi_listener_reference (&listener
, lp
, MDL
);
342 omapi_listener_dereference (&lp
, MDL
);
345 } omapi_array_foreach_end (trace_listeners
,
346 omapi_listener_object_t
, lp
);
348 log_error ("%s%ld, addr %s, port %d",
349 "Spurious traced listener connect - index ",
350 (long int)listener_index
,
351 inet_ntoa (local
.sin_addr
),
352 ntohs (local
.sin_port
));
355 obj
= (omapi_connection_object_t
*)0;
356 status
= omapi_listener_connect (&obj
, listener
, -1, &remote
);
357 if (status
!= ISC_R_SUCCESS
) {
358 log_error ("traced listener connect: %s",
359 isc_result_totext (status
));
362 omapi_connection_dereference (&obj
, MDL
);
363 omapi_listener_dereference (&listener
, MDL
);
367 /* Find the matching connect object, if there is one. */
368 omapi_array_foreach_begin (omapi_connections
,
369 omapi_connection_object_t
, lp
) {
370 for (i
= 0; (lp
-> connect_list
&&
371 i
< lp
-> connect_list
-> count
); i
++) {
372 if (!memcmp (&remote
.sin_addr
,
373 &lp
-> connect_list
-> addresses
[i
].address
,
374 sizeof remote
.sin_addr
) &&
375 (ntohs (remote
.sin_port
) ==
376 lp
-> connect_list
-> addresses
[i
].port
))
377 lp
-> state
= omapi_connection_connected
;
378 lp
-> remote_addr
= remote
;
379 lp
-> remote_addr
.sin_family
= AF_INET
;
380 #if defined (HAVE_SIN_LEN)
381 lp
-> remote_addr
.sin_len
= sizeof remote
;
383 omapi_addr_list_dereference (&lp
-> connect_list
, MDL
);
384 lp
-> index
= connect_index
;
385 status
= omapi_signal_in ((omapi_object_t
*)lp
,
387 omapi_connection_dereference (&lp
, MDL
);
390 } omapi_array_foreach_end (omapi_connections
,
391 omapi_connection_object_t
, lp
);
393 log_error ("Spurious traced connect - index %ld, addr %s, port %d",
394 (long int)connect_index
, inet_ntoa (remote
.sin_addr
),
395 ntohs (remote
.sin_port
));
399 static void trace_connect_stop (trace_type_t
*ttype
) { }
401 static void trace_disconnect_input (trace_type_t
*ttype
,
402 unsigned length
, char *buf
)
405 if (length
!= sizeof *index
) {
406 log_error ("trace disconnect: wrong length %d", length
);
410 index
= (int32_t *)buf
;
412 omapi_array_foreach_begin (omapi_connections
,
413 omapi_connection_object_t
, lp
) {
414 if (lp
-> index
== ntohl (*index
)) {
415 omapi_disconnect ((omapi_object_t
*)lp
, 1);
416 omapi_connection_dereference (&lp
, MDL
);
419 } omapi_array_foreach_end (omapi_connections
,
420 omapi_connection_object_t
, lp
);
422 log_error ("trace disconnect: no connection matching index %ld",
423 (long int)ntohl (*index
));
426 static void trace_disconnect_stop (trace_type_t
*ttype
) { }
429 /* Disconnect a connection object from the remote end. If force is nonzero,
430 close the connection immediately. Otherwise, shut down the receiving end
431 but allow any unsent data to be sent before actually closing the socket. */
433 isc_result_t
omapi_disconnect (omapi_object_t
*h
,
436 omapi_connection_object_t
*c
;
439 #ifdef DEBUG_PROTOCOL
440 log_debug ("omapi_disconnect(%s)", force
? "force" : "");
443 c
= (omapi_connection_object_t
*)h
;
444 if (c
-> type
!= omapi_type_connection
)
445 return ISC_R_INVALIDARG
;
447 #if defined (TRACING)
448 if (trace_record ()) {
451 index
= htonl (c
-> index
);
452 status
= trace_write_packet (trace_disconnect
,
453 sizeof index
, (char *)&index
,
455 if (status
!= ISC_R_SUCCESS
) {
457 log_error ("trace_write_packet: %s",
458 isc_result_totext (status
));
461 if (!trace_playback ()) {
464 /* If we're already disconnecting, we don't have to do
466 if (c
-> state
== omapi_connection_disconnecting
)
467 return ISC_R_SUCCESS
;
469 /* Try to shut down the socket - this sends a FIN to
470 the remote end, so that it won't send us any more
471 data. If the shutdown succeeds, and we still
472 have bytes left to write, defer closing the socket
473 until that's done. */
474 if (!shutdown (c
-> socket
, SHUT_RD
)) {
475 if (c
-> out_bytes
> 0) {
477 omapi_connection_disconnecting
;
478 return ISC_R_SUCCESS
;
483 #if defined (TRACING)
486 c
-> state
= omapi_connection_closed
;
488 /* Disconnect from I/O object, if any. */
490 if (h
-> outer
-> inner
)
491 omapi_object_dereference (&h
-> outer
-> inner
, MDL
);
492 omapi_object_dereference (&h
-> outer
, MDL
);
495 /* If whatever created us registered a signal handler, send it
496 a disconnect signal. */
497 omapi_signal (h
, "disconnect", h
);
498 return ISC_R_SUCCESS
;
501 isc_result_t
omapi_connection_require (omapi_object_t
*h
, unsigned bytes
)
503 omapi_connection_object_t
*c
;
505 if (h
-> type
!= omapi_type_connection
)
506 return ISC_R_INVALIDARG
;
507 c
= (omapi_connection_object_t
*)h
;
509 c
-> bytes_needed
= bytes
;
510 if (c
-> bytes_needed
<= c
-> in_bytes
) {
511 return ISC_R_SUCCESS
;
516 /* Return the socket on which the dispatcher should wait for readiness
517 to read, for a connection object. If we already have more bytes than
518 we need to do the next thing, and we have at least a single full input
519 buffer, then don't indicate that we're ready to read. */
520 int omapi_connection_readfd (omapi_object_t
*h
)
522 omapi_connection_object_t
*c
;
523 if (h
-> type
!= omapi_type_connection
)
525 c
= (omapi_connection_object_t
*)h
;
526 if (c
-> state
!= omapi_connection_connected
)
528 if (c
-> in_bytes
>= OMAPI_BUF_SIZE
- 1 &&
529 c
-> in_bytes
> c
-> bytes_needed
)
534 /* Return the socket on which the dispatcher should wait for readiness
535 to write, for a connection object. If there are no bytes buffered
536 for writing, then don't indicate that we're ready to write. */
537 int omapi_connection_writefd (omapi_object_t
*h
)
539 omapi_connection_object_t
*c
;
540 if (h
-> type
!= omapi_type_connection
)
542 c
= (omapi_connection_object_t
*)h
;
543 if (c
-> state
== omapi_connection_connecting
)
551 isc_result_t
omapi_connection_connect (omapi_object_t
*h
)
555 status
= omapi_connection_connect_internal (h
);
556 if (status
!= ISC_R_SUCCESS
)
557 omapi_signal (h
, "status", status
);
558 return ISC_R_SUCCESS
;
561 static isc_result_t
omapi_connection_connect_internal (omapi_object_t
*h
)
564 omapi_connection_object_t
*c
;
568 if (h
-> type
!= omapi_type_connection
)
569 return ISC_R_INVALIDARG
;
570 c
= (omapi_connection_object_t
*)h
;
572 if (c
-> state
== omapi_connection_connecting
) {
574 if (getsockopt (c
-> socket
, SOL_SOCKET
, SO_ERROR
,
575 (char *)&error
, &sl
) < 0) {
576 omapi_disconnect (h
, 1);
577 return ISC_R_SUCCESS
;
580 c
-> state
= omapi_connection_connected
;
582 if (c
-> state
== omapi_connection_connecting
||
583 c
-> state
== omapi_connection_unconnected
) {
584 if (c
-> cptr
>= c
-> connect_list
-> count
) {
587 status
= ISC_R_CONNREFUSED
;
590 status
= ISC_R_NETUNREACH
;
593 status
= uerr2isc (error
);
596 omapi_disconnect (h
, 1);
600 if (c
-> connect_list
-> addresses
[c
-> cptr
].addrtype
!=
602 omapi_disconnect (h
, 1);
603 return ISC_R_INVALIDARG
;
606 memset (&c
->remote_addr
, 0, sizeof c
->remote_addr
);
607 memcpy (&c
-> remote_addr
.sin_addr
,
608 &c
-> connect_list
-> addresses
[c
-> cptr
].address
,
609 sizeof c
-> remote_addr
.sin_addr
);
610 c
-> remote_addr
.sin_family
= AF_INET
;
611 c
-> remote_addr
.sin_port
=
612 htons (c
-> connect_list
-> addresses
[c
-> cptr
].port
);
613 #if defined (HAVE_SA_LEN)
614 c
-> remote_addr
.sin_len
= sizeof c
-> remote_addr
;
618 error
= connect (c
-> socket
,
619 (struct sockaddr
*)&c
-> remote_addr
,
620 sizeof c
-> remote_addr
);
623 if (error
!= EINPROGRESS
) {
624 omapi_disconnect (h
, 1);
627 status
= ISC_R_CONNREFUSED
;
630 status
= ISC_R_NETUNREACH
;
633 status
= uerr2isc (error
);
638 c
-> state
= omapi_connection_connecting
;
639 return ISC_R_INCOMPLETE
;
641 c
-> state
= omapi_connection_connected
;
644 /* I don't know why this would fail, so I'm tempted not to test
646 sl
= sizeof (c
-> local_addr
);
647 if (getsockname (c
-> socket
,
648 (struct sockaddr
*)&c
-> local_addr
, &sl
) < 0) {
651 /* Disconnect from I/O object, if any. */
653 omapi_unregister_io_object (h
);
655 status
= omapi_register_io_object (h
,
656 omapi_connection_readfd
,
657 omapi_connection_writefd
,
658 omapi_connection_reader
,
659 omapi_connection_writer
,
660 omapi_connection_reaper
);
662 if (status
!= ISC_R_SUCCESS
) {
663 omapi_disconnect (h
, 1);
667 omapi_signal_in (h
, "connect");
668 omapi_addr_list_dereference (&c
-> connect_list
, MDL
);
669 return ISC_R_SUCCESS
;
672 /* Reaper function for connection - if the connection is completely closed,
673 reap it. If it's in the disconnecting state, there were bytes left
674 to write when the user closed it, so if there are now no bytes left to
675 write, we can close it. */
676 isc_result_t
omapi_connection_reaper (omapi_object_t
*h
)
678 omapi_connection_object_t
*c
;
680 if (h
-> type
!= omapi_type_connection
)
681 return ISC_R_INVALIDARG
;
683 c
= (omapi_connection_object_t
*)h
;
684 if (c
-> state
== omapi_connection_disconnecting
&&
685 c
-> out_bytes
== 0) {
686 #ifdef DEBUG_PROTOCOL
687 log_debug ("omapi_connection_reaper(): disconnect");
689 omapi_disconnect (h
, 1);
691 if (c
-> state
== omapi_connection_closed
) {
692 #ifdef DEBUG_PROTOCOL
693 log_debug ("omapi_connection_reaper(): closed");
695 return ISC_R_NOTCONNECTED
;
697 return ISC_R_SUCCESS
;
700 static isc_result_t
make_dst_key (DST_KEY
**dst_key
, omapi_object_t
*a
) {
701 omapi_value_t
*name
= (omapi_value_t
*)0;
702 omapi_value_t
*algorithm
= (omapi_value_t
*)0;
703 omapi_value_t
*key
= (omapi_value_t
*)0;
704 int algorithm_id
= UNKNOWN_KEYALG
;
705 char *name_str
= NULL
;
706 isc_result_t status
= ISC_R_SUCCESS
;
708 if (status
== ISC_R_SUCCESS
)
709 status
= omapi_get_value_str
710 (a
, (omapi_object_t
*)0, "name", &name
);
712 if (status
== ISC_R_SUCCESS
)
713 status
= omapi_get_value_str
714 (a
, (omapi_object_t
*)0, "algorithm", &algorithm
);
716 if (status
== ISC_R_SUCCESS
)
717 status
= omapi_get_value_str
718 (a
, (omapi_object_t
*)0, "key", &key
);
720 if (status
== ISC_R_SUCCESS
) {
721 if ((algorithm
-> value
-> type
== omapi_datatype_data
||
722 algorithm
-> value
-> type
== omapi_datatype_string
) &&
723 strncasecmp ((char *)algorithm
-> value
-> u
.buffer
.value
,
724 NS_TSIG_ALG_HMAC_MD5
".",
725 algorithm
-> value
-> u
.buffer
.len
) == 0) {
726 algorithm_id
= KEY_HMAC_MD5
;
728 status
= ISC_R_INVALIDARG
;
732 if (status
== ISC_R_SUCCESS
) {
733 name_str
= dmalloc (name
-> value
-> u
.buffer
.len
+ 1, MDL
);
735 status
= ISC_R_NOMEMORY
;
738 if (status
== ISC_R_SUCCESS
) {
740 name
-> value
-> u
.buffer
.value
,
741 name
-> value
-> u
.buffer
.len
);
742 name_str
[name
-> value
-> u
.buffer
.len
] = 0;
744 *dst_key
= dst_buffer_to_key (name_str
, algorithm_id
, 0, 0,
745 key
-> value
-> u
.buffer
.value
,
746 key
-> value
-> u
.buffer
.len
);
748 status
= ISC_R_NOMEMORY
;
752 dfree (name_str
, MDL
);
754 omapi_value_dereference (&key
, MDL
);
756 omapi_value_dereference (&algorithm
, MDL
);
758 omapi_value_dereference (&name
, MDL
);
763 isc_result_t
omapi_connection_sign_data (int mode
,
766 const unsigned char *data
,
768 omapi_typed_data_t
**result
)
770 omapi_typed_data_t
*td
= (omapi_typed_data_t
*)0;
774 if (mode
& SIG_MODE_FINAL
) {
775 status
= omapi_typed_data_new (MDL
, &td
,
778 if (status
!= ISC_R_SUCCESS
)
782 r
= dst_sign_data (mode
, key
, context
, data
, len
,
783 td
? td
-> u
.buffer
.value
: (u_char
*)0,
784 td
? td
-> u
.buffer
.len
: 0);
786 /* dst_sign_data() really should do this for us, shouldn't it? */
787 if (mode
& SIG_MODE_FINAL
)
788 *context
= (void *)0;
792 omapi_typed_data_dereference (&td
, MDL
);
793 return ISC_R_INVALIDKEY
;
797 omapi_typed_data_reference (result
, td
, MDL
);
801 omapi_typed_data_dereference (&td
, MDL
);
803 return ISC_R_SUCCESS
;
806 isc_result_t
omapi_connection_output_auth_length (omapi_object_t
*h
,
809 omapi_connection_object_t
*c
;
811 if (h
-> type
!= omapi_type_connection
)
812 return ISC_R_INVALIDARG
;
813 c
= (omapi_connection_object_t
*)h
;
816 return ISC_R_NOTFOUND
;
818 *l
= dst_sig_size (c
-> out_key
);
819 return ISC_R_SUCCESS
;
822 isc_result_t
omapi_connection_set_value (omapi_object_t
*h
,
824 omapi_data_string_t
*name
,
825 omapi_typed_data_t
*value
)
827 omapi_connection_object_t
*c
;
830 if (h
-> type
!= omapi_type_connection
)
831 return ISC_R_INVALIDARG
;
832 c
= (omapi_connection_object_t
*)h
;
834 if (omapi_ds_strcmp (name
, "input-authenticator") == 0) {
835 if (value
&& value
-> type
!= omapi_datatype_object
)
836 return ISC_R_INVALIDARG
;
838 if (c
-> in_context
) {
839 omapi_connection_sign_data (SIG_MODE_FINAL
,
843 (omapi_typed_data_t
**) 0);
847 dst_free_key (c
-> in_key
);
848 c
-> in_key
= (DST_KEY
*)0;
852 status
= make_dst_key (&c
-> in_key
,
854 if (status
!= ISC_R_SUCCESS
)
858 return ISC_R_SUCCESS
;
860 else if (omapi_ds_strcmp (name
, "output-authenticator") == 0) {
861 if (value
&& value
-> type
!= omapi_datatype_object
)
862 return ISC_R_INVALIDARG
;
864 if (c
-> out_context
) {
865 omapi_connection_sign_data (SIG_MODE_FINAL
,
869 (omapi_typed_data_t
**) 0);
873 dst_free_key (c
-> out_key
);
874 c
-> out_key
= (DST_KEY
*)0;
878 status
= make_dst_key (&c
-> out_key
,
880 if (status
!= ISC_R_SUCCESS
)
884 return ISC_R_SUCCESS
;
887 if (h
-> inner
&& h
-> inner
-> type
-> set_value
)
888 return (*(h
-> inner
-> type
-> set_value
))
889 (h
-> inner
, id
, name
, value
);
890 return ISC_R_NOTFOUND
;
893 isc_result_t
omapi_connection_get_value (omapi_object_t
*h
,
895 omapi_data_string_t
*name
,
896 omapi_value_t
**value
)
898 omapi_connection_object_t
*c
;
899 omapi_typed_data_t
*td
= (omapi_typed_data_t
*)0;
902 if (h
-> type
!= omapi_type_connection
)
903 return ISC_R_INVALIDARG
;
904 c
= (omapi_connection_object_t
*)h
;
906 if (omapi_ds_strcmp (name
, "input-signature") == 0) {
907 if (!c
-> in_key
|| !c
-> in_context
)
908 return ISC_R_NOTFOUND
;
910 status
= omapi_connection_sign_data (SIG_MODE_FINAL
,
914 if (status
!= ISC_R_SUCCESS
)
917 status
= omapi_make_value (value
, name
, td
, MDL
);
918 omapi_typed_data_dereference (&td
, MDL
);
921 } else if (omapi_ds_strcmp (name
, "input-signature-size") == 0) {
923 return ISC_R_NOTFOUND
;
925 return omapi_make_int_value (value
, name
,
926 dst_sig_size (c
-> in_key
), MDL
);
928 } else if (omapi_ds_strcmp (name
, "output-signature") == 0) {
929 if (!c
-> out_key
|| !c
-> out_context
)
930 return ISC_R_NOTFOUND
;
932 status
= omapi_connection_sign_data (SIG_MODE_FINAL
,
936 if (status
!= ISC_R_SUCCESS
)
939 status
= omapi_make_value (value
, name
, td
, MDL
);
940 omapi_typed_data_dereference (&td
, MDL
);
943 } else if (omapi_ds_strcmp (name
, "output-signature-size") == 0) {
945 return ISC_R_NOTFOUND
;
947 return omapi_make_int_value (value
, name
,
948 dst_sig_size (c
-> out_key
), MDL
);
951 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
952 return (*(h
-> inner
-> type
-> get_value
))
953 (h
-> inner
, id
, name
, value
);
954 return ISC_R_NOTFOUND
;
957 isc_result_t
omapi_connection_destroy (omapi_object_t
*h
,
958 const char *file
, int line
)
960 omapi_connection_object_t
*c
;
962 #ifdef DEBUG_PROTOCOL
963 log_debug ("omapi_connection_destroy()");
966 if (h
-> type
!= omapi_type_connection
)
967 return ISC_R_UNEXPECTED
;
968 c
= (omapi_connection_object_t
*)(h
);
969 if (c
-> state
== omapi_connection_connected
)
970 omapi_disconnect (h
, 1);
972 omapi_listener_dereference (&c
-> listener
, file
, line
);
973 if (c
-> connect_list
)
974 omapi_addr_list_dereference (&c
-> connect_list
, file
, line
);
975 return ISC_R_SUCCESS
;
978 isc_result_t
omapi_connection_signal_handler (omapi_object_t
*h
,
979 const char *name
, va_list ap
)
981 if (h
-> type
!= omapi_type_connection
)
982 return ISC_R_INVALIDARG
;
984 #ifdef DEBUG_PROTOCOL
985 log_debug ("omapi_connection_signal_handler(%s)", name
);
988 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
989 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
991 return ISC_R_NOTFOUND
;
994 /* Write all the published values associated with the object through the
995 specified connection. */
997 isc_result_t
omapi_connection_stuff_values (omapi_object_t
*c
,
1002 if (m
-> type
!= omapi_type_connection
)
1003 return ISC_R_INVALIDARG
;
1005 if (m
-> inner
&& m
-> inner
-> type
-> stuff_values
)
1006 return (*(m
-> inner
-> type
-> stuff_values
)) (c
, id
,
1008 return ISC_R_SUCCESS
;