1 /* $NetBSD: message.c,v 1.3 2022/04/03 01:10:59 christos Exp $ */
2
3 /* message.c
4
5 Subroutines for dealing with message objects. */
6
7 /*
8 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1999-2003 by Internet Software Consortium
10 *
11 * This Source Code Form is subject to the terms of the Mozilla Public
12 * License, v. 2.0. If a copy of the MPL was not distributed with this
13 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Internet Systems Consortium, Inc.
24 * PO Box 360
25 * Newmarket, NH 03857 USA
26 * <info@isc.org>
27 * https://www.isc.org/
28 *
29 */
30
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: message.c,v 1.3 2022/04/03 01:10:59 christos Exp $");
33
34 #include "dhcpd.h"
35
36 #include <omapip/omapip_p.h>
37
OMAPI_OBJECT_ALLOC(omapi_message,omapi_message_object_t,omapi_type_message)38 OMAPI_OBJECT_ALLOC (omapi_message,
39 omapi_message_object_t, omapi_type_message)
40
41 omapi_message_object_t *omapi_registered_messages;
42
43 isc_result_t omapi_message_new (omapi_object_t **o, const char *file, int line)
44 {
45 omapi_message_object_t *m;
46 omapi_object_t *g;
47 isc_result_t status;
48
49 m = (omapi_message_object_t *)0;
50 status = omapi_message_allocate (&m, file, line);
51 if (status != ISC_R_SUCCESS)
52 return status;
53
54 g = (omapi_object_t *)0;
55 status = omapi_generic_new (&g, file, line);
56 if (status != ISC_R_SUCCESS) {
57 dfree (m, file, line);
58 return status;
59 }
60 status = omapi_object_reference (&m -> inner, g, file, line);
61 if (status != ISC_R_SUCCESS) {
62 omapi_object_dereference ((omapi_object_t **)&m, file, line);
63 omapi_object_dereference (&g, file, line);
64 return status;
65 }
66 status = omapi_object_reference (&g -> outer,
67 (omapi_object_t *)m, file, line);
68
69 if (status != ISC_R_SUCCESS) {
70 omapi_object_dereference ((omapi_object_t **)&m, file, line);
71 omapi_object_dereference (&g, file, line);
72 return status;
73 }
74
75 status = omapi_object_reference (o, (omapi_object_t *)m, file, line);
76 omapi_message_dereference (&m, file, line);
77 omapi_object_dereference (&g, file, line);
78 if (status != ISC_R_SUCCESS)
79 return status;
80
81 return status;
82 }
83
omapi_message_set_value(omapi_object_t * h,omapi_object_t * id,omapi_data_string_t * name,omapi_typed_data_t * value)84 isc_result_t omapi_message_set_value (omapi_object_t *h,
85 omapi_object_t *id,
86 omapi_data_string_t *name,
87 omapi_typed_data_t *value)
88 {
89 omapi_message_object_t *m;
90 isc_result_t status;
91
92 if (h -> type != omapi_type_message)
93 return DHCP_R_INVALIDARG;
94 m = (omapi_message_object_t *)h;
95
96 /* Can't set authlen. */
97
98 /* Can set authenticator, but the value must be typed data. */
99 if (!omapi_ds_strcmp (name, "authenticator")) {
100 if (m -> authenticator)
101 omapi_typed_data_dereference (&m -> authenticator,
102 MDL);
103 omapi_typed_data_reference (&m -> authenticator, value, MDL);
104 return ISC_R_SUCCESS;
105
106 } else if (!omapi_ds_strcmp (name, "object")) {
107 if (value -> type != omapi_datatype_object)
108 return DHCP_R_INVALIDARG;
109 if (m -> object)
110 omapi_object_dereference (&m -> object, MDL);
111 omapi_object_reference (&m -> object, value -> u.object, MDL);
112 return ISC_R_SUCCESS;
113
114 } else if (!omapi_ds_strcmp (name, "notify-object")) {
115 if (value -> type != omapi_datatype_object)
116 return DHCP_R_INVALIDARG;
117 if (m -> notify_object)
118 omapi_object_dereference (&m -> notify_object, MDL);
119 omapi_object_reference (&m -> notify_object,
120 value -> u.object, MDL);
121 return ISC_R_SUCCESS;
122
123 /* Can set authid, but it has to be an integer. */
124 } else if (!omapi_ds_strcmp (name, "authid")) {
125 if (value -> type != omapi_datatype_int)
126 return DHCP_R_INVALIDARG;
127 m -> authid = value -> u.integer;
128 return ISC_R_SUCCESS;
129
130 /* Can set op, but it has to be an integer. */
131 } else if (!omapi_ds_strcmp (name, "op")) {
132 if (value -> type != omapi_datatype_int)
133 return DHCP_R_INVALIDARG;
134 m -> op = value -> u.integer;
135 return ISC_R_SUCCESS;
136
137 /* Handle also has to be an integer. */
138 } else if (!omapi_ds_strcmp (name, "handle")) {
139 if (value -> type != omapi_datatype_int)
140 return DHCP_R_INVALIDARG;
141 m -> h = value -> u.integer;
142 return ISC_R_SUCCESS;
143
144 /* Transaction ID has to be an integer. */
145 } else if (!omapi_ds_strcmp (name, "id")) {
146 if (value -> type != omapi_datatype_int)
147 return DHCP_R_INVALIDARG;
148 m -> id = value -> u.integer;
149 return ISC_R_SUCCESS;
150
151 /* Remote transaction ID has to be an integer. */
152 } else if (!omapi_ds_strcmp (name, "rid")) {
153 if (value -> type != omapi_datatype_int)
154 return DHCP_R_INVALIDARG;
155 m -> rid = value -> u.integer;
156 return ISC_R_SUCCESS;
157 }
158
159 /* Try to find some inner object that can take the value. */
160 if (h -> inner && h -> inner -> type -> set_value) {
161 status = ((*(h -> inner -> type -> set_value))
162 (h -> inner, id, name, value));
163 if (status == ISC_R_SUCCESS)
164 return status;
165 }
166
167 return ISC_R_NOTFOUND;
168 }
169
omapi_message_get_value(omapi_object_t * h,omapi_object_t * id,omapi_data_string_t * name,omapi_value_t ** value)170 isc_result_t omapi_message_get_value (omapi_object_t *h,
171 omapi_object_t *id,
172 omapi_data_string_t *name,
173 omapi_value_t **value)
174 {
175 omapi_message_object_t *m;
176 if (h -> type != omapi_type_message)
177 return DHCP_R_INVALIDARG;
178 m = (omapi_message_object_t *)h;
179
180 /* Look for values that are in the message data structure. */
181 if (!omapi_ds_strcmp (name, "authlen"))
182 return omapi_make_int_value (value, name, (int)m -> authlen,
183 MDL);
184 else if (!omapi_ds_strcmp (name, "authenticator")) {
185 if (m -> authenticator)
186 return omapi_make_value (value, name,
187 m -> authenticator, MDL);
188 else
189 return ISC_R_NOTFOUND;
190 } else if (!omapi_ds_strcmp (name, "authid")) {
191 return omapi_make_int_value (value,
192 name, (int)m -> authid, MDL);
193 } else if (!omapi_ds_strcmp (name, "op")) {
194 return omapi_make_int_value (value, name, (int)m -> op, MDL);
195 } else if (!omapi_ds_strcmp (name, "handle")) {
196 return omapi_make_int_value (value, name, (int)m -> h, MDL);
197 } else if (!omapi_ds_strcmp (name, "id")) {
198 return omapi_make_int_value (value, name, (int)m -> id, MDL);
199 } else if (!omapi_ds_strcmp (name, "rid")) {
200 return omapi_make_int_value (value, name, (int)m -> rid, MDL);
201 }
202
203 /* See if there's an inner object that has the value. */
204 if (h -> inner && h -> inner -> type -> get_value)
205 return (*(h -> inner -> type -> get_value))
206 (h -> inner, id, name, value);
207 return ISC_R_NOTFOUND;
208 }
209
omapi_message_destroy(omapi_object_t * h,const char * file,int line)210 isc_result_t omapi_message_destroy (omapi_object_t *h,
211 const char *file, int line)
212 {
213 omapi_message_object_t *m;
214 if (h -> type != omapi_type_message)
215 return DHCP_R_INVALIDARG;
216 m = (omapi_message_object_t *)h;
217 if (m -> authenticator) {
218 omapi_typed_data_dereference (&m -> authenticator, file, line);
219 }
220 if (!m -> prev && omapi_registered_messages != m)
221 omapi_message_unregister (h);
222 if (m -> id_object)
223 omapi_object_dereference (&m -> id_object, file, line);
224 if (m -> object)
225 omapi_object_dereference (&m -> object, file, line);
226 if (m -> notify_object)
227 omapi_object_dereference (&m -> notify_object, file, line);
228 if (m -> protocol_object)
229 omapi_protocol_dereference (&m -> protocol_object, file, line);
230 return ISC_R_SUCCESS;
231 }
232
omapi_message_signal_handler(omapi_object_t * h,const char * name,va_list ap)233 isc_result_t omapi_message_signal_handler (omapi_object_t *h,
234 const char *name, va_list ap)
235 {
236 omapi_message_object_t *m;
237 if (h -> type != omapi_type_message)
238 return DHCP_R_INVALIDARG;
239 m = (omapi_message_object_t *)h;
240
241 if (!strcmp (name, "status")) {
242 if (m -> notify_object &&
243 m -> notify_object -> type -> signal_handler)
244 return ((m -> notify_object -> type -> signal_handler))
245 (m -> notify_object, name, ap);
246 else if (m -> object && m -> object -> type -> signal_handler)
247 return ((m -> object -> type -> signal_handler))
248 (m -> object, name, ap);
249 }
250 if (h -> inner && h -> inner -> type -> signal_handler)
251 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
252 name, ap);
253 return ISC_R_NOTFOUND;
254 }
255
256 /* Write all the published values associated with the object through the
257 specified connection. */
258
omapi_message_stuff_values(omapi_object_t * c,omapi_object_t * id,omapi_object_t * m)259 isc_result_t omapi_message_stuff_values (omapi_object_t *c,
260 omapi_object_t *id,
261 omapi_object_t *m)
262 {
263 if (m -> type != omapi_type_message)
264 return DHCP_R_INVALIDARG;
265
266 if (m -> inner && m -> inner -> type -> stuff_values)
267 return (*(m -> inner -> type -> stuff_values)) (c, id,
268 m -> inner);
269 return ISC_R_SUCCESS;
270 }
271
omapi_message_register(omapi_object_t * mo)272 isc_result_t omapi_message_register (omapi_object_t *mo)
273 {
274 omapi_message_object_t *m;
275
276 if (mo -> type != omapi_type_message)
277 return DHCP_R_INVALIDARG;
278 m = (omapi_message_object_t *)mo;
279
280 /* Already registered? */
281 if (m -> prev || m -> next || omapi_registered_messages == m)
282 return DHCP_R_INVALIDARG;
283
284 if (omapi_registered_messages) {
285 omapi_object_reference
286 ((omapi_object_t **)&m -> next,
287 (omapi_object_t *)omapi_registered_messages, MDL);
288 omapi_object_reference
289 ((omapi_object_t **)&omapi_registered_messages -> prev,
290 (omapi_object_t *)m, MDL);
291 omapi_object_dereference
292 ((omapi_object_t **)&omapi_registered_messages, MDL);
293 }
294 omapi_object_reference
295 ((omapi_object_t **)&omapi_registered_messages,
296 (omapi_object_t *)m, MDL);
297 return ISC_R_SUCCESS;;
298 }
299
omapi_message_unregister(omapi_object_t * mo)300 isc_result_t omapi_message_unregister (omapi_object_t *mo)
301 {
302 omapi_message_object_t *m;
303 omapi_message_object_t *n;
304
305 if (mo -> type != omapi_type_message)
306 return DHCP_R_INVALIDARG;
307 m = (omapi_message_object_t *)mo;
308
309 /* Not registered? */
310 if (!m -> prev && omapi_registered_messages != m)
311 return DHCP_R_INVALIDARG;
312
313 n = (omapi_message_object_t *)0;
314 if (m -> next) {
315 omapi_object_reference ((omapi_object_t **)&n,
316 (omapi_object_t *)m -> next, MDL);
317 omapi_object_dereference ((omapi_object_t **)&m -> next, MDL);
318 omapi_object_dereference ((omapi_object_t **)&n -> prev, MDL);
319 }
320 if (m -> prev) {
321 omapi_message_object_t *tmp = (omapi_message_object_t *)0;
322 omapi_object_reference ((omapi_object_t **)&tmp,
323 (omapi_object_t *)m -> prev, MDL);
324 omapi_object_dereference ((omapi_object_t **)&m -> prev, MDL);
325 if (tmp -> next)
326 omapi_object_dereference
327 ((omapi_object_t **)&tmp -> next, MDL);
328 if (n)
329 omapi_object_reference
330 ((omapi_object_t **)&tmp -> next,
331 (omapi_object_t *)n, MDL);
332 omapi_object_dereference ((omapi_object_t **)&tmp, MDL);
333 } else {
334 omapi_object_dereference
335 ((omapi_object_t **)&omapi_registered_messages, MDL);
336 if (n)
337 omapi_object_reference
338 ((omapi_object_t **)&omapi_registered_messages,
339 (omapi_object_t *)n, MDL);
340 }
341 if (n)
342 omapi_object_dereference ((omapi_object_t **)&n, MDL);
343 return ISC_R_SUCCESS;
344 }
345
346 #ifdef DEBUG_PROTOCOL
omapi_message_op_name(int op)347 const char *omapi_message_op_name(int op) {
348 switch (op) {
349 case OMAPI_OP_OPEN: return "OMAPI_OP_OPEN";
350 case OMAPI_OP_REFRESH: return "OMAPI_OP_REFRESH";
351 case OMAPI_OP_UPDATE: return "OMAPI_OP_UPDATE";
352 case OMAPI_OP_STATUS: return "OMAPI_OP_STATUS";
353 case OMAPI_OP_DELETE: return "OMAPI_OP_DELETE";
354 case OMAPI_OP_NOTIFY: return "OMAPI_OP_NOTIFY";
355 default: return "(unknown op)";
356 }
357 }
358 #endif
359
360 static isc_result_t
361 omapi_message_process_internal (omapi_object_t *, omapi_object_t *);
362
omapi_message_process(omapi_object_t * mo,omapi_object_t * po)363 isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
364 {
365 isc_result_t status;
366 #if defined (DEBUG_MEMORY_LEAKAGE) && 0
367 unsigned long previous_outstanding = dmalloc_outstanding;
368 #endif
369
370 status = omapi_message_process_internal (mo, po);
371
372 #if defined (DEBUG_MEMORY_LEAKAGE) && 0
373 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
374 dmalloc_generation,
375 dmalloc_outstanding - previous_outstanding,
376 dmalloc_outstanding, dmalloc_longterm);
377 #endif
378 #if defined (DEBUG_MEMORY_LEAKAGE) && 0
379 dmalloc_dump_outstanding ();
380 #endif
381 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY) && 0
382 dump_rc_history ();
383 #endif
384
385 return status;
386 }
387
388 static isc_result_t
omapi_message_process_internal(omapi_object_t * mo,omapi_object_t * po)389 omapi_message_process_internal (omapi_object_t *mo, omapi_object_t *po)
390 {
391 omapi_message_object_t *message, *m;
392 omapi_object_t *object = (omapi_object_t *)0;
393 omapi_value_t *tv = (omapi_value_t *)0;
394 unsigned long create, update, exclusive;
395 unsigned long wsi;
396 isc_result_t status, waitstatus;
397 omapi_object_type_t *type;
398
399 if (mo -> type != omapi_type_message)
400 return DHCP_R_INVALIDARG;
401 message = (omapi_message_object_t *)mo;
402
403 #ifdef DEBUG_PROTOCOL
404 log_debug ("omapi_message_process(): "
405 "op=%s handle=%#x id=%#x rid=%#x",
406 omapi_message_op_name (message -> op),
407 message -> h, message -> id, message -> rid);
408 #endif
409
410 if (message -> rid) {
411 for (m = omapi_registered_messages; m; m = m -> next)
412 if (m -> id == message -> rid)
413 break;
414 /* If we don't have a real message corresponding to
415 the message ID to which this message claims it is a
416 response, something's fishy. */
417 if (!m)
418 return ISC_R_NOTFOUND;
419 /* The authenticator on responses must match the initial
420 message. */
421 if (message -> authid != m -> authid)
422 return ISC_R_NOTFOUND;
423 } else {
424 m = (omapi_message_object_t *)0;
425
426 /* All messages must have an authenticator, with the exception
427 of messages that are opening a new authenticator. */
428 if (omapi_protocol_authenticated(po) &&
429 !message->id_object &&
430 message->op != OMAPI_OP_OPEN) {
431 return omapi_protocol_send_status
432 (po, message->id_object, DHCP_R_NOKEYS,
433 message->id, "No authenticator on message");
434 }
435 }
436
437 switch (message -> op) {
438 case OMAPI_OP_OPEN:
439 if (m) {
440 return omapi_protocol_send_status
441 (po, message->id_object, DHCP_R_INVALIDARG,
442 message->id, "OPEN can't be a response");
443 }
444
445 /* Get the type of the requested object, if one was
446 specified. */
447 status = omapi_get_value_str (mo, message -> id_object,
448 "type", &tv);
449 if (status == ISC_R_SUCCESS &&
450 (tv -> value -> type == omapi_datatype_data ||
451 tv -> value -> type == omapi_datatype_string)) {
452 for (type = omapi_object_types;
453 type; type = type -> next)
454 if (!omapi_td_strcmp (tv -> value,
455 type -> name))
456 break;
457 } else
458 type = (omapi_object_type_t *)0;
459 if (tv)
460 omapi_value_dereference (&tv, MDL);
461
462 /* If this object had no authenticator, the requested object
463 must be an authenticator object. */
464 if (omapi_protocol_authenticated(po) &&
465 !message->id_object &&
466 type != omapi_type_auth_key) {
467 return omapi_protocol_send_status
468 (po, message->id_object, DHCP_R_NOKEYS,
469 message->id, "No authenticator on message");
470 }
471
472 /* Get the create flag. */
473 status = omapi_get_value_str (mo, message -> id_object,
474 "create", &tv);
475 if (status == ISC_R_SUCCESS) {
476 status = omapi_get_int_value (&create, tv -> value);
477 omapi_value_dereference (&tv, MDL);
478 if (status != ISC_R_SUCCESS) {
479 return omapi_protocol_send_status
480 (po, message -> id_object,
481 status, message -> id,
482 "invalid create flag value");
483 }
484 } else
485 create = 0;
486
487 /* Get the update flag. */
488 status = omapi_get_value_str (mo, message -> id_object,
489 "update", &tv);
490 if (status == ISC_R_SUCCESS) {
491 status = omapi_get_int_value (&update, tv -> value);
492 omapi_value_dereference (&tv, MDL);
493 if (status != ISC_R_SUCCESS) {
494 return omapi_protocol_send_status
495 (po, message -> id_object,
496 status, message -> id,
497 "invalid update flag value");
498 }
499 } else
500 update = 0;
501
502 /* Get the exclusive flag. */
503 status = omapi_get_value_str (mo, message -> id_object,
504 "exclusive", &tv);
505 if (status == ISC_R_SUCCESS) {
506 status = omapi_get_int_value (&exclusive, tv -> value);
507 omapi_value_dereference (&tv, MDL);
508 if (status != ISC_R_SUCCESS) {
509 return omapi_protocol_send_status
510 (po, message -> id_object,
511 status, message -> id,
512 "invalid exclusive flag value");
513 }
514 } else
515 exclusive = 0;
516
517 /* If we weren't given a type, look the object up with
518 the handle. */
519 if (!type) {
520 if (create) {
521 return omapi_protocol_send_status
522 (po, message->id_object,
523 DHCP_R_INVALIDARG,
524 message->id,
525 "type required on create");
526 }
527 goto refresh;
528 }
529
530 /* If the type doesn't provide a lookup method, we can't
531 look up the object. */
532 if (!type -> lookup) {
533 return omapi_protocol_send_status
534 (po, message -> id_object,
535 ISC_R_NOTIMPLEMENTED, message -> id,
536 "unsearchable object type");
537 }
538
539 status = (*(type -> lookup)) (&object, message -> id_object,
540 message -> object);
541
542 if (status != ISC_R_SUCCESS &&
543 status != ISC_R_NOTFOUND &&
544 status != DHCP_R_NOKEYS) {
545 return omapi_protocol_send_status
546 (po, message -> id_object,
547 status, message -> id,
548 "object lookup failed");
549 }
550
551 /* If we didn't find the object and we aren't supposed to
552 create it, return an error. */
553 if (status == ISC_R_NOTFOUND && !create) {
554 return omapi_protocol_send_status
555 (po, message -> id_object,
556 ISC_R_NOTFOUND, message -> id,
557 "no object matches specification");
558 }
559
560 /* If we found an object, we're supposed to be creating an
561 object, and we're not supposed to have found an object,
562 return an error. */
563 if (status == ISC_R_SUCCESS && create && exclusive) {
564 omapi_object_dereference (&object, MDL);
565 return omapi_protocol_send_status
566 (po, message -> id_object,
567 ISC_R_EXISTS, message -> id,
568 "specified object already exists");
569 }
570
571 /* If we're creating the object, do it now. */
572 if (!object) {
573 status = omapi_object_create (&object,
574 message -> id_object,
575 type);
576 if (status != ISC_R_SUCCESS) {
577 return omapi_protocol_send_status
578 (po, message -> id_object,
579 status, message -> id,
580 "can't create new object");
581 }
582 }
583
584 /* If we're updating it, do so now. */
585 if (create || update) {
586 /* This check does not belong here. */
587 if (object -> type == omapi_type_auth_key) {
588 omapi_object_dereference (&object, MDL);
589 return omapi_protocol_send_status
590 (po, message -> id_object,
591 status, message -> id,
592 "can't update object");
593 }
594
595 status = omapi_object_update (object,
596 message -> id_object,
597 message -> object,
598 message -> h);
599 if (status != ISC_R_SUCCESS) {
600 omapi_object_dereference (&object, MDL);
601 return omapi_protocol_send_status
602 (po, message -> id_object,
603 status, message -> id,
604 "can't update object");
605 }
606 }
607
608 /* If this is an authenticator object, add it to the active
609 set for the connection. */
610 if (object -> type == omapi_type_auth_key) {
611 omapi_handle_t handle;
612 status = omapi_object_handle (&handle, object);
613 if (status != ISC_R_SUCCESS) {
614 omapi_object_dereference (&object, MDL);
615 return omapi_protocol_send_status
616 (po, message -> id_object,
617 status, message -> id,
618 "can't select authenticator");
619 }
620
621 status = omapi_protocol_add_auth (po, object, handle);
622 if (status != ISC_R_SUCCESS) {
623 omapi_object_dereference (&object, MDL);
624 return omapi_protocol_send_status
625 (po, message -> id_object,
626 status, message -> id,
627 "can't select authenticator");
628 }
629 }
630
631 /* Now send the new contents of the object back in
632 response. */
633 goto send;
634
635 case OMAPI_OP_REFRESH:
636 refresh:
637 status = omapi_handle_lookup (&object, message -> h);
638 if (status != ISC_R_SUCCESS) {
639 return omapi_protocol_send_status
640 (po, message -> id_object,
641 status, message -> id,
642 "no matching handle");
643 }
644 send:
645 status = omapi_protocol_send_update (po, message -> id_object,
646 message -> id, object);
647 omapi_object_dereference (&object, MDL);
648 return status;
649
650 case OMAPI_OP_UPDATE:
651 if (m && m -> object) {
652 status = omapi_object_reference (&object, m -> object,
653 MDL);
654 } else {
655 status = omapi_handle_lookup (&object, message -> h);
656 if (status != ISC_R_SUCCESS) {
657 return omapi_protocol_send_status
658 (po, message -> id_object,
659 status, message -> id,
660 "no matching handle");
661 }
662 }
663
664 if (object -> type == omapi_type_auth_key ||
665 (object -> inner &&
666 object -> inner -> type == omapi_type_auth_key)) {
667 if (!m) {
668 omapi_object_dereference (&object, MDL);
669 return omapi_protocol_send_status
670 (po, message -> id_object,
671 status, message -> id,
672 "cannot update authenticator");
673 }
674
675 status = omapi_protocol_add_auth (po, object,
676 message -> h);
677 } else {
678 status = omapi_object_update (object,
679 message -> id_object,
680 message -> object,
681 message -> h);
682 }
683 if (status != ISC_R_SUCCESS) {
684 omapi_object_dereference (&object, MDL);
685 if (!message -> rid)
686 return omapi_protocol_send_status
687 (po, message -> id_object,
688 status, message -> id,
689 "can't update object");
690 if (m)
691 omapi_signal ((omapi_object_t *)m,
692 "status", status,
693 (omapi_typed_data_t *)0);
694 return ISC_R_SUCCESS;
695 }
696 if (!message -> rid)
697 status = omapi_protocol_send_status
698 (po, message -> id_object, ISC_R_SUCCESS,
699 message -> id, (char *)0);
700 if (m) {
701 omapi_signal ((omapi_object_t *)m,
702 "status", ISC_R_SUCCESS,
703 (omapi_typed_data_t *)0);
704 omapi_message_unregister ((omapi_object_t *)m);
705 }
706
707 omapi_object_dereference (&object, MDL);
708
709 return status;
710
711 case OMAPI_OP_NOTIFY:
712 return omapi_protocol_send_status
713 (po, message -> id_object, ISC_R_NOTIMPLEMENTED,
714 message -> id, "notify not implemented yet");
715
716 case OMAPI_OP_STATUS:
717 /* The return status of a request. */
718 if (!m)
719 return ISC_R_UNEXPECTED;
720
721 /* Get the wait status. */
722 status = omapi_get_value_str (mo, message -> id_object,
723 "result", &tv);
724 if (status == ISC_R_SUCCESS) {
725 status = omapi_get_int_value (&wsi, tv -> value);
726 waitstatus = wsi;
727 omapi_value_dereference (&tv, MDL);
728 if (status != ISC_R_SUCCESS)
729 waitstatus = ISC_R_UNEXPECTED;
730 } else
731 waitstatus = ISC_R_UNEXPECTED;
732
733 status = omapi_get_value_str (mo, message -> id_object,
734 "message", &tv);
735 omapi_signal ((omapi_object_t *)m, "status", waitstatus, tv);
736 if (status == ISC_R_SUCCESS)
737 omapi_value_dereference (&tv, MDL);
738
739 omapi_message_unregister((omapi_object_t *)m);
740
741 return ISC_R_SUCCESS;
742
743 case OMAPI_OP_DELETE:
744 status = omapi_handle_lookup (&object, message -> h);
745 if (status != ISC_R_SUCCESS) {
746 return omapi_protocol_send_status
747 (po, message -> id_object,
748 status, message -> id,
749 "no matching handle");
750 }
751
752 if (!object -> type -> remove)
753 return omapi_protocol_send_status
754 (po, message -> id_object,
755 ISC_R_NOTIMPLEMENTED, message -> id,
756 "no remove method for object");
757
758 status = (*(object -> type -> remove)) (object,
759 message -> id_object);
760 omapi_object_dereference (&object, MDL);
761
762 return omapi_protocol_send_status (po, message -> id_object,
763 status, message -> id,
764 (char *)0);
765 }
766 return ISC_R_NOTIMPLEMENTED;
767 }
768