1/* message.c
2
3   Subroutines for dealing with message objects. */
4
5/*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1999-2003 by Internet Software Consortium
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 *   Internet Systems Consortium, Inc.
22 *   950 Charter Street
23 *   Redwood City, CA 94063
24 *   <info@isc.org>
25 *   http://www.isc.org/
26 *
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
33 */
34
35#include <omapip/omapip_p.h>
36
37OMAPI_OBJECT_ALLOC (omapi_message,
38		    omapi_message_object_t, omapi_type_message)
39
40omapi_message_object_t *omapi_registered_messages;
41
42isc_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 ((void *)&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 ((void *)&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
83isc_result_t omapi_message_set_value (omapi_object_t *h,
84				      omapi_object_t *id,
85				      omapi_data_string_t *name,
86				      omapi_typed_data_t *value)
87{
88	omapi_message_object_t *m;
89	isc_result_t status;
90
91	if (h -> type != omapi_type_message)
92		return ISC_R_INVALIDARG;
93	m = (omapi_message_object_t *)h;
94
95	/* Can't set authlen. */
96
97	/* Can set authenticator, but the value must be typed data. */
98	if (!omapi_ds_strcmp (name, "authenticator")) {
99		if (m -> authenticator)
100			omapi_typed_data_dereference (&m -> authenticator,
101						      MDL);
102		omapi_typed_data_reference (&m -> authenticator, value, MDL);
103		return ISC_R_SUCCESS;
104
105	} else if (!omapi_ds_strcmp (name, "object")) {
106		if (value -> type != omapi_datatype_object)
107			return ISC_R_INVALIDARG;
108		if (m -> object)
109			omapi_object_dereference (&m -> object, MDL);
110		omapi_object_reference (&m -> object, value -> u.object, MDL);
111		return ISC_R_SUCCESS;
112
113	} else if (!omapi_ds_strcmp (name, "notify-object")) {
114		if (value -> type != omapi_datatype_object)
115			return ISC_R_INVALIDARG;
116		if (m -> notify_object)
117			omapi_object_dereference (&m -> notify_object, MDL);
118		omapi_object_reference (&m -> notify_object,
119					value -> u.object, MDL);
120		return ISC_R_SUCCESS;
121
122	/* Can set authid, but it has to be an integer. */
123	} else if (!omapi_ds_strcmp (name, "authid")) {
124		if (value -> type != omapi_datatype_int)
125			return ISC_R_INVALIDARG;
126		m -> authid = value -> u.integer;
127		return ISC_R_SUCCESS;
128
129	/* Can set op, but it has to be an integer. */
130	} else if (!omapi_ds_strcmp (name, "op")) {
131		if (value -> type != omapi_datatype_int)
132			return ISC_R_INVALIDARG;
133		m -> op = value -> u.integer;
134		return ISC_R_SUCCESS;
135
136	/* Handle also has to be an integer. */
137	} else if (!omapi_ds_strcmp (name, "handle")) {
138		if (value -> type != omapi_datatype_int)
139			return ISC_R_INVALIDARG;
140		m -> h = value -> u.integer;
141		return ISC_R_SUCCESS;
142
143	/* Transaction ID has to be an integer. */
144	} else if (!omapi_ds_strcmp (name, "id")) {
145		if (value -> type != omapi_datatype_int)
146			return ISC_R_INVALIDARG;
147		m -> id = value -> u.integer;
148		return ISC_R_SUCCESS;
149
150	/* Remote transaction ID has to be an integer. */
151	} else if (!omapi_ds_strcmp (name, "rid")) {
152		if (value -> type != omapi_datatype_int)
153			return ISC_R_INVALIDARG;
154		m -> rid = value -> u.integer;
155		return ISC_R_SUCCESS;
156	}
157
158	/* Try to find some inner object that can take the value. */
159	if (h -> inner && h -> inner -> type -> set_value) {
160		status = ((*(h -> inner -> type -> set_value))
161			  (h -> inner, id, name, value));
162		if (status == ISC_R_SUCCESS)
163			return status;
164	}
165
166	return ISC_R_NOTFOUND;
167}
168
169isc_result_t omapi_message_get_value (omapi_object_t *h,
170				      omapi_object_t *id,
171				      omapi_data_string_t *name,
172				      omapi_value_t **value)
173{
174	omapi_message_object_t *m;
175	if (h -> type != omapi_type_message)
176		return ISC_R_INVALIDARG;
177	m = (omapi_message_object_t *)h;
178
179	/* Look for values that are in the message data structure. */
180	if (!omapi_ds_strcmp (name, "authlen"))
181		return omapi_make_int_value (value, name, (int)m -> authlen,
182					     MDL);
183	else if (!omapi_ds_strcmp (name, "authenticator")) {
184		if (m -> authenticator)
185			return omapi_make_value (value, name,
186						 m -> authenticator, MDL);
187		else
188			return ISC_R_NOTFOUND;
189	} else if (!omapi_ds_strcmp (name, "authid")) {
190		return omapi_make_int_value (value,
191					     name, (int)m -> authid, MDL);
192	} else if (!omapi_ds_strcmp (name, "op")) {
193		return omapi_make_int_value (value, name, (int)m -> op, MDL);
194	} else if (!omapi_ds_strcmp (name, "handle")) {
195		return omapi_make_int_value (value, name, (int)m -> h, MDL);
196	} else if (!omapi_ds_strcmp (name, "id")) {
197		return omapi_make_int_value (value, name, (int)m -> id, MDL);
198	} else if (!omapi_ds_strcmp (name, "rid")) {
199		return omapi_make_int_value (value, name, (int)m -> rid, MDL);
200	}
201
202	/* See if there's an inner object that has the value. */
203	if (h -> inner && h -> inner -> type -> get_value)
204		return (*(h -> inner -> type -> get_value))
205			(h -> inner, id, name, value);
206	return ISC_R_NOTFOUND;
207}
208
209isc_result_t omapi_message_destroy (omapi_object_t *h,
210				    const char *file, int line)
211{
212
213	omapi_message_object_t *m;
214	if (h -> type != omapi_type_message)
215		return ISC_R_INVALIDARG;
216	m = (omapi_message_object_t *)h;
217	if (m -> authenticator) {
218		omapi_typed_data_dereference (&m -> authenticator, file, line);
219	}
220	if (!m -> prev && omapi_registered_messages != m)
221		omapi_message_unregister (h);
222	if (m -> id_object)
223		omapi_object_dereference (&m -> id_object, file, line);
224	if (m -> object)
225		omapi_object_dereference (&m -> object, file, line);
226	if (m -> notify_object)
227		omapi_object_dereference (&m -> notify_object, file, line);
228	if (m -> protocol_object)
229		omapi_protocol_dereference (&m -> protocol_object, file, line);
230	return ISC_R_SUCCESS;
231}
232
233isc_result_t omapi_message_signal_handler (omapi_object_t *h,
234					   const char *name, va_list ap)
235{
236	omapi_message_object_t *m;
237	if (h -> type != omapi_type_message)
238		return ISC_R_INVALIDARG;
239	m = (omapi_message_object_t *)h;
240
241	if (!strcmp (name, "status")) {
242		if (m -> notify_object &&
243		    m -> notify_object -> type -> signal_handler)
244			return ((m -> notify_object -> type -> signal_handler))
245				(m -> notify_object, name, ap);
246		else if (m -> object && m -> object -> type -> signal_handler)
247			return ((m -> object -> type -> signal_handler))
248				(m -> object, name, ap);
249	}
250	if (h -> inner && h -> inner -> type -> signal_handler)
251		return (*(h -> inner -> type -> signal_handler)) (h -> inner,
252								  name, ap);
253	return ISC_R_NOTFOUND;
254}
255
256/* Write all the published values associated with the object through the
257   specified connection. */
258
259isc_result_t omapi_message_stuff_values (omapi_object_t *c,
260					 omapi_object_t *id,
261					 omapi_object_t *m)
262{
263
264	if (m -> type != omapi_type_message)
265		return ISC_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
273isc_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 ISC_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 ISC_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			((void *)&omapi_registered_messages, MDL);
294	}
295	omapi_object_reference
296		((void *)&omapi_registered_messages,
297		 (omapi_object_t *)m, MDL);
298	return ISC_R_SUCCESS;;
299}
300
301isc_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 ISC_R_INVALIDARG;
308	m = (omapi_message_object_t *)mo;
309
310	/* Not registered? */
311	if (!m -> prev && omapi_registered_messages != m)
312		return ISC_R_INVALIDARG;
313
314	n = (omapi_message_object_t *)0;
315	if (m -> next) {
316		omapi_object_reference ((void *)&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 ((void *)&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 ((void *)&tmp, MDL);
334	} else {
335		omapi_object_dereference
336			((void *)&omapi_registered_messages, MDL);
337		if (n)
338			omapi_object_reference
339				((void *)&omapi_registered_messages,
340				 (omapi_object_t *)n, MDL);
341	}
342	if (n)
343		omapi_object_dereference ((void *)&n, MDL);
344	return ISC_R_SUCCESS;
345}
346
347#ifdef DEBUG_PROTOCOL
348static 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
361static isc_result_t
362omapi_message_process_internal (omapi_object_t *, omapi_object_t *);
363
364isc_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)
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
389static isc_result_t
390omapi_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 ISC_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, ISC_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, ISC_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, ISC_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					 ISC_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 != ISC_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}
769