3 Functions supporting the object management protocol... */
6 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1999-2003 by Internet Software Consortium
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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 * Newmarket, NH 03857 USA
25 * https://www.isc.org/
31 #include <omapip/omapip_p.h>
33 OMAPI_OBJECT_ALLOC (omapi_protocol
, omapi_protocol_object_t
,
35 OMAPI_OBJECT_ALLOC (omapi_protocol_listener
, omapi_protocol_listener_object_t
,
36 omapi_type_protocol_listener
)
38 isc_result_t
omapi_protocol_connect (omapi_object_t
*h
,
39 const char *server_name
,
43 isc_result_t rstatus
, status
;
44 omapi_protocol_object_t
*obj
;
47 log_debug ("omapi_protocol_connect(%s port=%d)", server_name
, port
);
50 obj
= (omapi_protocol_object_t
*)0;
51 status
= omapi_protocol_allocate (&obj
, MDL
);
52 if (status
!= ISC_R_SUCCESS
)
55 rstatus
= omapi_connect ((omapi_object_t
*)obj
, server_name
, port
);
56 if (rstatus
!= ISC_R_SUCCESS
&& rstatus
!= DHCP_R_INCOMPLETE
) {
57 omapi_protocol_dereference (&obj
, MDL
);
60 status
= omapi_object_reference (&h
-> outer
,
61 (omapi_object_t
*)obj
, MDL
);
62 if (status
!= ISC_R_SUCCESS
) {
63 omapi_protocol_dereference (&obj
, MDL
);
66 status
= omapi_object_reference (&obj
-> inner
, h
, MDL
);
67 if (status
!= ISC_R_SUCCESS
) {
68 omapi_protocol_dereference (&obj
, MDL
);
72 /* If we were passed a default authenticator, store it now. We'll
73 open it once we're connected. */
76 dmalloc (sizeof(omapi_remote_auth_t
), MDL
);
77 if (!obj
-> default_auth
) {
78 omapi_protocol_dereference (&obj
, MDL
);
79 return ISC_R_NOMEMORY
;
82 obj
-> default_auth
-> next
= (omapi_remote_auth_t
*)0;
83 status
= omapi_object_reference (&obj
-> default_auth
-> a
,
85 if (status
!= ISC_R_SUCCESS
) {
86 dfree (obj
-> default_auth
, MDL
);
87 omapi_protocol_dereference (&obj
, MDL
);
92 rstatus
= DHCP_R_INCOMPLETE
;
96 status
= ISC_R_SUCCESS
;
100 omapi_protocol_dereference (&obj
, MDL
);
104 /* Send the protocol introduction message. */
105 isc_result_t
omapi_protocol_send_intro (omapi_object_t
*h
,
110 omapi_protocol_object_t
*p
;
112 #ifdef DEBUG_PROTOCOL
113 log_debug ("omapi_protocol_send_intro()");
116 if (h
-> type
!= omapi_type_protocol
)
117 return DHCP_R_INVALIDARG
;
118 p
= (omapi_protocol_object_t
*)h
;
120 if (!h
-> outer
|| h
-> outer
-> type
!= omapi_type_connection
)
121 return ISC_R_NOTCONNECTED
;
123 status
= omapi_connection_put_uint32 (h
-> outer
, ver
);
124 if (status
!= ISC_R_SUCCESS
)
127 status
= omapi_connection_put_uint32 (h
-> outer
, hsize
);
129 if (status
!= ISC_R_SUCCESS
)
132 /* Require the other end to send an intro - this kicks off the
133 protocol input state machine. */
134 p
-> state
= omapi_protocol_intro_wait
;
135 status
= omapi_connection_require (h
-> outer
, 8);
136 if (status
!= ISC_R_SUCCESS
&& status
!= DHCP_R_NOTYET
)
139 /* Make up an initial transaction ID for this connection. */
140 p
-> next_xid
= random ();
141 return ISC_R_SUCCESS
;
144 #ifdef DEBUG_PROTOCOL
145 extern const char *omapi_message_op_name(int);
146 #endif /* DEBUG_PROTOCOL */
148 isc_result_t
omapi_protocol_send_message (omapi_object_t
*po
,
153 omapi_protocol_object_t
*p
;
155 omapi_message_object_t
*m
, *om
;
156 omapi_remote_auth_t
*ra
;
157 omapi_value_t
*signature
;
161 if (po
-> type
!= omapi_type_protocol
||
162 !po
-> outer
|| po
-> outer
-> type
!= omapi_type_connection
||
163 mo
-> type
!= omapi_type_message
)
164 return DHCP_R_INVALIDARG
;
165 if (omo
&& omo
-> type
!= omapi_type_message
)
166 return DHCP_R_INVALIDARG
;
167 p
= (omapi_protocol_object_t
*)po
;
168 c
= (omapi_object_t
*)(po
-> outer
);
169 m
= (omapi_message_object_t
*)mo
;
170 om
= (omapi_message_object_t
*)omo
;
172 #ifdef DEBUG_PROTOCOL
173 log_debug ("omapi_protocol_send_message(): "
174 "op=%s handle=%#lx id=%#lx rid=%#lx",
175 omapi_message_op_name (m
->op
),
176 (long)(m
-> object
? m
-> object
-> handle
: m
-> handle
),
177 (long)p
-> next_xid
, (long)m
-> rid
);
180 /* Find the authid to use for this message. */
182 for (ra
= p
-> remote_auth_list
; ra
; ra
= ra
-> next
) {
189 return DHCP_R_KEY_UNKNOWN
;
190 } else if (p
-> remote_auth_list
) {
191 ra
= p
-> default_auth
;
193 ra
= (omapi_remote_auth_t
*)0;
197 m
-> authid
= ra
-> remote_handle
;
198 status
= omapi_object_reference (&m
-> id_object
,
200 if (status
!= ISC_R_SUCCESS
)
204 /* Write the ID of the authentication key we're using. */
205 status
= omapi_connection_put_uint32 (c
, ra
? ra
-> remote_handle
: 0);
206 if (status
!= ISC_R_SUCCESS
) {
207 omapi_disconnect (c
, 1);
211 /* Activate the authentication key on the connection. */
214 status
= omapi_set_object_value (c
, (omapi_object_t
*)0,
215 "output-authenticator",
217 if (status
!= ISC_R_SUCCESS
) {
218 omapi_disconnect (c
, 1);
222 status
= omapi_connection_output_auth_length (c
, &auth_len
);
223 if (status
!= ISC_R_SUCCESS
) {
224 omapi_disconnect (c
, 1);
229 /* Write the authenticator length */
230 status
= omapi_connection_put_uint32 (c
, auth_len
);
231 if (status
!= ISC_R_SUCCESS
) {
232 omapi_disconnect (c
, 1);
236 /* Write the opcode. */
237 status
= omapi_connection_put_uint32 (c
, m
-> op
);
238 if (status
!= ISC_R_SUCCESS
) {
239 omapi_disconnect (c
, 1);
243 /* Write the handle. If we've been given an explicit handle, use
244 that. Otherwise, use the handle of the object we're sending.
245 The caller is responsible for arranging for one of these handles
246 to be set (or not). */
247 status
= omapi_connection_put_uint32 (c
, (m
-> h
250 ? m
-> object
-> handle
252 if (status
!= ISC_R_SUCCESS
) {
253 omapi_disconnect (c
, 1);
257 /* Set and write the transaction ID. */
258 m
-> id
= p
-> next_xid
++;
259 status
= omapi_connection_put_uint32 (c
, m
-> id
);
260 if (status
!= ISC_R_SUCCESS
) {
261 omapi_disconnect (c
, 1);
265 /* Write the transaction ID of the message to which this is a
266 response, if there is such a message. */
267 status
= omapi_connection_put_uint32 (c
, om
? om
-> id
: m
-> rid
);
268 if (status
!= ISC_R_SUCCESS
) {
269 omapi_disconnect (c
, 1);
273 /* Stuff out the name/value pairs specific to this message. */
274 status
= omapi_stuff_values (c
, id
, (omapi_object_t
*)m
);
275 if (status
!= ISC_R_SUCCESS
) {
276 omapi_disconnect (c
, 1);
280 /* Write the zero-length name that terminates the list of name/value
281 pairs specific to the message. */
282 status
= omapi_connection_put_uint16 (c
, 0);
283 if (status
!= ISC_R_SUCCESS
) {
284 omapi_disconnect (c
, 1);
288 /* Stuff out all the published name/value pairs in the object that's
289 being sent in the message, if there is one. */
291 status
= omapi_stuff_values (c
, id
, m
-> object
);
292 if (status
!= ISC_R_SUCCESS
) {
293 omapi_disconnect (c
, 1);
298 /* Write the zero-length name that terminates the list of name/value
299 pairs for the associated object. */
300 status
= omapi_connection_put_uint16 (c
, 0);
301 if (status
!= ISC_R_SUCCESS
) {
302 omapi_disconnect (c
, 1);
307 /* Calculate the message signature. */
308 signature
= (omapi_value_t
*)0;
309 status
= omapi_get_value_str (c
, (omapi_object_t
*)0,
310 "output-signature", &signature
);
311 if (status
!= ISC_R_SUCCESS
) {
312 omapi_disconnect (c
, 1);
316 /* Write the authenticator... */
317 status
= (omapi_connection_copyin
318 (c
, signature
-> value
-> u
.buffer
.value
,
319 signature
-> value
-> u
.buffer
.len
));
320 omapi_value_dereference (&signature
, MDL
);
321 if (status
!= ISC_R_SUCCESS
) {
322 omapi_disconnect (c
, 1);
326 /* Dectivate the authentication key on the connection. */
327 status
= omapi_set_value_str (c
, (omapi_object_t
*)0,
328 "output-authenticator",
329 (omapi_typed_data_t
*)0);
330 if (status
!= ISC_R_SUCCESS
) {
331 omapi_disconnect (c
, 1);
337 omapi_protocol_reference (&m
-> protocol_object
, p
, MDL
);
339 return ISC_R_SUCCESS
;
343 isc_result_t
omapi_protocol_signal_handler (omapi_object_t
*h
,
344 const char *name
, va_list ap
)
347 omapi_protocol_object_t
*p
;
349 omapi_message_object_t
*m
;
350 omapi_value_t
*signature
= NULL
;
354 #if defined (DEBUG_MEMORY_LEAKAGE)
355 unsigned long previous_outstanding
= 0xDEADBEEF;
356 unsigned long connect_outstanding
= 0xDEADBEEF;
359 if (h
-> type
!= omapi_type_protocol
) {
360 /* XXX shouldn't happen. Put an assert here? */
361 return ISC_R_UNEXPECTED
;
363 p
= (omapi_protocol_object_t
*)h
;
365 if (!strcmp (name
, "connect")) {
366 #if defined (DEBUG_MEMORY_LEAKAGE)
367 connect_outstanding
= dmalloc_outstanding
;
369 /* Send the introductory message. */
370 status
= omapi_protocol_send_intro
371 (h
, OMAPI_PROTOCOL_VERSION
,
372 sizeof (omapi_protocol_header_t
));
373 if (status
!= ISC_R_SUCCESS
) {
374 omapi_disconnect (p
-> outer
, 1);
377 return ISC_R_SUCCESS
;
380 /* Should only receive these when opening the initial authenticator. */
381 if (!strcmp (name
, "status")) {
382 status
= va_arg (ap
, isc_result_t
);
383 if (status
!= ISC_R_SUCCESS
) {
384 omapi_signal_in (h
-> inner
, "status", status
,
385 (omapi_object_t
*)0);
386 omapi_disconnect (p
-> outer
, 1);
389 return omapi_signal_in (h
-> inner
, "ready");
393 /* If we get a disconnect, dump memory usage. */
394 if (!strcmp (name
, "disconnect")) {
395 #if defined (DEBUG_MEMORY_LEAKAGE)
396 if (connect_outstanding
!= 0xDEADBEEF) {
397 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
399 dmalloc_outstanding
- previous_outstanding
,
400 dmalloc_outstanding
, dmalloc_longterm
, " long-term");
403 #if defined (DEBUG_MEMORY_LEAKAGE)
404 dmalloc_dump_outstanding ();
406 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
409 for (m
= omapi_registered_messages
; m
; m
= m
-> next
) {
410 if (m
-> protocol_object
== p
) {
412 omapi_signal (m
-> object
, "disconnect");
417 return ISC_R_SUCCESS
;
420 /* Not a signal we recognize? */
421 if (strcmp (name
, "ready")) {
422 if (p
-> inner
&& p
-> inner
-> type
-> signal_handler
)
423 return (*(p
-> inner
-> type
-> signal_handler
)) (h
,
426 return ISC_R_NOTFOUND
;
429 if (!p
-> outer
|| p
-> outer
-> type
!= omapi_type_connection
)
430 return DHCP_R_INVALIDARG
;
433 /* We get here because we requested that we be woken up after
434 some number of bytes were read, and that number of bytes
435 has in fact been read. */
436 switch (p
-> state
) {
437 case omapi_protocol_intro_wait
:
438 /* Get protocol version and header size in network
440 omapi_connection_get_uint32 (c
, &p
-> protocol_version
);
441 omapi_connection_get_uint32 (c
, &p
-> header_size
);
443 /* We currently only support the current protocol version. */
444 if (p
-> protocol_version
!= OMAPI_PROTOCOL_VERSION
) {
445 omapi_disconnect (c
, 1);
446 return DHCP_R_VERSIONMISMATCH
;
449 if (p
-> header_size
< sizeof (omapi_protocol_header_t
)) {
450 omapi_disconnect (c
, 1);
451 return DHCP_R_PROTOCOLERROR
;
454 if (p
-> default_auth
) {
455 status
= omapi_protocol_send_open
456 (h
, (omapi_object_t
*)0, "authenticator",
457 p
-> default_auth
-> a
,
458 OMAPI_NOTIFY_PROTOCOL
);
459 if (status
!= ISC_R_SUCCESS
) {
460 omapi_disconnect (c
, 1);
464 status
= omapi_signal_in (h
-> inner
, "ready");
468 /* The next thing we're expecting is a message header. */
469 p
-> state
= omapi_protocol_header_wait
;
471 /* Register a need for the number of bytes in a
472 header, and if we already have that many, process
474 if ((omapi_connection_require (c
, p
-> header_size
)) !=
477 /* If we already have the data, fall through. */
479 case omapi_protocol_header_wait
:
480 #if defined (DEBUG_MEMORY_LEAKAGE)
481 if (previous_outstanding
!= 0xDEADBEEF) {
482 log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
483 "generation", dmalloc_generation
,
484 dmalloc_outstanding
- previous_outstanding
,
485 dmalloc_outstanding
, dmalloc_longterm
,
488 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
489 dmalloc_dump_outstanding ();
491 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
494 #if defined (DEBUG_MEMORY_LEAKAGE)
496 previous_outstanding
= dmalloc_outstanding
;
498 status
= omapi_message_new ((omapi_object_t
**)&p
-> message
,
500 if (status
!= ISC_R_SUCCESS
) {
501 omapi_disconnect (c
, 1);
505 p
-> verify_result
= ISC_R_SUCCESS
;
507 /* Swap in the header... */
508 omapi_connection_get_uint32 (c
, &p
-> message
-> authid
);
510 /* Bind the authenticator to the message object. */
511 if (p
-> message
-> authid
) {
512 status
= (omapi_protocol_lookup_auth
513 (&p
-> message
-> id_object
, h
,
514 p
-> message
-> authid
));
515 if (status
!= ISC_R_SUCCESS
)
516 p
-> verify_result
= status
;
518 /* Activate the authentication key. */
519 status
= omapi_set_object_value
520 (c
, (omapi_object_t
*)0, "input-authenticator",
521 p
-> message
-> id_object
);
522 if (status
!= ISC_R_SUCCESS
) {
523 omapi_disconnect (c
, 1);
528 omapi_connection_get_uint32 (c
, &p
-> message
-> authlen
);
529 omapi_connection_get_uint32 (c
, &p
-> message
-> op
);
530 omapi_connection_get_uint32 (c
, &th
);
531 p
-> message
-> h
= th
;
532 omapi_connection_get_uint32 (c
, &p
-> message
-> id
);
533 omapi_connection_get_uint32 (c
, &p
-> message
-> rid
);
535 /* If there was any extra header data, skip over it. */
536 if (p
-> header_size
> sizeof (omapi_protocol_header_t
)) {
537 omapi_connection_copyout
538 (0, c
, (p
-> header_size
-
539 sizeof (omapi_protocol_header_t
)));
542 /* XXX must compute partial signature across the
543 XXX preceding bytes. Also, if authenticator
544 specifies encryption as well as signing, we may
545 have to decrypt the data on the way in. */
547 /* First we read in message-specific values, then object
549 p
-> reading_message_values
= 1;
552 /* The next thing we're expecting is length of the
554 p
-> state
= omapi_protocol_name_length_wait
;
556 /* Wait for a 16-bit length. */
557 if ((omapi_connection_require (c
, 2)) != ISC_R_SUCCESS
)
559 /* If it's already here, fall through. */
561 case omapi_protocol_name_length_wait
:
562 omapi_connection_get_uint16 (c
, &nlen
);
563 /* A zero-length name means that we're done reading name+value
566 /* If we've already read in the object, we are
567 done reading the message, but if we've just
568 finished reading in the values associated
569 with the message, we need to read the
571 if (p
-> reading_message_values
) {
572 p
-> reading_message_values
= 0;
573 goto need_name_length
;
576 /* If the authenticator length is zero, there's no
577 signature to read in, so go straight to processing
579 if (p
-> message
-> authlen
== 0)
582 /* The next thing we're expecting is the
583 message signature. */
584 p
-> state
= omapi_protocol_signature_wait
;
586 /* Wait for the number of bytes specified for
587 the authenticator. If we already have it,
589 if (omapi_connection_require
590 (c
, p
-> message
-> authlen
) == ISC_R_SUCCESS
)
595 /* Allocate a buffer for the name. */
596 status
= (omapi_data_string_new (&p
-> name
, nlen
, MDL
));
597 if (status
!= ISC_R_SUCCESS
) {
598 omapi_disconnect (c
, 1);
599 return ISC_R_NOMEMORY
;
601 p
-> state
= omapi_protocol_name_wait
;
602 if (omapi_connection_require (c
, nlen
) != ISC_R_SUCCESS
)
604 /* If it's already here, fall through. */
606 case omapi_protocol_name_wait
:
607 omapi_connection_copyout (p
-> name
-> value
, c
,
609 /* Wait for a 32-bit length. */
610 p
-> state
= omapi_protocol_value_length_wait
;
611 if ((omapi_connection_require (c
, 4)) != ISC_R_SUCCESS
)
613 /* If it's already here, fall through. */
615 case omapi_protocol_value_length_wait
:
616 omapi_connection_get_uint32 (c
, &vlen
);
618 /* Zero-length values are allowed - if we get one, we
619 don't have to read any data for the value - just
620 get the next one, if there is a next one. */
622 goto insert_new_value
;
624 status
= omapi_typed_data_new (MDL
, &p
-> value
,
627 if (status
!= ISC_R_SUCCESS
) {
628 omapi_disconnect (c
, 1);
629 return ISC_R_NOMEMORY
;
632 p
-> state
= omapi_protocol_value_wait
;
633 if (omapi_connection_require (c
, vlen
) != ISC_R_SUCCESS
)
635 /* If it's already here, fall through. */
637 case omapi_protocol_value_wait
:
638 omapi_connection_copyout (p
-> value
-> u
.buffer
.value
, c
,
639 p
-> value
-> u
.buffer
.len
);
642 if (p
-> reading_message_values
) {
643 status
= (omapi_set_value
644 ((omapi_object_t
*)p
-> message
,
645 p
-> message
-> id_object
,
646 p
-> name
, p
-> value
));
648 if (!p
-> message
-> object
) {
649 /* We need a generic object to hang off of the
651 status
= (omapi_generic_new
652 (&p
-> message
-> object
, MDL
));
653 if (status
!= ISC_R_SUCCESS
) {
654 omapi_disconnect (c
, 1);
658 status
= (omapi_set_value
659 ((omapi_object_t
*)p
-> message
-> object
,
660 p
-> message
-> id_object
,
661 p
-> name
, p
-> value
));
663 if (status
!= ISC_R_SUCCESS
) {
664 omapi_disconnect (c
, 1);
667 omapi_data_string_dereference (&p
-> name
, MDL
);
669 omapi_typed_data_dereference (&p
-> value
, MDL
);
670 goto need_name_length
;
673 case omapi_protocol_signature_wait
:
674 if (p
-> message
-> id_object
) {
675 /* Compute the signature of the message. */
676 status
= omapi_get_value_str (c
, (omapi_object_t
*)0,
679 if (status
!= ISC_R_SUCCESS
) {
680 omapi_disconnect (c
, 1);
684 /* Disable the authentication key on the connection. */
685 status
= omapi_set_value_str (c
, (omapi_object_t
*)0,
686 "input-authenticator",
687 (omapi_typed_data_t
*)0);
688 if (status
!= ISC_R_SUCCESS
) {
689 omapi_value_dereference (&signature
, MDL
);
690 omapi_disconnect (c
, 1);
695 /* Read the authenticator. */
696 status
= omapi_typed_data_new (MDL
,
697 &p
-> message
-> authenticator
,
699 p
-> message
-> authlen
);
701 if (status
!= ISC_R_SUCCESS
) {
702 if (signature
!= NULL
) {
703 omapi_value_dereference (&signature
, MDL
);
705 omapi_disconnect (c
, 1);
706 return ISC_R_NOMEMORY
;
708 omapi_connection_copyout
709 (p
-> message
-> authenticator
-> u
.buffer
.value
, c
,
710 p
-> message
-> authlen
);
712 /* Verify the signature. */
713 if (p
-> message
-> id_object
&&
714 ((signature
-> value
-> u
.buffer
.len
!=
715 p
-> message
-> authlen
) ||
716 (memcmp (signature
-> value
-> u
.buffer
.value
,
717 p
-> message
-> authenticator
-> u
.buffer
.value
,
718 p
-> message
-> authlen
) != 0))) {
719 /* Invalid signature. */
720 p
->verify_result
= DHCP_R_INVALIDKEY
;
723 if (signature
!= NULL
) {
724 omapi_value_dereference (&signature
, MDL
);
727 /* Process the message. */
729 if (p
-> verify_result
!= ISC_R_SUCCESS
) {
730 status
= omapi_protocol_send_status
731 (h
, (omapi_object_t
*)0, p
-> verify_result
,
732 p
-> message
-> id
, (char *)0);
734 status
= omapi_message_process
735 ((omapi_object_t
*)p
-> message
, h
);
737 if (status
!= ISC_R_SUCCESS
) {
738 omapi_disconnect (c
, 1);
739 return ISC_R_NOMEMORY
;
742 omapi_message_dereference (&p
-> message
, MDL
);
743 #if defined (DEBUG_MEMORY_LEAKAGE)
744 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
746 dmalloc_outstanding
- previous_outstanding
,
747 dmalloc_outstanding
, dmalloc_longterm
, " long-term");
749 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
750 dmalloc_dump_outstanding ();
752 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
755 #if defined (DEBUG_MEMORY_LEAKAGE)
756 previous_outstanding
= 0xDEADBEEF;
758 /* Now wait for the next message. */
762 /* XXX should never get here. Assertion? */
765 return ISC_R_SUCCESS
;
768 isc_result_t
omapi_protocol_add_auth (omapi_object_t
*po
,
770 omapi_handle_t handle
)
772 omapi_protocol_object_t
*p
;
773 omapi_remote_auth_t
*r
;
776 if (ao
-> type
!= omapi_type_auth_key
&&
777 (!ao
-> inner
|| ao
-> inner
-> type
!= omapi_type_auth_key
))
778 return DHCP_R_INVALIDARG
;
780 if (po
-> type
!= omapi_type_protocol
)
781 return DHCP_R_INVALIDARG
;
782 p
= (omapi_protocol_object_t
*)po
;
784 #ifdef DEBUG_PROTOCOL
785 log_debug ("omapi_protocol_add_auth(name=%s)",
786 ((omapi_auth_key_t
*)ao
) -> name
);
789 if (p
-> verify_auth
) {
790 status
= (p
-> verify_auth
) (po
, (omapi_auth_key_t
*)ao
);
791 if (status
!= ISC_R_SUCCESS
)
795 /* If omapi_protocol_connect() was called with a default
796 authenticator, p -> default_auth will already be set,
797 but p -> remote_auth_list will not yet be initialized. */
798 if (p
-> default_auth
&& !p
-> remote_auth_list
) {
799 if (p
-> default_auth
-> a
!= ao
) {
800 /* Something just went horribly wrong. */
801 omapi_disconnect (p
-> outer
, 1);
802 return ISC_R_UNEXPECTED
;
805 p
-> remote_auth_list
= p
-> default_auth
;
806 p
-> default_auth
-> remote_handle
= handle
;
808 return omapi_signal_in (p
-> inner
, "ready");
811 r
= dmalloc (sizeof(*r
), MDL
);
813 return ISC_R_NOMEMORY
;
815 status
= omapi_object_reference (&r
-> a
, ao
, MDL
);
816 if (status
!= ISC_R_SUCCESS
) {
821 r
-> remote_handle
= handle
;
822 r
-> next
= p
-> remote_auth_list
;
823 p
-> remote_auth_list
= r
;
825 return ISC_R_SUCCESS
;
828 isc_result_t
omapi_protocol_lookup_auth (omapi_object_t
**a
,
830 omapi_handle_t handle
)
832 omapi_protocol_object_t
*p
;
833 omapi_remote_auth_t
*r
;
835 if (po
-> type
!= omapi_type_protocol
)
836 return DHCP_R_INVALIDARG
;
837 p
= (omapi_protocol_object_t
*)po
;
839 for (r
= p
-> remote_auth_list
; r
; r
= r
-> next
)
840 if (r
-> remote_handle
== handle
)
841 return omapi_object_reference (a
, r
-> a
, MDL
);
843 return DHCP_R_KEY_UNKNOWN
;
846 isc_result_t
omapi_protocol_set_value (omapi_object_t
*h
,
848 omapi_data_string_t
*name
,
849 omapi_typed_data_t
*value
)
851 omapi_protocol_object_t
*p
;
852 omapi_remote_auth_t
*r
;
854 if (h
-> type
!= omapi_type_protocol
)
855 return DHCP_R_INVALIDARG
;
856 p
= (omapi_protocol_object_t
*)h
;
858 if (omapi_ds_strcmp (name
, "default-authenticator") == 0) {
859 if (!value
|| value
-> type
!= omapi_datatype_object
)
860 return DHCP_R_INVALIDARG
;
862 if (!value
-> u
.object
) {
863 p
-> default_auth
= (omapi_remote_auth_t
*)0;
865 for (r
= p
-> remote_auth_list
; r
; r
= r
-> next
)
866 if (r
-> a
== value
-> u
.object
)
870 return DHCP_R_KEY_UNKNOWN
;
872 p
-> default_auth
= r
;
875 return ISC_R_SUCCESS
;
878 if (h
-> inner
&& h
-> inner
-> type
-> set_value
)
879 return (*(h
-> inner
-> type
-> set_value
))
880 (h
-> inner
, id
, name
, value
);
881 return ISC_R_NOTFOUND
;
884 isc_result_t
omapi_protocol_get_value (omapi_object_t
*h
,
886 omapi_data_string_t
*name
,
887 omapi_value_t
**value
)
889 omapi_protocol_object_t
*p
;
891 if (h
-> type
!= omapi_type_protocol
)
892 return DHCP_R_INVALIDARG
;
893 p
= (omapi_protocol_object_t
*)h
;
895 if (omapi_ds_strcmp (name
, "default-authenticator") == 0) {
896 if (!p
-> default_auth
)
897 return ISC_R_NOTFOUND
;
899 return omapi_make_object_value (value
, name
,
900 p
-> default_auth
-> a
, MDL
);
903 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
904 return (*(h
-> inner
-> type
-> get_value
))
905 (h
-> inner
, id
, name
, value
);
906 return ISC_R_NOTFOUND
;
909 isc_result_t
omapi_protocol_destroy (omapi_object_t
*h
,
910 const char *file
, int line
)
912 omapi_protocol_object_t
*p
;
913 if (h
-> type
!= omapi_type_protocol
)
914 return DHCP_R_INVALIDARG
;
915 p
= (omapi_protocol_object_t
*)h
;
917 omapi_message_dereference (&p
-> message
, file
, line
);
919 /* This will happen if: 1) A default authenticator is supplied to
920 omapi_protocol_connect(), and 2) something goes wrong before
921 the authenticator can be opened. */
922 if (p
-> default_auth
&& !p
-> remote_auth_list
)
923 dfree (p
-> default_auth
, file
, line
);
925 while (p
-> remote_auth_list
) {
926 omapi_remote_auth_t
*r
= p
-> remote_auth_list
;
927 p
-> remote_auth_list
= p
-> remote_auth_list
-> next
;
928 omapi_object_dereference (&r
-> a
, file
, line
);
929 dfree (r
, file
, line
);
931 return ISC_R_SUCCESS
;
934 /* Write all the published values associated with the object through the
935 specified connection. */
937 isc_result_t
omapi_protocol_stuff_values (omapi_object_t
*c
,
941 if (p
-> type
!= omapi_type_protocol
)
942 return DHCP_R_INVALIDARG
;
944 if (p
-> inner
&& p
-> inner
-> type
-> stuff_values
)
945 return (*(p
-> inner
-> type
-> stuff_values
)) (c
, id
,
947 return ISC_R_SUCCESS
;
950 /* Returns a boolean indicating whether this protocol requires that
951 messages be authenticated or not. */
953 isc_boolean_t
omapi_protocol_authenticated (omapi_object_t
*h
)
955 if (h
-> type
!= omapi_type_protocol
)
956 return isc_boolean_false
;
957 if (((omapi_protocol_object_t
*)h
) -> insecure
)
958 return isc_boolean_false
;
960 return isc_boolean_true
;
963 /* Sets the address and authenticator verification callbacks. The handle
964 is to a listener object, not a protocol object. */
966 isc_result_t
omapi_protocol_configure_security (omapi_object_t
*h
,
967 isc_result_t (*verify_addr
)
970 isc_result_t (*verify_auth
)
974 omapi_protocol_listener_object_t
*l
;
976 if (h
-> outer
&& h
-> outer
-> type
== omapi_type_protocol_listener
)
979 if (h
-> type
!= omapi_type_protocol_listener
)
980 return DHCP_R_INVALIDARG
;
981 l
= (omapi_protocol_listener_object_t
*)h
;
983 l
-> verify_auth
= verify_auth
;
986 if (h
-> outer
!= NULL
) {
987 return omapi_listener_configure_security (h
-> outer
, verify_addr
);
989 return DHCP_R_INVALIDARG
;
994 /* Set up a listener for the omapi protocol. The handle stored points to
995 a listener object, not a protocol object. */
997 isc_result_t
omapi_protocol_listen (omapi_object_t
*h
,
1001 isc_result_t status
;
1002 omapi_protocol_listener_object_t
*obj
;
1004 obj
= (omapi_protocol_listener_object_t
*)0;
1005 status
= omapi_protocol_listener_allocate (&obj
, MDL
);
1006 if (status
!= ISC_R_SUCCESS
)
1009 status
= omapi_object_reference (&h
-> outer
,
1010 (omapi_object_t
*)obj
, MDL
);
1011 if (status
!= ISC_R_SUCCESS
) {
1012 omapi_protocol_listener_dereference (&obj
, MDL
);
1015 status
= omapi_object_reference (&obj
-> inner
, h
, MDL
);
1016 if (status
!= ISC_R_SUCCESS
) {
1017 omapi_protocol_listener_dereference (&obj
, MDL
);
1021 /* What a terrible default. */
1022 obj
-> insecure
= 1;
1024 status
= omapi_listen ((omapi_object_t
*)obj
, port
, max
);
1025 omapi_protocol_listener_dereference (&obj
, MDL
);
1029 /* Signal handler for protocol listener - if we get a connect signal,
1030 create a new protocol connection, otherwise pass the signal down. */
1032 isc_result_t
omapi_protocol_listener_signal (omapi_object_t
*o
,
1033 const char *name
, va_list ap
)
1035 isc_result_t status
;
1037 omapi_protocol_object_t
*obj
;
1038 omapi_protocol_listener_object_t
*p
;
1040 if (!o
|| o
-> type
!= omapi_type_protocol_listener
)
1041 return DHCP_R_INVALIDARG
;
1042 p
= (omapi_protocol_listener_object_t
*)o
;
1044 /* Not a signal we recognize? */
1045 if (strcmp (name
, "connect")) {
1046 if (p
-> inner
&& p
-> inner
-> type
-> signal_handler
)
1047 return (*(p
-> inner
-> type
-> signal_handler
))
1048 (p
-> inner
, name
, ap
);
1049 return ISC_R_NOTFOUND
;
1052 c
= va_arg (ap
, omapi_object_t
*);
1053 if (!c
|| c
-> type
!= omapi_type_connection
)
1054 return DHCP_R_INVALIDARG
;
1056 obj
= (omapi_protocol_object_t
*)0;
1057 status
= omapi_protocol_allocate (&obj
, MDL
);
1058 if (status
!= ISC_R_SUCCESS
)
1061 obj
-> verify_auth
= p
-> verify_auth
;
1062 obj
-> insecure
= p
-> insecure
;
1064 status
= omapi_object_reference (&obj
-> outer
, c
, MDL
);
1065 if (status
!= ISC_R_SUCCESS
) {
1067 omapi_protocol_dereference (&obj
, MDL
);
1068 omapi_disconnect (c
, 1);
1072 status
= omapi_object_reference (&c
-> inner
,
1073 (omapi_object_t
*)obj
, MDL
);
1074 if (status
!= ISC_R_SUCCESS
)
1077 /* Send the introductory message. */
1078 status
= omapi_protocol_send_intro ((omapi_object_t
*)obj
,
1079 OMAPI_PROTOCOL_VERSION
,
1080 sizeof (omapi_protocol_header_t
));
1081 if (status
!= ISC_R_SUCCESS
)
1084 omapi_protocol_dereference (&obj
, MDL
);
1088 isc_result_t
omapi_protocol_listener_set_value (omapi_object_t
*h
,
1090 omapi_data_string_t
*name
,
1091 omapi_typed_data_t
*value
)
1093 if (h
-> type
!= omapi_type_protocol_listener
)
1094 return DHCP_R_INVALIDARG
;
1096 if (h
-> inner
&& h
-> inner
-> type
-> set_value
)
1097 return (*(h
-> inner
-> type
-> set_value
))
1098 (h
-> inner
, id
, name
, value
);
1099 return ISC_R_NOTFOUND
;
1102 isc_result_t
omapi_protocol_listener_get_value (omapi_object_t
*h
,
1104 omapi_data_string_t
*name
,
1105 omapi_value_t
**value
)
1107 if (h
-> type
!= omapi_type_protocol_listener
)
1108 return DHCP_R_INVALIDARG
;
1110 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
1111 return (*(h
-> inner
-> type
-> get_value
))
1112 (h
-> inner
, id
, name
, value
);
1113 return ISC_R_NOTFOUND
;
1116 isc_result_t
omapi_protocol_listener_destroy (omapi_object_t
*h
,
1117 const char *file
, int line
)
1119 if (h
-> type
!= omapi_type_protocol_listener
)
1120 return DHCP_R_INVALIDARG
;
1121 return ISC_R_SUCCESS
;
1124 /* Write all the published values associated with the object through the
1125 specified connection. */
1127 isc_result_t
omapi_protocol_listener_stuff (omapi_object_t
*c
,
1131 if (p
-> type
!= omapi_type_protocol_listener
)
1132 return DHCP_R_INVALIDARG
;
1134 if (p
-> inner
&& p
-> inner
-> type
-> stuff_values
)
1135 return (*(p
-> inner
-> type
-> stuff_values
)) (c
, id
,
1137 return ISC_R_SUCCESS
;
1140 isc_result_t
omapi_protocol_send_status (omapi_object_t
*po
,
1142 isc_result_t waitstatus
,
1143 unsigned rid
, const char *msg
)
1145 isc_result_t status
;
1146 omapi_message_object_t
*message
= (omapi_message_object_t
*)0;
1149 if (po
-> type
!= omapi_type_protocol
)
1150 return DHCP_R_INVALIDARG
;
1152 status
= omapi_message_new ((omapi_object_t
**)&message
, MDL
);
1153 if (status
!= ISC_R_SUCCESS
)
1155 mo
= (omapi_object_t
*)message
;
1157 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1158 "op", OMAPI_OP_STATUS
);
1159 if (status
!= ISC_R_SUCCESS
) {
1160 omapi_message_dereference (&message
, MDL
);
1164 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1166 if (status
!= ISC_R_SUCCESS
) {
1167 omapi_message_dereference (&message
, MDL
);
1171 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1172 "result", (int)waitstatus
);
1173 if (status
!= ISC_R_SUCCESS
) {
1174 omapi_message_dereference (&message
, MDL
);
1178 /* If a message has been provided, send it. */
1180 status
= omapi_set_string_value (mo
, (omapi_object_t
*)0,
1182 if (status
!= ISC_R_SUCCESS
) {
1183 omapi_message_dereference (&message
, MDL
);
1188 status
= omapi_protocol_send_message (po
, id
, mo
, (omapi_object_t
*)0);
1189 omapi_message_dereference (&message
, MDL
);
1193 /* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the
1194 message to be set to the protocol object. This is used when opening
1195 the default authenticator. */
1197 isc_result_t
omapi_protocol_send_open (omapi_object_t
*po
,
1200 omapi_object_t
*object
,
1203 isc_result_t status
;
1204 omapi_message_object_t
*message
= (omapi_message_object_t
*)0;
1207 if (po
-> type
!= omapi_type_protocol
)
1208 return DHCP_R_INVALIDARG
;
1210 status
= omapi_message_new ((omapi_object_t
**)&message
, MDL
);
1211 mo
= (omapi_object_t
*)message
;
1213 if (status
== ISC_R_SUCCESS
)
1214 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1215 "op", OMAPI_OP_OPEN
);
1217 if (status
== ISC_R_SUCCESS
)
1218 status
= omapi_set_object_value (mo
, (omapi_object_t
*)0,
1221 if ((flags
& OMAPI_CREATE
) && (status
== ISC_R_SUCCESS
))
1222 status
= omapi_set_boolean_value (mo
, (omapi_object_t
*)0,
1225 if ((flags
& OMAPI_UPDATE
) && (status
== ISC_R_SUCCESS
))
1226 status
= omapi_set_boolean_value (mo
, (omapi_object_t
*)0,
1229 if ((flags
& OMAPI_EXCL
) && (status
== ISC_R_SUCCESS
))
1230 status
= omapi_set_boolean_value (mo
, (omapi_object_t
*)0,
1233 if ((flags
& OMAPI_NOTIFY_PROTOCOL
) && (status
== ISC_R_SUCCESS
))
1234 status
= omapi_set_object_value (mo
, (omapi_object_t
*)0,
1235 "notify-object", po
);
1237 if (type
&& (status
== ISC_R_SUCCESS
))
1238 status
= omapi_set_string_value (mo
, (omapi_object_t
*)0,
1241 if (status
== ISC_R_SUCCESS
)
1242 status
= omapi_message_register (mo
);
1244 if (status
== ISC_R_SUCCESS
) {
1245 status
= omapi_protocol_send_message (po
, id
, mo
,
1246 (omapi_object_t
*)0);
1247 if (status
!= ISC_R_SUCCESS
)
1248 omapi_message_unregister (mo
);
1252 omapi_message_dereference (&message
, MDL
);
1257 isc_result_t
omapi_protocol_send_update (omapi_object_t
*po
,
1260 omapi_object_t
*object
)
1262 isc_result_t status
;
1263 omapi_message_object_t
*message
= (omapi_message_object_t
*)0;
1266 if (po
-> type
!= omapi_type_protocol
)
1267 return DHCP_R_INVALIDARG
;
1269 status
= omapi_message_new ((omapi_object_t
**)&message
, MDL
);
1270 if (status
!= ISC_R_SUCCESS
)
1272 mo
= (omapi_object_t
*)message
;
1274 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1275 "op", OMAPI_OP_UPDATE
);
1276 if (status
!= ISC_R_SUCCESS
) {
1277 omapi_message_dereference (&message
, MDL
);
1282 omapi_handle_t handle
;
1283 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1285 if (status
!= ISC_R_SUCCESS
) {
1286 omapi_message_dereference (&message
, MDL
);
1290 status
= omapi_object_handle (&handle
, object
);
1291 if (status
!= ISC_R_SUCCESS
) {
1292 omapi_message_dereference (&message
, MDL
);
1295 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1296 "handle", (int)handle
);
1297 if (status
!= ISC_R_SUCCESS
) {
1298 omapi_message_dereference (&message
, MDL
);
1303 status
= omapi_set_object_value (mo
, (omapi_object_t
*)0,
1305 if (status
!= ISC_R_SUCCESS
) {
1306 omapi_message_dereference (&message
, MDL
);
1310 status
= omapi_protocol_send_message (po
, id
, mo
, (omapi_object_t
*)0);
1311 omapi_message_dereference (&message
, MDL
);