]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/protocol.c
- Fix all the OMAPI objects in the DHCP server and client that weren't
[thirdparty/dhcp.git] / omapip / protocol.c
CommitLineData
61b844bf
TL
1/* protocol.c
2
3 Functions supporting the object management protocol... */
4
5/*
49733f31
TL
6 * Copyright (c) 1999-2000 Internet Software Consortium.
7 * All rights reserved.
61b844bf 8 *
49733f31
TL
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
61b844bf 12 *
49733f31
TL
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
61b844bf 21 *
49733f31
TL
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
61b844bf
TL
42 */
43
6a4c4be8 44#include <omapip/omapip_p.h>
61b844bf 45
20916cae
TL
46OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
47 omapi_type_protocol)
48OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
49 omapi_type_protocol_listener)
50
61b844bf 51isc_result_t omapi_protocol_connect (omapi_object_t *h,
b1b7b521 52 const char *server_name,
d9eefc5d 53 unsigned port,
61b844bf
TL
54 omapi_object_t *authinfo)
55{
56 isc_result_t status;
57 omapi_protocol_object_t *obj;
58
20916cae
TL
59 obj = (omapi_protocol_object_t *)0;
60 status = omapi_protocol_allocate (&obj, MDL);
61 if (status != ISC_R_SUCCESS)
62 return status;
61b844bf
TL
63
64 status = omapi_connect ((omapi_object_t *)obj, server_name, port);
65 if (status != ISC_R_SUCCESS) {
20916cae 66 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
67 return status;
68 }
4bd8800e
TL
69 status = omapi_object_reference (&h -> outer,
70 (omapi_object_t *)obj, MDL);
61b844bf 71 if (status != ISC_R_SUCCESS) {
20916cae 72 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
73 return status;
74 }
4bd8800e 75 status = omapi_object_reference (&obj -> inner, h, MDL);
61b844bf 76 if (status != ISC_R_SUCCESS) {
20916cae 77 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
78 return status;
79 }
80
61b844bf 81 if (authinfo)
4bd8800e 82 omapi_object_reference (&obj -> authinfo, authinfo, MDL);
20916cae 83 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
84 return ISC_R_SUCCESS;
85}
86
87/* Send the protocol introduction message. */
88isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
b1b7b521
TL
89 unsigned ver,
90 unsigned hsize)
61b844bf
TL
91{
92 isc_result_t status;
93 omapi_protocol_object_t *p;
94
95 if (h -> type != omapi_type_protocol)
96 return ISC_R_INVALIDARG;
97 p = (omapi_protocol_object_t *)h;
98
99 if (!h -> outer || h -> outer -> type != omapi_type_connection)
100 return ISC_R_NOTCONNECTED;
101
102 status = omapi_connection_put_uint32 (h -> outer, ver);
103 if (status != ISC_R_SUCCESS)
104 return status;
105
106 status = omapi_connection_put_uint32 (h -> outer, hsize);
107
108 if (status != ISC_R_SUCCESS)
109 return status;
110
111 /* Require the other end to send an intro - this kicks off the
112 protocol input state machine. */
113 p -> state = omapi_protocol_intro_wait;
114 status = omapi_connection_require (h -> outer, 8);
115 if (status != ISC_R_SUCCESS && status != ISC_R_NOTYET)
116 return status;
117
118 /* Make up an initial transaction ID for this connection. */
119 p -> next_xid = random ();
120 return ISC_R_SUCCESS;
121}
122
123isc_result_t omapi_protocol_send_message (omapi_object_t *po,
124 omapi_object_t *id,
125 omapi_object_t *mo,
126 omapi_object_t *omo)
127{
128 omapi_protocol_object_t *p;
129 omapi_object_t *c;
20916cae 130 omapi_message_object_t *m, *om;
61b844bf
TL
131 isc_result_t status;
132 u_int32_t foo;
133
134 if (po -> type != omapi_type_protocol ||
135 !po -> outer || po -> outer -> type != omapi_type_connection ||
20916cae 136 m -> type != omapi_type_message)
61b844bf 137 return ISC_R_INVALIDARG;
20916cae 138 if (om && om -> type != omapi_type_message)
61b844bf
TL
139 return ISC_R_INVALIDARG;
140 p = (omapi_protocol_object_t *)po;
141 c = (omapi_object_t *)(po -> outer);
142 m = (omapi_message_object_t *)mo;
143 om = (omapi_message_object_t *)omo;
144
145 /* XXX Write the authenticator length */
146 status = omapi_connection_put_uint32 (c, 0);
147 if (status != ISC_R_SUCCESS)
148 return status;
149 /* XXX Write the ID of the authentication key we're using. */
150 status = omapi_connection_put_uint32 (c, 0);
151 if (status != ISC_R_SUCCESS) {
152 omapi_disconnect (c, 1);
153 return status;
154 }
155
156 /* Write the opcode. */
157 status = omapi_connection_put_uint32 (c, m -> op);
158 if (status != ISC_R_SUCCESS) {
159 omapi_disconnect (c, 1);
160 return status;
161 }
162
163 /* Write the handle. If we've been given an explicit handle, use
164 that. Otherwise, use the handle of the object we're sending.
165 The caller is responsible for arranging for one of these handles
166 to be set (or not). */
167 status = omapi_connection_put_uint32 (c, (m -> h
168 ? m -> h
5a8e13c6
TL
169 : (m -> object
170 ? m -> object -> handle
171 : 0)));
61b844bf
TL
172 if (status != ISC_R_SUCCESS) {
173 omapi_disconnect (c, 1);
174 return status;
175 }
176
177 /* Set and write the transaction ID. */
178 m -> id = p -> next_xid++;
179 status = omapi_connection_put_uint32 (c, m -> id);
180 if (status != ISC_R_SUCCESS) {
181 omapi_disconnect (c, 1);
182 return status;
183 }
184
185 /* Write the transaction ID of the message to which this is a
186 response, if there is such a message. */
5a8e13c6 187 status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
61b844bf
TL
188 if (status != ISC_R_SUCCESS) {
189 omapi_disconnect (c, 1);
190 return status;
191 }
192
581e37e4 193 /* Stuff out the name/value pairs specific to this message. */
5a8e13c6
TL
194 status = omapi_stuff_values (c, id, (omapi_object_t *)m);
195 if (status != ISC_R_SUCCESS) {
196 omapi_disconnect (c, 1);
197 return status;
581e37e4
TL
198 }
199
200 /* Write the zero-length name that terminates the list of name/value
201 pairs specific to the message. */
202 status = omapi_connection_put_uint16 (c, 0);
61b844bf
TL
203 if (status != ISC_R_SUCCESS) {
204 omapi_disconnect (c, 1);
205 return status;
206 }
207
581e37e4
TL
208 /* Stuff out all the published name/value pairs in the object that's
209 being sent in the message, if there is one. */
210 if (m -> object) {
211 status = omapi_stuff_values (c, id, m -> object);
212 if (status != ISC_R_SUCCESS) {
213 omapi_disconnect (c, 1);
214 return status;
215 }
216 }
217
61b844bf 218 /* Write the zero-length name that terminates the list of name/value
581e37e4 219 pairs for the associated object. */
61b844bf
TL
220 status = omapi_connection_put_uint16 (c, 0);
221 if (status != ISC_R_SUCCESS) {
222 omapi_disconnect (c, 1);
223 return status;
224 }
225
226 /* XXX Write the authenticator... */
227
228 return ISC_R_SUCCESS;
229}
230
231
232isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
b1b7b521 233 const char *name, va_list ap)
61b844bf
TL
234{
235 isc_result_t status;
236 omapi_protocol_object_t *p;
237 omapi_object_t *c;
238 u_int16_t nlen;
239 u_int32_t vlen;
bbdb72a4 240 u_int32_t th;
61b844bf
TL
241
242 if (h -> type != omapi_type_protocol) {
243 /* XXX shouldn't happen. Put an assert here? */
244 return ISC_R_UNEXPECTED;
245 }
246 p = (omapi_protocol_object_t *)h;
247
ffc05866
TL
248 if (!strcmp (name, "connect")) {
249 /* Send the introductory message. */
250 status = omapi_protocol_send_intro
7deff076 251 (h, OMAPI_PROTOCOL_VERSION,
ffc05866
TL
252 sizeof (omapi_protocol_header_t));
253 if (status != ISC_R_SUCCESS) {
254 omapi_disconnect (p -> outer, 1);
255 return status;
256 }
257 return ISC_R_SUCCESS;
258 }
259
61b844bf
TL
260 /* Not a signal we recognize? */
261 if (strcmp (name, "ready")) {
262 if (p -> inner && p -> inner -> type -> signal_handler)
263 return (*(p -> inner -> type -> signal_handler)) (h,
264 name,
265 ap);
266 return ISC_R_NOTFOUND;
267 }
268
269 if (!p -> outer || p -> outer -> type != omapi_type_connection)
270 return ISC_R_INVALIDARG;
271 c = p -> outer;
272
273 /* We get here because we requested that we be woken up after
274 some number of bytes were read, and that number of bytes
275 has in fact been read. */
276 switch (p -> state) {
277 case omapi_protocol_intro_wait:
278 /* Get protocol version and header size in network
279 byte order. */
d9eefc5d
TL
280 omapi_connection_get_uint32 (c, &p -> protocol_version);
281 omapi_connection_get_uint32 (c, &p -> header_size);
61b844bf
TL
282
283 /* We currently only support the current protocol version. */
284 if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
285 omapi_disconnect (c, 1);
286 return ISC_R_VERSIONMISMATCH;
287 }
288
289 if (p -> header_size < sizeof (omapi_protocol_header_t)) {
290 omapi_disconnect (c, 1);
291 return ISC_R_PROTOCOLERROR;
292 }
293
294 status = omapi_signal_in (h -> inner, "ready");
295
296 to_header_wait:
297 /* The next thing we're expecting is a message header. */
298 p -> state = omapi_protocol_header_wait;
299
300 /* Register a need for the number of bytes in a
301 header, and if we already have that many, process
302 them immediately. */
d9eefc5d
TL
303 if ((omapi_connection_require (c, p -> header_size)) !=
304 ISC_R_SUCCESS)
61b844bf
TL
305 break;
306 /* If we already have the data, fall through. */
307
308 case omapi_protocol_header_wait:
20916cae 309 status = omapi_message_allocate (&p -> message, MDL);
61b844bf
TL
310 if (status != ISC_R_SUCCESS) {
311 omapi_disconnect (c, 1);
312 return status;
313 }
314
61b844bf 315 /* Swap in the header... */
d9eefc5d 316 omapi_connection_get_uint32 (c, &p -> message -> authid);
61b844bf
TL
317
318 /* XXX bind the authenticator here! */
d9eefc5d
TL
319 omapi_connection_get_uint32 (c, &p -> message -> authlen);
320 omapi_connection_get_uint32 (c, &p -> message -> op);
bbdb72a4 321 omapi_connection_get_uint32 (c, &th);
3185c188 322 p -> message -> h = th;
d9eefc5d
TL
323 omapi_connection_get_uint32 (c, &p -> message -> id);
324 omapi_connection_get_uint32 (c, &p -> message -> rid);
61b844bf
TL
325
326 /* If there was any extra header data, skip over it. */
327 if (p -> header_size > sizeof (omapi_protocol_header_t)) {
328 omapi_connection_copyout
329 (0, c, (p -> header_size -
330 sizeof (omapi_protocol_header_t)));
331 }
332
333 /* XXX must compute partial signature across the
334 XXX preceding bytes. Also, if authenticator
335 specifies encryption as well as signing, we may
336 have to decrypt the data on the way in. */
337
581e37e4
TL
338 /* First we read in message-specific values, then object
339 values. */
340 p -> reading_message_values = 1;
341
61b844bf
TL
342 need_name_length:
343 /* The next thing we're expecting is length of the
344 first name. */
345 p -> state = omapi_protocol_name_length_wait;
346
347 /* Wait for a 16-bit length. */
348 if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
349 break;
350 /* If it's already here, fall through. */
351
352 case omapi_protocol_name_length_wait:
353 omapi_connection_get_uint16 (c, &nlen);
354 /* A zero-length name means that we're done reading name+value
355 pairs. */
356 if (nlen == 0) {
581e37e4
TL
357 /* If we've already read in the object, we are
358 done reading the message, but if we've just
359 finished reading in the values associated
360 with the message, we need to read the
361 object. */
362 if (p -> reading_message_values) {
363 p -> reading_message_values = 0;
364 goto need_name_length;
365 }
366
61b844bf
TL
367 /* If the authenticator length is zero, there's no
368 signature to read in, so go straight to processing
369 the message. */
370 if (p -> message -> authlen == 0)
371 goto message_done;
372
373 /* The next thing we're expecting is the
374 message signature. */
375 p -> state = omapi_protocol_signature_wait;
376
377 /* Wait for the number of bytes specified for
378 the authenticator. If we already have it,
379 go read it in. */
380 if (omapi_connection_require
381 (c, p -> message -> authlen) == ISC_R_SUCCESS)
382 goto signature_wait;
383 break;
384 }
385
386 /* Allocate a buffer for the name. */
4bd8800e 387 status = (omapi_data_string_new (&p -> name, nlen, MDL));
61b844bf
TL
388 if (status != ISC_R_SUCCESS) {
389 omapi_disconnect (c, 1);
390 return ISC_R_NOMEMORY;
391 }
581e37e4 392 p -> state = omapi_protocol_name_wait;
61b844bf
TL
393 if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
394 break;
395 /* If it's already here, fall through. */
396
397 case omapi_protocol_name_wait:
398 omapi_connection_copyout (p -> name -> value, c,
399 p -> name -> len);
400 /* Wait for a 32-bit length. */
581e37e4 401 p -> state = omapi_protocol_value_length_wait;
61b844bf
TL
402 if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
403 break;
404 /* If it's already here, fall through. */
405
406 case omapi_protocol_value_length_wait:
407 omapi_connection_get_uint32 (c, &vlen);
408
409 /* Zero-length values are allowed - if we get one, we
410 don't have to read any data for the value - just
411 get the next one, if there is a next one. */
412 if (!vlen)
413 goto insert_new_value;
414
4bd8800e
TL
415 status = omapi_typed_data_new (MDL, &p -> value,
416 omapi_datatype_data,
417 vlen);
61b844bf
TL
418 if (status != ISC_R_SUCCESS) {
419 omapi_disconnect (c, 1);
420 return ISC_R_NOMEMORY;
421 }
422
581e37e4 423 p -> state = omapi_protocol_value_wait;
61b844bf
TL
424 if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
425 break;
426 /* If it's already here, fall through. */
427
428 case omapi_protocol_value_wait:
429 omapi_connection_copyout (p -> value -> u.buffer.value, c,
430 p -> value -> u.buffer.len);
431
432 insert_new_value:
581e37e4
TL
433 if (p -> reading_message_values) {
434 status = (omapi_set_value
435 ((omapi_object_t *)p -> message,
436 p -> message -> id_object,
437 p -> name, p -> value));
438 } else {
439 if (!p -> message -> object) {
440 /* We need a generic object to hang off of the
441 incoming message. */
442 status = (omapi_generic_new
4bd8800e 443 (&p -> message -> object, MDL));
581e37e4
TL
444 if (status != ISC_R_SUCCESS) {
445 omapi_disconnect (c, 1);
446 return status;
447 }
448 }
449 status = (omapi_set_value
450 ((omapi_object_t *)p -> message -> object,
451 p -> message -> id_object,
452 p -> name, p -> value));
453 }
61b844bf
TL
454 if (status != ISC_R_SUCCESS) {
455 omapi_disconnect (c, 1);
456 return status;
457 }
4bd8800e
TL
458 omapi_data_string_dereference (&p -> name, MDL);
459 omapi_typed_data_dereference (&p -> value, MDL);
61b844bf
TL
460 goto need_name_length;
461
462 signature_wait:
463 case omapi_protocol_signature_wait:
4bd8800e
TL
464 status = omapi_typed_data_new (MDL,
465 &p -> message -> authenticator,
61b844bf
TL
466 omapi_datatype_data,
467 p -> message -> authlen);
468
469 if (status != ISC_R_SUCCESS) {
470 omapi_disconnect (c, 1);
471 return ISC_R_NOMEMORY;
472 }
473 omapi_connection_copyout
474 (p -> message -> authenticator -> u.buffer.value, c,
475 p -> message -> authlen);
476 /* XXX now do something to verify the signature. */
477
581e37e4 478 /* Process the message. */
61b844bf 479 message_done:
5a8e13c6
TL
480 status = omapi_message_process ((omapi_object_t *)p -> message,
481 h);
581e37e4
TL
482 if (status != ISC_R_SUCCESS) {
483 omapi_disconnect (c, 1);
484 return ISC_R_NOMEMORY;
485 }
486
61b844bf 487 /* XXX unbind the authenticator. */
581e37e4 488 auth_unbind:
20916cae 489 omapi_message_dereference (&p -> message, MDL);
61b844bf
TL
490
491 /* Now wait for the next message. */
492 goto to_header_wait;
493
494 default:
495 /* XXX should never get here. Assertion? */
8a6dfe4c 496 break;
61b844bf
TL
497 }
498 return ISC_R_SUCCESS;
499}
500
501isc_result_t omapi_protocol_set_value (omapi_object_t *h,
502 omapi_object_t *id,
503 omapi_data_string_t *name,
504 omapi_typed_data_t *value)
505{
506 if (h -> type != omapi_type_protocol)
507 return ISC_R_INVALIDARG;
508
509 if (h -> inner && h -> inner -> type -> set_value)
510 return (*(h -> inner -> type -> set_value))
511 (h -> inner, id, name, value);
512 return ISC_R_NOTFOUND;
513}
514
515isc_result_t omapi_protocol_get_value (omapi_object_t *h,
516 omapi_object_t *id,
517 omapi_data_string_t *name,
518 omapi_value_t **value)
519{
520 if (h -> type != omapi_type_protocol)
521 return ISC_R_INVALIDARG;
522
523 if (h -> inner && h -> inner -> type -> get_value)
524 return (*(h -> inner -> type -> get_value))
525 (h -> inner, id, name, value);
526 return ISC_R_NOTFOUND;
527}
528
4bd8800e
TL
529isc_result_t omapi_protocol_destroy (omapi_object_t *h,
530 const char *file, int line)
61b844bf
TL
531{
532 omapi_protocol_object_t *p;
533 if (h -> type != omapi_type_protocol)
534 return ISC_R_INVALIDARG;
535 p = (omapi_protocol_object_t *)h;
536 if (p -> message)
20916cae 537 omapi_message_dereference (&p -> message, file, line);
61b844bf 538 if (p -> authinfo)
4bd8800e 539 return omapi_object_dereference (&p -> authinfo, file, line);
61b844bf
TL
540 return ISC_R_SUCCESS;
541}
542
543/* Write all the published values associated with the object through the
544 specified connection. */
545
546isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
547 omapi_object_t *id,
548 omapi_object_t *p)
549{
550 int i;
551
552 if (p -> type != omapi_type_protocol)
553 return ISC_R_INVALIDARG;
554
555 if (p -> inner && p -> inner -> type -> stuff_values)
556 return (*(p -> inner -> type -> stuff_values)) (c, id,
557 p -> inner);
558 return ISC_R_SUCCESS;
559}
560
561/* Set up a listener for the omapi protocol. The handle stored points to
562 a listener object, not a protocol object. */
563
564isc_result_t omapi_protocol_listen (omapi_object_t *h,
d9eefc5d 565 unsigned port,
61b844bf
TL
566 int max)
567{
568 isc_result_t status;
569 omapi_protocol_listener_object_t *obj;
570
20916cae
TL
571 obj = (omapi_protocol_listener_object_t *)0;
572 status = omapi_protocol_listener_allocate (&obj, MDL);
573 if (status != ISC_R_SUCCESS)
574 return status;
61b844bf 575
4bd8800e
TL
576 status = omapi_object_reference (&h -> outer,
577 (omapi_object_t *)obj, MDL);
61b844bf 578 if (status != ISC_R_SUCCESS) {
20916cae 579 omapi_protocol_listener_dereference (&obj, MDL);
61b844bf
TL
580 return status;
581 }
4bd8800e 582 status = omapi_object_reference (&obj -> inner, h, MDL);
61b844bf 583 if (status != ISC_R_SUCCESS) {
20916cae 584 omapi_protocol_listener_dereference (&obj, MDL);
61b844bf
TL
585 return status;
586 }
587
588 status = omapi_listen ((omapi_object_t *)obj, port, max);
20916cae 589 omapi_protocol_listener_dereference (&obj, MDL);
61b844bf
TL
590 return status;
591}
592
593/* Signal handler for protocol listener - if we get a connect signal,
594 create a new protocol connection, otherwise pass the signal down. */
595
596isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
b1b7b521 597 const char *name, va_list ap)
61b844bf
TL
598{
599 isc_result_t status;
600 omapi_object_t *c;
601 omapi_protocol_object_t *obj;
602 omapi_protocol_listener_object_t *p;
603
604 if (!o || o -> type != omapi_type_protocol_listener)
605 return ISC_R_INVALIDARG;
606 p = (omapi_protocol_listener_object_t *)o;
607
608 /* Not a signal we recognize? */
609 if (strcmp (name, "connect")) {
610 if (p -> inner && p -> inner -> type -> signal_handler)
611 return (*(p -> inner -> type -> signal_handler))
612 (p -> inner, name, ap);
613 return ISC_R_NOTFOUND;
614 }
615
616 c = va_arg (ap, omapi_object_t *);
617 if (!c || c -> type != omapi_type_connection)
618 return ISC_R_INVALIDARG;
619
20916cae
TL
620 obj = (omapi_protocol_object_t *)0;
621 status = omapi_protocol_allocate (&obj, MDL);
622 if (status != ISC_R_SUCCESS)
623 return status;
61b844bf 624
4bd8800e 625 status = omapi_object_reference (&obj -> outer, c, MDL);
61b844bf
TL
626 if (status != ISC_R_SUCCESS) {
627 lose:
20916cae 628 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
629 omapi_disconnect (c, 1);
630 return status;
631 }
632
4bd8800e
TL
633 status = omapi_object_reference (&c -> inner,
634 (omapi_object_t *)obj, MDL);
61b844bf
TL
635 if (status != ISC_R_SUCCESS)
636 goto lose;
637
638 /* Send the introductory message. */
639 status = omapi_protocol_send_intro ((omapi_object_t *)obj,
640 OMAPI_PROTOCOL_VERSION,
641 sizeof (omapi_protocol_header_t));
642 if (status != ISC_R_SUCCESS)
643 goto lose;
644
20916cae 645 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
646 return status;
647}
648
649isc_result_t omapi_protocol_listener_set_value (omapi_object_t *h,
650 omapi_object_t *id,
651 omapi_data_string_t *name,
652 omapi_typed_data_t *value)
653{
654 if (h -> type != omapi_type_protocol_listener)
655 return ISC_R_INVALIDARG;
656
657 if (h -> inner && h -> inner -> type -> set_value)
658 return (*(h -> inner -> type -> set_value))
659 (h -> inner, id, name, value);
660 return ISC_R_NOTFOUND;
661}
662
663isc_result_t omapi_protocol_listener_get_value (omapi_object_t *h,
664 omapi_object_t *id,
665 omapi_data_string_t *name,
666 omapi_value_t **value)
667{
668 if (h -> type != omapi_type_protocol_listener)
669 return ISC_R_INVALIDARG;
670
671 if (h -> inner && h -> inner -> type -> get_value)
672 return (*(h -> inner -> type -> get_value))
673 (h -> inner, id, name, value);
674 return ISC_R_NOTFOUND;
675}
676
b1b7b521 677isc_result_t omapi_protocol_listener_destroy (omapi_object_t *h,
4bd8800e 678 const char *file, int line)
61b844bf
TL
679{
680 if (h -> type != omapi_type_protocol_listener)
681 return ISC_R_INVALIDARG;
682 return ISC_R_SUCCESS;
683}
684
685/* Write all the published values associated with the object through the
686 specified connection. */
687
688isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
689 omapi_object_t *id,
690 omapi_object_t *p)
691{
692 int i;
693
694 if (p -> type != omapi_type_protocol_listener)
695 return ISC_R_INVALIDARG;
696
697 if (p -> inner && p -> inner -> type -> stuff_values)
698 return (*(p -> inner -> type -> stuff_values)) (c, id,
699 p -> inner);
700 return ISC_R_SUCCESS;
701}
702
5a8e13c6
TL
703isc_result_t omapi_protocol_send_status (omapi_object_t *po,
704 omapi_object_t *id,
705 isc_result_t waitstatus,
b1b7b521 706 unsigned rid, const char *msg)
5a8e13c6
TL
707{
708 isc_result_t status;
20916cae
TL
709 omapi_message_object_t *message = (omapi_message_object_t *)0;
710 omapi_object_t *mo;
5a8e13c6
TL
711
712 if (po -> type != omapi_type_protocol)
713 return ISC_R_INVALIDARG;
714
20916cae 715 status = omapi_message_allocate (&message, MDL);
5a8e13c6
TL
716 if (status != ISC_R_SUCCESS)
717 return status;
20916cae 718 mo = (omapi_object_t *)message;
5a8e13c6 719
20916cae 720 status = omapi_set_int_value (mo, (omapi_object_t *)0,
5a8e13c6
TL
721 "op", OMAPI_OP_STATUS);
722 if (status != ISC_R_SUCCESS) {
20916cae 723 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
724 return status;
725 }
726
20916cae 727 status = omapi_set_int_value (mo, (omapi_object_t *)0,
b1b7b521 728 "rid", (int)rid);
5a8e13c6 729 if (status != ISC_R_SUCCESS) {
20916cae 730 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
731 return status;
732 }
733
20916cae 734 status = omapi_set_int_value (mo, (omapi_object_t *)0,
b1b7b521 735 "result", (int)waitstatus);
5a8e13c6 736 if (status != ISC_R_SUCCESS) {
20916cae 737 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
738 return status;
739 }
740
741 /* If a message has been provided, send it. */
742 if (msg) {
20916cae 743 status = omapi_set_string_value (mo, (omapi_object_t *)0,
5a8e13c6
TL
744 "message", msg);
745 if (status != ISC_R_SUCCESS) {
20916cae 746 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
747 return status;
748 }
749 }
750
20916cae
TL
751 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
752 omapi_message_dereference (&message, MDL);
753 return status;
5a8e13c6
TL
754}
755
756isc_result_t omapi_protocol_send_update (omapi_object_t *po,
757 omapi_object_t *id,
b1b7b521 758 unsigned rid,
5a8e13c6
TL
759 omapi_object_t *object)
760{
761 isc_result_t status;
20916cae
TL
762 omapi_message_object_t *message = (omapi_message_object_t *)0;
763 omapi_object_t *mo;
5a8e13c6
TL
764
765 if (po -> type != omapi_type_protocol)
766 return ISC_R_INVALIDARG;
767
20916cae 768 status = omapi_message_allocate (&message, MDL);
5a8e13c6
TL
769 if (status != ISC_R_SUCCESS)
770 return status;
20916cae 771 mo = (omapi_object_t *)message;
5a8e13c6 772
20916cae 773 status = omapi_set_int_value (mo, (omapi_object_t *)0,
5a8e13c6
TL
774 "op", OMAPI_OP_UPDATE);
775 if (status != ISC_R_SUCCESS) {
20916cae 776 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
777 return status;
778 }
779
780 if (rid) {
e5bbe4da 781 omapi_handle_t handle;
20916cae 782 status = omapi_set_int_value (mo, (omapi_object_t *)0,
b1b7b521 783 "rid", (int)rid);
5a8e13c6 784 if (status != ISC_R_SUCCESS) {
20916cae 785 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
786 return status;
787 }
e5bbe4da 788
5a8e13c6
TL
789 status = omapi_object_handle (&handle, object);
790 if (status != ISC_R_SUCCESS) {
20916cae 791 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
792 return status;
793 }
20916cae 794 status = omapi_set_int_value (mo, (omapi_object_t *)0,
b1b7b521 795 "handle", (int)handle);
5a8e13c6 796 if (status != ISC_R_SUCCESS) {
20916cae 797 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
798 return status;
799 }
800 }
801
20916cae 802 status = omapi_set_object_value (mo, (omapi_object_t *)0,
5a8e13c6
TL
803 "object", object);
804 if (status != ISC_R_SUCCESS) {
20916cae 805 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
806 return status;
807 }
808
20916cae
TL
809 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
810 omapi_message_dereference (&message, MDL);
811 return status;
5a8e13c6 812}