1: /* omapi.c
2:
3: OMAPI object interfaces for the DHCP server. */
4:
5: /*
6: * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
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>
25: * https://www.isc.org/
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
30: * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
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)
212: return ISC_R_INVALIDARG;
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)
225: return ISC_R_INVALIDARG;
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: }
244: return ISC_R_UNCHANGED;
245: } else if (!omapi_ds_strcmp (name, "ip-address")) {
246: return ISC_R_NOPERM;
247: } else if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
248: return ISC_R_UNCHANGED; /* XXX take change. */
249: } else if (!omapi_ds_strcmp (name, "hostname")) {
250: return ISC_R_UNCHANGED; /* XXX take change. */
251: } else if (!omapi_ds_strcmp (name, "client-hostname")) {
252: return ISC_R_UNCHANGED; /* XXX take change. */
253: } else if (!omapi_ds_strcmp (name, "host")) {
254: return ISC_R_UNCHANGED; /* XXX take change. */
255: } else if (!omapi_ds_strcmp (name, "subnet")) {
256: return ISC_R_INVALIDARG;
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)
280: return ISC_R_INVALIDARG;
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")) {
294: return ISC_R_UNCHANGED; /* XXX carefully allow change. */
295: } else if (!omapi_ds_strcmp (name, "hardware-address")) {
296: return ISC_R_UNCHANGED; /* XXX take change. */
297: } else if (!omapi_ds_strcmp (name, "hardware-type")) {
298: return ISC_R_UNCHANGED; /* XXX take change. */
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));
312: if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
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)
338: return ISC_R_INVALIDARG;
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: }
403: return ISC_R_UNKNOWNATTRIBUTE;
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)
411: return ISC_R_INVALIDARG;
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: {
483: struct lease *lease;
484: isc_result_t status;
485:
486: if (h -> type != dhcp_type_lease)
487: return ISC_R_INVALIDARG;
488: lease = (struct lease *)h;
489:
490: if (!strcmp (name, "updated"))
491: return ISC_R_SUCCESS;
492:
493: /* Try to find some inner object that can take the value. */
494: if (h -> inner && h -> inner -> type -> signal_handler) {
495: status = ((*(h -> inner -> type -> signal_handler))
496: (h -> inner, name, ap));
497: if (status == ISC_R_SUCCESS)
498: return status;
499: }
500: return ISC_R_NOTFOUND;
501: }
502:
503: isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
504: omapi_object_t *id,
505: omapi_object_t *h)
506: {
507: u_int32_t bouncer;
508: struct lease *lease;
509: isc_result_t status;
510: u_int8_t flagbuf;
511:
512: if (h -> type != dhcp_type_lease)
513: return ISC_R_INVALIDARG;
514: lease = (struct lease *)h;
515:
516: /* Write out all the values. */
517:
518: status = omapi_connection_put_name (c, "state");
519: if (status != ISC_R_SUCCESS)
520: return status;
521: status = omapi_connection_put_uint32 (c, sizeof (int));
522: if (status != ISC_R_SUCCESS)
523: return status;
524: status = omapi_connection_put_uint32 (c, lease -> binding_state);
525: if (status != ISC_R_SUCCESS)
526: return status;
527:
528: status = omapi_connection_put_name (c, "ip-address");
529: if (status != ISC_R_SUCCESS)
530: return status;
531: status = omapi_connection_put_uint32 (c, lease -> ip_addr.len);
532: if (status != ISC_R_SUCCESS)
533: return status;
534: status = omapi_connection_copyin (c, lease -> ip_addr.iabuf,
535: lease -> ip_addr.len);
536: if (status != ISC_R_SUCCESS)
537: return status;
538:
539: if (lease -> uid_len) {
540: status = omapi_connection_put_name (c,
541: "dhcp-client-identifier");
542: if (status != ISC_R_SUCCESS)
543: return status;
544: status = omapi_connection_put_uint32 (c, lease -> uid_len);
545: if (status != ISC_R_SUCCESS)
546: return status;
547: if (lease -> uid_len) {
548: status = omapi_connection_copyin (c, lease -> uid,
549: lease -> uid_len);
550: if (status != ISC_R_SUCCESS)
551: return status;
552: }
553: }
554:
555: if (lease -> client_hostname) {
556: status = omapi_connection_put_name (c, "client-hostname");
557: if (status != ISC_R_SUCCESS)
558: return status;
559: status =
560: omapi_connection_put_string (c,
561: lease -> client_hostname);
562: if (status != ISC_R_SUCCESS)
563: return status;
564: }
565:
566: if (lease -> host) {
567: status = omapi_connection_put_name (c, "host");
568: if (status != ISC_R_SUCCESS)
569: return status;
570: status = omapi_connection_put_handle (c,
571: (omapi_object_t *)
572: lease -> host);
573: if (status != ISC_R_SUCCESS)
574: return status;
575: }
576:
577: status = omapi_connection_put_name (c, "subnet");
578: if (status != ISC_R_SUCCESS)
579: return status;
580: status = omapi_connection_put_handle
581: (c, (omapi_object_t *)lease -> subnet);
582: if (status != ISC_R_SUCCESS)
583: return status;
584:
585: status = omapi_connection_put_name (c, "pool");
586: if (status != ISC_R_SUCCESS)
587: return status;
588: status = omapi_connection_put_handle (c,
589: (omapi_object_t *)lease -> pool);
590: if (status != ISC_R_SUCCESS)
591: return status;
592:
593: if (lease -> billing_class) {
594: status = omapi_connection_put_name (c, "billing-class");
595: if (status != ISC_R_SUCCESS)
596: return status;
597: status = omapi_connection_put_handle
598: (c, (omapi_object_t *)lease -> billing_class);
599: if (status != ISC_R_SUCCESS)
600: return status;
601: }
602:
603: if (lease -> hardware_addr.hlen) {
604: status = omapi_connection_put_name (c, "hardware-address");
605: if (status != ISC_R_SUCCESS)
606: return status;
607: status = (omapi_connection_put_uint32
608: (c,
609: (unsigned long)(lease -> hardware_addr.hlen - 1)));
610: if (status != ISC_R_SUCCESS)
611: return status;
612: status = (omapi_connection_copyin
613: (c, &lease -> hardware_addr.hbuf [1],
614: (unsigned long)(lease -> hardware_addr.hlen - 1)));
615:
616: if (status != ISC_R_SUCCESS)
617: return status;
618:
619: status = omapi_connection_put_name (c, "hardware-type");
620: if (status != ISC_R_SUCCESS)
621: return status;
622: status = omapi_connection_put_uint32 (c, sizeof (int));
623: if (status != ISC_R_SUCCESS)
624: return status;
625: status = omapi_connection_put_uint32
626: (c, lease -> hardware_addr.hbuf [0]);
627: if (status != ISC_R_SUCCESS)
628: return status;
629: }
630:
631: /* TIME values may be 64-bit, depending on system architecture.
632: * OMAPI must be system independent, both in terms of transmitting
633: * bytes on the wire in network byte order, and in terms of being
634: * readable and usable by both systems.
635: *
636: * XXX: In a future feature release, a put_int64() should be made
637: * to exist, and perhaps a put_time() wrapper that selects which
638: * to use based upon sizeof(TIME). In the meantime, use existing,
639: * 32-bit, code.
640: */
641: bouncer = (u_int32_t)lease->ends;
642: status = omapi_connection_put_name(c, "ends");
643: if (status != ISC_R_SUCCESS)
644: return status;
645: status = omapi_connection_put_uint32(c, sizeof(bouncer));
646: if (status != ISC_R_SUCCESS)
647: return status;
648: status = omapi_connection_put_uint32(c, bouncer);
649: if (status != ISC_R_SUCCESS)
650: return status;
651:
652: bouncer = (u_int32_t)lease->starts;
653: status = omapi_connection_put_name(c, "starts");
654: if (status != ISC_R_SUCCESS)
655: return status;
656: status = omapi_connection_put_uint32(c, sizeof(bouncer));
657: if (status != ISC_R_SUCCESS)
658: return status;
659: status = omapi_connection_put_uint32(c, bouncer);
660: if (status != ISC_R_SUCCESS)
661: return status;
662:
663: bouncer = (u_int32_t)lease->tstp;
664: status = omapi_connection_put_name(c, "tstp");
665: if (status != ISC_R_SUCCESS)
666: return status;
667: status = omapi_connection_put_uint32(c, sizeof(bouncer));
668: if (status != ISC_R_SUCCESS)
669: return status;
670: status = omapi_connection_put_uint32(c, bouncer);
671: if (status != ISC_R_SUCCESS)
672: return status;
673:
674: bouncer = (u_int32_t)lease->tsfp;
675: status = omapi_connection_put_name(c, "tsfp");
676: if (status != ISC_R_SUCCESS)
677: return status;
678: status = omapi_connection_put_uint32(c, sizeof(bouncer));
679: if (status != ISC_R_SUCCESS)
680: return status;
681: status = omapi_connection_put_uint32(c, bouncer);
682: if (status != ISC_R_SUCCESS)
683: return status;
684:
685: bouncer = (u_int32_t)lease->atsfp;
686: status = omapi_connection_put_name(c, "atsfp");
687: if (status != ISC_R_SUCCESS)
688: return status;
689: status = omapi_connection_put_uint32(c, sizeof(bouncer));
690: if (status != ISC_R_SUCCESS)
691: return status;
692: status = omapi_connection_put_uint32(c, bouncer);
693: if (status != ISC_R_SUCCESS)
694: return status;
695:
696: bouncer = (u_int32_t)lease->cltt;
697: status = omapi_connection_put_name(c, "cltt");
698: if (status != ISC_R_SUCCESS)
699: return status;
700: status = omapi_connection_put_uint32(c, sizeof(bouncer));
701: if (status != ISC_R_SUCCESS)
702: return status;
703: status = omapi_connection_put_uint32(c, bouncer);
704: if (status != ISC_R_SUCCESS)
705: return status;
706:
707: status = omapi_connection_put_name (c, "flags");
708: if (status != ISC_R_SUCCESS)
709: return status;
710: status = omapi_connection_put_uint32(c, sizeof(flagbuf));
711: if (status != ISC_R_SUCCESS)
712: return status;
713: flagbuf = lease->flags & EPHEMERAL_FLAGS;
714: status = omapi_connection_copyin(c, &flagbuf, sizeof(flagbuf));
715: if (status != ISC_R_SUCCESS)
716: return status;
717:
718: if (lease -> scope) {
719: status = binding_scope_stuff_values (c, lease -> scope);
720: if (status != ISC_R_SUCCESS)
721: return status;
722: }
723:
724: /* Write out the inner object, if any. */
725: if (h -> inner && h -> inner -> type -> stuff_values) {
726: status = ((*(h -> inner -> type -> stuff_values))
727: (c, id, h -> inner));
728: if (status == ISC_R_SUCCESS)
729: return status;
730: }
731:
732: return ISC_R_SUCCESS;
733: }
734:
735: isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
736: omapi_object_t *id, omapi_object_t *ref)
737: {
738: omapi_value_t *tv = (omapi_value_t *)0;
739: isc_result_t status;
740: struct lease *lease;
741:
742: if (!ref)
743: return ISC_R_NOKEYS;
744:
745: /* First see if we were sent a handle. */
746: status = omapi_get_value_str (ref, id, "handle", &tv);
747: if (status == ISC_R_SUCCESS) {
748: status = omapi_handle_td_lookup (lp, tv -> value);
749:
750: omapi_value_dereference (&tv, MDL);
751: if (status != ISC_R_SUCCESS)
752: return status;
753:
754: /* Don't return the object if the type is wrong. */
755: if ((*lp) -> type != dhcp_type_lease) {
756: omapi_object_dereference (lp, MDL);
757: return ISC_R_INVALIDARG;
758: }
759: }
760:
761: /* Now look for an IP address. */
762: status = omapi_get_value_str (ref, id, "ip-address", &tv);
763: if (status == ISC_R_SUCCESS) {
764: lease = (struct lease *)0;
765: lease_ip_hash_lookup(&lease, lease_ip_addr_hash,
766: tv->value->u.buffer.value,
767: tv->value->u.buffer.len, MDL);
768:
769: omapi_value_dereference (&tv, MDL);
770:
771: /* If we already have a lease, and it's not the same one,
772: then the query was invalid. */
773: if (*lp && *lp != (omapi_object_t *)lease) {
774: omapi_object_dereference (lp, MDL);
775: lease_dereference (&lease, MDL);
776: return ISC_R_KEYCONFLICT;
777: } else if (!lease) {
778: if (*lp)
779: omapi_object_dereference (lp, MDL);
780: return ISC_R_NOTFOUND;
781: } else if (!*lp) {
782: /* XXX fix so that hash lookup itself creates
783: XXX the reference. */
784: omapi_object_reference (lp,
785: (omapi_object_t *)lease, MDL);
786: lease_dereference (&lease, MDL);
787: }
788: }
789:
790: /* Now look for a client identifier. */
791: status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
792: if (status == ISC_R_SUCCESS) {
793: lease = (struct lease *)0;
794: lease_id_hash_lookup(&lease, lease_uid_hash,
795: tv->value->u.buffer.value,
796: tv->value->u.buffer.len, MDL);
797: omapi_value_dereference (&tv, MDL);
798:
799: if (*lp && *lp != (omapi_object_t *)lease) {
800: omapi_object_dereference (lp, MDL);
801: lease_dereference (&lease, MDL);
802: return ISC_R_KEYCONFLICT;
803: } else if (!lease) {
804: if (*lp)
805: omapi_object_dereference (lp, MDL);
806: return ISC_R_NOTFOUND;
807: } else if (lease -> n_uid) {
808: if (*lp)
809: omapi_object_dereference (lp, MDL);
810: return ISC_R_MULTIPLE;
811: } else if (!*lp) {
812: /* XXX fix so that hash lookup itself creates
813: XXX the reference. */
814: omapi_object_reference (lp,
815: (omapi_object_t *)lease, MDL);
816: lease_dereference (&lease, MDL);
817: }
818: }
819:
820: /* Now look for a hardware address. */
821: status = omapi_get_value_str (ref, id, "hardware-address", &tv);
822: if (status == ISC_R_SUCCESS) {
823: unsigned char *haddr;
824: unsigned int len;
825:
826: len = tv -> value -> u.buffer.len + 1;
827: haddr = dmalloc (len, MDL);
828: if (!haddr) {
829: omapi_value_dereference (&tv, MDL);
830: return ISC_R_NOMEMORY;
831: }
832:
833: memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
834: omapi_value_dereference (&tv, MDL);
835:
836: status = omapi_get_value_str (ref, id, "hardware-type", &tv);
837: if (status == ISC_R_SUCCESS) {
838: if (tv -> value -> type == omapi_datatype_data) {
839: if ((tv -> value -> u.buffer.len != 4) ||
840: (tv -> value -> u.buffer.value[0] != 0) ||
841: (tv -> value -> u.buffer.value[1] != 0) ||
842: (tv -> value -> u.buffer.value[2] != 0)) {
843: omapi_value_dereference (&tv, MDL);
844: dfree (haddr, MDL);
845: return ISC_R_INVALIDARG;
846: }
847:
848: haddr[0] = tv -> value -> u.buffer.value[3];
849: } else if (tv -> value -> type == omapi_datatype_int) {
850: haddr[0] = (unsigned char)
851: tv -> value -> u.integer;
852: } else {
853: omapi_value_dereference (&tv, MDL);
854: dfree (haddr, MDL);
855: return ISC_R_INVALIDARG;
856: }
857:
858: omapi_value_dereference (&tv, MDL);
859: } else {
860: /* If no hardware-type is specified, default to
861: ethernet. This may or may not be a good idea,
862: but Telus is currently relying on this behavior.
863: - DPN */
864: haddr[0] = HTYPE_ETHER;
865: }
866:
867: lease = (struct lease *)0;
868: lease_id_hash_lookup(&lease, lease_hw_addr_hash, haddr, len,
869: MDL);
870: dfree (haddr, MDL);
871:
872: if (*lp && *lp != (omapi_object_t *)lease) {
873: omapi_object_dereference (lp, MDL);
874: lease_dereference (&lease, MDL);
875: return ISC_R_KEYCONFLICT;
876: } else if (!lease) {
877: if (*lp)
878: omapi_object_dereference (lp, MDL);
879: return ISC_R_NOTFOUND;
880: } else if (lease -> n_hw) {
881: if (*lp)
882: omapi_object_dereference (lp, MDL);
883: lease_dereference (&lease, MDL);
884: return ISC_R_MULTIPLE;
885: } else if (!*lp) {
886: /* XXX fix so that hash lookup itself creates
887: XXX the reference. */
888: omapi_object_reference (lp,
889: (omapi_object_t *)lease, MDL);
890: lease_dereference (&lease, MDL);
891: }
892: }
893:
894: /* If we get to here without finding a lease, no valid key was
895: specified. */
896: if (!*lp)
897: return ISC_R_NOKEYS;
898: return ISC_R_SUCCESS;
899: }
900:
901: isc_result_t dhcp_lease_create (omapi_object_t **lp,
902: omapi_object_t *id)
903: {
904: return ISC_R_NOTIMPLEMENTED;
905: }
906:
907: isc_result_t dhcp_lease_remove (omapi_object_t *lp,
908: omapi_object_t *id)
909: {
910: return ISC_R_NOTIMPLEMENTED;
911: }
912:
913: isc_result_t dhcp_host_set_value (omapi_object_t *h,
914: omapi_object_t *id,
915: omapi_data_string_t *name,
916: omapi_typed_data_t *value)
917: {
918: struct host_decl *host;
919: isc_result_t status;
920:
921: if (h -> type != dhcp_type_host)
922: return ISC_R_INVALIDARG;
923: host = (struct host_decl *)h;
924:
925: /* XXX For now, we can only set these values on new host objects.
926: XXX Soon, we need to be able to update host objects. */
927: if (!omapi_ds_strcmp (name, "name")) {
928: if (host -> name)
929: return ISC_R_EXISTS;
930: if (value && (value -> type == omapi_datatype_data ||
931: value -> type == omapi_datatype_string)) {
932: host -> name = dmalloc (value -> u.buffer.len + 1,
933: MDL);
934: if (!host -> name)
935: return ISC_R_NOMEMORY;
936: memcpy (host -> name,
937: value -> u.buffer.value,
938: value -> u.buffer.len);
939: host -> name [value -> u.buffer.len] = 0;
940: } else
941: return ISC_R_INVALIDARG;
942: return ISC_R_SUCCESS;
943: }
944:
945: if (!omapi_ds_strcmp (name, "group")) {
946: if (value && (value -> type == omapi_datatype_data ||
947: value -> type == omapi_datatype_string)) {
948: struct group_object *group;
949: group = (struct group_object *)0;
950: group_hash_lookup (&group, group_name_hash,
951: (char *)value -> u.buffer.value,
952: value -> u.buffer.len, MDL);
953: if (!group || (group -> flags & GROUP_OBJECT_DELETED))
954: return ISC_R_NOTFOUND;
955: if (host -> group)
956: group_dereference (&host -> group, MDL);
957: group_reference (&host -> group, group -> group, MDL);
958: if (host -> named_group)
959: group_object_dereference (&host -> named_group,
960: MDL);
961: group_object_reference (&host -> named_group,
962: group, MDL);
963: group_object_dereference (&group, MDL);
964: } else
965: return ISC_R_INVALIDARG;
966: return ISC_R_SUCCESS;
967: }
968:
969: if (!omapi_ds_strcmp (name, "hardware-address")) {
970: if (host -> interface.hlen)
971: return ISC_R_EXISTS;
972: if (value && (value -> type == omapi_datatype_data ||
973: value -> type == omapi_datatype_string)) {
974: if (value -> u.buffer.len >
975: (sizeof host -> interface.hbuf) - 1)
976: return ISC_R_INVALIDARG;
977: memcpy (&host -> interface.hbuf [1],
978: value -> u.buffer.value,
979: value -> u.buffer.len);
980: host -> interface.hlen = value -> u.buffer.len + 1;
981: } else
982: return ISC_R_INVALIDARG;
983: return ISC_R_SUCCESS;
984: }
985:
986: if (!omapi_ds_strcmp (name, "hardware-type")) {
987: int type;
988: if (value && (value -> type == omapi_datatype_data &&
989: value -> u.buffer.len == sizeof type)) {
990: if (value -> u.buffer.len > sizeof type)
991: return ISC_R_INVALIDARG;
992: memcpy (&type,
993: value -> u.buffer.value,
994: value -> u.buffer.len);
995: type = ntohl (type);
996: } else if (value -> type == omapi_datatype_int)
997: type = value -> u.integer;
998: else
999: return ISC_R_INVALIDARG;
1000: host -> interface.hbuf [0] = type;
1001: return ISC_R_SUCCESS;
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
1019: return ISC_R_INVALIDARG;
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
1046: return ISC_R_INVALIDARG;
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);
1081: return ISC_R_BADPARSE;
1082: }
1083: end_parse (&parse);
1084: } else
1085: return ISC_R_INVALIDARG;
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));
1099: if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
1100: return status;
1101: }
1102:
1103: return ISC_R_UNKNOWNATTRIBUTE;
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)
1116: return ISC_R_INVALIDARG;
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: }
1173: return ISC_R_UNKNOWNATTRIBUTE;
1174: }
1175:
1176: isc_result_t dhcp_host_destroy (omapi_object_t *h, const char *file, int line)
1177: {
1178: struct host_decl *host;
1179:
1180: if (h -> type != dhcp_type_host)
1181: return ISC_R_INVALIDARG;
1182: host = (struct host_decl *)h;
1183:
1184: #if defined (DEBUG_MEMORY_LEAKAGE) || \
1185: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1186: if (host -> n_ipaddr)
1187: host_dereference (&host -> n_ipaddr, file, line);
1188: if (host -> n_dynamic)
1189: host_dereference (&host -> n_dynamic, file, line);
1190: if (host -> name) {
1191: dfree (host -> name, file, line);
1192: host -> name = (char *)0;
1193: }
1194: data_string_forget (&host -> client_identifier, file, line);
1195: if (host -> fixed_addr)
1196: option_cache_dereference (&host -> fixed_addr, file, line);
1197: if (host -> group)
1198: group_dereference (&host -> group, file, line);
1199: if (host -> named_group)
1200: omapi_object_dereference ((omapi_object_t **)
1201: &host -> named_group, file, line);
1202: data_string_forget (&host -> auth_key_id, file, line);
1203: #endif
1204:
1205: return ISC_R_SUCCESS;
1206: }
1207:
1208: isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
1209: const char *name, va_list ap)
1210: {
1211: struct host_decl *host;
1212: isc_result_t status;
1213: int updatep = 0;
1214:
1215: if (h -> type != dhcp_type_host)
1216: return ISC_R_INVALIDARG;
1217: host = (struct host_decl *)h;
1218:
1219: if (!strcmp (name, "updated")) {
1220: /* There must be a client identifier of some sort. */
1221: if (host -> interface.hlen == 0 &&
1222: !host -> client_identifier.len)
1223: return ISC_R_INVALIDARG;
1224:
1225: if (!host -> name) {
1226: char hnbuf [64];
1227: sprintf (hnbuf, "nh%08lx%08lx",
1228: (unsigned long)cur_time, (unsigned long)host);
1229: host -> name = dmalloc (strlen (hnbuf) + 1, MDL);
1230: if (!host -> name)
1231: return ISC_R_NOMEMORY;
1232: strcpy (host -> name, hnbuf);
1233: }
1234:
1235: #ifdef DEBUG_OMAPI
1236: log_debug ("OMAPI added host %s", host -> name);
1237: #endif
1238: status = enter_host (host, 1, 1);
1239: if (status != ISC_R_SUCCESS)
1240: return status;
1241: updatep = 1;
1242: }
1243:
1244: /* Try to find some inner object that can take the value. */
1245: if (h -> inner && h -> inner -> type -> signal_handler) {
1246: status = ((*(h -> inner -> type -> signal_handler))
1247: (h -> inner, name, ap));
1248: if (status == ISC_R_SUCCESS)
1249: return status;
1250: }
1251: if (updatep)
1252: return ISC_R_SUCCESS;
1253: return ISC_R_NOTFOUND;
1254: }
1255:
1256: isc_result_t dhcp_host_stuff_values (omapi_object_t *c,
1257: omapi_object_t *id,
1258: omapi_object_t *h)
1259: {
1260: struct host_decl *host;
1261: isc_result_t status;
1262: struct data_string ip_addrs;
1263:
1264: if (h -> type != dhcp_type_host)
1265: return ISC_R_INVALIDARG;
1266: host = (struct host_decl *)h;
1267:
1268: /* Write out all the values. */
1269:
1270: memset (&ip_addrs, 0, sizeof ip_addrs);
1271: if (host -> fixed_addr &&
1272: evaluate_option_cache (&ip_addrs, (struct packet *)0,
1273: (struct lease *)0,
1274: (struct client_state *)0,
1275: (struct option_state *)0,
1276: (struct option_state *)0,
1277: &global_scope,
1278: host -> fixed_addr, MDL)) {
1279: status = omapi_connection_put_name (c, "ip-address");
1280: if (status != ISC_R_SUCCESS)
1281: return status;
1282: status = omapi_connection_put_uint32 (c, ip_addrs.len);
1283: if (status != ISC_R_SUCCESS)
1284: return status;
1285: status = omapi_connection_copyin (c,
1286: ip_addrs.data, ip_addrs.len);
1287: if (status != ISC_R_SUCCESS)
1288: return status;
1289: }
1290:
1291: if (host -> client_identifier.len) {
1292: status = omapi_connection_put_name (c,
1293: "dhcp-client-identifier");
1294: if (status != ISC_R_SUCCESS)
1295: return status;
1296: status = (omapi_connection_put_uint32
1297: (c, host -> client_identifier.len));
1298: if (status != ISC_R_SUCCESS)
1299: return status;
1300: status = (omapi_connection_copyin
1301: (c,
1302: host -> client_identifier.data,
1303: host -> client_identifier.len));
1304: if (status != ISC_R_SUCCESS)
1305: return status;
1306: }
1307:
1308: if (host -> name) {
1309: status = omapi_connection_put_name (c, "name");
1310: if (status != ISC_R_SUCCESS)
1311: return status;
1312: status = omapi_connection_put_string (c, host -> name);
1313: if (status != ISC_R_SUCCESS)
1314: return status;
1315: }
1316:
1317: if (host -> interface.hlen) {
1318: status = omapi_connection_put_name (c, "hardware-address");
1319: if (status != ISC_R_SUCCESS)
1320: return status;
1321: status = (omapi_connection_put_uint32
1322: (c, (unsigned long)(host -> interface.hlen - 1)));
1323: if (status != ISC_R_SUCCESS)
1324: return status;
1325: status = (omapi_connection_copyin
1326: (c, &host -> interface.hbuf [1],
1327: (unsigned long)(host -> interface.hlen - 1)));
1328: if (status != ISC_R_SUCCESS)
1329: return status;
1330:
1331: status = omapi_connection_put_name (c, "hardware-type");
1332: if (status != ISC_R_SUCCESS)
1333: return status;
1334: status = omapi_connection_put_uint32 (c, sizeof (int));
1335: if (status != ISC_R_SUCCESS)
1336: return status;
1337: status = (omapi_connection_put_uint32
1338: (c, host -> interface.hbuf [0]));
1339: if (status != ISC_R_SUCCESS)
1340: return status;
1341: }
1342:
1343: /* Write out the inner object, if any. */
1344: if (h -> inner && h -> inner -> type -> stuff_values) {
1345: status = ((*(h -> inner -> type -> stuff_values))
1346: (c, id, h -> inner));
1347: if (status == ISC_R_SUCCESS)
1348: return status;
1349: }
1350:
1351: return ISC_R_SUCCESS;
1352: }
1353:
1354: isc_result_t dhcp_host_lookup (omapi_object_t **lp,
1355: omapi_object_t *id, omapi_object_t *ref)
1356: {
1357: omapi_value_t *tv = (omapi_value_t *)0;
1358: isc_result_t status;
1359: struct host_decl *host;
1360:
1361: if (!ref)
1362: return ISC_R_NOKEYS;
1363:
1364: /* First see if we were sent a handle. */
1365: status = omapi_get_value_str (ref, id, "handle", &tv);
1366: if (status == ISC_R_SUCCESS) {
1367: status = omapi_handle_td_lookup (lp, tv -> value);
1368:
1369: omapi_value_dereference (&tv, MDL);
1370: if (status != ISC_R_SUCCESS)
1371: return status;
1372:
1373: /* Don't return the object if the type is wrong. */
1374: if ((*lp) -> type != dhcp_type_host) {
1375: omapi_object_dereference (lp, MDL);
1376: return ISC_R_INVALIDARG;
1377: }
1378: if (((struct host_decl *)(*lp)) -> flags & HOST_DECL_DELETED) {
1379: omapi_object_dereference (lp, MDL);
1380: }
1381: }
1382:
1383: /* Now look for a client identifier. */
1384: status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
1385: if (status == ISC_R_SUCCESS) {
1386: host = (struct host_decl *)0;
1387: host_hash_lookup (&host, host_uid_hash,
1388: tv -> value -> u.buffer.value,
1389: tv -> value -> u.buffer.len, MDL);
1390: omapi_value_dereference (&tv, MDL);
1391:
1392: if (*lp && *lp != (omapi_object_t *)host) {
1393: omapi_object_dereference (lp, MDL);
1394: if (host)
1395: host_dereference (&host, MDL);
1396: return ISC_R_KEYCONFLICT;
1397: } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
1398: if (*lp)
1399: omapi_object_dereference (lp, MDL);
1400: if (host)
1401: host_dereference (&host, MDL);
1402: return ISC_R_NOTFOUND;
1403: } else if (!*lp) {
1404: /* XXX fix so that hash lookup itself creates
1405: XXX the reference. */
1406: omapi_object_reference (lp,
1407: (omapi_object_t *)host, MDL);
1408: host_dereference (&host, MDL);
1409: }
1410: }
1411:
1412: /* Now look for a hardware address. */
1413: status = omapi_get_value_str (ref, id, "hardware-address", &tv);
1414: if (status == ISC_R_SUCCESS) {
1415: unsigned char *haddr;
1416: unsigned int len;
1417:
1418: len = tv -> value -> u.buffer.len + 1;
1419: haddr = dmalloc (len, MDL);
1420: if (!haddr) {
1421: omapi_value_dereference (&tv, MDL);
1422: return ISC_R_NOMEMORY;
1423: }
1424:
1425: memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
1426: omapi_value_dereference (&tv, MDL);
1427:
1428: status = omapi_get_value_str (ref, id, "hardware-type", &tv);
1429: if (status == ISC_R_SUCCESS) {
1430: if (tv -> value -> type == omapi_datatype_data) {
1431: if ((tv -> value -> u.buffer.len != 4) ||
1432: (tv -> value -> u.buffer.value[0] != 0) ||
1433: (tv -> value -> u.buffer.value[1] != 0) ||
1434: (tv -> value -> u.buffer.value[2] != 0)) {
1435: omapi_value_dereference (&tv, MDL);
1436: dfree (haddr, MDL);
1437: return ISC_R_INVALIDARG;
1438: }
1439:
1440: haddr[0] = tv -> value -> u.buffer.value[3];
1441: } else if (tv -> value -> type == omapi_datatype_int) {
1442: haddr[0] = (unsigned char)
1443: tv -> value -> u.integer;
1444: } else {
1445: omapi_value_dereference (&tv, MDL);
1446: dfree (haddr, MDL);
1447: return ISC_R_INVALIDARG;
1448: }
1449:
1450: omapi_value_dereference (&tv, MDL);
1451: } else {
1452: /* If no hardware-type is specified, default to
1453: ethernet. This may or may not be a good idea,
1454: but Telus is currently relying on this behavior.
1455: - DPN */
1456: haddr[0] = HTYPE_ETHER;
1457: }
1458:
1459: host = (struct host_decl *)0;
1460: host_hash_lookup (&host, host_hw_addr_hash, haddr, len, MDL);
1461: dfree (haddr, MDL);
1462:
1463: if (*lp && *lp != (omapi_object_t *)host) {
1464: omapi_object_dereference (lp, MDL);
1465: if (host)
1466: host_dereference (&host, MDL);
1467: return ISC_R_KEYCONFLICT;
1468: } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
1469: if (*lp)
1470: omapi_object_dereference (lp, MDL);
1471: if (host)
1472: host_dereference (&host, MDL);
1473: return ISC_R_NOTFOUND;
1474: } else if (!*lp) {
1475: /* XXX fix so that hash lookup itself creates
1476: XXX the reference. */
1477: omapi_object_reference (lp,
1478: (omapi_object_t *)host, MDL);
1479: host_dereference (&host, MDL);
1480: }
1481: }
1482:
1483: /* Now look for an ip address. */
1484: status = omapi_get_value_str (ref, id, "ip-address", &tv);
1485: if (status == ISC_R_SUCCESS) {
1486: struct lease *l;
1487:
1488: /* first find the lease for this ip address */
1489: l = (struct lease *)0;
1490: lease_ip_hash_lookup(&l, lease_ip_addr_hash,
1491: tv->value->u.buffer.value,
1492: tv->value->u.buffer.len, MDL);
1493: omapi_value_dereference (&tv, MDL);
1494:
1495: if (!l && !*lp)
1496: return ISC_R_NOTFOUND;
1497:
1498: if (l) {
1499: /* now use that to get a host */
1500: host = (struct host_decl *)0;
1501: host_hash_lookup (&host, host_hw_addr_hash,
1502: l -> hardware_addr.hbuf,
1503: l -> hardware_addr.hlen, MDL);
1504:
1505: if (host && *lp && *lp != (omapi_object_t *)host) {
1506: omapi_object_dereference (lp, MDL);
1507: if (host)
1508: host_dereference (&host, MDL);
1509: return ISC_R_KEYCONFLICT;
1510: } else if (!host || (host -> flags &
1511: HOST_DECL_DELETED)) {
1512: if (host)
1513: host_dereference (&host, MDL);
1514: if (!*lp)
1515: return ISC_R_NOTFOUND;
1516: } else if (!*lp) {
1517: /* XXX fix so that hash lookup itself creates
1518: XXX the reference. */
1519: omapi_object_reference (lp, (omapi_object_t *)host,
1520: MDL);
1521: host_dereference (&host, MDL);
1522: }
1523: lease_dereference (&l, MDL);
1524: }
1525: }
1526:
1527: /* Now look for a name. */
1528: status = omapi_get_value_str (ref, id, "name", &tv);
1529: if (status == ISC_R_SUCCESS) {
1530: host = (struct host_decl *)0;
1531: host_hash_lookup (&host, host_name_hash,
1532: tv -> value -> u.buffer.value,
1533: tv -> value -> u.buffer.len, MDL);
1534: omapi_value_dereference (&tv, MDL);
1535:
1536: if (*lp && *lp != (omapi_object_t *)host) {
1537: omapi_object_dereference (lp, MDL);
1538: if (host)
1539: host_dereference (&host, MDL);
1540: return ISC_R_KEYCONFLICT;
1541: } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
1542: if (host)
1543: host_dereference (&host, MDL);
1544: return ISC_R_NOTFOUND;
1545: } else if (!*lp) {
1546: /* XXX fix so that hash lookup itself creates
1547: XXX the reference. */
1548: omapi_object_reference (lp,
1549: (omapi_object_t *)host, MDL);
1550: host_dereference (&host, MDL);
1551: }
1552: }
1553:
1554: /* If we get to here without finding a host, no valid key was
1555: specified. */
1556: if (!*lp)
1557: return ISC_R_NOKEYS;
1558: return ISC_R_SUCCESS;
1559: }
1560:
1561: isc_result_t dhcp_host_create (omapi_object_t **lp,
1562: omapi_object_t *id)
1563: {
1564: struct host_decl *hp;
1565: isc_result_t status;
1566: hp = (struct host_decl *)0;
1567: status = host_allocate (&hp, MDL);
1568: if (status != ISC_R_SUCCESS)
1569: return status;
1570: group_reference (&hp -> group, root_group, MDL);
1571: hp -> flags = HOST_DECL_DYNAMIC;
1572: status = omapi_object_reference (lp, (omapi_object_t *)hp, MDL);
1573: host_dereference (&hp, MDL);
1574: return status;
1575: }
1576:
1577: isc_result_t dhcp_host_remove (omapi_object_t *lp,
1578: omapi_object_t *id)
1579: {
1580: struct host_decl *hp;
1581: if (lp -> type != dhcp_type_host)
1582: return ISC_R_INVALIDARG;
1583: hp = (struct host_decl *)lp;
1584:
1585: #ifdef DEBUG_OMAPI
1586: log_debug ("OMAPI delete host %s", hp -> name);
1587: #endif
1588: delete_host (hp, 1);
1589: return ISC_R_SUCCESS;
1590: }
1591:
1592: isc_result_t dhcp_pool_set_value (omapi_object_t *h,
1593: omapi_object_t *id,
1594: omapi_data_string_t *name,
1595: omapi_typed_data_t *value)
1596: {
1597: struct pool *pool;
1598: isc_result_t status;
1599:
1600: if (h -> type != dhcp_type_pool)
1601: return ISC_R_INVALIDARG;
1602: pool = (struct pool *)h;
1603:
1604: /* No values to set yet. */
1605:
1606: /* Try to find some inner object that can take the value. */
1607: if (h -> inner && h -> inner -> type -> set_value) {
1608: status = ((*(h -> inner -> type -> set_value))
1609: (h -> inner, id, name, value));
1610: if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
1611: return status;
1612: }
1613:
1614: return ISC_R_UNKNOWNATTRIBUTE;
1615: }
1616:
1617:
1618: isc_result_t dhcp_pool_get_value (omapi_object_t *h, omapi_object_t *id,
1619: omapi_data_string_t *name,
1620: omapi_value_t **value)
1621: {
1622: struct pool *pool;
1623: isc_result_t status;
1624:
1625: if (h -> type != dhcp_type_pool)
1626: return ISC_R_INVALIDARG;
1627: pool = (struct pool *)h;
1628:
1629: /* No values to get yet. */
1630:
1631: /* Try to find some inner object that can provide the value. */
1632: if (h -> inner && h -> inner -> type -> get_value) {
1633: status = ((*(h -> inner -> type -> get_value))
1634: (h -> inner, id, name, value));
1635: if (status == ISC_R_SUCCESS)
1636: return status;
1637: }
1638: return ISC_R_UNKNOWNATTRIBUTE;
1639: }
1640:
1641: isc_result_t dhcp_pool_destroy (omapi_object_t *h, const char *file, int line)
1642: {
1643: struct pool *pool;
1644: #if defined (DEBUG_MEMORY_LEAKAGE) || \
1645: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1646: struct permit *pc, *pn;
1647: #endif
1648:
1649: if (h -> type != dhcp_type_pool)
1650: return ISC_R_INVALIDARG;
1651: pool = (struct pool *)h;
1652:
1653: #if defined (DEBUG_MEMORY_LEAKAGE) || \
1654: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1655: if (pool -> next)
1656: pool_dereference (&pool -> next, file, line);
1657: if (pool -> group)
1658: group_dereference (&pool -> group, file, line);
1659: if (pool -> shared_network)
1660: shared_network_dereference (&pool -> shared_network, file, line);
1661: if (pool -> active)
1662: lease_dereference (&pool -> active, file, line);
1663: if (pool -> expired)
1664: lease_dereference (&pool -> expired, file, line);
1665: if (pool -> free)
1666: lease_dereference (&pool -> free, file, line);
1667: if (pool -> backup)
1668: lease_dereference (&pool -> backup, file, line);
1669: if (pool -> abandoned)
1670: lease_dereference (&pool -> abandoned, file, line);
1671: #if defined (FAILOVER_PROTOCOL)
1672: if (pool -> failover_peer)
1673: dhcp_failover_state_dereference (&pool -> failover_peer,
1674: file, line);
1675: #endif
1676: for (pc = pool -> permit_list; pc; pc = pn) {
1677: pn = pc -> next;
1678: free_permit (pc, file, line);
1679: }
1680: pool -> permit_list = (struct permit *)0;
1681:
1682: for (pc = pool -> prohibit_list; pc; pc = pn) {
1683: pn = pc -> next;
1684: free_permit (pc, file, line);
1685: }
1686: pool -> prohibit_list = (struct permit *)0;
1687: #endif
1688:
1689: return ISC_R_SUCCESS;
1690: }
1691:
1692: isc_result_t dhcp_pool_signal_handler (omapi_object_t *h,
1693: const char *name, va_list ap)
1694: {
1695: struct pool *pool;
1696: isc_result_t status;
1697: int updatep = 0;
1698:
1699: if (h -> type != dhcp_type_pool)
1700: return ISC_R_INVALIDARG;
1701: pool = (struct pool *)h;
1702:
1703: /* Can't write pools yet. */
1704:
1705: /* Try to find some inner object that can take the value. */
1706: if (h -> inner && h -> inner -> type -> signal_handler) {
1707: status = ((*(h -> inner -> type -> signal_handler))
1708: (h -> inner, name, ap));
1709: if (status == ISC_R_SUCCESS)
1710: return status;
1711: }
1712: if (updatep)
1713: return ISC_R_SUCCESS;
1714: return ISC_R_NOTFOUND;
1715: }
1716:
1717: isc_result_t dhcp_pool_stuff_values (omapi_object_t *c,
1718: omapi_object_t *id,
1719: omapi_object_t *h)
1720: {
1721: struct pool *pool;
1722: isc_result_t status;
1723:
1724: if (h -> type != dhcp_type_pool)
1725: return ISC_R_INVALIDARG;
1726: pool = (struct pool *)h;
1727:
1728: /* Can't stuff pool values yet. */
1729:
1730: /* Write out the inner object, if any. */
1731: if (h -> inner && h -> inner -> type -> stuff_values) {
1732: status = ((*(h -> inner -> type -> stuff_values))
1733: (c, id, h -> inner));
1734: if (status == ISC_R_SUCCESS)
1735: return status;
1736: }
1737:
1738: return ISC_R_SUCCESS;
1739: }
1740:
1741: isc_result_t dhcp_pool_lookup (omapi_object_t **lp,
1742: omapi_object_t *id, omapi_object_t *ref)
1743: {
1744: /* Can't look up pools yet. */
1745:
1746: /* If we get to here without finding a pool, no valid key was
1747: specified. */
1748: if (!*lp)
1749: return ISC_R_NOKEYS;
1750: return ISC_R_SUCCESS;
1751: }
1752:
1753: isc_result_t dhcp_pool_create (omapi_object_t **lp,
1754: omapi_object_t *id)
1755: {
1756: return ISC_R_NOTIMPLEMENTED;
1757: }
1758:
1759: isc_result_t dhcp_pool_remove (omapi_object_t *lp,
1760: omapi_object_t *id)
1761: {
1762: return ISC_R_NOTIMPLEMENTED;
1763: }
1764:
1765: static isc_result_t
1766: class_set_value (omapi_object_t *h,
1767: omapi_object_t *id,
1768: omapi_data_string_t *name,
1769: omapi_typed_data_t *value)
1770: {
1771: struct class *class;
1772: struct class *superclass = 0;
1773: isc_result_t status;
1774: int issubclass = (h -> type == dhcp_type_subclass);
1775:
1776: class = (struct class *)h;
1777:
1778: if (!omapi_ds_strcmp(name, "name")) {
1779: char *tname;
1780:
1781: if (class->name)
1782: return ISC_R_EXISTS;
1783:
1784: if ((tname = dmalloc(value->u.buffer.len + 1, MDL)) == NULL) {
1785: return ISC_R_NOMEMORY;
1786: }
1787:
1788: /* tname is null terminated from dmalloc() */
1789: memcpy(tname, value->u.buffer.value, value->u.buffer.len);
1790:
1791: if (issubclass) {
1792: status = find_class(&superclass, tname, MDL);
1793: dfree(tname, MDL);
1794:
1795: if (status == ISC_R_NOTFOUND)
1796: return status;
1797:
1798: if (class->superclass != NULL)
1799: class_dereference(&class->superclass, MDL);
1800:
1801: class_reference(&class->superclass, superclass, MDL);
1802: } else if (value -> type == omapi_datatype_data ||
1803: value -> type == omapi_datatype_string) {
1804: class->name = dmalloc(value->u.buffer.len + 1, MDL);
1805: if (!class->name)
1806: return ISC_R_NOMEMORY;
1807:
1808: /* class->name is null-terminated from dmalloc() */
1809: memcpy(class->name, value->u.buffer.value,
1810: value->u.buffer.len);
1811: } else
1812: return ISC_R_INVALIDARG;
1813:
1814: return ISC_R_SUCCESS;
1815: }
1816:
1817:
1818: if (issubclass && !omapi_ds_strcmp(name, "hashstring")) {
1819: if (class->hash_string.data)
1820: return ISC_R_EXISTS;
1821:
1822: if (value->type == omapi_datatype_data ||
1823: value->type == omapi_datatype_string) {
1824: if (!buffer_allocate(&class->hash_string.buffer,
1825: value->u.buffer.len, MDL))
1826: return ISC_R_NOMEMORY;
1827: class->hash_string.data =
1828: class->hash_string.buffer->data;
1829: memcpy(class->hash_string.buffer->data,
1830: value->u.buffer.value, value->u.buffer.len);
1831: class->hash_string.len = value->u.buffer.len;
1832: } else
1833: return ISC_R_INVALIDARG;
1834:
1835: return ISC_R_SUCCESS;
1836: }
1837:
1838: if (!omapi_ds_strcmp(name, "group")) {
1839: if (value->type == omapi_datatype_data ||
1840: value->type == omapi_datatype_string) {
1841: struct group_object *group = NULL;
1842:
1843: group_hash_lookup(&group, group_name_hash,
1844: (char *)value->u.buffer.value,
1845: value->u.buffer.len, MDL);
1846: if (!group || (group->flags & GROUP_OBJECT_DELETED))
1847: return ISC_R_NOTFOUND;
1848: if (class->group)
1849: group_dereference(&class->group, MDL);
1850: group_reference(&class->group, group->group, MDL);
1851: group_object_dereference(&group, MDL);
1852: } else
1853: return ISC_R_INVALIDARG;
1854:
1855: return ISC_R_SUCCESS;
1856: }
1857:
1858:
1859: /* note we do not support full expressions via omapi because the
1860: expressions parser needs to be re-done to support parsing from
1861: strings and not just files. */
1862:
1863: if (!omapi_ds_strcmp(name, "match")) {
1864: if (value->type == omapi_datatype_data ||
1865: value->type == omapi_datatype_string) {
1866: unsigned minlen = (value->u.buffer.len > 8 ?
1867: 8 : value->u.buffer.len);
1868:
1869: if (!strncmp("hardware",
1870: (char *)value->u.buffer.value, minlen))
1871: {
1872: if (!expression_allocate(&class->submatch, MDL))
1873: return ISC_R_NOMEMORY;
1874:
1875: class->submatch->op = expr_hardware;
1876: } else
1877: return ISC_R_INVALIDARG;
1878: } else
1879: return ISC_R_INVALIDARG;
1880:
1881: return ISC_R_SUCCESS;
1882: }
1883:
1884:
1885: if (!omapi_ds_strcmp(name, "option")) {
1886: if (value->type == omapi_datatype_data ||
1887: value->type == omapi_datatype_string) {
1888: /* XXXJAB support 'options' here. */
1889: /* XXXJAB specifically 'bootfile-name' */
1890: return ISC_R_INVALIDARG; /* XXX tmp */
1891: } else
1892: return ISC_R_INVALIDARG;
1893:
1894: /*
1895: * Currently no way to get here, if we update the above
1896: * code so that we do get here this return needs to be
1897: * uncommented.
1898: * return ISC_R_SUCCESS;
1899: */
1900: }
1901:
1902:
1903: /* Try to find some inner object that can take the value. */
1904: if (h->inner && h->inner->type->set_value) {
1905: status = ((*(h->inner->type->set_value))
1906: (h->inner, id, name, value));
1907: if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
1908: return status;
1909: }
1910:
1911: return ISC_R_UNKNOWNATTRIBUTE;
1912: }
1913:
1914:
1915:
1916: isc_result_t dhcp_class_set_value (omapi_object_t *h,
1917: omapi_object_t *id,
1918: omapi_data_string_t *name,
1919: omapi_typed_data_t *value)
1920: {
1921: if (h -> type != dhcp_type_class)
1922: return ISC_R_INVALIDARG;
1923:
1924: return class_set_value(h, id, name, value);
1925: }
1926:
1927: isc_result_t dhcp_class_get_value (omapi_object_t *h, omapi_object_t *id,
1928: omapi_data_string_t *name,
1929: omapi_value_t **value)
1930: {
1931: struct class *class;
1932: isc_result_t status;
1933:
1934: if (h -> type != dhcp_type_class)
1935: return ISC_R_INVALIDARG;
1936: class = (struct class *)h;
1937:
1938: if (!omapi_ds_strcmp (name, "name"))
1939: return omapi_make_string_value (value, name, class -> name,
1940: MDL);
1941:
1942: /* Try to find some inner object that can provide the value. */
1943: if (h -> inner && h -> inner -> type -> get_value) {
1944: status = ((*(h -> inner -> type -> get_value))
1945: (h -> inner, id, name, value));
1946: if (status == ISC_R_SUCCESS)
1947: return status;
1948: }
1949: return ISC_R_UNKNOWNATTRIBUTE;
1950: }
1951:
1952: isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
1953: {
1954: struct class *class;
1955:
1956: if (h -> type != dhcp_type_class && h -> type != dhcp_type_subclass)
1957: return ISC_R_INVALIDARG;
1958: class = (struct class *)h;
1959:
1960: #if defined (DEBUG_MEMORY_LEAKAGE) || \
1961: defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1962: if (class -> nic)
1963: class_dereference (&class -> nic, file, line);
1964: if (class -> superclass)
1965: class_dereference (&class -> superclass, file, line);
1966: if (class -> name) {
1967: dfree (class -> name, file, line);
1968: class -> name = (char *)0;
1969: }
1970: if (class -> billed_leases) {
1971: int i;
1972: for (i = 0; i < class -> lease_limit; i++) {
1973: if (class -> billed_leases [i]) {
1974: lease_dereference (&class -> billed_leases [i],
1975: file, line);
1976: }
1977: }
1978: dfree (class -> billed_leases, file, line);
1979: class -> billed_leases = (struct lease **)0;
1980: }
1981: if (class -> hash) {
1982: class_free_hash_table (&class -> hash, file, line);
1983: class -> hash = (class_hash_t *)0;
1984: }
1985: data_string_forget (&class -> hash_string, file, line);
1986:
1987: if (class -> expr)
1988: expression_dereference (&class -> expr, file, line);
1989: if (class -> submatch)
1990: expression_dereference (&class -> submatch, file, line);
1991: if (class -> group)
1992: group_dereference (&class -> group, file, line);
1993: if (class -> statements)
1994: executable_statement_dereference (&class -> statements,
1995: file, line);
1996: if (class -> superclass)
1997: class_dereference (&class -> superclass, file, line);
1998: #endif
1999:
2000: return ISC_R_SUCCESS;
2001: }
2002:
2003: static isc_result_t
2004: class_signal_handler(omapi_object_t *h,
2005: const char *name, va_list ap)
2006: {
2007: struct class *class = (struct class *)h;
2008: isc_result_t status;
2009: int updatep = 0;
2010: int issubclass;
2011:
2012: issubclass = (h -> type == dhcp_type_subclass);
2013:
2014: if (!strcmp (name, "updated")) {
2015:
2016: if (!issubclass) {
2017: if (class -> name == 0 || strlen(class -> name) == 0) {
2018: return ISC_R_INVALIDARG;
2019: }
2020: } else {
2021: if (class -> superclass == 0) {
2022: return ISC_R_INVALIDARG; /* didn't give name */
2023: }
2024:
2025: if (class -> hash_string.data == NULL) {
2026: return ISC_R_INVALIDARG;
2027: }
2028: }
2029:
2030:
2031: if (issubclass) {
2032: if (!class -> superclass -> hash)
2033: class_new_hash(&class->superclass->hash,
2034: SCLASS_HASH_SIZE, MDL);
2035:
2036: add_hash (class -> superclass -> hash,
2037: class -> hash_string.data,
2038: class -> hash_string.len,
2039: (void *)class, MDL);
2040: }
2041:
2042:
2043: #ifdef DEBUG_OMAPI
2044: if (issubclass) {
2045: log_debug ("OMAPI added subclass %s",
2046: class -> superclass -> name);
2047: } else {
2048: log_debug ("OMAPI added class %s", class -> name);
2049: }
2050: #endif
2051:
2052: status = enter_class (class, 1, 1);
2053: if (status != ISC_R_SUCCESS)
2054: return status;
2055: updatep = 1;
2056: }
2057:
2058: /* Try to find some inner object that can take the value. */
2059: if (h -> inner && h -> inner -> type -> signal_handler) {
2060: status = ((*(h -> inner -> type -> signal_handler))
2061: (h -> inner, name, ap));
2062: if (status == ISC_R_SUCCESS)
2063: return status;
2064: }
2065:
2066: if (updatep)
2067: return ISC_R_SUCCESS;
2068:
2069: return ISC_R_NOTFOUND;
2070: }
2071:
2072:
2073: isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
2074: const char *name, va_list ap)
2075: {
2076: if (h -> type != dhcp_type_class)
2077: return ISC_R_INVALIDARG;
2078:
2079: return class_signal_handler(h, name, ap);
2080: }
2081:
2082: isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
2083: omapi_object_t *id,
2084: omapi_object_t *h)
2085: {
2086: struct class *class;
2087: isc_result_t status;
2088:
2089: if (h -> type != dhcp_type_class)
2090: return ISC_R_INVALIDARG;
2091: class = (struct class *)h;
2092:
2093: /* Can't stuff class values yet. */
2094:
2095: /* Write out the inner object, if any. */
2096: if (h -> inner && h -> inner -> type -> stuff_values) {
2097: status = ((*(h -> inner -> type -> stuff_values))
2098: (c, id, h -> inner));
2099: if (status == ISC_R_SUCCESS)
2100: return status;
2101: }
2102:
2103: return ISC_R_SUCCESS;
2104: }
2105:
2106: static isc_result_t class_lookup (omapi_object_t **lp,
2107: omapi_object_t *id, omapi_object_t *ref,
2108: omapi_object_type_t *typewanted)
2109: {
2110: omapi_value_t *nv = (omapi_value_t *)0;
2111: omapi_value_t *hv = (omapi_value_t *)0;
2112: isc_result_t status;
2113: struct class *class = 0;
2114: struct class *subclass = 0;
2115:
2116: *lp = NULL;
2117:
2118: /* see if we have a name */
2119: status = omapi_get_value_str (ref, id, "name", &nv);
2120: if (status == ISC_R_SUCCESS) {
2121: char *name = dmalloc(nv -> value -> u.buffer.len + 1, MDL);
2122: memcpy (name,
2123: nv -> value -> u.buffer.value,
2124: nv -> value -> u.buffer.len);
2125:
2126: omapi_value_dereference (&nv, MDL);
2127:
2128: find_class(&class, name, MDL);
2129:
2130: dfree(name, MDL);
2131:
2132: if (class == NULL) {
2133: return ISC_R_NOTFOUND;
2134: }
2135:
2136: if (typewanted == dhcp_type_subclass) {
2137: status = omapi_get_value_str (ref, id,
2138: "hashstring", &hv);
2139: if (status != ISC_R_SUCCESS) {
2140: class_dereference(&class, MDL);
2141: return ISC_R_NOKEYS;
2142: }
2143:
2144: if (hv -> value -> type != omapi_datatype_data &&
2145: hv -> value -> type != omapi_datatype_string) {
2146: class_dereference(&class, MDL);
2147: omapi_value_dereference (&hv, MDL);
2148: return ISC_R_NOKEYS;
2149: }
2150:
2151: class_hash_lookup (&subclass, class -> hash,
2152: (const char *)
2153: hv -> value -> u.buffer.value,
2154: hv -> value -> u.buffer.len, MDL);
2155:
2156: omapi_value_dereference (&hv, MDL);
2157:
2158: class_dereference(&class, MDL);
2159:
2160: if (subclass == NULL) {
2161: return ISC_R_NOTFOUND;
2162: }
2163:
2164: class_reference(&class, subclass, MDL);
2165: class_dereference(&subclass, MDL);
2166: }
2167:
2168:
2169: /* Don't return the object if the type is wrong. */
2170: if (class -> type != typewanted) {
2171: class_dereference (&class, MDL);
2172: return ISC_R_INVALIDARG;
2173: }
2174:
2175: if (class -> flags & CLASS_DECL_DELETED) {
2176: class_dereference (&class, MDL);
2177: }
2178:
2179: omapi_object_reference(lp, (omapi_object_t *)class, MDL);
2180:
2181: return ISC_R_SUCCESS;
2182: }
2183:
2184: return ISC_R_NOKEYS;
2185: }
2186:
2187:
2188: isc_result_t dhcp_class_lookup (omapi_object_t **lp,
2189: omapi_object_t *id, omapi_object_t *ref)
2190: {
2191: return class_lookup(lp, id, ref, dhcp_type_class);
2192: }
2193:
2194: isc_result_t dhcp_class_create (omapi_object_t **lp,
2195: omapi_object_t *id)
2196: {
2197: struct class *cp = 0;
2198: isc_result_t status;
2199:
2200: status = class_allocate(&cp, MDL);
2201: if (status != ISC_R_SUCCESS)
2202: return status;
2203:
2204: group_reference (&cp -> group, root_group, MDL);
2205: cp -> flags = CLASS_DECL_DYNAMIC;
2206: status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
2207: class_dereference (&cp, MDL);
2208: return status;
2209: }
2210:
2211: isc_result_t dhcp_class_remove (omapi_object_t *lp,
2212: omapi_object_t *id)
2213: {
2214: struct class *cp;
2215: if (lp -> type != dhcp_type_class)
2216: return ISC_R_INVALIDARG;
2217: cp = (struct class *)lp;
2218:
2219: #ifdef DEBUG_OMAPI
2220: log_debug ("OMAPI delete class %s", cp -> name);
2221: #endif
2222:
2223: delete_class (cp, 1);
2224: return ISC_R_SUCCESS;
2225: }
2226:
2227: isc_result_t dhcp_subclass_set_value (omapi_object_t *h,
2228: omapi_object_t *id,
2229: omapi_data_string_t *name,
2230: omapi_typed_data_t *value)
2231: {
2232: if (h -> type != dhcp_type_subclass)
2233: return ISC_R_INVALIDARG;
2234:
2235: return class_set_value(h, id, name, value);
2236: }
2237:
2238:
2239: isc_result_t dhcp_subclass_get_value (omapi_object_t *h, omapi_object_t *id,
2240: omapi_data_string_t *name,
2241: omapi_value_t **value)
2242: {
2243: struct class *subclass;
2244: isc_result_t status;
2245:
2246: if (h -> type != dhcp_type_class)
2247: return ISC_R_INVALIDARG;
2248: subclass = (struct class *)h;
2249: if (subclass -> name != 0)
2250: return ISC_R_INVALIDARG;
2251:
2252: /* XXXJAB No values to get yet. */
2253:
2254: /* Try to find some inner object that can provide the value. */
2255: if (h -> inner && h -> inner -> type -> get_value) {
2256: status = ((*(h -> inner -> type -> get_value))
2257: (h -> inner, id, name, value));
2258: if (status == ISC_R_SUCCESS)
2259: return status;
2260: }
2261: return ISC_R_UNKNOWNATTRIBUTE;
2262: }
2263:
2264: isc_result_t dhcp_subclass_signal_handler (omapi_object_t *h,
2265: const char *name, va_list ap)
2266: {
2267: if (h -> type != dhcp_type_subclass)
2268: return ISC_R_INVALIDARG;
2269:
2270: return class_signal_handler(h, name, ap);
2271: }
2272:
2273:
2274: isc_result_t dhcp_subclass_stuff_values (omapi_object_t *c,
2275: omapi_object_t *id,
2276: omapi_object_t *h)
2277: {
2278: struct class *subclass;
2279: isc_result_t status;
2280:
2281: if (h -> type != dhcp_type_class)
2282: return ISC_R_INVALIDARG;
2283: subclass = (struct class *)h;
2284: if (subclass -> name != 0)
2285: return ISC_R_INVALIDARG;
2286:
2287:
2288: /* Can't stuff subclass values yet. */
2289:
2290: /* Write out the inner object, if any. */
2291: if (h -> inner && h -> inner -> type -> stuff_values) {
2292: status = ((*(h -> inner -> type -> stuff_values))
2293: (c, id, h -> inner));
2294: if (status == ISC_R_SUCCESS)
2295: return status;
2296: }
2297:
2298: return ISC_R_SUCCESS;
2299: }
2300:
2301: isc_result_t dhcp_subclass_lookup (omapi_object_t **lp,
2302: omapi_object_t *id, omapi_object_t *ref)
2303: {
2304: return class_lookup(lp, id, ref, dhcp_type_subclass);
2305: }
2306:
2307:
2308:
2309:
2310: isc_result_t dhcp_subclass_create (omapi_object_t **lp,
2311: omapi_object_t *id)
2312: {
2313: struct class *cp = 0;
2314: isc_result_t status;
2315:
2316: /*
2317: * XXX
2318: * NOTE: subclasses and classes have the same internal type, which makes it
2319: * difficult to tell them apart. Specifically, in this function we need to
2320: * create a class object (because there is no such thing as a subclass
2321: * object), but one field of the class object is the type (which has the
2322: * value dhcp_type_class), and it is from here that all the other omapi
2323: * functions are accessed. So, even though there's a whole suite of
2324: * subclass functions registered, they won't get used. Now we could change
2325: * the type pointer after creating the class object, but I'm not certain
2326: * that won't break something else.
2327: */
2328:
2329: status = subclass_allocate(&cp, MDL);
2330: if (status != ISC_R_SUCCESS)
2331: return status;
2332: group_reference (&cp -> group, root_group, MDL);
2333:
2334: cp -> flags = CLASS_DECL_DYNAMIC;
2335:
2336: status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
2337: subclass_dereference (&cp, MDL);
2338: return status;
2339: }
2340:
2341: isc_result_t dhcp_subclass_remove (omapi_object_t *lp,
2342: omapi_object_t *id)
2343: {
2344: #if 1
2345:
2346: log_fatal("calling dhcp_subclass_set_value");
2347: /* this should never be called see dhcp_subclass_create for why */
2348:
2349: #else
2350:
2351: struct class *cp;
2352: if (lp -> type != dhcp_type_subclass)
2353: return ISC_R_INVALIDARG;
2354: cp = (struct class *)lp;
2355:
2356: #ifdef DEBUG_OMAPI
2357: log_debug ("OMAPI delete subclass %s", cp -> name);
2358: #endif
2359:
2360: delete_class (cp, 1);
2361:
2362: #endif
2363:
2364: return ISC_R_SUCCESS;
2365: }
2366:
2367: isc_result_t binding_scope_set_value (struct binding_scope *scope, int createp,
2368: omapi_data_string_t *name,
2369: omapi_typed_data_t *value)
2370: {
2371: struct binding *bp;
2372: char *nname;
2373: struct binding_value *nv;
2374: nname = dmalloc (name -> len + 1, MDL);
2375: if (!nname)
2376: return ISC_R_NOMEMORY;
2377: memcpy (nname, name -> value, name -> len);
2378: nname [name -> len] = 0;
2379: bp = find_binding (scope, nname);
2380: if (!bp && !createp) {
2381: dfree (nname, MDL);
2382: return ISC_R_UNKNOWNATTRIBUTE;
2383: }
2384: if (!value) {
2385: dfree (nname, MDL);
2386: if (!bp)
2387: return ISC_R_UNKNOWNATTRIBUTE;
2388: binding_value_dereference (&bp -> value, MDL);
2389: return ISC_R_SUCCESS;
2390: }
2391:
2392: nv = (struct binding_value *)0;
2393: if (!binding_value_allocate (&nv, MDL)) {
2394: dfree (nname, MDL);
2395: return ISC_R_NOMEMORY;
2396: }
2397: switch (value -> type) {
2398: case omapi_datatype_int:
2399: nv -> type = binding_numeric;
2400: nv -> value.intval = value -> u.integer;
2401: break;
2402:
2403: case omapi_datatype_string:
2404: case omapi_datatype_data:
2405: if (!buffer_allocate (&nv -> value.data.buffer,
2406: value -> u.buffer.len, MDL)) {
2407: binding_value_dereference (&nv, MDL);
2408: dfree (nname, MDL);
2409: return ISC_R_NOMEMORY;
2410: }
2411: memcpy (&nv -> value.data.buffer -> data [1],
2412: value -> u.buffer.value, value -> u.buffer.len);
2413: nv -> value.data.len = value -> u.buffer.len;
2414: break;
2415:
2416: case omapi_datatype_object:
2417: binding_value_dereference (&nv, MDL);
2418: dfree (nname, MDL);
2419: return ISC_R_INVALIDARG;
2420: }
2421:
2422: if (!bp) {
2423: bp = dmalloc (sizeof *bp, MDL);
2424: if (!bp) {
2425: binding_value_dereference (&nv, MDL);
2426: dfree (nname, MDL);
2427: return ISC_R_NOMEMORY;
2428: }
2429: memset (bp, 0, sizeof *bp);
2430: bp -> name = nname;
2431: nname = (char *)0;
2432: bp -> next = scope -> bindings;
2433: scope -> bindings = bp;
2434: } else {
2435: if (bp -> value)
2436: binding_value_dereference (&bp -> value, MDL);
2437: dfree (nname, MDL);
2438: }
2439: binding_value_reference (&bp -> value, nv, MDL);
2440: binding_value_dereference (&nv, MDL);
2441: return ISC_R_SUCCESS;
2442: }
2443:
2444: isc_result_t binding_scope_get_value (omapi_value_t **value,
2445: struct binding_scope *scope,
2446: omapi_data_string_t *name)
2447: {
2448: struct binding *bp;
2449: omapi_typed_data_t *td;
2450: isc_result_t status;
2451: char *nname;
2452: nname = dmalloc (name -> len + 1, MDL);
2453: if (!nname)
2454: return ISC_R_NOMEMORY;
2455: memcpy (nname, name -> value, name -> len);
2456: nname [name -> len] = 0;
2457: bp = find_binding (scope, nname);
2458: dfree (nname, MDL);
2459: if (!bp)
2460: return ISC_R_UNKNOWNATTRIBUTE;
2461: if (!bp -> value)
2462: return ISC_R_UNKNOWNATTRIBUTE;
2463:
2464: switch (bp -> value -> type) {
2465: case binding_boolean:
2466: td = (omapi_typed_data_t *)0;
2467: status = omapi_typed_data_new (MDL, &td, omapi_datatype_int,
2468: bp -> value -> value.boolean);
2469: break;
2470:
2471: case binding_numeric:
2472: td = (omapi_typed_data_t *)0;
2473: status = omapi_typed_data_new (MDL, &td, omapi_datatype_int,
2474: (int)
2475: bp -> value -> value.intval);
2476: break;
2477:
2478: case binding_data:
2479: td = (omapi_typed_data_t *)0;
2480: status = omapi_typed_data_new (MDL, &td, omapi_datatype_data,
2481: bp -> value -> value.data.len);
2482: if (status != ISC_R_SUCCESS)
2483: return status;
2484: memcpy (&td -> u.buffer.value [0],
2485: bp -> value -> value.data.data,
2486: bp -> value -> value.data.len);
2487: break;
2488:
2489: /* Can't return values for these two (yet?). */
2490: case binding_dns:
2491: case binding_function:
2492: return ISC_R_INVALIDARG;
2493:
2494: default:
2495: log_fatal ("Impossible case at %s:%d.", MDL);
2496: return ISC_R_FAILURE;
2497: }
2498:
2499: if (status != ISC_R_SUCCESS)
2500: return status;
2501: status = omapi_value_new (value, MDL);
2502: if (status != ISC_R_SUCCESS) {
2503: omapi_typed_data_dereference (&td, MDL);
2504: return status;
2505: }
2506:
2507: omapi_data_string_reference (&(*value) -> name, name, MDL);
2508: omapi_typed_data_reference (&(*value) -> value, td, MDL);
2509: omapi_typed_data_dereference (&td, MDL);
2510:
2511: return ISC_R_SUCCESS;
2512: }
2513:
2514: isc_result_t binding_scope_stuff_values (omapi_object_t *c,
2515: struct binding_scope *scope)
2516: {
2517: struct binding *bp;
2518: unsigned len;
2519: isc_result_t status;
2520:
2521: for (bp = scope -> bindings; bp; bp = bp -> next) {
2522: if (bp -> value) {
2523: if (bp -> value -> type == binding_dns ||
2524: bp -> value -> type == binding_function)
2525: continue;
2526:
2527: /* Stuff the name. */
2528: len = strlen (bp -> name);
2529: status = omapi_connection_put_uint16 (c, len);
2530: if (status != ISC_R_SUCCESS)
2531: return status;
2532: status = omapi_connection_copyin (c,
2533: (unsigned char *)bp -> name,
2534: len);
2535: if (status != ISC_R_SUCCESS)
2536: return status;
2537:
2538: switch (bp -> value -> type) {
2539: case binding_boolean:
2540: status = omapi_connection_put_uint32 (c,
2541: sizeof (u_int32_t));
2542: if (status != ISC_R_SUCCESS)
2543: return status;
2544: status = (omapi_connection_put_uint32
2545: (c,
2546: ((u_int32_t)(bp -> value -> value.boolean))));
2547: break;
2548:
2549: case binding_data:
2550: status = (omapi_connection_put_uint32
2551: (c, bp -> value -> value.data.len));
2552: if (status != ISC_R_SUCCESS)
2553: return status;
2554: if (bp -> value -> value.data.len) {
2555: status = (omapi_connection_copyin
2556: (c, bp -> value -> value.data.data,
2557: bp -> value -> value.data.len));
2558: if (status != ISC_R_SUCCESS)
2559: return status;
2560: }
2561: break;
2562:
2563: case binding_numeric:
2564: status = (omapi_connection_put_uint32
2565: (c, sizeof (u_int32_t)));
2566: if (status != ISC_R_SUCCESS)
2567: return status;
2568: status = (omapi_connection_put_uint32
2569: (c, ((u_int32_t)
2570: (bp -> value -> value.intval))));
2571: break;
2572:
2573:
2574: /* NOTREACHED */
2575: case binding_dns:
2576: case binding_function:
2577: break;
2578: }
2579: }
2580: }
2581: return ISC_R_SUCCESS;
2582: }
2583:
2584: /* vim: set tabstop=8: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>