xref: /minix/external/bsd/dhcp/dist/omapip/message.c (revision 9f7f0ad0)
1 /*	$NetBSD: message.c,v 1.1.1.2 2014/07/12 11:57:59 spz Exp $	*/
2 /* message.c
3 
4    Subroutines for dealing with message objects. */
5 
6 /*
7  * Copyright (c) 2004,2007,2009,2014 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 1999-2003 by Internet Software Consortium
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  *   Internet Systems Consortium, Inc.
23  *   950 Charter Street
24  *   Redwood City, CA 94063
25  *   <info@isc.org>
26  *   https://www.isc.org/
27  *
28  */
29 
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: message.c,v 1.1.1.2 2014/07/12 11:57:59 spz Exp $");
32 
33 #include "dhcpd.h"
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 DHCP_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 DHCP_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 DHCP_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 DHCP_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 DHCP_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 DHCP_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 DHCP_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 DHCP_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 DHCP_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 	omapi_message_object_t *m;
213 	if (h -> type != omapi_type_message)
214 		return DHCP_R_INVALIDARG;
215 	m = (omapi_message_object_t *)h;
216 	if (m -> authenticator) {
217 		omapi_typed_data_dereference (&m -> authenticator, file, line);
218 	}
219 	if (!m -> prev && omapi_registered_messages != m)
220 		omapi_message_unregister (h);
221 	if (m -> id_object)
222 		omapi_object_dereference (&m -> id_object, file, line);
223 	if (m -> object)
224 		omapi_object_dereference (&m -> object, file, line);
225 	if (m -> notify_object)
226 		omapi_object_dereference (&m -> notify_object, file, line);
227 	if (m -> protocol_object)
228 		omapi_protocol_dereference (&m -> protocol_object, file, line);
229 	return ISC_R_SUCCESS;
230 }
231 
232 isc_result_t omapi_message_signal_handler (omapi_object_t *h,
233 					   const char *name, va_list ap)
234 {
235 	omapi_message_object_t *m;
236 	if (h -> type != omapi_type_message)
237 		return DHCP_R_INVALIDARG;
238 	m = (omapi_message_object_t *)h;
239 
240 	if (!strcmp (name, "status")) {
241 		if (m -> notify_object &&
242 		    m -> notify_object -> type -> signal_handler)
243 			return ((m -> notify_object -> type -> signal_handler))
244 				(m -> notify_object, name, ap);
245 		else if (m -> object && m -> object -> type -> signal_handler)
246 			return ((m -> object -> type -> signal_handler))
247 				(m -> object, name, ap);
248 	}
249 	if (h -> inner && h -> inner -> type -> signal_handler)
250 		return (*(h -> inner -> type -> signal_handler)) (h -> inner,
251 								  name, ap);
252 	return ISC_R_NOTFOUND;
253 }
254 
255 /* Write all the published values associated with the object through the
256    specified connection. */
257 
258 isc_result_t omapi_message_stuff_values (omapi_object_t *c,
259 					 omapi_object_t *id,
260 					 omapi_object_t *m)
261 {
262 	if (m -> type != omapi_type_message)
263 		return DHCP_R_INVALIDARG;
264 
265 	if (m -> inner && m -> inner -> type -> stuff_values)
266 		return (*(m -> inner -> type -> stuff_values)) (c, id,
267 								m -> inner);
268 	return ISC_R_SUCCESS;
269 }
270 
271 isc_result_t omapi_message_register (omapi_object_t *mo)
272 {
273 	omapi_message_object_t *m;
274 
275 	if (mo -> type != omapi_type_message)
276 		return DHCP_R_INVALIDARG;
277 	m = (omapi_message_object_t *)mo;
278 
279 	/* Already registered? */
280 	if (m -> prev || m -> next || omapi_registered_messages == m)
281 		return DHCP_R_INVALIDARG;
282 
283 	if (omapi_registered_messages) {
284 		omapi_object_reference
285 			((omapi_object_t **)&m -> next,
286 			 (omapi_object_t *)omapi_registered_messages, MDL);
287 		omapi_object_reference
288 			((omapi_object_t **)&omapi_registered_messages -> prev,
289 			 (omapi_object_t *)m, MDL);
290 		omapi_object_dereference
291 			((omapi_object_t **)&omapi_registered_messages, MDL);
292 	}
293 	omapi_object_reference
294 		((omapi_object_t **)&omapi_registered_messages,
295 		 (omapi_object_t *)m, MDL);
296 	return ISC_R_SUCCESS;;
297 }
298 
299 isc_result_t omapi_message_unregister (omapi_object_t *mo)
300 {
301 	omapi_message_object_t *m;
302 	omapi_message_object_t *n;
303 
304 	if (mo -> type != omapi_type_message)
305 		return DHCP_R_INVALIDARG;
306 	m = (omapi_message_object_t *)mo;
307 
308 	/* Not registered? */
309 	if (!m -> prev && omapi_registered_messages != m)
310 		return DHCP_R_INVALIDARG;
311 
312 	n = (omapi_message_object_t *)0;
313 	if (m -> next) {
314 		omapi_object_reference ((omapi_object_t **)&n,
315 					(omapi_object_t *)m -> next, MDL);
316 		omapi_object_dereference ((omapi_object_t **)&m -> next, MDL);
317 		omapi_object_dereference ((omapi_object_t **)&n -> prev, MDL);
318 	}
319 	if (m -> prev) {
320 		omapi_message_object_t *tmp = (omapi_message_object_t *)0;
321 		omapi_object_reference ((omapi_object_t **)&tmp,
322 					(omapi_object_t *)m -> prev, MDL);
323 		omapi_object_dereference ((omapi_object_t **)&m -> prev, MDL);
324 		if (tmp -> next)
325 			omapi_object_dereference
326 				((omapi_object_t **)&tmp -> next, MDL);
327 		if (n)
328 			omapi_object_reference
329 				((omapi_object_t **)&tmp -> next,
330 				 (omapi_object_t *)n, MDL);
331 		omapi_object_dereference ((omapi_object_t **)&tmp, MDL);
332 	} else {
333 		omapi_object_dereference
334 			((omapi_object_t **)&omapi_registered_messages, MDL);
335 		if (n)
336 			omapi_object_reference
337 				((omapi_object_t **)&omapi_registered_messages,
338 				 (omapi_object_t *)n, MDL);
339 	}
340 	if (n)
341 		omapi_object_dereference ((omapi_object_t **)&n, MDL);
342 	return ISC_R_SUCCESS;
343 }
344 
345 #ifdef DEBUG_PROTOCOL
346 static const char *omapi_message_op_name(int op) {
347 	switch (op) {
348 	case OMAPI_OP_OPEN:    return "OMAPI_OP_OPEN";
349 	case OMAPI_OP_REFRESH: return "OMAPI_OP_REFRESH";
350 	case OMAPI_OP_UPDATE:  return "OMAPI_OP_UPDATE";
351 	case OMAPI_OP_STATUS:  return "OMAPI_OP_STATUS";
352 	case OMAPI_OP_DELETE:  return "OMAPI_OP_DELETE";
353 	case OMAPI_OP_NOTIFY:  return "OMAPI_OP_NOTIFY";
354 	default:               return "(unknown op)";
355 	}
356 }
357 #endif
358 
359 static isc_result_t
360 omapi_message_process_internal (omapi_object_t *, omapi_object_t *);
361 
362 isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
363 {
364 	isc_result_t status;
365 #if defined (DEBUG_MEMORY_LEAKAGE) && 0
366 	unsigned long previous_outstanding = dmalloc_outstanding;
367 #endif
368 
369 	status = omapi_message_process_internal (mo, po);
370 
371 #if defined (DEBUG_MEMORY_LEAKAGE) && 0
372 	log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
373 		  dmalloc_generation,
374 		  dmalloc_outstanding - previous_outstanding,
375 		  dmalloc_outstanding, dmalloc_longterm);
376 #endif
377 #if defined (DEBUG_MEMORY_LEAKAGE) && 0
378 	dmalloc_dump_outstanding ();
379 #endif
380 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY) && 0
381 	dump_rc_history ();
382 #endif
383 
384 	return status;
385 }
386 
387 static isc_result_t
388 omapi_message_process_internal (omapi_object_t *mo, omapi_object_t *po)
389 {
390 	omapi_message_object_t *message, *m;
391 	omapi_object_t *object = (omapi_object_t *)0;
392 	omapi_value_t *tv = (omapi_value_t *)0;
393 	unsigned long create, update, exclusive;
394 	unsigned long wsi;
395 	isc_result_t status, waitstatus;
396 	omapi_object_type_t *type;
397 
398 	if (mo -> type != omapi_type_message)
399 		return DHCP_R_INVALIDARG;
400 	message = (omapi_message_object_t *)mo;
401 
402 #ifdef DEBUG_PROTOCOL
403 	log_debug ("omapi_message_process(): "
404 		   "op=%s  handle=%#x  id=%#x  rid=%#x",
405 		   omapi_message_op_name (message -> op),
406 		   message -> h, message -> id, message -> rid);
407 #endif
408 
409 	if (message -> rid) {
410 		for (m = omapi_registered_messages; m; m = m -> next)
411 			if (m -> id == message -> rid)
412 				break;
413 		/* If we don't have a real message corresponding to
414 		   the message ID to which this message claims it is a
415 		   response, something's fishy. */
416 		if (!m)
417 			return ISC_R_NOTFOUND;
418 		/* The authenticator on responses must match the initial
419 		   message. */
420 		if (message -> authid != m -> authid)
421 			return ISC_R_NOTFOUND;
422 	} else {
423 		m = (omapi_message_object_t *)0;
424 
425 		/* All messages must have an authenticator, with the exception
426 		   of messages that are opening a new authenticator. */
427 		if (omapi_protocol_authenticated(po) &&
428 		    !message->id_object &&
429 		    message->op != OMAPI_OP_OPEN) {
430 			return omapi_protocol_send_status
431 				(po, message->id_object, DHCP_R_NOKEYS,
432 				 message->id, "No authenticator on message");
433 		}
434 	}
435 
436 	switch (message -> op) {
437 	      case OMAPI_OP_OPEN:
438 		if (m) {
439 			return omapi_protocol_send_status
440 				(po, message->id_object, DHCP_R_INVALIDARG,
441 				 message->id, "OPEN can't be a response");
442 		}
443 
444 		/* Get the type of the requested object, if one was
445 		   specified. */
446 		status = omapi_get_value_str (mo, message -> id_object,
447 					      "type", &tv);
448 		if (status == ISC_R_SUCCESS &&
449 		    (tv -> value -> type == omapi_datatype_data ||
450 		     tv -> value -> type == omapi_datatype_string)) {
451 			for (type = omapi_object_types;
452 			     type; type = type -> next)
453 				if (!omapi_td_strcmp (tv -> value,
454 						      type -> name))
455 					break;
456 		} else
457 			type = (omapi_object_type_t *)0;
458 		if (tv)
459 			omapi_value_dereference (&tv, MDL);
460 
461 		/* If this object had no authenticator, the requested object
462 		   must be an authenticator object. */
463 		if (omapi_protocol_authenticated(po) &&
464 		    !message->id_object &&
465 		    type != omapi_type_auth_key) {
466 			return omapi_protocol_send_status
467 				(po, message->id_object, DHCP_R_NOKEYS,
468 				 message->id, "No authenticator on message");
469 		}
470 
471 		/* Get the create flag. */
472 		status = omapi_get_value_str (mo, message -> id_object,
473 					      "create", &tv);
474 		if (status == ISC_R_SUCCESS) {
475 			status = omapi_get_int_value (&create, tv -> value);
476 			omapi_value_dereference (&tv, MDL);
477 			if (status != ISC_R_SUCCESS) {
478 				return omapi_protocol_send_status
479 					(po, message -> id_object,
480 					 status, message -> id,
481 					 "invalid create flag value");
482 			}
483 		} else
484 			create = 0;
485 
486 		/* Get the update flag. */
487 		status = omapi_get_value_str (mo, message -> id_object,
488 					      "update", &tv);
489 		if (status == ISC_R_SUCCESS) {
490 			status = omapi_get_int_value (&update, tv -> value);
491 			omapi_value_dereference (&tv, MDL);
492 			if (status != ISC_R_SUCCESS) {
493 				return omapi_protocol_send_status
494 					(po, message -> id_object,
495 					 status, message -> id,
496 					 "invalid update flag value");
497 			}
498 		} else
499 			update = 0;
500 
501 		/* Get the exclusive flag. */
502 		status = omapi_get_value_str (mo, message -> id_object,
503 					      "exclusive", &tv);
504 		if (status == ISC_R_SUCCESS) {
505 			status = omapi_get_int_value (&exclusive, tv -> value);
506 			omapi_value_dereference (&tv, MDL);
507 			if (status != ISC_R_SUCCESS) {
508 				return omapi_protocol_send_status
509 					(po, message -> id_object,
510 					 status, message -> id,
511 					 "invalid exclusive flag value");
512 			}
513 		} else
514 			exclusive = 0;
515 
516 		/* If we weren't given a type, look the object up with
517                    the handle. */
518 		if (!type) {
519 			if (create) {
520 				return omapi_protocol_send_status
521 					(po, message->id_object,
522 					 DHCP_R_INVALIDARG,
523 					 message->id,
524 					 "type required on create");
525 			}
526 			goto refresh;
527 		}
528 
529 		/* If the type doesn't provide a lookup method, we can't
530 		   look up the object. */
531 		if (!type -> lookup) {
532 			return omapi_protocol_send_status
533 				(po, message -> id_object,
534 				 ISC_R_NOTIMPLEMENTED, message -> id,
535 				 "unsearchable object type");
536 		}
537 
538 		status = (*(type -> lookup)) (&object, message -> id_object,
539 					      message -> object);
540 
541 		if (status != ISC_R_SUCCESS &&
542 		    status != ISC_R_NOTFOUND &&
543 		    status != DHCP_R_NOKEYS) {
544 			return omapi_protocol_send_status
545 				(po, message -> id_object,
546 				 status, message -> id,
547 				 "object lookup failed");
548 		}
549 
550 		/* If we didn't find the object and we aren't supposed to
551 		   create it, return an error. */
552 		if (status == ISC_R_NOTFOUND && !create) {
553 			return omapi_protocol_send_status
554 				(po, message -> id_object,
555 				 ISC_R_NOTFOUND, message -> id,
556 				 "no object matches specification");
557 		}
558 
559 		/* If we found an object, we're supposed to be creating an
560 		   object, and we're not supposed to have found an object,
561 		   return an error. */
562 		if (status == ISC_R_SUCCESS && create && exclusive) {
563 			omapi_object_dereference (&object, MDL);
564 			return omapi_protocol_send_status
565 				(po, message -> id_object,
566 				 ISC_R_EXISTS, message -> id,
567 				 "specified object already exists");
568 		}
569 
570 		/* If we're creating the object, do it now. */
571 		if (!object) {
572 			status = omapi_object_create (&object,
573 						      message -> id_object,
574 						      type);
575 			if (status != ISC_R_SUCCESS) {
576 				return omapi_protocol_send_status
577 					(po, message -> id_object,
578 					 status, message -> id,
579 					 "can't create new object");
580 			}
581 		}
582 
583 		/* If we're updating it, do so now. */
584 		if (create || update) {
585 			/* This check does not belong here. */
586 			if (object -> type == omapi_type_auth_key) {
587 				omapi_object_dereference (&object, MDL);
588 				return omapi_protocol_send_status
589 					(po, message -> id_object,
590 					 status, message -> id,
591 					 "can't update object");
592 			}
593 
594 			status = omapi_object_update (object,
595 						      message -> id_object,
596 						      message -> object,
597 						      message -> h);
598 			if (status != ISC_R_SUCCESS) {
599 				omapi_object_dereference (&object, MDL);
600 				return omapi_protocol_send_status
601 					(po, message -> id_object,
602 					 status, message -> id,
603 					 "can't update object");
604 			}
605 		}
606 
607 		/* If this is an authenticator object, add it to the active
608 		   set for the connection. */
609 		if (object -> type == omapi_type_auth_key) {
610 			omapi_handle_t handle;
611 			status = omapi_object_handle (&handle, object);
612 			if (status != ISC_R_SUCCESS) {
613 				omapi_object_dereference (&object, MDL);
614 				return omapi_protocol_send_status
615 					(po, message -> id_object,
616 					 status, message -> id,
617 					 "can't select authenticator");
618 			}
619 
620 			status = omapi_protocol_add_auth (po, object, handle);
621 			if (status != ISC_R_SUCCESS) {
622 				omapi_object_dereference (&object, MDL);
623 				return omapi_protocol_send_status
624 					(po, message -> id_object,
625 					 status, message -> id,
626 					 "can't select authenticator");
627 			}
628 		}
629 
630 		/* Now send the new contents of the object back in
631 		   response. */
632 		goto send;
633 
634 	      case OMAPI_OP_REFRESH:
635 	      refresh:
636 		status = omapi_handle_lookup (&object, message -> h);
637 		if (status != ISC_R_SUCCESS) {
638 			return omapi_protocol_send_status
639 				(po, message -> id_object,
640 				 status, message -> id,
641 				 "no matching handle");
642 		}
643 	      send:
644 		status = omapi_protocol_send_update (po, message -> id_object,
645 						     message -> id, object);
646 		omapi_object_dereference (&object, MDL);
647 		return status;
648 
649 	      case OMAPI_OP_UPDATE:
650 		if (m && m -> object) {
651 			status = omapi_object_reference (&object, m -> object,
652 									MDL);
653 		} else {
654 			status = omapi_handle_lookup (&object, message -> h);
655 			if (status != ISC_R_SUCCESS) {
656 				return omapi_protocol_send_status
657 					(po, message -> id_object,
658 					 status, message -> id,
659 					 "no matching handle");
660 			}
661 		}
662 
663 		if (object -> type == omapi_type_auth_key ||
664 		    (object -> inner &&
665 		     object -> inner -> type == omapi_type_auth_key)) {
666 			if (!m) {
667 				omapi_object_dereference (&object, MDL);
668 				return omapi_protocol_send_status
669 					(po, message -> id_object,
670 					 status, message -> id,
671 					 "cannot update authenticator");
672 			}
673 
674 			status = omapi_protocol_add_auth (po, object,
675 							  message -> h);
676 		} else {
677 			status = omapi_object_update (object,
678 						      message -> id_object,
679 						      message -> object,
680 						      message -> h);
681 		}
682 		if (status != ISC_R_SUCCESS) {
683 			omapi_object_dereference (&object, MDL);
684 			if (!message -> rid)
685 				return omapi_protocol_send_status
686 					(po, message -> id_object,
687 					 status, message -> id,
688 					 "can't update object");
689 			if (m)
690 				omapi_signal ((omapi_object_t *)m,
691 					      "status", status,
692 					      (omapi_typed_data_t *)0);
693 			return ISC_R_SUCCESS;
694 		}
695 		if (!message -> rid)
696 			status = omapi_protocol_send_status
697 				(po, message -> id_object, ISC_R_SUCCESS,
698 				 message -> id, (char *)0);
699 		if (m) {
700 			omapi_signal ((omapi_object_t *)m,
701 				      "status", ISC_R_SUCCESS,
702 				      (omapi_typed_data_t *)0);
703 			omapi_message_unregister ((omapi_object_t *)m);
704 		}
705 
706 		omapi_object_dereference (&object, MDL);
707 
708 		return status;
709 
710 	      case OMAPI_OP_NOTIFY:
711 		return omapi_protocol_send_status
712 			(po, message -> id_object, ISC_R_NOTIMPLEMENTED,
713 			 message -> id, "notify not implemented yet");
714 
715 	      case OMAPI_OP_STATUS:
716 		/* The return status of a request. */
717 		if (!m)
718 			return ISC_R_UNEXPECTED;
719 
720 		/* Get the wait status. */
721 		status = omapi_get_value_str (mo, message -> id_object,
722 					      "result", &tv);
723 		if (status == ISC_R_SUCCESS) {
724 			status = omapi_get_int_value (&wsi, tv -> value);
725 			waitstatus = wsi;
726 			omapi_value_dereference (&tv, MDL);
727 			if (status != ISC_R_SUCCESS)
728 				waitstatus = ISC_R_UNEXPECTED;
729 		} else
730 			waitstatus = ISC_R_UNEXPECTED;
731 
732 		status = omapi_get_value_str (mo, message -> id_object,
733 					      "message", &tv);
734 		omapi_signal ((omapi_object_t *)m, "status", waitstatus, tv);
735 		if (status == ISC_R_SUCCESS)
736 			omapi_value_dereference (&tv, MDL);
737 
738 		omapi_message_unregister((omapi_object_t *)m);
739 
740 		return ISC_R_SUCCESS;
741 
742 	      case OMAPI_OP_DELETE:
743 		status = omapi_handle_lookup (&object, message -> h);
744 		if (status != ISC_R_SUCCESS) {
745 			return omapi_protocol_send_status
746 				(po, message -> id_object,
747 				 status, message -> id,
748 				 "no matching handle");
749 		}
750 
751 		if (!object -> type -> remove)
752 			return omapi_protocol_send_status
753 				(po, message -> id_object,
754 				 ISC_R_NOTIMPLEMENTED, message -> id,
755 				 "no remove method for object");
756 
757 		status = (*(object -> type -> remove)) (object,
758 							message -> id_object);
759 		omapi_object_dereference (&object, MDL);
760 
761 		return omapi_protocol_send_status (po, message -> id_object,
762 						   status, message -> id,
763 						   (char *)0);
764 	}
765 	return ISC_R_NOTIMPLEMENTED;
766 }
767