message.c 23.2 KB
Newer Older
Ted Lemon's avatar
Ted Lemon committed
1 2 3 4 5
/* message.c

   Subroutines for dealing with message objects. */

/*
Ted Lemon's avatar
Ted Lemon committed
6 7
 * Copyright (c) 1999-2000 Internet Software Consortium.
 * All rights reserved.
Ted Lemon's avatar
Ted Lemon committed
8
 *
Ted Lemon's avatar
Ted Lemon committed
9 10 11
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
Ted Lemon's avatar
Ted Lemon committed
12
 *
Ted Lemon's avatar
Ted Lemon committed
13 14 15 16 17 18 19 20
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of The Internet Software Consortium nor the names
 *    of its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
Ted Lemon's avatar
Ted Lemon committed
21
 *
Ted Lemon's avatar
Ted Lemon committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This software has been written for the Internet Software Consortium
 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
 * To learn more about the Internet Software Consortium, see
 * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
 * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
 * ``http://www.nominum.com''.
Ted Lemon's avatar
Ted Lemon committed
42 43
 */

44
#include <omapip/omapip_p.h>
Ted Lemon's avatar
Ted Lemon committed
45

46 47 48
OMAPI_OBJECT_ALLOC (omapi_message,
		    omapi_message_object_t, omapi_type_message)

Ted Lemon's avatar
Ted Lemon committed
49 50
omapi_message_object_t *omapi_registered_messages;

Ted Lemon's avatar
Ted Lemon committed
51
isc_result_t omapi_message_new (omapi_object_t **o, const char *file, int line)
Ted Lemon's avatar
Ted Lemon committed
52 53
{
	omapi_message_object_t *m;
54
	omapi_object_t *g;
Ted Lemon's avatar
Ted Lemon committed
55 56
	isc_result_t status;

Ted Lemon's avatar
Ted Lemon committed
57 58 59 60
	m = (omapi_message_object_t *)0;
	status = omapi_message_allocate (&m, file, line);
	if (status != ISC_R_SUCCESS)
		return status;
Ted Lemon's avatar
Ted Lemon committed
61

62
	g = (omapi_object_t *)0;
Ted Lemon's avatar
Ted Lemon committed
63
	status = omapi_generic_new (&g, file, line);
64
	if (status != ISC_R_SUCCESS) {
65
		dfree (m, file, line);
66 67
		return status;
	}
Ted Lemon's avatar
Ted Lemon committed
68
	status = omapi_object_reference (&m -> inner, g, file, line);
69
	if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
70
		omapi_object_dereference ((omapi_object_t **)&m, file, line);
71
		omapi_object_dereference (&g, file, line);
72 73 74
		return status;
	}
	status = omapi_object_reference (&g -> outer,
Ted Lemon's avatar
Ted Lemon committed
75
					 (omapi_object_t *)m, file, line);
76 77

	if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
78
		omapi_object_dereference ((omapi_object_t **)&m, file, line);
79
		omapi_object_dereference (&g, file, line);
80 81 82
		return status;
	}

Ted Lemon's avatar
Ted Lemon committed
83
	status = omapi_object_reference (o, (omapi_object_t *)m, file, line);
Ted Lemon's avatar
Ted Lemon committed
84
	omapi_message_dereference (&m, file, line);
Ted Lemon's avatar
Ted Lemon committed
85
	omapi_object_dereference (&g, file, line);
86 87 88
	if (status != ISC_R_SUCCESS)
		return status;

Ted Lemon's avatar
Ted Lemon committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
	return status;
}

isc_result_t omapi_message_set_value (omapi_object_t *h,
				      omapi_object_t *id,
				      omapi_data_string_t *name,
				      omapi_typed_data_t *value)
{
	omapi_message_object_t *m;
	isc_result_t status;

	if (h -> type != omapi_type_message)
		return ISC_R_INVALIDARG;
	m = (omapi_message_object_t *)h;

	/* Can't set authlen. */

	/* Can set authenticator, but the value must be typed data. */
	if (!omapi_ds_strcmp (name, "authenticator")) {
		if (m -> authenticator)
109 110 111
			omapi_typed_data_dereference (&m -> authenticator,
						      MDL);
		omapi_typed_data_reference (&m -> authenticator, value, MDL);
Ted Lemon's avatar
Ted Lemon committed
112 113
		return ISC_R_SUCCESS;

114 115 116 117
	} else if (!omapi_ds_strcmp (name, "object")) {
		if (value -> type != omapi_datatype_object)
			return ISC_R_INVALIDARG;
		if (m -> object)
118 119
			omapi_object_dereference (&m -> object, MDL);
		omapi_object_reference (&m -> object, value -> u.object, MDL);
120 121
		return ISC_R_SUCCESS;

122 123 124 125
	} else if (!omapi_ds_strcmp (name, "notify-object")) {
		if (value -> type != omapi_datatype_object)
			return ISC_R_INVALIDARG;
		if (m -> notify_object)
126
			omapi_object_dereference (&m -> notify_object, MDL);
127
		omapi_object_reference (&m -> notify_object,
Ted Lemon's avatar
Ted Lemon committed
128
					value -> u.object, MDL);
129 130
		return ISC_R_SUCCESS;

Ted Lemon's avatar
Ted Lemon committed
131 132 133 134 135
	/* Can set authid, but it has to be an integer. */
	} else if (!omapi_ds_strcmp (name, "authid")) {
		if (value -> type != omapi_datatype_int)
			return ISC_R_INVALIDARG;
		m -> authid = value -> u.integer;
136
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
137 138 139 140 141 142

	/* Can set op, but it has to be an integer. */
	} else if (!omapi_ds_strcmp (name, "op")) {
		if (value -> type != omapi_datatype_int)
			return ISC_R_INVALIDARG;
		m -> op = value -> u.integer;
143
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
144 145 146 147 148 149

	/* Handle also has to be an integer. */
	} else if (!omapi_ds_strcmp (name, "handle")) {
		if (value -> type != omapi_datatype_int)
			return ISC_R_INVALIDARG;
		m -> h = value -> u.integer;
150
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
151 152 153 154 155 156

	/* Transaction ID has to be an integer. */
	} else if (!omapi_ds_strcmp (name, "id")) {
		if (value -> type != omapi_datatype_int)
			return ISC_R_INVALIDARG;
		m -> id = value -> u.integer;
157
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
158 159 160 161 162 163

	/* Remote transaction ID has to be an integer. */
	} else if (!omapi_ds_strcmp (name, "rid")) {
		if (value -> type != omapi_datatype_int)
			return ISC_R_INVALIDARG;
		m -> rid = value -> u.integer;
164
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
	}

	/* Try to find some inner object that can take the value. */
	if (h -> inner && h -> inner -> type -> set_value) {
		status = ((*(h -> inner -> type -> set_value))
			  (h -> inner, id, name, value));
		if (status == ISC_R_SUCCESS)
			return status;
	}
			  
	return ISC_R_NOTFOUND;
}

isc_result_t omapi_message_get_value (omapi_object_t *h,
				      omapi_object_t *id,
				      omapi_data_string_t *name,
				      omapi_value_t **value)
{
	omapi_message_object_t *m;
	if (h -> type != omapi_type_message)
		return ISC_R_INVALIDARG;
	m = (omapi_message_object_t *)h;

	/* Look for values that are in the message data structure. */
	if (!omapi_ds_strcmp (name, "authlen"))
190
		return omapi_make_int_value (value, name, (int)m -> authlen,
Ted Lemon's avatar
Ted Lemon committed
191
					     MDL);
Ted Lemon's avatar
Ted Lemon committed
192 193
	else if (!omapi_ds_strcmp (name, "authenticator")) {
		if (m -> authenticator)
Ted Lemon's avatar
Ted Lemon committed
194 195
			return omapi_make_value (value, name,
						 m -> authenticator, MDL);
Ted Lemon's avatar
Ted Lemon committed
196 197 198
		else
			return ISC_R_NOTFOUND;
	} else if (!omapi_ds_strcmp (name, "authid")) {
Ted Lemon's avatar
Ted Lemon committed
199 200
		return omapi_make_int_value (value,
					     name, (int)m -> authid, MDL);
Ted Lemon's avatar
Ted Lemon committed
201
	} else if (!omapi_ds_strcmp (name, "op")) {
Ted Lemon's avatar
Ted Lemon committed
202
		return omapi_make_int_value (value, name, (int)m -> op, MDL);
Ted Lemon's avatar
Ted Lemon committed
203
	} else if (!omapi_ds_strcmp (name, "handle")) {
Ted Lemon's avatar
Ted Lemon committed
204
		return omapi_make_int_value (value, name, (int)m -> h, MDL);
Ted Lemon's avatar
Ted Lemon committed
205
	} else if (!omapi_ds_strcmp (name, "id")) {
Ted Lemon's avatar
Ted Lemon committed
206
		return omapi_make_int_value (value, name, (int)m -> id, MDL);
Ted Lemon's avatar
Ted Lemon committed
207
	} else if (!omapi_ds_strcmp (name, "rid")) {
Ted Lemon's avatar
Ted Lemon committed
208
		return omapi_make_int_value (value, name, (int)m -> rid, MDL);
Ted Lemon's avatar
Ted Lemon committed
209 210 211 212 213 214 215 216 217
	}

	/* See if there's an inner object that has the value. */
	if (h -> inner && h -> inner -> type -> get_value)
		return (*(h -> inner -> type -> get_value))
			(h -> inner, id, name, value);
	return ISC_R_NOTFOUND;
}

Ted Lemon's avatar
Ted Lemon committed
218 219
isc_result_t omapi_message_destroy (omapi_object_t *h,
				    const char *file, int line)
Ted Lemon's avatar
Ted Lemon committed
220 221 222 223 224 225
{
	int i;

	omapi_message_object_t *m;
	if (h -> type != omapi_type_message)
		return ISC_R_INVALIDARG;
226
	m = (omapi_message_object_t *)h;
Ted Lemon's avatar
Ted Lemon committed
227
	if (m -> authenticator) {
Ted Lemon's avatar
Ted Lemon committed
228
		omapi_typed_data_dereference (&m -> authenticator, file, line);
Ted Lemon's avatar
Ted Lemon committed
229 230 231 232
	}
	if (!m -> prev && omapi_registered_messages != m)
		omapi_message_unregister (h);
	if (m -> id_object)
233
		omapi_object_dereference (&m -> id_object, file, line);
Ted Lemon's avatar
Ted Lemon committed
234
	if (m -> object)
235 236 237 238 239
		omapi_object_dereference (&m -> object, file, line);
	if (m -> notify_object)
		omapi_object_dereference (&m -> notify_object, file, line);
	if (m -> protocol_object)
		omapi_protocol_dereference (&m -> protocol_object, file, line);
Ted Lemon's avatar
Ted Lemon committed
240 241 242 243
	return ISC_R_SUCCESS;
}

isc_result_t omapi_message_signal_handler (omapi_object_t *h,
244
					   const char *name, va_list ap)
Ted Lemon's avatar
Ted Lemon committed
245
{
Ted Lemon's avatar
Ted Lemon committed
246
	omapi_message_object_t *m;
Ted Lemon's avatar
Ted Lemon committed
247 248
	if (h -> type != omapi_type_message)
		return ISC_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
249
	m = (omapi_message_object_t *)h;
Ted Lemon's avatar
Ted Lemon committed
250
	
251 252 253
	if (!strcmp (name, "status")) {
		if (m -> notify_object &&
		    m -> notify_object -> type -> signal_handler)
254 255
			return ((m -> notify_object -> type -> signal_handler))
				(m -> notify_object, name, ap);
256 257 258
		else if (m -> object && m -> object -> type -> signal_handler)
			return ((m -> object -> type -> signal_handler))
				(m -> object, name, ap);
Ted Lemon's avatar
Ted Lemon committed
259
	}
Ted Lemon's avatar
Ted Lemon committed
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
	if (h -> inner && h -> inner -> type -> signal_handler)
		return (*(h -> inner -> type -> signal_handler)) (h -> inner,
								  name, ap);
	return ISC_R_NOTFOUND;
}

/* Write all the published values associated with the object through the
   specified connection. */

isc_result_t omapi_message_stuff_values (omapi_object_t *c,
					 omapi_object_t *id,
					 omapi_object_t *m)
{
	int i;

	if (m -> type != omapi_type_message)
		return ISC_R_INVALIDARG;

	if (m -> inner && m -> inner -> type -> stuff_values)
		return (*(m -> inner -> type -> stuff_values)) (c, id,
								m -> inner);
	return ISC_R_SUCCESS;
}

isc_result_t omapi_message_register (omapi_object_t *mo)
{
	omapi_message_object_t *m;

	if (mo -> type != omapi_type_message)
		return ISC_R_INVALIDARG;
	m = (omapi_message_object_t *)mo;
	
	/* Already registered? */
	if (m -> prev || m -> next || omapi_registered_messages == m)
		return ISC_R_INVALIDARG;

	if (omapi_registered_messages) {
		omapi_object_reference
			((omapi_object_t **)&m -> next,
299
			 (omapi_object_t *)omapi_registered_messages, MDL);
Ted Lemon's avatar
Ted Lemon committed
300 301
		omapi_object_reference
			((omapi_object_t **)&omapi_registered_messages -> prev,
302
			 (omapi_object_t *)m, MDL);
Ted Lemon's avatar
Ted Lemon committed
303
		omapi_object_dereference
304
			((omapi_object_t **)&omapi_registered_messages, MDL);
Ted Lemon's avatar
Ted Lemon committed
305 306 307
	}
	omapi_object_reference
		((omapi_object_t **)&omapi_registered_messages,
308
		 (omapi_object_t *)m, MDL);
Ted Lemon's avatar
Ted Lemon committed
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
	return ISC_R_SUCCESS;;
}

isc_result_t omapi_message_unregister (omapi_object_t *mo)
{
	omapi_message_object_t *m;
	omapi_message_object_t *n;

	if (mo -> type != omapi_type_message)
		return ISC_R_INVALIDARG;
	m = (omapi_message_object_t *)mo;
	
	/* Not registered? */
	if (!m -> prev && omapi_registered_messages != m)
		return ISC_R_INVALIDARG;

	n = (omapi_message_object_t *)0;
	if (m -> next) {
		omapi_object_reference ((omapi_object_t **)&n,
Ted Lemon's avatar
Ted Lemon committed
328 329
					(omapi_object_t *)m -> next, MDL);
		omapi_object_dereference ((omapi_object_t **)&m -> next, MDL);
Ted Lemon's avatar
Ted Lemon committed
330 331 332 333
	}
	if (m -> prev) {
		omapi_message_object_t *tmp = (omapi_message_object_t *)0;
		omapi_object_reference ((omapi_object_t **)&tmp,
Ted Lemon's avatar
Ted Lemon committed
334 335
					(omapi_object_t *)m -> prev, MDL);
		omapi_object_dereference ((omapi_object_t **)&m -> prev, MDL);
Ted Lemon's avatar
Ted Lemon committed
336 337
		if (tmp -> next)
			omapi_object_dereference
Ted Lemon's avatar
Ted Lemon committed
338
				((omapi_object_t **)&tmp -> next, MDL);
Ted Lemon's avatar
Ted Lemon committed
339 340 341
		if (n)
			omapi_object_reference
				((omapi_object_t **)&tmp -> next,
Ted Lemon's avatar
Ted Lemon committed
342 343
				 (omapi_object_t *)n, MDL);
		omapi_object_dereference ((omapi_object_t **)&tmp, MDL);
Ted Lemon's avatar
Ted Lemon committed
344 345
	} else {
		omapi_object_dereference
Ted Lemon's avatar
Ted Lemon committed
346
			((omapi_object_t **)&omapi_registered_messages, MDL);
Ted Lemon's avatar
Ted Lemon committed
347 348 349
		if (n)
			omapi_object_reference
				((omapi_object_t **)&omapi_registered_messages,
Ted Lemon's avatar
Ted Lemon committed
350
				 (omapi_object_t *)n, MDL);
Ted Lemon's avatar
Ted Lemon committed
351 352
	}
	if (n)
Ted Lemon's avatar
Ted Lemon committed
353
		omapi_object_dereference ((omapi_object_t **)&n, MDL);
Ted Lemon's avatar
Ted Lemon committed
354 355
	return ISC_R_SUCCESS;
}
356

357 358 359 360 361 362 363 364 365 366 367 368 369 370
#ifdef DEBUG_PROTOCOL
static const char *omapi_message_op_name(int op) {
	switch (op) {
	case OMAPI_OP_OPEN:    return "OMAPI_OP_OPEN";
	case OMAPI_OP_REFRESH: return "OMAPI_OP_REFRESH";
	case OMAPI_OP_UPDATE:  return "OMAPI_OP_UPDATE";
	case OMAPI_OP_STATUS:  return "OMAPI_OP_STATUS";
	case OMAPI_OP_DELETE:  return "OMAPI_OP_DELETE";
	case OMAPI_OP_NOTIFY:  return "OMAPI_OP_NOTIFY";
	default:               return "(unknown op)";
	}
}
#endif

Ted Lemon's avatar
Ted Lemon committed
371 372 373
static isc_result_t
omapi_message_process_internal (omapi_object_t *, omapi_object_t *);

374
isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
Ted Lemon's avatar
Ted Lemon committed
375 376 377 378 379 380 381 382 383 384 385 386 387 388
{
	isc_result_t status;
#if defined (DEBUG_MEMORY_LEAKAGE)
	unsigned long previous_outstanding = dmalloc_outstanding;
#endif

	status = omapi_message_process_internal (mo, po);

#if defined (DEBUG_MEMORY_LEAKAGE) && 0
	log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
		  dmalloc_generation,
		  dmalloc_outstanding - previous_outstanding,
		  dmalloc_outstanding, dmalloc_longterm);
#endif
389
#if defined (DEBUG_MEMORY_LEAKAGE) && 0
Ted Lemon's avatar
Ted Lemon committed
390 391 392 393 394 395 396 397 398 399 400
	dmalloc_dump_outstanding ();
#endif
#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY) && 0
	dump_rc_history ();
#endif

	return status;
}

static isc_result_t
omapi_message_process_internal (omapi_object_t *mo, omapi_object_t *po)
401 402 403
{
	omapi_message_object_t *message, *m;
	omapi_object_t *object = (omapi_object_t *)0;
Ted Lemon's avatar
Ted Lemon committed
404
	omapi_value_t *tv = (omapi_value_t *)0;
405 406
	unsigned long create, update, exclusive;
	unsigned long wsi;
407 408 409 410 411 412 413
	isc_result_t status, waitstatus;
	omapi_object_type_t *type;

	if (mo -> type != omapi_type_message)
		return ISC_R_INVALIDARG;
	message = (omapi_message_object_t *)mo;

414 415 416 417 418 419 420
#ifdef DEBUG_PROTOCOL
	log_debug ("omapi_message_process(): "
		   "op=%s  handle=%#x  id=%#x  rid=%#x",
		   omapi_message_op_name (message -> op),
		   message -> h, message -> id, message -> rid);
#endif

421 422 423 424 425 426 427 428 429
	if (message -> rid) {
		for (m = omapi_registered_messages; m; m = m -> next)
			if (m -> id == message -> rid)
				break;
		/* If we don't have a real message corresponding to
		   the message ID to which this message claims it is a
		   response, something's fishy. */
		if (!m)
			return ISC_R_NOTFOUND;
430 431 432 433 434
		/* The authenticator on responses must match the initial
		   message. */
		if (message -> authid != m -> authid)
			return ISC_R_NOTFOUND;
	} else {
Ted Lemon's avatar
Ted Lemon committed
435
		m = (omapi_message_object_t *)0;
436

437 438 439 440 441 442 443 444 445 446 447
		/* All messages must have an authenticator, with the exception
		   of messages that are opening a new authenticator. */
		if (omapi_protocol_authenticated (po) &&
		    !message -> id_object &&
		    message -> op != OMAPI_OP_OPEN) {
			return omapi_protocol_send_status
				(po, message -> id_object, ISC_R_NOKEYS,
				 message -> id, "No authenticator on message");
		}
	}

448 449 450
	switch (message -> op) {
	      case OMAPI_OP_OPEN:
		if (m) {
Ted Lemon's avatar
Ted Lemon committed
451
			return omapi_protocol_send_status
452
				(po, message -> id_object, ISC_R_INVALIDARG,
Ted Lemon's avatar
Ted Lemon committed
453
				 message -> id, "OPEN can't be a response");
454 455 456 457
		}

		/* Get the type of the requested object, if one was
		   specified. */
458
		status = omapi_get_value_str (mo, message -> id_object,
459 460 461 462 463 464 465 466 467 468 469 470
					      "type", &tv);
		if (status == ISC_R_SUCCESS &&
		    (tv -> value -> type == omapi_datatype_data ||
		     tv -> value -> type == omapi_datatype_string)) {
			for (type = omapi_object_types;
			     type; type = type -> next)
				if (!omapi_td_strcmp (tv -> value,
						      type -> name))
					break;
		} else
			type = (omapi_object_type_t *)0;
		if (tv)
Ted Lemon's avatar
Ted Lemon committed
471
			omapi_value_dereference (&tv, MDL);
472

473 474 475 476 477 478 479 480 481 482
		/* If this object had no authenticator, the requested object
		   must be an authenticator object. */
		if (omapi_protocol_authenticated (po) &&
		    !message -> id_object &&
		    type != omapi_type_auth_key) {
			return omapi_protocol_send_status
				(po, message -> id_object, ISC_R_NOKEYS,
				 message -> id, "No authenticator on message");
		}

483
		/* Get the create flag. */
484
		status = omapi_get_value_str (mo, message -> id_object,
485 486
					      "create", &tv);
		if (status == ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
487
			status = omapi_get_int_value (&create, tv -> value);
Ted Lemon's avatar
Ted Lemon committed
488
			omapi_value_dereference (&tv, MDL);
489
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
490
				return omapi_protocol_send_status
491
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
492
					 status, message -> id,
493 494 495 496 497 498
					 "invalid create flag value");
			}
		} else
			create = 0;

		/* Get the update flag. */
499
		status = omapi_get_value_str (mo, message -> id_object,
500 501
					      "update", &tv);
		if (status == ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
502
			status = omapi_get_int_value (&update, tv -> value);
Ted Lemon's avatar
Ted Lemon committed
503
			omapi_value_dereference (&tv, MDL);
504
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
505
				return omapi_protocol_send_status
506
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
507
					 status, message -> id,
508 509 510 511 512 513
					 "invalid update flag value");
			}
		} else
			update = 0;

		/* Get the exclusive flag. */
514
		status = omapi_get_value_str (mo, message -> id_object,
515 516
					      "exclusive", &tv);
		if (status == ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
517
			status = omapi_get_int_value (&exclusive, tv -> value);
Ted Lemon's avatar
Ted Lemon committed
518
			omapi_value_dereference (&tv, MDL);
519
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
520
				return omapi_protocol_send_status
521
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
522
					 status, message -> id,
523 524 525 526 527 528 529 530 531
					 "invalid exclusive flag value");
			}
		} else
			exclusive = 0;

		/* If we weren't given a type, look the object up with
                   the handle. */
		if (!type) {
			if (create) {
Ted Lemon's avatar
Ted Lemon committed
532
				return omapi_protocol_send_status
533 534 535
					(po, message -> id_object,
					 ISC_R_INVALIDARG,
					 message -> id,
536 537 538 539 540 541 542 543
					 "type required on create");
			}
			goto refresh;
		}

		/* If the type doesn't provide a lookup method, we can't
		   look up the object. */
		if (!type -> lookup) {
Ted Lemon's avatar
Ted Lemon committed
544
			return omapi_protocol_send_status
545
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
546
				 ISC_R_NOTIMPLEMENTED, message -> id,
547 548
				 "unsearchable object type");
		}
549

550
		status = (*(type -> lookup)) (&object, message -> id_object,
551 552
					      message -> object);

553 554 555
		if (status != ISC_R_SUCCESS &&
		    status != ISC_R_NOTFOUND &&
		    status != ISC_R_NOKEYS) {
Ted Lemon's avatar
Ted Lemon committed
556
			return omapi_protocol_send_status
557
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
558
				 status, message -> id,
559 560 561 562 563 564
				 "object lookup failed");
		}

		/* If we didn't find the object and we aren't supposed to
		   create it, return an error. */
		if (status == ISC_R_NOTFOUND && !create) {
Ted Lemon's avatar
Ted Lemon committed
565
			return omapi_protocol_send_status
566
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
567
				 ISC_R_NOTFOUND, message -> id,
568 569 570 571 572 573 574
				 "no object matches specification");
		}			

		/* If we found an object, we're supposed to be creating an
		   object, and we're not supposed to have found an object,
		   return an error. */
		if (status == ISC_R_SUCCESS && create && exclusive) {
Ted Lemon's avatar
Ted Lemon committed
575
			omapi_object_dereference (&object, MDL);
Ted Lemon's avatar
Ted Lemon committed
576
			return omapi_protocol_send_status
577
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
578
				 ISC_R_EXISTS, message -> id,
579 580 581 582 583
				 "specified object already exists");
		}

		/* If we're creating the object, do it now. */
		if (!object) {
Ted Lemon's avatar
Ted Lemon committed
584
			status = omapi_object_create (&object,
585
						      message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
586
						      type);
587
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
588
				return omapi_protocol_send_status
589
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
590
					 status, message -> id,
591 592 593 594 595 596
					 "can't create new object");
			}
		}

		/* If we're updating it, do so now. */
		if (create || update) {
597 598 599 600 601 602 603 604 605
			/* This check does not belong here. */
			if (object -> type == omapi_type_auth_key) {
				omapi_object_dereference (&object, MDL);
				return omapi_protocol_send_status
					(po, message -> id_object,
					 status, message -> id,
					 "can't update object");
			}

606
			status = omapi_object_update (object,
607
						      message -> id_object,
608
						      message -> object,
Ted Lemon's avatar
Ted Lemon committed
609
						      message -> h);
610
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
611
				omapi_object_dereference (&object, MDL);
Ted Lemon's avatar
Ted Lemon committed
612
				return omapi_protocol_send_status
613
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
614
					 status, message -> id,
615 616 617
					 "can't update object");
			}
		}
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640

		/* If this is an authenticator object, add it to the active
		   set for the connection. */
		if (object -> type == omapi_type_auth_key) {
			omapi_handle_t handle;
			status = omapi_object_handle (&handle, object);
			if (status != ISC_R_SUCCESS) {
				omapi_object_dereference (&object, MDL);
				return omapi_protocol_send_status
					(po, message -> id_object,
					 status, message -> id,
					 "can't select authenticator");
			}

			status = omapi_protocol_add_auth (po, object, handle);
			if (status != ISC_R_SUCCESS) {
				omapi_object_dereference (&object, MDL);
				return omapi_protocol_send_status
					(po, message -> id_object,
					 status, message -> id,
					 "can't select authenticator");
			}
		}
641 642 643 644 645 646 647
		
		/* Now send the new contents of the object back in
		   response. */
		goto send;

	      case OMAPI_OP_REFRESH:
	      refresh:
Ted Lemon's avatar
Ted Lemon committed
648
		status = omapi_handle_lookup (&object, message -> h);
649
		if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
650
			return omapi_protocol_send_status
651
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
652
				 status, message -> id,
653 654 655
				 "no matching handle");
		}
	      send:		
656
		status = omapi_protocol_send_update (po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
657
						     message -> id, object);
Ted Lemon's avatar
Ted Lemon committed
658
		omapi_object_dereference (&object, MDL);
Ted Lemon's avatar
Ted Lemon committed
659
		return status;
660 661

	      case OMAPI_OP_UPDATE:
662
		if (m && m -> object) {
Ted Lemon's avatar
Ted Lemon committed
663
			omapi_object_reference (&object, m -> object, MDL);
664
		} else {
Ted Lemon's avatar
Ted Lemon committed
665
			status = omapi_handle_lookup (&object, message -> h);
666
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
667
				return omapi_protocol_send_status
668
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
669
					 status, message -> id,
670 671 672 673
					 "no matching handle");
			}
		}

674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
		if (object -> type == omapi_type_auth_key ||
		    (object -> inner &&
		     object -> inner -> type == omapi_type_auth_key)) {
			if (!m) {
				omapi_object_dereference (&object, MDL);
				return omapi_protocol_send_status
					(po, message -> id_object,
					 status, message -> id,
					 "cannot update authenticator");
			}
			
			status = omapi_protocol_add_auth (po, object,
							  message -> h);
		} else {
			status = omapi_object_update (object,
						      message -> id_object,
						      message -> object,
						      message -> h);
		}
693
		if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
694
			omapi_object_dereference (&object, MDL);
695
			if (!message -> rid)
Ted Lemon's avatar
Ted Lemon committed
696
				return omapi_protocol_send_status
697
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
698
					 status, message -> id,
699 700 701
					 "can't update object");
			if (m)
				omapi_signal ((omapi_object_t *)m,
Ted Lemon's avatar
Ted Lemon committed
702 703
					      "status", status,
					      (omapi_typed_data_t *)0);
704 705 706
			return ISC_R_SUCCESS;
		}
		if (!message -> rid)
Ted Lemon's avatar
Ted Lemon committed
707
			status = omapi_protocol_send_status
708
				(po, message -> id_object, ISC_R_SUCCESS,
Ted Lemon's avatar
Ted Lemon committed
709
				 message -> id, (char *)0);
710 711
		if (m)
			omapi_signal ((omapi_object_t *)m,
Ted Lemon's avatar
Ted Lemon committed
712 713 714
				      "status", ISC_R_SUCCESS,
				      (omapi_typed_data_t *)0);
		return status;
715 716

	      case OMAPI_OP_NOTIFY:
Ted Lemon's avatar
Ted Lemon committed
717
		return omapi_protocol_send_status
718
			(po, message -> id_object, ISC_R_NOTIMPLEMENTED,
Ted Lemon's avatar
Ted Lemon committed
719
			 message -> id, "notify not implemented yet");
720

Ted Lemon's avatar
Ted Lemon committed
721 722
	      case OMAPI_OP_STATUS:
		/* The return status of a request. */
723 724 725 726
		if (!m)
			return ISC_R_UNEXPECTED;

		/* Get the wait status. */
727
		status = omapi_get_value_str (mo, message -> id_object,
728 729
					      "result", &tv);
		if (status == ISC_R_SUCCESS) {
730 731
			status = omapi_get_int_value (&wsi, tv -> value);
			waitstatus = wsi;
Ted Lemon's avatar
Ted Lemon committed
732
			omapi_value_dereference (&tv, MDL);
733 734 735 736 737
			if (status != ISC_R_SUCCESS)
				waitstatus = ISC_R_UNEXPECTED;
		} else
			waitstatus = ISC_R_UNEXPECTED;

738
		status = omapi_get_value_str (mo, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
739 740 741
					      "message", &tv);
		omapi_signal ((omapi_object_t *)m, "status", waitstatus, tv);
		if (status == ISC_R_SUCCESS)
Ted Lemon's avatar
Ted Lemon committed
742
			omapi_value_dereference (&tv, MDL);
743
		return ISC_R_SUCCESS;
744 745

	      case OMAPI_OP_DELETE:
Ted Lemon's avatar
Ted Lemon committed
746
		status = omapi_handle_lookup (&object, message -> h);
747 748
		if (status != ISC_R_SUCCESS) {
			return omapi_protocol_send_status
749
				(po, message -> id_object,
750 751 752 753
				 status, message -> id,
				 "no matching handle");
		}

754
		if (!object -> type -> remove)
755
			return omapi_protocol_send_status
756
				(po, message -> id_object,
757
				 ISC_R_NOTIMPLEMENTED, message -> id,
758
				 "no remove method for object");
759

760
		status = (*(object -> type -> remove)) (object,
761
							message -> id_object);
Ted Lemon's avatar
Ted Lemon committed
762
		omapi_object_dereference (&object, MDL);
763

764
		return omapi_protocol_send_status (po, message -> id_object,
765 766
						   status, message -> id,
						   (char *)0);
767 768 769
	}
	return ISC_R_NOTIMPLEMENTED;
}