3 Functions supporting the object management protocol... */
6 * Copyright (c) 1999-2000 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>
46 OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
48 OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
49 omapi_type_protocol_listener)
51 isc_result_t omapi_protocol_connect (omapi_object_t *h,
52 const char *server_name,
56 isc_result_t rstatus, status;
57 omapi_protocol_object_t *obj;
60 log_debug ("omapi_protocol_connect(%s port=%d)", server_name, port);
63 obj = (omapi_protocol_object_t *)0;
64 status = omapi_protocol_allocate (&obj, MDL);
65 if (status != ISC_R_SUCCESS)
68 rstatus = omapi_connect ((omapi_object_t *)obj, server_name, port);
69 if (rstatus != ISC_R_SUCCESS && rstatus != ISC_R_INCOMPLETE) {
70 omapi_protocol_dereference (&obj, MDL);
73 status = omapi_object_reference (&h -> outer,
74 (omapi_object_t *)obj, MDL);
75 if (status != ISC_R_SUCCESS) {
76 omapi_protocol_dereference (&obj, MDL);
79 status = omapi_object_reference (&obj -> inner, h, MDL);
80 if (status != ISC_R_SUCCESS) {
81 omapi_protocol_dereference (&obj, MDL);
85 /* If we were passed a default authenticator, store it now. We'll
86 open it once we're connected. */
89 dmalloc (sizeof(omapi_remote_auth_t), MDL);
90 if (!obj -> default_auth) {
91 omapi_protocol_dereference (&obj, MDL);
92 return ISC_R_NOMEMORY;
95 obj -> default_auth -> next = (omapi_remote_auth_t *)0;
96 status = omapi_object_reference (&obj -> default_auth -> a,
98 if (status != ISC_R_SUCCESS) {
99 dfree (obj -> default_auth, MDL);
100 omapi_protocol_dereference (&obj, MDL);
105 rstatus = ISC_R_INCOMPLETE;
109 status = ISC_R_SUCCESS;
113 omapi_protocol_dereference (&obj, MDL);
117 /* Send the protocol introduction message. */
118 isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
123 omapi_protocol_object_t *p;
125 #ifdef DEBUG_PROTOCOL
126 log_debug ("omapi_protocol_send_intro()");
129 if (h -> type != omapi_type_protocol)
130 return ISC_R_INVALIDARG;
131 p = (omapi_protocol_object_t *)h;
133 if (!h -> outer || h -> outer -> type != omapi_type_connection)
134 return ISC_R_NOTCONNECTED;
136 status = omapi_connection_put_uint32 (h -> outer, ver);
137 if (status != ISC_R_SUCCESS)
140 status = omapi_connection_put_uint32 (h -> outer, hsize);
142 if (status != ISC_R_SUCCESS)
145 /* Require the other end to send an intro - this kicks off the
146 protocol input state machine. */
147 p -> state = omapi_protocol_intro_wait;
148 status = omapi_connection_require (h -> outer, 8);
149 if (status != ISC_R_SUCCESS && status != ISC_R_NOTYET)
152 /* Make up an initial transaction ID for this connection. */
153 p -> next_xid = random ();
154 return ISC_R_SUCCESS;
157 isc_result_t omapi_protocol_send_message (omapi_object_t *po,
162 omapi_protocol_object_t *p;
164 omapi_message_object_t *m, *om;
165 omapi_remote_auth_t *ra;
166 omapi_value_t *signature;
171 if (po -> type != omapi_type_protocol ||
172 !po -> outer || po -> outer -> type != omapi_type_connection ||
173 mo -> type != omapi_type_message)
174 return ISC_R_INVALIDARG;
175 if (omo && omo -> type != omapi_type_message)
176 return ISC_R_INVALIDARG;
177 p = (omapi_protocol_object_t *)po;
178 c = (omapi_object_t *)(po -> outer);
179 m = (omapi_message_object_t *)mo;
180 om = (omapi_message_object_t *)omo;
182 #ifdef DEBUG_PROTOCOL
183 log_debug ("omapi_protocol_send_message()"
184 "op=%ld handle=%#lx id=%#lx rid=%#lx",
186 (long)(m -> object ? m -> object -> handle : m -> handle),
187 (long)p -> next_xid, (long)m -> rid);
190 /* Find the authid to use for this message. */
192 for (ra = p -> remote_auth_list; ra; ra = ra -> next) {
199 return ISC_R_KEY_UNKNOWN;
200 } else if (p -> remote_auth_list) {
201 ra = p -> default_auth;
203 ra = (omapi_remote_auth_t *)0;
207 m -> authid = ra -> remote_handle;
208 status = omapi_object_reference (&m -> id_object,
210 if (status != ISC_R_SUCCESS)
214 /* Write the ID of the authentication key we're using. */
215 status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0);
216 if (status != ISC_R_SUCCESS) {
217 omapi_disconnect (c, 1);
221 /* Activate the authentication key on the connection. */
224 status = omapi_set_object_value (c, (omapi_object_t *)0,
225 "output-authenticator",
227 if (status != ISC_R_SUCCESS) {
228 omapi_disconnect (c, 1);
232 status = omapi_connection_output_auth_length (c, &auth_len);
233 if (status != ISC_R_SUCCESS) {
234 omapi_disconnect (c, 1);
239 /* Write the authenticator length */
240 status = omapi_connection_put_uint32 (c, auth_len);
241 if (status != ISC_R_SUCCESS) {
242 omapi_disconnect (c, 1);
246 /* Write the opcode. */
247 status = omapi_connection_put_uint32 (c, m -> op);
248 if (status != ISC_R_SUCCESS) {
249 omapi_disconnect (c, 1);
253 /* Write the handle. If we've been given an explicit handle, use
254 that. Otherwise, use the handle of the object we're sending.
255 The caller is responsible for arranging for one of these handles
256 to be set (or not). */
257 status = omapi_connection_put_uint32 (c, (m -> h
260 ? m -> object -> handle
262 if (status != ISC_R_SUCCESS) {
263 omapi_disconnect (c, 1);
267 /* Set and write the transaction ID. */
268 m -> id = p -> next_xid++;
269 status = omapi_connection_put_uint32 (c, m -> id);
270 if (status != ISC_R_SUCCESS) {
271 omapi_disconnect (c, 1);
275 /* Write the transaction ID of the message to which this is a
276 response, if there is such a message. */
277 status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
278 if (status != ISC_R_SUCCESS) {
279 omapi_disconnect (c, 1);
283 /* Stuff out the name/value pairs specific to this message. */
284 status = omapi_stuff_values (c, id, (omapi_object_t *)m);
285 if (status != ISC_R_SUCCESS) {
286 omapi_disconnect (c, 1);
290 /* Write the zero-length name that terminates the list of name/value
291 pairs specific to the message. */
292 status = omapi_connection_put_uint16 (c, 0);
293 if (status != ISC_R_SUCCESS) {
294 omapi_disconnect (c, 1);
298 /* Stuff out all the published name/value pairs in the object that's
299 being sent in the message, if there is one. */
301 status = omapi_stuff_values (c, id, m -> object);
302 if (status != ISC_R_SUCCESS) {
303 omapi_disconnect (c, 1);
308 /* Write the zero-length name that terminates the list of name/value
309 pairs for the associated object. */
310 status = omapi_connection_put_uint16 (c, 0);
311 if (status != ISC_R_SUCCESS) {
312 omapi_disconnect (c, 1);
317 /* Calculate the message signature. */
318 signature = (omapi_value_t *)0;
319 status = omapi_get_value_str (c, (omapi_object_t *)0,
320 "output-signature", &signature);
321 if (status != ISC_R_SUCCESS) {
322 omapi_disconnect (c, 1);
326 /* Write the authenticator... */
327 status = (omapi_connection_copyin
328 (c, signature -> value -> u.buffer.value,
329 signature -> value -> u.buffer.len));
330 omapi_value_dereference (&signature, MDL);
331 if (status != ISC_R_SUCCESS) {
332 omapi_disconnect (c, 1);
336 /* Dectivate the authentication key on the connection. */
337 status = omapi_set_value_str (c, (omapi_object_t *)0,
338 "output-authenticator",
339 (omapi_typed_data_t *)0);
340 if (status != ISC_R_SUCCESS) {
341 omapi_disconnect (c, 1);
347 omapi_protocol_reference (&m -> protocol_object, p, MDL);
349 return ISC_R_SUCCESS;
353 isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
354 const char *name, va_list ap)
357 omapi_protocol_object_t *p;
359 omapi_message_object_t *m;
360 omapi_value_t *signature;
364 #if defined (DEBUG_MEMORY_LEAKAGE)
365 unsigned long previous_outstanding = 0xDEADBEEF;
366 unsigned long connect_outstanding = 0xDEADBEEF;
369 if (h -> type != omapi_type_protocol) {
370 /* XXX shouldn't happen. Put an assert here? */
371 return ISC_R_UNEXPECTED;
373 p = (omapi_protocol_object_t *)h;
375 if (!strcmp (name, "connect")) {
376 #if defined (DEBUG_MEMORY_LEAKAGE)
377 connect_outstanding = dmalloc_outstanding;
379 /* Send the introductory message. */
380 status = omapi_protocol_send_intro
381 (h, OMAPI_PROTOCOL_VERSION,
382 sizeof (omapi_protocol_header_t));
383 if (status != ISC_R_SUCCESS) {
384 omapi_disconnect (p -> outer, 1);
387 return ISC_R_SUCCESS;
390 /* Should only receive these when opening the initial authenticator. */
391 if (!strcmp (name, "status")) {
392 status = va_arg (ap, isc_result_t);
393 if (status != ISC_R_SUCCESS) {
394 omapi_signal_in (h -> inner, "status", status,
395 (omapi_object_t *)0);
396 omapi_disconnect (p -> outer, 1);
399 return omapi_signal_in (h -> inner, "ready");
403 /* If we get a disconnect, dump memory usage. */
404 if (!strcmp (name, "disconnect")) {
405 #if defined (DEBUG_MEMORY_LEAKAGE)
406 if (connect_outstanding != 0xDEADBEEF) {
407 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
409 dmalloc_outstanding - previous_outstanding,
410 dmalloc_outstanding, dmalloc_longterm, " long-term");
413 #if defined (DEBUG_MEMORY_LEAKAGE)
414 dmalloc_dump_outstanding ();
416 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
419 for (m = omapi_registered_messages; m; m = m -> next) {
420 if (m -> protocol_object == p) {
422 omapi_signal (m -> object, "disconnect");
427 /* Not a signal we recognize? */
428 if (strcmp (name, "ready")) {
429 if (p -> inner && p -> inner -> type -> signal_handler)
430 return (*(p -> inner -> type -> signal_handler)) (h,
433 return ISC_R_NOTFOUND;
436 if (!p -> outer || p -> outer -> type != omapi_type_connection)
437 return ISC_R_INVALIDARG;
440 /* We get here because we requested that we be woken up after
441 some number of bytes were read, and that number of bytes
442 has in fact been read. */
443 switch (p -> state) {
444 case omapi_protocol_intro_wait:
445 /* Get protocol version and header size in network
447 omapi_connection_get_uint32 (c, &p -> protocol_version);
448 omapi_connection_get_uint32 (c, &p -> header_size);
450 /* We currently only support the current protocol version. */
451 if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
452 omapi_disconnect (c, 1);
453 return ISC_R_VERSIONMISMATCH;
456 if (p -> header_size < sizeof (omapi_protocol_header_t)) {
457 omapi_disconnect (c, 1);
458 return ISC_R_PROTOCOLERROR;
461 if (p -> default_auth) {
462 status = omapi_protocol_send_open
463 (h, (omapi_object_t *)0, "authenticator",
464 p -> default_auth -> a,
465 OMAPI_NOTIFY_PROTOCOL);
466 if (status != ISC_R_SUCCESS) {
467 omapi_disconnect (c, 1);
471 status = omapi_signal_in (h -> inner, "ready");
475 /* The next thing we're expecting is a message header. */
476 p -> state = omapi_protocol_header_wait;
478 /* Register a need for the number of bytes in a
479 header, and if we already have that many, process
481 if ((omapi_connection_require (c, p -> header_size)) !=
484 /* If we already have the data, fall through. */
486 case omapi_protocol_header_wait:
487 #if defined (DEBUG_MEMORY_LEAKAGE)
488 if (previous_outstanding != 0xDEADBEEF) {
489 log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
490 "generation", dmalloc_generation,
491 dmalloc_outstanding - previous_outstanding,
492 dmalloc_outstanding, dmalloc_longterm,
495 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
496 dmalloc_dump_outstanding ();
498 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
501 #if defined (DEBUG_MEMORY_LEAKAGE)
503 previous_outstanding = dmalloc_outstanding;
505 status = omapi_message_new ((omapi_object_t **)&p -> message,
507 if (status != ISC_R_SUCCESS) {
508 omapi_disconnect (c, 1);
512 p -> verify_result = ISC_R_SUCCESS;
514 /* Swap in the header... */
515 omapi_connection_get_uint32 (c, &p -> message -> authid);
517 /* Bind the authenticator to the message object. */
518 if (p -> message -> authid) {
519 status = (omapi_protocol_lookup_auth
520 (&p -> message -> id_object, h,
521 p -> message -> authid));
522 if (status != ISC_R_SUCCESS)
523 p -> verify_result = status;
525 /* Activate the authentication key. */
526 status = omapi_set_object_value
527 (c, (omapi_object_t *)0, "input-authenticator",
528 p -> message -> id_object);
529 if (status != ISC_R_SUCCESS) {
530 omapi_disconnect (c, 1);
535 omapi_connection_get_uint32 (c, &p -> message -> authlen);
536 omapi_connection_get_uint32 (c, &p -> message -> op);
537 omapi_connection_get_uint32 (c, &th);
538 p -> message -> h = th;
539 omapi_connection_get_uint32 (c, &p -> message -> id);
540 omapi_connection_get_uint32 (c, &p -> message -> rid);
542 /* If there was any extra header data, skip over it. */
543 if (p -> header_size > sizeof (omapi_protocol_header_t)) {
544 omapi_connection_copyout
545 (0, c, (p -> header_size -
546 sizeof (omapi_protocol_header_t)));
549 /* XXX must compute partial signature across the
550 XXX preceding bytes. Also, if authenticator
551 specifies encryption as well as signing, we may
552 have to decrypt the data on the way in. */
554 /* First we read in message-specific values, then object
556 p -> reading_message_values = 1;
559 /* The next thing we're expecting is length of the
561 p -> state = omapi_protocol_name_length_wait;
563 /* Wait for a 16-bit length. */
564 if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
566 /* If it's already here, fall through. */
568 case omapi_protocol_name_length_wait:
569 omapi_connection_get_uint16 (c, &nlen);
570 /* A zero-length name means that we're done reading name+value
573 /* If we've already read in the object, we are
574 done reading the message, but if we've just
575 finished reading in the values associated
576 with the message, we need to read the
578 if (p -> reading_message_values) {
579 p -> reading_message_values = 0;
580 goto need_name_length;
583 /* If the authenticator length is zero, there's no
584 signature to read in, so go straight to processing
586 if (p -> message -> authlen == 0)
589 /* The next thing we're expecting is the
590 message signature. */
591 p -> state = omapi_protocol_signature_wait;
593 /* Wait for the number of bytes specified for
594 the authenticator. If we already have it,
596 if (omapi_connection_require
597 (c, p -> message -> authlen) == ISC_R_SUCCESS)
602 /* Allocate a buffer for the name. */
603 status = (omapi_data_string_new (&p -> name, nlen, MDL));
604 if (status != ISC_R_SUCCESS) {
605 omapi_disconnect (c, 1);
606 return ISC_R_NOMEMORY;
608 p -> state = omapi_protocol_name_wait;
609 if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
611 /* If it's already here, fall through. */
613 case omapi_protocol_name_wait:
614 omapi_connection_copyout (p -> name -> value, c,
616 /* Wait for a 32-bit length. */
617 p -> state = omapi_protocol_value_length_wait;
618 if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
620 /* If it's already here, fall through. */
622 case omapi_protocol_value_length_wait:
623 omapi_connection_get_uint32 (c, &vlen);
625 /* Zero-length values are allowed - if we get one, we
626 don't have to read any data for the value - just
627 get the next one, if there is a next one. */
629 goto insert_new_value;
631 status = omapi_typed_data_new (MDL, &p -> value,
634 if (status != ISC_R_SUCCESS) {
635 omapi_disconnect (c, 1);
636 return ISC_R_NOMEMORY;
639 p -> state = omapi_protocol_value_wait;
640 if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
642 /* If it's already here, fall through. */
644 case omapi_protocol_value_wait:
645 omapi_connection_copyout (p -> value -> u.buffer.value, c,
646 p -> value -> u.buffer.len);
649 if (p -> reading_message_values) {
650 status = (omapi_set_value
651 ((omapi_object_t *)p -> message,
652 p -> message -> id_object,
653 p -> name, p -> value));
655 if (!p -> message -> object) {
656 /* We need a generic object to hang off of the
658 status = (omapi_generic_new
659 (&p -> message -> object, MDL));
660 if (status != ISC_R_SUCCESS) {
661 omapi_disconnect (c, 1);
665 status = (omapi_set_value
666 ((omapi_object_t *)p -> message -> object,
667 p -> message -> id_object,
668 p -> name, p -> value));
670 if (status != ISC_R_SUCCESS) {
671 omapi_disconnect (c, 1);
674 omapi_data_string_dereference (&p -> name, MDL);
676 omapi_typed_data_dereference (&p -> value, MDL);
677 goto need_name_length;
680 case omapi_protocol_signature_wait:
681 if (p -> message -> id_object) {
682 /* Compute the signature of the message. */
683 signature = (omapi_value_t *)0;
684 status = omapi_get_value_str (c, (omapi_object_t *)0,
687 if (status != ISC_R_SUCCESS) {
688 omapi_disconnect (c, 1);
692 /* Disable the authentication key on the connection. */
693 status = omapi_set_value_str (c, (omapi_object_t *)0,
694 "input-authenticator",
695 (omapi_typed_data_t *)0);
696 if (status != ISC_R_SUCCESS) {
697 omapi_value_dereference (&signature, MDL);
698 omapi_disconnect (c, 1);
703 /* Read the authenticator. */
704 status = omapi_typed_data_new (MDL,
705 &p -> message -> authenticator,
707 p -> message -> authlen);
709 if (status != ISC_R_SUCCESS) {
710 omapi_value_dereference (&signature, MDL);
711 omapi_disconnect (c, 1);
712 return ISC_R_NOMEMORY;
714 omapi_connection_copyout
715 (p -> message -> authenticator -> u.buffer.value, c,
716 p -> message -> authlen);
718 /* Verify the signature. */
719 if (p -> message -> id_object &&
720 ((signature -> value -> u.buffer.len !=
721 p -> message -> authlen) ||
722 (memcmp (signature -> value -> u.buffer.value,
723 p -> message -> authenticator -> u.buffer.value,
724 p -> message -> authlen) != 0))) {
725 /* Invalid signature. */
726 p -> verify_result = ISC_R_INVALIDKEY;
729 omapi_value_dereference (&signature, MDL);
731 /* Process the message. */
733 if (p -> verify_result != ISC_R_SUCCESS) {
734 status = omapi_protocol_send_status
735 (h, (omapi_object_t *)0, p -> verify_result,
736 p -> message -> id, (char *)0);
738 status = omapi_message_process
739 ((omapi_object_t *)p -> message, h);
741 if (status != ISC_R_SUCCESS) {
742 omapi_disconnect (c, 1);
743 return ISC_R_NOMEMORY;
746 omapi_message_dereference (&p -> message, MDL);
747 #if defined (DEBUG_MEMORY_LEAKAGE)
748 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
750 dmalloc_outstanding - previous_outstanding,
751 dmalloc_outstanding, dmalloc_longterm, " long-term");
753 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
754 dmalloc_dump_outstanding ();
756 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
759 #if defined (DEBUG_MEMORY_LEAKAGE)
760 previous_outstanding = 0xDEADBEEF;
762 /* Now wait for the next message. */
766 /* XXX should never get here. Assertion? */
769 return ISC_R_SUCCESS;
772 isc_result_t omapi_protocol_add_auth (omapi_object_t *po,
774 omapi_handle_t handle)
776 omapi_protocol_object_t *p;
777 omapi_remote_auth_t *r;
780 if (ao -> type != omapi_type_auth_key &&
781 (!ao -> inner || ao -> inner -> type != omapi_type_auth_key))
782 return ISC_R_INVALIDARG;
784 if (po -> type != omapi_type_protocol)
785 return ISC_R_INVALIDARG;
786 p = (omapi_protocol_object_t *)po;
788 #ifdef DEBUG_PROTOCOL
789 log_debug ("omapi_protocol_add_auth(name=%s)",
790 ((omapi_auth_key_t *)ao) -> name);
793 if (p -> verify_auth) {
794 status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao);
795 if (status != ISC_R_SUCCESS)
799 /* If omapi_protocol_connect() was called with a default
800 authenticator, p -> default_auth will already be set,
801 but p -> remote_auth_list will not yet be initialized. */
802 if (p -> default_auth && !p -> remote_auth_list) {
803 if (p -> default_auth -> a != ao) {
804 /* Something just went horribly wrong. */
805 omapi_disconnect (p -> outer, 1);
806 return ISC_R_UNEXPECTED;
809 p -> remote_auth_list = p -> default_auth;
810 p -> default_auth -> remote_handle = handle;
812 return omapi_signal_in (p -> inner, "ready");
815 r = dmalloc (sizeof(*r), MDL);
817 return ISC_R_NOMEMORY;
819 status = omapi_object_reference (&r -> a, ao, MDL);
820 if (status != ISC_R_SUCCESS) {
825 r -> remote_handle = handle;
826 r -> next = p -> remote_auth_list;
827 p -> remote_auth_list = r;
829 return ISC_R_SUCCESS;
832 isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a,
834 omapi_handle_t handle)
836 omapi_protocol_object_t *p;
837 omapi_remote_auth_t *r;
839 if (po -> type != omapi_type_protocol)
840 return ISC_R_INVALIDARG;
841 p = (omapi_protocol_object_t *)po;
843 for (r = p -> remote_auth_list; r; r = r -> next)
844 if (r -> remote_handle == handle)
845 return omapi_object_reference (a, r -> a, MDL);
847 return ISC_R_KEY_UNKNOWN;
850 isc_result_t omapi_protocol_set_value (omapi_object_t *h,
852 omapi_data_string_t *name,
853 omapi_typed_data_t *value)
855 omapi_protocol_object_t *p;
856 omapi_remote_auth_t *r;
858 if (h -> type != omapi_type_protocol)
859 return ISC_R_INVALIDARG;
860 p = (omapi_protocol_object_t *)h;
862 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
863 if (value -> type != omapi_datatype_object)
864 return ISC_R_INVALIDARG;
866 if (!value || !value -> u.object) {
867 p -> default_auth = (omapi_remote_auth_t *)0;
869 for (r = p -> remote_auth_list; r; r = r -> next)
870 if (r -> a == value -> u.object)
874 return ISC_R_KEY_UNKNOWN;
876 p -> default_auth = r;
879 return ISC_R_SUCCESS;
882 if (h -> inner && h -> inner -> type -> set_value)
883 return (*(h -> inner -> type -> set_value))
884 (h -> inner, id, name, value);
885 return ISC_R_NOTFOUND;
888 isc_result_t omapi_protocol_get_value (omapi_object_t *h,
890 omapi_data_string_t *name,
891 omapi_value_t **value)
893 omapi_protocol_object_t *p;
895 if (h -> type != omapi_type_protocol)
896 return ISC_R_INVALIDARG;
897 p = (omapi_protocol_object_t *)h;
899 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
900 if (!p -> default_auth)
901 return ISC_R_NOTFOUND;
903 return omapi_make_object_value (value, name,
904 p -> default_auth -> a, MDL);
907 if (h -> inner && h -> inner -> type -> get_value)
908 return (*(h -> inner -> type -> get_value))
909 (h -> inner, id, name, value);
910 return ISC_R_NOTFOUND;
913 isc_result_t omapi_protocol_destroy (omapi_object_t *h,
914 const char *file, int line)
916 omapi_protocol_object_t *p;
917 if (h -> type != omapi_type_protocol)
918 return ISC_R_INVALIDARG;
919 p = (omapi_protocol_object_t *)h;
921 omapi_message_dereference (&p -> message, file, line);
923 /* This will happen if: 1) A default authenticator is supplied to
924 omapi_protocol_connect(), and 2) something goes wrong before
925 the authenticator can be opened. */
926 if (p -> default_auth && !p -> remote_auth_list)
927 dfree (p -> default_auth, file, line);
929 while (p -> remote_auth_list) {
930 omapi_remote_auth_t *r = p -> remote_auth_list -> next;
931 p -> remote_auth_list = r;
933 omapi_object_dereference (&r -> a, file, line);
934 dfree (r, file, line);
937 return ISC_R_SUCCESS;
940 /* Write all the published values associated with the object through the
941 specified connection. */
943 isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
949 if (p -> type != omapi_type_protocol)
950 return ISC_R_INVALIDARG;
952 if (p -> inner && p -> inner -> type -> stuff_values)
953 return (*(p -> inner -> type -> stuff_values)) (c, id,
955 return ISC_R_SUCCESS;
958 /* Returns a boolean indicating whether this protocol requires that
959 messages be authenticated or not. */
961 isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h)
963 if (h -> type != omapi_type_protocol)
964 return isc_boolean_false;
965 if (((omapi_protocol_object_t *)h) -> insecure)
966 return isc_boolean_false;
968 return isc_boolean_true;
971 /* Sets the address and authenticator verification callbacks. The handle
972 is to a listener object, not a protocol object. */
974 isc_result_t omapi_protocol_configure_security (omapi_object_t *h,
975 isc_result_t (*verify_addr)
978 isc_result_t (*verify_auth)
982 omapi_protocol_listener_object_t *l;
984 if (h -> outer && h -> outer -> type == omapi_type_protocol_listener)
987 if (h -> type != omapi_type_protocol_listener)
988 return ISC_R_INVALIDARG;
989 l = (omapi_protocol_listener_object_t *)h;
991 l -> verify_auth = verify_auth;
994 return omapi_listener_configure_security (h -> outer, verify_addr);
998 /* Set up a listener for the omapi protocol. The handle stored points to
999 a listener object, not a protocol object. */
1001 isc_result_t omapi_protocol_listen (omapi_object_t *h,
1005 isc_result_t status;
1006 omapi_protocol_listener_object_t *obj;
1008 obj = (omapi_protocol_listener_object_t *)0;
1009 status = omapi_protocol_listener_allocate (&obj, MDL);
1010 if (status != ISC_R_SUCCESS)
1013 status = omapi_object_reference (&h -> outer,
1014 (omapi_object_t *)obj, MDL);
1015 if (status != ISC_R_SUCCESS) {
1016 omapi_protocol_listener_dereference (&obj, MDL);
1019 status = omapi_object_reference (&obj -> inner, h, MDL);
1020 if (status != ISC_R_SUCCESS) {
1021 omapi_protocol_listener_dereference (&obj, MDL);
1025 /* What a terrible default. */
1026 obj -> insecure = 1;
1028 status = omapi_listen ((omapi_object_t *)obj, port, max);
1029 omapi_protocol_listener_dereference (&obj, MDL);
1033 /* Signal handler for protocol listener - if we get a connect signal,
1034 create a new protocol connection, otherwise pass the signal down. */
1036 isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
1037 const char *name, va_list ap)
1039 isc_result_t status;
1041 omapi_protocol_object_t *obj;
1042 omapi_protocol_listener_object_t *p;
1044 if (!o || o -> type != omapi_type_protocol_listener)
1045 return ISC_R_INVALIDARG;
1046 p = (omapi_protocol_listener_object_t *)o;
1048 /* Not a signal we recognize? */
1049 if (strcmp (name, "connect")) {
1050 if (p -> inner && p -> inner -> type -> signal_handler)
1051 return (*(p -> inner -> type -> signal_handler))
1052 (p -> inner, name, ap);
1053 return ISC_R_NOTFOUND;
1056 c = va_arg (ap, omapi_object_t *);
1057 if (!c || c -> type != omapi_type_connection)
1058 return ISC_R_INVALIDARG;
1060 obj = (omapi_protocol_object_t *)0;
1061 status = omapi_protocol_allocate (&obj, MDL);
1062 if (status != ISC_R_SUCCESS)
1065 obj -> verify_auth = p -> verify_auth;
1066 obj -> insecure = p -> insecure;
1068 status = omapi_object_reference (&obj -> outer, c, MDL);
1069 if (status != ISC_R_SUCCESS) {
1071 omapi_protocol_dereference (&obj, MDL);
1072 omapi_disconnect (c, 1);
1076 status = omapi_object_reference (&c -> inner,
1077 (omapi_object_t *)obj, MDL);
1078 if (status != ISC_R_SUCCESS)
1081 /* Send the introductory message. */
1082 status = omapi_protocol_send_intro ((omapi_object_t *)obj,
1083 OMAPI_PROTOCOL_VERSION,
1084 sizeof (omapi_protocol_header_t));
1085 if (status != ISC_R_SUCCESS)
1088 omapi_protocol_dereference (&obj, MDL);
1092 isc_result_t omapi_protocol_listener_set_value (omapi_object_t *h,
1094 omapi_data_string_t *name,
1095 omapi_typed_data_t *value)
1097 if (h -> type != omapi_type_protocol_listener)
1098 return ISC_R_INVALIDARG;
1100 if (h -> inner && h -> inner -> type -> set_value)
1101 return (*(h -> inner -> type -> set_value))
1102 (h -> inner, id, name, value);
1103 return ISC_R_NOTFOUND;
1106 isc_result_t omapi_protocol_listener_get_value (omapi_object_t *h,
1108 omapi_data_string_t *name,
1109 omapi_value_t **value)
1111 if (h -> type != omapi_type_protocol_listener)
1112 return ISC_R_INVALIDARG;
1114 if (h -> inner && h -> inner -> type -> get_value)
1115 return (*(h -> inner -> type -> get_value))
1116 (h -> inner, id, name, value);
1117 return ISC_R_NOTFOUND;
1120 isc_result_t omapi_protocol_listener_destroy (omapi_object_t *h,
1121 const char *file, int line)
1123 if (h -> type != omapi_type_protocol_listener)
1124 return ISC_R_INVALIDARG;
1125 return ISC_R_SUCCESS;
1128 /* Write all the published values associated with the object through the
1129 specified connection. */
1131 isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
1137 if (p -> type != omapi_type_protocol_listener)
1138 return ISC_R_INVALIDARG;
1140 if (p -> inner && p -> inner -> type -> stuff_values)
1141 return (*(p -> inner -> type -> stuff_values)) (c, id,
1143 return ISC_R_SUCCESS;
1146 isc_result_t omapi_protocol_send_status (omapi_object_t *po,
1148 isc_result_t waitstatus,
1149 unsigned rid, const char *msg)
1151 isc_result_t status;
1152 omapi_message_object_t *message = (omapi_message_object_t *)0;
1155 if (po -> type != omapi_type_protocol)
1156 return ISC_R_INVALIDARG;
1158 status = omapi_message_new ((omapi_object_t **)&message, MDL);
1159 if (status != ISC_R_SUCCESS)
1161 mo = (omapi_object_t *)message;
1163 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1164 "op", OMAPI_OP_STATUS);
1165 if (status != ISC_R_SUCCESS) {
1166 omapi_message_dereference (&message, MDL);
1170 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1172 if (status != ISC_R_SUCCESS) {
1173 omapi_message_dereference (&message, MDL);
1177 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1178 "result", (int)waitstatus);
1179 if (status != ISC_R_SUCCESS) {
1180 omapi_message_dereference (&message, MDL);
1184 /* If a message has been provided, send it. */
1186 status = omapi_set_string_value (mo, (omapi_object_t *)0,
1188 if (status != ISC_R_SUCCESS) {
1189 omapi_message_dereference (&message, MDL);
1194 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1195 omapi_message_dereference (&message, MDL);
1199 /* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the
1200 message to be set to the protocol object. This is used when opening
1201 the default authenticator. */
1203 isc_result_t omapi_protocol_send_open (omapi_object_t *po,
1206 omapi_object_t *object,
1209 isc_result_t status;
1210 omapi_message_object_t *message = (omapi_message_object_t *)0;
1213 if (po -> type != omapi_type_protocol)
1214 return ISC_R_INVALIDARG;
1216 status = omapi_message_new ((omapi_object_t **)&message, MDL);
1217 mo = (omapi_object_t *)message;
1219 if (status == ISC_R_SUCCESS)
1220 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1221 "op", OMAPI_OP_OPEN);
1223 if (status == ISC_R_SUCCESS)
1224 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1227 if ((flags & OMAPI_CREATE) && (status == ISC_R_SUCCESS))
1228 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1231 if ((flags & OMAPI_UPDATE) && (status == ISC_R_SUCCESS))
1232 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1235 if ((flags & OMAPI_EXCL) && (status == ISC_R_SUCCESS))
1236 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1239 if ((flags & OMAPI_NOTIFY_PROTOCOL) && (status == ISC_R_SUCCESS))
1240 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1241 "notify-object", po);
1243 if (type && (status == ISC_R_SUCCESS))
1244 status = omapi_set_string_value (mo, (omapi_object_t *)0,
1247 if (status == ISC_R_SUCCESS)
1248 status = omapi_message_register (mo);
1250 if (status == ISC_R_SUCCESS) {
1251 status = omapi_protocol_send_message (po, id, mo,
1252 (omapi_object_t *)0);
1253 if (status != ISC_R_SUCCESS)
1254 omapi_message_unregister (mo);
1258 omapi_message_dereference (&message, MDL);
1263 isc_result_t omapi_protocol_send_update (omapi_object_t *po,
1266 omapi_object_t *object)
1268 isc_result_t status;
1269 omapi_message_object_t *message = (omapi_message_object_t *)0;
1272 if (po -> type != omapi_type_protocol)
1273 return ISC_R_INVALIDARG;
1275 status = omapi_message_new ((omapi_object_t **)&message, MDL);
1276 if (status != ISC_R_SUCCESS)
1278 mo = (omapi_object_t *)message;
1280 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1281 "op", OMAPI_OP_UPDATE);
1282 if (status != ISC_R_SUCCESS) {
1283 omapi_message_dereference (&message, MDL);
1288 omapi_handle_t handle;
1289 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1291 if (status != ISC_R_SUCCESS) {
1292 omapi_message_dereference (&message, MDL);
1296 status = omapi_object_handle (&handle, object);
1297 if (status != ISC_R_SUCCESS) {
1298 omapi_message_dereference (&message, MDL);
1301 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1302 "handle", (int)handle);
1303 if (status != ISC_R_SUCCESS) {
1304 omapi_message_dereference (&message, MDL);
1309 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1311 if (status != ISC_R_SUCCESS) {
1312 omapi_message_dereference (&message, MDL);
1316 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1317 omapi_message_dereference (&message, MDL);