dhcpctl/dhcpctl.c

Go to the documentation of this file.
00001 /* dhcpctl.c
00002 
00003    Subroutines providing general support for objects. */
00004 
00005 /*
00006  * Copyright (c) 2009,2013,2014 by Internet Systems Consortium, Inc. ("ISC")
00007  * Copyright (c) 2004,2007 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 #include "dhcpd.h"
00031 #include <omapip/omapip_p.h>
00032 #include "dhcpctl.h"
00033 
00034 omapi_object_type_t *dhcpctl_callback_type;
00035 omapi_object_type_t *dhcpctl_remote_type;
00036 
00037 /* dhcpctl_initialize ()
00038 
00039    Must be called before any other dhcpctl function. */
00040 
00041 dhcpctl_status dhcpctl_initialize ()
00042 {
00043         isc_result_t status;
00044 
00045         /* Set up the isc and dns library managers */
00046         status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
00047                                      NULL, NULL);
00048         if (status != ISC_R_SUCCESS)
00049                 return status;
00050 
00051         status = omapi_init();
00052         if (status != ISC_R_SUCCESS)
00053                 return status;
00054 
00055         status = omapi_object_type_register (&dhcpctl_callback_type,
00056                                              "dhcpctl-callback",
00057                                              dhcpctl_callback_set_value,
00058                                              dhcpctl_callback_get_value,
00059                                              dhcpctl_callback_destroy,
00060                                              dhcpctl_callback_signal_handler,
00061                                              dhcpctl_callback_stuff_values,
00062                                              0, 0, 0, 0, 0, 0,
00063                                              sizeof
00064                                              (dhcpctl_callback_object_t), 0,
00065                                              RC_MISC);
00066         if (status != ISC_R_SUCCESS)
00067                 return status;
00068 
00069         status = omapi_object_type_register (&dhcpctl_remote_type,
00070                                              "dhcpctl-remote",
00071                                              dhcpctl_remote_set_value,
00072                                              dhcpctl_remote_get_value,
00073                                              dhcpctl_remote_destroy,
00074                                              dhcpctl_remote_signal_handler,
00075                                              dhcpctl_remote_stuff_values,
00076                                              0, 0, 0, 0, 0, 0,
00077                                              sizeof (dhcpctl_remote_object_t),
00078                                              0, RC_MISC);
00079         if (status != ISC_R_SUCCESS)
00080                 return status;
00081 
00082         return ISC_R_SUCCESS;
00083 }
00084 
00085 /* dhcpctl_connect
00086 
00087    synchronous
00088    returns nonzero status code if it didn't connect, zero otherwise
00089    stores connection handle through connection, which can be used
00090    for subsequent access to the specified server. 
00091    server_name is the name of the server, and port is the TCP
00092    port on which it is listening.
00093    authinfo is the handle to an object containing authentication
00094    information. */
00095 
00096 dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
00097                                 const char *server_name, int port,
00098                                 dhcpctl_handle authinfo)
00099 {
00100         isc_result_t status;
00101 
00102         status = omapi_generic_new (connection, MDL);
00103         if (status != ISC_R_SUCCESS) {
00104                 return status;
00105         }
00106 
00107         status = omapi_protocol_connect (*connection, server_name,
00108                                          (unsigned)port, authinfo);
00109         if (status == ISC_R_SUCCESS)
00110                 return status;
00111         if (status != DHCP_R_INCOMPLETE) {
00112                 omapi_object_dereference (connection, MDL);
00113                 return status;
00114         }
00115 
00116         status = omapi_wait_for_completion (*connection, 0);
00117         if (status != ISC_R_SUCCESS) {
00118                 omapi_object_dereference (connection, MDL);
00119                 return status;
00120         }
00121 
00122         return status;
00123 }
00124 
00125 /* dhcpctl_wait_for_completion
00126 
00127    synchronous
00128    returns zero if the callback completes, a nonzero status if
00129    there was some problem relating to the wait operation.   The
00130    status of the queued request will be stored through s, and
00131    will also be either zero for success or nonzero for some kind
00132    of failure.    Never returns until completion or until the
00133    connection to the server is lost.   This performs the same
00134    function as dhcpctl_set_callback and the subsequent callback,
00135    for programs that want to do inline execution instead of using
00136    callbacks. */
00137 
00138 dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
00139                                             dhcpctl_status *s)
00140 {
00141         isc_result_t status;
00142         status = omapi_wait_for_completion (h, 0);
00143         if (status != ISC_R_SUCCESS)
00144                 return status;
00145         if (h -> type == dhcpctl_remote_type)
00146                 *s = ((dhcpctl_remote_object_t *)h) -> waitstatus;
00147         return ISC_R_SUCCESS;
00148 }
00149 
00150 /* dhcpctl_get_value
00151 
00152    synchronous
00153    returns zero if the call succeeded, a nonzero status code if
00154    it didn't. 
00155    result is the address of an empty data string (initialized
00156    with bzero or cleared with data_string_forget).   On
00157    successful completion, the addressed data string will contain
00158    the value that was fetched.
00159    dhcpctl_handle refers to some dhcpctl item
00160    value_name refers to some value related to that item - e.g.,
00161    for a handle associated with a completed host lookup, value
00162    could be one of "hardware-address", "dhcp-client-identifier",
00163    "known" or "client-hostname". */
00164 
00165 dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result,
00166                                   dhcpctl_handle h, const char *value_name)
00167 {
00168         isc_result_t status;
00169         omapi_value_t *tv = (omapi_value_t *)0;
00170         unsigned len;
00171         int ip;
00172 
00173         status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv);
00174         if (status != ISC_R_SUCCESS)
00175                 return status;
00176 
00177         switch (tv -> value -> type) {
00178               case omapi_datatype_int:
00179                 len = sizeof (int);
00180                 break;
00181 
00182               case omapi_datatype_string:
00183               case omapi_datatype_data:
00184                 len = tv -> value -> u.buffer.len;
00185                 break;
00186 
00187               case omapi_datatype_object:
00188                 len = sizeof (omapi_handle_t);
00189                 break;
00190 
00191               default:
00192                 omapi_typed_data_dereference (&tv -> value, MDL);
00193                 return ISC_R_UNEXPECTED;
00194         }
00195 
00196         status = omapi_data_string_new (result, len, MDL);
00197         if (status != ISC_R_SUCCESS) {
00198                 omapi_typed_data_dereference (&tv -> value, MDL);
00199                 return status;
00200         }
00201 
00202         switch (tv -> value -> type) {
00203               case omapi_datatype_int:
00204                 ip = htonl (tv -> value -> u.integer);
00205                 memcpy ((*result) -> value, &ip, sizeof ip);
00206                 break;
00207 
00208               case omapi_datatype_string:
00209               case omapi_datatype_data:
00210                 memcpy ((*result) -> value,
00211                         tv -> value -> u.buffer.value,
00212                         tv -> value -> u.buffer.len);
00213                 break;
00214 
00215               case omapi_datatype_object:
00216                 ip = htonl (tv -> value -> u.object -> handle);
00217                 memcpy ((*result) -> value, &ip, sizeof ip);
00218                 break;
00219         }
00220 
00221         omapi_value_dereference (&tv, MDL);
00222         return ISC_R_SUCCESS;
00223 }
00224 
00225 /* dhcpctl_get_boolean
00226 
00227    like dhcpctl_get_value, but more convenient for boolean
00228    values, since no data_string needs to be dealt with. */
00229 
00230 dhcpctl_status dhcpctl_get_boolean (int *result,
00231                                     dhcpctl_handle h, const char *value_name)
00232 {
00233         isc_result_t status;
00234         dhcpctl_data_string data = (dhcpctl_data_string)0;
00235         int rv;
00236         
00237         status = dhcpctl_get_value (&data, h, value_name);
00238         if (status != ISC_R_SUCCESS)
00239                 return status;
00240         if (data -> len != sizeof rv) {
00241                 omapi_data_string_dereference (&data, MDL);
00242                 return ISC_R_UNEXPECTED;
00243         }
00244         memcpy (&rv, data -> value, sizeof rv);
00245         *result = ntohl (rv);
00246         return ISC_R_SUCCESS;
00247 }
00248 
00249 /* dhcpctl_set_value
00250 
00251    Sets a value on an object referred to by a dhcpctl_handle.
00252    The opposite of dhcpctl_get_value.   Does not update the
00253    server - just sets the value on the handle. */
00254 
00255 dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, dhcpctl_data_string value,
00256                                   const char *value_name)
00257 {
00258         isc_result_t status;
00259         omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
00260         omapi_data_string_t *name = (omapi_data_string_t *)0;
00261 
00262         status = omapi_data_string_new (&name, strlen (value_name), MDL);
00263         if (status != ISC_R_SUCCESS)
00264                 return status;
00265         memcpy (name -> value, value_name, strlen (value_name));
00266 
00267         status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data,
00268                                        value -> len);
00269         if (status != ISC_R_SUCCESS) {
00270                 omapi_data_string_dereference (&name, MDL);
00271                 return status;
00272         }
00273         memcpy (tv -> u.buffer.value, value -> value, value -> len);
00274 
00275         status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
00276         omapi_data_string_dereference (&name, MDL);
00277         omapi_typed_data_dereference (&tv, MDL);
00278         return status;
00279 }
00280 
00281 /* dhcpctl_set_string_value
00282 
00283    Sets a NUL-terminated ASCII value on an object referred to by
00284    a dhcpctl_handle.   like dhcpctl_set_value, but saves the
00285    trouble of creating a data_string for a NUL-terminated string.
00286    Does not update the server - just sets the value on the handle. */
00287 
00288 dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, const char *value,
00289                                          const char *value_name)
00290 {
00291         isc_result_t status;
00292         omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
00293         omapi_data_string_t *name = (omapi_data_string_t *)0;
00294 
00295         status = omapi_data_string_new (&name, strlen (value_name), MDL);
00296         if (status != ISC_R_SUCCESS)
00297                 return status;
00298         memcpy (name -> value, value_name, strlen (value_name));
00299 
00300         status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value);
00301         if (status != ISC_R_SUCCESS) {
00302                 omapi_data_string_dereference (&name, MDL);
00303                 return status;
00304         }
00305 
00306         status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
00307         omapi_data_string_dereference (&name, MDL);
00308         omapi_typed_data_dereference (&tv, MDL);
00309         return status;
00310 }
00311 
00312 /* dhcpctl_set_buffer_value
00313 
00314    Sets a value on an object referred to by a dhcpctl_handle.  like
00315    dhcpctl_set_value, but saves the trouble of creating a data_string
00316    for string for which we have a buffer and length.  Does not update
00317    the server - just sets the value on the handle. */
00318 
00319 dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h,
00320                                        const char *value, unsigned len,
00321                                        const char *value_name)
00322 {
00323         isc_result_t status;
00324         omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
00325         omapi_data_string_t *name = (omapi_data_string_t *)0;
00326         unsigned ll;
00327 
00328         ll = strlen (value_name);
00329         status = omapi_data_string_new (&name, ll, MDL);
00330         if (status != ISC_R_SUCCESS)
00331                 return status;
00332         memcpy (name -> value, value_name, ll);
00333 
00334         status = omapi_typed_data_new (MDL, &tv,
00335                                        omapi_datatype_data, len, value);
00336         if (status != ISC_R_SUCCESS) {
00337                 omapi_data_string_dereference (&name, MDL);
00338                 return status;
00339         }
00340         memcpy (tv -> u.buffer.value, value, len);
00341 
00342         status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
00343         omapi_data_string_dereference (&name, MDL);
00344         omapi_typed_data_dereference (&tv, MDL);
00345         return status;
00346 }
00347 
00348 /* dhcpctl_set_null_value
00349 
00350    Sets a null value on an object referred to by a dhcpctl_handle. */
00351 
00352 dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h,
00353                                        const char *value_name)
00354 {
00355         isc_result_t status;
00356         omapi_data_string_t *name = (omapi_data_string_t *)0;
00357         unsigned ll;
00358 
00359         ll = strlen (value_name);
00360         status = omapi_data_string_new (&name, ll, MDL);
00361         if (status != ISC_R_SUCCESS)
00362                 return status;
00363         memcpy (name -> value, value_name, ll);
00364 
00365         status = omapi_set_value (h, (omapi_object_t *)0, name,
00366                                   (omapi_typed_data_t *)0);
00367         omapi_data_string_dereference (&name, MDL);
00368         return status;
00369 }
00370 
00371 /* dhcpctl_set_boolean_value
00372 
00373    Sets a boolean value on an object - like dhcpctl_set_value,
00374    only more convenient for booleans. */
00375 
00376 dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle h, int value,
00377                                           const char *value_name)
00378 {
00379         isc_result_t status;
00380         omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
00381         omapi_data_string_t *name = (omapi_data_string_t *)0;
00382 
00383         status = omapi_data_string_new (&name, strlen (value_name), MDL);
00384         if (status != ISC_R_SUCCESS)
00385                 return status;
00386         memcpy (name -> value, value_name, strlen (value_name));
00387 
00388         status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
00389         if (status != ISC_R_SUCCESS) {
00390                 omapi_data_string_dereference (&name, MDL);
00391                 return status;
00392         }
00393 
00394         status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
00395         omapi_data_string_dereference (&name, MDL);
00396         omapi_typed_data_dereference (&tv, MDL);
00397         return status;
00398 }
00399 
00400 /* dhcpctl_set_int_value
00401 
00402    Sets a boolean value on an object - like dhcpctl_set_value,
00403    only more convenient for booleans. */
00404 
00405 dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value,
00406                                       const char *value_name)
00407 {
00408         isc_result_t status;
00409         omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
00410         omapi_data_string_t *name = (omapi_data_string_t *)0;
00411 
00412         status = omapi_data_string_new (&name, strlen (value_name), MDL);
00413         if (status != ISC_R_SUCCESS)
00414                 return status;
00415         memcpy (name -> value, value_name, strlen (value_name));
00416 
00417         status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
00418         if (status != ISC_R_SUCCESS) {
00419                 omapi_data_string_dereference (&name, MDL);
00420                 return status;
00421         }
00422 
00423         status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
00424         omapi_data_string_dereference (&name, MDL);
00425         omapi_typed_data_dereference (&tv, MDL);
00426         return status;
00427 }
00428 
00429 /* dhcpctl_object_update
00430 
00431    Queues an update on the object referenced by the handle (there
00432    can't be any other work in progress on the handle).   An
00433    update means local parameters will be sent to the server. */
00434 
00435 dhcpctl_status dhcpctl_object_update (dhcpctl_handle connection,
00436                                       dhcpctl_handle h)
00437 {
00438         isc_result_t status;
00439         omapi_object_t *message = (omapi_object_t *)0;
00440         dhcpctl_remote_object_t *ro;
00441 
00442         if (h -> type != dhcpctl_remote_type)
00443                 return DHCP_R_INVALIDARG;
00444         ro = (dhcpctl_remote_object_t *)h;
00445 
00446         status = omapi_message_new (&message, MDL);
00447         if (status != ISC_R_SUCCESS) {
00448                 omapi_object_dereference (&message, MDL);
00449                 return status;
00450         }
00451         status = omapi_set_int_value (message, (omapi_object_t *)0,
00452                                       "op", OMAPI_OP_UPDATE);
00453         if (status != ISC_R_SUCCESS) {
00454                 omapi_object_dereference (&message, MDL);
00455                 return status;
00456         }
00457 
00458         status = omapi_set_object_value (message, (omapi_object_t *)0,
00459                                          "object", h);
00460         if (status != ISC_R_SUCCESS) {
00461                 omapi_object_dereference (&message, MDL);
00462                 return status;
00463         }
00464 
00465         status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
00466                                       (int)(ro -> remote_handle));
00467         if (status != ISC_R_SUCCESS) {
00468                 omapi_object_dereference (&message, MDL);
00469                 return status;
00470         }
00471 
00472         omapi_message_register (message);
00473         status = omapi_protocol_send_message (connection -> outer,
00474                                               (omapi_object_t *)0,
00475                                               message, (omapi_object_t *)0);
00476         omapi_object_dereference (&message, MDL);
00477         return status;
00478 }
00479 
00480 /* Requests a refresh on the object referenced by the handle (there
00481    can't be any other work in progress on the handle).   A
00482    refresh means local parameters are updated from the server. */
00483 
00484 dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle connection,
00485                                        dhcpctl_handle h)
00486 {
00487         isc_result_t status;
00488         omapi_object_t *message = (omapi_object_t *)0;
00489         dhcpctl_remote_object_t *ro;
00490 
00491         if (h -> type != dhcpctl_remote_type)
00492                 return DHCP_R_INVALIDARG;
00493         ro = (dhcpctl_remote_object_t *)h;
00494 
00495         status = omapi_message_new (&message, MDL);
00496         if (status != ISC_R_SUCCESS) {
00497                 omapi_object_dereference (&message, MDL);
00498                 return status;
00499         }
00500         status = omapi_set_int_value (message, (omapi_object_t *)0,
00501                                       "op", OMAPI_OP_REFRESH);
00502         if (status != ISC_R_SUCCESS) {
00503                 omapi_object_dereference (&message, MDL);
00504                 return status;
00505         }
00506         status = omapi_set_int_value (message, (omapi_object_t *)0,
00507                                       "handle", (int)(ro -> remote_handle));
00508         if (status != ISC_R_SUCCESS) {
00509                 omapi_object_dereference (&message, MDL);
00510                 return status;
00511         }
00512 
00513         omapi_message_register (message);
00514         status = omapi_protocol_send_message (connection -> outer,
00515                                               (omapi_object_t *)0,
00516                                               message, (omapi_object_t *)0);
00517 
00518         /* We don't want to send the contents of the object down the
00519            wire, but we do need to reference it so that we know what
00520            to do with the update. */
00521         status = omapi_set_object_value (message, (omapi_object_t *)0,
00522                                          "object", h);
00523         if (status != ISC_R_SUCCESS) {
00524                 omapi_object_dereference (&message, MDL);
00525                 return status;
00526         }
00527 
00528         omapi_object_dereference (&message, MDL);
00529         return status;
00530 }
00531 
00532 /* Requests the removal of the object referenced by the handle (there
00533    can't be any other work in progress on the handle).   A
00534    removal means that all searchable references to the object on the
00535    server are deleted. */
00536 
00537 dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection,
00538                                       dhcpctl_handle h)
00539 {
00540         isc_result_t status;
00541         omapi_object_t *message = (omapi_object_t *)0;
00542         dhcpctl_remote_object_t *ro;
00543 
00544         if (h -> type != dhcpctl_remote_type)
00545                 return DHCP_R_INVALIDARG;
00546         ro = (dhcpctl_remote_object_t *)h;
00547 
00548         status = omapi_message_new (&message, MDL);
00549         if (status != ISC_R_SUCCESS) {
00550                 omapi_object_dereference (&message, MDL);
00551                 return status;
00552         }
00553         status = omapi_set_int_value (message, (omapi_object_t *)0,
00554                                       "op", OMAPI_OP_DELETE);
00555         if (status != ISC_R_SUCCESS) {
00556                 omapi_object_dereference (&message, MDL);
00557                 return status;
00558         }
00559 
00560         status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
00561                                       (int)(ro -> remote_handle));
00562         if (status != ISC_R_SUCCESS) {
00563                 omapi_object_dereference (&message, MDL);
00564                 return status;
00565         }
00566 
00567         status = omapi_set_object_value (message, (omapi_object_t *)0,
00568                                          "notify-object", h);
00569         if (status != ISC_R_SUCCESS) {
00570                 omapi_object_dereference (&message, MDL);
00571                 return status;
00572         }
00573 
00574         omapi_message_register (message);
00575         status = omapi_protocol_send_message (connection -> outer,
00576                                               (omapi_object_t *)0,
00577                                               message, (omapi_object_t *)0);
00578         omapi_object_dereference (&message, MDL);
00579         return status;
00580 }
00581 
00582 isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *vp,
00583                                               const char *file, int line)
00584 {
00585         return omapi_data_string_dereference (vp, file, line);
00586 }

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1