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