Fix a number of core kernel issues related to HAMMER operation.
[dragonfly.git] / contrib / dhcp-3.0 / omapip / protocol.c
bloba9d76f753fe9f9d5521c2883ce640bd8df4a4d56
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 #if 0
100 status = ISC_R_SUCCESS;
101 #endif
104 omapi_protocol_dereference (&obj, MDL);
105 return rstatus;
108 /* Send the protocol introduction message. */
109 isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
110 unsigned ver,
111 unsigned hsize)
113 isc_result_t status;
114 omapi_protocol_object_t *p;
116 #ifdef DEBUG_PROTOCOL
117 log_debug ("omapi_protocol_send_intro()");
118 #endif
120 if (h -> type != omapi_type_protocol)
121 return ISC_R_INVALIDARG;
122 p = (omapi_protocol_object_t *)h;
124 if (!h -> outer || h -> outer -> type != omapi_type_connection)
125 return ISC_R_NOTCONNECTED;
127 status = omapi_connection_put_uint32 (h -> outer, ver);
128 if (status != ISC_R_SUCCESS)
129 return status;
131 status = omapi_connection_put_uint32 (h -> outer, hsize);
133 if (status != ISC_R_SUCCESS)
134 return status;
136 /* Require the other end to send an intro - this kicks off the
137 protocol input state machine. */
138 p -> state = omapi_protocol_intro_wait;
139 status = omapi_connection_require (h -> outer, 8);
140 if (status != ISC_R_SUCCESS && status != ISC_R_NOTYET)
141 return status;
143 /* Make up an initial transaction ID for this connection. */
144 p -> next_xid = random ();
145 return ISC_R_SUCCESS;
148 isc_result_t omapi_protocol_send_message (omapi_object_t *po,
149 omapi_object_t *id,
150 omapi_object_t *mo,
151 omapi_object_t *omo)
153 omapi_protocol_object_t *p;
154 omapi_object_t *c;
155 omapi_message_object_t *m, *om;
156 omapi_remote_auth_t *ra;
157 omapi_value_t *signature;
158 isc_result_t status;
159 u_int32_t foo;
160 unsigned auth_len;
162 if (po -> type != omapi_type_protocol ||
163 !po -> outer || po -> outer -> type != omapi_type_connection ||
164 mo -> type != omapi_type_message)
165 return ISC_R_INVALIDARG;
166 if (omo && omo -> type != omapi_type_message)
167 return ISC_R_INVALIDARG;
168 p = (omapi_protocol_object_t *)po;
169 c = (omapi_object_t *)(po -> outer);
170 m = (omapi_message_object_t *)mo;
171 om = (omapi_message_object_t *)omo;
173 #ifdef DEBUG_PROTOCOL
174 log_debug ("omapi_protocol_send_message()"
175 "op=%ld handle=%#lx id=%#lx rid=%#lx",
176 (long)m -> op,
177 (long)(m -> object ? m -> object -> handle : m -> handle),
178 (long)p -> next_xid, (long)m -> rid);
179 #endif
181 /* Find the authid to use for this message. */
182 if (id) {
183 for (ra = p -> remote_auth_list; ra; ra = ra -> next) {
184 if (ra -> a == id) {
185 break;
189 if (!ra)
190 return ISC_R_KEY_UNKNOWN;
191 } else if (p -> remote_auth_list) {
192 ra = p -> default_auth;
193 } else {
194 ra = (omapi_remote_auth_t *)0;
197 if (ra) {
198 m -> authid = ra -> remote_handle;
199 status = omapi_object_reference (&m -> id_object,
200 ra -> a, MDL);
201 if (status != ISC_R_SUCCESS)
202 return status;
205 /* Write the ID of the authentication key we're using. */
206 status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0);
207 if (status != ISC_R_SUCCESS) {
208 omapi_disconnect (c, 1);
209 return status;
212 /* Activate the authentication key on the connection. */
213 auth_len = 0;
214 if (ra) {
215 status = omapi_set_object_value (c, (omapi_object_t *)0,
216 "output-authenticator",
217 ra -> a);
218 if (status != ISC_R_SUCCESS) {
219 omapi_disconnect (c, 1);
220 return status;
223 status = omapi_connection_output_auth_length (c, &auth_len);
224 if (status != ISC_R_SUCCESS) {
225 omapi_disconnect (c, 1);
226 return status;
230 /* Write the authenticator length */
231 status = omapi_connection_put_uint32 (c, auth_len);
232 if (status != ISC_R_SUCCESS) {
233 omapi_disconnect (c, 1);
234 return status;
237 /* Write the opcode. */
238 status = omapi_connection_put_uint32 (c, m -> op);
239 if (status != ISC_R_SUCCESS) {
240 omapi_disconnect (c, 1);
241 return status;
244 /* Write the handle. If we've been given an explicit handle, use
245 that. Otherwise, use the handle of the object we're sending.
246 The caller is responsible for arranging for one of these handles
247 to be set (or not). */
248 status = omapi_connection_put_uint32 (c, (m -> h
249 ? m -> h
250 : (m -> object
251 ? m -> object -> handle
252 : 0)));
253 if (status != ISC_R_SUCCESS) {
254 omapi_disconnect (c, 1);
255 return status;
258 /* Set and write the transaction ID. */
259 m -> id = p -> next_xid++;
260 status = omapi_connection_put_uint32 (c, m -> id);
261 if (status != ISC_R_SUCCESS) {
262 omapi_disconnect (c, 1);
263 return status;
266 /* Write the transaction ID of the message to which this is a
267 response, if there is such a message. */
268 status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
269 if (status != ISC_R_SUCCESS) {
270 omapi_disconnect (c, 1);
271 return status;
274 /* Stuff out the name/value pairs specific to this message. */
275 status = omapi_stuff_values (c, id, (omapi_object_t *)m);
276 if (status != ISC_R_SUCCESS) {
277 omapi_disconnect (c, 1);
278 return status;
281 /* Write the zero-length name that terminates the list of name/value
282 pairs specific to the message. */
283 status = omapi_connection_put_uint16 (c, 0);
284 if (status != ISC_R_SUCCESS) {
285 omapi_disconnect (c, 1);
286 return status;
289 /* Stuff out all the published name/value pairs in the object that's
290 being sent in the message, if there is one. */
291 if (m -> object) {
292 status = omapi_stuff_values (c, id, m -> object);
293 if (status != ISC_R_SUCCESS) {
294 omapi_disconnect (c, 1);
295 return status;
299 /* Write the zero-length name that terminates the list of name/value
300 pairs for the associated object. */
301 status = omapi_connection_put_uint16 (c, 0);
302 if (status != ISC_R_SUCCESS) {
303 omapi_disconnect (c, 1);
304 return status;
307 if (ra) {
308 /* Calculate the message signature. */
309 signature = (omapi_value_t *)0;
310 status = omapi_get_value_str (c, (omapi_object_t *)0,
311 "output-signature", &signature);
312 if (status != ISC_R_SUCCESS) {
313 omapi_disconnect (c, 1);
314 return status;
317 /* Write the authenticator... */
318 status = (omapi_connection_copyin
319 (c, signature -> value -> u.buffer.value,
320 signature -> value -> u.buffer.len));
321 omapi_value_dereference (&signature, MDL);
322 if (status != ISC_R_SUCCESS) {
323 omapi_disconnect (c, 1);
324 return status;
327 /* Dectivate the authentication key on the connection. */
328 status = omapi_set_value_str (c, (omapi_object_t *)0,
329 "output-authenticator",
330 (omapi_typed_data_t *)0);
331 if (status != ISC_R_SUCCESS) {
332 omapi_disconnect (c, 1);
333 return status;
337 if (!omo) {
338 omapi_protocol_reference (&m -> protocol_object, p, MDL);
340 return ISC_R_SUCCESS;
344 isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
345 const char *name, va_list ap)
347 isc_result_t status;
348 omapi_protocol_object_t *p;
349 omapi_object_t *c;
350 omapi_message_object_t *m;
351 omapi_value_t *signature;
352 u_int16_t nlen;
353 u_int32_t vlen;
354 u_int32_t th;
355 #if defined (DEBUG_MEMORY_LEAKAGE)
356 unsigned long previous_outstanding = 0xDEADBEEF;
357 unsigned long connect_outstanding = 0xDEADBEEF;
358 #endif
360 if (h -> type != omapi_type_protocol) {
361 /* XXX shouldn't happen. Put an assert here? */
362 return ISC_R_UNEXPECTED;
364 p = (omapi_protocol_object_t *)h;
366 if (!strcmp (name, "connect")) {
367 #if defined (DEBUG_MEMORY_LEAKAGE)
368 connect_outstanding = dmalloc_outstanding;
369 #endif
370 /* Send the introductory message. */
371 status = omapi_protocol_send_intro
372 (h, OMAPI_PROTOCOL_VERSION,
373 sizeof (omapi_protocol_header_t));
374 if (status != ISC_R_SUCCESS) {
375 omapi_disconnect (p -> outer, 1);
376 return status;
378 return ISC_R_SUCCESS;
381 /* Should only receive these when opening the initial authenticator. */
382 if (!strcmp (name, "status")) {
383 status = va_arg (ap, isc_result_t);
384 if (status != ISC_R_SUCCESS) {
385 omapi_signal_in (h -> inner, "status", status,
386 (omapi_object_t *)0);
387 omapi_disconnect (p -> outer, 1);
388 return status;
389 } else {
390 return omapi_signal_in (h -> inner, "ready");
394 /* If we get a disconnect, dump memory usage. */
395 if (!strcmp (name, "disconnect")) {
396 #if defined (DEBUG_MEMORY_LEAKAGE)
397 if (connect_outstanding != 0xDEADBEEF) {
398 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
399 dmalloc_generation,
400 dmalloc_outstanding - previous_outstanding,
401 dmalloc_outstanding, dmalloc_longterm, " long-term");
403 #endif
404 #if defined (DEBUG_MEMORY_LEAKAGE)
405 dmalloc_dump_outstanding ();
406 #endif
407 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
408 dump_rc_history ();
409 #endif
410 for (m = omapi_registered_messages; m; m = m -> next) {
411 if (m -> protocol_object == p) {
412 if (m -> object)
413 omapi_signal (m -> object, "disconnect");
418 /* Not a signal we recognize? */
419 if (strcmp (name, "ready")) {
420 if (p -> inner && p -> inner -> type -> signal_handler)
421 return (*(p -> inner -> type -> signal_handler)) (h,
422 name,
423 ap);
424 return ISC_R_NOTFOUND;
427 if (!p -> outer || p -> outer -> type != omapi_type_connection)
428 return ISC_R_INVALIDARG;
429 c = p -> outer;
431 /* We get here because we requested that we be woken up after
432 some number of bytes were read, and that number of bytes
433 has in fact been read. */
434 switch (p -> state) {
435 case omapi_protocol_intro_wait:
436 /* Get protocol version and header size in network
437 byte order. */
438 omapi_connection_get_uint32 (c, &p -> protocol_version);
439 omapi_connection_get_uint32 (c, &p -> header_size);
441 /* We currently only support the current protocol version. */
442 if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
443 omapi_disconnect (c, 1);
444 return ISC_R_VERSIONMISMATCH;
447 if (p -> header_size < sizeof (omapi_protocol_header_t)) {
448 omapi_disconnect (c, 1);
449 return ISC_R_PROTOCOLERROR;
452 if (p -> default_auth) {
453 status = omapi_protocol_send_open
454 (h, (omapi_object_t *)0, "authenticator",
455 p -> default_auth -> a,
456 OMAPI_NOTIFY_PROTOCOL);
457 if (status != ISC_R_SUCCESS) {
458 omapi_disconnect (c, 1);
459 return status;
461 } else {
462 status = omapi_signal_in (h -> inner, "ready");
465 to_header_wait:
466 /* The next thing we're expecting is a message header. */
467 p -> state = omapi_protocol_header_wait;
469 /* Register a need for the number of bytes in a
470 header, and if we already have that many, process
471 them immediately. */
472 if ((omapi_connection_require (c, p -> header_size)) !=
473 ISC_R_SUCCESS)
474 break;
475 /* If we already have the data, fall through. */
477 case omapi_protocol_header_wait:
478 #if defined (DEBUG_MEMORY_LEAKAGE)
479 if (previous_outstanding != 0xDEADBEEF) {
480 log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
481 "generation", dmalloc_generation,
482 dmalloc_outstanding - previous_outstanding,
483 dmalloc_outstanding, dmalloc_longterm,
484 " long-term");
485 #endif
486 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
487 dmalloc_dump_outstanding ();
488 #endif
489 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
490 dump_rc_history ();
491 #endif
492 #if defined (DEBUG_MEMORY_LEAKAGE)
494 previous_outstanding = dmalloc_outstanding;
495 #endif
496 status = omapi_message_new ((omapi_object_t **)&p -> message,
497 MDL);
498 if (status != ISC_R_SUCCESS) {
499 omapi_disconnect (c, 1);
500 return status;
503 p -> verify_result = ISC_R_SUCCESS;
505 /* Swap in the header... */
506 omapi_connection_get_uint32 (c, &p -> message -> authid);
508 /* Bind the authenticator to the message object. */
509 if (p -> message -> authid) {
510 status = (omapi_protocol_lookup_auth
511 (&p -> message -> id_object, h,
512 p -> message -> authid));
513 if (status != ISC_R_SUCCESS)
514 p -> verify_result = status;
516 /* Activate the authentication key. */
517 status = omapi_set_object_value
518 (c, (omapi_object_t *)0, "input-authenticator",
519 p -> message -> id_object);
520 if (status != ISC_R_SUCCESS) {
521 omapi_disconnect (c, 1);
522 return status;
526 omapi_connection_get_uint32 (c, &p -> message -> authlen);
527 omapi_connection_get_uint32 (c, &p -> message -> op);
528 omapi_connection_get_uint32 (c, &th);
529 p -> message -> h = th;
530 omapi_connection_get_uint32 (c, &p -> message -> id);
531 omapi_connection_get_uint32 (c, &p -> message -> rid);
533 /* If there was any extra header data, skip over it. */
534 if (p -> header_size > sizeof (omapi_protocol_header_t)) {
535 omapi_connection_copyout
536 (0, c, (p -> header_size -
537 sizeof (omapi_protocol_header_t)));
540 /* XXX must compute partial signature across the
541 XXX preceding bytes. Also, if authenticator
542 specifies encryption as well as signing, we may
543 have to decrypt the data on the way in. */
545 /* First we read in message-specific values, then object
546 values. */
547 p -> reading_message_values = 1;
549 need_name_length:
550 /* The next thing we're expecting is length of the
551 first name. */
552 p -> state = omapi_protocol_name_length_wait;
554 /* Wait for a 16-bit length. */
555 if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
556 break;
557 /* If it's already here, fall through. */
559 case omapi_protocol_name_length_wait:
560 omapi_connection_get_uint16 (c, &nlen);
561 /* A zero-length name means that we're done reading name+value
562 pairs. */
563 if (nlen == 0) {
564 /* If we've already read in the object, we are
565 done reading the message, but if we've just
566 finished reading in the values associated
567 with the message, we need to read the
568 object. */
569 if (p -> reading_message_values) {
570 p -> reading_message_values = 0;
571 goto need_name_length;
574 /* If the authenticator length is zero, there's no
575 signature to read in, so go straight to processing
576 the message. */
577 if (p -> message -> authlen == 0)
578 goto message_done;
580 /* The next thing we're expecting is the
581 message signature. */
582 p -> state = omapi_protocol_signature_wait;
584 /* Wait for the number of bytes specified for
585 the authenticator. If we already have it,
586 go read it in. */
587 if (omapi_connection_require
588 (c, p -> message -> authlen) == ISC_R_SUCCESS)
589 goto signature_wait;
590 break;
593 /* Allocate a buffer for the name. */
594 status = (omapi_data_string_new (&p -> name, nlen, MDL));
595 if (status != ISC_R_SUCCESS) {
596 omapi_disconnect (c, 1);
597 return ISC_R_NOMEMORY;
599 p -> state = omapi_protocol_name_wait;
600 if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
601 break;
602 /* If it's already here, fall through. */
604 case omapi_protocol_name_wait:
605 omapi_connection_copyout (p -> name -> value, c,
606 p -> name -> len);
607 /* Wait for a 32-bit length. */
608 p -> state = omapi_protocol_value_length_wait;
609 if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
610 break;
611 /* If it's already here, fall through. */
613 case omapi_protocol_value_length_wait:
614 omapi_connection_get_uint32 (c, &vlen);
616 /* Zero-length values are allowed - if we get one, we
617 don't have to read any data for the value - just
618 get the next one, if there is a next one. */
619 if (!vlen)
620 goto insert_new_value;
622 status = omapi_typed_data_new (MDL, &p -> value,
623 omapi_datatype_data,
624 vlen);
625 if (status != ISC_R_SUCCESS) {
626 omapi_disconnect (c, 1);
627 return ISC_R_NOMEMORY;
630 p -> state = omapi_protocol_value_wait;
631 if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
632 break;
633 /* If it's already here, fall through. */
635 case omapi_protocol_value_wait:
636 omapi_connection_copyout (p -> value -> u.buffer.value, c,
637 p -> value -> u.buffer.len);
639 insert_new_value:
640 if (p -> reading_message_values) {
641 status = (omapi_set_value
642 ((omapi_object_t *)p -> message,
643 p -> message -> id_object,
644 p -> name, p -> value));
645 } else {
646 if (!p -> message -> object) {
647 /* We need a generic object to hang off of the
648 incoming message. */
649 status = (omapi_generic_new
650 (&p -> message -> object, MDL));
651 if (status != ISC_R_SUCCESS) {
652 omapi_disconnect (c, 1);
653 return status;
656 status = (omapi_set_value
657 ((omapi_object_t *)p -> message -> object,
658 p -> message -> id_object,
659 p -> name, p -> value));
661 if (status != ISC_R_SUCCESS) {
662 omapi_disconnect (c, 1);
663 return status;
665 omapi_data_string_dereference (&p -> name, MDL);
666 if (p -> value)
667 omapi_typed_data_dereference (&p -> value, MDL);
668 goto need_name_length;
670 signature_wait:
671 case omapi_protocol_signature_wait:
672 if (p -> message -> id_object) {
673 /* Compute the signature of the message. */
674 signature = (omapi_value_t *)0;
675 status = omapi_get_value_str (c, (omapi_object_t *)0,
676 "input-signature",
677 &signature);
678 if (status != ISC_R_SUCCESS) {
679 omapi_disconnect (c, 1);
680 return status;
683 /* Disable the authentication key on the connection. */
684 status = omapi_set_value_str (c, (omapi_object_t *)0,
685 "input-authenticator",
686 (omapi_typed_data_t *)0);
687 if (status != ISC_R_SUCCESS) {
688 omapi_value_dereference (&signature, MDL);
689 omapi_disconnect (c, 1);
690 return status;
694 /* Read the authenticator. */
695 status = omapi_typed_data_new (MDL,
696 &p -> message -> authenticator,
697 omapi_datatype_data,
698 p -> message -> authlen);
700 if (status != ISC_R_SUCCESS) {
701 omapi_value_dereference (&signature, MDL);
702 omapi_disconnect (c, 1);
703 return ISC_R_NOMEMORY;
705 omapi_connection_copyout
706 (p -> message -> authenticator -> u.buffer.value, c,
707 p -> message -> authlen);
709 /* Verify the signature. */
710 if (p -> message -> id_object &&
711 ((signature -> value -> u.buffer.len !=
712 p -> message -> authlen) ||
713 (memcmp (signature -> value -> u.buffer.value,
714 p -> message -> authenticator -> u.buffer.value,
715 p -> message -> authlen) != 0))) {
716 /* Invalid signature. */
717 p -> verify_result = ISC_R_INVALIDKEY;
720 omapi_value_dereference (&signature, MDL);
722 /* Process the message. */
723 message_done:
724 if (p -> verify_result != ISC_R_SUCCESS) {
725 status = omapi_protocol_send_status
726 (h, (omapi_object_t *)0, p -> verify_result,
727 p -> message -> id, (char *)0);
728 } else {
729 status = omapi_message_process
730 ((omapi_object_t *)p -> message, h);
732 if (status != ISC_R_SUCCESS) {
733 omapi_disconnect (c, 1);
734 return ISC_R_NOMEMORY;
737 omapi_message_dereference (&p -> message, MDL);
738 #if defined (DEBUG_MEMORY_LEAKAGE)
739 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
740 dmalloc_generation,
741 dmalloc_outstanding - previous_outstanding,
742 dmalloc_outstanding, dmalloc_longterm, " long-term");
743 #endif
744 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
745 dmalloc_dump_outstanding ();
746 #endif
747 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
748 dump_rc_history ();
749 #endif
750 #if defined (DEBUG_MEMORY_LEAKAGE)
751 previous_outstanding = 0xDEADBEEF;
752 #endif
753 /* Now wait for the next message. */
754 goto to_header_wait;
756 default:
757 /* XXX should never get here. Assertion? */
758 break;
760 return ISC_R_SUCCESS;
763 isc_result_t omapi_protocol_add_auth (omapi_object_t *po,
764 omapi_object_t *ao,
765 omapi_handle_t handle)
767 omapi_protocol_object_t *p;
768 omapi_remote_auth_t *r;
769 isc_result_t status;
771 if (ao -> type != omapi_type_auth_key &&
772 (!ao -> inner || ao -> inner -> type != omapi_type_auth_key))
773 return ISC_R_INVALIDARG;
775 if (po -> type != omapi_type_protocol)
776 return ISC_R_INVALIDARG;
777 p = (omapi_protocol_object_t *)po;
779 #ifdef DEBUG_PROTOCOL
780 log_debug ("omapi_protocol_add_auth(name=%s)",
781 ((omapi_auth_key_t *)ao) -> name);
782 #endif
784 if (p -> verify_auth) {
785 status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao);
786 if (status != ISC_R_SUCCESS)
787 return status;
790 /* If omapi_protocol_connect() was called with a default
791 authenticator, p -> default_auth will already be set,
792 but p -> remote_auth_list will not yet be initialized. */
793 if (p -> default_auth && !p -> remote_auth_list) {
794 if (p -> default_auth -> a != ao) {
795 /* Something just went horribly wrong. */
796 omapi_disconnect (p -> outer, 1);
797 return ISC_R_UNEXPECTED;
800 p -> remote_auth_list = p -> default_auth;
801 p -> default_auth -> remote_handle = handle;
803 return omapi_signal_in (p -> inner, "ready");
806 r = dmalloc (sizeof(*r), MDL);
807 if (!r)
808 return ISC_R_NOMEMORY;
810 status = omapi_object_reference (&r -> a, ao, MDL);
811 if (status != ISC_R_SUCCESS) {
812 dfree (r, MDL);
813 return status;
816 r -> remote_handle = handle;
817 r -> next = p -> remote_auth_list;
818 p -> remote_auth_list = r;
820 return ISC_R_SUCCESS;
823 isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a,
824 omapi_object_t *po,
825 omapi_handle_t handle)
827 omapi_protocol_object_t *p;
828 omapi_remote_auth_t *r;
830 if (po -> type != omapi_type_protocol)
831 return ISC_R_INVALIDARG;
832 p = (omapi_protocol_object_t *)po;
834 for (r = p -> remote_auth_list; r; r = r -> next)
835 if (r -> remote_handle == handle)
836 return omapi_object_reference (a, r -> a, MDL);
838 return ISC_R_KEY_UNKNOWN;
841 isc_result_t omapi_protocol_set_value (omapi_object_t *h,
842 omapi_object_t *id,
843 omapi_data_string_t *name,
844 omapi_typed_data_t *value)
846 omapi_protocol_object_t *p;
847 omapi_remote_auth_t *r;
849 if (h -> type != omapi_type_protocol)
850 return ISC_R_INVALIDARG;
851 p = (omapi_protocol_object_t *)h;
853 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
854 if (value -> type != omapi_datatype_object)
855 return ISC_R_INVALIDARG;
857 if (!value || !value -> u.object) {
858 p -> default_auth = (omapi_remote_auth_t *)0;
859 } else {
860 for (r = p -> remote_auth_list; r; r = r -> next)
861 if (r -> a == value -> u.object)
862 break;
864 if (!r)
865 return ISC_R_KEY_UNKNOWN;
867 p -> default_auth = r;
870 return ISC_R_SUCCESS;
873 if (h -> inner && h -> inner -> type -> set_value)
874 return (*(h -> inner -> type -> set_value))
875 (h -> inner, id, name, value);
876 return ISC_R_NOTFOUND;
879 isc_result_t omapi_protocol_get_value (omapi_object_t *h,
880 omapi_object_t *id,
881 omapi_data_string_t *name,
882 omapi_value_t **value)
884 omapi_protocol_object_t *p;
886 if (h -> type != omapi_type_protocol)
887 return ISC_R_INVALIDARG;
888 p = (omapi_protocol_object_t *)h;
890 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
891 if (!p -> default_auth)
892 return ISC_R_NOTFOUND;
894 return omapi_make_object_value (value, name,
895 p -> default_auth -> a, MDL);
898 if (h -> inner && h -> inner -> type -> get_value)
899 return (*(h -> inner -> type -> get_value))
900 (h -> inner, id, name, value);
901 return ISC_R_NOTFOUND;
904 isc_result_t omapi_protocol_destroy (omapi_object_t *h,
905 const char *file, int line)
907 omapi_protocol_object_t *p;
908 if (h -> type != omapi_type_protocol)
909 return ISC_R_INVALIDARG;
910 p = (omapi_protocol_object_t *)h;
911 if (p -> message)
912 omapi_message_dereference (&p -> message, file, line);
914 /* This will happen if: 1) A default authenticator is supplied to
915 omapi_protocol_connect(), and 2) something goes wrong before
916 the authenticator can be opened. */
917 if (p -> default_auth && !p -> remote_auth_list)
918 dfree (p -> default_auth, file, line);
920 while (p -> remote_auth_list) {
921 omapi_remote_auth_t *r = p -> remote_auth_list -> next;
922 p -> remote_auth_list = r;
923 if (r) {
924 omapi_object_dereference (&r -> a, file, line);
925 dfree (r, file, line);
928 return ISC_R_SUCCESS;
931 /* Write all the published values associated with the object through the
932 specified connection. */
934 isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
935 omapi_object_t *id,
936 omapi_object_t *p)
938 int i;
940 if (p -> type != omapi_type_protocol)
941 return ISC_R_INVALIDARG;
943 if (p -> inner && p -> inner -> type -> stuff_values)
944 return (*(p -> inner -> type -> stuff_values)) (c, id,
945 p -> inner);
946 return ISC_R_SUCCESS;
949 /* Returns a boolean indicating whether this protocol requires that
950 messages be authenticated or not. */
952 isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h)
954 if (h -> type != omapi_type_protocol)
955 return isc_boolean_false;
956 if (((omapi_protocol_object_t *)h) -> insecure)
957 return isc_boolean_false;
958 else
959 return isc_boolean_true;
962 /* Sets the address and authenticator verification callbacks. The handle
963 is to a listener object, not a protocol object. */
965 isc_result_t omapi_protocol_configure_security (omapi_object_t *h,
966 isc_result_t (*verify_addr)
967 (omapi_object_t *,
968 omapi_addr_t *),
969 isc_result_t (*verify_auth)
970 (omapi_object_t *,
971 omapi_auth_key_t *))
973 omapi_protocol_listener_object_t *l;
975 if (h -> outer && h -> outer -> type == omapi_type_protocol_listener)
976 h = h -> outer;
978 if (h -> type != omapi_type_protocol_listener)
979 return ISC_R_INVALIDARG;
980 l = (omapi_protocol_listener_object_t *)h;
982 l -> verify_auth = verify_auth;
983 l -> insecure = 0;
985 return omapi_listener_configure_security (h -> outer, verify_addr);
989 /* Set up a listener for the omapi protocol. The handle stored points to
990 a listener object, not a protocol object. */
992 isc_result_t omapi_protocol_listen (omapi_object_t *h,
993 unsigned port,
994 int max)
996 isc_result_t status;
997 omapi_protocol_listener_object_t *obj;
999 obj = (omapi_protocol_listener_object_t *)0;
1000 status = omapi_protocol_listener_allocate (&obj, MDL);
1001 if (status != ISC_R_SUCCESS)
1002 return status;
1004 status = omapi_object_reference (&h -> outer,
1005 (omapi_object_t *)obj, MDL);
1006 if (status != ISC_R_SUCCESS) {
1007 omapi_protocol_listener_dereference (&obj, MDL);
1008 return status;
1010 status = omapi_object_reference (&obj -> inner, h, MDL);
1011 if (status != ISC_R_SUCCESS) {
1012 omapi_protocol_listener_dereference (&obj, MDL);
1013 return status;
1016 /* What a terrible default. */
1017 obj -> insecure = 1;
1019 status = omapi_listen ((omapi_object_t *)obj, port, max);
1020 omapi_protocol_listener_dereference (&obj, MDL);
1021 return status;
1024 /* Signal handler for protocol listener - if we get a connect signal,
1025 create a new protocol connection, otherwise pass the signal down. */
1027 isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
1028 const char *name, va_list ap)
1030 isc_result_t status;
1031 omapi_object_t *c;
1032 omapi_protocol_object_t *obj;
1033 omapi_protocol_listener_object_t *p;
1035 if (!o || o -> type != omapi_type_protocol_listener)
1036 return ISC_R_INVALIDARG;
1037 p = (omapi_protocol_listener_object_t *)o;
1039 /* Not a signal we recognize? */
1040 if (strcmp (name, "connect")) {
1041 if (p -> inner && p -> inner -> type -> signal_handler)
1042 return (*(p -> inner -> type -> signal_handler))
1043 (p -> inner, name, ap);
1044 return ISC_R_NOTFOUND;
1047 c = va_arg (ap, omapi_object_t *);
1048 if (!c || c -> type != omapi_type_connection)
1049 return ISC_R_INVALIDARG;
1051 obj = (omapi_protocol_object_t *)0;
1052 status = omapi_protocol_allocate (&obj, MDL);
1053 if (status != ISC_R_SUCCESS)
1054 return status;
1056 obj -> verify_auth = p -> verify_auth;
1057 obj -> insecure = p -> insecure;
1059 status = omapi_object_reference (&obj -> outer, c, MDL);
1060 if (status != ISC_R_SUCCESS) {
1061 lose:
1062 omapi_protocol_dereference (&obj, MDL);
1063 omapi_disconnect (c, 1);
1064 return status;
1067 status = omapi_object_reference (&c -> inner,
1068 (omapi_object_t *)obj, MDL);
1069 if (status != ISC_R_SUCCESS)
1070 goto lose;
1072 /* Send the introductory message. */
1073 status = omapi_protocol_send_intro ((omapi_object_t *)obj,
1074 OMAPI_PROTOCOL_VERSION,
1075 sizeof (omapi_protocol_header_t));
1076 if (status != ISC_R_SUCCESS)
1077 goto lose;
1079 omapi_protocol_dereference (&obj, MDL);
1080 return status;
1083 isc_result_t omapi_protocol_listener_set_value (omapi_object_t *h,
1084 omapi_object_t *id,
1085 omapi_data_string_t *name,
1086 omapi_typed_data_t *value)
1088 if (h -> type != omapi_type_protocol_listener)
1089 return ISC_R_INVALIDARG;
1091 if (h -> inner && h -> inner -> type -> set_value)
1092 return (*(h -> inner -> type -> set_value))
1093 (h -> inner, id, name, value);
1094 return ISC_R_NOTFOUND;
1097 isc_result_t omapi_protocol_listener_get_value (omapi_object_t *h,
1098 omapi_object_t *id,
1099 omapi_data_string_t *name,
1100 omapi_value_t **value)
1102 if (h -> type != omapi_type_protocol_listener)
1103 return ISC_R_INVALIDARG;
1105 if (h -> inner && h -> inner -> type -> get_value)
1106 return (*(h -> inner -> type -> get_value))
1107 (h -> inner, id, name, value);
1108 return ISC_R_NOTFOUND;
1111 isc_result_t omapi_protocol_listener_destroy (omapi_object_t *h,
1112 const char *file, int line)
1114 if (h -> type != omapi_type_protocol_listener)
1115 return ISC_R_INVALIDARG;
1116 return ISC_R_SUCCESS;
1119 /* Write all the published values associated with the object through the
1120 specified connection. */
1122 isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
1123 omapi_object_t *id,
1124 omapi_object_t *p)
1126 int i;
1128 if (p -> type != omapi_type_protocol_listener)
1129 return ISC_R_INVALIDARG;
1131 if (p -> inner && p -> inner -> type -> stuff_values)
1132 return (*(p -> inner -> type -> stuff_values)) (c, id,
1133 p -> inner);
1134 return ISC_R_SUCCESS;
1137 isc_result_t omapi_protocol_send_status (omapi_object_t *po,
1138 omapi_object_t *id,
1139 isc_result_t waitstatus,
1140 unsigned rid, const char *msg)
1142 isc_result_t status;
1143 omapi_message_object_t *message = (omapi_message_object_t *)0;
1144 omapi_object_t *mo;
1146 if (po -> type != omapi_type_protocol)
1147 return ISC_R_INVALIDARG;
1149 status = omapi_message_new ((omapi_object_t **)&message, MDL);
1150 if (status != ISC_R_SUCCESS)
1151 return status;
1152 mo = (omapi_object_t *)message;
1154 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1155 "op", OMAPI_OP_STATUS);
1156 if (status != ISC_R_SUCCESS) {
1157 omapi_message_dereference (&message, MDL);
1158 return status;
1161 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1162 "rid", (int)rid);
1163 if (status != ISC_R_SUCCESS) {
1164 omapi_message_dereference (&message, MDL);
1165 return status;
1168 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1169 "result", (int)waitstatus);
1170 if (status != ISC_R_SUCCESS) {
1171 omapi_message_dereference (&message, MDL);
1172 return status;
1175 /* If a message has been provided, send it. */
1176 if (msg) {
1177 status = omapi_set_string_value (mo, (omapi_object_t *)0,
1178 "message", msg);
1179 if (status != ISC_R_SUCCESS) {
1180 omapi_message_dereference (&message, MDL);
1181 return status;
1185 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1186 omapi_message_dereference (&message, MDL);
1187 return status;
1190 /* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the
1191 message to be set to the protocol object. This is used when opening
1192 the default authenticator. */
1194 isc_result_t omapi_protocol_send_open (omapi_object_t *po,
1195 omapi_object_t *id,
1196 const char *type,
1197 omapi_object_t *object,
1198 unsigned flags)
1200 isc_result_t status;
1201 omapi_message_object_t *message = (omapi_message_object_t *)0;
1202 omapi_object_t *mo;
1204 if (po -> type != omapi_type_protocol)
1205 return ISC_R_INVALIDARG;
1207 status = omapi_message_new ((omapi_object_t **)&message, MDL);
1208 mo = (omapi_object_t *)message;
1210 if (status == ISC_R_SUCCESS)
1211 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1212 "op", OMAPI_OP_OPEN);
1214 if (status == ISC_R_SUCCESS)
1215 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1216 "object", object);
1218 if ((flags & OMAPI_CREATE) && (status == ISC_R_SUCCESS))
1219 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1220 "create", 1);
1222 if ((flags & OMAPI_UPDATE) && (status == ISC_R_SUCCESS))
1223 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1224 "update", 1);
1226 if ((flags & OMAPI_EXCL) && (status == ISC_R_SUCCESS))
1227 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1228 "exclusive", 1);
1230 if ((flags & OMAPI_NOTIFY_PROTOCOL) && (status == ISC_R_SUCCESS))
1231 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1232 "notify-object", po);
1234 if (type && (status == ISC_R_SUCCESS))
1235 status = omapi_set_string_value (mo, (omapi_object_t *)0,
1236 "type", type);
1238 if (status == ISC_R_SUCCESS)
1239 status = omapi_message_register (mo);
1241 if (status == ISC_R_SUCCESS) {
1242 status = omapi_protocol_send_message (po, id, mo,
1243 (omapi_object_t *)0);
1244 if (status != ISC_R_SUCCESS)
1245 omapi_message_unregister (mo);
1248 if (message)
1249 omapi_message_dereference (&message, MDL);
1251 return status;
1254 isc_result_t omapi_protocol_send_update (omapi_object_t *po,
1255 omapi_object_t *id,
1256 unsigned rid,
1257 omapi_object_t *object)
1259 isc_result_t status;
1260 omapi_message_object_t *message = (omapi_message_object_t *)0;
1261 omapi_object_t *mo;
1263 if (po -> type != omapi_type_protocol)
1264 return ISC_R_INVALIDARG;
1266 status = omapi_message_new ((omapi_object_t **)&message, MDL);
1267 if (status != ISC_R_SUCCESS)
1268 return status;
1269 mo = (omapi_object_t *)message;
1271 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1272 "op", OMAPI_OP_UPDATE);
1273 if (status != ISC_R_SUCCESS) {
1274 omapi_message_dereference (&message, MDL);
1275 return status;
1278 if (rid) {
1279 omapi_handle_t handle;
1280 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1281 "rid", (int)rid);
1282 if (status != ISC_R_SUCCESS) {
1283 omapi_message_dereference (&message, MDL);
1284 return status;
1287 status = omapi_object_handle (&handle, object);
1288 if (status != ISC_R_SUCCESS) {
1289 omapi_message_dereference (&message, MDL);
1290 return status;
1292 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1293 "handle", (int)handle);
1294 if (status != ISC_R_SUCCESS) {
1295 omapi_message_dereference (&message, MDL);
1296 return status;
1300 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1301 "object", object);
1302 if (status != ISC_R_SUCCESS) {
1303 omapi_message_dereference (&message, MDL);
1304 return status;
1307 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1308 omapi_message_dereference (&message, MDL);
1309 return status;