server/omapi.c

Go to the documentation of this file.
00001 /* omapi.c
00002 
00003    OMAPI object interfaces for the DHCP server. */
00004 
00005 /*
00006  * Copyright (c) 2012-2014 by Internet Systems Consortium, Inc. ("ISC")
00007  * Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
00008  * Copyright (c) 1999-2003 by Internet Software Consortium
00009  *
00010  * Permission to use, copy, modify, and distribute this software for any
00011  * purpose with or without fee is hereby granted, provided that the above
00012  * copyright notice and this permission notice appear in all copies.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00015  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00016  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00017  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00018  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00019  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00020  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00021  *
00022  *   Internet Systems Consortium, Inc.
00023  *   950 Charter Street
00024  *   Redwood City, CA 94063
00025  *   <info@isc.org>
00026  *   https://www.isc.org/
00027  *
00028  */
00029 
00030 /* Many, many thanks to Brian Murrell and BCtel for this code - BCtel
00031    provided the funding that resulted in this code and the entire
00032    OMAPI support library being written, and Brian helped brainstorm
00033    and refine the requirements.  To the extent that this code is
00034    useful, you have Brian and BCtel to thank.  Any limitations in the
00035    code are a result of mistakes on my part.  -- Ted Lemon */
00036 
00037 #include "dhcpd.h"
00038 #include <omapip/omapip_p.h>
00039 
00040 static isc_result_t class_lookup (omapi_object_t **,
00041                                   omapi_object_t *, omapi_object_t *,
00042                                   omapi_object_type_t *);
00043 
00044 omapi_object_type_t *dhcp_type_lease;
00045 omapi_object_type_t *dhcp_type_pool;
00046 omapi_object_type_t *dhcp_type_class;
00047 omapi_object_type_t *dhcp_type_subclass;
00048 omapi_object_type_t *dhcp_type_host;
00049 #if defined (FAILOVER_PROTOCOL)
00050 omapi_object_type_t *dhcp_type_failover_state;
00051 omapi_object_type_t *dhcp_type_failover_link;
00052 omapi_object_type_t *dhcp_type_failover_listener;
00053 #endif
00054 
00055 void dhcp_db_objects_setup ()
00056 {
00057         isc_result_t status;
00058 
00059         status = omapi_object_type_register (&dhcp_type_lease,
00060                                              "lease",
00061                                              dhcp_lease_set_value,
00062                                              dhcp_lease_get_value,
00063                                              dhcp_lease_destroy,
00064                                              dhcp_lease_signal_handler,
00065                                              dhcp_lease_stuff_values,
00066                                              dhcp_lease_lookup,
00067                                              dhcp_lease_create,
00068                                              dhcp_lease_remove,
00069 #if defined (COMPACT_LEASES)
00070                                              dhcp_lease_free,
00071                                              dhcp_lease_get,
00072 #else
00073                                              0, 0,
00074 #endif
00075                                              0,
00076                                              sizeof (struct lease),
00077                                              0, RC_LEASE);
00078         if (status != ISC_R_SUCCESS)
00079                 log_fatal ("Can't register lease object type: %s",
00080                            isc_result_totext (status));
00081 
00082         status = omapi_object_type_register (&dhcp_type_class,
00083                                              "class",
00084                                              dhcp_class_set_value,
00085                                              dhcp_class_get_value,
00086                                              dhcp_class_destroy,
00087                                              dhcp_class_signal_handler,
00088                                              dhcp_class_stuff_values,
00089                                              dhcp_class_lookup,
00090                                              dhcp_class_create,
00091                                              dhcp_class_remove, 0, 0, 0,
00092                                              sizeof (struct class), 0,
00093                                              RC_MISC);
00094         if (status != ISC_R_SUCCESS)
00095                 log_fatal ("Can't register class object type: %s",
00096                            isc_result_totext (status));
00097 
00098         status = omapi_object_type_register (&dhcp_type_subclass,
00099                                              "subclass",
00100                                              dhcp_subclass_set_value,
00101                                              dhcp_subclass_get_value,
00102                                              dhcp_class_destroy,
00103                                              dhcp_subclass_signal_handler,
00104                                              dhcp_subclass_stuff_values,
00105                                              dhcp_subclass_lookup,
00106                                              dhcp_subclass_create,
00107                                              dhcp_subclass_remove, 0, 0, 0,
00108                                              sizeof (struct class), 0, RC_MISC);
00109         if (status != ISC_R_SUCCESS)
00110                 log_fatal ("Can't register subclass object type: %s",
00111                            isc_result_totext (status));
00112 
00113         status = omapi_object_type_register (&dhcp_type_pool,
00114                                              "pool",
00115                                              dhcp_pool_set_value,
00116                                              dhcp_pool_get_value,
00117                                              dhcp_pool_destroy,
00118                                              dhcp_pool_signal_handler,
00119                                              dhcp_pool_stuff_values,
00120                                              dhcp_pool_lookup,
00121                                              dhcp_pool_create,
00122                                              dhcp_pool_remove, 0, 0, 0,
00123                                              sizeof (struct pool), 0, RC_MISC);
00124 
00125         if (status != ISC_R_SUCCESS)
00126                 log_fatal ("Can't register pool object type: %s",
00127                            isc_result_totext (status));
00128 
00129         status = omapi_object_type_register (&dhcp_type_host,
00130                                              "host",
00131                                              dhcp_host_set_value,
00132                                              dhcp_host_get_value,
00133                                              dhcp_host_destroy,
00134                                              dhcp_host_signal_handler,
00135                                              dhcp_host_stuff_values,
00136                                              dhcp_host_lookup,
00137                                              dhcp_host_create,
00138                                              dhcp_host_remove, 0, 0, 0,
00139                                              sizeof (struct host_decl),
00140                                              0, RC_MISC);
00141 
00142         if (status != ISC_R_SUCCESS)
00143                 log_fatal ("Can't register host object type: %s",
00144                            isc_result_totext (status));
00145 
00146 #if defined (FAILOVER_PROTOCOL)
00147         status = omapi_object_type_register (&dhcp_type_failover_state,
00148                                              "failover-state",
00149                                              dhcp_failover_state_set_value,
00150                                              dhcp_failover_state_get_value,
00151                                              dhcp_failover_state_destroy,
00152                                              dhcp_failover_state_signal,
00153                                              dhcp_failover_state_stuff,
00154                                              dhcp_failover_state_lookup,
00155                                              dhcp_failover_state_create,
00156                                              dhcp_failover_state_remove,
00157                                              0, 0, 0,
00158                                              sizeof (dhcp_failover_state_t),
00159                                              0, RC_MISC);
00160 
00161         if (status != ISC_R_SUCCESS)
00162                 log_fatal ("Can't register failover state object type: %s",
00163                            isc_result_totext (status));
00164 
00165         status = omapi_object_type_register (&dhcp_type_failover_link,
00166                                              "failover-link",
00167                                              dhcp_failover_link_set_value,
00168                                              dhcp_failover_link_get_value,
00169                                              dhcp_failover_link_destroy,
00170                                              dhcp_failover_link_signal,
00171                                              dhcp_failover_link_stuff_values,
00172                                              0, 0, 0, 0, 0, 0,
00173                                              sizeof (dhcp_failover_link_t), 0,
00174                                              RC_MISC);
00175 
00176         if (status != ISC_R_SUCCESS)
00177                 log_fatal ("Can't register failover link object type: %s",
00178                            isc_result_totext (status));
00179 
00180         status = omapi_object_type_register (&dhcp_type_failover_listener,
00181                                              "failover-listener",
00182                                              dhcp_failover_listener_set_value,
00183                                              dhcp_failover_listener_get_value,
00184                                              dhcp_failover_listener_destroy,
00185                                              dhcp_failover_listener_signal,
00186                                              dhcp_failover_listener_stuff,
00187                                              0, 0, 0, 0, 0, 0,
00188                                              sizeof
00189                                              (dhcp_failover_listener_t), 0,
00190                                              RC_MISC);
00191 
00192         if (status != ISC_R_SUCCESS)
00193                 log_fatal ("Can't register failover listener object type: %s",
00194                            isc_result_totext (status));
00195 #endif /* FAILOVER_PROTOCOL */
00196 }
00197 
00198 isc_result_t dhcp_lease_set_value  (omapi_object_t *h,
00199                                     omapi_object_t *id,
00200                                     omapi_data_string_t *name,
00201                                     omapi_typed_data_t *value)
00202 {
00203         struct lease *lease;
00204         isc_result_t status;
00205 
00206         if (h -> type != dhcp_type_lease)
00207                 return DHCP_R_INVALIDARG;
00208         lease = (struct lease *)h;
00209 
00210         /* We're skipping a lot of things it might be interesting to
00211            set - for now, we just make it possible to whack the state. */
00212         if (!omapi_ds_strcmp (name, "state")) {
00213             unsigned long bar;
00214             const char *ols, *nls;
00215             status = omapi_get_int_value (&bar, value);
00216             if (status != ISC_R_SUCCESS)
00217                 return status;
00218 
00219             if (bar < 1 || bar > FTS_LAST)
00220                 return DHCP_R_INVALIDARG;
00221             nls = binding_state_names [bar - 1];
00222             if (lease -> binding_state >= 1 &&
00223                 lease -> binding_state <= FTS_LAST)
00224                 ols = binding_state_names [lease -> binding_state - 1];
00225             else
00226                 ols = "unknown state";
00227 
00228             if (lease -> binding_state != bar) {
00229                 lease -> next_binding_state = bar;
00230                 if (supersede_lease (lease, 0, 1, 1, 1)) {
00231                         log_info ("lease %s state changed from %s to %s",
00232                                   piaddr(lease->ip_addr), ols, nls);
00233                         return ISC_R_SUCCESS;
00234                 }
00235                 log_info ("lease %s state change from %s to %s failed.",
00236                           piaddr (lease -> ip_addr), ols, nls);
00237                 return ISC_R_IOERROR;
00238             }
00239             return DHCP_R_UNCHANGED;
00240         } else if (!omapi_ds_strcmp (name, "ip-address")) {
00241             return ISC_R_NOPERM;
00242         } else if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
00243             return DHCP_R_UNCHANGED;    /* XXX take change. */
00244         } else if (!omapi_ds_strcmp (name, "hostname")) {
00245             return DHCP_R_UNCHANGED;    /* XXX take change. */
00246         } else if (!omapi_ds_strcmp (name, "client-hostname")) {
00247             return DHCP_R_UNCHANGED;    /* XXX take change. */
00248         } else if (!omapi_ds_strcmp (name, "host")) {
00249             return DHCP_R_UNCHANGED;    /* XXX take change. */
00250         } else if (!omapi_ds_strcmp (name, "subnet")) {
00251             return DHCP_R_INVALIDARG;
00252         } else if (!omapi_ds_strcmp (name, "pool")) {
00253             return ISC_R_NOPERM;
00254         } else if (!omapi_ds_strcmp (name, "starts")) {
00255             return ISC_R_NOPERM;
00256         } else if (!omapi_ds_strcmp (name, "ends")) {
00257             unsigned long lease_end, old_lease_end;
00258             status = omapi_get_int_value (&lease_end, value);
00259             if (status != ISC_R_SUCCESS)
00260                 return status;
00261             old_lease_end = lease->ends;
00262             lease->ends = lease_end;
00263             if (supersede_lease (lease, 0, 1, 1, 1)) {
00264                 log_info ("lease %s end changed from %lu to %lu",
00265                           piaddr(lease->ip_addr), old_lease_end, lease_end);
00266                 return ISC_R_SUCCESS;
00267             }
00268             log_info ("lease %s end change from %lu to %lu failed",
00269                       piaddr(lease->ip_addr), old_lease_end, lease_end);
00270             return ISC_R_IOERROR;
00271         } else if (!omapi_ds_strcmp(name, "flags")) {
00272             u_int8_t oldflags;
00273 
00274             if (value->type != omapi_datatype_data)
00275                 return DHCP_R_INVALIDARG;
00276 
00277             oldflags = lease->flags;
00278             lease->flags = (value->u.buffer.value[0] & EPHEMERAL_FLAGS) |
00279                            (lease->flags & ~EPHEMERAL_FLAGS);
00280             if(oldflags == lease->flags)
00281                 return ISC_R_SUCCESS;
00282             if (!supersede_lease(lease, NULL, 1, 1, 1)) {
00283                 log_error("Failed to update flags for lease %s.",
00284                           piaddr(lease->ip_addr));
00285                 return ISC_R_IOERROR;
00286             }
00287             return ISC_R_SUCCESS;
00288         } else if (!omapi_ds_strcmp (name, "billing-class")) {
00289             return DHCP_R_UNCHANGED;    /* XXX carefully allow change. */
00290         } else if (!omapi_ds_strcmp (name, "hardware-address")) {
00291             return DHCP_R_UNCHANGED;    /* XXX take change. */
00292         } else if (!omapi_ds_strcmp (name, "hardware-type")) {
00293             return DHCP_R_UNCHANGED;    /* XXX take change. */
00294         } else if (lease -> scope) {
00295             status = binding_scope_set_value (lease -> scope, 0, name, value);
00296             if (status == ISC_R_SUCCESS) {
00297                     if (write_lease (lease) && commit_leases ())
00298                             return ISC_R_SUCCESS;
00299                     return ISC_R_IOERROR;
00300             }
00301         }
00302 
00303         /* Try to find some inner object that can take the value. */
00304         if (h -> inner && h -> inner -> type -> set_value) {
00305                 status = ((*(h -> inner -> type -> set_value))
00306                           (h -> inner, id, name, value));
00307                 if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
00308                         return status;
00309         }
00310 
00311         if (!lease -> scope) {
00312                 if (!binding_scope_allocate (&lease -> scope, MDL))
00313                         return ISC_R_NOMEMORY;
00314         }
00315         status = binding_scope_set_value (lease -> scope, 1, name, value);
00316         if (status != ISC_R_SUCCESS)
00317                 return status;
00318 
00319         if (write_lease (lease) && commit_leases ())
00320                 return ISC_R_SUCCESS;
00321         return ISC_R_IOERROR;
00322 }
00323 
00324 
00325 isc_result_t dhcp_lease_get_value (omapi_object_t *h, omapi_object_t *id,
00326                                    omapi_data_string_t *name,
00327                                    omapi_value_t **value)
00328 {
00329         struct lease *lease;
00330         isc_result_t status;
00331 
00332         if (h -> type != dhcp_type_lease)
00333                 return DHCP_R_INVALIDARG;
00334         lease = (struct lease *)h;
00335 
00336         if (!omapi_ds_strcmp (name, "state"))
00337                 return omapi_make_int_value (value, name,
00338                                              (int)lease -> binding_state, MDL);
00339         else if (!omapi_ds_strcmp (name, "ip-address"))
00340                 return omapi_make_const_value (value, name,
00341                                                lease -> ip_addr.iabuf,
00342                                                lease -> ip_addr.len, MDL);
00343         else if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
00344                 return omapi_make_const_value (value, name,
00345                                                lease -> uid,
00346                                                lease -> uid_len, MDL);
00347         } else if (!omapi_ds_strcmp (name, "client-hostname")) {
00348                 if (lease -> client_hostname)
00349                         return omapi_make_string_value
00350                                 (value, name, lease -> client_hostname, MDL);
00351                 return ISC_R_NOTFOUND;
00352         } else if (!omapi_ds_strcmp (name, "host")) {
00353                 if (lease -> host)
00354                         return omapi_make_handle_value
00355                                 (value, name,
00356                                  ((omapi_object_t *)lease -> host), MDL);
00357         } else if (!omapi_ds_strcmp (name, "subnet"))
00358                 return omapi_make_handle_value (value, name,
00359                                                 ((omapi_object_t *)
00360                                                  lease -> subnet), MDL);
00361         else if (!omapi_ds_strcmp (name, "pool"))
00362                 return omapi_make_handle_value (value, name,
00363                                                 ((omapi_object_t *)
00364                                                  lease -> pool), MDL);
00365         else if (!omapi_ds_strcmp (name, "billing-class")) {
00366                 if (lease -> billing_class)
00367                         return omapi_make_handle_value
00368                                 (value, name,
00369                                  ((omapi_object_t *)lease -> billing_class),
00370                                  MDL);
00371                 return ISC_R_NOTFOUND;
00372         } else if (!omapi_ds_strcmp (name, "hardware-address")) {
00373                 if (lease -> hardware_addr.hlen)
00374                         return omapi_make_const_value
00375                                 (value, name, &lease -> hardware_addr.hbuf [1],
00376                                  (unsigned)(lease -> hardware_addr.hlen - 1),
00377                                  MDL);
00378                 return ISC_R_NOTFOUND;
00379         } else if (!omapi_ds_strcmp (name, "hardware-type")) {
00380                 if (lease -> hardware_addr.hlen)
00381                         return omapi_make_int_value
00382                                 (value, name, lease -> hardware_addr.hbuf [0],
00383                                  MDL);
00384                 return ISC_R_NOTFOUND;
00385         } else if (lease -> scope) {
00386                 status = binding_scope_get_value (value, lease -> scope, name);
00387                 if (status != ISC_R_NOTFOUND)
00388                         return status;
00389         }
00390 
00391         /* Try to find some inner object that can take the value. */
00392         if (h -> inner && h -> inner -> type -> get_value) {
00393                 status = ((*(h -> inner -> type -> get_value))
00394                           (h -> inner, id, name, value));
00395                 if (status == ISC_R_SUCCESS)
00396                         return status;
00397         }
00398         return DHCP_R_UNKNOWNATTRIBUTE;
00399 }
00400 
00401 isc_result_t dhcp_lease_destroy (omapi_object_t *h, const char *file, int line)
00402 {
00403         struct lease *lease;
00404 
00405         if (h->type != dhcp_type_lease)
00406                 return DHCP_R_INVALIDARG;
00407         lease = (struct lease *)h;
00408 
00409         if (lease-> uid)
00410                 uid_hash_delete (lease);
00411         hw_hash_delete (lease);
00412 
00413         if (lease->on_star.on_release)
00414                 executable_statement_dereference (&lease->on_star.on_release,
00415                                                   file, line);
00416         if (lease->on_star.on_expiry)
00417                 executable_statement_dereference (&lease->on_star.on_expiry,
00418                                                   file, line);
00419         if (lease->on_star.on_commit)
00420                 executable_statement_dereference (&lease->on_star.on_commit,
00421                                                   file, line);
00422         if (lease->scope)
00423                 binding_scope_dereference (&lease->scope, file, line);
00424 
00425         if (lease->agent_options)
00426                 option_chain_head_dereference (&lease->agent_options,
00427                                                file, line);
00428         if (lease->uid && lease->uid != lease->uid_buf) {
00429                 dfree (lease->uid, MDL);
00430                 lease->uid = &lease->uid_buf [0];
00431                 lease->uid_len = 0;
00432         }
00433 
00434         if (lease->client_hostname) {
00435                 dfree (lease->client_hostname, MDL);
00436                 lease->client_hostname = (char *)0;
00437         }
00438 
00439         if (lease->host)
00440                 host_dereference (&lease->host, file, line);
00441         if (lease->subnet)
00442                 subnet_dereference (&lease->subnet, file, line);
00443         if (lease->pool)
00444                 pool_dereference (&lease->pool, file, line);
00445 
00446         if (lease->state) {
00447                 free_lease_state (lease->state, file, line);
00448                 lease->state = (struct lease_state *)0;
00449 
00450                 cancel_timeout (lease_ping_timeout, lease);
00451                 --outstanding_pings; /* XXX */
00452         }
00453 
00454         if (lease->billing_class)
00455                 class_dereference
00456                         (&lease->billing_class, file, line);
00457 
00458 #if defined (DEBUG_MEMORY_LEAKAGE) || \
00459                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00460         /* XXX we should never be destroying a lease with a next
00461            XXX pointer except on exit... */
00462         if (lease->next)
00463                 lease_dereference (&lease->next, file, line);
00464         if (lease->n_hw)
00465                 lease_dereference (&lease->n_hw, file, line);
00466         if (lease->n_uid)
00467                 lease_dereference (&lease->n_uid, file, line);
00468         if (lease->next_pending)
00469                 lease_dereference (&lease->next_pending, file, line);
00470 #endif
00471 
00472         return ISC_R_SUCCESS;
00473 }
00474 
00475 isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
00476                                         const char *name, va_list ap)
00477 {
00478         /* h should point to (struct lease *) */
00479         isc_result_t status;
00480 
00481         if (h -> type != dhcp_type_lease)
00482                 return DHCP_R_INVALIDARG;
00483 
00484         if (!strcmp (name, "updated"))
00485                 return ISC_R_SUCCESS;
00486 
00487         /* Try to find some inner object that can take the value. */
00488         if (h -> inner && h -> inner -> type -> signal_handler) {
00489                 status = ((*(h -> inner -> type -> signal_handler))
00490                           (h -> inner, name, ap));
00491                 if (status == ISC_R_SUCCESS)
00492                         return status;
00493         }
00494         return ISC_R_NOTFOUND;
00495 }
00496 
00497 isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
00498                                       omapi_object_t *id,
00499                                       omapi_object_t *h)
00500 {
00501         u_int32_t bouncer;
00502         struct lease *lease;
00503         isc_result_t status;
00504         u_int8_t flagbuf;
00505 
00506         if (h -> type != dhcp_type_lease)
00507                 return DHCP_R_INVALIDARG;
00508         lease = (struct lease *)h;
00509 
00510         /* Write out all the values. */
00511 
00512         status = omapi_connection_put_named_uint32(c, "state",
00513                                                    lease->binding_state);
00514         if (status != ISC_R_SUCCESS)
00515                 return (status);
00516 
00517         status = omapi_connection_put_name (c, "ip-address");
00518         if (status != ISC_R_SUCCESS)
00519                 return status;
00520         status = omapi_connection_put_uint32 (c, lease -> ip_addr.len);
00521         if (status != ISC_R_SUCCESS)
00522                 return status;
00523         status = omapi_connection_copyin (c, lease -> ip_addr.iabuf,
00524                                           lease -> ip_addr.len);
00525         if (status != ISC_R_SUCCESS)
00526                 return status;
00527 
00528         if (lease -> uid_len) {
00529                 status = omapi_connection_put_name (c,
00530                                                     "dhcp-client-identifier");
00531                 if (status != ISC_R_SUCCESS)
00532                         return status;
00533                 status = omapi_connection_put_uint32 (c, lease -> uid_len);
00534                 if (status != ISC_R_SUCCESS)
00535                         return status;
00536                 if (lease -> uid_len) {
00537                         status = omapi_connection_copyin (c, lease -> uid,
00538                                                           lease -> uid_len);
00539                         if (status != ISC_R_SUCCESS)
00540                                 return status;
00541                 }
00542         }
00543 
00544         if (lease -> client_hostname) {
00545                 status = omapi_connection_put_name (c, "client-hostname");
00546                 if (status != ISC_R_SUCCESS)
00547                         return status;
00548                 status =
00549                         omapi_connection_put_string (c,
00550                                                      lease -> client_hostname);
00551                 if (status != ISC_R_SUCCESS)
00552                         return status;
00553         }
00554 
00555         if (lease -> host) {
00556                 status = omapi_connection_put_name (c, "host");
00557                 if (status != ISC_R_SUCCESS)
00558                         return status;
00559                 status = omapi_connection_put_handle (c,
00560                                                       (omapi_object_t *)
00561                                                       lease -> host);
00562                 if (status != ISC_R_SUCCESS)
00563                         return status;
00564         }
00565 
00566         status = omapi_connection_put_name (c, "subnet");
00567         if (status != ISC_R_SUCCESS)
00568                 return status;
00569         status = omapi_connection_put_handle
00570                 (c, (omapi_object_t *)lease -> subnet);
00571         if (status != ISC_R_SUCCESS)
00572                 return status;
00573 
00574         status = omapi_connection_put_name (c, "pool");
00575         if (status != ISC_R_SUCCESS)
00576                 return status;
00577         status = omapi_connection_put_handle (c,
00578                                               (omapi_object_t *)lease -> pool);
00579         if (status != ISC_R_SUCCESS)
00580                 return status;
00581 
00582         if (lease -> billing_class) {
00583                 status = omapi_connection_put_name (c, "billing-class");
00584                 if (status != ISC_R_SUCCESS)
00585                         return status;
00586                 status = omapi_connection_put_handle
00587                         (c, (omapi_object_t *)lease -> billing_class);
00588                 if (status != ISC_R_SUCCESS)
00589                         return status;
00590         }
00591 
00592         if (lease -> hardware_addr.hlen) {
00593                 status = omapi_connection_put_name (c, "hardware-address");
00594                 if (status != ISC_R_SUCCESS)
00595                         return status;
00596                 status = (omapi_connection_put_uint32
00597                           (c,
00598                            (unsigned long)(lease -> hardware_addr.hlen - 1)));
00599                 if (status != ISC_R_SUCCESS)
00600                         return status;
00601                 status = (omapi_connection_copyin
00602                           (c, &lease -> hardware_addr.hbuf [1],
00603                            (unsigned long)(lease -> hardware_addr.hlen - 1)));
00604 
00605                 if (status != ISC_R_SUCCESS)
00606                         return status;
00607 
00608                 status = omapi_connection_put_named_uint32(c, "hardware-type",
00609                                                 lease->hardware_addr.hbuf[0]);
00610                 if (status != ISC_R_SUCCESS)
00611                         return (status);
00612         }
00613 
00614         /* TIME values may be 64-bit, depending on system architecture.
00615          * OMAPI must be system independent, both in terms of transmitting
00616          * bytes on the wire in network byte order, and in terms of being
00617          * readable and usable by both systems.
00618          *
00619          * XXX: In a future feature release, a put_int64() should be made
00620          * to exist, and perhaps a put_time() wrapper that selects which
00621          * to use based upon sizeof(TIME).  In the meantime, use existing,
00622          * 32-bit, code.
00623          */
00624         bouncer = (u_int32_t)lease->ends;
00625         status = omapi_connection_put_named_uint32(c, "ends", bouncer);
00626         if (status != ISC_R_SUCCESS)
00627                 return (status);
00628 
00629         bouncer = (u_int32_t)lease->starts;
00630         status = omapi_connection_put_named_uint32(c, "starts", bouncer);
00631         if (status != ISC_R_SUCCESS)
00632                 return (status);
00633 
00634         bouncer = (u_int32_t)lease->tstp;
00635         status = omapi_connection_put_named_uint32(c, "tstp", bouncer);
00636         if (status != ISC_R_SUCCESS)
00637                 return (status);
00638 
00639         bouncer = (u_int32_t)lease->tsfp;
00640         status = omapi_connection_put_named_uint32(c, "tsfp", bouncer);
00641         if (status != ISC_R_SUCCESS)
00642                 return status;
00643 
00644         bouncer = (u_int32_t)lease->atsfp;
00645         status = omapi_connection_put_named_uint32(c, "atsfp", bouncer);
00646         if (status != ISC_R_SUCCESS)
00647                 return status;
00648 
00649         bouncer = (u_int32_t)lease->cltt;
00650         status = omapi_connection_put_named_uint32(c, "cltt", bouncer);
00651         if (status != ISC_R_SUCCESS)
00652                 return status;
00653 
00654         status = omapi_connection_put_name (c, "flags");
00655         if (status != ISC_R_SUCCESS)
00656                 return status;
00657         status = omapi_connection_put_uint32(c, sizeof(flagbuf));
00658         if (status != ISC_R_SUCCESS)
00659                 return status;
00660         flagbuf = lease->flags & EPHEMERAL_FLAGS;
00661         status = omapi_connection_copyin(c, &flagbuf, sizeof(flagbuf));
00662         if (status != ISC_R_SUCCESS)
00663                 return status;
00664 
00665         if (lease -> scope) {
00666                 status = binding_scope_stuff_values (c, lease -> scope);
00667                 if (status != ISC_R_SUCCESS)
00668                         return status;
00669         }
00670 
00671         /* Write out the inner object, if any. */
00672         if (h -> inner && h -> inner -> type -> stuff_values) {
00673                 status = ((*(h -> inner -> type -> stuff_values))
00674                           (c, id, h -> inner));
00675                 if (status == ISC_R_SUCCESS)
00676                         return status;
00677         }
00678 
00679         return ISC_R_SUCCESS;
00680 }
00681 
00682 isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
00683                                 omapi_object_t *id, omapi_object_t *ref)
00684 {
00685         omapi_value_t *tv = (omapi_value_t *)0;
00686         isc_result_t status;
00687         struct lease *lease;
00688 
00689         if (!ref)
00690                 return DHCP_R_NOKEYS;
00691 
00692         /* First see if we were sent a handle. */
00693         status = omapi_get_value_str (ref, id, "handle", &tv);
00694         if (status == ISC_R_SUCCESS) {
00695                 status = omapi_handle_td_lookup (lp, tv -> value);
00696 
00697                 omapi_value_dereference (&tv, MDL);
00698                 if (status != ISC_R_SUCCESS)
00699                         return status;
00700 
00701                 /* Don't return the object if the type is wrong. */
00702                 if ((*lp) -> type != dhcp_type_lease) {
00703                         omapi_object_dereference (lp, MDL);
00704                         return DHCP_R_INVALIDARG;
00705                 }
00706         }
00707 
00708         /* Now look for an IP address. */
00709         status = omapi_get_value_str (ref, id, "ip-address", &tv);
00710         if (status == ISC_R_SUCCESS) {
00711                 lease = (struct lease *)0;
00712                 lease_ip_hash_lookup(&lease, lease_ip_addr_hash,
00713                                      tv->value->u.buffer.value,
00714                                      tv->value->u.buffer.len, MDL);
00715 
00716                 omapi_value_dereference (&tv, MDL);
00717 
00718                 /* If we already have a lease, and it's not the same one,
00719                    then the query was invalid. */
00720                 if (*lp && *lp != (omapi_object_t *)lease) {
00721                         omapi_object_dereference (lp, MDL);
00722                         lease_dereference (&lease, MDL);
00723                         return DHCP_R_KEYCONFLICT;
00724                 } else if (!lease) {
00725                         if (*lp)
00726                                 omapi_object_dereference (lp, MDL);
00727                         return ISC_R_NOTFOUND;
00728                 } else if (!*lp) {
00729                         /* XXX fix so that hash lookup itself creates
00730                            XXX the reference. */
00731                         omapi_object_reference (lp,
00732                                                 (omapi_object_t *)lease, MDL);
00733                         lease_dereference (&lease, MDL);
00734                 }
00735         }
00736 
00737         /* Now look for a client identifier. */
00738         status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
00739         if (status == ISC_R_SUCCESS) {
00740                 lease = (struct lease *)0;
00741                 lease_id_hash_lookup(&lease, lease_uid_hash,
00742                                      tv->value->u.buffer.value,
00743                                      tv->value->u.buffer.len, MDL);
00744                 omapi_value_dereference (&tv, MDL);
00745 
00746                 if (*lp && *lp != (omapi_object_t *)lease) {
00747                         omapi_object_dereference (lp, MDL);
00748                         lease_dereference (&lease, MDL);
00749                         return DHCP_R_KEYCONFLICT;
00750                 } else if (!lease) {
00751                         if (*lp)
00752                             omapi_object_dereference (lp, MDL);
00753                         return ISC_R_NOTFOUND;
00754                 } else if (lease -> n_uid) {
00755                         if (*lp)
00756                             omapi_object_dereference (lp, MDL);
00757                         return DHCP_R_MULTIPLE;
00758                 } else if (!*lp) {
00759                         /* XXX fix so that hash lookup itself creates
00760                            XXX the reference. */
00761                         omapi_object_reference (lp,
00762                                                 (omapi_object_t *)lease, MDL);
00763                         lease_dereference (&lease, MDL);
00764                 }
00765         }
00766 
00767         /* Now look for a hardware address. */
00768         status = omapi_get_value_str (ref, id, "hardware-address", &tv);
00769         if (status == ISC_R_SUCCESS) {
00770                 unsigned char *haddr;
00771                 unsigned int len;
00772 
00773                 len = tv -> value -> u.buffer.len + 1;
00774                 haddr = dmalloc (len, MDL);
00775                 if (!haddr) {
00776                         omapi_value_dereference (&tv, MDL);
00777                         return ISC_R_NOMEMORY;
00778                 }
00779 
00780                 memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
00781                 omapi_value_dereference (&tv, MDL);
00782 
00783                 status = omapi_get_value_str (ref, id, "hardware-type", &tv);
00784                 if (status == ISC_R_SUCCESS) {
00785                         if (tv -> value -> type == omapi_datatype_data) {
00786                                 if ((tv -> value -> u.buffer.len != 4) ||
00787                                     (tv -> value -> u.buffer.value[0] != 0) ||
00788                                     (tv -> value -> u.buffer.value[1] != 0) ||
00789                                     (tv -> value -> u.buffer.value[2] != 0)) {
00790                                         omapi_value_dereference (&tv, MDL);
00791                                         dfree (haddr, MDL);
00792                                         return DHCP_R_INVALIDARG;
00793                                 }
00794 
00795                                 haddr[0] = tv -> value -> u.buffer.value[3];
00796                         } else if (tv -> value -> type == omapi_datatype_int) {
00797                                 haddr[0] = (unsigned char)
00798                                         tv -> value -> u.integer;
00799                         } else {
00800                                 omapi_value_dereference (&tv, MDL);
00801                                 dfree (haddr, MDL);
00802                                 return DHCP_R_INVALIDARG;
00803                         }
00804 
00805                         omapi_value_dereference (&tv, MDL);
00806                 } else {
00807                         /* If no hardware-type is specified, default to
00808                            ethernet.  This may or may not be a good idea,
00809                            but Telus is currently relying on this behavior.
00810                            - DPN */
00811                         haddr[0] = HTYPE_ETHER;
00812                 }
00813 
00814                 lease = (struct lease *)0;
00815                 lease_id_hash_lookup(&lease, lease_hw_addr_hash, haddr, len,
00816                                      MDL);
00817                 dfree (haddr, MDL);
00818 
00819                 if (*lp && *lp != (omapi_object_t *)lease) {
00820                         omapi_object_dereference (lp, MDL);
00821                         lease_dereference (&lease, MDL);
00822                         return DHCP_R_KEYCONFLICT;
00823                 } else if (!lease) {
00824                         if (*lp)
00825                             omapi_object_dereference (lp, MDL);
00826                         return ISC_R_NOTFOUND;
00827                 } else if (lease -> n_hw) {
00828                         if (*lp)
00829                             omapi_object_dereference (lp, MDL);
00830                         lease_dereference (&lease, MDL);
00831                         return DHCP_R_MULTIPLE;
00832                 } else if (!*lp) {
00833                         /* XXX fix so that hash lookup itself creates
00834                            XXX the reference. */
00835                         omapi_object_reference (lp,
00836                                                 (omapi_object_t *)lease, MDL);
00837                         lease_dereference (&lease, MDL);
00838                 }
00839         }
00840 
00841         /* If we get to here without finding a lease, no valid key was
00842            specified. */
00843         if (!*lp)
00844                 return DHCP_R_NOKEYS;
00845         return ISC_R_SUCCESS;
00846 }
00847 
00848 isc_result_t dhcp_lease_create (omapi_object_t **lp,
00849                                 omapi_object_t *id)
00850 {
00851         return ISC_R_NOTIMPLEMENTED;
00852 }
00853 
00854 isc_result_t dhcp_lease_remove (omapi_object_t *lp,
00855                                 omapi_object_t *id)
00856 {
00857         return ISC_R_NOTIMPLEMENTED;
00858 }
00859 
00860 isc_result_t dhcp_host_set_value  (omapi_object_t *h,
00861                                    omapi_object_t *id,
00862                                    omapi_data_string_t *name,
00863                                    omapi_typed_data_t *value)
00864 {
00865         struct host_decl *host;
00866         isc_result_t status;
00867 
00868         if (h -> type != dhcp_type_host)
00869                 return DHCP_R_INVALIDARG;
00870         host = (struct host_decl *)h;
00871 
00872         /* XXX For now, we can only set these values on new host objects.
00873            XXX Soon, we need to be able to update host objects. */
00874         if (!omapi_ds_strcmp (name, "name")) {
00875                 if (host -> name)
00876                         return ISC_R_EXISTS;
00877                 if (value && (value -> type == omapi_datatype_data ||
00878                               value -> type == omapi_datatype_string)) {
00879                         host -> name = dmalloc (value -> u.buffer.len + 1,
00880                                                 MDL);
00881                         if (!host -> name)
00882                                 return ISC_R_NOMEMORY;
00883                         memcpy (host -> name,
00884                                 value -> u.buffer.value,
00885                                 value -> u.buffer.len);
00886                         host -> name [value -> u.buffer.len] = 0;
00887                 } else
00888                         return DHCP_R_INVALIDARG;
00889                 return ISC_R_SUCCESS;
00890         }
00891 
00892         if (!omapi_ds_strcmp (name, "group")) {
00893                 if (value && (value -> type == omapi_datatype_data ||
00894                               value -> type == omapi_datatype_string)) {
00895                         struct group_object *group;
00896                         group = (struct group_object *)0;
00897                         group_hash_lookup (&group, group_name_hash,
00898                                            (char *)value -> u.buffer.value,
00899                                            value -> u.buffer.len, MDL);
00900                         if (!group || (group -> flags & GROUP_OBJECT_DELETED))
00901                                 return ISC_R_NOTFOUND;
00902                         if (host -> group)
00903                                 group_dereference (&host -> group, MDL);
00904                         group_reference (&host -> group, group -> group, MDL);
00905                         if (host -> named_group)
00906                                 group_object_dereference (&host -> named_group,
00907                                                           MDL);
00908                         group_object_reference (&host -> named_group,
00909                                                 group, MDL);
00910                         group_object_dereference (&group, MDL);
00911                 } else
00912                         return DHCP_R_INVALIDARG;
00913                 return ISC_R_SUCCESS;
00914         }
00915 
00916         if (!omapi_ds_strcmp (name, "hardware-address")) {
00917                 if (host -> interface.hlen)
00918                         return ISC_R_EXISTS;
00919                 if (value && (value -> type == omapi_datatype_data ||
00920                               value -> type == omapi_datatype_string)) {
00921                         if (value -> u.buffer.len >
00922                             (sizeof host -> interface.hbuf) - 1)
00923                                 return DHCP_R_INVALIDARG;
00924                         memcpy (&host -> interface.hbuf [1],
00925                                 value -> u.buffer.value,
00926                                 value -> u.buffer.len);
00927                         host -> interface.hlen = value -> u.buffer.len + 1;
00928                 } else
00929                         return DHCP_R_INVALIDARG;
00930                 return ISC_R_SUCCESS;
00931         }
00932 
00933         if (!omapi_ds_strcmp (name, "hardware-type")) {
00934                 int type;
00935                 if ((value != NULL) &&
00936                     ((value->type == omapi_datatype_data) &&
00937                      (value->u.buffer.len == sizeof(type)))) {
00938                         if (value->u.buffer.len > sizeof(type))
00939                                 return (DHCP_R_INVALIDARG);
00940                         memcpy(&type, value->u.buffer.value,
00941                                value->u.buffer.len);
00942                         type = ntohl(type);
00943                 } else if ((value != NULL) &&
00944                            (value->type == omapi_datatype_int))
00945                         type = value->u.integer;
00946                 else
00947                         return (DHCP_R_INVALIDARG);
00948                 host->interface.hbuf[0] = type;
00949                 return (ISC_R_SUCCESS);
00950         }
00951 
00952         if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
00953                 if (host -> client_identifier.data)
00954                         return ISC_R_EXISTS;
00955                 if (value && (value -> type == omapi_datatype_data ||
00956                               value -> type == omapi_datatype_string)) {
00957                     if (!buffer_allocate (&host -> client_identifier.buffer,
00958                                           value -> u.buffer.len, MDL))
00959                             return ISC_R_NOMEMORY;
00960                     host -> client_identifier.data =
00961                             &host -> client_identifier.buffer -> data [0];
00962                     memcpy (host -> client_identifier.buffer -> data,
00963                             value -> u.buffer.value,
00964                             value -> u.buffer.len);
00965                     host -> client_identifier.len = value -> u.buffer.len;
00966                 } else
00967                     return DHCP_R_INVALIDARG;
00968                 return ISC_R_SUCCESS;
00969         }
00970 
00971         if (!omapi_ds_strcmp (name, "ip-address")) {
00972                 if (host -> fixed_addr)
00973                         option_cache_dereference (&host -> fixed_addr, MDL);
00974                 if (!value)
00975                         return ISC_R_SUCCESS;
00976                 if (value && (value -> type == omapi_datatype_data ||
00977                               value -> type == omapi_datatype_string)) {
00978                         struct data_string ds;
00979                         memset (&ds, 0, sizeof ds);
00980                         ds.len = value -> u.buffer.len;
00981                         if (!buffer_allocate (&ds.buffer, ds.len, MDL))
00982                                 return ISC_R_NOMEMORY;
00983                         ds.data = (&ds.buffer -> data [0]);
00984                         memcpy (ds.buffer -> data,
00985                                 value -> u.buffer.value, ds.len);
00986                         if (!option_cache (&host -> fixed_addr,
00987                                            &ds, (struct expression *)0,
00988                                            (struct option *)0, MDL)) {
00989                                 data_string_forget (&ds, MDL);
00990                                 return ISC_R_NOMEMORY;
00991                         }
00992                         data_string_forget (&ds, MDL);
00993                 } else
00994                         return DHCP_R_INVALIDARG;
00995                 return ISC_R_SUCCESS;
00996         }
00997 
00998         if (!omapi_ds_strcmp (name, "statements")) {
00999                 if (!host -> group) {
01000                         if (!clone_group (&host -> group, root_group, MDL))
01001                                 return ISC_R_NOMEMORY;
01002                 } else {
01003                         if (host -> group -> statements &&
01004                             (!host -> named_group ||
01005                              host -> group != host -> named_group -> group) &&
01006                             host -> group != root_group)
01007                                 return ISC_R_EXISTS;
01008                         if (!clone_group (&host -> group, host -> group, MDL))
01009                                 return ISC_R_NOMEMORY;
01010                 }
01011                 if (!host -> group)
01012                         return ISC_R_NOMEMORY;
01013                 if (value && (value -> type == omapi_datatype_data ||
01014                               value -> type == omapi_datatype_string)) {
01015                         struct parse *parse;
01016                         int lose = 0;
01017                         parse = (struct parse *)0;
01018                         status = new_parse(&parse, -1,
01019                                             (char *) value->u.buffer.value,
01020                                             value->u.buffer.len,
01021                                             "network client", 0);
01022                         if (status != ISC_R_SUCCESS || parse == NULL)
01023                                 return status;
01024 
01025                         if (!(parse_executable_statements
01026                               (&host -> group -> statements, parse, &lose,
01027                                context_any))) {
01028                                 end_parse (&parse);
01029                                 return DHCP_R_BADPARSE;
01030                         }
01031                         end_parse (&parse);
01032                 } else
01033                         return DHCP_R_INVALIDARG;
01034                 return ISC_R_SUCCESS;
01035         }
01036 
01037         /* The "known" flag isn't supported in the database yet, but it's
01038            legitimate. */
01039         if (!omapi_ds_strcmp (name, "known")) {
01040                 return ISC_R_SUCCESS;
01041         }
01042 
01043         /* Try to find some inner object that can take the value. */
01044         if (h -> inner && h -> inner -> type -> set_value) {
01045                 status = ((*(h -> inner -> type -> set_value))
01046                           (h -> inner, id, name, value));
01047                 if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
01048                         return status;
01049         }
01050 
01051         return DHCP_R_UNKNOWNATTRIBUTE;
01052 }
01053 
01054 
01055 isc_result_t dhcp_host_get_value (omapi_object_t *h, omapi_object_t *id,
01056                                    omapi_data_string_t *name,
01057                                    omapi_value_t **value)
01058 {
01059         struct host_decl *host;
01060         isc_result_t status;
01061         struct data_string ip_addrs;
01062 
01063         if (h -> type != dhcp_type_host)
01064                 return DHCP_R_INVALIDARG;
01065         host = (struct host_decl *)h;
01066 
01067         if (!omapi_ds_strcmp (name, "ip-addresses")) {
01068             memset (&ip_addrs, 0, sizeof ip_addrs);
01069             if (host -> fixed_addr &&
01070                 evaluate_option_cache (&ip_addrs, (struct packet *)0,
01071                                        (struct lease *)0,
01072                                        (struct client_state *)0,
01073                                        (struct option_state *)0,
01074                                        (struct option_state *)0,
01075                                        &global_scope,
01076                                        host -> fixed_addr, MDL)) {
01077                     status = omapi_make_const_value (value, name,
01078                                                      ip_addrs.data,
01079                                                      ip_addrs.len, MDL);
01080                     data_string_forget (&ip_addrs, MDL);
01081                     return status;
01082             }
01083             return ISC_R_NOTFOUND;
01084         }
01085 
01086         if (!omapi_ds_strcmp (name, "dhcp-client-identifier")) {
01087                 if (!host -> client_identifier.len)
01088                         return ISC_R_NOTFOUND;
01089                 return omapi_make_const_value (value, name,
01090                                                host -> client_identifier.data,
01091                                                host -> client_identifier.len,
01092                                                MDL);
01093         }
01094 
01095         if (!omapi_ds_strcmp (name, "name"))
01096                 return omapi_make_string_value (value, name, host -> name,
01097                                                 MDL);
01098 
01099         if (!omapi_ds_strcmp (name, "hardware-address")) {
01100                 if (!host -> interface.hlen)
01101                         return ISC_R_NOTFOUND;
01102                 return (omapi_make_const_value
01103                         (value, name, &host -> interface.hbuf [1],
01104                          (unsigned long)(host -> interface.hlen - 1), MDL));
01105         }
01106 
01107         if (!omapi_ds_strcmp (name, "hardware-type")) {
01108                 if (!host -> interface.hlen)
01109                         return ISC_R_NOTFOUND;
01110                 return omapi_make_int_value (value, name,
01111                                              host -> interface.hbuf [0], MDL);
01112         }
01113 
01114         /* Try to find some inner object that can take the value. */
01115         if (h -> inner && h -> inner -> type -> get_value) {
01116                 status = ((*(h -> inner -> type -> get_value))
01117                           (h -> inner, id, name, value));
01118                 if (status == ISC_R_SUCCESS)
01119                         return status;
01120         }
01121         return DHCP_R_UNKNOWNATTRIBUTE;
01122 }
01123 
01124 isc_result_t dhcp_host_destroy (omapi_object_t *h, const char *file, int line)
01125 {
01126 
01127         if (h -> type != dhcp_type_host)
01128                 return DHCP_R_INVALIDARG;
01129 
01130         struct host_decl *host = (struct host_decl *)h;
01131         if (host -> n_ipaddr)
01132                 host_dereference (&host -> n_ipaddr, file, line);
01133         if (host -> n_dynamic)
01134                 host_dereference (&host -> n_dynamic, file, line);
01135         if (host -> name) {
01136                 dfree (host -> name, file, line);
01137                 host -> name = (char *)0;
01138         }
01139         data_string_forget (&host -> client_identifier, file, line);
01140         if (host -> fixed_addr)
01141                 option_cache_dereference (&host -> fixed_addr, file, line);
01142         if (host -> group)
01143                 group_dereference (&host -> group, file, line);
01144         if (host -> named_group)
01145                 omapi_object_dereference ((omapi_object_t **)
01146                                           &host -> named_group, file, line);
01147         data_string_forget (&host -> auth_key_id, file, line);
01148 
01149         return ISC_R_SUCCESS;
01150 }
01151 
01152 isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
01153                                        const char *name, va_list ap)
01154 {
01155         struct host_decl *host;
01156         isc_result_t status;
01157         int updatep = 0;
01158 
01159         if (h -> type != dhcp_type_host)
01160                 return DHCP_R_INVALIDARG;
01161         host = (struct host_decl *)h;
01162 
01163         if (!strcmp (name, "updated")) {
01164                 /* There must be a client identifier of some sort. */
01165                 if (host -> interface.hlen == 0 &&
01166                     !host -> client_identifier.len)
01167                         return DHCP_R_INVALIDARG;
01168 
01169                 if (!host -> name) {
01170                         char hnbuf [64];
01171                         sprintf (hnbuf, "nh%08lx%08lx",
01172                                  (unsigned long)cur_time, (unsigned long)host);
01173                         host -> name = dmalloc (strlen (hnbuf) + 1, MDL);
01174                         if (!host -> name)
01175                                 return ISC_R_NOMEMORY;
01176                         strcpy (host -> name, hnbuf);
01177                 }
01178 
01179 #ifdef DEBUG_OMAPI
01180                 log_debug ("OMAPI added host %s", host -> name);
01181 #endif
01182                 status = enter_host (host, 1, 1);
01183                 if (status != ISC_R_SUCCESS)
01184                         return status;
01185                 updatep = 1;
01186         }
01187 
01188         /* Try to find some inner object that can take the value. */
01189         if (h -> inner && h -> inner -> type -> signal_handler) {
01190                 status = ((*(h -> inner -> type -> signal_handler))
01191                           (h -> inner, name, ap));
01192                 if (status == ISC_R_SUCCESS)
01193                         return status;
01194         }
01195         if (updatep)
01196                 return ISC_R_SUCCESS;
01197         return ISC_R_NOTFOUND;
01198 }
01199 
01200 isc_result_t dhcp_host_stuff_values (omapi_object_t *c,
01201                                       omapi_object_t *id,
01202                                       omapi_object_t *h)
01203 {
01204         struct host_decl *host;
01205         isc_result_t status;
01206         struct data_string ip_addrs;
01207 
01208         if (h -> type != dhcp_type_host)
01209                 return DHCP_R_INVALIDARG;
01210         host = (struct host_decl *)h;
01211 
01212         /* Write out all the values. */
01213 
01214         memset (&ip_addrs, 0, sizeof ip_addrs);
01215         if (host -> fixed_addr &&
01216             evaluate_option_cache (&ip_addrs, (struct packet *)0,
01217                                    (struct lease *)0,
01218                                    (struct client_state *)0,
01219                                    (struct option_state *)0,
01220                                    (struct option_state *)0,
01221                                    &global_scope,
01222                                    host -> fixed_addr, MDL)) {
01223                 status = omapi_connection_put_name (c, "ip-address");
01224                 if (status != ISC_R_SUCCESS)
01225                         return status;
01226                 status = omapi_connection_put_uint32 (c, ip_addrs.len);
01227                 if (status != ISC_R_SUCCESS)
01228                         return status;
01229                 status = omapi_connection_copyin (c,
01230                                                   ip_addrs.data, ip_addrs.len);
01231                 if (status != ISC_R_SUCCESS)
01232                         return status;
01233                 data_string_forget (&ip_addrs, MDL);
01234         }
01235 
01236         if (host -> client_identifier.len) {
01237                 status = omapi_connection_put_name (c,
01238                                                     "dhcp-client-identifier");
01239                 if (status != ISC_R_SUCCESS)
01240                         return status;
01241                 status = (omapi_connection_put_uint32
01242                           (c, host -> client_identifier.len));
01243                 if (status != ISC_R_SUCCESS)
01244                         return status;
01245                 status = (omapi_connection_copyin
01246                           (c,
01247                            host -> client_identifier.data,
01248                            host -> client_identifier.len));
01249                 if (status != ISC_R_SUCCESS)
01250                         return status;
01251         }
01252 
01253         if (host -> name) {
01254                 status = omapi_connection_put_name (c, "name");
01255                 if (status != ISC_R_SUCCESS)
01256                         return status;
01257                 status = omapi_connection_put_string (c, host -> name);
01258                 if (status != ISC_R_SUCCESS)
01259                         return status;
01260         }
01261 
01262         if (host -> interface.hlen) {
01263                 status = omapi_connection_put_name (c, "hardware-address");
01264                 if (status != ISC_R_SUCCESS)
01265                         return status;
01266                 status = (omapi_connection_put_uint32
01267                           (c, (unsigned long)(host -> interface.hlen - 1)));
01268                 if (status != ISC_R_SUCCESS)
01269                         return status;
01270                 status = (omapi_connection_copyin
01271                           (c, &host -> interface.hbuf [1],
01272                            (unsigned long)(host -> interface.hlen - 1)));
01273                 if (status != ISC_R_SUCCESS)
01274                         return status;
01275 
01276                 status = omapi_connection_put_named_uint32(c, "hardware-type",
01277                                                            host->interface.hbuf[0]);
01278                 if (status != ISC_R_SUCCESS)
01279                         return status;
01280         }
01281 
01282         /* Write out the inner object, if any. */
01283         if (h -> inner && h -> inner -> type -> stuff_values) {
01284                 status = ((*(h -> inner -> type -> stuff_values))
01285                           (c, id, h -> inner));
01286                 if (status == ISC_R_SUCCESS)
01287                         return status;
01288         }
01289 
01290         return ISC_R_SUCCESS;
01291 }
01292 
01293 isc_result_t dhcp_host_lookup (omapi_object_t **lp,
01294                                omapi_object_t *id, omapi_object_t *ref)
01295 {
01296         omapi_value_t *tv = (omapi_value_t *)0;
01297         isc_result_t status;
01298         struct host_decl *host;
01299 
01300         if (!ref)
01301                 return DHCP_R_NOKEYS;
01302 
01303         /* First see if we were sent a handle. */
01304         status = omapi_get_value_str (ref, id, "handle", &tv);
01305         if (status == ISC_R_SUCCESS) {
01306                 status = omapi_handle_td_lookup (lp, tv -> value);
01307 
01308                 omapi_value_dereference (&tv, MDL);
01309                 if (status != ISC_R_SUCCESS)
01310                         return status;
01311 
01312                 /* Don't return the object if the type is wrong. */
01313                 if ((*lp) -> type != dhcp_type_host) {
01314                         omapi_object_dereference (lp, MDL);
01315                         return DHCP_R_INVALIDARG;
01316                 }
01317                 if (((struct host_decl *)(*lp)) -> flags & HOST_DECL_DELETED) {
01318                         omapi_object_dereference (lp, MDL);
01319                 }
01320         }
01321 
01322         /* Now look for a client identifier. */
01323         status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
01324         if (status == ISC_R_SUCCESS) {
01325                 host = (struct host_decl *)0;
01326                 host_hash_lookup (&host, host_uid_hash,
01327                                   tv -> value -> u.buffer.value,
01328                                   tv -> value -> u.buffer.len, MDL);
01329                 omapi_value_dereference (&tv, MDL);
01330 
01331                 if (*lp && *lp != (omapi_object_t *)host) {
01332                         omapi_object_dereference (lp, MDL);
01333                         if (host)
01334                                 host_dereference (&host, MDL);
01335                         return DHCP_R_KEYCONFLICT;
01336                 } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
01337                         if (*lp)
01338                             omapi_object_dereference (lp, MDL);
01339                         if (host)
01340                                 host_dereference (&host, MDL);
01341                         return ISC_R_NOTFOUND;
01342                 } else if (!*lp) {
01343                         /* XXX fix so that hash lookup itself creates
01344                            XXX the reference. */
01345                         omapi_object_reference (lp,
01346                                                 (omapi_object_t *)host, MDL);
01347                         host_dereference (&host, MDL);
01348                 }
01349         }
01350 
01351         /* Now look for a hardware address. */
01352         status = omapi_get_value_str (ref, id, "hardware-address", &tv);
01353         if (status == ISC_R_SUCCESS) {
01354                 unsigned char *haddr;
01355                 unsigned int len;
01356 
01357                 len = tv -> value -> u.buffer.len + 1;
01358                 haddr = dmalloc (len, MDL);
01359                 if (!haddr) {
01360                         omapi_value_dereference (&tv, MDL);
01361                         return ISC_R_NOMEMORY;
01362                 }
01363 
01364                 memcpy (haddr + 1, tv -> value -> u.buffer.value, len - 1);
01365                 omapi_value_dereference (&tv, MDL);
01366 
01367                 status = omapi_get_value_str (ref, id, "hardware-type", &tv);
01368                 if (status == ISC_R_SUCCESS) {
01369                         if (tv -> value -> type == omapi_datatype_data) {
01370                                 if ((tv -> value -> u.buffer.len != 4) ||
01371                                     (tv -> value -> u.buffer.value[0] != 0) ||
01372                                     (tv -> value -> u.buffer.value[1] != 0) ||
01373                                     (tv -> value -> u.buffer.value[2] != 0)) {
01374                                         omapi_value_dereference (&tv, MDL);
01375                                         dfree (haddr, MDL);
01376                                         return DHCP_R_INVALIDARG;
01377                                 }
01378 
01379                                 haddr[0] = tv -> value -> u.buffer.value[3];
01380                         } else if (tv -> value -> type == omapi_datatype_int) {
01381                                 haddr[0] = (unsigned char)
01382                                         tv -> value -> u.integer;
01383                         } else {
01384                                 omapi_value_dereference (&tv, MDL);
01385                                 dfree (haddr, MDL);
01386                                 return DHCP_R_INVALIDARG;
01387                         }
01388 
01389                         omapi_value_dereference (&tv, MDL);
01390                 } else {
01391                         /* If no hardware-type is specified, default to
01392                            ethernet.  This may or may not be a good idea,
01393                            but Telus is currently relying on this behavior.
01394                            - DPN */
01395                         haddr[0] = HTYPE_ETHER;
01396                 }
01397 
01398                 host = (struct host_decl *)0;
01399                 host_hash_lookup (&host, host_hw_addr_hash, haddr, len, MDL);
01400                 dfree (haddr, MDL);
01401 
01402                 if (*lp && *lp != (omapi_object_t *)host) {
01403                         omapi_object_dereference (lp, MDL);
01404                         if (host)
01405                                 host_dereference (&host, MDL);
01406                         return DHCP_R_KEYCONFLICT;
01407                 } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
01408                         if (*lp)
01409                             omapi_object_dereference (lp, MDL);
01410                         if (host)
01411                                 host_dereference (&host, MDL);
01412                         return ISC_R_NOTFOUND;
01413                 } else if (!*lp) {
01414                         /* XXX fix so that hash lookup itself creates
01415                            XXX the reference. */
01416                         omapi_object_reference (lp,
01417                                                 (omapi_object_t *)host, MDL);
01418                         host_dereference (&host, MDL);
01419                 }
01420         }
01421 
01422         /* Now look for an ip address. */
01423         status = omapi_get_value_str (ref, id, "ip-address", &tv);
01424         if (status == ISC_R_SUCCESS) {
01425                 struct lease *l;
01426 
01427                 /* first find the lease for this ip address */
01428                 l = (struct lease *)0;
01429                 lease_ip_hash_lookup(&l, lease_ip_addr_hash,
01430                                      tv->value->u.buffer.value,
01431                                      tv->value->u.buffer.len, MDL);
01432                 omapi_value_dereference (&tv, MDL);
01433 
01434                 if (!l && !*lp)
01435                         return ISC_R_NOTFOUND;
01436 
01437                 if (l) {
01438                         /* now use that to get a host */
01439                         host = (struct host_decl *)0;
01440                         host_hash_lookup (&host, host_hw_addr_hash,
01441                                           l -> hardware_addr.hbuf,
01442                                           l -> hardware_addr.hlen, MDL);
01443 
01444                         if (host && *lp && *lp != (omapi_object_t *)host) {
01445                             omapi_object_dereference (lp, MDL);
01446                             if (host)
01447                                 host_dereference (&host, MDL);
01448                             return DHCP_R_KEYCONFLICT;
01449                         } else if (!host || (host -> flags &
01450                                              HOST_DECL_DELETED)) {
01451                             if (host)
01452                                 host_dereference (&host, MDL);
01453                             if (!*lp)
01454                                     return ISC_R_NOTFOUND;
01455                         } else if (!*lp) {
01456                                 /* XXX fix so that hash lookup itself creates
01457                                    XXX the reference. */
01458                             omapi_object_reference (lp, (omapi_object_t *)host,
01459                                                     MDL);
01460                             host_dereference (&host, MDL);
01461                         }
01462                         lease_dereference (&l, MDL);
01463                 }
01464         }
01465 
01466         /* Now look for a name. */
01467         status = omapi_get_value_str (ref, id, "name", &tv);
01468         if (status == ISC_R_SUCCESS) {
01469                 host = (struct host_decl *)0;
01470                 host_hash_lookup (&host, host_name_hash,
01471                                   tv -> value -> u.buffer.value,
01472                                   tv -> value -> u.buffer.len, MDL);
01473                 omapi_value_dereference (&tv, MDL);
01474 
01475                 if (*lp && *lp != (omapi_object_t *)host) {
01476                         omapi_object_dereference (lp, MDL);
01477                         if (host)
01478                             host_dereference (&host, MDL);
01479                         return DHCP_R_KEYCONFLICT;
01480                 } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
01481                         if (host)
01482                             host_dereference (&host, MDL);
01483                         return ISC_R_NOTFOUND;
01484                 } else if (!*lp) {
01485                         /* XXX fix so that hash lookup itself creates
01486                            XXX the reference. */
01487                         omapi_object_reference (lp,
01488                                                 (omapi_object_t *)host, MDL);
01489                         host_dereference (&host, MDL);
01490                 }
01491         }
01492 
01493         /* If we get to here without finding a host, no valid key was
01494            specified. */
01495         if (!*lp)
01496                 return DHCP_R_NOKEYS;
01497         return ISC_R_SUCCESS;
01498 }
01499 
01500 isc_result_t dhcp_host_create (omapi_object_t **lp,
01501                                omapi_object_t *id)
01502 {
01503         struct host_decl *hp;
01504         isc_result_t status;
01505         hp = (struct host_decl *)0;
01506         status = host_allocate (&hp, MDL);
01507         if (status != ISC_R_SUCCESS)
01508                 return status;
01509         group_reference (&hp -> group, root_group, MDL);
01510         hp -> flags = HOST_DECL_DYNAMIC;
01511         status = omapi_object_reference (lp, (omapi_object_t *)hp, MDL);
01512         host_dereference (&hp, MDL);
01513         return status;
01514 }
01515 
01516 isc_result_t dhcp_host_remove (omapi_object_t *lp,
01517                                omapi_object_t *id)
01518 {
01519         struct host_decl *hp;
01520         if (lp -> type != dhcp_type_host)
01521                 return DHCP_R_INVALIDARG;
01522         hp = (struct host_decl *)lp;
01523 
01524 #ifdef DEBUG_OMAPI
01525         log_debug ("OMAPI delete host %s", hp -> name);
01526 #endif
01527         delete_host (hp, 1);
01528         return ISC_R_SUCCESS;
01529 }
01530 
01531 isc_result_t dhcp_pool_set_value  (omapi_object_t *h,
01532                                    omapi_object_t *id,
01533                                    omapi_data_string_t *name,
01534                                    omapi_typed_data_t *value)
01535 {
01536         /* h should point to (struct pool *) */
01537         isc_result_t status;
01538 
01539         if (h -> type != dhcp_type_pool)
01540                 return DHCP_R_INVALIDARG;
01541 
01542         /* No values to set yet. */
01543 
01544         /* Try to find some inner object that can take the value. */
01545         if (h -> inner && h -> inner -> type -> set_value) {
01546                 status = ((*(h -> inner -> type -> set_value))
01547                           (h -> inner, id, name, value));
01548                 if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
01549                         return status;
01550         }
01551 
01552         return DHCP_R_UNKNOWNATTRIBUTE;
01553 }
01554 
01555 
01556 isc_result_t dhcp_pool_get_value (omapi_object_t *h, omapi_object_t *id,
01557                                   omapi_data_string_t *name,
01558                                   omapi_value_t **value)
01559 {
01560         /* h should point to (struct pool *) */
01561         isc_result_t status;
01562 
01563         if (h -> type != dhcp_type_pool)
01564                 return DHCP_R_INVALIDARG;
01565 
01566         /* No values to get yet. */
01567 
01568         /* Try to find some inner object that can provide the value. */
01569         if (h -> inner && h -> inner -> type -> get_value) {
01570                 status = ((*(h -> inner -> type -> get_value))
01571                           (h -> inner, id, name, value));
01572                 if (status == ISC_R_SUCCESS)
01573                         return status;
01574         }
01575         return DHCP_R_UNKNOWNATTRIBUTE;
01576 }
01577 
01578 isc_result_t dhcp_pool_destroy (omapi_object_t *h, const char *file, int line)
01579 {
01580 #if defined (DEBUG_MEMORY_LEAKAGE) || \
01581                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
01582         struct permit *pc, *pn;
01583 #endif
01584 
01585         if (h -> type != dhcp_type_pool)
01586                 return DHCP_R_INVALIDARG;
01587 
01588 #if defined (DEBUG_MEMORY_LEAKAGE) || \
01589                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
01590         struct pool *pool = (struct pool *)h;
01591         if (pool -> next)
01592                 pool_dereference (&pool -> next, file, line);
01593         if (pool -> group)
01594                 group_dereference (&pool -> group, file, line);
01595         if (pool -> shared_network)
01596             shared_network_dereference (&pool -> shared_network, file, line);
01597         if (pool -> active)
01598                 lease_dereference (&pool -> active, file, line);
01599         if (pool -> expired)
01600                 lease_dereference (&pool -> expired, file, line);
01601         if (pool -> free)
01602                 lease_dereference (&pool -> free, file, line);
01603         if (pool -> backup)
01604                 lease_dereference (&pool -> backup, file, line);
01605         if (pool -> abandoned)
01606                 lease_dereference (&pool -> abandoned, file, line);
01607 #if defined (FAILOVER_PROTOCOL)
01608         if (pool -> failover_peer)
01609                 dhcp_failover_state_dereference (&pool -> failover_peer,
01610                                                  file, line);
01611 #endif
01612         for (pc = pool -> permit_list; pc; pc = pn) {
01613                 pn = pc -> next;
01614                 free_permit (pc, file, line);
01615         }
01616         pool -> permit_list = (struct permit *)0;
01617 
01618         for (pc = pool -> prohibit_list; pc; pc = pn) {
01619                 pn = pc -> next;
01620                 free_permit (pc, file, line);
01621         }
01622         pool -> prohibit_list = (struct permit *)0;
01623 #endif
01624 
01625         return ISC_R_SUCCESS;
01626 }
01627 
01628 isc_result_t dhcp_pool_signal_handler (omapi_object_t *h,
01629                                        const char *name, va_list ap)
01630 {
01631         /* h should point to (struct pool *) */
01632         isc_result_t status;
01633 
01634         if (h -> type != dhcp_type_pool)
01635                 return DHCP_R_INVALIDARG;
01636 
01637         /* Can't write pools yet. */
01638 
01639         /* Try to find some inner object that can take the value. */
01640         if (h -> inner && h -> inner -> type -> signal_handler) {
01641                 status = ((*(h -> inner -> type -> signal_handler))
01642                           (h -> inner, name, ap));
01643                 if (status == ISC_R_SUCCESS)
01644                         return status;
01645         }
01646 
01647         return ISC_R_NOTFOUND;
01648 }
01649 
01650 isc_result_t dhcp_pool_stuff_values (omapi_object_t *c,
01651                                      omapi_object_t *id,
01652                                      omapi_object_t *h)
01653 {
01654         struct pool *pool;
01655         isc_result_t status;
01656 
01657         if (h->type != dhcp_type_pool)
01658                 return (DHCP_R_INVALIDARG);
01659         pool = (struct pool *)h;
01660 
01661         /*
01662          * I don't think we can actually find a pool yet
01663          * but include the output of interesting values
01664          * for when we do
01665          */
01666         status = omapi_connection_put_named_uint32(c, "lease-count",
01667                                                    ((u_int32_t)
01668                                                     pool->lease_count));
01669         if (status != ISC_R_SUCCESS)
01670                 return (status);
01671 
01672         status = omapi_connection_put_named_uint32(c, "free-leases",
01673                                                    ((u_int32_t)
01674                                                     pool->free_leases));
01675         if (status != ISC_R_SUCCESS)
01676                 return (status);
01677 
01678         status = omapi_connection_put_named_uint32(c, "backup-leases", 
01679                                                    ((u_int32_t)
01680                                                     pool->backup_leases));
01681         if (status != ISC_R_SUCCESS)
01682                 return (status);
01683         /* we could add time stamps but lets wait on those */
01684 
01685         /* Write out the inner object, if any. */
01686         if (h->inner && h->inner->type->stuff_values) {
01687                 status = ((*(h->inner->type->stuff_values))
01688                           (c, id, h->inner));
01689                 if (status == ISC_R_SUCCESS)
01690                         return (status);
01691         }
01692 
01693         return (ISC_R_SUCCESS);
01694 }
01695 
01696 isc_result_t dhcp_pool_lookup (omapi_object_t **lp,
01697                                omapi_object_t *id, omapi_object_t *ref)
01698 {
01699         /* Can't look up pools yet. */
01700 
01701         /* If we get to here without finding a pool, no valid key was
01702            specified. */
01703         if (!*lp)
01704                 return DHCP_R_NOKEYS;
01705         return ISC_R_SUCCESS;
01706 }
01707 
01708 isc_result_t dhcp_pool_create (omapi_object_t **lp,
01709                                omapi_object_t *id)
01710 {
01711         return ISC_R_NOTIMPLEMENTED;
01712 }
01713 
01714 isc_result_t dhcp_pool_remove (omapi_object_t *lp,
01715                                omapi_object_t *id)
01716 {
01717         return ISC_R_NOTIMPLEMENTED;
01718 }
01719 
01720 static isc_result_t
01721 class_set_value (omapi_object_t *h,
01722                  omapi_object_t *id,
01723                  omapi_data_string_t *name,
01724                  omapi_typed_data_t *value)
01725 {
01726         struct class *class;
01727         struct class *superclass = 0;
01728         isc_result_t status;
01729         int issubclass = (h -> type == dhcp_type_subclass);
01730 
01731         class = (struct class *)h;
01732 
01733         if (!omapi_ds_strcmp(name, "name")) {
01734                 char *tname;
01735 
01736                 if (class->name)
01737                         return ISC_R_EXISTS;
01738 
01739                 if ((tname = dmalloc(value->u.buffer.len + 1, MDL)) == NULL) {
01740                         return ISC_R_NOMEMORY;
01741                 }
01742 
01743                 /* tname is null terminated from dmalloc() */
01744                 memcpy(tname, value->u.buffer.value, value->u.buffer.len);
01745 
01746                 if (issubclass) {
01747                         status = find_class(&superclass, tname, MDL);
01748                         dfree(tname, MDL);
01749 
01750                         if (status == ISC_R_NOTFOUND)
01751                                 return status;
01752 
01753                         if (class->superclass != NULL)
01754                                 class_dereference(&class->superclass, MDL);
01755                         class_reference(&class->superclass, superclass, MDL);
01756 
01757                         if (class->group != NULL)
01758                                 group_dereference(&class->group, MDL);
01759                         group_reference(&class->group, superclass->group, MDL);
01760 
01761                         class->lease_limit = superclass->lease_limit;
01762                         if (class->lease_limit != 0) {
01763                                 class->billed_leases =
01764                                         dmalloc(class->lease_limit *
01765                                                 sizeof(struct lease *),
01766                                                 MDL);
01767                                 if (class->billed_leases == NULL) {
01768                                         return ISC_R_NOMEMORY;
01769                                 }
01770                         }
01771 
01772                 } else if (value->type == omapi_datatype_data ||
01773                            value->type == omapi_datatype_string) {
01774                         class->name = dmalloc(value->u.buffer.len + 1, MDL);
01775                         if (!class->name)
01776                                 return ISC_R_NOMEMORY;
01777 
01778                         /* class->name is null-terminated from dmalloc() */
01779                         memcpy(class->name, value->u.buffer.value,
01780                                value->u.buffer.len);
01781                 } else
01782                         return DHCP_R_INVALIDARG;
01783 
01784                 return ISC_R_SUCCESS;
01785         }
01786 
01787 
01788         if (issubclass && !omapi_ds_strcmp(name, "hashstring")) {
01789                 if (class->hash_string.data)
01790                         return ISC_R_EXISTS;
01791 
01792                 if (value->type == omapi_datatype_data ||
01793                     value->type == omapi_datatype_string) {
01794                         if (!buffer_allocate(&class->hash_string.buffer,
01795                                              value->u.buffer.len, MDL))
01796                                 return ISC_R_NOMEMORY;
01797                         class->hash_string.data =
01798                                         class->hash_string.buffer->data;
01799                         memcpy(class->hash_string.buffer->data,
01800                                value->u.buffer.value, value->u.buffer.len);
01801                         class->hash_string.len = value->u.buffer.len;
01802                 } else
01803                         return DHCP_R_INVALIDARG;
01804 
01805                 return ISC_R_SUCCESS;
01806         }
01807 
01808         if (!omapi_ds_strcmp(name, "group")) {
01809                 if (value->type == omapi_datatype_data ||
01810                     value->type == omapi_datatype_string) {
01811                         struct group_object *group = NULL;
01812 
01813                         group_hash_lookup(&group, group_name_hash,
01814                                           (char *)value->u.buffer.value,
01815                                           value->u.buffer.len, MDL);
01816                         if (!group || (group->flags & GROUP_OBJECT_DELETED))
01817                                 return ISC_R_NOTFOUND;
01818                         if (class->group)
01819                                 group_dereference(&class->group, MDL);
01820                         group_reference(&class->group, group->group, MDL);
01821                         group_object_dereference(&group, MDL);
01822                 } else
01823                         return DHCP_R_INVALIDARG;
01824 
01825                 return ISC_R_SUCCESS;
01826         }
01827 
01828 
01829         /* note we do not support full expressions via omapi because the
01830            expressions parser needs to be re-done to support parsing from
01831            strings and not just files. */
01832 
01833         if (!omapi_ds_strcmp(name, "match")) {
01834                 if (value->type == omapi_datatype_data ||
01835                     value->type == omapi_datatype_string) {
01836                         unsigned minlen = (value->u.buffer.len > 8 ?
01837                                                 8 : value->u.buffer.len);
01838 
01839                         if (!strncmp("hardware",
01840                                      (char *)value->u.buffer.value, minlen))
01841                         {
01842                                 if (!expression_allocate(&class->submatch, MDL))
01843                                         return ISC_R_NOMEMORY;
01844 
01845                                 class->submatch->op = expr_hardware;
01846                         } else
01847                                 return DHCP_R_INVALIDARG;
01848                 } else
01849                         return DHCP_R_INVALIDARG;
01850 
01851                 return ISC_R_SUCCESS;
01852         }
01853 
01854 
01855         if (!omapi_ds_strcmp(name, "option")) {
01856                 if (value->type == omapi_datatype_data ||
01857                     value->type == omapi_datatype_string) {
01858                         /* XXXJAB support 'options' here. */
01859                         /* XXXJAB specifically 'bootfile-name' */
01860                         return DHCP_R_INVALIDARG; /* XXX tmp */
01861                 } else
01862                         return DHCP_R_INVALIDARG;
01863 
01864                 /*
01865                  * Currently no way to get here, if we update the above
01866                  * code so that we do get here this return needs to be
01867                  * uncommented.
01868                  * return ISC_R_SUCCESS;
01869                  */
01870         }
01871 
01872 
01873         /* Try to find some inner object that can take the value. */
01874         if (h->inner && h->inner->type->set_value) {
01875                 status = ((*(h->inner->type->set_value))
01876                           (h->inner, id, name, value));
01877                 if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
01878                         return status;
01879         }
01880 
01881         return DHCP_R_UNKNOWNATTRIBUTE;
01882 }
01883 
01884 
01885 
01886 isc_result_t dhcp_class_set_value  (omapi_object_t *h,
01887                                     omapi_object_t *id,
01888                                     omapi_data_string_t *name,
01889                                     omapi_typed_data_t *value)
01890 {
01891         if (h -> type != dhcp_type_class)
01892                 return DHCP_R_INVALIDARG;
01893 
01894         return class_set_value(h, id, name, value);
01895 }
01896 
01897 isc_result_t dhcp_class_get_value (omapi_object_t *h, omapi_object_t *id,
01898                                    omapi_data_string_t *name,
01899                                    omapi_value_t **value)
01900 {
01901         struct class *class;
01902         isc_result_t status;
01903 
01904         if (h -> type != dhcp_type_class)
01905                 return DHCP_R_INVALIDARG;
01906         class = (struct class *)h;
01907 
01908         if (!omapi_ds_strcmp (name, "name"))
01909                 return omapi_make_string_value (value, name, class -> name,
01910                                                 MDL);
01911 
01912         /* Try to find some inner object that can provide the value. */
01913         if (h -> inner && h -> inner -> type -> get_value) {
01914                 status = ((*(h -> inner -> type -> get_value))
01915                           (h -> inner, id, name, value));
01916                 if (status == ISC_R_SUCCESS)
01917                         return status;
01918         }
01919         return DHCP_R_UNKNOWNATTRIBUTE;
01920 }
01921 
01922 isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
01923 {
01924 
01925         if (h -> type != dhcp_type_class && h -> type != dhcp_type_subclass)
01926                 return DHCP_R_INVALIDARG;
01927         struct class *class = (struct class *)h;
01928 
01929         if (class -> nic)
01930                 class_dereference (&class -> nic, file, line);
01931         if (class -> superclass)
01932                 class_dereference (&class -> superclass, file, line);
01933         if (class -> name) {
01934                 dfree (class -> name, file, line);
01935                 class -> name = (char *)0;
01936         }
01937         if (class -> billed_leases) {
01938                 int i;
01939                 for (i = 0; i < class -> lease_limit; i++) {
01940                         if (class -> billed_leases [i]) {
01941                                 lease_dereference (&class -> billed_leases [i],
01942                                                    file, line);
01943                         }
01944                 }
01945                 dfree (class -> billed_leases, file, line);
01946                 class -> billed_leases = (struct lease **)0;
01947         }
01948         if (class -> hash) {
01949                 class_free_hash_table (&class -> hash, file, line);
01950                 class -> hash = (class_hash_t *)0;
01951         }
01952         data_string_forget (&class -> hash_string, file, line);
01953 
01954         if (class -> expr)
01955                 expression_dereference (&class -> expr, file, line);
01956         if (class -> submatch)
01957                 expression_dereference (&class -> submatch, file, line);
01958         if (class -> group)
01959                 group_dereference (&class -> group, file, line);
01960         if (class -> statements)
01961                 executable_statement_dereference (&class -> statements,
01962                                                   file, line);
01963         if (class -> superclass)
01964                 class_dereference (&class -> superclass, file, line);
01965 
01966         return ISC_R_SUCCESS;
01967 }
01968 
01969 static isc_result_t
01970 class_signal_handler(omapi_object_t *h,
01971                      const char *name, va_list ap)
01972 {
01973         struct class *class = (struct class *)h;
01974         isc_result_t status;
01975         int updatep = 0;
01976         int issubclass;
01977 
01978         issubclass = (h->type == dhcp_type_subclass);
01979 
01980         if (!strcmp (name, "updated")) {
01981 
01982                 if (!issubclass) {
01983                         if (class->name == 0 || strlen(class->name) == 0) {
01984                                 return DHCP_R_INVALIDARG;
01985                         }
01986                 } else {
01987                         if (class->superclass == 0) {
01988                                 return DHCP_R_INVALIDARG; /* didn't give name */
01989                         }
01990 
01991                         if (class->hash_string.data == NULL) {
01992                                 return DHCP_R_INVALIDARG;
01993                         }
01994                 }
01995 
01996 
01997                 if (issubclass) {
01998                         if (!class->superclass->hash)
01999                                 class_new_hash(&class->superclass->hash,
02000                                                SCLASS_HASH_SIZE, MDL);
02001 
02002                         class_hash_add(class->superclass->hash,
02003                                        (const char *)class->hash_string.data,
02004                                        class->hash_string.len,
02005                                        (void *)class, MDL);
02006                 }
02007 
02008 #ifdef DEBUG_OMAPI
02009                 if (issubclass) {
02010                         log_debug ("OMAPI added subclass %s",
02011                                    class->superclass->name);
02012                 } else {
02013                         log_debug ("OMAPI added class %s", class->name);
02014                 }
02015 #endif
02016 
02017                 status = enter_class (class, 1, 1);
02018                 if (status != ISC_R_SUCCESS)
02019                         return status;
02020                 updatep = 1;
02021         }
02022 
02023         /* Try to find some inner object that can take the value. */
02024         if (h->inner && h->inner->type->signal_handler) {
02025                 status = ((*(h->inner->type->signal_handler))
02026                           (h->inner, name, ap));
02027                 if (status == ISC_R_SUCCESS)
02028                         return status;
02029         }
02030 
02031         if (updatep)
02032                 return ISC_R_SUCCESS;
02033 
02034         return ISC_R_NOTFOUND;
02035 }
02036 
02037 
02038 isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
02039                                         const char *name, va_list ap)
02040 {
02041         if (h -> type != dhcp_type_class)
02042                 return DHCP_R_INVALIDARG;
02043 
02044         return class_signal_handler(h, name, ap);
02045 }
02046 
02047 
02048 /*
02049  * Routine to put out generic class & subclass information
02050  */
02051 isc_result_t class_stuff_values (omapi_object_t *c,
02052                                  omapi_object_t *id,
02053                                  omapi_object_t *h)
02054 {
02055         struct class *class;
02056         isc_result_t status;
02057 
02058         class = (struct class *)h;
02059 
02060         status = omapi_connection_put_named_uint32(c, "lease-limit",
02061                                                    ((u_int32_t)
02062                                                     class->lease_limit));
02063         if (status != ISC_R_SUCCESS)
02064                 return (status);
02065 
02066         status = omapi_connection_put_named_uint32(c, "leases-used",
02067                                                    ((u_int32_t)
02068                                                     class->leases_consumed));
02069         if (status != ISC_R_SUCCESS)
02070                 return (status);
02071 
02072         /* Write out the inner object, if any. */
02073         if (h->inner && h->inner->type->stuff_values) {
02074                 status = ((*(h->inner->type->stuff_values))
02075                           (c, id, h->inner));
02076                 if (status == ISC_R_SUCCESS)
02077                         return (status);
02078         }
02079 
02080         return (ISC_R_SUCCESS);
02081 }
02082 
02083 
02084 isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
02085                                       omapi_object_t *id,
02086                                       omapi_object_t *h)
02087 {
02088         if (h->type != dhcp_type_class)
02089                 return (DHCP_R_INVALIDARG);
02090 
02091         /* add any class specific items here */
02092 
02093         return (class_stuff_values(c, id, h));
02094 }
02095 
02096 static isc_result_t class_lookup (omapi_object_t **lp,
02097                                   omapi_object_t *id, omapi_object_t *ref,
02098                                   omapi_object_type_t *typewanted)
02099 {
02100         omapi_value_t *nv = NULL;
02101         omapi_value_t *hv = NULL;
02102         isc_result_t status;
02103         struct class *class = 0;
02104         struct class *subclass = 0;
02105 
02106         *lp = NULL;
02107 
02108         if (ref == NULL)
02109                 return (DHCP_R_NOKEYS);
02110 
02111         /* see if we have a name */
02112         status = omapi_get_value_str(ref, id, "name", &nv);
02113         if (status == ISC_R_SUCCESS) {
02114                 char *name = dmalloc(nv->value->u.buffer.len + 1, MDL);
02115                 memcpy (name,
02116                         nv->value->u.buffer.value,
02117                         nv->value->u.buffer.len);
02118 
02119                 omapi_value_dereference(&nv, MDL);
02120 
02121                 find_class(&class, name, MDL);
02122 
02123                 dfree(name, MDL);
02124 
02125                 if (class == NULL) {
02126                         return (ISC_R_NOTFOUND);
02127                 }
02128 
02129                 if (typewanted == dhcp_type_subclass) {
02130                         status = omapi_get_value_str(ref, id,
02131                                                      "hashstring", &hv);
02132                         if (status != ISC_R_SUCCESS) {
02133                                 class_dereference(&class, MDL);
02134                                 return (DHCP_R_NOKEYS);
02135                         }
02136 
02137                         if (hv->value->type != omapi_datatype_data &&
02138                             hv->value->type != omapi_datatype_string) {
02139                                 class_dereference(&class, MDL);
02140                                 omapi_value_dereference(&hv, MDL);
02141                                 return (DHCP_R_NOKEYS);
02142                         }
02143 
02144                         class_hash_lookup(&subclass, class->hash,
02145                                           (const char *)
02146                                           hv->value->u.buffer.value,
02147                                           hv->value->u.buffer.len, MDL);
02148 
02149                         omapi_value_dereference(&hv, MDL);
02150 
02151                         class_dereference(&class, MDL);
02152 
02153                         if (subclass == NULL) {
02154                                 return (ISC_R_NOTFOUND);
02155                         }
02156 
02157                         class_reference(&class, subclass, MDL);
02158                         class_dereference(&subclass, MDL);
02159                 }
02160 
02161                 /* Don't return the object if the type is wrong. */
02162                 if (class->type != typewanted) {
02163                         class_dereference(&class, MDL);
02164                         return (DHCP_R_INVALIDARG);
02165                 }
02166 
02167                 if (class->flags & CLASS_DECL_DELETED) {
02168                         class_dereference(&class, MDL);
02169                         return (ISC_R_NOTFOUND);
02170                 }
02171 
02172                 omapi_object_reference(lp, (omapi_object_t *)class, MDL);
02173                 class_dereference(&class, MDL);
02174 
02175                 return (ISC_R_SUCCESS);
02176         }
02177 
02178         return (DHCP_R_NOKEYS);
02179 }
02180 
02181 
02182 isc_result_t dhcp_class_lookup (omapi_object_t **lp,
02183                                 omapi_object_t *id, omapi_object_t *ref)
02184 {
02185         return class_lookup(lp, id, ref, dhcp_type_class);
02186 }
02187 
02188 isc_result_t dhcp_class_create (omapi_object_t **lp,
02189                                 omapi_object_t *id)
02190 {
02191         struct class *cp = 0;
02192         isc_result_t status;
02193 
02194         status = class_allocate(&cp, MDL);
02195         if (status != ISC_R_SUCCESS)
02196                 return (status);
02197 
02198         clone_group(&cp->group, root_group, MDL);
02199         cp->flags = CLASS_DECL_DYNAMIC;
02200         status = omapi_object_reference(lp, (omapi_object_t *)cp, MDL);
02201         class_dereference(&cp, MDL);
02202         return (status);
02203 }
02204 
02205 isc_result_t dhcp_class_remove (omapi_object_t *lp,
02206                                 omapi_object_t *id)
02207 {
02208         struct class *cp;
02209         if (lp -> type != dhcp_type_class)
02210                 return DHCP_R_INVALIDARG;
02211         cp = (struct class *)lp;
02212 
02213 #ifdef DEBUG_OMAPI
02214         log_debug ("OMAPI delete class %s", cp -> name);
02215 #endif
02216 
02217         delete_class (cp, 1);
02218         return ISC_R_SUCCESS;
02219 }
02220 
02221 isc_result_t dhcp_subclass_set_value  (omapi_object_t *h,
02222                                        omapi_object_t *id,
02223                                        omapi_data_string_t *name,
02224                                        omapi_typed_data_t *value)
02225 {
02226         if (h -> type != dhcp_type_subclass)
02227                 return DHCP_R_INVALIDARG;
02228 
02229         return class_set_value(h, id, name, value);
02230 }
02231 
02232 
02233 isc_result_t dhcp_subclass_get_value (omapi_object_t *h, omapi_object_t *id,
02234                                       omapi_data_string_t *name,
02235                                       omapi_value_t **value)
02236 {
02237         struct class *subclass;
02238         isc_result_t status;
02239 
02240         if (h -> type != dhcp_type_class)
02241                 return DHCP_R_INVALIDARG;
02242         subclass = (struct class *)h;
02243         if (subclass -> name != 0)
02244                 return DHCP_R_INVALIDARG;
02245 
02246         /* XXXJAB No values to get yet. */
02247 
02248         /* Try to find some inner object that can provide the value. */
02249         if (h -> inner && h -> inner -> type -> get_value) {
02250                 status = ((*(h -> inner -> type -> get_value))
02251                           (h -> inner, id, name, value));
02252                 if (status == ISC_R_SUCCESS)
02253                         return status;
02254         }
02255         return DHCP_R_UNKNOWNATTRIBUTE;
02256 }
02257 
02258 isc_result_t dhcp_subclass_signal_handler (omapi_object_t *h,
02259                                            const char *name, va_list ap)
02260 {
02261         if (h -> type != dhcp_type_subclass)
02262                 return DHCP_R_INVALIDARG;
02263 
02264         return class_signal_handler(h, name, ap);
02265 }
02266 
02267 
02268 isc_result_t dhcp_subclass_stuff_values (omapi_object_t *c,
02269                                          omapi_object_t *id,
02270                                          omapi_object_t *h)
02271 {
02272         struct class *subclass;
02273 
02274         if (h->type != dhcp_type_subclass)
02275                 return (DHCP_R_INVALIDARG);
02276         subclass = (struct class *)h;
02277         if (subclass->name != 0)
02278                 return (DHCP_R_INVALIDARG);
02279 
02280         /* add any subclass specific items here */
02281 
02282         return (class_stuff_values(c, id, h));
02283 }
02284 
02285 isc_result_t dhcp_subclass_lookup (omapi_object_t **lp,
02286                                    omapi_object_t *id, omapi_object_t *ref)
02287 {
02288         return class_lookup(lp, id, ref, dhcp_type_subclass);
02289 }
02290 
02291 
02292 
02293 
02294 isc_result_t dhcp_subclass_create (omapi_object_t **lp,
02295                                    omapi_object_t *id)
02296 {
02297         struct class *cp = 0;
02298         isc_result_t status;
02299 
02300         status = subclass_allocate(&cp, MDL);
02301         if (status != ISC_R_SUCCESS)
02302                 return status;
02303         group_reference (&cp->group, root_group, MDL);
02304 
02305         cp->flags = CLASS_DECL_DYNAMIC;
02306 
02307         status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
02308         subclass_dereference (&cp, MDL);
02309         return status;
02310 }
02311 
02312 isc_result_t dhcp_subclass_remove (omapi_object_t *lp,
02313                                    omapi_object_t *id)
02314 {
02315         struct class *cp;
02316         if (lp -> type != dhcp_type_subclass)
02317                 return DHCP_R_INVALIDARG;
02318         cp = (struct class *)lp;
02319 
02320 #ifdef DEBUG_OMAPI
02321         log_debug ("OMAPI delete subclass %s", cp -> name);
02322 #endif
02323 
02324         delete_class (cp, 1);
02325 
02326         return ISC_R_SUCCESS;
02327 }
02328 
02329 isc_result_t binding_scope_set_value (struct binding_scope *scope, int createp,
02330                                       omapi_data_string_t *name,
02331                                       omapi_typed_data_t *value)
02332 {
02333         struct binding *bp;
02334         char *nname;
02335         struct binding_value *nv;
02336         nname = dmalloc (name -> len + 1, MDL);
02337         if (!nname)
02338                 return ISC_R_NOMEMORY;
02339         memcpy (nname, name -> value, name -> len);
02340         nname [name -> len] = 0;
02341         bp = find_binding (scope, nname);
02342         if (!bp && !createp) {
02343                 dfree (nname, MDL);
02344                 return DHCP_R_UNKNOWNATTRIBUTE;
02345         }
02346         if (!value) {
02347                 dfree (nname, MDL);
02348                 if (!bp)
02349                         return DHCP_R_UNKNOWNATTRIBUTE;
02350                 binding_value_dereference (&bp -> value, MDL);
02351                 return ISC_R_SUCCESS;
02352         }
02353 
02354         nv = (struct binding_value *)0;
02355         if (!binding_value_allocate (&nv, MDL)) {
02356                 dfree (nname, MDL);
02357                 return ISC_R_NOMEMORY;
02358         }
02359         switch (value -> type) {
02360               case omapi_datatype_int:
02361                 nv -> type = binding_numeric;
02362                 nv -> value.intval = value -> u.integer;
02363                 break;
02364 
02365               case omapi_datatype_string:
02366               case omapi_datatype_data:
02367                 if (!buffer_allocate (&nv -> value.data.buffer,
02368                                       value -> u.buffer.len, MDL)) {
02369                         binding_value_dereference (&nv, MDL);
02370                         dfree (nname, MDL);
02371                         return ISC_R_NOMEMORY;
02372                 }
02373                 memcpy (&nv -> value.data.buffer -> data [1],
02374                         value -> u.buffer.value, value -> u.buffer.len);
02375                 nv -> value.data.len = value -> u.buffer.len;
02376                 break;
02377 
02378               case omapi_datatype_object:
02379                 binding_value_dereference (&nv, MDL);
02380                 dfree (nname, MDL);
02381                 return DHCP_R_INVALIDARG;
02382         }
02383 
02384         if (!bp) {
02385                 bp = dmalloc (sizeof *bp, MDL);
02386                 if (!bp) {
02387                         binding_value_dereference (&nv, MDL);
02388                         dfree (nname, MDL);
02389                         return ISC_R_NOMEMORY;
02390                 }
02391                 memset (bp, 0, sizeof *bp);
02392                 bp -> name = nname;
02393                 bp -> next = scope -> bindings;
02394                 scope -> bindings = bp;
02395         } else {
02396                 if (bp -> value)
02397                         binding_value_dereference (&bp -> value, MDL);
02398                 dfree (nname, MDL);
02399         }
02400         binding_value_reference (&bp -> value, nv, MDL);
02401         binding_value_dereference (&nv, MDL);
02402         return ISC_R_SUCCESS;
02403 }
02404 
02405 isc_result_t binding_scope_get_value (omapi_value_t **value,
02406                                       struct binding_scope *scope,
02407                                       omapi_data_string_t *name)
02408 {
02409         struct binding *bp;
02410         omapi_typed_data_t *td;
02411         isc_result_t status;
02412         char *nname;
02413         nname = dmalloc (name -> len + 1, MDL);
02414         if (!nname)
02415                 return ISC_R_NOMEMORY;
02416         memcpy (nname, name -> value, name -> len);
02417         nname [name -> len] = 0;
02418         bp = find_binding (scope, nname);
02419         dfree (nname, MDL);
02420         if (!bp)
02421                 return DHCP_R_UNKNOWNATTRIBUTE;
02422         if (!bp -> value)
02423                 return DHCP_R_UNKNOWNATTRIBUTE;
02424 
02425         switch (bp -> value -> type) {
02426               case binding_boolean:
02427                 td = (omapi_typed_data_t *)0;
02428                 status = omapi_typed_data_new (MDL, &td, omapi_datatype_int,
02429                                                bp -> value -> value.boolean);
02430                 break;
02431 
02432               case binding_numeric:
02433                 td = (omapi_typed_data_t *)0;
02434                 status = omapi_typed_data_new (MDL, &td, omapi_datatype_int,
02435                                                (int)
02436                                                bp -> value -> value.intval);
02437                 break;
02438 
02439               case binding_data:
02440                 td = (omapi_typed_data_t *)0;
02441                 status = omapi_typed_data_new (MDL, &td, omapi_datatype_data,
02442                                                bp -> value -> value.data.len);
02443                 if (status != ISC_R_SUCCESS)
02444                         return status;
02445                 memcpy (&td -> u.buffer.value [0],
02446                         bp -> value -> value.data.data,
02447                         bp -> value -> value.data.len);
02448                 break;
02449 
02450                 /* Can't return values for these two (yet?). */
02451               case binding_dns:
02452               case binding_function:
02453                 return DHCP_R_INVALIDARG;
02454 
02455               default:
02456                 log_fatal ("Impossible case at %s:%d.", MDL);
02457                 return ISC_R_FAILURE;
02458         }
02459 
02460         if (status != ISC_R_SUCCESS)
02461                 return status;
02462         status = omapi_value_new (value, MDL);
02463         if (status != ISC_R_SUCCESS) {
02464                 omapi_typed_data_dereference (&td, MDL);
02465                 return status;
02466         }
02467 
02468         omapi_data_string_reference (&(*value) -> name, name, MDL);
02469         omapi_typed_data_reference (&(*value) -> value, td, MDL);
02470         omapi_typed_data_dereference (&td, MDL);
02471 
02472         return ISC_R_SUCCESS;
02473 }
02474 
02475 isc_result_t binding_scope_stuff_values (omapi_object_t *c,
02476                                          struct binding_scope *scope)
02477 {
02478         struct binding *bp;
02479         unsigned len;
02480         isc_result_t status;
02481 
02482         for (bp = scope -> bindings; bp; bp = bp -> next) {
02483             if (bp -> value) {
02484                 if (bp -> value -> type == binding_dns ||
02485                     bp -> value -> type == binding_function)
02486                         continue;
02487 
02488                 /* Stuff the name. */
02489                 len = strlen (bp -> name);
02490                 status = omapi_connection_put_uint16 (c, len);
02491                 if (status != ISC_R_SUCCESS)
02492                     return status;
02493                 status = omapi_connection_copyin (c,
02494                                                   (unsigned char *)bp -> name,
02495                                                   len);
02496                 if (status != ISC_R_SUCCESS)
02497                         return status;
02498 
02499                 switch (bp -> value -> type) {
02500                   case binding_boolean:
02501                     status = omapi_connection_put_uint32 (c,
02502                                                           sizeof (u_int32_t));
02503                     if (status != ISC_R_SUCCESS)
02504                         return status;
02505                     status = (omapi_connection_put_uint32
02506                               (c,
02507                                ((u_int32_t)(bp -> value -> value.boolean))));
02508                     if (status != ISC_R_SUCCESS)
02509                             return status;
02510                     break;
02511 
02512                   case binding_data:
02513                     status = (omapi_connection_put_uint32
02514                               (c, bp -> value -> value.data.len));
02515                     if (status != ISC_R_SUCCESS)
02516                         return status;
02517                     if (bp -> value -> value.data.len) {
02518                         status = (omapi_connection_copyin
02519                                   (c, bp -> value -> value.data.data,
02520                                    bp -> value -> value.data.len));
02521                         if (status != ISC_R_SUCCESS)
02522                             return status;
02523                     }
02524                     break;
02525 
02526                   case binding_numeric:
02527                     status = (omapi_connection_put_uint32
02528                               (c, sizeof (u_int32_t)));
02529                     if (status != ISC_R_SUCCESS)
02530                             return status;
02531                     status = (omapi_connection_put_uint32
02532                               (c, ((u_int32_t)
02533                                    (bp -> value -> value.intval))));
02534                     if (status != ISC_R_SUCCESS)
02535                             return status;
02536                     break;
02537 
02538 
02539                     /* NOTREACHED */
02540                   case binding_dns:
02541                   case binding_function:
02542                     break;
02543                 }
02544             }
02545         }
02546         return ISC_R_SUCCESS;
02547 }
02548 
02549 /* vim: set tabstop=8: */

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1