1 /* $NetBSD: protocol.c,v 1.1.1.3 2014/07/12 11:58:00 spz Exp $ */
4 Functions supporting the object management protocol... */
7 * Copyright (c) 2009,2012,2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1999-2003 by Internet Software Consortium
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Internet Systems Consortium, Inc.
25 * Redwood City, CA 94063
27 * https://www.isc.org/
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: protocol.c,v 1.1.1.3 2014/07/12 11:58:00 spz Exp $");
36 #include <omapip/omapip_p.h>
38 OMAPI_OBJECT_ALLOC (omapi_protocol
, omapi_protocol_object_t
,
40 OMAPI_OBJECT_ALLOC (omapi_protocol_listener
, omapi_protocol_listener_object_t
,
41 omapi_type_protocol_listener
)
43 isc_result_t
omapi_protocol_connect (omapi_object_t
*h
,
44 const char *server_name
,
48 isc_result_t rstatus
, status
;
49 omapi_protocol_object_t
*obj
;
52 log_debug ("omapi_protocol_connect(%s port=%d)", server_name
, port
);
55 obj
= (omapi_protocol_object_t
*)0;
56 status
= omapi_protocol_allocate (&obj
, MDL
);
57 if (status
!= ISC_R_SUCCESS
)
60 rstatus
= omapi_connect ((omapi_object_t
*)obj
, server_name
, port
);
61 if (rstatus
!= ISC_R_SUCCESS
&& rstatus
!= DHCP_R_INCOMPLETE
) {
62 omapi_protocol_dereference (&obj
, MDL
);
65 status
= omapi_object_reference (&h
-> outer
,
66 (omapi_object_t
*)obj
, MDL
);
67 if (status
!= ISC_R_SUCCESS
) {
68 omapi_protocol_dereference (&obj
, MDL
);
71 status
= omapi_object_reference (&obj
-> inner
, h
, MDL
);
72 if (status
!= ISC_R_SUCCESS
) {
73 omapi_protocol_dereference (&obj
, MDL
);
77 /* If we were passed a default authenticator, store it now. We'll
78 open it once we're connected. */
81 dmalloc (sizeof(omapi_remote_auth_t
), MDL
);
82 if (!obj
-> default_auth
) {
83 omapi_protocol_dereference (&obj
, MDL
);
84 return ISC_R_NOMEMORY
;
87 obj
-> default_auth
-> next
= (omapi_remote_auth_t
*)0;
88 status
= omapi_object_reference (&obj
-> default_auth
-> a
,
90 if (status
!= ISC_R_SUCCESS
) {
91 dfree (obj
-> default_auth
, MDL
);
92 omapi_protocol_dereference (&obj
, MDL
);
97 rstatus
= DHCP_R_INCOMPLETE
;
101 status
= ISC_R_SUCCESS
;
105 omapi_protocol_dereference (&obj
, MDL
);
109 /* Send the protocol introduction message. */
110 isc_result_t
omapi_protocol_send_intro (omapi_object_t
*h
,
115 omapi_protocol_object_t
*p
;
117 #ifdef DEBUG_PROTOCOL
118 log_debug ("omapi_protocol_send_intro()");
121 if (h
-> type
!= omapi_type_protocol
)
122 return DHCP_R_INVALIDARG
;
123 p
= (omapi_protocol_object_t
*)h
;
125 if (!h
-> outer
|| h
-> outer
-> type
!= omapi_type_connection
)
126 return ISC_R_NOTCONNECTED
;
128 status
= omapi_connection_put_uint32 (h
-> outer
, ver
);
129 if (status
!= ISC_R_SUCCESS
)
132 status
= omapi_connection_put_uint32 (h
-> outer
, hsize
);
134 if (status
!= ISC_R_SUCCESS
)
137 /* Require the other end to send an intro - this kicks off the
138 protocol input state machine. */
139 p
-> state
= omapi_protocol_intro_wait
;
140 status
= omapi_connection_require (h
-> outer
, 8);
141 if (status
!= ISC_R_SUCCESS
&& status
!= DHCP_R_NOTYET
)
144 /* Make up an initial transaction ID for this connection. */
145 p
-> next_xid
= random ();
146 return ISC_R_SUCCESS
;
149 #ifdef DEBUG_PROTOCOL
150 extern const char *omapi_message_op_name(int);
151 #endif /* DEBUG_PROTOCOL */
153 isc_result_t
omapi_protocol_send_message (omapi_object_t
*po
,
158 omapi_protocol_object_t
*p
;
160 omapi_message_object_t
*m
, *om
;
161 omapi_remote_auth_t
*ra
;
162 omapi_value_t
*signature
;
166 if (po
-> type
!= omapi_type_protocol
||
167 !po
-> outer
|| po
-> outer
-> type
!= omapi_type_connection
||
168 mo
-> type
!= omapi_type_message
)
169 return DHCP_R_INVALIDARG
;
170 if (omo
&& omo
-> type
!= omapi_type_message
)
171 return DHCP_R_INVALIDARG
;
172 p
= (omapi_protocol_object_t
*)po
;
173 c
= (omapi_object_t
*)(po
-> outer
);
174 m
= (omapi_message_object_t
*)mo
;
175 om
= (omapi_message_object_t
*)omo
;
177 #ifdef DEBUG_PROTOCOL
178 log_debug ("omapi_protocol_send_message(): "
179 "op=%s handle=%#lx id=%#lx rid=%#lx",
180 omapi_message_op_name (m
->op
),
181 (long)(m
-> object
? m
-> object
-> handle
: m
-> handle
),
182 (long)p
-> next_xid
, (long)m
-> rid
);
185 /* Find the authid to use for this message. */
187 for (ra
= p
-> remote_auth_list
; ra
; ra
= ra
-> next
) {
194 return DHCP_R_KEY_UNKNOWN
;
195 } else if (p
-> remote_auth_list
) {
196 ra
= p
-> default_auth
;
198 ra
= (omapi_remote_auth_t
*)0;
202 m
-> authid
= ra
-> remote_handle
;
203 status
= omapi_object_reference (&m
-> id_object
,
205 if (status
!= ISC_R_SUCCESS
)
209 /* Write the ID of the authentication key we're using. */
210 status
= omapi_connection_put_uint32 (c
, ra
? ra
-> remote_handle
: 0);
211 if (status
!= ISC_R_SUCCESS
) {
212 omapi_disconnect (c
, 1);
216 /* Activate the authentication key on the connection. */
219 status
= omapi_set_object_value (c
, (omapi_object_t
*)0,
220 "output-authenticator",
222 if (status
!= ISC_R_SUCCESS
) {
223 omapi_disconnect (c
, 1);
227 status
= omapi_connection_output_auth_length (c
, &auth_len
);
228 if (status
!= ISC_R_SUCCESS
) {
229 omapi_disconnect (c
, 1);
234 /* Write the authenticator length */
235 status
= omapi_connection_put_uint32 (c
, auth_len
);
236 if (status
!= ISC_R_SUCCESS
) {
237 omapi_disconnect (c
, 1);
241 /* Write the opcode. */
242 status
= omapi_connection_put_uint32 (c
, m
-> op
);
243 if (status
!= ISC_R_SUCCESS
) {
244 omapi_disconnect (c
, 1);
248 /* Write the handle. If we've been given an explicit handle, use
249 that. Otherwise, use the handle of the object we're sending.
250 The caller is responsible for arranging for one of these handles
251 to be set (or not). */
252 status
= omapi_connection_put_uint32 (c
, (m
-> h
255 ? m
-> object
-> handle
257 if (status
!= ISC_R_SUCCESS
) {
258 omapi_disconnect (c
, 1);
262 /* Set and write the transaction ID. */
263 m
-> id
= p
-> next_xid
++;
264 status
= omapi_connection_put_uint32 (c
, m
-> id
);
265 if (status
!= ISC_R_SUCCESS
) {
266 omapi_disconnect (c
, 1);
270 /* Write the transaction ID of the message to which this is a
271 response, if there is such a message. */
272 status
= omapi_connection_put_uint32 (c
, om
? om
-> id
: m
-> rid
);
273 if (status
!= ISC_R_SUCCESS
) {
274 omapi_disconnect (c
, 1);
278 /* Stuff out the name/value pairs specific to this message. */
279 status
= omapi_stuff_values (c
, id
, (omapi_object_t
*)m
);
280 if (status
!= ISC_R_SUCCESS
) {
281 omapi_disconnect (c
, 1);
285 /* Write the zero-length name that terminates the list of name/value
286 pairs specific to the message. */
287 status
= omapi_connection_put_uint16 (c
, 0);
288 if (status
!= ISC_R_SUCCESS
) {
289 omapi_disconnect (c
, 1);
293 /* Stuff out all the published name/value pairs in the object that's
294 being sent in the message, if there is one. */
296 status
= omapi_stuff_values (c
, id
, m
-> object
);
297 if (status
!= ISC_R_SUCCESS
) {
298 omapi_disconnect (c
, 1);
303 /* Write the zero-length name that terminates the list of name/value
304 pairs for the associated object. */
305 status
= omapi_connection_put_uint16 (c
, 0);
306 if (status
!= ISC_R_SUCCESS
) {
307 omapi_disconnect (c
, 1);
312 /* Calculate the message signature. */
313 signature
= (omapi_value_t
*)0;
314 status
= omapi_get_value_str (c
, (omapi_object_t
*)0,
315 "output-signature", &signature
);
316 if (status
!= ISC_R_SUCCESS
) {
317 omapi_disconnect (c
, 1);
321 /* Write the authenticator... */
322 status
= (omapi_connection_copyin
323 (c
, signature
-> value
-> u
.buffer
.value
,
324 signature
-> value
-> u
.buffer
.len
));
325 omapi_value_dereference (&signature
, MDL
);
326 if (status
!= ISC_R_SUCCESS
) {
327 omapi_disconnect (c
, 1);
331 /* Dectivate the authentication key on the connection. */
332 status
= omapi_set_value_str (c
, (omapi_object_t
*)0,
333 "output-authenticator",
334 (omapi_typed_data_t
*)0);
335 if (status
!= ISC_R_SUCCESS
) {
336 omapi_disconnect (c
, 1);
342 omapi_protocol_reference (&m
-> protocol_object
, p
, MDL
);
344 return ISC_R_SUCCESS
;
348 isc_result_t
omapi_protocol_signal_handler (omapi_object_t
*h
,
349 const char *name
, va_list ap
)
352 omapi_protocol_object_t
*p
;
354 omapi_message_object_t
*m
;
355 omapi_value_t
*signature
= NULL
;
359 #if defined (DEBUG_MEMORY_LEAKAGE)
360 unsigned long previous_outstanding
= 0xDEADBEEF;
361 unsigned long connect_outstanding
= 0xDEADBEEF;
364 if (h
-> type
!= omapi_type_protocol
) {
365 /* XXX shouldn't happen. Put an assert here? */
366 return ISC_R_UNEXPECTED
;
368 p
= (omapi_protocol_object_t
*)h
;
370 if (!strcmp (name
, "connect")) {
371 #if defined (DEBUG_MEMORY_LEAKAGE)
372 connect_outstanding
= dmalloc_outstanding
;
374 /* Send the introductory message. */
375 status
= omapi_protocol_send_intro
376 (h
, OMAPI_PROTOCOL_VERSION
,
377 sizeof (omapi_protocol_header_t
));
378 if (status
!= ISC_R_SUCCESS
) {
379 omapi_disconnect (p
-> outer
, 1);
382 return ISC_R_SUCCESS
;
385 /* Should only receive these when opening the initial authenticator. */
386 if (!strcmp (name
, "status")) {
387 status
= va_arg (ap
, isc_result_t
);
388 if (status
!= ISC_R_SUCCESS
) {
389 omapi_signal_in (h
-> inner
, "status", status
,
390 (omapi_object_t
*)0);
391 omapi_disconnect (p
-> outer
, 1);
394 return omapi_signal_in (h
-> inner
, "ready");
398 /* If we get a disconnect, dump memory usage. */
399 if (!strcmp (name
, "disconnect")) {
400 #if defined (DEBUG_MEMORY_LEAKAGE)
401 if (connect_outstanding
!= 0xDEADBEEF) {
402 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
404 dmalloc_outstanding
- previous_outstanding
,
405 dmalloc_outstanding
, dmalloc_longterm
, " long-term");
408 #if defined (DEBUG_MEMORY_LEAKAGE)
409 dmalloc_dump_outstanding ();
411 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
414 for (m
= omapi_registered_messages
; m
; m
= m
-> next
) {
415 if (m
-> protocol_object
== p
) {
417 omapi_signal (m
-> object
, "disconnect");
422 return ISC_R_SUCCESS
;
425 /* Not a signal we recognize? */
426 if (strcmp (name
, "ready")) {
427 if (p
-> inner
&& p
-> inner
-> type
-> signal_handler
)
428 return (*(p
-> inner
-> type
-> signal_handler
)) (h
,
431 return ISC_R_NOTFOUND
;
434 if (!p
-> outer
|| p
-> outer
-> type
!= omapi_type_connection
)
435 return DHCP_R_INVALIDARG
;
438 /* We get here because we requested that we be woken up after
439 some number of bytes were read, and that number of bytes
440 has in fact been read. */
441 switch (p
-> state
) {
442 case omapi_protocol_intro_wait
:
443 /* Get protocol version and header size in network
445 omapi_connection_get_uint32 (c
, &p
-> protocol_version
);
446 omapi_connection_get_uint32 (c
, &p
-> header_size
);
448 /* We currently only support the current protocol version. */
449 if (p
-> protocol_version
!= OMAPI_PROTOCOL_VERSION
) {
450 omapi_disconnect (c
, 1);
451 return DHCP_R_VERSIONMISMATCH
;
454 if (p
-> header_size
< sizeof (omapi_protocol_header_t
)) {
455 omapi_disconnect (c
, 1);
456 return DHCP_R_PROTOCOLERROR
;
459 if (p
-> default_auth
) {
460 status
= omapi_protocol_send_open
461 (h
, (omapi_object_t
*)0, "authenticator",
462 p
-> default_auth
-> a
,
463 OMAPI_NOTIFY_PROTOCOL
);
464 if (status
!= ISC_R_SUCCESS
) {
465 omapi_disconnect (c
, 1);
469 status
= omapi_signal_in (h
-> inner
, "ready");
473 /* The next thing we're expecting is a message header. */
474 p
-> state
= omapi_protocol_header_wait
;
476 /* Register a need for the number of bytes in a
477 header, and if we already have that many, process
479 if ((omapi_connection_require (c
, p
-> header_size
)) !=
482 /* If we already have the data, fall through. */
484 case omapi_protocol_header_wait
:
485 #if defined (DEBUG_MEMORY_LEAKAGE)
486 if (previous_outstanding
!= 0xDEADBEEF) {
487 log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
488 "generation", dmalloc_generation
,
489 dmalloc_outstanding
- previous_outstanding
,
490 dmalloc_outstanding
, dmalloc_longterm
,
493 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
494 dmalloc_dump_outstanding ();
496 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
499 #if defined (DEBUG_MEMORY_LEAKAGE)
501 previous_outstanding
= dmalloc_outstanding
;
503 status
= omapi_message_new ((omapi_object_t
**)&p
-> message
,
505 if (status
!= ISC_R_SUCCESS
) {
506 omapi_disconnect (c
, 1);
510 p
-> verify_result
= ISC_R_SUCCESS
;
512 /* Swap in the header... */
513 omapi_connection_get_uint32 (c
, &p
-> message
-> authid
);
515 /* Bind the authenticator to the message object. */
516 if (p
-> message
-> authid
) {
517 status
= (omapi_protocol_lookup_auth
518 (&p
-> message
-> id_object
, h
,
519 p
-> message
-> authid
));
520 if (status
!= ISC_R_SUCCESS
)
521 p
-> verify_result
= status
;
523 /* Activate the authentication key. */
524 status
= omapi_set_object_value
525 (c
, (omapi_object_t
*)0, "input-authenticator",
526 p
-> message
-> id_object
);
527 if (status
!= ISC_R_SUCCESS
) {
528 omapi_disconnect (c
, 1);
533 omapi_connection_get_uint32 (c
, &p
-> message
-> authlen
);
534 omapi_connection_get_uint32 (c
, &p
-> message
-> op
);
535 omapi_connection_get_uint32 (c
, &th
);
536 p
-> message
-> h
= th
;
537 omapi_connection_get_uint32 (c
, &p
-> message
-> id
);
538 omapi_connection_get_uint32 (c
, &p
-> message
-> rid
);
540 /* If there was any extra header data, skip over it. */
541 if (p
-> header_size
> sizeof (omapi_protocol_header_t
)) {
542 omapi_connection_copyout
543 (0, c
, (p
-> header_size
-
544 sizeof (omapi_protocol_header_t
)));
547 /* XXX must compute partial signature across the
548 XXX preceding bytes. Also, if authenticator
549 specifies encryption as well as signing, we may
550 have to decrypt the data on the way in. */
552 /* First we read in message-specific values, then object
554 p
-> reading_message_values
= 1;
557 /* The next thing we're expecting is length of the
559 p
-> state
= omapi_protocol_name_length_wait
;
561 /* Wait for a 16-bit length. */
562 if ((omapi_connection_require (c
, 2)) != ISC_R_SUCCESS
)
564 /* If it's already here, fall through. */
566 case omapi_protocol_name_length_wait
:
567 omapi_connection_get_uint16 (c
, &nlen
);
568 /* A zero-length name means that we're done reading name+value
571 /* If we've already read in the object, we are
572 done reading the message, but if we've just
573 finished reading in the values associated
574 with the message, we need to read the
576 if (p
-> reading_message_values
) {
577 p
-> reading_message_values
= 0;
578 goto need_name_length
;
581 /* If the authenticator length is zero, there's no
582 signature to read in, so go straight to processing
584 if (p
-> message
-> authlen
== 0)
587 /* The next thing we're expecting is the
588 message signature. */
589 p
-> state
= omapi_protocol_signature_wait
;
591 /* Wait for the number of bytes specified for
592 the authenticator. If we already have it,
594 if (omapi_connection_require
595 (c
, p
-> message
-> authlen
) == ISC_R_SUCCESS
)
600 /* Allocate a buffer for the name. */
601 status
= (omapi_data_string_new (&p
-> name
, nlen
, MDL
));
602 if (status
!= ISC_R_SUCCESS
) {
603 omapi_disconnect (c
, 1);
604 return ISC_R_NOMEMORY
;
606 p
-> state
= omapi_protocol_name_wait
;
607 if (omapi_connection_require (c
, nlen
) != ISC_R_SUCCESS
)
609 /* If it's already here, fall through. */
611 case omapi_protocol_name_wait
:
612 omapi_connection_copyout (p
-> name
-> value
, c
,
614 /* Wait for a 32-bit length. */
615 p
-> state
= omapi_protocol_value_length_wait
;
616 if ((omapi_connection_require (c
, 4)) != ISC_R_SUCCESS
)
618 /* If it's already here, fall through. */
620 case omapi_protocol_value_length_wait
:
621 omapi_connection_get_uint32 (c
, &vlen
);
623 /* Zero-length values are allowed - if we get one, we
624 don't have to read any data for the value - just
625 get the next one, if there is a next one. */
627 goto insert_new_value
;
629 status
= omapi_typed_data_new (MDL
, &p
-> value
,
632 if (status
!= ISC_R_SUCCESS
) {
633 omapi_disconnect (c
, 1);
634 return ISC_R_NOMEMORY
;
637 p
-> state
= omapi_protocol_value_wait
;
638 if (omapi_connection_require (c
, vlen
) != ISC_R_SUCCESS
)
640 /* If it's already here, fall through. */
642 case omapi_protocol_value_wait
:
643 omapi_connection_copyout (p
-> value
-> u
.buffer
.value
, c
,
644 p
-> value
-> u
.buffer
.len
);
647 if (p
-> reading_message_values
) {
648 status
= (omapi_set_value
649 ((omapi_object_t
*)p
-> message
,
650 p
-> message
-> id_object
,
651 p
-> name
, p
-> value
));
653 if (!p
-> message
-> object
) {
654 /* We need a generic object to hang off of the
656 status
= (omapi_generic_new
657 (&p
-> message
-> object
, MDL
));
658 if (status
!= ISC_R_SUCCESS
) {
659 omapi_disconnect (c
, 1);
663 status
= (omapi_set_value
664 ((omapi_object_t
*)p
-> message
-> object
,
665 p
-> message
-> id_object
,
666 p
-> name
, p
-> value
));
668 if (status
!= ISC_R_SUCCESS
) {
669 omapi_disconnect (c
, 1);
672 omapi_data_string_dereference (&p
-> name
, MDL
);
674 omapi_typed_data_dereference (&p
-> value
, MDL
);
675 goto need_name_length
;
678 case omapi_protocol_signature_wait
:
679 if (p
-> message
-> id_object
) {
680 /* Compute the signature of the message. */
681 status
= omapi_get_value_str (c
, (omapi_object_t
*)0,
684 if (status
!= ISC_R_SUCCESS
) {
685 omapi_disconnect (c
, 1);
689 /* Disable the authentication key on the connection. */
690 status
= omapi_set_value_str (c
, (omapi_object_t
*)0,
691 "input-authenticator",
692 (omapi_typed_data_t
*)0);
693 if (status
!= ISC_R_SUCCESS
) {
694 omapi_value_dereference (&signature
, MDL
);
695 omapi_disconnect (c
, 1);
700 /* Read the authenticator. */
701 status
= omapi_typed_data_new (MDL
,
702 &p
-> message
-> authenticator
,
704 p
-> message
-> authlen
);
706 if (status
!= ISC_R_SUCCESS
) {
707 if (signature
!= NULL
) {
708 omapi_value_dereference (&signature
, MDL
);
710 omapi_disconnect (c
, 1);
711 return ISC_R_NOMEMORY
;
713 omapi_connection_copyout
714 (p
-> message
-> authenticator
-> u
.buffer
.value
, c
,
715 p
-> message
-> authlen
);
717 /* Verify the signature. */
718 if (p
-> message
-> id_object
&&
719 ((signature
-> value
-> u
.buffer
.len
!=
720 p
-> message
-> authlen
) ||
721 (memcmp (signature
-> value
-> u
.buffer
.value
,
722 p
-> message
-> authenticator
-> u
.buffer
.value
,
723 p
-> message
-> authlen
) != 0))) {
724 /* Invalid signature. */
725 p
->verify_result
= DHCP_R_INVALIDKEY
;
728 if (signature
!= NULL
) {
729 omapi_value_dereference (&signature
, MDL
);
732 /* Process the message. */
734 if (p
-> verify_result
!= ISC_R_SUCCESS
) {
735 status
= omapi_protocol_send_status
736 (h
, (omapi_object_t
*)0, p
-> verify_result
,
737 p
-> message
-> id
, (char *)0);
739 status
= omapi_message_process
740 ((omapi_object_t
*)p
-> message
, h
);
742 if (status
!= ISC_R_SUCCESS
) {
743 omapi_disconnect (c
, 1);
744 return ISC_R_NOMEMORY
;
747 omapi_message_dereference (&p
-> message
, MDL
);
748 #if defined (DEBUG_MEMORY_LEAKAGE)
749 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
751 dmalloc_outstanding
- previous_outstanding
,
752 dmalloc_outstanding
, dmalloc_longterm
, " long-term");
754 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
755 dmalloc_dump_outstanding ();
757 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
760 #if defined (DEBUG_MEMORY_LEAKAGE)
761 previous_outstanding
= 0xDEADBEEF;
763 /* Now wait for the next message. */
767 /* XXX should never get here. Assertion? */
770 return ISC_R_SUCCESS
;
773 isc_result_t
omapi_protocol_add_auth (omapi_object_t
*po
,
775 omapi_handle_t handle
)
777 omapi_protocol_object_t
*p
;
778 omapi_remote_auth_t
*r
;
781 if (ao
-> type
!= omapi_type_auth_key
&&
782 (!ao
-> inner
|| ao
-> inner
-> type
!= omapi_type_auth_key
))
783 return DHCP_R_INVALIDARG
;
785 if (po
-> type
!= omapi_type_protocol
)
786 return DHCP_R_INVALIDARG
;
787 p
= (omapi_protocol_object_t
*)po
;
789 #ifdef DEBUG_PROTOCOL
790 log_debug ("omapi_protocol_add_auth(name=%s)",
791 ((omapi_auth_key_t
*)ao
) -> name
);
794 if (p
-> verify_auth
) {
795 status
= (p
-> verify_auth
) (po
, (omapi_auth_key_t
*)ao
);
796 if (status
!= ISC_R_SUCCESS
)
800 /* If omapi_protocol_connect() was called with a default
801 authenticator, p -> default_auth will already be set,
802 but p -> remote_auth_list will not yet be initialized. */
803 if (p
-> default_auth
&& !p
-> remote_auth_list
) {
804 if (p
-> default_auth
-> a
!= ao
) {
805 /* Something just went horribly wrong. */
806 omapi_disconnect (p
-> outer
, 1);
807 return ISC_R_UNEXPECTED
;
810 p
-> remote_auth_list
= p
-> default_auth
;
811 p
-> default_auth
-> remote_handle
= handle
;
813 return omapi_signal_in (p
-> inner
, "ready");
816 r
= dmalloc (sizeof(*r
), MDL
);
818 return ISC_R_NOMEMORY
;
820 status
= omapi_object_reference (&r
-> a
, ao
, MDL
);
821 if (status
!= ISC_R_SUCCESS
) {
826 r
-> remote_handle
= handle
;
827 r
-> next
= p
-> remote_auth_list
;
828 p
-> remote_auth_list
= r
;
830 return ISC_R_SUCCESS
;
833 isc_result_t
omapi_protocol_lookup_auth (omapi_object_t
**a
,
835 omapi_handle_t handle
)
837 omapi_protocol_object_t
*p
;
838 omapi_remote_auth_t
*r
;
840 if (po
-> type
!= omapi_type_protocol
)
841 return DHCP_R_INVALIDARG
;
842 p
= (omapi_protocol_object_t
*)po
;
844 for (r
= p
-> remote_auth_list
; r
; r
= r
-> next
)
845 if (r
-> remote_handle
== handle
)
846 return omapi_object_reference (a
, r
-> a
, MDL
);
848 return DHCP_R_KEY_UNKNOWN
;
851 isc_result_t
omapi_protocol_set_value (omapi_object_t
*h
,
853 omapi_data_string_t
*name
,
854 omapi_typed_data_t
*value
)
856 omapi_protocol_object_t
*p
;
857 omapi_remote_auth_t
*r
;
859 if (h
-> type
!= omapi_type_protocol
)
860 return DHCP_R_INVALIDARG
;
861 p
= (omapi_protocol_object_t
*)h
;
863 if (omapi_ds_strcmp (name
, "default-authenticator") == 0) {
864 if (!value
|| value
-> type
!= omapi_datatype_object
)
865 return DHCP_R_INVALIDARG
;
867 if (!value
-> u
.object
) {
868 p
-> default_auth
= (omapi_remote_auth_t
*)0;
870 for (r
= p
-> remote_auth_list
; r
; r
= r
-> next
)
871 if (r
-> a
== value
-> u
.object
)
875 return DHCP_R_KEY_UNKNOWN
;
877 p
-> default_auth
= r
;
880 return ISC_R_SUCCESS
;
883 if (h
-> inner
&& h
-> inner
-> type
-> set_value
)
884 return (*(h
-> inner
-> type
-> set_value
))
885 (h
-> inner
, id
, name
, value
);
886 return ISC_R_NOTFOUND
;
889 isc_result_t
omapi_protocol_get_value (omapi_object_t
*h
,
891 omapi_data_string_t
*name
,
892 omapi_value_t
**value
)
894 omapi_protocol_object_t
*p
;
896 if (h
-> type
!= omapi_type_protocol
)
897 return DHCP_R_INVALIDARG
;
898 p
= (omapi_protocol_object_t
*)h
;
900 if (omapi_ds_strcmp (name
, "default-authenticator") == 0) {
901 if (!p
-> default_auth
)
902 return ISC_R_NOTFOUND
;
904 return omapi_make_object_value (value
, name
,
905 p
-> default_auth
-> a
, MDL
);
908 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
909 return (*(h
-> inner
-> type
-> get_value
))
910 (h
-> inner
, id
, name
, value
);
911 return ISC_R_NOTFOUND
;
914 isc_result_t
omapi_protocol_destroy (omapi_object_t
*h
,
915 const char *file
, int line
)
917 omapi_protocol_object_t
*p
;
918 if (h
-> type
!= omapi_type_protocol
)
919 return DHCP_R_INVALIDARG
;
920 p
= (omapi_protocol_object_t
*)h
;
922 omapi_message_dereference (&p
-> message
, file
, line
);
924 /* This will happen if: 1) A default authenticator is supplied to
925 omapi_protocol_connect(), and 2) something goes wrong before
926 the authenticator can be opened. */
927 if (p
-> default_auth
&& !p
-> remote_auth_list
)
928 dfree (p
-> default_auth
, file
, line
);
930 while (p
-> remote_auth_list
) {
931 omapi_remote_auth_t
*r
= p
-> remote_auth_list
;
932 p
-> remote_auth_list
= p
-> remote_auth_list
-> next
;
933 omapi_object_dereference (&r
-> a
, file
, line
);
934 dfree (r
, file
, line
);
936 return ISC_R_SUCCESS
;
939 /* Write all the published values associated with the object through the
940 specified connection. */
942 isc_result_t
omapi_protocol_stuff_values (omapi_object_t
*c
,
946 if (p
-> type
!= omapi_type_protocol
)
947 return DHCP_R_INVALIDARG
;
949 if (p
-> inner
&& p
-> inner
-> type
-> stuff_values
)
950 return (*(p
-> inner
-> type
-> stuff_values
)) (c
, id
,
952 return ISC_R_SUCCESS
;
955 /* Returns a boolean indicating whether this protocol requires that
956 messages be authenticated or not. */
958 isc_boolean_t
omapi_protocol_authenticated (omapi_object_t
*h
)
960 if (h
-> type
!= omapi_type_protocol
)
961 return isc_boolean_false
;
962 if (((omapi_protocol_object_t
*)h
) -> insecure
)
963 return isc_boolean_false
;
965 return isc_boolean_true
;
968 /* Sets the address and authenticator verification callbacks. The handle
969 is to a listener object, not a protocol object. */
971 isc_result_t
omapi_protocol_configure_security (omapi_object_t
*h
,
972 isc_result_t (*verify_addr
)
975 isc_result_t (*verify_auth
)
979 omapi_protocol_listener_object_t
*l
;
981 if (h
-> outer
&& h
-> outer
-> type
== omapi_type_protocol_listener
)
984 if (h
-> type
!= omapi_type_protocol_listener
)
985 return DHCP_R_INVALIDARG
;
986 l
= (omapi_protocol_listener_object_t
*)h
;
988 l
-> verify_auth
= verify_auth
;
991 if (h
-> outer
!= NULL
) {
992 return omapi_listener_configure_security (h
-> outer
, verify_addr
);
994 return DHCP_R_INVALIDARG
;
999 /* Set up a listener for the omapi protocol. The handle stored points to
1000 a listener object, not a protocol object. */
1002 isc_result_t
omapi_protocol_listen (omapi_object_t
*h
,
1006 isc_result_t status
;
1007 omapi_protocol_listener_object_t
*obj
;
1009 obj
= (omapi_protocol_listener_object_t
*)0;
1010 status
= omapi_protocol_listener_allocate (&obj
, MDL
);
1011 if (status
!= ISC_R_SUCCESS
)
1014 status
= omapi_object_reference (&h
-> outer
,
1015 (omapi_object_t
*)obj
, MDL
);
1016 if (status
!= ISC_R_SUCCESS
) {
1017 omapi_protocol_listener_dereference (&obj
, MDL
);
1020 status
= omapi_object_reference (&obj
-> inner
, h
, MDL
);
1021 if (status
!= ISC_R_SUCCESS
) {
1022 omapi_protocol_listener_dereference (&obj
, MDL
);
1026 /* What a terrible default. */
1027 obj
-> insecure
= 1;
1029 status
= omapi_listen ((omapi_object_t
*)obj
, port
, max
);
1030 omapi_protocol_listener_dereference (&obj
, MDL
);
1034 /* Signal handler for protocol listener - if we get a connect signal,
1035 create a new protocol connection, otherwise pass the signal down. */
1037 isc_result_t
omapi_protocol_listener_signal (omapi_object_t
*o
,
1038 const char *name
, va_list ap
)
1040 isc_result_t status
;
1042 omapi_protocol_object_t
*obj
;
1043 omapi_protocol_listener_object_t
*p
;
1045 if (!o
|| o
-> type
!= omapi_type_protocol_listener
)
1046 return DHCP_R_INVALIDARG
;
1047 p
= (omapi_protocol_listener_object_t
*)o
;
1049 /* Not a signal we recognize? */
1050 if (strcmp (name
, "connect")) {
1051 if (p
-> inner
&& p
-> inner
-> type
-> signal_handler
)
1052 return (*(p
-> inner
-> type
-> signal_handler
))
1053 (p
-> inner
, name
, ap
);
1054 return ISC_R_NOTFOUND
;
1057 c
= va_arg (ap
, omapi_object_t
*);
1058 if (!c
|| c
-> type
!= omapi_type_connection
)
1059 return DHCP_R_INVALIDARG
;
1061 obj
= (omapi_protocol_object_t
*)0;
1062 status
= omapi_protocol_allocate (&obj
, MDL
);
1063 if (status
!= ISC_R_SUCCESS
)
1066 obj
-> verify_auth
= p
-> verify_auth
;
1067 obj
-> insecure
= p
-> insecure
;
1069 status
= omapi_object_reference (&obj
-> outer
, c
, MDL
);
1070 if (status
!= ISC_R_SUCCESS
) {
1072 omapi_protocol_dereference (&obj
, MDL
);
1073 omapi_disconnect (c
, 1);
1077 status
= omapi_object_reference (&c
-> inner
,
1078 (omapi_object_t
*)obj
, MDL
);
1079 if (status
!= ISC_R_SUCCESS
)
1082 /* Send the introductory message. */
1083 status
= omapi_protocol_send_intro ((omapi_object_t
*)obj
,
1084 OMAPI_PROTOCOL_VERSION
,
1085 sizeof (omapi_protocol_header_t
));
1086 if (status
!= ISC_R_SUCCESS
)
1089 omapi_protocol_dereference (&obj
, MDL
);
1093 isc_result_t
omapi_protocol_listener_set_value (omapi_object_t
*h
,
1095 omapi_data_string_t
*name
,
1096 omapi_typed_data_t
*value
)
1098 if (h
-> type
!= omapi_type_protocol_listener
)
1099 return DHCP_R_INVALIDARG
;
1101 if (h
-> inner
&& h
-> inner
-> type
-> set_value
)
1102 return (*(h
-> inner
-> type
-> set_value
))
1103 (h
-> inner
, id
, name
, value
);
1104 return ISC_R_NOTFOUND
;
1107 isc_result_t
omapi_protocol_listener_get_value (omapi_object_t
*h
,
1109 omapi_data_string_t
*name
,
1110 omapi_value_t
**value
)
1112 if (h
-> type
!= omapi_type_protocol_listener
)
1113 return DHCP_R_INVALIDARG
;
1115 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
1116 return (*(h
-> inner
-> type
-> get_value
))
1117 (h
-> inner
, id
, name
, value
);
1118 return ISC_R_NOTFOUND
;
1121 isc_result_t
omapi_protocol_listener_destroy (omapi_object_t
*h
,
1122 const char *file
, int line
)
1124 if (h
-> type
!= omapi_type_protocol_listener
)
1125 return DHCP_R_INVALIDARG
;
1126 return ISC_R_SUCCESS
;
1129 /* Write all the published values associated with the object through the
1130 specified connection. */
1132 isc_result_t
omapi_protocol_listener_stuff (omapi_object_t
*c
,
1136 if (p
-> type
!= omapi_type_protocol_listener
)
1137 return DHCP_R_INVALIDARG
;
1139 if (p
-> inner
&& p
-> inner
-> type
-> stuff_values
)
1140 return (*(p
-> inner
-> type
-> stuff_values
)) (c
, id
,
1142 return ISC_R_SUCCESS
;
1145 isc_result_t
omapi_protocol_send_status (omapi_object_t
*po
,
1147 isc_result_t waitstatus
,
1148 unsigned rid
, const char *msg
)
1150 isc_result_t status
;
1151 omapi_message_object_t
*message
= (omapi_message_object_t
*)0;
1154 if (po
-> type
!= omapi_type_protocol
)
1155 return DHCP_R_INVALIDARG
;
1157 status
= omapi_message_new ((omapi_object_t
**)&message
, MDL
);
1158 if (status
!= ISC_R_SUCCESS
)
1160 mo
= (omapi_object_t
*)message
;
1162 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1163 "op", OMAPI_OP_STATUS
);
1164 if (status
!= ISC_R_SUCCESS
) {
1165 omapi_message_dereference (&message
, MDL
);
1169 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1171 if (status
!= ISC_R_SUCCESS
) {
1172 omapi_message_dereference (&message
, MDL
);
1176 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1177 "result", (int)waitstatus
);
1178 if (status
!= ISC_R_SUCCESS
) {
1179 omapi_message_dereference (&message
, MDL
);
1183 /* If a message has been provided, send it. */
1185 status
= omapi_set_string_value (mo
, (omapi_object_t
*)0,
1187 if (status
!= ISC_R_SUCCESS
) {
1188 omapi_message_dereference (&message
, MDL
);
1193 status
= omapi_protocol_send_message (po
, id
, mo
, (omapi_object_t
*)0);
1194 omapi_message_dereference (&message
, MDL
);
1198 /* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the
1199 message to be set to the protocol object. This is used when opening
1200 the default authenticator. */
1202 isc_result_t
omapi_protocol_send_open (omapi_object_t
*po
,
1205 omapi_object_t
*object
,
1208 isc_result_t status
;
1209 omapi_message_object_t
*message
= (omapi_message_object_t
*)0;
1212 if (po
-> type
!= omapi_type_protocol
)
1213 return DHCP_R_INVALIDARG
;
1215 status
= omapi_message_new ((omapi_object_t
**)&message
, MDL
);
1216 mo
= (omapi_object_t
*)message
;
1218 if (status
== ISC_R_SUCCESS
)
1219 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1220 "op", OMAPI_OP_OPEN
);
1222 if (status
== ISC_R_SUCCESS
)
1223 status
= omapi_set_object_value (mo
, (omapi_object_t
*)0,
1226 if ((flags
& OMAPI_CREATE
) && (status
== ISC_R_SUCCESS
))
1227 status
= omapi_set_boolean_value (mo
, (omapi_object_t
*)0,
1230 if ((flags
& OMAPI_UPDATE
) && (status
== ISC_R_SUCCESS
))
1231 status
= omapi_set_boolean_value (mo
, (omapi_object_t
*)0,
1234 if ((flags
& OMAPI_EXCL
) && (status
== ISC_R_SUCCESS
))
1235 status
= omapi_set_boolean_value (mo
, (omapi_object_t
*)0,
1238 if ((flags
& OMAPI_NOTIFY_PROTOCOL
) && (status
== ISC_R_SUCCESS
))
1239 status
= omapi_set_object_value (mo
, (omapi_object_t
*)0,
1240 "notify-object", po
);
1242 if (type
&& (status
== ISC_R_SUCCESS
))
1243 status
= omapi_set_string_value (mo
, (omapi_object_t
*)0,
1246 if (status
== ISC_R_SUCCESS
)
1247 status
= omapi_message_register (mo
);
1249 if (status
== ISC_R_SUCCESS
) {
1250 status
= omapi_protocol_send_message (po
, id
, mo
,
1251 (omapi_object_t
*)0);
1252 if (status
!= ISC_R_SUCCESS
)
1253 omapi_message_unregister (mo
);
1257 omapi_message_dereference (&message
, MDL
);
1262 isc_result_t
omapi_protocol_send_update (omapi_object_t
*po
,
1265 omapi_object_t
*object
)
1267 isc_result_t status
;
1268 omapi_message_object_t
*message
= (omapi_message_object_t
*)0;
1271 if (po
-> type
!= omapi_type_protocol
)
1272 return DHCP_R_INVALIDARG
;
1274 status
= omapi_message_new ((omapi_object_t
**)&message
, MDL
);
1275 if (status
!= ISC_R_SUCCESS
)
1277 mo
= (omapi_object_t
*)message
;
1279 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1280 "op", OMAPI_OP_UPDATE
);
1281 if (status
!= ISC_R_SUCCESS
) {
1282 omapi_message_dereference (&message
, MDL
);
1287 omapi_handle_t handle
;
1288 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1290 if (status
!= ISC_R_SUCCESS
) {
1291 omapi_message_dereference (&message
, MDL
);
1295 status
= omapi_object_handle (&handle
, object
);
1296 if (status
!= ISC_R_SUCCESS
) {
1297 omapi_message_dereference (&message
, MDL
);
1300 status
= omapi_set_int_value (mo
, (omapi_object_t
*)0,
1301 "handle", (int)handle
);
1302 if (status
!= ISC_R_SUCCESS
) {
1303 omapi_message_dereference (&message
, MDL
);
1308 status
= omapi_set_object_value (mo
, (omapi_object_t
*)0,
1310 if (status
!= ISC_R_SUCCESS
) {
1311 omapi_message_dereference (&message
, MDL
);
1315 status
= omapi_protocol_send_message (po
, id
, mo
, (omapi_object_t
*)0);
1316 omapi_message_dereference (&message
, MDL
);