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. */

/*
David Hankins's avatar
David Hankins committed
6
 * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
7
 * 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
{
	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
	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)
{
	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,
288
			 (omapi_object_t *)omapi_registered_messages, MDL);
Ted Lemon's avatar
Ted Lemon committed
289 290
		omapi_object_reference
			((omapi_object_t **)&omapi_registered_messages -> prev,
291
			 (omapi_object_t *)m, MDL);
Ted Lemon's avatar
Ted Lemon committed
292
		omapi_object_dereference
293
			((omapi_object_t **)&omapi_registered_messages, MDL);
Ted Lemon's avatar
Ted Lemon committed
294 295 296
	}
	omapi_object_reference
		((omapi_object_t **)&omapi_registered_messages,
297
		 (omapi_object_t *)m, MDL);
Ted Lemon's avatar
Ted Lemon committed
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
	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
317 318
					(omapi_object_t *)m -> next, MDL);
		omapi_object_dereference ((omapi_object_t **)&m -> next, MDL);
319
		omapi_object_dereference ((omapi_object_t **)&n -> prev, MDL);
Ted Lemon's avatar
Ted Lemon committed
320 321 322 323
	}
	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
324 325
					(omapi_object_t *)m -> prev, MDL);
		omapi_object_dereference ((omapi_object_t **)&m -> prev, MDL);
Ted Lemon's avatar
Ted Lemon committed
326 327
		if (tmp -> next)
			omapi_object_dereference
Ted Lemon's avatar
Ted Lemon committed
328
				((omapi_object_t **)&tmp -> next, MDL);
Ted Lemon's avatar
Ted Lemon committed
329 330 331
		if (n)
			omapi_object_reference
				((omapi_object_t **)&tmp -> next,
Ted Lemon's avatar
Ted Lemon committed
332 333
				 (omapi_object_t *)n, MDL);
		omapi_object_dereference ((omapi_object_t **)&tmp, MDL);
Ted Lemon's avatar
Ted Lemon committed
334 335
	} else {
		omapi_object_dereference
Ted Lemon's avatar
Ted Lemon committed
336
			((omapi_object_t **)&omapi_registered_messages, MDL);
Ted Lemon's avatar
Ted Lemon committed
337 338 339
		if (n)
			omapi_object_reference
				((omapi_object_t **)&omapi_registered_messages,
Ted Lemon's avatar
Ted Lemon committed
340
				 (omapi_object_t *)n, MDL);
Ted Lemon's avatar
Ted Lemon committed
341 342
	}
	if (n)
Ted Lemon's avatar
Ted Lemon committed
343
		omapi_object_dereference ((omapi_object_t **)&n, MDL);
Ted Lemon's avatar
Ted Lemon committed
344 345
	return ISC_R_SUCCESS;
}
346

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

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

404 405 406 407 408 409 410
#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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		omapi_object_dereference (&object, MDL);

Ted Lemon's avatar
Ted Lemon committed
710
		return status;
711 712

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

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

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

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

		omapi_message_unregister((omapi_object_t *)m);

742
		return ISC_R_SUCCESS;
743 744

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

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

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

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