ISC DHCP  4.3.3
A reference DHCPv4 and DHCPv6 implementation
generic.c
Go to the documentation of this file.
1 /* generic.c
2 
3  Subroutines that support the generic object. */
4 
5 /*
6  * Copyright (c) 2004-2007,2009,2014 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1999-2003 by Internet Software Consortium
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  * Internet Systems Consortium, Inc.
22  * 950 Charter Street
23  * Redwood City, CA 94063
24  * <info@isc.org>
25  * https://www.isc.org/
26  *
27  */
28 
29 #include "dhcpd.h"
30 
31 #include <omapip/omapip_p.h>
32 
33 OMAPI_OBJECT_ALLOC (omapi_generic,
35 
36 isc_result_t omapi_generic_new (omapi_object_t **gen,
37  const char *file, int line)
38 {
39  /* Backwards compatibility. */
40  return omapi_generic_allocate ((omapi_generic_object_t **)gen,
41  file, line);
42 }
43 
45  omapi_object_t *id,
46  omapi_data_string_t *name,
47  omapi_typed_data_t *value)
48 {
50  omapi_value_t *new;
51  omapi_value_t **va;
52  u_int8_t *ca;
53  int vm_new;
54  int i, vfree = -1;
55  isc_result_t status;
56 
57  if (h -> type != omapi_type_generic)
58  return DHCP_R_INVALIDARG;
59  g = (omapi_generic_object_t *)h;
60 
61  /* See if there's already a value with this name attached to
62  the generic object, and if so, replace the current value
63  with the new one. */
64  for (i = 0; i < g -> nvalues; i++) {
65  if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
66  /* There's an inconsistency here: the standard
67  behaviour of a set_values method when
68  passed a matching name and a null value is
69  to delete the value associated with that
70  name (where possible). In the generic
71  object, we remember the name/null pair,
72  because generic objects are generally used
73  to pass messages around, and this is the
74  way that remote entities delete values from
75  local objects. If the get_value method of
76  a generic object is called for a name that
77  maps to a name/null pair, ISC_R_NOTFOUND is
78  returned. */
79  new = (omapi_value_t *)0;
80  status = (omapi_value_new (&new, MDL));
81  if (status != ISC_R_SUCCESS)
82  return status;
83  omapi_data_string_reference (&new -> name, name, MDL);
84  if (value)
85  omapi_typed_data_reference (&new -> value,
86  value, MDL);
87 
88  omapi_value_dereference (&(g -> values [i]), MDL);
89  status = (omapi_value_reference
90  (&(g -> values [i]), new, MDL));
92  g -> changed [i] = 1;
93  return status;
94  }
95  /* Notice a free slot if we pass one. */
96  else if (vfree == -1 && !g -> values [i])
97  vfree = i;
98  }
99 
100  /* If the name isn't already attached to this object, see if an
101  inner object has it. */
102  if (h -> inner && h -> inner -> type -> set_value) {
103  status = ((*(h -> inner -> type -> set_value))
104  (h -> inner, id, name, value));
105  if (status != ISC_R_NOTFOUND)
106  return status;
107  }
108 
109  /* Okay, so it's a value that no inner object knows about, and
110  (implicitly, since the outer object set_value method would
111  have called this object's set_value method) it's an object that
112  no outer object knows about, it's this object's responsibility
113  to remember it - that's what generic objects do. */
114 
115  /* Arrange for there to be space for the pointer to the new
116  name/value pair if necessary: */
117  if (vfree == -1) {
118  vfree = g -> nvalues;
119  if (vfree == g -> va_max) {
120  if (g -> va_max)
121  vm_new = 2 * g -> va_max;
122  else
123  vm_new = 10;
124  va = dmalloc (vm_new * sizeof *va, MDL);
125  if (!va)
126  return ISC_R_NOMEMORY;
127  ca = dmalloc (vm_new * sizeof *ca, MDL);
128  if (!ca) {
129  dfree (va, MDL);
130  return ISC_R_NOMEMORY;
131  }
132  if (g -> va_max) {
133  memcpy (va, g -> values,
134  g -> va_max * sizeof *va);
135  memcpy (ca, g -> changed,
136  g -> va_max * sizeof *ca);
137  }
138  memset (va + g -> va_max, 0,
139  (vm_new - g -> va_max) * sizeof *va);
140  memset (ca + g -> va_max, 0,
141  (vm_new - g -> va_max) * sizeof *ca);
142  if (g -> values)
143  dfree (g -> values, MDL);
144  if (g -> changed)
145  dfree (g -> changed, MDL);
146  g -> values = va;
147  g -> changed = ca;
148  g -> va_max = vm_new;
149  }
150  }
151  status = omapi_value_new (&g -> values [vfree], MDL);
152  if (status != ISC_R_SUCCESS)
153  return status;
154  omapi_data_string_reference (&g -> values [vfree] -> name,
155  name, MDL);
156  if (value)
158  (&g -> values [vfree] -> value, value, MDL);
159  g -> changed [vfree] = 1;
160  if (vfree == g -> nvalues)
161  g -> nvalues++;
162  return ISC_R_SUCCESS;
163 }
164 
166  omapi_object_t *id,
167  omapi_data_string_t *name,
168  omapi_value_t **value)
169 {
170  int i;
172 
173  if (h -> type != omapi_type_generic)
174  return DHCP_R_INVALIDARG;
175  g = (omapi_generic_object_t *)h;
176 
177  /* Look up the specified name in our list of objects. */
178  for (i = 0; i < g -> nvalues; i++) {
179  if (!g -> values[i])
180  continue;
181  if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
182  /* If this is a name/null value pair, this is the
183  same as if there were no value that matched
184  the specified name, so return ISC_R_NOTFOUND. */
185  if (!g -> values [i] -> value)
186  return ISC_R_NOTFOUND;
187  /* Otherwise, return the name/value pair. */
188  return omapi_value_reference (value,
189  g -> values [i], MDL);
190  }
191  }
192 
193  if (h -> inner && h -> inner -> type -> get_value)
194  return (*(h -> inner -> type -> get_value))
195  (h -> inner, id, name, value);
196  return ISC_R_NOTFOUND;
197 }
198 
200  const char *file, int line)
201 {
203  int i;
204 
205  if (h -> type != omapi_type_generic)
206  return ISC_R_UNEXPECTED;
207  g = (omapi_generic_object_t *)h;
208 
209  if (g -> values) {
210  for (i = 0; i < g -> nvalues; i++) {
211  if (g -> values [i])
212  omapi_value_dereference (&g -> values [i],
213  file, line);
214  }
215  dfree (g -> values, file, line);
216  dfree (g -> changed, file, line);
217  g -> values = (omapi_value_t **)0;
218  g -> changed = (u_int8_t *)0;
219  g -> va_max = 0;
220  }
221 
222  return ISC_R_SUCCESS;
223 }
224 
226  const char *name, va_list ap)
227 {
228  if (h -> type != omapi_type_generic)
229  return DHCP_R_INVALIDARG;
230 
231  if (h -> inner && h -> inner -> type -> signal_handler)
232  return (*(h -> inner -> type -> signal_handler)) (h -> inner,
233  name, ap);
234  return ISC_R_NOTFOUND;
235 }
236 
237 /* Write all the published values associated with the object through the
238  specified connection. */
239 
241  omapi_object_t *id,
242  omapi_object_t *g)
243 {
245  int i;
246  isc_result_t status;
247 
248  if (g -> type != omapi_type_generic)
249  return DHCP_R_INVALIDARG;
250  src = (omapi_generic_object_t *)g;
251 
252  for (i = 0; i < src -> nvalues; i++) {
253  if (src -> values [i] && src -> values [i] -> name -> len &&
254  src -> changed [i]) {
256  (c, src -> values [i] -> name -> len));
257  if (status != ISC_R_SUCCESS)
258  return status;
259  status = (omapi_connection_copyin
260  (c, src -> values [i] -> name -> value,
261  src -> values [i] -> name -> len));
262  if (status != ISC_R_SUCCESS)
263  return status;
264 
266  (c, src -> values [i] -> value));
267  if (status != ISC_R_SUCCESS)
268  return status;
269  }
270  }
271 
272  if (g -> inner && g -> inner -> type -> stuff_values)
273  return (*(g -> inner -> type -> stuff_values)) (c, id,
274  g -> inner);
275  return ISC_R_SUCCESS;
276 }
277 
278 /* Clear the changed flags on the object. This has the effect that if
279  generic_stuff is called, any attributes that still have a cleared changed
280  flag aren't sent to the peer. This also deletes any values that are
281  null, presuming that these have now been properly handled. */
282 
284 {
285  int i;
287 
288  if (o -> type != omapi_type_generic)
289  return DHCP_R_INVALIDARG;
290  g = (omapi_generic_object_t *)o;
291 
292  for (i = 0; i < g -> nvalues; i++) {
293  g -> changed [i] = 0;
294  if (g -> values [i] &&
295  !g -> values [i] -> value)
296  omapi_value_dereference (&g -> values [i], MDL);
297  }
298  return ISC_R_SUCCESS;
299 }
const char int line
Definition: dhcpd.h:3676
isc_result_t omapi_value_reference(omapi_value_t **, omapi_value_t *, const char *, int)
Definition: alloc.c:1024
isc_result_t omapi_generic_clear_flags(omapi_object_t *o)
Definition: generic.c:283
void * dmalloc(unsigned, const char *, int)
Definition: alloc.c:56
isc_result_t omapi_connection_copyin(omapi_object_t *, const unsigned char *, unsigned)
Definition: buffer.c:266
#define MDL
Definition: omapip.h:568
#define DHCP_R_INVALIDARG
Definition: result.h:48
int omapi_data_string_cmp(omapi_data_string_t *, omapi_data_string_t *)
Definition: support.c:563
isc_result_t omapi_data_string_reference(omapi_data_string_t **, omapi_data_string_t *, const char *, int)
Definition: alloc.c:953
isc_result_t omapi_value_new(omapi_value_t **, const char *, int)
Definition: alloc.c:1012
isc_result_t omapi_connection_write_typed_data(omapi_object_t *, omapi_typed_data_t *)
Definition: buffer.c:624
isc_result_t omapi_generic_set_value(omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value)
Definition: generic.c:44
isc_result_t omapi_generic_new(omapi_object_t **, const char *, int)
void dfree(void *, const char *, int)
Definition: alloc.c:131
OMAPI_OBJECT_ALLOC(omapi_generic, omapi_generic_object_t, omapi_type_generic)
Definition: generic.c:33
isc_result_t omapi_typed_data_reference(omapi_typed_data_t **, omapi_typed_data_t *, const char *, int)
Definition: alloc.c:866
isc_result_t omapi_value_dereference(omapi_value_t **, const char *, int)
Definition: alloc.c:1046
omapi_object_type_t * omapi_type_generic
Definition: support.c:38
isc_result_t omapi_generic_signal_handler(omapi_object_t *h, const char *name, va_list ap)
Definition: generic.c:225
isc_result_t omapi_connection_put_uint16(omapi_object_t *, u_int32_t)
Definition: buffer.c:613
isc_result_t omapi_generic_destroy(omapi_object_t *h, const char *file, int line)
Definition: generic.c:199
const char * file
Definition: dhcpd.h:3676
isc_result_t omapi_generic_stuff_values(omapi_object_t *c, omapi_object_t *id, omapi_object_t *g)
Definition: generic.c:240
isc_result_t omapi_generic_get_value(omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_value_t **value)
Definition: generic.c:165