omapip/generic.c

Go to the documentation of this file.
00001 /* generic.c
00002 
00003    Subroutines that support the generic object. */
00004 
00005 /*
00006  * Copyright (c) 2004-2007,2009,2014 by Internet Systems Consortium, Inc. ("ISC")
00007  * Copyright (c) 1999-2003 by Internet Software Consortium
00008  *
00009  * Permission to use, copy, modify, and distribute this software for any
00010  * purpose with or without fee is hereby granted, provided that the above
00011  * copyright notice and this permission notice appear in all copies.
00012  *
00013  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00014  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00015  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00016  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00017  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00018  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00019  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00020  *
00021  *   Internet Systems Consortium, Inc.
00022  *   950 Charter Street
00023  *   Redwood City, CA 94063
00024  *   <info@isc.org>
00025  *   https://www.isc.org/
00026  *
00027  */
00028 
00029 #include "dhcpd.h"
00030 
00031 #include <omapip/omapip_p.h>
00032 
00033 OMAPI_OBJECT_ALLOC (omapi_generic,
00034                     omapi_generic_object_t, omapi_type_generic)
00035 
00036 isc_result_t omapi_generic_new (omapi_object_t **gen,
00037                                 const char *file, int line)
00038 {
00039         /* Backwards compatibility. */
00040         return omapi_generic_allocate ((omapi_generic_object_t **)gen,
00041                                        file, line);
00042 }
00043 
00044 isc_result_t omapi_generic_set_value (omapi_object_t *h,
00045                                       omapi_object_t *id,
00046                                       omapi_data_string_t *name,
00047                                       omapi_typed_data_t *value)
00048 {
00049         omapi_generic_object_t *g;
00050         omapi_value_t *new;
00051         omapi_value_t **va;
00052         u_int8_t *ca;
00053         int vm_new;
00054         int i, vfree = -1;
00055         isc_result_t status;
00056 
00057         if (h -> type != omapi_type_generic)
00058                 return DHCP_R_INVALIDARG;
00059         g = (omapi_generic_object_t *)h;
00060 
00061         /* See if there's already a value with this name attached to
00062            the generic object, and if so, replace the current value
00063            with the new one. */
00064         for (i = 0; i < g -> nvalues; i++) {
00065                 if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
00066                         /* There's an inconsistency here: the standard
00067                            behaviour of a set_values method when
00068                            passed a matching name and a null value is
00069                            to delete the value associated with that
00070                            name (where possible).  In the generic
00071                            object, we remember the name/null pair,
00072                            because generic objects are generally used
00073                            to pass messages around, and this is the
00074                            way that remote entities delete values from
00075                            local objects.  If the get_value method of
00076                            a generic object is called for a name that
00077                            maps to a name/null pair, ISC_R_NOTFOUND is
00078                            returned. */
00079                         new = (omapi_value_t *)0;
00080                         status = (omapi_value_new (&new, MDL));
00081                         if (status != ISC_R_SUCCESS)
00082                                 return status;
00083                         omapi_data_string_reference (&new -> name, name, MDL);
00084                         if (value)
00085                                 omapi_typed_data_reference (&new -> value,
00086                                                             value, MDL);
00087 
00088                         omapi_value_dereference (&(g -> values [i]), MDL);
00089                         status = (omapi_value_reference
00090                                   (&(g -> values [i]), new, MDL));
00091                         omapi_value_dereference (&new, MDL);
00092                         g -> changed [i] = 1;
00093                         return status;
00094                 }
00095                 /* Notice a free slot if we pass one. */
00096                 else if (vfree == -1 && !g -> values [i])
00097                         vfree = i;
00098         }                       
00099 
00100         /* If the name isn't already attached to this object, see if an
00101            inner object has it. */
00102         if (h -> inner && h -> inner -> type -> set_value) {
00103                 status = ((*(h -> inner -> type -> set_value))
00104                           (h -> inner, id, name, value));
00105                 if (status != ISC_R_NOTFOUND)
00106                         return status;
00107         }
00108 
00109         /* Okay, so it's a value that no inner object knows about, and
00110            (implicitly, since the outer object set_value method would
00111            have called this object's set_value method) it's an object that
00112            no outer object knows about, it's this object's responsibility
00113            to remember it - that's what generic objects do. */
00114 
00115         /* Arrange for there to be space for the pointer to the new
00116            name/value pair if necessary: */
00117         if (vfree == -1) {
00118                 vfree = g -> nvalues;
00119                 if (vfree == g -> va_max) {
00120                         if (g -> va_max)
00121                                 vm_new = 2 * g -> va_max;
00122                         else
00123                                 vm_new = 10;
00124                         va = dmalloc (vm_new * sizeof *va, MDL);
00125                         if (!va)
00126                                 return ISC_R_NOMEMORY;
00127                         ca = dmalloc (vm_new * sizeof *ca, MDL);
00128                         if (!ca) {
00129                                 dfree (va, MDL);
00130                                 return ISC_R_NOMEMORY;
00131                         }
00132                         if (g -> va_max) {
00133                                 memcpy (va, g -> values,
00134                                         g -> va_max * sizeof *va);
00135                                 memcpy (ca, g -> changed,
00136                                         g -> va_max * sizeof *ca);
00137                         }
00138                         memset (va + g -> va_max, 0,
00139                                 (vm_new - g -> va_max) * sizeof *va);
00140                         memset (ca + g -> va_max, 0,
00141                                 (vm_new - g -> va_max) * sizeof *ca);
00142                         if (g -> values)
00143                                 dfree (g -> values, MDL);
00144                         if (g -> changed)
00145                                 dfree (g -> changed, MDL);
00146                         g -> values = va;
00147                         g -> changed = ca;
00148                         g -> va_max = vm_new;
00149                 }
00150         }
00151         status = omapi_value_new (&g -> values [vfree], MDL);
00152         if (status != ISC_R_SUCCESS)
00153                 return status;
00154         omapi_data_string_reference (&g -> values [vfree] -> name,
00155                                      name, MDL);
00156         if (value)
00157                 omapi_typed_data_reference
00158                         (&g -> values [vfree] -> value, value, MDL);
00159         g -> changed [vfree] = 1;
00160         if (vfree == g -> nvalues)
00161                 g -> nvalues++;
00162         return ISC_R_SUCCESS;
00163 }
00164 
00165 isc_result_t omapi_generic_get_value (omapi_object_t *h,
00166                                       omapi_object_t *id,
00167                                       omapi_data_string_t *name,
00168                                       omapi_value_t **value)
00169 {
00170         int i;
00171         omapi_generic_object_t *g;
00172 
00173         if (h -> type != omapi_type_generic)
00174                 return DHCP_R_INVALIDARG;
00175         g = (omapi_generic_object_t *)h;
00176         
00177         /* Look up the specified name in our list of objects. */
00178         for (i = 0; i < g -> nvalues; i++) {
00179                 if (!g -> values[i])
00180                         continue;
00181                 if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
00182                         /* If this is a name/null value pair, this is the
00183                            same as if there were no value that matched
00184                            the specified name, so return ISC_R_NOTFOUND. */
00185                         if (!g -> values [i] -> value)
00186                                 return ISC_R_NOTFOUND;
00187                         /* Otherwise, return the name/value pair. */
00188                         return omapi_value_reference (value,
00189                                                       g -> values [i], MDL);
00190                 }
00191         }                       
00192 
00193         if (h -> inner && h -> inner -> type -> get_value)
00194                 return (*(h -> inner -> type -> get_value))
00195                         (h -> inner, id, name, value);
00196         return ISC_R_NOTFOUND;
00197 }
00198 
00199 isc_result_t omapi_generic_destroy (omapi_object_t *h,
00200                                     const char *file, int line)
00201 {
00202         omapi_generic_object_t *g;
00203         int i;
00204 
00205         if (h -> type != omapi_type_generic)
00206                 return ISC_R_UNEXPECTED;
00207         g = (omapi_generic_object_t *)h;
00208         
00209         if (g -> values) {
00210                 for (i = 0; i < g -> nvalues; i++) {
00211                         if (g -> values [i])
00212                                 omapi_value_dereference (&g -> values [i],
00213                                                          file, line);
00214                 }
00215                 dfree (g -> values, file, line);
00216                 dfree (g -> changed, file, line);
00217                 g -> values = (omapi_value_t **)0;
00218                 g -> changed = (u_int8_t *)0;
00219                 g -> va_max = 0;
00220         }
00221 
00222         return ISC_R_SUCCESS;
00223 }
00224 
00225 isc_result_t omapi_generic_signal_handler (omapi_object_t *h,
00226                                            const char *name, va_list ap)
00227 {
00228         if (h -> type != omapi_type_generic)
00229                 return DHCP_R_INVALIDARG;
00230         
00231         if (h -> inner && h -> inner -> type -> signal_handler)
00232                 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
00233                                                                   name, ap);
00234         return ISC_R_NOTFOUND;
00235 }
00236 
00237 /* Write all the published values associated with the object through the
00238    specified connection. */
00239 
00240 isc_result_t omapi_generic_stuff_values (omapi_object_t *c,
00241                                          omapi_object_t *id,
00242                                          omapi_object_t *g)
00243 {
00244         omapi_generic_object_t *src;
00245         int i;
00246         isc_result_t status;
00247 
00248         if (g -> type != omapi_type_generic)
00249                 return DHCP_R_INVALIDARG;
00250         src = (omapi_generic_object_t *)g;
00251         
00252         for (i = 0; i < src -> nvalues; i++) {
00253                 if (src -> values [i] && src -> values [i] -> name -> len &&
00254                     src -> changed [i]) {
00255                         status = (omapi_connection_put_uint16
00256                                   (c, src -> values [i] -> name -> len));
00257                         if (status != ISC_R_SUCCESS)
00258                                 return status;
00259                         status = (omapi_connection_copyin
00260                                   (c, src -> values [i] -> name -> value,
00261                                    src -> values [i] -> name -> len));
00262                         if (status != ISC_R_SUCCESS)
00263                                 return status;
00264 
00265                         status = (omapi_connection_write_typed_data
00266                                   (c, src -> values [i] -> value));
00267                         if (status != ISC_R_SUCCESS)
00268                                 return status;
00269                 }
00270         }                       
00271 
00272         if (g -> inner && g -> inner -> type -> stuff_values)
00273                 return (*(g -> inner -> type -> stuff_values)) (c, id,
00274                                                                 g -> inner);
00275         return ISC_R_SUCCESS;
00276 }
00277 
00278 /* Clear the changed flags on the object.   This has the effect that if
00279    generic_stuff is called, any attributes that still have a cleared changed
00280    flag aren't sent to the peer.   This also deletes any values that are
00281    null, presuming that these have now been properly handled. */
00282 
00283 isc_result_t omapi_generic_clear_flags (omapi_object_t *o)
00284 {
00285         int i;
00286         omapi_generic_object_t *g;
00287 
00288         if (o -> type != omapi_type_generic)
00289                 return DHCP_R_INVALIDARG;
00290         g = (omapi_generic_object_t *)o;
00291 
00292         for (i = 0; i < g -> nvalues; i++) {
00293                 g -> changed [i] = 0;
00294                 if (g -> values [i] &&
00295                     !g -> values [i] -> value)
00296                         omapi_value_dereference (&g -> values [i], MDL);
00297         }
00298         return ISC_R_SUCCESS;
00299 }

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1