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

/*
Shawn Routhier's avatar
Shawn Routhier committed
6
 * Copyright (c) 2004,2007,2009 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
 *   Internet Systems Consortium, Inc.
 *   950 Charter Street
 *   Redwood City, CA 94063
 *   <info@isc.org>
25
 *   https://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
30
 * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
Ted Lemon's avatar
Ted Lemon committed
31 32
 * 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
	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)
94
		return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
95 96 97 98 99 100 101
	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
	} else if (!omapi_ds_strcmp (name, "object")) {
		if (value -> type != omapi_datatype_object)
109
			return DHCP_R_INVALIDARG;
110
		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
	} else if (!omapi_ds_strcmp (name, "notify-object")) {
		if (value -> type != omapi_datatype_object)
117
			return DHCP_R_INVALIDARG;
118
		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
	/* Can set authid, but it has to be an integer. */
	} else if (!omapi_ds_strcmp (name, "authid")) {
		if (value -> type != omapi_datatype_int)
127
			return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
128
		m -> authid = value -> u.integer;
129
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
130 131 132 133

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

	/* Handle also has to be an integer. */
	} else if (!omapi_ds_strcmp (name, "handle")) {
		if (value -> type != omapi_datatype_int)
141
			return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
142
		m -> h = value -> u.integer;
143
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
144 145 146 147

	/* Transaction ID has to be an integer. */
	} else if (!omapi_ds_strcmp (name, "id")) {
		if (value -> type != omapi_datatype_int)
148
			return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
149
		m -> id = value -> u.integer;
150
		return ISC_R_SUCCESS;
Ted Lemon's avatar
Ted Lemon committed
151 152 153 154

	/* Remote transaction ID has to be an integer. */
	} else if (!omapi_ds_strcmp (name, "rid")) {
		if (value -> type != omapi_datatype_int)
155
			return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
156
		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
	}

	/* 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)
178
		return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
179 180 181 182
	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
{
	omapi_message_object_t *m;
	if (h -> type != omapi_type_message)
216
		return DHCP_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
	if (h -> type != omapi_type_message)
239
		return DHCP_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
	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)
265
		return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
266 267 268 269 270 271 272 273 274 275 276 277

	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)
278
		return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
279 280 281 282
	m = (omapi_message_object_t *)mo;
	
	/* Already registered? */
	if (m -> prev || m -> next || omapi_registered_messages == m)
283
		return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
284 285 286 287

	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
	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)
307
		return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
308 309 310 311
	m = (omapi_message_object_t *)mo;
	
	/* Not registered? */
	if (!m -> prev && omapi_registered_messages != m)
312
		return DHCP_R_INVALIDARG;
Ted Lemon's avatar
Ted Lemon committed
313 314 315 316

	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
{
	isc_result_t status;
367
#if defined (DEBUG_MEMORY_LEAKAGE) && 0
Ted Lemon's avatar
Ted Lemon committed
368 369 370 371 372 373 374 375 376 377 378
	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
	isc_result_t status, waitstatus;
	omapi_object_type_t *type;

	if (mo -> type != omapi_type_message)
401
		return DHCP_R_INVALIDARG;
402 403
	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
		/* All messages must have an authenticator, with the exception
		   of messages that are opening a new authenticator. */
429 430 431
		if (omapi_protocol_authenticated(po) &&
		    !message->id_object &&
		    message->op != OMAPI_OP_OPEN) {
432
			return omapi_protocol_send_status
433 434
				(po, message->id_object, DHCP_R_NOKEYS,
				 message->id, "No authenticator on message");
435 436 437
		}
	}

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 443
				(po, message->id_object, DHCP_R_INVALIDARG,
				 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
		/* If this object had no authenticator, the requested object
		   must be an authenticator object. */
465 466
		if (omapi_protocol_authenticated(po) &&
		    !message->id_object &&
467 468
		    type != omapi_type_auth_key) {
			return omapi_protocol_send_status
469 470
				(po, message->id_object, DHCP_R_NOKEYS,
				 message->id, "No authenticator on message");
471 472
		}

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,
					 DHCP_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
		if (status != ISC_R_SUCCESS &&
		    status != ISC_R_NOTFOUND &&
545
		    status != DHCP_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;
}