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