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