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