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 36
#include "dhcpd.h"

37
#include <omapip/omapip_p.h>
Ted Lemon's avatar
Ted Lemon committed
38

39 40 41
OMAPI_OBJECT_ALLOC (omapi_message,
		    omapi_message_object_t, omapi_type_message)

Ted Lemon's avatar
Ted Lemon committed
42 43
omapi_message_object_t *omapi_registered_messages;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

408 409 410 411 412 413 414
#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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		omapi_object_dereference (&object, MDL);

Ted Lemon's avatar
Ted Lemon committed
714
		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 744 745

		omapi_message_unregister((omapi_object_t *)m);

746
		return ISC_R_SUCCESS;
747 748

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

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

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

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