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>