ISC DHCP  4.3.6
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-2017 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 (!g -> values[i])
66  continue;
67 
68  if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
69  /* There's an inconsistency here: the standard
70  behaviour of a set_values method when
71  passed a matching name and a null value is
72  to delete the value associated with that
73  name (where possible). In the generic
74  object, we remember the name/null pair,
75  because generic objects are generally used
76  to pass messages around, and this is the
77  way that remote entities delete values from
78  local objects. If the get_value method of
79  a generic object is called for a name that
80  maps to a name/null pair, ISC_R_NOTFOUND is
81  returned. */
82  new = (omapi_value_t *)0;
83  status = (omapi_value_new (&new, MDL));
84  if (status != ISC_R_SUCCESS)
85  return status;
86  omapi_data_string_reference (&new -> name, name, MDL);
87  if (value)
88  omapi_typed_data_reference (&new -> value,
89  value, MDL);
90 
91  omapi_value_dereference (&(g -> values [i]), MDL);
92  status = (omapi_value_reference
93  (&(g -> values [i]), new, MDL));
95  g -> changed [i] = 1;
96  return status;
97  }
98  /* Notice a free slot if we pass one. */
99  else if (vfree == -1 && !g -> values [i])
100  vfree = i;
101  }
102 
103  /* If the name isn't already attached to this object, see if an
104  inner object has it. */
105  if (h -> inner && h -> inner -> type -> set_value) {
106  status = ((*(h -> inner -> type -> set_value))
107  (h -> inner, id, name, value));
108  if (status != ISC_R_NOTFOUND)
109  return status;
110  }
111 
112  /* Okay, so it's a value that no inner object knows about, and
113  (implicitly, since the outer object set_value method would
114  have called this object's set_value method) it's an object that
115  no outer object knows about, it's this object's responsibility
116  to remember it - that's what generic objects do. */
117 
118  /* Arrange for there to be space for the pointer to the new
119  name/value pair if necessary: */
120  if (vfree == -1) {
121  vfree = g -> nvalues;
122  if (vfree == g -> va_max) {
123  if (g -> va_max)
124  vm_new = 2 * g -> va_max;
125  else
126  vm_new = 10;
127  va = dmalloc (vm_new * sizeof *va, MDL);
128  if (!va)
129  return ISC_R_NOMEMORY;
130  ca = dmalloc (vm_new * sizeof *ca, MDL);
131  if (!ca) {
132  dfree (va, MDL);
133  return ISC_R_NOMEMORY;
134  }
135  if (g -> va_max) {
136  memcpy (va, g -> values,
137  g -> va_max * sizeof *va);
138  memcpy (ca, g -> changed,
139  g -> va_max * sizeof *ca);
140  }
141  memset (va + g -> va_max, 0,
142  (vm_new - g -> va_max) * sizeof *va);
143  memset (ca + g -> va_max, 0,
144  (vm_new - g -> va_max) * sizeof *ca);
145  if (g -> values)
146  dfree (g -> values, MDL);
147  if (g -> changed)
148  dfree (g -> changed, MDL);
149  g -> values = va;
150  g -> changed = ca;
151  g -> va_max = vm_new;
152  }
153  }
154  status = omapi_value_new (&g -> values [vfree], MDL);
155  if (status != ISC_R_SUCCESS)
156  return status;
157  omapi_data_string_reference (&g -> values [vfree] -> name,
158  name, MDL);
159  if (value)
161  (&g -> values [vfree] -> value, value, MDL);
162  g -> changed [vfree] = 1;
163  if (vfree == g -> nvalues)
164  g -> nvalues++;
165  return ISC_R_SUCCESS;
166 }
167 
169  omapi_object_t *id,
170  omapi_data_string_t *name,
171  omapi_value_t **value)
172 {
173  int i;
175 
176  if (h -> type != omapi_type_generic)
177  return DHCP_R_INVALIDARG;
178  g = (omapi_generic_object_t *)h;
179 
180  /* Look up the specified name in our list of objects. */
181  for (i = 0; i < g -> nvalues; i++) {
182  if (!g -> values[i])
183  continue;
184  if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
185  /* If this is a name/null value pair, this is the
186  same as if there were no value that matched
187  the specified name, so return ISC_R_NOTFOUND. */
188  if (!g -> values [i] -> value)
189  return ISC_R_NOTFOUND;
190  /* Otherwise, return the name/value pair. */
191  return omapi_value_reference (value,
192  g -> values [i], MDL);
193  }
194  }
195 
196  if (h -> inner && h -> inner -> type -> get_value)
197  return (*(h -> inner -> type -> get_value))
198  (h -> inner, id, name, value);
199  return ISC_R_NOTFOUND;
200 }
201 
203  const char *file, int line)
204 {
206  int i;
207 
208  if (h -> type != omapi_type_generic)
209  return ISC_R_UNEXPECTED;
210  g = (omapi_generic_object_t *)h;
211 
212  if (g -> values) {
213  for (i = 0; i < g -> nvalues; i++) {
214  if (g -> values [i])
215  omapi_value_dereference (&g -> values [i],
216  file, line);
217  }
218  dfree (g -> values, file, line);
219  dfree (g -> changed, file, line);
220  g -> values = (omapi_value_t **)0;
221  g -> changed = (u_int8_t *)0;
222  g -> va_max = 0;
223  }
224 
225  return ISC_R_SUCCESS;
226 }
227 
229  const char *name, va_list ap)
230 {
231  if (h -> type != omapi_type_generic)
232  return DHCP_R_INVALIDARG;
233 
234  if (h -> inner && h -> inner -> type -> signal_handler)
235  return (*(h -> inner -> type -> signal_handler)) (h -> inner,
236  name, ap);
237  return ISC_R_NOTFOUND;
238 }
239 
240 /* Write all the published values associated with the object through the
241  specified connection. */
242 
244  omapi_object_t *id,
245  omapi_object_t *g)
246 {
248  int i;
249  isc_result_t status;
250 
251  if (g -> type != omapi_type_generic)
252  return DHCP_R_INVALIDARG;
253  src = (omapi_generic_object_t *)g;
254 
255  for (i = 0; i < src -> nvalues; i++) {
256  if (src -> values [i] && src -> values [i] -> name -> len &&
257  src -> changed [i]) {
259  (c, src -> values [i] -> name -> len));
260  if (status != ISC_R_SUCCESS)
261  return status;
262  status = (omapi_connection_copyin
263  (c, src -> values [i] -> name -> value,
264  src -> values [i] -> name -> len));
265  if (status != ISC_R_SUCCESS)
266  return status;
267 
269  (c, src -> values [i] -> value));
270  if (status != ISC_R_SUCCESS)
271  return status;
272  }
273  }
274 
275  if (g -> inner && g -> inner -> type -> stuff_values)
276  return (*(g -> inner -> type -> stuff_values)) (c, id,
277  g -> inner);
278  return ISC_R_SUCCESS;
279 }
280 
281 /* Clear the changed flags on the object. This has the effect that if
282  generic_stuff is called, any attributes that still have a cleared changed
283  flag aren't sent to the peer. This also deletes any values that are
284  null, presuming that these have now been properly handled. */
285 
287 {
288  int i;
290 
291  if (o -> type != omapi_type_generic)
292  return DHCP_R_INVALIDARG;
293  g = (omapi_generic_object_t *)o;
294 
295  for (i = 0; i < g -> nvalues; i++) {
296  g -> changed [i] = 0;
297  if (g -> values [i] &&
298  !g -> values [i] -> value)
299  omapi_value_dereference (&g -> values [i], MDL);
300  }
301  return ISC_R_SUCCESS;
302 }
const char int line
Definition: dhcpd.h:3723
isc_result_t omapi_value_reference(omapi_value_t **, omapi_value_t *, const char *, int)
Definition: alloc.c:1038
isc_result_t omapi_generic_clear_flags(omapi_object_t *o)
Definition: generic.c:286
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:967
isc_result_t omapi_value_new(omapi_value_t **, const char *, int)
Definition: alloc.c:1026
isc_result_t omapi_connection_write_typed_data(omapi_object_t *, omapi_typed_data_t *)
Definition: buffer.c:633
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:145
void * dmalloc(size_t, const char *, int)
Definition: alloc.c:57
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:880
isc_result_t omapi_value_dereference(omapi_value_t **, const char *, int)
Definition: alloc.c:1060
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:228
isc_result_t omapi_connection_put_uint16(omapi_object_t *, u_int32_t)
Definition: buffer.c:622
isc_result_t omapi_generic_destroy(omapi_object_t *h, const char *file, int line)
Definition: generic.c:202
const char * file
Definition: dhcpd.h:3723
isc_result_t omapi_generic_stuff_values(omapi_object_t *c, omapi_object_t *id, omapi_object_t *g)
Definition: generic.c:243
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:168