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