Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / dhcp / omapip / protocol.c
blob17b4bfe8007186886e03b83b63d3b7a62c252ad7
1 /* protocol.c
3 Functions supporting the object management protocol... */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1999-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #include <omapip/omapip_p.h>
37 OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
38 omapi_type_protocol)
39 OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
40 omapi_type_protocol_listener)
42 isc_result_t omapi_protocol_connect (omapi_object_t *h,
43 const char *server_name,
44 unsigned port,
45 omapi_object_t *a)
47 isc_result_t rstatus, status;
48 omapi_protocol_object_t *obj;
50 #ifdef DEBUG_PROTOCOL
51 log_debug ("omapi_protocol_connect(%s port=%d)", server_name, port);
52 #endif
54 obj = (omapi_protocol_object_t *)0;
55 status = omapi_protocol_allocate (&obj, MDL);
56 if (status != ISC_R_SUCCESS)
57 return status;
59 rstatus = omapi_connect ((omapi_object_t *)obj, server_name, port);
60 if (rstatus != ISC_R_SUCCESS && rstatus != ISC_R_INCOMPLETE) {
61 omapi_protocol_dereference (&obj, MDL);
62 return rstatus;
64 status = omapi_object_reference (&h -> outer,
65 (omapi_object_t *)obj, MDL);
66 if (status != ISC_R_SUCCESS) {
67 omapi_protocol_dereference (&obj, MDL);
68 return status;
70 status = omapi_object_reference (&obj -> inner, h, MDL);
71 if (status != ISC_R_SUCCESS) {
72 omapi_protocol_dereference (&obj, MDL);
73 return status;
76 /* If we were passed a default authenticator, store it now. We'll
77 open it once we're connected. */
78 if (a) {
79 obj -> default_auth =
80 dmalloc (sizeof(omapi_remote_auth_t), MDL);
81 if (!obj -> default_auth) {
82 omapi_protocol_dereference (&obj, MDL);
83 return ISC_R_NOMEMORY;
86 obj -> default_auth -> next = (omapi_remote_auth_t *)0;
87 status = omapi_object_reference (&obj -> default_auth -> a,
88 a, MDL);
89 if (status != ISC_R_SUCCESS) {
90 dfree (obj -> default_auth, MDL);
91 omapi_protocol_dereference (&obj, MDL);
92 return status;
95 obj -> insecure = 0;
96 rstatus = ISC_R_INCOMPLETE;
97 } else {
98 obj -> insecure = 1;
99 rstatus = ISC_R_SUCCESS;
102 omapi_protocol_dereference (&obj, MDL);
103 return rstatus;
106 /* Send the protocol introduction message. */
107 isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
108 unsigned ver,
109 unsigned hsize)
111 isc_result_t status;
112 omapi_protocol_object_t *p;
114 #ifdef DEBUG_PROTOCOL
115 log_debug ("omapi_protocol_send_intro()");
116 #endif
118 if (h -> type != omapi_type_protocol)
119 return ISC_R_INVALIDARG;
120 p = (omapi_protocol_object_t *)h;
122 if (!h -> outer || h -> outer -> type != omapi_type_connection)
123 return ISC_R_NOTCONNECTED;
125 status = omapi_connection_put_uint32 (h -> outer, ver);
126 if (status != ISC_R_SUCCESS)
127 return status;
129 status = omapi_connection_put_uint32 (h -> outer, hsize);
131 if (status != ISC_R_SUCCESS)
132 return status;
134 /* Require the other end to send an intro - this kicks off the
135 protocol input state machine. */
136 p -> state = omapi_protocol_intro_wait;
137 status = omapi_connection_require (h -> outer, 8);
138 if (status != ISC_R_SUCCESS && status != ISC_R_NOTYET)
139 return status;
141 /* Make up an initial transaction ID for this connection. */
142 p -> next_xid = random ();
143 return ISC_R_SUCCESS;
146 isc_result_t omapi_protocol_send_message (omapi_object_t *po,
147 omapi_object_t *id,
148 omapi_object_t *mo,
149 omapi_object_t *omo)
151 omapi_protocol_object_t *p;
152 omapi_object_t *c;
153 omapi_message_object_t *m, *om;
154 omapi_remote_auth_t *ra;
155 omapi_value_t *signature;
156 isc_result_t status;
157 unsigned auth_len;
159 if (po -> type != omapi_type_protocol ||
160 !po -> outer || po -> outer -> type != omapi_type_connection ||
161 mo -> type != omapi_type_message)
162 return ISC_R_INVALIDARG;
163 if (omo && omo -> type != omapi_type_message)
164 return ISC_R_INVALIDARG;
165 p = (omapi_protocol_object_t *)po;
166 c = (omapi_object_t *)(po -> outer);
167 m = (omapi_message_object_t *)mo;
168 om = (omapi_message_object_t *)omo;
170 #ifdef DEBUG_PROTOCOL
171 log_debug ("omapi_protocol_send_message()"
172 "op=%ld handle=%#lx id=%#lx rid=%#lx",
173 (long)m -> op,
174 (long)(m -> object ? m -> object -> handle : m -> handle),
175 (long)p -> next_xid, (long)m -> rid);
176 #endif
178 /* Find the authid to use for this message. */
179 if (id) {
180 for (ra = p -> remote_auth_list; ra; ra = ra -> next) {
181 if (ra -> a == id) {
182 break;
186 if (!ra)
187 return ISC_R_KEY_UNKNOWN;
188 } else if (p -> remote_auth_list) {
189 ra = p -> default_auth;
190 } else {
191 ra = (omapi_remote_auth_t *)0;
194 if (ra) {
195 m -> authid = ra -> remote_handle;
196 status = omapi_object_reference (&m -> id_object,
197 ra -> a, MDL);
198 if (status != ISC_R_SUCCESS)
199 return status;
202 /* Write the ID of the authentication key we're using. */
203 status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0);
204 if (status != ISC_R_SUCCESS) {
205 omapi_disconnect (c, 1);
206 return status;
209 /* Activate the authentication key on the connection. */
210 auth_len = 0;
211 if (ra) {
212 status = omapi_set_object_value (c, (omapi_object_t *)0,
213 "output-authenticator",
214 ra -> a);
215 if (status != ISC_R_SUCCESS) {
216 omapi_disconnect (c, 1);
217 return status;
220 status = omapi_connection_output_auth_length (c, &auth_len);
221 if (status != ISC_R_SUCCESS) {
222 omapi_disconnect (c, 1);
223 return status;
227 /* Write the authenticator length */
228 status = omapi_connection_put_uint32 (c, auth_len);
229 if (status != ISC_R_SUCCESS) {
230 omapi_disconnect (c, 1);
231 return status;
234 /* Write the opcode. */
235 status = omapi_connection_put_uint32 (c, m -> op);
236 if (status != ISC_R_SUCCESS) {
237 omapi_disconnect (c, 1);
238 return status;
241 /* Write the handle. If we've been given an explicit handle, use
242 that. Otherwise, use the handle of the object we're sending.
243 The caller is responsible for arranging for one of these handles
244 to be set (or not). */
245 status = omapi_connection_put_uint32 (c, (m -> h
246 ? m -> h
247 : (m -> object
248 ? m -> object -> handle
249 : 0)));
250 if (status != ISC_R_SUCCESS) {
251 omapi_disconnect (c, 1);
252 return status;
255 /* Set and write the transaction ID. */
256 m -> id = p -> next_xid++;
257 status = omapi_connection_put_uint32 (c, m -> id);
258 if (status != ISC_R_SUCCESS) {
259 omapi_disconnect (c, 1);
260 return status;
263 /* Write the transaction ID of the message to which this is a
264 response, if there is such a message. */
265 status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
266 if (status != ISC_R_SUCCESS) {
267 omapi_disconnect (c, 1);
268 return status;
271 /* Stuff out the name/value pairs specific to this message. */
272 status = omapi_stuff_values (c, id, (omapi_object_t *)m);
273 if (status != ISC_R_SUCCESS) {
274 omapi_disconnect (c, 1);
275 return status;
278 /* Write the zero-length name that terminates the list of name/value
279 pairs specific to the message. */
280 status = omapi_connection_put_uint16 (c, 0);
281 if (status != ISC_R_SUCCESS) {
282 omapi_disconnect (c, 1);
283 return status;
286 /* Stuff out all the published name/value pairs in the object that's
287 being sent in the message, if there is one. */
288 if (m -> object) {
289 status = omapi_stuff_values (c, id, m -> object);
290 if (status != ISC_R_SUCCESS) {
291 omapi_disconnect (c, 1);
292 return status;
296 /* Write the zero-length name that terminates the list of name/value
297 pairs for the associated object. */
298 status = omapi_connection_put_uint16 (c, 0);
299 if (status != ISC_R_SUCCESS) {
300 omapi_disconnect (c, 1);
301 return status;
304 if (ra) {
305 /* Calculate the message signature. */
306 signature = (omapi_value_t *)0;
307 status = omapi_get_value_str (c, (omapi_object_t *)0,
308 "output-signature", &signature);
309 if (status != ISC_R_SUCCESS) {
310 omapi_disconnect (c, 1);
311 return status;
314 /* Write the authenticator... */
315 status = (omapi_connection_copyin
316 (c, signature -> value -> u.buffer.value,
317 signature -> value -> u.buffer.len));
318 omapi_value_dereference (&signature, MDL);
319 if (status != ISC_R_SUCCESS) {
320 omapi_disconnect (c, 1);
321 return status;
324 /* Dectivate the authentication key on the connection. */
325 status = omapi_set_value_str (c, (omapi_object_t *)0,
326 "output-authenticator",
327 (omapi_typed_data_t *)0);
328 if (status != ISC_R_SUCCESS) {
329 omapi_disconnect (c, 1);
330 return status;
334 if (!omo) {
335 omapi_protocol_reference (&m -> protocol_object, p, MDL);
337 return ISC_R_SUCCESS;
341 isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
342 const char *name, va_list ap)
344 isc_result_t status;
345 omapi_protocol_object_t *p;
346 omapi_object_t *c;
347 omapi_message_object_t *m;
348 omapi_value_t *signature;
349 u_int16_t nlen;
350 u_int32_t vlen;
351 u_int32_t th;
352 #if defined (DEBUG_MEMORY_LEAKAGE)
353 unsigned long previous_outstanding = 0xDEADBEEF;
354 unsigned long connect_outstanding = 0xDEADBEEF;
355 #endif
357 if (h -> type != omapi_type_protocol) {
358 /* XXX shouldn't happen. Put an assert here? */
359 return ISC_R_UNEXPECTED;
361 p = (omapi_protocol_object_t *)h;
363 if (!strcmp (name, "connect")) {
364 #if defined (DEBUG_MEMORY_LEAKAGE)
365 connect_outstanding = dmalloc_outstanding;
366 #endif
367 /* Send the introductory message. */
368 status = omapi_protocol_send_intro
369 (h, OMAPI_PROTOCOL_VERSION,
370 sizeof (omapi_protocol_header_t));
371 if (status != ISC_R_SUCCESS) {
372 omapi_disconnect (p -> outer, 1);
373 return status;
375 return ISC_R_SUCCESS;
378 /* Should only receive these when opening the initial authenticator. */
379 if (!strcmp (name, "status")) {
380 status = va_arg (ap, isc_result_t);
381 if (status != ISC_R_SUCCESS) {
382 omapi_signal_in (h -> inner, "status", status,
383 (omapi_object_t *)0);
384 omapi_disconnect (p -> outer, 1);
385 return status;
386 } else {
387 return omapi_signal_in (h -> inner, "ready");
391 /* If we get a disconnect, dump memory usage. */
392 if (!strcmp (name, "disconnect")) {
393 #if defined (DEBUG_MEMORY_LEAKAGE)
394 if (connect_outstanding != 0xDEADBEEF) {
395 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
396 dmalloc_generation,
397 dmalloc_outstanding - previous_outstanding,
398 dmalloc_outstanding, dmalloc_longterm, " long-term");
400 #endif
401 #if defined (DEBUG_MEMORY_LEAKAGE)
402 dmalloc_dump_outstanding ();
403 #endif
404 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
405 dump_rc_history ();
406 #endif
407 for (m = omapi_registered_messages; m; m = m -> next) {
408 if (m -> protocol_object == p) {
409 if (m -> object)
410 omapi_signal (m -> object, "disconnect");
415 /* Not a signal we recognize? */
416 if (strcmp (name, "ready")) {
417 if (p -> inner && p -> inner -> type -> signal_handler)
418 return (*(p -> inner -> type -> signal_handler)) (h,
419 name,
420 ap);
421 return ISC_R_NOTFOUND;
424 if (!p -> outer || p -> outer -> type != omapi_type_connection)
425 return ISC_R_INVALIDARG;
426 c = p -> outer;
428 /* We get here because we requested that we be woken up after
429 some number of bytes were read, and that number of bytes
430 has in fact been read. */
431 switch (p -> state) {
432 case omapi_protocol_intro_wait:
433 /* Get protocol version and header size in network
434 byte order. */
435 omapi_connection_get_uint32 (c, &p -> protocol_version);
436 omapi_connection_get_uint32 (c, &p -> header_size);
438 /* We currently only support the current protocol version. */
439 if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
440 omapi_disconnect (c, 1);
441 return ISC_R_VERSIONMISMATCH;
444 if (p -> header_size < sizeof (omapi_protocol_header_t)) {
445 omapi_disconnect (c, 1);
446 return ISC_R_PROTOCOLERROR;
449 if (p -> default_auth) {
450 status = omapi_protocol_send_open
451 (h, (omapi_object_t *)0, "authenticator",
452 p -> default_auth -> a,
453 OMAPI_NOTIFY_PROTOCOL);
454 if (status != ISC_R_SUCCESS) {
455 omapi_disconnect (c, 1);
456 return status;
458 } else {
459 status = omapi_signal_in (h -> inner, "ready");
462 to_header_wait:
463 /* The next thing we're expecting is a message header. */
464 p -> state = omapi_protocol_header_wait;
466 /* Register a need for the number of bytes in a
467 header, and if we already have that many, process
468 them immediately. */
469 if ((omapi_connection_require (c, p -> header_size)) !=
470 ISC_R_SUCCESS)
471 break;
472 /* If we already have the data, fall through. */
474 case omapi_protocol_header_wait:
475 #if defined (DEBUG_MEMORY_LEAKAGE)
476 if (previous_outstanding != 0xDEADBEEF) {
477 log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
478 "generation", dmalloc_generation,
479 dmalloc_outstanding - previous_outstanding,
480 dmalloc_outstanding, dmalloc_longterm,
481 " long-term");
482 #endif
483 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
484 dmalloc_dump_outstanding ();
485 #endif
486 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
487 dump_rc_history ();
488 #endif
489 #if defined (DEBUG_MEMORY_LEAKAGE)
491 previous_outstanding = dmalloc_outstanding;
492 #endif
493 status = omapi_message_new ((omapi_object_t **)&p -> message,
494 MDL);
495 if (status != ISC_R_SUCCESS) {
496 omapi_disconnect (c, 1);
497 return status;
500 p -> verify_result = ISC_R_SUCCESS;
502 /* Swap in the header... */
503 omapi_connection_get_uint32 (c, &p -> message -> authid);
505 /* Bind the authenticator to the message object. */
506 if (p -> message -> authid) {
507 status = (omapi_protocol_lookup_auth
508 (&p -> message -> id_object, h,
509 p -> message -> authid));
510 if (status != ISC_R_SUCCESS)
511 p -> verify_result = status;
513 /* Activate the authentication key. */
514 status = omapi_set_object_value
515 (c, (omapi_object_t *)0, "input-authenticator",
516 p -> message -> id_object);
517 if (status != ISC_R_SUCCESS) {
518 omapi_disconnect (c, 1);
519 return status;
523 omapi_connection_get_uint32 (c, &p -> message -> authlen);
524 omapi_connection_get_uint32 (c, &p -> message -> op);
525 omapi_connection_get_uint32 (c, &th);
526 p -> message -> h = th;
527 omapi_connection_get_uint32 (c, &p -> message -> id);
528 omapi_connection_get_uint32 (c, &p -> message -> rid);
530 /* If there was any extra header data, skip over it. */
531 if (p -> header_size > sizeof (omapi_protocol_header_t)) {
532 omapi_connection_copyout
533 (0, c, (p -> header_size -
534 sizeof (omapi_protocol_header_t)));
537 /* XXX must compute partial signature across the
538 XXX preceding bytes. Also, if authenticator
539 specifies encryption as well as signing, we may
540 have to decrypt the data on the way in. */
542 /* First we read in message-specific values, then object
543 values. */
544 p -> reading_message_values = 1;
546 need_name_length:
547 /* The next thing we're expecting is length of the
548 first name. */
549 p -> state = omapi_protocol_name_length_wait;
551 /* Wait for a 16-bit length. */
552 if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
553 break;
554 /* If it's already here, fall through. */
556 case omapi_protocol_name_length_wait:
557 omapi_connection_get_uint16 (c, &nlen);
558 /* A zero-length name means that we're done reading name+value
559 pairs. */
560 if (nlen == 0) {
561 /* If we've already read in the object, we are
562 done reading the message, but if we've just
563 finished reading in the values associated
564 with the message, we need to read the
565 object. */
566 if (p -> reading_message_values) {
567 p -> reading_message_values = 0;
568 goto need_name_length;
571 /* If the authenticator length is zero, there's no
572 signature to read in, so go straight to processing
573 the message. */
574 if (p -> message -> authlen == 0)
575 goto message_done;
577 /* The next thing we're expecting is the
578 message signature. */
579 p -> state = omapi_protocol_signature_wait;
581 /* Wait for the number of bytes specified for
582 the authenticator. If we already have it,
583 go read it in. */
584 if (omapi_connection_require
585 (c, p -> message -> authlen) == ISC_R_SUCCESS)
586 goto signature_wait;
587 break;
590 /* Allocate a buffer for the name. */
591 status = (omapi_data_string_new (&p -> name, nlen, MDL));
592 if (status != ISC_R_SUCCESS) {
593 omapi_disconnect (c, 1);
594 return ISC_R_NOMEMORY;
596 p -> state = omapi_protocol_name_wait;
597 if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
598 break;
599 /* If it's already here, fall through. */
601 case omapi_protocol_name_wait:
602 omapi_connection_copyout (p -> name -> value, c,
603 p -> name -> len);
604 /* Wait for a 32-bit length. */
605 p -> state = omapi_protocol_value_length_wait;
606 if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
607 break;
608 /* If it's already here, fall through. */
610 case omapi_protocol_value_length_wait:
611 omapi_connection_get_uint32 (c, &vlen);
613 /* Zero-length values are allowed - if we get one, we
614 don't have to read any data for the value - just
615 get the next one, if there is a next one. */
616 if (!vlen)
617 goto insert_new_value;
619 status = omapi_typed_data_new (MDL, &p -> value,
620 omapi_datatype_data,
621 vlen);
622 if (status != ISC_R_SUCCESS) {
623 omapi_disconnect (c, 1);
624 return ISC_R_NOMEMORY;
627 p -> state = omapi_protocol_value_wait;
628 if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
629 break;
630 /* If it's already here, fall through. */
632 case omapi_protocol_value_wait:
633 omapi_connection_copyout (p -> value -> u.buffer.value, c,
634 p -> value -> u.buffer.len);
636 insert_new_value:
637 if (p -> reading_message_values) {
638 status = (omapi_set_value
639 ((omapi_object_t *)p -> message,
640 p -> message -> id_object,
641 p -> name, p -> value));
642 } else {
643 if (!p -> message -> object) {
644 /* We need a generic object to hang off of the
645 incoming message. */
646 status = (omapi_generic_new
647 (&p -> message -> object, MDL));
648 if (status != ISC_R_SUCCESS) {
649 omapi_disconnect (c, 1);
650 return status;
653 status = (omapi_set_value
654 ((omapi_object_t *)p -> message -> object,
655 p -> message -> id_object,
656 p -> name, p -> value));
658 if (status != ISC_R_SUCCESS) {
659 omapi_disconnect (c, 1);
660 return status;
662 omapi_data_string_dereference (&p -> name, MDL);
663 if (p -> value)
664 omapi_typed_data_dereference (&p -> value, MDL);
665 goto need_name_length;
667 signature_wait:
668 case omapi_protocol_signature_wait:
669 if (p -> message -> id_object) {
670 /* Compute the signature of the message. */
671 signature = (omapi_value_t *)0;
672 status = omapi_get_value_str (c, (omapi_object_t *)0,
673 "input-signature",
674 &signature);
675 if (status != ISC_R_SUCCESS) {
676 omapi_disconnect (c, 1);
677 return status;
680 /* Disable the authentication key on the connection. */
681 status = omapi_set_value_str (c, (omapi_object_t *)0,
682 "input-authenticator",
683 (omapi_typed_data_t *)0);
684 if (status != ISC_R_SUCCESS) {
685 omapi_value_dereference (&signature, MDL);
686 omapi_disconnect (c, 1);
687 return status;
691 /* Read the authenticator. */
692 status = omapi_typed_data_new (MDL,
693 &p -> message -> authenticator,
694 omapi_datatype_data,
695 p -> message -> authlen);
697 if (status != ISC_R_SUCCESS) {
698 omapi_value_dereference (&signature, MDL);
699 omapi_disconnect (c, 1);
700 return ISC_R_NOMEMORY;
702 omapi_connection_copyout
703 (p -> message -> authenticator -> u.buffer.value, c,
704 p -> message -> authlen);
706 /* Verify the signature. */
707 if (p -> message -> id_object &&
708 ((signature -> value -> u.buffer.len !=
709 p -> message -> authlen) ||
710 (memcmp (signature -> value -> u.buffer.value,
711 p -> message -> authenticator -> u.buffer.value,
712 p -> message -> authlen) != 0))) {
713 /* Invalid signature. */
714 p -> verify_result = ISC_R_INVALIDKEY;
717 omapi_value_dereference (&signature, MDL);
719 /* Process the message. */
720 message_done:
721 if (p -> verify_result != ISC_R_SUCCESS) {
722 status = omapi_protocol_send_status
723 (h, (omapi_object_t *)0, p -> verify_result,
724 p -> message -> id, (char *)0);
725 } else {
726 status = omapi_message_process
727 ((omapi_object_t *)p -> message, h);
729 if (status != ISC_R_SUCCESS) {
730 omapi_disconnect (c, 1);
731 return ISC_R_NOMEMORY;
734 omapi_message_dereference (&p -> message, MDL);
735 #if defined (DEBUG_MEMORY_LEAKAGE)
736 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
737 dmalloc_generation,
738 dmalloc_outstanding - previous_outstanding,
739 dmalloc_outstanding, dmalloc_longterm, " long-term");
740 #endif
741 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
742 dmalloc_dump_outstanding ();
743 #endif
744 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
745 dump_rc_history ();
746 #endif
747 #if defined (DEBUG_MEMORY_LEAKAGE)
748 previous_outstanding = 0xDEADBEEF;
749 #endif
750 /* Now wait for the next message. */
751 goto to_header_wait;
753 default:
754 /* XXX should never get here. Assertion? */
755 break;
757 return ISC_R_SUCCESS;
760 isc_result_t omapi_protocol_add_auth (omapi_object_t *po,
761 omapi_object_t *ao,
762 omapi_handle_t handle)
764 omapi_protocol_object_t *p;
765 omapi_remote_auth_t *r;
766 isc_result_t status;
768 if (ao -> type != omapi_type_auth_key &&
769 (!ao -> inner || ao -> inner -> type != omapi_type_auth_key))
770 return ISC_R_INVALIDARG;
772 if (po -> type != omapi_type_protocol)
773 return ISC_R_INVALIDARG;
774 p = (omapi_protocol_object_t *)po;
776 #ifdef DEBUG_PROTOCOL
777 log_debug ("omapi_protocol_add_auth(name=%s)",
778 ((omapi_auth_key_t *)ao) -> name);
779 #endif
781 if (p -> verify_auth) {
782 status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao);
783 if (status != ISC_R_SUCCESS)
784 return status;
787 /* If omapi_protocol_connect() was called with a default
788 authenticator, p -> default_auth will already be set,
789 but p -> remote_auth_list will not yet be initialized. */
790 if (p -> default_auth && !p -> remote_auth_list) {
791 if (p -> default_auth -> a != ao) {
792 /* Something just went horribly wrong. */
793 omapi_disconnect (p -> outer, 1);
794 return ISC_R_UNEXPECTED;
797 p -> remote_auth_list = p -> default_auth;
798 p -> default_auth -> remote_handle = handle;
800 return omapi_signal_in (p -> inner, "ready");
803 r = dmalloc (sizeof(*r), MDL);
804 if (!r)
805 return ISC_R_NOMEMORY;
807 status = omapi_object_reference (&r -> a, ao, MDL);
808 if (status != ISC_R_SUCCESS) {
809 dfree (r, MDL);
810 return status;
813 r -> remote_handle = handle;
814 r -> next = p -> remote_auth_list;
815 p -> remote_auth_list = r;
817 return ISC_R_SUCCESS;
820 isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a,
821 omapi_object_t *po,
822 omapi_handle_t handle)
824 omapi_protocol_object_t *p;
825 omapi_remote_auth_t *r;
827 if (po -> type != omapi_type_protocol)
828 return ISC_R_INVALIDARG;
829 p = (omapi_protocol_object_t *)po;
831 for (r = p -> remote_auth_list; r; r = r -> next)
832 if (r -> remote_handle == handle)
833 return omapi_object_reference (a, r -> a, MDL);
835 return ISC_R_KEY_UNKNOWN;
838 isc_result_t omapi_protocol_set_value (omapi_object_t *h,
839 omapi_object_t *id,
840 omapi_data_string_t *name,
841 omapi_typed_data_t *value)
843 omapi_protocol_object_t *p;
844 omapi_remote_auth_t *r;
846 if (h -> type != omapi_type_protocol)
847 return ISC_R_INVALIDARG;
848 p = (omapi_protocol_object_t *)h;
850 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
851 if (value -> type != omapi_datatype_object)
852 return ISC_R_INVALIDARG;
854 if (!value || !value -> u.object) {
855 p -> default_auth = (omapi_remote_auth_t *)0;
856 } else {
857 for (r = p -> remote_auth_list; r; r = r -> next)
858 if (r -> a == value -> u.object)
859 break;
861 if (!r)
862 return ISC_R_KEY_UNKNOWN;
864 p -> default_auth = r;
867 return ISC_R_SUCCESS;
870 if (h -> inner && h -> inner -> type -> set_value)
871 return (*(h -> inner -> type -> set_value))
872 (h -> inner, id, name, value);
873 return ISC_R_NOTFOUND;
876 isc_result_t omapi_protocol_get_value (omapi_object_t *h,
877 omapi_object_t *id,
878 omapi_data_string_t *name,
879 omapi_value_t **value)
881 omapi_protocol_object_t *p;
883 if (h -> type != omapi_type_protocol)
884 return ISC_R_INVALIDARG;
885 p = (omapi_protocol_object_t *)h;
887 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
888 if (!p -> default_auth)
889 return ISC_R_NOTFOUND;
891 return omapi_make_object_value (value, name,
892 p -> default_auth -> a, MDL);
895 if (h -> inner && h -> inner -> type -> get_value)
896 return (*(h -> inner -> type -> get_value))
897 (h -> inner, id, name, value);
898 return ISC_R_NOTFOUND;
901 isc_result_t omapi_protocol_destroy (omapi_object_t *h,
902 const char *file, int line)
904 omapi_protocol_object_t *p;
905 if (h -> type != omapi_type_protocol)
906 return ISC_R_INVALIDARG;
907 p = (omapi_protocol_object_t *)h;
908 if (p -> message)
909 omapi_message_dereference (&p -> message, file, line);
911 /* This will happen if: 1) A default authenticator is supplied to
912 omapi_protocol_connect(), and 2) something goes wrong before
913 the authenticator can be opened. */
914 if (p -> default_auth && !p -> remote_auth_list)
915 dfree (p -> default_auth, file, line);
917 while (p -> remote_auth_list) {
918 omapi_remote_auth_t *r = p -> remote_auth_list;
919 p -> remote_auth_list = r -> next;
920 if (r) {
921 omapi_object_dereference (&r -> a, file, line);
922 dfree (r, file, line);
925 return ISC_R_SUCCESS;
928 /* Write all the published values associated with the object through the
929 specified connection. */
931 isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
932 omapi_object_t *id,
933 omapi_object_t *p)
936 if (p -> type != omapi_type_protocol)
937 return ISC_R_INVALIDARG;
939 if (p -> inner && p -> inner -> type -> stuff_values)
940 return (*(p -> inner -> type -> stuff_values)) (c, id,
941 p -> inner);
942 return ISC_R_SUCCESS;
945 /* Returns a boolean indicating whether this protocol requires that
946 messages be authenticated or not. */
948 isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h)
950 if (h -> type != omapi_type_protocol)
951 return isc_boolean_false;
952 if (((omapi_protocol_object_t *)h) -> insecure)
953 return isc_boolean_false;
954 else
955 return isc_boolean_true;
958 /* Sets the address and authenticator verification callbacks. The handle
959 is to a listener object, not a protocol object. */
961 isc_result_t omapi_protocol_configure_security (omapi_object_t *h,
962 isc_result_t (*verify_addr)
963 (omapi_object_t *,
964 omapi_addr_t *),
965 isc_result_t (*verify_auth)
966 (omapi_object_t *,
967 omapi_auth_key_t *))
969 omapi_protocol_listener_object_t *l;
971 if (h -> outer && h -> outer -> type == omapi_type_protocol_listener)
972 h = h -> outer;
974 if (h -> type != omapi_type_protocol_listener)
975 return ISC_R_INVALIDARG;
976 l = (omapi_protocol_listener_object_t *)h;
978 l -> verify_auth = verify_auth;
979 l -> insecure = 0;
981 return omapi_listener_configure_security (h -> outer, verify_addr);
985 /* Set up a listener for the omapi protocol. The handle stored points to
986 a listener object, not a protocol object. */
988 isc_result_t omapi_protocol_listen (omapi_object_t *h,
989 unsigned port,
990 int max)
992 isc_result_t status;
993 omapi_protocol_listener_object_t *obj;
995 obj = (omapi_protocol_listener_object_t *)0;
996 status = omapi_protocol_listener_allocate (&obj, MDL);
997 if (status != ISC_R_SUCCESS)
998 return status;
1000 status = omapi_object_reference (&h -> outer,
1001 (omapi_object_t *)obj, MDL);
1002 if (status != ISC_R_SUCCESS) {
1003 omapi_protocol_listener_dereference (&obj, MDL);
1004 return status;
1006 status = omapi_object_reference (&obj -> inner, h, MDL);
1007 if (status != ISC_R_SUCCESS) {
1008 omapi_protocol_listener_dereference (&obj, MDL);
1009 return status;
1012 /* What a terrible default. */
1013 obj -> insecure = 1;
1015 status = omapi_listen ((omapi_object_t *)obj, port, max);
1016 omapi_protocol_listener_dereference (&obj, MDL);
1017 return status;
1020 /* Signal handler for protocol listener - if we get a connect signal,
1021 create a new protocol connection, otherwise pass the signal down. */
1023 isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
1024 const char *name, va_list ap)
1026 isc_result_t status;
1027 omapi_object_t *c;
1028 omapi_protocol_object_t *obj;
1029 omapi_protocol_listener_object_t *p;
1031 if (!o || o -> type != omapi_type_protocol_listener)
1032 return ISC_R_INVALIDARG;
1033 p = (omapi_protocol_listener_object_t *)o;
1035 /* Not a signal we recognize? */
1036 if (strcmp (name, "connect")) {
1037 if (p -> inner && p -> inner -> type -> signal_handler)
1038 return (*(p -> inner -> type -> signal_handler))
1039 (p -> inner, name, ap);
1040 return ISC_R_NOTFOUND;
1043 c = va_arg (ap, omapi_object_t *);
1044 if (!c || c -> type != omapi_type_connection)
1045 return ISC_R_INVALIDARG;
1047 obj = (omapi_protocol_object_t *)0;
1048 status = omapi_protocol_allocate (&obj, MDL);
1049 if (status != ISC_R_SUCCESS)
1050 return status;
1052 obj -> verify_auth = p -> verify_auth;
1053 obj -> insecure = p -> insecure;
1055 status = omapi_object_reference (&obj -> outer, c, MDL);
1056 if (status != ISC_R_SUCCESS) {
1057 lose:
1058 omapi_protocol_dereference (&obj, MDL);
1059 omapi_disconnect (c, 1);
1060 return status;
1063 status = omapi_object_reference (&c -> inner,
1064 (omapi_object_t *)obj, MDL);
1065 if (status != ISC_R_SUCCESS)
1066 goto lose;
1068 /* Send the introductory message. */
1069 status = omapi_protocol_send_intro ((omapi_object_t *)obj,
1070 OMAPI_PROTOCOL_VERSION,
1071 sizeof (omapi_protocol_header_t));
1072 if (status != ISC_R_SUCCESS)
1073 goto lose;
1075 omapi_protocol_dereference (&obj, MDL);
1076 return status;
1079 isc_result_t omapi_protocol_listener_set_value (omapi_object_t *h,
1080 omapi_object_t *id,
1081 omapi_data_string_t *name,
1082 omapi_typed_data_t *value)
1084 if (h -> type != omapi_type_protocol_listener)
1085 return ISC_R_INVALIDARG;
1087 if (h -> inner && h -> inner -> type -> set_value)
1088 return (*(h -> inner -> type -> set_value))
1089 (h -> inner, id, name, value);
1090 return ISC_R_NOTFOUND;
1093 isc_result_t omapi_protocol_listener_get_value (omapi_object_t *h,
1094 omapi_object_t *id,
1095 omapi_data_string_t *name,
1096 omapi_value_t **value)
1098 if (h -> type != omapi_type_protocol_listener)
1099 return ISC_R_INVALIDARG;
1101 if (h -> inner && h -> inner -> type -> get_value)
1102 return (*(h -> inner -> type -> get_value))
1103 (h -> inner, id, name, value);
1104 return ISC_R_NOTFOUND;
1107 isc_result_t omapi_protocol_listener_destroy (omapi_object_t *h,
1108 const char *file, int line)
1110 if (h -> type != omapi_type_protocol_listener)
1111 return ISC_R_INVALIDARG;
1112 return ISC_R_SUCCESS;
1115 /* Write all the published values associated with the object through the
1116 specified connection. */
1118 isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
1119 omapi_object_t *id,
1120 omapi_object_t *p)
1123 if (p -> type != omapi_type_protocol_listener)
1124 return ISC_R_INVALIDARG;
1126 if (p -> inner && p -> inner -> type -> stuff_values)
1127 return (*(p -> inner -> type -> stuff_values)) (c, id,
1128 p -> inner);
1129 return ISC_R_SUCCESS;
1132 isc_result_t omapi_protocol_send_status (omapi_object_t *po,
1133 omapi_object_t *id,
1134 isc_result_t waitstatus,
1135 unsigned rid, const char *msg)
1137 isc_result_t status;
1138 omapi_message_object_t *message = (omapi_message_object_t *)0;
1139 omapi_object_t *mo;
1141 if (po -> type != omapi_type_protocol)
1142 return ISC_R_INVALIDARG;
1144 status = omapi_message_new ((void *)&message, MDL);
1145 if (status != ISC_R_SUCCESS)
1146 return status;
1147 mo = (omapi_object_t *)message;
1149 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1150 "op", OMAPI_OP_STATUS);
1151 if (status != ISC_R_SUCCESS) {
1152 omapi_message_dereference (&message, MDL);
1153 return status;
1156 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1157 "rid", (int)rid);
1158 if (status != ISC_R_SUCCESS) {
1159 omapi_message_dereference (&message, MDL);
1160 return status;
1163 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1164 "result", (int)waitstatus);
1165 if (status != ISC_R_SUCCESS) {
1166 omapi_message_dereference (&message, MDL);
1167 return status;
1170 /* If a message has been provided, send it. */
1171 if (msg) {
1172 status = omapi_set_string_value (mo, (omapi_object_t *)0,
1173 "message", msg);
1174 if (status != ISC_R_SUCCESS) {
1175 omapi_message_dereference (&message, MDL);
1176 return status;
1180 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1181 omapi_message_dereference (&message, MDL);
1182 return status;
1185 /* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the
1186 message to be set to the protocol object. This is used when opening
1187 the default authenticator. */
1189 isc_result_t omapi_protocol_send_open (omapi_object_t *po,
1190 omapi_object_t *id,
1191 const char *type,
1192 omapi_object_t *object,
1193 unsigned flags)
1195 isc_result_t status;
1196 omapi_message_object_t *message = (omapi_message_object_t *)0;
1197 omapi_object_t *mo;
1199 if (po -> type != omapi_type_protocol)
1200 return ISC_R_INVALIDARG;
1202 status = omapi_message_new ((void *)&message, MDL);
1203 mo = (omapi_object_t *)message;
1205 if (status == ISC_R_SUCCESS)
1206 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1207 "op", OMAPI_OP_OPEN);
1209 if (status == ISC_R_SUCCESS)
1210 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1211 "object", object);
1213 if ((flags & OMAPI_CREATE) && (status == ISC_R_SUCCESS))
1214 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1215 "create", 1);
1217 if ((flags & OMAPI_UPDATE) && (status == ISC_R_SUCCESS))
1218 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1219 "update", 1);
1221 if ((flags & OMAPI_EXCL) && (status == ISC_R_SUCCESS))
1222 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1223 "exclusive", 1);
1225 if ((flags & OMAPI_NOTIFY_PROTOCOL) && (status == ISC_R_SUCCESS))
1226 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1227 "notify-object", po);
1229 if (type && (status == ISC_R_SUCCESS))
1230 status = omapi_set_string_value (mo, (omapi_object_t *)0,
1231 "type", type);
1233 if (status == ISC_R_SUCCESS)
1234 status = omapi_message_register (mo);
1236 if (status == ISC_R_SUCCESS) {
1237 status = omapi_protocol_send_message (po, id, mo,
1238 (omapi_object_t *)0);
1239 if (status != ISC_R_SUCCESS)
1240 omapi_message_unregister (mo);
1243 if (message)
1244 omapi_message_dereference (&message, MDL);
1246 return status;
1249 isc_result_t omapi_protocol_send_update (omapi_object_t *po,
1250 omapi_object_t *id,
1251 unsigned rid,
1252 omapi_object_t *object)
1254 isc_result_t status;
1255 omapi_message_object_t *message = (omapi_message_object_t *)0;
1256 omapi_object_t *mo;
1258 if (po -> type != omapi_type_protocol)
1259 return ISC_R_INVALIDARG;
1261 status = omapi_message_new ((void *)&message, MDL);
1262 if (status != ISC_R_SUCCESS)
1263 return status;
1264 mo = (omapi_object_t *)message;
1266 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1267 "op", OMAPI_OP_UPDATE);
1268 if (status != ISC_R_SUCCESS) {
1269 omapi_message_dereference (&message, MDL);
1270 return status;
1273 if (rid) {
1274 omapi_handle_t handle;
1275 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1276 "rid", (int)rid);
1277 if (status != ISC_R_SUCCESS) {
1278 omapi_message_dereference (&message, MDL);
1279 return status;
1282 status = omapi_object_handle (&handle, object);
1283 if (status != ISC_R_SUCCESS) {
1284 omapi_message_dereference (&message, MDL);
1285 return status;
1287 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1288 "handle", (int)handle);
1289 if (status != ISC_R_SUCCESS) {
1290 omapi_message_dereference (&message, MDL);
1291 return status;
1295 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1296 "object", object);
1297 if (status != ISC_R_SUCCESS) {
1298 omapi_message_dereference (&message, MDL);
1299 return status;
1302 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1303 omapi_message_dereference (&message, MDL);
1304 return status;