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