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

   Subroutines for dealing with message objects. */

/*
6 7
 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
 * Copyright (c) 1999-2003 by Internet Software Consortium
Ted Lemon's avatar
Ted Lemon committed
8
 *
9 10 11
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
Ted Lemon's avatar
Ted Lemon committed
12
 *
13 14 15 16 17 18 19
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Ted Lemon's avatar
Ted Lemon committed
20
 *
21 22 23 24 25
 *   Internet Systems Consortium, Inc.
 *   950 Charter Street
 *   Redwood City, CA 94063
 *   <info@isc.org>
 *   http://www.isc.org/
Ted Lemon's avatar
Ted Lemon committed
26
 *
27
 * This software has been written for Internet Systems Consortium
Ted Lemon's avatar
Ted Lemon committed
28
 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29
 * To learn more about Internet Systems Consortium, see
Ted Lemon's avatar
Ted Lemon committed
30 31 32
 * ``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
33 34
 */

35
#include <omapip/omapip_p.h>
Ted Lemon's avatar
Ted Lemon committed
36

37 38 39
OMAPI_OBJECT_ALLOC (omapi_message,
		    omapi_message_object_t, omapi_type_message)

Ted Lemon's avatar
Ted Lemon committed
40 41
omapi_message_object_t *omapi_registered_messages;

Ted Lemon's avatar
Ted Lemon committed
42
isc_result_t omapi_message_new (omapi_object_t **o, const char *file, int line)
Ted Lemon's avatar
Ted Lemon committed
43 44
{
	omapi_message_object_t *m;
45
	omapi_object_t *g;
Ted Lemon's avatar
Ted Lemon committed
46 47
	isc_result_t status;

Ted Lemon's avatar
Ted Lemon committed
48 49 50 51
	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
52

53
	g = (omapi_object_t *)0;
Ted Lemon's avatar
Ted Lemon committed
54
	status = omapi_generic_new (&g, file, line);
55
	if (status != ISC_R_SUCCESS) {
56
		dfree (m, file, line);
57 58
		return status;
	}
Ted Lemon's avatar
Ted Lemon committed
59
	status = omapi_object_reference (&m -> inner, g, file, line);
60
	if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
61
		omapi_object_dereference ((omapi_object_t **)&m, file, line);
62
		omapi_object_dereference (&g, file, line);
63 64 65
		return status;
	}
	status = omapi_object_reference (&g -> outer,
Ted Lemon's avatar
Ted Lemon committed
66
					 (omapi_object_t *)m, file, line);
67 68

	if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
69
		omapi_object_dereference ((omapi_object_t **)&m, file, line);
70
		omapi_object_dereference (&g, file, line);
71 72 73
		return status;
	}

Ted Lemon's avatar
Ted Lemon committed
74
	status = omapi_object_reference (o, (omapi_object_t *)m, file, line);
Ted Lemon's avatar
Ted Lemon committed
75
	omapi_message_dereference (&m, file, line);
Ted Lemon's avatar
Ted Lemon committed
76
	omapi_object_dereference (&g, file, line);
77 78 79
	if (status != ISC_R_SUCCESS)
		return status;

Ted Lemon's avatar
Ted Lemon committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
	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)
100 101 102
			omapi_typed_data_dereference (&m -> authenticator,
						      MDL);
		omapi_typed_data_reference (&m -> authenticator, value, MDL);
Ted Lemon's avatar
Ted Lemon committed
103 104
		return ISC_R_SUCCESS;

105 106 107 108
	} else if (!omapi_ds_strcmp (name, "object")) {
		if (value -> type != omapi_datatype_object)
			return ISC_R_INVALIDARG;
		if (m -> object)
109 110
			omapi_object_dereference (&m -> object, MDL);
		omapi_object_reference (&m -> object, value -> u.object, MDL);
111 112
		return ISC_R_SUCCESS;

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

Ted Lemon's avatar
Ted Lemon committed
122 123 124 125 126
	/* 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;
127
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
128 129 130 131 132 133

	/* 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;
134
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
135 136 137 138 139 140

	/* 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;
141
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
142 143 144 145 146 147

	/* 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;
148
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
149 150 151 152 153 154

	/* 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;
155
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
	}

	/* 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"))
181
		return omapi_make_int_value (value, name, (int)m -> authlen,
Ted Lemon's avatar
Ted Lemon committed
182
					     MDL);
Ted Lemon's avatar
Ted Lemon committed
183 184
	else if (!omapi_ds_strcmp (name, "authenticator")) {
		if (m -> authenticator)
Ted Lemon's avatar
Ted Lemon committed
185 186
			return omapi_make_value (value, name,
						 m -> authenticator, MDL);
Ted Lemon's avatar
Ted Lemon committed
187 188 189
		else
			return ISC_R_NOTFOUND;
	} else if (!omapi_ds_strcmp (name, "authid")) {
Ted Lemon's avatar
Ted Lemon committed
190 191
		return omapi_make_int_value (value,
					     name, (int)m -> authid, MDL);
Ted Lemon's avatar
Ted Lemon committed
192
	} else if (!omapi_ds_strcmp (name, "op")) {
Ted Lemon's avatar
Ted Lemon committed
193
		return omapi_make_int_value (value, name, (int)m -> op, MDL);
Ted Lemon's avatar
Ted Lemon committed
194
	} else if (!omapi_ds_strcmp (name, "handle")) {
Ted Lemon's avatar
Ted Lemon committed
195
		return omapi_make_int_value (value, name, (int)m -> h, MDL);
Ted Lemon's avatar
Ted Lemon committed
196
	} else if (!omapi_ds_strcmp (name, "id")) {
Ted Lemon's avatar
Ted Lemon committed
197
		return omapi_make_int_value (value, name, (int)m -> id, MDL);
Ted Lemon's avatar
Ted Lemon committed
198
	} else if (!omapi_ds_strcmp (name, "rid")) {
Ted Lemon's avatar
Ted Lemon committed
199
		return omapi_make_int_value (value, name, (int)m -> rid, MDL);
Ted Lemon's avatar
Ted Lemon committed
200 201 202 203 204 205 206 207 208
	}

	/* 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
209 210
isc_result_t omapi_message_destroy (omapi_object_t *h,
				    const char *file, int line)
Ted Lemon's avatar
Ted Lemon committed
211 212 213 214 215 216
{
	int i;

	omapi_message_object_t *m;
	if (h -> type != omapi_type_message)
		return ISC_R_INVALIDARG;
217
	m = (omapi_message_object_t *)h;
Ted Lemon's avatar
Ted Lemon committed
218
	if (m -> authenticator) {
Ted Lemon's avatar
Ted Lemon committed
219
		omapi_typed_data_dereference (&m -> authenticator, file, line);
Ted Lemon's avatar
Ted Lemon committed
220 221 222 223
	}
	if (!m -> prev && omapi_registered_messages != m)
		omapi_message_unregister (h);
	if (m -> id_object)
224
		omapi_object_dereference (&m -> id_object, file, line);
Ted Lemon's avatar
Ted Lemon committed
225
	if (m -> object)
226 227 228 229 230
		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
231 232 233 234
	return ISC_R_SUCCESS;
}

isc_result_t omapi_message_signal_handler (omapi_object_t *h,
235
					   const char *name, va_list ap)
Ted Lemon's avatar
Ted Lemon committed
236
{
Ted Lemon's avatar
Ted Lemon committed
237
	omapi_message_object_t *m;
Ted Lemon's avatar
Ted Lemon committed
238 239
	if (h -> type != omapi_type_message)
		return ISC_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
240
	m = (omapi_message_object_t *)h;
Ted Lemon's avatar
Ted Lemon committed
241
	
242 243 244
	if (!strcmp (name, "status")) {
		if (m -> notify_object &&
		    m -> notify_object -> type -> signal_handler)
245 246
			return ((m -> notify_object -> type -> signal_handler))
				(m -> notify_object, name, ap);
247 248 249
		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
250
	}
Ted Lemon's avatar
Ted Lemon committed
251 252 253 254 255 256 257 258 259 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
	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,
290
			 (omapi_object_t *)omapi_registered_messages, MDL);
Ted Lemon's avatar
Ted Lemon committed
291 292
		omapi_object_reference
			((omapi_object_t **)&omapi_registered_messages -> prev,
293
			 (omapi_object_t *)m, MDL);
Ted Lemon's avatar
Ted Lemon committed
294
		omapi_object_dereference
295
			((omapi_object_t **)&omapi_registered_messages, MDL);
Ted Lemon's avatar
Ted Lemon committed
296 297 298
	}
	omapi_object_reference
		((omapi_object_t **)&omapi_registered_messages,
299
		 (omapi_object_t *)m, MDL);
Ted Lemon's avatar
Ted Lemon committed
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
	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
319 320
					(omapi_object_t *)m -> next, MDL);
		omapi_object_dereference ((omapi_object_t **)&m -> next, MDL);
321
		omapi_object_dereference ((omapi_object_t **)&n -> prev, MDL);
Ted Lemon's avatar
Ted Lemon committed
322 323 324 325
	}
	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
326 327
					(omapi_object_t *)m -> prev, MDL);
		omapi_object_dereference ((omapi_object_t **)&m -> prev, MDL);
Ted Lemon's avatar
Ted Lemon committed
328 329
		if (tmp -> next)
			omapi_object_dereference
Ted Lemon's avatar
Ted Lemon committed
330
				((omapi_object_t **)&tmp -> next, MDL);
Ted Lemon's avatar
Ted Lemon committed
331 332 333
		if (n)
			omapi_object_reference
				((omapi_object_t **)&tmp -> next,
Ted Lemon's avatar
Ted Lemon committed
334 335
				 (omapi_object_t *)n, MDL);
		omapi_object_dereference ((omapi_object_t **)&tmp, MDL);
Ted Lemon's avatar
Ted Lemon committed
336 337
	} else {
		omapi_object_dereference
Ted Lemon's avatar
Ted Lemon committed
338
			((omapi_object_t **)&omapi_registered_messages, MDL);
Ted Lemon's avatar
Ted Lemon committed
339 340 341
		if (n)
			omapi_object_reference
				((omapi_object_t **)&omapi_registered_messages,
Ted Lemon's avatar
Ted Lemon committed
342
				 (omapi_object_t *)n, MDL);
Ted Lemon's avatar
Ted Lemon committed
343 344
	}
	if (n)
Ted Lemon's avatar
Ted Lemon committed
345
		omapi_object_dereference ((omapi_object_t **)&n, MDL);
Ted Lemon's avatar
Ted Lemon committed
346 347
	return ISC_R_SUCCESS;
}
348

349 350 351 352 353 354 355 356 357 358 359 360 361 362
#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
363 364 365
static isc_result_t
omapi_message_process_internal (omapi_object_t *, omapi_object_t *);

366
isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
Ted Lemon's avatar
Ted Lemon committed
367 368 369 370 371 372 373 374 375 376 377 378 379 380
{
	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
381
#if defined (DEBUG_MEMORY_LEAKAGE) && 0
Ted Lemon's avatar
Ted Lemon committed
382 383 384 385 386 387 388 389 390 391 392
	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)
393 394 395
{
	omapi_message_object_t *message, *m;
	omapi_object_t *object = (omapi_object_t *)0;
Ted Lemon's avatar
Ted Lemon committed
396
	omapi_value_t *tv = (omapi_value_t *)0;
397 398
	unsigned long create, update, exclusive;
	unsigned long wsi;
399 400 401 402 403 404 405
	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;

406 407 408 409 410 411 412
#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

413 414 415 416 417 418 419 420 421
	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;
422 423 424 425 426
		/* 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
427
		m = (omapi_message_object_t *)0;
428

429 430 431 432 433 434 435 436 437 438 439
		/* 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");
		}
	}

440 441 442
	switch (message -> op) {
	      case OMAPI_OP_OPEN:
		if (m) {
Ted Lemon's avatar
Ted Lemon committed
443
			return omapi_protocol_send_status
444
				(po, message -> id_object, ISC_R_INVALIDARG,
Ted Lemon's avatar
Ted Lemon committed
445
				 message -> id, "OPEN can't be a response");
446 447 448 449
		}

		/* Get the type of the requested object, if one was
		   specified. */
450
		status = omapi_get_value_str (mo, message -> id_object,
451 452 453 454 455 456 457 458 459 460 461 462
					      "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
463
			omapi_value_dereference (&tv, MDL);
464

465 466 467 468 469 470 471 472 473 474
		/* 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");
		}

475
		/* Get the create flag. */
476
		status = omapi_get_value_str (mo, message -> id_object,
477 478
					      "create", &tv);
		if (status == ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
479
			status = omapi_get_int_value (&create, tv -> value);
Ted Lemon's avatar
Ted Lemon committed
480
			omapi_value_dereference (&tv, MDL);
481
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
482
				return omapi_protocol_send_status
483
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
484
					 status, message -> id,
485 486 487 488 489 490
					 "invalid create flag value");
			}
		} else
			create = 0;

		/* Get the update flag. */
491
		status = omapi_get_value_str (mo, message -> id_object,
492 493
					      "update", &tv);
		if (status == ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
494
			status = omapi_get_int_value (&update, tv -> value);
Ted Lemon's avatar
Ted Lemon committed
495
			omapi_value_dereference (&tv, MDL);
496
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
497
				return omapi_protocol_send_status
498
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
499
					 status, message -> id,
500 501 502 503 504 505
					 "invalid update flag value");
			}
		} else
			update = 0;

		/* Get the exclusive flag. */
506
		status = omapi_get_value_str (mo, message -> id_object,
507 508
					      "exclusive", &tv);
		if (status == ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
509
			status = omapi_get_int_value (&exclusive, tv -> value);
Ted Lemon's avatar
Ted Lemon committed
510
			omapi_value_dereference (&tv, MDL);
511
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
512
				return omapi_protocol_send_status
513
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
514
					 status, message -> id,
515 516 517 518 519 520 521 522 523
					 "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
524
				return omapi_protocol_send_status
525 526 527
					(po, message -> id_object,
					 ISC_R_INVALIDARG,
					 message -> id,
528 529 530 531 532 533 534 535
					 "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
536
			return omapi_protocol_send_status
537
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
538
				 ISC_R_NOTIMPLEMENTED, message -> id,
539 540
				 "unsearchable object type");
		}
541

542
		status = (*(type -> lookup)) (&object, message -> id_object,
543 544
					      message -> object);

545 546 547
		if (status != ISC_R_SUCCESS &&
		    status != ISC_R_NOTFOUND &&
		    status != ISC_R_NOKEYS) {
Ted Lemon's avatar
Ted Lemon committed
548
			return omapi_protocol_send_status
549
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
550
				 status, message -> id,
551 552 553 554 555 556
				 "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
557
			return omapi_protocol_send_status
558
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
559
				 ISC_R_NOTFOUND, message -> id,
560 561 562 563 564 565 566
				 "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
567
			omapi_object_dereference (&object, MDL);
Ted Lemon's avatar
Ted Lemon committed
568
			return omapi_protocol_send_status
569
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
570
				 ISC_R_EXISTS, message -> id,
571 572 573 574 575
				 "specified object already exists");
		}

		/* If we're creating the object, do it now. */
		if (!object) {
Ted Lemon's avatar
Ted Lemon committed
576
			status = omapi_object_create (&object,
577
						      message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
578
						      type);
579
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
580
				return omapi_protocol_send_status
581
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
582
					 status, message -> id,
583 584 585 586 587 588
					 "can't create new object");
			}
		}

		/* If we're updating it, do so now. */
		if (create || update) {
589 590 591 592 593 594 595 596 597
			/* 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");
			}

598
			status = omapi_object_update (object,
599
						      message -> id_object,
600
						      message -> object,
Ted Lemon's avatar
Ted Lemon committed
601
						      message -> h);
602
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
603
				omapi_object_dereference (&object, MDL);
Ted Lemon's avatar
Ted Lemon committed
604
				return omapi_protocol_send_status
605
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
606
					 status, message -> id,
607 608 609
					 "can't update object");
			}
		}
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632

		/* 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");
			}
		}
633 634 635 636 637 638 639
		
		/* 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
640
		status = omapi_handle_lookup (&object, message -> h);
641
		if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
642
			return omapi_protocol_send_status
643
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
644
				 status, message -> id,
645 646 647
				 "no matching handle");
		}
	      send:		
648
		status = omapi_protocol_send_update (po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
649
						     message -> id, object);
Ted Lemon's avatar
Ted Lemon committed
650
		omapi_object_dereference (&object, MDL);
Ted Lemon's avatar
Ted Lemon committed
651
		return status;
652 653

	      case OMAPI_OP_UPDATE:
654
		if (m && m -> object) {
655 656
			status = omapi_object_reference (&object, m -> object,
									MDL);
657
		} else {
Ted Lemon's avatar
Ted Lemon committed
658
			status = omapi_handle_lookup (&object, message -> h);
659
			if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
660
				return omapi_protocol_send_status
661
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
662
					 status, message -> id,
663 664 665 666
					 "no matching handle");
			}
		}

667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
		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);
		}
686
		if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
687
			omapi_object_dereference (&object, MDL);
688
			if (!message -> rid)
Ted Lemon's avatar
Ted Lemon committed
689
				return omapi_protocol_send_status
690
					(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
691
					 status, message -> id,
692 693 694
					 "can't update object");
			if (m)
				omapi_signal ((omapi_object_t *)m,
Ted Lemon's avatar
Ted Lemon committed
695 696
					      "status", status,
					      (omapi_typed_data_t *)0);
697 698 699
			return ISC_R_SUCCESS;
		}
		if (!message -> rid)
Ted Lemon's avatar
Ted Lemon committed
700
			status = omapi_protocol_send_status
701
				(po, message -> id_object, ISC_R_SUCCESS,
Ted Lemon's avatar
Ted Lemon committed
702
				 message -> id, (char *)0);
703
		if (m) {
704
			omapi_signal ((omapi_object_t *)m,
Ted Lemon's avatar
Ted Lemon committed
705 706
				      "status", ISC_R_SUCCESS,
				      (omapi_typed_data_t *)0);
707 708 709 710 711
			omapi_message_unregister ((omapi_object_t *)m);
		}

		omapi_object_dereference (&object, MDL);

Ted Lemon's avatar
Ted Lemon committed
712
		return status;
713 714

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

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

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

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

		omapi_message_unregister((omapi_object_t *)m);

744
		return ISC_R_SUCCESS;
745 746

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

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

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

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