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

   Subroutines for dealing with message objects. */

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

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

46 47 48
OMAPI_OBJECT_ALLOC (omapi_message,
		    omapi_message_object_t, omapi_type_message)

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

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

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

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

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

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

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

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

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

	/* Can't set authlen. */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

355 356 357 358 359 360 361 362 363 364 365 366 367 368
#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
369 370 371
static isc_result_t
omapi_message_process_internal (omapi_object_t *, omapi_object_t *);

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

412 413 414 415 416 417 418
#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

419 420 421 422 423 424 425 426 427
	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;
428 429 430 431 432
		/* 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
433
		m = (omapi_message_object_t *)0;
434

435 436 437 438 439 440 441 442 443 444 445
		/* 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");
		}
	}

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

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

471 472 473 474 475 476 477 478 479 480
		/* 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");
		}

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

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

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

		if (!message -> object) {
			return omapi_protocol_send_status
550
				(po, message -> id_object,
551 552 553
				 ISC_R_NOTFOUND, message -> id,
				 "no lookup key specified");
		}
554
		status = (*(type -> lookup)) (&object, message -> id_object,
555 556
					      message -> object);

557 558 559
		if (status != ISC_R_SUCCESS &&
		    status != ISC_R_NOTFOUND &&
		    status != ISC_R_NOKEYS) {
Ted Lemon's avatar
Ted Lemon committed
560
			return omapi_protocol_send_status
561
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
562
				 status, message -> id,
563 564 565 566 567 568
				 "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
569
			return omapi_protocol_send_status
570
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
571
				 ISC_R_NOTFOUND, message -> id,
572 573 574 575 576 577 578
				 "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
579
			omapi_object_dereference (&object, MDL);
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
				 ISC_R_EXISTS, message -> id,
583 584 585 586 587
				 "specified object already exists");
		}

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

		/* If we're updating it, do so now. */
		if (create || update) {
601 602 603 604 605 606 607 608 609
			/* 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");
			}

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

		/* 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");
			}
		}
645 646 647 648 649 650 651
		
		/* 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
652
		status = omapi_handle_lookup (&object, message -> h);
653
		if (status != ISC_R_SUCCESS) {
Ted Lemon's avatar
Ted Lemon committed
654
			return omapi_protocol_send_status
655
				(po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
656
				 status, message -> id,
657 658 659
				 "no matching handle");
		}
	      send:		
660
		status = omapi_protocol_send_update (po, message -> id_object,
Ted Lemon's avatar
Ted Lemon committed
661
						     message -> id, object);
Ted Lemon's avatar
Ted Lemon committed
662
		omapi_object_dereference (&object, MDL);
Ted Lemon's avatar
Ted Lemon committed
663
		return status;
664 665

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

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

	      case OMAPI_OP_NOTIFY:
Ted Lemon's avatar
Ted Lemon committed
721
		return omapi_protocol_send_status
722
			(po, message -> id_object, ISC_R_NOTIMPLEMENTED,
Ted Lemon's avatar
Ted Lemon committed
723
			 message -> id, "notify not implemented yet");
724

Ted Lemon's avatar
Ted Lemon committed
725 726
	      case OMAPI_OP_STATUS:
		/* The return status of a request. */
727 728 729 730
		if (!m)
			return ISC_R_UNEXPECTED;

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

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

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

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

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

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