~ubuntu-branches/ubuntu/quantal/isc-dhcp/quantal-proposed

1 by Andrew Pollock
Import upstream version 4.1.0
1
/* omapi.c
2
3
   OMAPI object interfaces for the DHCP server. */
4
5
/*
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
6
 * Copyright (c) 2004-2010,2012 by Internet Systems Consortium, Inc. ("ISC")
1 by Andrew Pollock
Import upstream version 4.1.0
7
 * Copyright (c) 1999-2003 by Internet Software Consortium
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 *
21
 *   Internet Systems Consortium, Inc.
22
 *   950 Charter Street
23
 *   Redwood City, CA 94063
24
 *   <info@isc.org>
1.1.1 by Andrew Pollock
Import upstream version 4.1.1
25
 *   https://www.isc.org/
1 by Andrew Pollock
Import upstream version 4.1.0
26
 *
27
 * This software has been written for Internet Systems Consortium
28
 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29
 * To learn more about Internet Systems Consortium, see
1.1.1 by Andrew Pollock
Import upstream version 4.1.1
30
 * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
1 by Andrew Pollock
Import upstream version 4.1.0
31
 * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
32
 * ``http://www.nominum.com''.
33
 */
34
35
/* Many, many thanks to Brian Murrell and BCtel for this code - BCtel
36
   provided the funding that resulted in this code and the entire
37
   OMAPI support library being written, and Brian helped brainstorm
38
   and refine the requirements.  To the extent that this code is
39
   useful, you have Brian and BCtel to thank.  Any limitations in the
40
   code are a result of mistakes on my part.  -- Ted Lemon */
41
42
#include "dhcpd.h"
43
#include <omapip/omapip_p.h>
44
45
static isc_result_t class_lookup (omapi_object_t **,
46
				  omapi_object_t *, omapi_object_t *,
47
				  omapi_object_type_t *);
48
49
omapi_object_type_t *dhcp_type_lease;
50
omapi_object_type_t *dhcp_type_pool;
51
omapi_object_type_t *dhcp_type_class;
52
omapi_object_type_t *dhcp_type_subclass;
53
omapi_object_type_t *dhcp_type_host;
54
#if defined (FAILOVER_PROTOCOL)
55
omapi_object_type_t *dhcp_type_failover_state;
56
omapi_object_type_t *dhcp_type_failover_link;
57
omapi_object_type_t *dhcp_type_failover_listener;
58
#endif
59
60
void dhcp_db_objects_setup ()
61
{
62
	isc_result_t status;
63
64
	status = omapi_object_type_register (&dhcp_type_lease,
65
					     "lease",
66
					     dhcp_lease_set_value,
67
					     dhcp_lease_get_value,
68
					     dhcp_lease_destroy,
69
					     dhcp_lease_signal_handler,
70
					     dhcp_lease_stuff_values,
71
					     dhcp_lease_lookup, 
72
					     dhcp_lease_create,
73
					     dhcp_lease_remove,
74
#if defined (COMPACT_LEASES)
75
					     dhcp_lease_free,
76
					     dhcp_lease_get,
77
#else
78
					     0, 0,
79
#endif
80
					     0,
81
					     sizeof (struct lease),
82
					     0, RC_LEASE);
83
	if (status != ISC_R_SUCCESS)
84
		log_fatal ("Can't register lease object type: %s",
85
			   isc_result_totext (status));
86
87
	status = omapi_object_type_register (&dhcp_type_class,
88
					     "class",
89
					     dhcp_class_set_value,
90
					     dhcp_class_get_value,
91
					     dhcp_class_destroy,
92
					     dhcp_class_signal_handler,
93
					     dhcp_class_stuff_values,
94
					     dhcp_class_lookup, 
95
					     dhcp_class_create,
96
					     dhcp_class_remove, 0, 0, 0,
97
					     sizeof (struct class), 0,
98
					     RC_MISC);
99
	if (status != ISC_R_SUCCESS)
100
		log_fatal ("Can't register class object type: %s",
101
			   isc_result_totext (status));
102
103
	status = omapi_object_type_register (&dhcp_type_subclass,
104
					     "subclass",
105
					     dhcp_subclass_set_value,
106
					     dhcp_subclass_get_value,
107
					     dhcp_class_destroy,
108
					     dhcp_subclass_signal_handler,
109
					     dhcp_subclass_stuff_values,
110
					     dhcp_subclass_lookup, 
111
					     dhcp_subclass_create,
112
					     dhcp_subclass_remove, 0, 0, 0,
113
					     sizeof (struct class), 0, RC_MISC);
114
	if (status != ISC_R_SUCCESS)
115
		log_fatal ("Can't register subclass object type: %s",
116
			   isc_result_totext (status));
117
118
	status = omapi_object_type_register (&dhcp_type_pool,
119
					     "pool",
120
					     dhcp_pool_set_value,
121
					     dhcp_pool_get_value,
122
					     dhcp_pool_destroy,
123
					     dhcp_pool_signal_handler,
124
					     dhcp_pool_stuff_values,
125
					     dhcp_pool_lookup, 
126
					     dhcp_pool_create,
127
					     dhcp_pool_remove, 0, 0, 0,
128
					     sizeof (struct pool), 0, RC_MISC);
129
130
	if (status != ISC_R_SUCCESS)
131
		log_fatal ("Can't register pool object type: %s",
132
			   isc_result_totext (status));
133
134
	status = omapi_object_type_register (&dhcp_type_host,
135
					     "host",
136
					     dhcp_host_set_value,
137
					     dhcp_host_get_value,
138
					     dhcp_host_destroy,
139
					     dhcp_host_signal_handler,
140
					     dhcp_host_stuff_values,
141
					     dhcp_host_lookup, 
142
					     dhcp_host_create,
143
					     dhcp_host_remove, 0, 0, 0,
144
					     sizeof (struct host_decl),
145
					     0, RC_MISC);
146
147
	if (status != ISC_R_SUCCESS)
148
		log_fatal ("Can't register host object type: %s",
149
			   isc_result_totext (status));
150
151
#if defined (FAILOVER_PROTOCOL)
152
	status = omapi_object_type_register (&dhcp_type_failover_state,
153
					     "failover-state",
154
					     dhcp_failover_state_set_value,
155
					     dhcp_failover_state_get_value,
156
					     dhcp_failover_state_destroy,
157
					     dhcp_failover_state_signal,
158
					     dhcp_failover_state_stuff,
159
					     dhcp_failover_state_lookup, 
160
					     dhcp_failover_state_create,
161
					     dhcp_failover_state_remove,
162
					     0, 0, 0,
163
					     sizeof (dhcp_failover_state_t),
164
					     0, RC_MISC);
165
166
	if (status != ISC_R_SUCCESS)
167
		log_fatal ("Can't register failover state object type: %s",
168
			   isc_result_totext (status));
169
170
	status = omapi_object_type_register (&dhcp_type_failover_link,
171
					     "failover-link",
172
					     dhcp_failover_link_set_value,
173
					     dhcp_failover_link_get_value,
174
					     dhcp_failover_link_destroy,
175
					     dhcp_failover_link_signal,
176
					     dhcp_failover_link_stuff_values,
177
					     0, 0, 0, 0, 0, 0,
178
					     sizeof (dhcp_failover_link_t), 0,
179
					     RC_MISC);
180
181
	if (status != ISC_R_SUCCESS)
182
		log_fatal ("Can't register failover link object type: %s",
183
			   isc_result_totext (status));
184
185
	status = omapi_object_type_register (&dhcp_type_failover_listener,
186
					     "failover-listener",
187
					     dhcp_failover_listener_set_value,
188
					     dhcp_failover_listener_get_value,
189
					     dhcp_failover_listener_destroy,
190
					     dhcp_failover_listener_signal,
191
					     dhcp_failover_listener_stuff,
192
					     0, 0, 0, 0, 0, 0,
193
					     sizeof
194
					     (dhcp_failover_listener_t), 0,
195
					     RC_MISC);
196
197
	if (status != ISC_R_SUCCESS)
198
		log_fatal ("Can't register failover listener object type: %s",
199
			   isc_result_totext (status));
200
#endif /* FAILOVER_PROTOCOL */
201
}
202
203
isc_result_t dhcp_lease_set_value  (omapi_object_t *h,
204
				    omapi_object_t *id,
205
				    omapi_data_string_t *name,
206
				    omapi_typed_data_t *value)
207
{
208
	struct lease *lease;
209
	isc_result_t status;
210
211
	if (h -> type != dhcp_type_lease)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
212
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
213
	lease = (struct lease *)h;
214
215
	/* We're skipping a lot of things it might be interesting to
216
	   set - for now, we just make it possible to whack the state. */
217
	if (!omapi_ds_strcmp (name, "state")) {
218
	    unsigned long bar;
219
	    const char *ols, *nls;
220
	    status = omapi_get_int_value (&bar, value);
221
	    if (status != ISC_R_SUCCESS)
222
		return status;
223
	    
224
	    if (bar < 1 || bar > FTS_LAST)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
225
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
226
	    nls = binding_state_names [bar - 1];
227
	    if (lease -> binding_state >= 1 &&
228
		lease -> binding_state <= FTS_LAST)
229
		ols = binding_state_names [lease -> binding_state - 1];
230
	    else
231
		ols = "unknown state";
232
	    
233
	    if (lease -> binding_state != bar) {
234
		lease -> next_binding_state = bar;
235
		if (supersede_lease (lease, 0, 1, 1, 1)) {
236
			log_info ("lease %s state changed from %s to %s",
237
				  piaddr(lease->ip_addr), ols, nls);
238
			return ISC_R_SUCCESS;
239
		}
240
		log_info ("lease %s state change from %s to %s failed.",
241
			  piaddr (lease -> ip_addr), ols, nls);
242
		return ISC_R_IOERROR;
243
	    }
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
244
	    return DHCP_R_UNCHANGED;
1 by Andrew Pollock
Import upstream version 4.1.0
245
	} else if (!omapi_ds_strcmp (name, "ip-address")) {
246
	    return ISC_R_NOPERM;
247
	} else if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
248
	    return DHCP_R_UNCHANGED;	/* XXX take change. */
1 by Andrew Pollock
Import upstream version 4.1.0
249
	} else if (!omapi_ds_strcmp (name, "hostname")) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
250
	    return DHCP_R_UNCHANGED;	/* XXX take change. */
1 by Andrew Pollock
Import upstream version 4.1.0
251
	} else if (!omapi_ds_strcmp (name, "client-hostname")) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
252
	    return DHCP_R_UNCHANGED;	/* XXX take change. */
1 by Andrew Pollock
Import upstream version 4.1.0
253
	} else if (!omapi_ds_strcmp (name, "host")) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
254
	    return DHCP_R_UNCHANGED;	/* XXX take change. */
1 by Andrew Pollock
Import upstream version 4.1.0
255
	} else if (!omapi_ds_strcmp (name, "subnet")) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
256
	    return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
257
	} else if (!omapi_ds_strcmp (name, "pool")) {
258
	    return ISC_R_NOPERM;
259
	} else if (!omapi_ds_strcmp (name, "starts")) {
260
	    return ISC_R_NOPERM;
261
	} else if (!omapi_ds_strcmp (name, "ends")) {
262
	    unsigned long lease_end, old_lease_end;
263
	    status = omapi_get_int_value (&lease_end, value);
264
	    if (status != ISC_R_SUCCESS)
265
		return status;
266
	    old_lease_end = lease->ends;
267
	    lease->ends = lease_end;
268
	    if (supersede_lease (lease, 0, 1, 1, 1)) {
269
		log_info ("lease %s end changed from %lu to %lu",
270
			  piaddr(lease->ip_addr), old_lease_end, lease_end);
271
		return ISC_R_SUCCESS;
272
	    }
273
	    log_info ("lease %s end change from %lu to %lu failed",
274
		      piaddr(lease->ip_addr), old_lease_end, lease_end);
275
	    return ISC_R_IOERROR;
276
	} else if (!omapi_ds_strcmp(name, "flags")) {
277
	    u_int8_t oldflags;
278
279
	    if (value->type != omapi_datatype_data)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
280
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
281
282
	    oldflags = lease->flags;
283
	    lease->flags = (value->u.buffer.value[0] & EPHEMERAL_FLAGS) |
284
			   (lease->flags & ~EPHEMERAL_FLAGS);
285
	    if(oldflags == lease->flags)
286
		return ISC_R_SUCCESS;
287
	    if (!supersede_lease(lease, NULL, 1, 1, 1)) {
288
		log_error("Failed to update flags for lease %s.",
289
			  piaddr(lease->ip_addr));
290
		return ISC_R_IOERROR;
291
	    }
292
	    return ISC_R_SUCCESS;
293
	} else if (!omapi_ds_strcmp (name, "billing-class")) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
294
	    return DHCP_R_UNCHANGED;	/* XXX carefully allow change. */
1 by Andrew Pollock
Import upstream version 4.1.0
295
	} else if (!omapi_ds_strcmp (name, "hardware-address")) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
296
	    return DHCP_R_UNCHANGED;	/* XXX take change. */
1 by Andrew Pollock
Import upstream version 4.1.0
297
	} else if (!omapi_ds_strcmp (name, "hardware-type")) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
298
	    return DHCP_R_UNCHANGED;	/* XXX take change. */
1 by Andrew Pollock
Import upstream version 4.1.0
299
	} else if (lease -> scope) {
300
	    status = binding_scope_set_value (lease -> scope, 0, name, value);
301
	    if (status == ISC_R_SUCCESS) {
302
		    if (write_lease (lease) && commit_leases ())
303
			    return ISC_R_SUCCESS;
304
		    return ISC_R_IOERROR;
305
	    }
306
	}
307
308
	/* Try to find some inner object that can take the value. */
309
	if (h -> inner && h -> inner -> type -> set_value) {
310
		status = ((*(h -> inner -> type -> set_value))
311
			  (h -> inner, id, name, value));
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
312
		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
1 by Andrew Pollock
Import upstream version 4.1.0
313
			return status;
314
	}
315
			  
316
	if (!lease -> scope) {
317
		if (!binding_scope_allocate (&lease -> scope, MDL))
318
			return ISC_R_NOMEMORY;
319
	}
320
	status = binding_scope_set_value (lease -> scope, 1, name, value);
321
	if (status != ISC_R_SUCCESS)
322
		return status;
323
324
	if (write_lease (lease) && commit_leases ())
325
		return ISC_R_SUCCESS;
326
	return ISC_R_IOERROR;
327
}
328
329
330
isc_result_t dhcp_lease_get_value (omapi_object_t *h, omapi_object_t *id,
331
				   omapi_data_string_t *name,
332
				   omapi_value_t **value)
333
{
334
	struct lease *lease;
335
	isc_result_t status;
336
337
	if (h -> type != dhcp_type_lease)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
338
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
339
	lease = (struct lease *)h;
340
341
	if (!omapi_ds_strcmp (name, "state"))
342
		return omapi_make_int_value (value, name,
343
					     (int)lease -> binding_state, MDL);
344
	else if (!omapi_ds_strcmp (name, "ip-address"))
345
		return omapi_make_const_value (value, name,
346
					       lease -> ip_addr.iabuf,
347
					       lease -> ip_addr.len, MDL);
348
	else if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
349
		return omapi_make_const_value (value, name,
350
					       lease -> uid,
351
					       lease -> uid_len, MDL);
352
	} else if (!omapi_ds_strcmp (name, "client-hostname")) {
353
		if (lease -> client_hostname)
354
			return omapi_make_string_value
355
				(value, name, lease -> client_hostname, MDL);
356
		return ISC_R_NOTFOUND;
357
	} else if (!omapi_ds_strcmp (name, "host")) {
358
		if (lease -> host)
359
			return omapi_make_handle_value
360
				(value, name,
361
				 ((omapi_object_t *)lease -> host), MDL);
362
	} else if (!omapi_ds_strcmp (name, "subnet"))
363
		return omapi_make_handle_value (value, name,
364
						((omapi_object_t *)
365
						 lease -> subnet), MDL);
366
	else if (!omapi_ds_strcmp (name, "pool"))
367
		return omapi_make_handle_value (value, name,
368
						((omapi_object_t *)
369
						 lease -> pool), MDL);
370
	else if (!omapi_ds_strcmp (name, "billing-class")) {
371
		if (lease -> billing_class)
372
			return omapi_make_handle_value
373
				(value, name,
374
				 ((omapi_object_t *)lease -> billing_class),
375
				 MDL);
376
		return ISC_R_NOTFOUND;
377
	} else if (!omapi_ds_strcmp (name, "hardware-address")) {
378
		if (lease -> hardware_addr.hlen)
379
			return omapi_make_const_value
380
				(value, name, &lease -> hardware_addr.hbuf [1],
381
				 (unsigned)(lease -> hardware_addr.hlen - 1),
382
				 MDL);
383
		return ISC_R_NOTFOUND;
384
	} else if (!omapi_ds_strcmp (name, "hardware-type")) {
385
		if (lease -> hardware_addr.hlen)
386
			return omapi_make_int_value
387
				(value, name, lease -> hardware_addr.hbuf [0],
388
				 MDL);
389
		return ISC_R_NOTFOUND;
390
	} else if (lease -> scope) {
391
		status = binding_scope_get_value (value, lease -> scope, name);
392
		if (status != ISC_R_NOTFOUND)
393
			return status;
394
	}
395
396
	/* Try to find some inner object that can take the value. */
397
	if (h -> inner && h -> inner -> type -> get_value) {
398
		status = ((*(h -> inner -> type -> get_value))
399
			  (h -> inner, id, name, value));
400
		if (status == ISC_R_SUCCESS)
401
			return status;
402
	}
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
403
	return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
404
}
405
406
isc_result_t dhcp_lease_destroy (omapi_object_t *h, const char *file, int line)
407
{
408
	struct lease *lease;
409
410
	if (h -> type != dhcp_type_lease)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
411
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
412
	lease = (struct lease *)h;
413
414
	if (lease -> uid)
415
		uid_hash_delete (lease);
416
	hw_hash_delete (lease);
417
418
	if (lease -> on_release)
419
		executable_statement_dereference (&lease -> on_release,
420
						  file, line);
421
	if (lease -> on_expiry)
422
		executable_statement_dereference (&lease -> on_expiry,
423
						  file, line);
424
	if (lease -> on_commit)
425
		executable_statement_dereference (&lease -> on_commit,
426
						  file, line);
427
	if (lease -> scope)
428
		binding_scope_dereference (&lease -> scope, file, line);
429
430
	if (lease -> agent_options)
431
		option_chain_head_dereference (&lease -> agent_options,
432
					       file, line);
433
	if (lease -> uid && lease -> uid != lease -> uid_buf) {
434
		dfree (lease -> uid, MDL);
435
		lease -> uid = &lease -> uid_buf [0];
436
		lease -> uid_len = 0;
437
	}
438
439
	if (lease -> client_hostname) {
440
		dfree (lease -> client_hostname, MDL);
441
		lease -> client_hostname = (char *)0;
442
	}
443
444
	if (lease -> host)
445
		host_dereference (&lease -> host, file, line);
446
	if (lease -> subnet)
447
		subnet_dereference (&lease -> subnet, file, line);
448
	if (lease -> pool)
449
		pool_dereference (&lease -> pool, file, line);
450
451
	if (lease -> state) {
452
		free_lease_state (lease -> state, file, line);
453
		lease -> state = (struct lease_state *)0;
454
455
		cancel_timeout (lease_ping_timeout, lease);
456
		--outstanding_pings; /* XXX */
457
	}
458
459
	if (lease -> billing_class)
460
		class_dereference
461
			(&lease -> billing_class, file, line);
462
463
#if defined (DEBUG_MEMORY_LEAKAGE) || \
464
		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
465
	/* XXX we should never be destroying a lease with a next
466
	   XXX pointer except on exit... */
467
	if (lease -> next)
468
		lease_dereference (&lease -> next, file, line);
469
	if (lease -> n_hw)
470
		lease_dereference (&lease -> n_hw, file, line);
471
	if (lease -> n_uid)
472
		lease_dereference (&lease -> n_uid, file, line);
473
	if (lease -> next_pending)
474
		lease_dereference (&lease -> next_pending, file, line);
475
#endif
476
477
	return ISC_R_SUCCESS;
478
}
479
480
isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
481
					const char *name, va_list ap)
482
{
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
483
	/* h should point to (struct lease *) */
1 by Andrew Pollock
Import upstream version 4.1.0
484
	isc_result_t status;
485
486
	if (h -> type != dhcp_type_lease)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
487
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
488
489
	if (!strcmp (name, "updated"))
490
		return ISC_R_SUCCESS;
491
492
	/* Try to find some inner object that can take the value. */
493
	if (h -> inner && h -> inner -> type -> signal_handler) {
494
		status = ((*(h -> inner -> type -> signal_handler))
495
			  (h -> inner, name, ap));
496
		if (status == ISC_R_SUCCESS)
497
			return status;
498
	}
499
	return ISC_R_NOTFOUND;
500
}
501
502
isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
503
				      omapi_object_t *id,
504
				      omapi_object_t *h)
505
{
506
	u_int32_t bouncer;
507
	struct lease *lease;
508
	isc_result_t status;
509
	u_int8_t flagbuf;
510
511
	if (h -> type != dhcp_type_lease)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
512
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
513
	lease = (struct lease *)h;
514
515
	/* Write out all the values. */
516
517
	status = omapi_connection_put_name (c, "state");
518
	if (status != ISC_R_SUCCESS)
519
		return status;
520
	status = omapi_connection_put_uint32 (c, sizeof (int));
521
	if (status != ISC_R_SUCCESS)
522
		return status;
523
	status = omapi_connection_put_uint32 (c, lease -> binding_state);
524
	if (status != ISC_R_SUCCESS)
525
		return status;
526
527
	status = omapi_connection_put_name (c, "ip-address");
528
	if (status != ISC_R_SUCCESS)
529
		return status;
530
	status = omapi_connection_put_uint32 (c, lease -> ip_addr.len);
531
	if (status != ISC_R_SUCCESS)
532
		return status;
533
	status = omapi_connection_copyin (c, lease -> ip_addr.iabuf,
534
					  lease -> ip_addr.len);
535
	if (status != ISC_R_SUCCESS)
536
		return status;
537
538
	if (lease -> uid_len) {
539
		status = omapi_connection_put_name (c,
540
						    "dhcp-client-identifier");
541
		if (status != ISC_R_SUCCESS)
542
			return status;
543
		status = omapi_connection_put_uint32 (c, lease -> uid_len);
544
		if (status != ISC_R_SUCCESS)
545
			return status;
546
		if (lease -> uid_len) {
547
			status = omapi_connection_copyin (c, lease -> uid,
548
							  lease -> uid_len);
549
			if (status != ISC_R_SUCCESS)
550
				return status;
551
		}
552
	}
553
554
	if (lease -> client_hostname) {
555
		status = omapi_connection_put_name (c, "client-hostname");
556
		if (status != ISC_R_SUCCESS)
557
			return status;
558
		status =
559
			omapi_connection_put_string (c,
560
						     lease -> client_hostname);
561
		if (status != ISC_R_SUCCESS)
562
			return status;
563
	}
564
565
	if (lease -> host) {
566
		status = omapi_connection_put_name (c, "host");
567
		if (status != ISC_R_SUCCESS)
568
			return status;
569
		status = omapi_connection_put_handle (c,
570
						      (omapi_object_t *)
571
						      lease -> host);
572
		if (status != ISC_R_SUCCESS)
573
			return status;
574
	}
575
576
	status = omapi_connection_put_name (c, "subnet");
577
	if (status != ISC_R_SUCCESS)
578
		return status;
579
	status = omapi_connection_put_handle
580
		(c, (omapi_object_t *)lease -> subnet);
581
	if (status != ISC_R_SUCCESS)
582
		return status;
583
584
	status = omapi_connection_put_name (c, "pool");
585
	if (status != ISC_R_SUCCESS)
586
		return status;
587
	status = omapi_connection_put_handle (c,
588
					      (omapi_object_t *)lease -> pool);
589
	if (status != ISC_R_SUCCESS)
590
		return status;
591
592
	if (lease -> billing_class) {
593
		status = omapi_connection_put_name (c, "billing-class");
594
		if (status != ISC_R_SUCCESS)
595
			return status;
596
		status = omapi_connection_put_handle
597
			(c, (omapi_object_t *)lease -> billing_class);
598
		if (status != ISC_R_SUCCESS)
599
			return status;
600
	}
601
602
	if (lease -> hardware_addr.hlen) {
603
		status = omapi_connection_put_name (c, "hardware-address");
604
		if (status != ISC_R_SUCCESS)
605
			return status;
606
		status = (omapi_connection_put_uint32
607
			  (c,
608
			   (unsigned long)(lease -> hardware_addr.hlen - 1)));
609
		if (status != ISC_R_SUCCESS)
610
			return status;
611
		status = (omapi_connection_copyin
612
			  (c, &lease -> hardware_addr.hbuf [1],
613
			   (unsigned long)(lease -> hardware_addr.hlen - 1)));
614
615
		if (status != ISC_R_SUCCESS)
616
			return status;
617
618
		status = omapi_connection_put_name (c, "hardware-type");
619
		if (status != ISC_R_SUCCESS)
620
			return status;
621
		status = omapi_connection_put_uint32 (c, sizeof (int));
622
		if (status != ISC_R_SUCCESS)
623
			return status;
624
		status = omapi_connection_put_uint32
625
			(c, lease -> hardware_addr.hbuf [0]);
626
		if (status != ISC_R_SUCCESS)
627
			return status;
628
	}
629
630
	/* TIME values may be 64-bit, depending on system architecture.
631
	 * OMAPI must be system independent, both in terms of transmitting
632
	 * bytes on the wire in network byte order, and in terms of being
633
	 * readable and usable by both systems.
634
	 *
635
	 * XXX: In a future feature release, a put_int64() should be made
636
	 * to exist, and perhaps a put_time() wrapper that selects which
637
	 * to use based upon sizeof(TIME).  In the meantime, use existing,
638
	 * 32-bit, code.
639
	 */
640
	bouncer = (u_int32_t)lease->ends;
641
	status = omapi_connection_put_name(c, "ends");
642
	if (status != ISC_R_SUCCESS)
643
		return status;
644
	status = omapi_connection_put_uint32(c, sizeof(bouncer));
645
	if (status != ISC_R_SUCCESS)
646
		return status;
647
	status = omapi_connection_put_uint32(c, bouncer);
648
	if (status != ISC_R_SUCCESS)
649
		return status;
650
651
	bouncer = (u_int32_t)lease->starts;
652
	status = omapi_connection_put_name(c, "starts");
653
	if (status != ISC_R_SUCCESS)
654
		return status;
655
	status = omapi_connection_put_uint32(c, sizeof(bouncer));
656
	if (status != ISC_R_SUCCESS)
657
		return status;
658
	status = omapi_connection_put_uint32(c, bouncer);
659
	if (status != ISC_R_SUCCESS)
660
		return status;
661
662
	bouncer = (u_int32_t)lease->tstp;
663
	status = omapi_connection_put_name(c, "tstp");
664
	if (status != ISC_R_SUCCESS)
665
		return status;
666
	status = omapi_connection_put_uint32(c, sizeof(bouncer));
667
	if (status != ISC_R_SUCCESS)
668
		return status;
669
	status = omapi_connection_put_uint32(c, bouncer);
670
	if (status != ISC_R_SUCCESS)
671
		return status;
672
673
	bouncer = (u_int32_t)lease->tsfp;
674
	status = omapi_connection_put_name(c, "tsfp");
675
	if (status != ISC_R_SUCCESS)
676
		return status;
677
	status = omapi_connection_put_uint32(c, sizeof(bouncer));
678
	if (status != ISC_R_SUCCESS)
679
		return status;
680
	status = omapi_connection_put_uint32(c, bouncer);
681
	if (status != ISC_R_SUCCESS)
682
		return status;
683
684
	bouncer = (u_int32_t)lease->atsfp;
685
	status = omapi_connection_put_name(c, "atsfp");
686
	if (status != ISC_R_SUCCESS)
687
		return status;
688
	status = omapi_connection_put_uint32(c, sizeof(bouncer));
689
	if (status != ISC_R_SUCCESS)
690
		return status;
691
	status = omapi_connection_put_uint32(c, bouncer);
692
	if (status != ISC_R_SUCCESS)
693
		return status;
694
695
	bouncer = (u_int32_t)lease->cltt;
696
	status = omapi_connection_put_name(c, "cltt");
697
	if (status != ISC_R_SUCCESS)
698
		return status;
699
	status = omapi_connection_put_uint32(c, sizeof(bouncer));
700
	if (status != ISC_R_SUCCESS)
701
		return status;
702
	status = omapi_connection_put_uint32(c, bouncer);
703
	if (status != ISC_R_SUCCESS)
704
		return status;
705
706
	status = omapi_connection_put_name (c, "flags");
707
	if (status != ISC_R_SUCCESS)
708
		return status;
709
	status = omapi_connection_put_uint32(c, sizeof(flagbuf));
710
	if (status != ISC_R_SUCCESS)
711
		return status;
712
	flagbuf = lease->flags & EPHEMERAL_FLAGS;
713
	status = omapi_connection_copyin(c, &flagbuf, sizeof(flagbuf));
714
	if (status != ISC_R_SUCCESS)
715
		return status;
716
717
	if (lease -> scope) {
718
		status = binding_scope_stuff_values (c, lease -> scope);
719
		if (status != ISC_R_SUCCESS)
720
			return status;
721
	}
722
723
	/* Write out the inner object, if any. */
724
	if (h -> inner && h -> inner -> type -> stuff_values) {
725
		status = ((*(h -> inner -> type -> stuff_values))
726
			  (c, id, h -> inner));
727
		if (status == ISC_R_SUCCESS)
728
			return status;
729
	}
730
731
	return ISC_R_SUCCESS;
732
}
733
734
isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
735
				omapi_object_t *id, omapi_object_t *ref)
736
{
737
	omapi_value_t *tv = (omapi_value_t *)0;
738
	isc_result_t status;
739
	struct lease *lease;
740
741
	if (!ref)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
742
		return DHCP_R_NOKEYS;
1 by Andrew Pollock
Import upstream version 4.1.0
743
744
	/* First see if we were sent a handle. */
745
	status = omapi_get_value_str (ref, id, "handle", &tv);
746
	if (status == ISC_R_SUCCESS) {
747
		status = omapi_handle_td_lookup (lp, tv -> value);
748
749
		omapi_value_dereference (&tv, MDL);
750
		if (status != ISC_R_SUCCESS)
751
			return status;
752
753
		/* Don't return the object if the type is wrong. */
754
		if ((*lp) -> type != dhcp_type_lease) {
755
			omapi_object_dereference (lp, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
756
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
757
		}
758
	}
759
760
	/* Now look for an IP address. */
761
	status = omapi_get_value_str (ref, id, "ip-address", &tv);
762
	if (status == ISC_R_SUCCESS) {
763
		lease = (struct lease *)0;
764
		lease_ip_hash_lookup(&lease, lease_ip_addr_hash,
765
				     tv->value->u.buffer.value,
766
				     tv->value->u.buffer.len, MDL);
767
768
		omapi_value_dereference (&tv, MDL);
769
770
		/* If we already have a lease, and it's not the same one,
771
		   then the query was invalid. */
772
		if (*lp && *lp != (omapi_object_t *)lease) {
773
			omapi_object_dereference (lp, MDL);
774
			lease_dereference (&lease, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
775
			return DHCP_R_KEYCONFLICT;
1 by Andrew Pollock
Import upstream version 4.1.0
776
		} else if (!lease) {
777
			if (*lp)
778
				omapi_object_dereference (lp, MDL);
779
			return ISC_R_NOTFOUND;
780
		} else if (!*lp) {
781
			/* XXX fix so that hash lookup itself creates
782
			   XXX the reference. */
783
			omapi_object_reference (lp,
784
						(omapi_object_t *)lease, MDL);
785
			lease_dereference (&lease, MDL);
786
		}
787
	}
788
789
	/* Now look for a client identifier. */
790
	status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
791
	if (status == ISC_R_SUCCESS) {
792
		lease = (struct lease *)0;
793
		lease_id_hash_lookup(&lease, lease_uid_hash,
794
				     tv->value->u.buffer.value,
795
				     tv->value->u.buffer.len, MDL);
796
		omapi_value_dereference (&tv, MDL);
797
			
798
		if (*lp && *lp != (omapi_object_t *)lease) {
799
			omapi_object_dereference (lp, MDL);
800
			lease_dereference (&lease, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
801
			return DHCP_R_KEYCONFLICT;
1 by Andrew Pollock
Import upstream version 4.1.0
802
		} else if (!lease) {
803
			if (*lp)
804
			    omapi_object_dereference (lp, MDL);
805
			return ISC_R_NOTFOUND;
806
		} else if (lease -> n_uid) {
807
			if (*lp)
808
			    omapi_object_dereference (lp, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
809
			return DHCP_R_MULTIPLE;
1 by Andrew Pollock
Import upstream version 4.1.0
810
		} else if (!*lp) {
811
			/* XXX fix so that hash lookup itself creates
812
			   XXX the reference. */
813
			omapi_object_reference (lp,
814
						(omapi_object_t *)lease, MDL);
815
			lease_dereference (&lease, MDL);
816
		}
817
	}
818
819
	/* Now look for a hardware address. */
820
	status = omapi_get_value_str (ref, id, "hardware-address", &tv);
821
	if (status == ISC_R_SUCCESS) {
822
		unsigned char *haddr;
823
		unsigned int len;
824
825
		len = tv -> value -> u.buffer.len + 1;
826
		haddr = dmalloc (len, MDL);
827
		if (!haddr) {
828
			omapi_value_dereference (&tv, MDL);
829
			return ISC_R_NOMEMORY;
830
		}
831
832
		memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
833
		omapi_value_dereference (&tv, MDL);
834
835
		status = omapi_get_value_str (ref, id, "hardware-type", &tv);
836
		if (status == ISC_R_SUCCESS) {
837
			if (tv -> value -> type == omapi_datatype_data) {
838
				if ((tv -> value -> u.buffer.len != 4) ||
839
				    (tv -> value -> u.buffer.value[0] != 0) ||
840
				    (tv -> value -> u.buffer.value[1] != 0) ||
841
				    (tv -> value -> u.buffer.value[2] != 0)) {
842
					omapi_value_dereference (&tv, MDL);
843
					dfree (haddr, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
844
					return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
845
				}
846
847
				haddr[0] = tv -> value -> u.buffer.value[3];
848
			} else if (tv -> value -> type == omapi_datatype_int) {
849
				haddr[0] = (unsigned char)
850
					tv -> value -> u.integer;
851
			} else {
852
				omapi_value_dereference (&tv, MDL);
853
				dfree (haddr, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
854
				return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
855
			}
856
857
			omapi_value_dereference (&tv, MDL);
858
		} else {
859
			/* If no hardware-type is specified, default to
860
			   ethernet.  This may or may not be a good idea,
861
			   but Telus is currently relying on this behavior.
862
			   - DPN */
863
			haddr[0] = HTYPE_ETHER;
864
		}
865
866
		lease = (struct lease *)0;
867
		lease_id_hash_lookup(&lease, lease_hw_addr_hash, haddr, len,
868
				     MDL);
869
		dfree (haddr, MDL);
870
871
		if (*lp && *lp != (omapi_object_t *)lease) {
872
			omapi_object_dereference (lp, MDL);
873
			lease_dereference (&lease, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
874
			return DHCP_R_KEYCONFLICT;
1 by Andrew Pollock
Import upstream version 4.1.0
875
		} else if (!lease) {
876
			if (*lp)
877
			    omapi_object_dereference (lp, MDL);
878
			return ISC_R_NOTFOUND;
879
		} else if (lease -> n_hw) {
880
			if (*lp)
881
			    omapi_object_dereference (lp, MDL);
882
			lease_dereference (&lease, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
883
			return DHCP_R_MULTIPLE;
1 by Andrew Pollock
Import upstream version 4.1.0
884
		} else if (!*lp) {
885
			/* XXX fix so that hash lookup itself creates
886
			   XXX the reference. */
887
			omapi_object_reference (lp,
888
						(omapi_object_t *)lease, MDL);
889
			lease_dereference (&lease, MDL);
890
		}
891
	}
892
893
	/* If we get to here without finding a lease, no valid key was
894
	   specified. */
895
	if (!*lp)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
896
		return DHCP_R_NOKEYS;
1 by Andrew Pollock
Import upstream version 4.1.0
897
	return ISC_R_SUCCESS;
898
}
899
900
isc_result_t dhcp_lease_create (omapi_object_t **lp,
901
				omapi_object_t *id)
902
{
903
	return ISC_R_NOTIMPLEMENTED;
904
}
905
906
isc_result_t dhcp_lease_remove (omapi_object_t *lp,
907
				omapi_object_t *id)
908
{
909
	return ISC_R_NOTIMPLEMENTED;
910
}
911
912
isc_result_t dhcp_host_set_value  (omapi_object_t *h,
913
				   omapi_object_t *id,
914
				   omapi_data_string_t *name,
915
				   omapi_typed_data_t *value)
916
{
917
	struct host_decl *host;
918
	isc_result_t status;
919
920
	if (h -> type != dhcp_type_host)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
921
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
922
	host = (struct host_decl *)h;
923
924
	/* XXX For now, we can only set these values on new host objects. 
925
	   XXX Soon, we need to be able to update host objects. */
926
	if (!omapi_ds_strcmp (name, "name")) {
927
		if (host -> name)
928
			return ISC_R_EXISTS;
929
		if (value && (value -> type == omapi_datatype_data ||
930
		    	      value -> type == omapi_datatype_string)) {
931
			host -> name = dmalloc (value -> u.buffer.len + 1,
932
						MDL);
933
			if (!host -> name)
934
				return ISC_R_NOMEMORY;
935
			memcpy (host -> name,
936
				value -> u.buffer.value,
937
				value -> u.buffer.len);
938
			host -> name [value -> u.buffer.len] = 0;
939
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
940
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
941
		return ISC_R_SUCCESS;
942
	}
943
944
	if (!omapi_ds_strcmp (name, "group")) {
945
		if (value && (value -> type == omapi_datatype_data ||
946
		    	      value -> type == omapi_datatype_string)) {
947
			struct group_object *group;
948
			group = (struct group_object *)0;
949
			group_hash_lookup (&group, group_name_hash,
950
					   (char *)value -> u.buffer.value,
951
					   value -> u.buffer.len, MDL);
952
			if (!group || (group -> flags & GROUP_OBJECT_DELETED))
953
				return ISC_R_NOTFOUND;
954
			if (host -> group)
955
				group_dereference (&host -> group, MDL);
956
			group_reference (&host -> group, group -> group, MDL);
957
			if (host -> named_group)
958
				group_object_dereference (&host -> named_group,
959
							  MDL);
960
			group_object_reference (&host -> named_group,
961
						group, MDL);
962
			group_object_dereference (&group, MDL);
963
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
964
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
965
		return ISC_R_SUCCESS;
966
	}
967
968
	if (!omapi_ds_strcmp (name, "hardware-address")) {
969
		if (host -> interface.hlen)
970
			return ISC_R_EXISTS;
971
		if (value && (value -> type == omapi_datatype_data ||
972
		    	      value -> type == omapi_datatype_string)) {
973
			if (value -> u.buffer.len >
974
			    (sizeof host -> interface.hbuf) - 1)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
975
				return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
976
			memcpy (&host -> interface.hbuf [1],
977
				value -> u.buffer.value,
978
				value -> u.buffer.len);
979
			host -> interface.hlen = value -> u.buffer.len + 1;
980
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
981
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
982
		return ISC_R_SUCCESS;
983
	}
984
985
	if (!omapi_ds_strcmp (name, "hardware-type")) {
986
		int type;
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
987
		if ((value != NULL) &&
988
		    ((value->type == omapi_datatype_data) &&
989
		     (value->u.buffer.len == sizeof(type)))) {
990
			if (value->u.buffer.len > sizeof(type))
991
				return (DHCP_R_INVALIDARG);
992
			memcpy(&type, value->u.buffer.value,
993
			       value->u.buffer.len);
994
			type = ntohl(type);
995
		} else if ((value != NULL) &&
996
			   (value->type == omapi_datatype_int))
997
			type = value->u.integer;
1 by Andrew Pollock
Import upstream version 4.1.0
998
		else
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
999
			return (DHCP_R_INVALIDARG);
1000
		host->interface.hbuf[0] = type;
1001
		return (ISC_R_SUCCESS);
1 by Andrew Pollock
Import upstream version 4.1.0
1002
	}
1003
1004
	if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
1005
		if (host -> client_identifier.data)
1006
			return ISC_R_EXISTS;
1007
		if (value && (value -> type == omapi_datatype_data ||
1008
		    	      value -> type == omapi_datatype_string)) {
1009
		    if (!buffer_allocate (&host -> client_identifier.buffer,
1010
					  value -> u.buffer.len, MDL))
1011
			    return ISC_R_NOMEMORY;
1012
		    host -> client_identifier.data =
1013
			    &host -> client_identifier.buffer -> data [0];
1014
		    memcpy (host -> client_identifier.buffer -> data,
1015
			    value -> u.buffer.value,
1016
			    value -> u.buffer.len);
1017
		    host -> client_identifier.len = value -> u.buffer.len;
1018
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1019
		    return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1020
		return ISC_R_SUCCESS;
1021
	}
1022
1023
	if (!omapi_ds_strcmp (name, "ip-address")) {
1024
		if (host -> fixed_addr)
1025
			option_cache_dereference (&host -> fixed_addr, MDL);
1026
		if (!value)
1027
			return ISC_R_SUCCESS;
1028
		if (value && (value -> type == omapi_datatype_data ||
1029
			      value -> type == omapi_datatype_string)) {
1030
			struct data_string ds;
1031
			memset (&ds, 0, sizeof ds);
1032
			ds.len = value -> u.buffer.len;
1033
			if (!buffer_allocate (&ds.buffer, ds.len, MDL))
1034
				return ISC_R_NOMEMORY;
1035
			ds.data = (&ds.buffer -> data [0]);
1036
			memcpy (ds.buffer -> data,
1037
				value -> u.buffer.value, ds.len);
1038
			if (!option_cache (&host -> fixed_addr,
1039
					   &ds, (struct expression *)0,
1040
					   (struct option *)0, MDL)) {
1041
				data_string_forget (&ds, MDL);
1042
				return ISC_R_NOMEMORY;
1043
			}
1044
			data_string_forget (&ds, MDL);
1045
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1046
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1047
		return ISC_R_SUCCESS;
1048
	}
1049
1050
	if (!omapi_ds_strcmp (name, "statements")) {
1051
		if (!host -> group) {
1052
			if (!clone_group (&host -> group, root_group, MDL))
1053
				return ISC_R_NOMEMORY;
1054
		} else {
1055
			if (host -> group -> statements &&
1056
			    (!host -> named_group ||
1057
			     host -> group != host -> named_group -> group) &&
1058
			    host -> group != root_group)
1059
				return ISC_R_EXISTS;
1060
			if (!clone_group (&host -> group, host -> group, MDL))
1061
				return ISC_R_NOMEMORY;
1062
		}
1063
		if (!host -> group)
1064
			return ISC_R_NOMEMORY;
1065
		if (value && (value -> type == omapi_datatype_data ||
1066
			      value -> type == omapi_datatype_string)) {
1067
			struct parse *parse;
1068
			int lose = 0;
1069
			parse = (struct parse *)0;
1070
			status = new_parse(&parse, -1,
1071
					    (char *) value->u.buffer.value,
1072
					    value->u.buffer.len,
1073
					    "network client", 0);
1074
			if (status != ISC_R_SUCCESS || parse == NULL)
1075
				return status;
1076
1077
			if (!(parse_executable_statements
1078
			      (&host -> group -> statements, parse, &lose,
1079
			       context_any))) {
1080
				end_parse (&parse);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1081
				return DHCP_R_BADPARSE;
1 by Andrew Pollock
Import upstream version 4.1.0
1082
			}
1083
			end_parse (&parse);
1084
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1085
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1086
		return ISC_R_SUCCESS;
1087
	}
1088
1089
	/* The "known" flag isn't supported in the database yet, but it's
1090
	   legitimate. */
1091
	if (!omapi_ds_strcmp (name, "known")) {
1092
		return ISC_R_SUCCESS;
1093
	}
1094
1095
	/* Try to find some inner object that can take the value. */
1096
	if (h -> inner && h -> inner -> type -> set_value) {
1097
		status = ((*(h -> inner -> type -> set_value))
1098
			  (h -> inner, id, name, value));
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1099
		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
1 by Andrew Pollock
Import upstream version 4.1.0
1100
			return status;
1101
	}
1102
			  
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1103
	return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
1104
}
1105
1106
1107
isc_result_t dhcp_host_get_value (omapi_object_t *h, omapi_object_t *id,
1108
				   omapi_data_string_t *name,
1109
				   omapi_value_t **value)
1110
{
1111
	struct host_decl *host;
1112
	isc_result_t status;
1113
	struct data_string ip_addrs;
1114
1115
	if (h -> type != dhcp_type_host)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1116
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1117
	host = (struct host_decl *)h;
1118
1119
	if (!omapi_ds_strcmp (name, "ip-addresses")) {
1120
	    memset (&ip_addrs, 0, sizeof ip_addrs);
1121
	    if (host -> fixed_addr &&
1122
		evaluate_option_cache (&ip_addrs, (struct packet *)0,
1123
				       (struct lease *)0,
1124
				       (struct client_state *)0,
1125
				       (struct option_state *)0,
1126
				       (struct option_state *)0,
1127
				       &global_scope,
1128
				       host -> fixed_addr, MDL)) {
1129
		    status = omapi_make_const_value (value, name,
1130
						     ip_addrs.data,
1131
						     ip_addrs.len, MDL);
1132
		    data_string_forget (&ip_addrs, MDL);
1133
		    return status;
1134
	    }
1135
	    return ISC_R_NOTFOUND;
1136
	}
1137
1138
	if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
1139
		if (!host -> client_identifier.len)
1140
			return ISC_R_NOTFOUND;
1141
		return omapi_make_const_value (value, name,
1142
					       host -> client_identifier.data,
1143
					       host -> client_identifier.len,
1144
					       MDL);
1145
	}
1146
1147
	if (!omapi_ds_strcmp (name, "name"))
1148
		return omapi_make_string_value (value, name, host -> name,
1149
						MDL);
1150
1151
	if (!omapi_ds_strcmp (name, "hardware-address")) {
1152
		if (!host -> interface.hlen)
1153
			return ISC_R_NOTFOUND;
1154
		return (omapi_make_const_value
1155
			(value, name, &host -> interface.hbuf [1],
1156
			 (unsigned long)(host -> interface.hlen - 1), MDL));
1157
	}
1158
1159
	if (!omapi_ds_strcmp (name, "hardware-type")) {
1160
		if (!host -> interface.hlen)
1161
			return ISC_R_NOTFOUND;
1162
		return omapi_make_int_value (value, name,
1163
					     host -> interface.hbuf [0], MDL);
1164
	}
1165
1166
	/* Try to find some inner object that can take the value. */
1167
	if (h -> inner && h -> inner -> type -> get_value) {
1168
		status = ((*(h -> inner -> type -> get_value))
1169
			  (h -> inner, id, name, value));
1170
		if (status == ISC_R_SUCCESS)
1171
			return status;
1172
	}
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1173
	return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
1174
}
1175
1176
isc_result_t dhcp_host_destroy (omapi_object_t *h, const char *file, int line)
1177
{
1178
1179
	if (h -> type != dhcp_type_host)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1180
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1181
1182
#if defined (DEBUG_MEMORY_LEAKAGE) || \
1183
		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
1184
	struct host_decl *host = (struct host_decl *)h;
1 by Andrew Pollock
Import upstream version 4.1.0
1185
	if (host -> n_ipaddr)
1186
		host_dereference (&host -> n_ipaddr, file, line);
1187
	if (host -> n_dynamic)
1188
		host_dereference (&host -> n_dynamic, file, line);
1189
	if (host -> name) {
1190
		dfree (host -> name, file, line);
1191
		host -> name = (char *)0;
1192
	}
1193
	data_string_forget (&host -> client_identifier, file, line);
1194
	if (host -> fixed_addr)
1195
		option_cache_dereference (&host -> fixed_addr, file, line);
1196
	if (host -> group)
1197
		group_dereference (&host -> group, file, line);
1198
	if (host -> named_group)
1199
		omapi_object_dereference ((omapi_object_t **)
1200
					  &host -> named_group, file, line);
1201
	data_string_forget (&host -> auth_key_id, file, line);
1202
#endif
1203
1204
	return ISC_R_SUCCESS;
1205
}
1206
1207
isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
1208
				       const char *name, va_list ap)
1209
{
1210
	struct host_decl *host;
1211
	isc_result_t status;
1212
	int updatep = 0;
1213
1214
	if (h -> type != dhcp_type_host)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1215
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1216
	host = (struct host_decl *)h;
1217
1218
	if (!strcmp (name, "updated")) {
1219
		/* There must be a client identifier of some sort. */
1220
		if (host -> interface.hlen == 0 &&
1221
		    !host -> client_identifier.len)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1222
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1223
1224
		if (!host -> name) {
1225
			char hnbuf [64];
1226
			sprintf (hnbuf, "nh%08lx%08lx",
1227
				 (unsigned long)cur_time, (unsigned long)host);
1228
			host -> name = dmalloc (strlen (hnbuf) + 1, MDL);
1229
			if (!host -> name)
1230
				return ISC_R_NOMEMORY;
1231
			strcpy (host -> name, hnbuf);
1232
		}
1233
1234
#ifdef DEBUG_OMAPI
1235
		log_debug ("OMAPI added host %s", host -> name);
1236
#endif
1237
		status = enter_host (host, 1, 1);
1238
		if (status != ISC_R_SUCCESS)
1239
			return status;
1240
		updatep = 1;
1241
	}
1242
1243
	/* Try to find some inner object that can take the value. */
1244
	if (h -> inner && h -> inner -> type -> signal_handler) {
1245
		status = ((*(h -> inner -> type -> signal_handler))
1246
			  (h -> inner, name, ap));
1247
		if (status == ISC_R_SUCCESS)
1248
			return status;
1249
	}
1250
	if (updatep)
1251
		return ISC_R_SUCCESS;
1252
	return ISC_R_NOTFOUND;
1253
}
1254
1255
isc_result_t dhcp_host_stuff_values (omapi_object_t *c,
1256
				      omapi_object_t *id,
1257
				      omapi_object_t *h)
1258
{
1259
	struct host_decl *host;
1260
	isc_result_t status;
1261
	struct data_string ip_addrs;
1262
1263
	if (h -> type != dhcp_type_host)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1264
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1265
	host = (struct host_decl *)h;
1266
1267
	/* Write out all the values. */
1268
1269
	memset (&ip_addrs, 0, sizeof ip_addrs);
1270
	if (host -> fixed_addr &&
1271
	    evaluate_option_cache (&ip_addrs, (struct packet *)0,
1272
				   (struct lease *)0,
1273
				   (struct client_state *)0,
1274
				   (struct option_state *)0,
1275
				   (struct option_state *)0,
1276
				   &global_scope,
1277
				   host -> fixed_addr, MDL)) {
1278
		status = omapi_connection_put_name (c, "ip-address");
1279
		if (status != ISC_R_SUCCESS)
1280
			return status;
1281
		status = omapi_connection_put_uint32 (c, ip_addrs.len);
1282
		if (status != ISC_R_SUCCESS)
1283
			return status;
1284
		status = omapi_connection_copyin (c,
1285
						  ip_addrs.data, ip_addrs.len);
1286
		if (status != ISC_R_SUCCESS)
1287
			return status;
1288
	}
1289
1290
	if (host -> client_identifier.len) {
1291
		status = omapi_connection_put_name (c,
1292
						    "dhcp-client-identifier");
1293
		if (status != ISC_R_SUCCESS)
1294
			return status;
1295
		status = (omapi_connection_put_uint32
1296
			  (c, host -> client_identifier.len));
1297
		if (status != ISC_R_SUCCESS)
1298
			return status;
1299
		status = (omapi_connection_copyin
1300
			  (c,
1301
			   host -> client_identifier.data,
1302
			   host -> client_identifier.len));
1303
		if (status != ISC_R_SUCCESS)
1304
			return status;
1305
	}
1306
1307
	if (host -> name) {
1308
		status = omapi_connection_put_name (c, "name");
1309
		if (status != ISC_R_SUCCESS)
1310
			return status;
1311
		status = omapi_connection_put_string (c, host -> name);
1312
		if (status != ISC_R_SUCCESS)
1313
			return status;
1314
	}
1315
1316
	if (host -> interface.hlen) {
1317
		status = omapi_connection_put_name (c, "hardware-address");
1318
		if (status != ISC_R_SUCCESS)
1319
			return status;
1320
		status = (omapi_connection_put_uint32
1321
			  (c, (unsigned long)(host -> interface.hlen - 1)));
1322
		if (status != ISC_R_SUCCESS)
1323
			return status;
1324
		status = (omapi_connection_copyin
1325
			  (c, &host -> interface.hbuf [1],
1326
			   (unsigned long)(host -> interface.hlen - 1)));
1327
		if (status != ISC_R_SUCCESS)
1328
			return status;
1329
1330
		status = omapi_connection_put_name (c, "hardware-type");
1331
		if (status != ISC_R_SUCCESS)
1332
			return status;
1333
		status = omapi_connection_put_uint32 (c, sizeof (int));
1334
		if (status != ISC_R_SUCCESS)
1335
			return status;
1336
		status = (omapi_connection_put_uint32
1337
			  (c, host -> interface.hbuf [0]));
1338
		if (status != ISC_R_SUCCESS)
1339
			return status;
1340
	}
1341
1342
	/* Write out the inner object, if any. */
1343
	if (h -> inner && h -> inner -> type -> stuff_values) {
1344
		status = ((*(h -> inner -> type -> stuff_values))
1345
			  (c, id, h -> inner));
1346
		if (status == ISC_R_SUCCESS)
1347
			return status;
1348
	}
1349
1350
	return ISC_R_SUCCESS;
1351
}
1352
1353
isc_result_t dhcp_host_lookup (omapi_object_t **lp,
1354
			       omapi_object_t *id, omapi_object_t *ref)
1355
{
1356
	omapi_value_t *tv = (omapi_value_t *)0;
1357
	isc_result_t status;
1358
	struct host_decl *host;
1359
1360
	if (!ref)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1361
		return DHCP_R_NOKEYS;
1 by Andrew Pollock
Import upstream version 4.1.0
1362
1363
	/* First see if we were sent a handle. */
1364
	status = omapi_get_value_str (ref, id, "handle", &tv);
1365
	if (status == ISC_R_SUCCESS) {
1366
		status = omapi_handle_td_lookup (lp, tv -> value);
1367
1368
		omapi_value_dereference (&tv, MDL);
1369
		if (status != ISC_R_SUCCESS)
1370
			return status;
1371
1372
		/* Don't return the object if the type is wrong. */
1373
		if ((*lp) -> type != dhcp_type_host) {
1374
			omapi_object_dereference (lp, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1375
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1376
		}
1377
		if (((struct host_decl *)(*lp)) -> flags & HOST_DECL_DELETED) {
1378
			omapi_object_dereference (lp, MDL);
1379
		}
1380
	}
1381
1382
	/* Now look for a client identifier. */
1383
	status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
1384
	if (status == ISC_R_SUCCESS) {
1385
		host = (struct host_decl *)0;
1386
		host_hash_lookup (&host, host_uid_hash,
1387
				  tv -> value -> u.buffer.value,
1388
				  tv -> value -> u.buffer.len, MDL);
1389
		omapi_value_dereference (&tv, MDL);
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
1390
1 by Andrew Pollock
Import upstream version 4.1.0
1391
		if (*lp && *lp != (omapi_object_t *)host) {
1392
			omapi_object_dereference (lp, MDL);
1393
			if (host)
1394
				host_dereference (&host, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1395
			return DHCP_R_KEYCONFLICT;
1 by Andrew Pollock
Import upstream version 4.1.0
1396
		} else if (!host || (host -> flags & HOST_DECL_DELETED)) {
1397
			if (*lp)
1398
			    omapi_object_dereference (lp, MDL);
1399
			if (host)
1400
				host_dereference (&host, MDL);
1401
			return ISC_R_NOTFOUND;
1402
		} else if (!*lp) {
1403
			/* XXX fix so that hash lookup itself creates
1404
			   XXX the reference. */
1405
			omapi_object_reference (lp,
1406
						(omapi_object_t *)host, MDL);
1407
			host_dereference (&host, MDL);
1408
		}
1409
	}
1410
1411
	/* Now look for a hardware address. */
1412
	status = omapi_get_value_str (ref, id, "hardware-address", &tv);
1413
	if (status == ISC_R_SUCCESS) {
1414
		unsigned char *haddr;
1415
		unsigned int len;
1416
1417
		len = tv -> value -> u.buffer.len + 1;
1418
		haddr = dmalloc (len, MDL);
1419
		if (!haddr) {
1420
			omapi_value_dereference (&tv, MDL);
1421
			return ISC_R_NOMEMORY;
1422
		}
1423
1424
		memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
1425
		omapi_value_dereference (&tv, MDL);
1426
1427
		status = omapi_get_value_str (ref, id, "hardware-type", &tv);
1428
		if (status == ISC_R_SUCCESS) {
1429
			if (tv -> value -> type == omapi_datatype_data) {
1430
				if ((tv -> value -> u.buffer.len != 4) ||
1431
				    (tv -> value -> u.buffer.value[0] != 0) ||
1432
				    (tv -> value -> u.buffer.value[1] != 0) ||
1433
				    (tv -> value -> u.buffer.value[2] != 0)) {
1434
					omapi_value_dereference (&tv, MDL);
1435
					dfree (haddr, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1436
					return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1437
				}
1438
1439
				haddr[0] = tv -> value -> u.buffer.value[3];
1440
			} else if (tv -> value -> type == omapi_datatype_int) {
1441
				haddr[0] = (unsigned char)
1442
					tv -> value -> u.integer;
1443
			} else {
1444
				omapi_value_dereference (&tv, MDL);
1445
				dfree (haddr, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1446
				return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1447
			}
1448
1449
			omapi_value_dereference (&tv, MDL);
1450
		} else {
1451
			/* If no hardware-type is specified, default to
1452
			   ethernet.  This may or may not be a good idea,
1453
			   but Telus is currently relying on this behavior.
1454
			   - DPN */
1455
			haddr[0] = HTYPE_ETHER;
1456
		}
1457
1458
		host = (struct host_decl *)0;
1459
		host_hash_lookup (&host, host_hw_addr_hash, haddr, len, MDL);
1460
		dfree (haddr, MDL);
1461
			
1462
		if (*lp && *lp != (omapi_object_t *)host) {
1463
			omapi_object_dereference (lp, MDL);
1464
			if (host)
1465
				host_dereference (&host, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1466
			return DHCP_R_KEYCONFLICT;
1 by Andrew Pollock
Import upstream version 4.1.0
1467
		} else if (!host || (host -> flags & HOST_DECL_DELETED)) {
1468
			if (*lp)
1469
			    omapi_object_dereference (lp, MDL);
1470
			if (host)
1471
				host_dereference (&host, MDL);
1472
			return ISC_R_NOTFOUND;
1473
		} else if (!*lp) {
1474
			/* XXX fix so that hash lookup itself creates
1475
			   XXX the reference. */
1476
			omapi_object_reference (lp,
1477
						(omapi_object_t *)host, MDL);
1478
			host_dereference (&host, MDL);
1479
		}
1480
	}
1481
1482
	/* Now look for an ip address. */
1483
	status = omapi_get_value_str (ref, id, "ip-address", &tv);
1484
	if (status == ISC_R_SUCCESS) {
1485
		struct lease *l;
1486
1487
		/* first find the lease for this ip address */
1488
		l = (struct lease *)0;
1489
		lease_ip_hash_lookup(&l, lease_ip_addr_hash,
1490
				     tv->value->u.buffer.value,
1491
				     tv->value->u.buffer.len, MDL);
1492
		omapi_value_dereference (&tv, MDL);
1493
1494
		if (!l && !*lp)
1495
			return ISC_R_NOTFOUND;
1496
1497
		if (l) {
1498
			/* now use that to get a host */
1499
			host = (struct host_decl *)0;
1500
			host_hash_lookup (&host, host_hw_addr_hash,
1501
					  l -> hardware_addr.hbuf,
1502
					  l -> hardware_addr.hlen, MDL);
1503
			
1504
			if (host && *lp && *lp != (omapi_object_t *)host) {
1505
			    omapi_object_dereference (lp, MDL);
1506
			    if (host)
1507
				host_dereference (&host, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1508
			    return DHCP_R_KEYCONFLICT;
1 by Andrew Pollock
Import upstream version 4.1.0
1509
			} else if (!host || (host -> flags &
1510
					     HOST_DECL_DELETED)) {
1511
			    if (host)
1512
				host_dereference (&host, MDL);
1513
			    if (!*lp)
1514
				    return ISC_R_NOTFOUND;
1515
			} else if (!*lp) {
1516
				/* XXX fix so that hash lookup itself creates
1517
				   XXX the reference. */
1518
			    omapi_object_reference (lp, (omapi_object_t *)host,
1519
						    MDL);
1520
			    host_dereference (&host, MDL);
1521
			}
1522
			lease_dereference (&l, MDL);
1523
		}
1524
	}
1525
1526
	/* Now look for a name. */
1527
	status = omapi_get_value_str (ref, id, "name", &tv);
1528
	if (status == ISC_R_SUCCESS) {
1529
		host = (struct host_decl *)0;
1530
		host_hash_lookup (&host, host_name_hash,
1531
				  tv -> value -> u.buffer.value,
1532
				  tv -> value -> u.buffer.len, MDL);
1533
		omapi_value_dereference (&tv, MDL);
1534
			
1535
		if (*lp && *lp != (omapi_object_t *)host) {
1536
			omapi_object_dereference (lp, MDL);
1537
			if (host)
1538
			    host_dereference (&host, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1539
			return DHCP_R_KEYCONFLICT;
1 by Andrew Pollock
Import upstream version 4.1.0
1540
		} else if (!host || (host -> flags & HOST_DECL_DELETED)) {
1541
			if (host)
1542
			    host_dereference (&host, MDL);
1543
			return ISC_R_NOTFOUND;	
1544
		} else if (!*lp) {
1545
			/* XXX fix so that hash lookup itself creates
1546
			   XXX the reference. */
1547
			omapi_object_reference (lp,
1548
						(omapi_object_t *)host, MDL);
1549
			host_dereference (&host, MDL);
1550
		}
1551
	}
1552
1553
	/* If we get to here without finding a host, no valid key was
1554
	   specified. */
1555
	if (!*lp)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1556
		return DHCP_R_NOKEYS;
1 by Andrew Pollock
Import upstream version 4.1.0
1557
	return ISC_R_SUCCESS;
1558
}
1559
1560
isc_result_t dhcp_host_create (omapi_object_t **lp,
1561
			       omapi_object_t *id)
1562
{
1563
	struct host_decl *hp;
1564
	isc_result_t status;
1565
	hp = (struct host_decl *)0;
1566
	status = host_allocate (&hp, MDL);
1567
	if (status != ISC_R_SUCCESS)
1568
		return status;
1569
	group_reference (&hp -> group, root_group, MDL);
1570
	hp -> flags = HOST_DECL_DYNAMIC;
1571
	status = omapi_object_reference (lp, (omapi_object_t *)hp, MDL);
1572
	host_dereference (&hp, MDL);
1573
	return status;
1574
}
1575
1576
isc_result_t dhcp_host_remove (omapi_object_t *lp,
1577
			       omapi_object_t *id)
1578
{
1579
	struct host_decl *hp;
1580
	if (lp -> type != dhcp_type_host)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1581
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1582
	hp = (struct host_decl *)lp;
1583
1584
#ifdef DEBUG_OMAPI
1585
	log_debug ("OMAPI delete host %s", hp -> name);
1586
#endif
1587
	delete_host (hp, 1);
1588
	return ISC_R_SUCCESS;
1589
}
1590
1591
isc_result_t dhcp_pool_set_value  (omapi_object_t *h,
1592
				   omapi_object_t *id,
1593
				   omapi_data_string_t *name,
1594
				   omapi_typed_data_t *value)
1595
{
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
1596
	/* h should point to (struct pool *) */
1 by Andrew Pollock
Import upstream version 4.1.0
1597
	isc_result_t status;
1598
1599
	if (h -> type != dhcp_type_pool)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1600
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1601
1602
	/* No values to set yet. */
1603
1604
	/* Try to find some inner object that can take the value. */
1605
	if (h -> inner && h -> inner -> type -> set_value) {
1606
		status = ((*(h -> inner -> type -> set_value))
1607
			  (h -> inner, id, name, value));
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1608
		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
1 by Andrew Pollock
Import upstream version 4.1.0
1609
			return status;
1610
	}
1611
			  
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1612
	return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
1613
}
1614
1615
1616
isc_result_t dhcp_pool_get_value (omapi_object_t *h, omapi_object_t *id,
1617
				  omapi_data_string_t *name,
1618
				  omapi_value_t **value)
1619
{
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
1620
	/* h should point to (struct pool *) */
1 by Andrew Pollock
Import upstream version 4.1.0
1621
	isc_result_t status;
1622
1623
	if (h -> type != dhcp_type_pool)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1624
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1625
1626
	/* No values to get yet. */
1627
1628
	/* Try to find some inner object that can provide the value. */
1629
	if (h -> inner && h -> inner -> type -> get_value) {
1630
		status = ((*(h -> inner -> type -> get_value))
1631
			  (h -> inner, id, name, value));
1632
		if (status == ISC_R_SUCCESS)
1633
			return status;
1634
	}
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1635
	return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
1636
}
1637
1638
isc_result_t dhcp_pool_destroy (omapi_object_t *h, const char *file, int line)
1639
{
1640
#if defined (DEBUG_MEMORY_LEAKAGE) || \
1641
		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1642
	struct permit *pc, *pn;
1643
#endif
1644
1645
	if (h -> type != dhcp_type_pool)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1646
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1647
1648
#if defined (DEBUG_MEMORY_LEAKAGE) || \
1649
		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
1650
	struct pool *pool = (struct pool *)h;
1 by Andrew Pollock
Import upstream version 4.1.0
1651
	if (pool -> next)
1652
		pool_dereference (&pool -> next, file, line);
1653
	if (pool -> group)
1654
		group_dereference (&pool -> group, file, line);
1655
	if (pool -> shared_network)
1656
	    shared_network_dereference (&pool -> shared_network, file, line);
1657
	if (pool -> active)
1658
		lease_dereference (&pool -> active, file, line);
1659
	if (pool -> expired)
1660
		lease_dereference (&pool -> expired, file, line);
1661
	if (pool -> free)
1662
		lease_dereference (&pool -> free, file, line);
1663
	if (pool -> backup)
1664
		lease_dereference (&pool -> backup, file, line);
1665
	if (pool -> abandoned)
1666
		lease_dereference (&pool -> abandoned, file, line);
1667
#if defined (FAILOVER_PROTOCOL)
1668
	if (pool -> failover_peer)
1669
		dhcp_failover_state_dereference (&pool -> failover_peer,
1670
						 file, line);
1671
#endif
1672
	for (pc = pool -> permit_list; pc; pc = pn) {
1673
		pn = pc -> next;
1674
		free_permit (pc, file, line);
1675
	}
1676
	pool -> permit_list = (struct permit *)0;
1677
1678
	for (pc = pool -> prohibit_list; pc; pc = pn) {
1679
		pn = pc -> next;
1680
		free_permit (pc, file, line);
1681
	}
1682
	pool -> prohibit_list = (struct permit *)0;
1683
#endif
1684
1685
	return ISC_R_SUCCESS;
1686
}
1687
1688
isc_result_t dhcp_pool_signal_handler (omapi_object_t *h,
1689
				       const char *name, va_list ap)
1690
{
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
1691
	/* h should point to (struct pool *) */
1 by Andrew Pollock
Import upstream version 4.1.0
1692
	isc_result_t status;
1693
	int updatep = 0;
1694
1695
	if (h -> type != dhcp_type_pool)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1696
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1697
1698
	/* Can't write pools yet. */
1699
1700
	/* Try to find some inner object that can take the value. */
1701
	if (h -> inner && h -> inner -> type -> signal_handler) {
1702
		status = ((*(h -> inner -> type -> signal_handler))
1703
			  (h -> inner, name, ap));
1704
		if (status == ISC_R_SUCCESS)
1705
			return status;
1706
	}
1707
	if (updatep)
1708
		return ISC_R_SUCCESS;
1709
	return ISC_R_NOTFOUND;
1710
}
1711
1712
isc_result_t dhcp_pool_stuff_values (omapi_object_t *c,
1713
				     omapi_object_t *id,
1714
				     omapi_object_t *h)
1715
{
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
1716
	/* h should point to (struct pool *) */
1 by Andrew Pollock
Import upstream version 4.1.0
1717
	isc_result_t status;
1718
1719
	if (h -> type != dhcp_type_pool)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1720
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1721
1722
	/* Can't stuff pool values yet. */
1723
1724
	/* Write out the inner object, if any. */
1725
	if (h -> inner && h -> inner -> type -> stuff_values) {
1726
		status = ((*(h -> inner -> type -> stuff_values))
1727
			  (c, id, h -> inner));
1728
		if (status == ISC_R_SUCCESS)
1729
			return status;
1730
	}
1731
1732
	return ISC_R_SUCCESS;
1733
}
1734
1735
isc_result_t dhcp_pool_lookup (omapi_object_t **lp,
1736
			       omapi_object_t *id, omapi_object_t *ref)
1737
{
1738
	/* Can't look up pools yet. */
1739
1740
	/* If we get to here without finding a pool, no valid key was
1741
	   specified. */
1742
	if (!*lp)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1743
		return DHCP_R_NOKEYS;
1 by Andrew Pollock
Import upstream version 4.1.0
1744
	return ISC_R_SUCCESS;
1745
}
1746
1747
isc_result_t dhcp_pool_create (omapi_object_t **lp,
1748
			       omapi_object_t *id)
1749
{
1750
	return ISC_R_NOTIMPLEMENTED;
1751
}
1752
1753
isc_result_t dhcp_pool_remove (omapi_object_t *lp,
1754
			       omapi_object_t *id)
1755
{
1756
	return ISC_R_NOTIMPLEMENTED;
1757
}
1758
1759
static isc_result_t
1760
class_set_value (omapi_object_t *h,
1761
		 omapi_object_t *id,
1762
		 omapi_data_string_t *name,
1763
		 omapi_typed_data_t *value)
1764
{
1765
	struct class *class;
1766
	struct class *superclass = 0;
1767
	isc_result_t status;
1768
	int issubclass = (h -> type == dhcp_type_subclass);
1769
1770
	class = (struct class *)h;
1771
1772
	if (!omapi_ds_strcmp(name, "name")) {
1773
		char *tname;
1774
1775
		if (class->name)
1776
			return ISC_R_EXISTS;
1777
1778
		if ((tname = dmalloc(value->u.buffer.len + 1, MDL)) == NULL) {
1779
			return ISC_R_NOMEMORY;
1780
		}
1781
1782
		/* tname is null terminated from dmalloc() */
1783
		memcpy(tname, value->u.buffer.value, value->u.buffer.len);
1784
1785
		if (issubclass) {
1786
			status = find_class(&superclass, tname, MDL);
1787
			dfree(tname, MDL);
1788
1789
			if (status == ISC_R_NOTFOUND)
1790
				return status;
1791
1792
			if (class->superclass != NULL)
1793
				class_dereference(&class->superclass, MDL);
1794
1795
			class_reference(&class->superclass, superclass, MDL);
1796
		} else if (value -> type == omapi_datatype_data ||
1797
			   value -> type == omapi_datatype_string) {
1798
			class->name = dmalloc(value->u.buffer.len + 1, MDL);
1799
			if (!class->name)
1800
				return ISC_R_NOMEMORY;
1801
1802
			/* class->name is null-terminated from dmalloc() */
1803
			memcpy(class->name, value->u.buffer.value,
1804
			       value->u.buffer.len);
1805
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1806
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1807
1808
		return ISC_R_SUCCESS;
1809
	}
1810
1811
1812
	if (issubclass && !omapi_ds_strcmp(name, "hashstring")) {
1813
		if (class->hash_string.data)
1814
			return ISC_R_EXISTS;
1815
1816
		if (value->type == omapi_datatype_data ||
1817
		    value->type == omapi_datatype_string) {
1818
			if (!buffer_allocate(&class->hash_string.buffer,
1819
					     value->u.buffer.len, MDL))
1820
				return ISC_R_NOMEMORY;
1821
			class->hash_string.data =
1822
					class->hash_string.buffer->data;
1823
			memcpy(class->hash_string.buffer->data,
1824
			       value->u.buffer.value, value->u.buffer.len);
1825
			class->hash_string.len = value->u.buffer.len;
1826
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1827
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1828
1829
		return ISC_R_SUCCESS;
1830
	}
1831
1832
	if (!omapi_ds_strcmp(name, "group")) {
1833
		if (value->type == omapi_datatype_data ||
1834
		    value->type == omapi_datatype_string) {
1835
			struct group_object *group = NULL;
1836
1837
			group_hash_lookup(&group, group_name_hash,
1838
					  (char *)value->u.buffer.value,
1839
					  value->u.buffer.len, MDL);
1840
			if (!group || (group->flags & GROUP_OBJECT_DELETED))
1841
				return ISC_R_NOTFOUND;
1842
			if (class->group)
1843
				group_dereference(&class->group, MDL);
1844
			group_reference(&class->group, group->group, MDL);
1845
			group_object_dereference(&group, MDL);
1846
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1847
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1848
1849
		return ISC_R_SUCCESS;
1850
	}
1851
1852
1853
	/* note we do not support full expressions via omapi because the
1854
	   expressions parser needs to be re-done to support parsing from
1855
	   strings and not just files. */
1856
1857
	if (!omapi_ds_strcmp(name, "match")) {
1858
		if (value->type == omapi_datatype_data ||
1859
		    value->type == omapi_datatype_string) {
1860
			unsigned minlen = (value->u.buffer.len > 8 ?
1861
						8 : value->u.buffer.len);
1862
1863
			if (!strncmp("hardware",
1864
				     (char *)value->u.buffer.value, minlen))
1865
			{
1866
				if (!expression_allocate(&class->submatch, MDL))
1867
					return ISC_R_NOMEMORY;
1868
1869
				class->submatch->op = expr_hardware;
1870
			} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1871
				return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1872
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1873
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1874
1875
		return ISC_R_SUCCESS;
1876
	}
1877
1878
1879
	if (!omapi_ds_strcmp(name, "option")) {
1880
		if (value->type == omapi_datatype_data ||
1881
		    value->type == omapi_datatype_string) {
1882
			/* XXXJAB support 'options' here. */
1883
			/* XXXJAB specifically 'bootfile-name' */
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1884
			return DHCP_R_INVALIDARG; /* XXX tmp */
1 by Andrew Pollock
Import upstream version 4.1.0
1885
		} else
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1886
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1887
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1888
		/* 
1889
		 * Currently no way to get here, if we update the above
1890
		 * code so that we do get here this return needs to be
1891
		 * uncommented.
1892
		 * return ISC_R_SUCCESS;
1893
		 */
1 by Andrew Pollock
Import upstream version 4.1.0
1894
	}
1895
1896
1897
	/* Try to find some inner object that can take the value. */
1898
	if (h->inner && h->inner->type->set_value) {
1899
		status = ((*(h->inner->type->set_value))
1900
			  (h->inner, id, name, value));
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1901
		if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
1 by Andrew Pollock
Import upstream version 4.1.0
1902
			return status;
1903
	}
1904
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1905
	return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
1906
}
1907
1908
1909
1910
isc_result_t dhcp_class_set_value  (omapi_object_t *h,
1911
				    omapi_object_t *id,
1912
				    omapi_data_string_t *name,
1913
				    omapi_typed_data_t *value)
1914
{
1915
	if (h -> type != dhcp_type_class)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1916
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1917
1918
	return class_set_value(h, id, name, value);
1919
}
1920
1921
isc_result_t dhcp_class_get_value (omapi_object_t *h, omapi_object_t *id,
1922
				   omapi_data_string_t *name,
1923
				   omapi_value_t **value)
1924
{
1925
	struct class *class;
1926
	isc_result_t status;
1927
1928
	if (h -> type != dhcp_type_class)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1929
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1930
	class = (struct class *)h;
1931
1932
	if (!omapi_ds_strcmp (name, "name"))
1933
		return omapi_make_string_value (value, name, class -> name,
1934
						MDL);
1935
1936
	/* Try to find some inner object that can provide the value. */
1937
	if (h -> inner && h -> inner -> type -> get_value) {
1938
		status = ((*(h -> inner -> type -> get_value))
1939
			  (h -> inner, id, name, value));
1940
		if (status == ISC_R_SUCCESS)
1941
			return status;
1942
	}
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1943
	return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
1944
}
1945
1946
isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
1947
{
1948
1949
	if (h -> type != dhcp_type_class && h -> type != dhcp_type_subclass)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
1950
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
1951
1952
#if defined (DEBUG_MEMORY_LEAKAGE) || \
1953
		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
1954
	struct class *class = (struct class *)h;
1 by Andrew Pollock
Import upstream version 4.1.0
1955
	if (class -> nic)
1956
		class_dereference (&class -> nic, file, line);
1957
	if (class -> superclass)
1958
		class_dereference (&class -> superclass, file, line);
1959
	if (class -> name) {
1960
		dfree (class -> name, file, line);
1961
		class -> name = (char *)0;
1962
	}
1963
	if (class -> billed_leases) {
1964
		int i;
1965
		for (i = 0; i < class -> lease_limit; i++) {
1966
			if (class -> billed_leases [i]) {
1967
				lease_dereference (&class -> billed_leases [i],
1968
						   file, line);
1969
			}
1970
		}
1971
		dfree (class -> billed_leases, file, line);
1972
		class -> billed_leases = (struct lease **)0;
1973
	}
1974
	if (class -> hash) {
1975
		class_free_hash_table (&class -> hash, file, line);
1976
		class -> hash = (class_hash_t *)0;
1977
	}
1978
	data_string_forget (&class -> hash_string, file, line);
1979
1980
	if (class -> expr)
1981
		expression_dereference (&class -> expr, file, line);
1982
	if (class -> submatch)
1983
		expression_dereference (&class -> submatch, file, line);
1984
	if (class -> group)
1985
		group_dereference (&class -> group, file, line);
1986
	if (class -> statements)
1987
		executable_statement_dereference (&class -> statements,
1988
						  file, line);
1989
	if (class -> superclass)
1990
		class_dereference (&class -> superclass, file, line);
1991
#endif
1992
1993
	return ISC_R_SUCCESS;
1994
}
1995
1996
static isc_result_t
1997
class_signal_handler(omapi_object_t *h,
1998
		     const char *name, va_list ap)
1999
{
2000
	struct class *class = (struct class *)h;
2001
	isc_result_t status;
2002
	int updatep = 0;
2003
	int issubclass;
2004
2005
	issubclass = (h -> type == dhcp_type_subclass);
2006
2007
	if (!strcmp (name, "updated")) {
2008
		
2009
		if (!issubclass) {
2010
			if (class -> name == 0 || strlen(class -> name) == 0) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2011
				return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2012
			}
2013
		} else {
2014
			if (class -> superclass == 0) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2015
				return DHCP_R_INVALIDARG; /* didn't give name */
1 by Andrew Pollock
Import upstream version 4.1.0
2016
			}
2017
2018
			if (class -> hash_string.data == NULL) {
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2019
				return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2020
			}
2021
		}
2022
2023
2024
		if (issubclass) {
2025
			if (!class -> superclass -> hash)
2026
				class_new_hash(&class->superclass->hash,
2027
					       SCLASS_HASH_SIZE, MDL);
2028
2029
			add_hash (class -> superclass -> hash,
2030
				  class -> hash_string.data,
2031
				  class -> hash_string.len,
2032
				  (void *)class, MDL);
2033
		}
2034
			
2035
		
2036
#ifdef DEBUG_OMAPI
2037
		if (issubclass) {
2038
			log_debug ("OMAPI added subclass %s",
2039
				   class -> superclass -> name);
2040
		} else {
2041
			log_debug ("OMAPI added class %s", class -> name);
2042
		}
2043
#endif
2044
		
2045
		status = enter_class (class, 1, 1);
2046
		if (status != ISC_R_SUCCESS)
2047
			return status;
2048
		updatep = 1;
2049
	}
2050
2051
	/* Try to find some inner object that can take the value. */
2052
	if (h -> inner && h -> inner -> type -> signal_handler) {
2053
		status = ((*(h -> inner -> type -> signal_handler))
2054
			  (h -> inner, name, ap));
2055
		if (status == ISC_R_SUCCESS)
2056
			return status;
2057
	}
2058
2059
	if (updatep)
2060
		return ISC_R_SUCCESS;
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
2061
1 by Andrew Pollock
Import upstream version 4.1.0
2062
	return ISC_R_NOTFOUND;
2063
}
2064
2065
2066
isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
2067
					const char *name, va_list ap)
2068
{
2069
	if (h -> type != dhcp_type_class)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2070
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2071
2072
	return class_signal_handler(h, name, ap);
2073
}
2074
2075
isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
2076
				      omapi_object_t *id,
2077
				      omapi_object_t *h)
2078
{
1.2.3 by Andrew Pollock
Import upstream version 4.2.4
2079
	/* h should point to (struct class *) */
1 by Andrew Pollock
Import upstream version 4.1.0
2080
	isc_result_t status;
2081
2082
	if (h -> type != dhcp_type_class)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2083
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2084
2085
	/* Can't stuff class values yet. */
2086
2087
	/* Write out the inner object, if any. */
2088
	if (h -> inner && h -> inner -> type -> stuff_values) {
2089
		status = ((*(h -> inner -> type -> stuff_values))
2090
			  (c, id, h -> inner));
2091
		if (status == ISC_R_SUCCESS)
2092
			return status;
2093
	}
2094
2095
	return ISC_R_SUCCESS;
2096
}
2097
2098
static isc_result_t class_lookup (omapi_object_t **lp,
2099
				  omapi_object_t *id, omapi_object_t *ref,
2100
				  omapi_object_type_t *typewanted)
2101
{
2102
	omapi_value_t *nv = (omapi_value_t *)0;
2103
	omapi_value_t *hv = (omapi_value_t *)0;
2104
	isc_result_t status;
2105
	struct class *class = 0;
2106
	struct class *subclass = 0;
2107
2108
	*lp = NULL;
2109
	
2110
	/* see if we have a name */
2111
	status = omapi_get_value_str (ref, id, "name", &nv);
2112
	if (status == ISC_R_SUCCESS) {
2113
		char *name = dmalloc(nv -> value -> u.buffer.len + 1, MDL);
2114
		memcpy (name,
2115
			nv -> value -> u.buffer.value,
2116
			nv -> value -> u.buffer.len);
2117
2118
		omapi_value_dereference (&nv, MDL);
2119
2120
		find_class(&class, name, MDL);
2121
2122
		dfree(name, MDL);
2123
		
2124
		if (class == NULL) {
2125
			return ISC_R_NOTFOUND;
2126
		}
2127
2128
		if (typewanted == dhcp_type_subclass) {
2129
			status = omapi_get_value_str (ref, id,
2130
						      "hashstring", &hv);
2131
			if (status != ISC_R_SUCCESS) {
2132
				class_dereference(&class, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2133
				return DHCP_R_NOKEYS;
1 by Andrew Pollock
Import upstream version 4.1.0
2134
			}
2135
2136
			if (hv -> value -> type != omapi_datatype_data &&
2137
			    hv -> value -> type != omapi_datatype_string) {
2138
				class_dereference(&class, MDL);
2139
				omapi_value_dereference (&hv, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2140
				return DHCP_R_NOKEYS;
1 by Andrew Pollock
Import upstream version 4.1.0
2141
			}
2142
			
2143
			class_hash_lookup (&subclass, class -> hash,
2144
					   (const char *)
2145
					   hv -> value -> u.buffer.value,
2146
					   hv -> value -> u.buffer.len, MDL);
2147
			
2148
			omapi_value_dereference (&hv, MDL);
2149
2150
			class_dereference(&class, MDL);
2151
			
2152
			if (subclass == NULL) {
2153
				return ISC_R_NOTFOUND;
2154
			}
2155
2156
			class_reference(&class, subclass, MDL);
2157
			class_dereference(&subclass, MDL);
2158
		}
2159
		
2160
			
2161
		/* Don't return the object if the type is wrong. */
2162
		if (class -> type != typewanted) {
2163
			class_dereference (&class, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2164
			return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2165
		}
2166
		
2167
		if (class -> flags & CLASS_DECL_DELETED) {
2168
			class_dereference (&class, MDL);
2169
		}
2170
2171
		omapi_object_reference(lp, (omapi_object_t *)class, MDL);
2172
		
2173
		return ISC_R_SUCCESS;
2174
	}
2175
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2176
	return DHCP_R_NOKEYS;
1 by Andrew Pollock
Import upstream version 4.1.0
2177
}
2178
2179
2180
isc_result_t dhcp_class_lookup (omapi_object_t **lp,
2181
				omapi_object_t *id, omapi_object_t *ref)
2182
{
2183
	return class_lookup(lp, id, ref, dhcp_type_class);
2184
}
2185
2186
isc_result_t dhcp_class_create (omapi_object_t **lp,
2187
				omapi_object_t *id)
2188
{
2189
	struct class *cp = 0;
2190
	isc_result_t status;
2191
	
2192
	status = class_allocate(&cp, MDL);
2193
	if (status != ISC_R_SUCCESS)
2194
		return status;
2195
	
2196
	group_reference (&cp -> group, root_group, MDL);
2197
	cp -> flags = CLASS_DECL_DYNAMIC;
2198
	status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
2199
	class_dereference (&cp, MDL);
2200
	return status;
2201
}
2202
2203
isc_result_t dhcp_class_remove (omapi_object_t *lp,
2204
				omapi_object_t *id)
2205
{
2206
	struct class *cp;
2207
	if (lp -> type != dhcp_type_class)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2208
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2209
	cp = (struct class *)lp;
2210
2211
#ifdef DEBUG_OMAPI
2212
	log_debug ("OMAPI delete class %s", cp -> name);
2213
#endif
2214
	
2215
	delete_class (cp, 1);
2216
	return ISC_R_SUCCESS;
2217
}
2218
2219
isc_result_t dhcp_subclass_set_value  (omapi_object_t *h,
2220
				       omapi_object_t *id,
2221
				       omapi_data_string_t *name,
2222
				       omapi_typed_data_t *value)
2223
{
2224
	if (h -> type != dhcp_type_subclass)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2225
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2226
2227
	return class_set_value(h, id, name, value);
2228
}
2229
2230
2231
isc_result_t dhcp_subclass_get_value (omapi_object_t *h, omapi_object_t *id,
2232
				      omapi_data_string_t *name,
2233
				      omapi_value_t **value)
2234
{
2235
	struct class *subclass;
2236
	isc_result_t status;
2237
2238
	if (h -> type != dhcp_type_class)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2239
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2240
	subclass = (struct class *)h;
2241
	if (subclass -> name != 0)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2242
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2243
	
2244
	/* XXXJAB No values to get yet. */
2245
2246
	/* Try to find some inner object that can provide the value. */
2247
	if (h -> inner && h -> inner -> type -> get_value) {
2248
		status = ((*(h -> inner -> type -> get_value))
2249
			  (h -> inner, id, name, value));
2250
		if (status == ISC_R_SUCCESS)
2251
			return status;
2252
	}
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2253
	return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
2254
}
2255
2256
isc_result_t dhcp_subclass_signal_handler (omapi_object_t *h,
2257
					   const char *name, va_list ap)
2258
{
2259
	if (h -> type != dhcp_type_subclass)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2260
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2261
2262
	return class_signal_handler(h, name, ap);
2263
}
2264
2265
2266
isc_result_t dhcp_subclass_stuff_values (omapi_object_t *c,
2267
					 omapi_object_t *id,
2268
					 omapi_object_t *h)
2269
{
2270
	struct class *subclass;
2271
	isc_result_t status;
2272
2273
	if (h -> type != dhcp_type_class)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2274
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2275
	subclass = (struct class *)h;
2276
	if (subclass -> name != 0)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2277
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2278
	
2279
2280
	/* Can't stuff subclass values yet. */
2281
2282
	/* Write out the inner object, if any. */
2283
	if (h -> inner && h -> inner -> type -> stuff_values) {
2284
		status = ((*(h -> inner -> type -> stuff_values))
2285
			  (c, id, h -> inner));
2286
		if (status == ISC_R_SUCCESS)
2287
			return status;
2288
	}
2289
2290
	return ISC_R_SUCCESS;
2291
}
2292
2293
isc_result_t dhcp_subclass_lookup (omapi_object_t **lp,
2294
				   omapi_object_t *id, omapi_object_t *ref)
2295
{
2296
	return class_lookup(lp, id, ref, dhcp_type_subclass);
2297
}
2298
2299
2300
2301
2302
isc_result_t dhcp_subclass_create (omapi_object_t **lp,
2303
				   omapi_object_t *id)
2304
{
2305
	struct class *cp = 0;
2306
	isc_result_t status;
2307
2308
/*
2309
 * XXX
2310
 * NOTE: subclasses and classes have the same internal type, which makes it
2311
 * difficult to tell them apart. Specifically, in this function we need to
2312
 * create a class object (because there is no such thing as a subclass
2313
 * object), but one field of the class object is the type (which has the
2314
 * value dhcp_type_class), and it is from here that all the other omapi
2315
 * functions are accessed. So, even though there's a whole suite of
2316
 * subclass functions registered, they won't get used. Now we could change
2317
 * the type pointer after creating the class object, but I'm not certain
2318
 * that won't break something else.
2319
 */
2320
	
2321
	status = subclass_allocate(&cp, MDL);
2322
	if (status != ISC_R_SUCCESS)
2323
		return status;
2324
	group_reference (&cp -> group, root_group, MDL);
2325
2326
	cp -> flags = CLASS_DECL_DYNAMIC;
2327
	
2328
	status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
2329
	subclass_dereference (&cp, MDL);
2330
	return status;
2331
}
2332
2333
isc_result_t dhcp_subclass_remove (omapi_object_t *lp,
2334
				   omapi_object_t *id)
2335
{
2336
#if 1
2337
2338
	log_fatal("calling dhcp_subclass_set_value");
2339
	/* this should never be called see dhcp_subclass_create for why */
2340
2341
#else	
2342
	
2343
	struct class *cp;
2344
	if (lp -> type != dhcp_type_subclass)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2345
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2346
	cp = (struct class *)lp;
2347
2348
#ifdef DEBUG_OMAPI
2349
	log_debug ("OMAPI delete subclass %s", cp -> name);
2350
#endif
2351
	
2352
	delete_class (cp, 1);
2353
2354
#endif
2355
	
2356
	return ISC_R_SUCCESS;
2357
}
2358
2359
isc_result_t binding_scope_set_value (struct binding_scope *scope, int createp,
2360
				      omapi_data_string_t *name,
2361
				      omapi_typed_data_t *value)
2362
{
2363
	struct binding *bp;
2364
	char *nname;
2365
	struct binding_value *nv;
2366
	nname = dmalloc (name -> len + 1, MDL);
2367
	if (!nname)
2368
		return ISC_R_NOMEMORY;
2369
	memcpy (nname, name -> value, name -> len);
2370
	nname [name -> len] = 0;
2371
	bp = find_binding (scope, nname);
2372
	if (!bp && !createp) {
2373
		dfree (nname, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2374
		return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
2375
	} 
2376
	if (!value) {
2377
		dfree (nname, MDL);
2378
		if (!bp)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2379
			return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
2380
		binding_value_dereference (&bp -> value, MDL);
2381
		return ISC_R_SUCCESS;
2382
	}
2383
2384
	nv = (struct binding_value *)0;
2385
	if (!binding_value_allocate (&nv, MDL)) {
2386
		dfree (nname, MDL);
2387
		return ISC_R_NOMEMORY;
2388
	}
2389
	switch (value -> type) {
2390
	      case omapi_datatype_int:
2391
		nv -> type = binding_numeric;
2392
		nv -> value.intval = value -> u.integer;
2393
		break;
2394
2395
	      case omapi_datatype_string:
2396
	      case omapi_datatype_data:
2397
		if (!buffer_allocate (&nv -> value.data.buffer,
2398
				      value -> u.buffer.len, MDL)) {
2399
			binding_value_dereference (&nv, MDL);
2400
			dfree (nname, MDL);
2401
			return ISC_R_NOMEMORY;
2402
		}
2403
		memcpy (&nv -> value.data.buffer -> data [1],
2404
			value -> u.buffer.value, value -> u.buffer.len);
2405
		nv -> value.data.len = value -> u.buffer.len;
2406
		break;
2407
2408
	      case omapi_datatype_object:
2409
		binding_value_dereference (&nv, MDL);
2410
		dfree (nname, MDL);
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2411
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2412
	}
2413
2414
	if (!bp) {
2415
		bp = dmalloc (sizeof *bp, MDL);
2416
		if (!bp) {
2417
			binding_value_dereference (&nv, MDL);
2418
			dfree (nname, MDL);
2419
			return ISC_R_NOMEMORY;
2420
		}
2421
		memset (bp, 0, sizeof *bp);
2422
		bp -> name = nname;
2423
		nname = (char *)0;
2424
		bp -> next = scope -> bindings;
2425
		scope -> bindings = bp;
2426
	} else {
2427
		if (bp -> value)
2428
			binding_value_dereference (&bp -> value, MDL);
2429
		dfree (nname, MDL);
2430
	}
2431
	binding_value_reference (&bp -> value, nv, MDL);
2432
	binding_value_dereference (&nv, MDL);
2433
	return ISC_R_SUCCESS;
2434
}
2435
2436
isc_result_t binding_scope_get_value (omapi_value_t **value,
2437
				      struct binding_scope *scope,
2438
				      omapi_data_string_t *name)
2439
{
2440
	struct binding *bp;
2441
	omapi_typed_data_t *td;
2442
	isc_result_t status;
2443
	char *nname;
2444
	nname = dmalloc (name -> len + 1, MDL);
2445
	if (!nname)
2446
		return ISC_R_NOMEMORY;
2447
	memcpy (nname, name -> value, name -> len);
2448
	nname [name -> len] = 0;
2449
	bp = find_binding (scope, nname);
2450
	dfree (nname, MDL);
2451
	if (!bp)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2452
		return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
2453
	if (!bp -> value)
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2454
		return DHCP_R_UNKNOWNATTRIBUTE;
1 by Andrew Pollock
Import upstream version 4.1.0
2455
2456
	switch (bp -> value -> type) {
2457
	      case binding_boolean:
2458
		td = (omapi_typed_data_t *)0;
2459
		status = omapi_typed_data_new (MDL, &td, omapi_datatype_int,
2460
					       bp -> value -> value.boolean);
2461
		break;
2462
2463
	      case binding_numeric:
2464
		td = (omapi_typed_data_t *)0;
2465
		status = omapi_typed_data_new (MDL, &td, omapi_datatype_int,
2466
					       (int)
2467
					       bp -> value -> value.intval);
2468
		break;
2469
2470
	      case binding_data:
2471
		td = (omapi_typed_data_t *)0;
2472
		status = omapi_typed_data_new (MDL, &td, omapi_datatype_data,
2473
					       bp -> value -> value.data.len);
2474
		if (status != ISC_R_SUCCESS)
2475
			return status;
2476
		memcpy (&td -> u.buffer.value [0],
2477
			bp -> value -> value.data.data,
2478
			bp -> value -> value.data.len);
2479
		break;
2480
2481
		/* Can't return values for these two (yet?). */
2482
	      case binding_dns:
2483
	      case binding_function:
1.2.1 by Andrew Pollock
Import upstream version 4.2.2
2484
		return DHCP_R_INVALIDARG;
1 by Andrew Pollock
Import upstream version 4.1.0
2485
2486
	      default:
2487
		log_fatal ("Impossible case at %s:%d.", MDL);
2488
		return ISC_R_FAILURE;
2489
	}
2490
2491
	if (status != ISC_R_SUCCESS)
2492
		return status;
2493
	status = omapi_value_new (value, MDL);
2494
	if (status != ISC_R_SUCCESS) {
2495
		omapi_typed_data_dereference (&td, MDL);
2496
		return status;
2497
	}
2498
	
2499
	omapi_data_string_reference (&(*value) -> name, name, MDL);
2500
	omapi_typed_data_reference (&(*value) -> value, td, MDL);
2501
	omapi_typed_data_dereference (&td, MDL);
2502
2503
	return ISC_R_SUCCESS;
2504
}
2505
2506
isc_result_t binding_scope_stuff_values (omapi_object_t *c,
2507
					 struct binding_scope *scope)
2508
{
2509
	struct binding *bp;
2510
	unsigned len;
2511
	isc_result_t status;
2512
2513
	for (bp = scope -> bindings; bp; bp = bp -> next) {
2514
	    if (bp -> value) {
2515
		if (bp -> value -> type == binding_dns ||
2516
		    bp -> value -> type == binding_function)
2517
			continue;
2518
2519
		/* Stuff the name. */
2520
		len = strlen (bp -> name);
2521
		status = omapi_connection_put_uint16 (c, len);
2522
		if (status != ISC_R_SUCCESS)
2523
		    return status;
2524
		status = omapi_connection_copyin (c,
2525
						  (unsigned char *)bp -> name,
2526
						  len);
2527
		if (status != ISC_R_SUCCESS)
2528
			return status;
2529
2530
		switch (bp -> value -> type) {
2531
		  case binding_boolean:
2532
		    status = omapi_connection_put_uint32 (c,
2533
							  sizeof (u_int32_t));
2534
		    if (status != ISC_R_SUCCESS)
2535
			return status;
2536
		    status = (omapi_connection_put_uint32
2537
			      (c,
2538
			       ((u_int32_t)(bp -> value -> value.boolean))));
2539
		    break;
2540
2541
		  case binding_data:
2542
		    status = (omapi_connection_put_uint32
2543
			      (c, bp -> value -> value.data.len));
2544
		    if (status != ISC_R_SUCCESS)
2545
			return status;
2546
		    if (bp -> value -> value.data.len) {
2547
			status = (omapi_connection_copyin
2548
				  (c, bp -> value -> value.data.data,
2549
				   bp -> value -> value.data.len));
2550
			if (status != ISC_R_SUCCESS)
2551
			    return status;
2552
		    }
2553
		    break;
2554
2555
		  case binding_numeric:
2556
		    status = (omapi_connection_put_uint32
2557
			      (c, sizeof (u_int32_t)));
2558
		    if (status != ISC_R_SUCCESS)
2559
			    return status;
2560
		    status = (omapi_connection_put_uint32
2561
			      (c, ((u_int32_t)
2562
				   (bp -> value -> value.intval))));
2563
		    break;
2564
2565
2566
		    /* NOTREACHED */
2567
		  case binding_dns:
2568
		  case binding_function:
2569
		    break;
2570
		}
2571
	    }
2572
	}
2573
	return ISC_R_SUCCESS;
2574
}
2575
2576
/* vim: set tabstop=8: */