ISC DHCP  4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
dhcpctl.c
Go to the documentation of this file.
1 /* dhcpctl.c
2 
3  Subroutines providing general support for objects. */
4 
5 /*
6  * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1999-2003 by Internet Software Consortium
8  *
9  * This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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 #include <omapip/omapip_p.h>
31 #include "dhcpctl.h"
32 
35 
36 /* dhcpctl_initialize ()
37 
38  Must be called before any other dhcpctl function. */
39 
41 {
42  isc_result_t status;
43 
44  /* Set up the isc and dns library managers */
46  NULL, NULL);
47  if (status != ISC_R_SUCCESS)
48  return status;
49 
50  status = omapi_init();
51  if (status != ISC_R_SUCCESS)
52  return status;
53 
55  "dhcpctl-callback",
61  0, 0, 0, 0, 0, 0,
62  sizeof
64  RC_MISC);
65  if (status != ISC_R_SUCCESS)
66  return status;
67 
69  "dhcpctl-remote",
75  0, 0, 0, 0, 0, 0,
76  sizeof (dhcpctl_remote_object_t),
77  0, RC_MISC);
78  if (status != ISC_R_SUCCESS)
79  return status;
80 
81  return ISC_R_SUCCESS;
82 }
83 
84 /* dhcpctl_connect
85 
86  synchronous
87  returns nonzero status code if it didn't connect, zero otherwise
88  stores connection handle through connection, which can be used
89  for subsequent access to the specified server.
90  server_name is the name of the server, and port is the TCP
91  port on which it is listening.
92  authinfo is the handle to an object containing authentication
93  information. */
94 
96  const char *server_name, int port,
97  dhcpctl_handle authinfo)
98 {
99  isc_result_t status;
100 
101  status = omapi_generic_new (connection, MDL);
102  if (status != ISC_R_SUCCESS) {
103  return status;
104  }
105 
106  status = omapi_protocol_connect (*connection, server_name,
107  (unsigned)port, authinfo);
108  if (status == ISC_R_SUCCESS)
109  return status;
110  if (status != DHCP_R_INCOMPLETE) {
111  omapi_object_dereference (connection, MDL);
112  return status;
113  }
114 
115  status = omapi_wait_for_completion (*connection, 0);
116  if (status != ISC_R_SUCCESS) {
117  omapi_object_dereference (connection, MDL);
118  return status;
119  }
120 
121  return status;
122 }
123 
124 /* dhcpctl_wait_for_completion
125 
126  synchronous
127  returns zero if the callback completes, a nonzero status if
128  there was some problem relating to the wait operation. The
129  status of the queued request will be stored through s, and
130  will also be either zero for success or nonzero for some kind
131  of failure. Never returns until completion or until the
132  connection to the server is lost. This performs the same
133  function as dhcpctl_set_callback and the subsequent callback,
134  for programs that want to do inline execution instead of using
135  callbacks. */
136 
138  dhcpctl_status *s)
139 {
140  isc_result_t status;
141  status = omapi_wait_for_completion (h, 0);
142  if (status != ISC_R_SUCCESS)
143  return status;
144  if (h -> type == dhcpctl_remote_type)
145  *s = ((dhcpctl_remote_object_t *)h) -> waitstatus;
146  return ISC_R_SUCCESS;
147 }
148 
149 /* dhcpctl_get_value
150 
151  synchronous
152  returns zero if the call succeeded, a nonzero status code if
153  it didn't.
154  result is the address of an empty data string (initialized
155  with bzero or cleared with data_string_forget). On
156  successful completion, the addressed data string will contain
157  the value that was fetched.
158  dhcpctl_handle refers to some dhcpctl item
159  value_name refers to some value related to that item - e.g.,
160  for a handle associated with a completed host lookup, value
161  could be one of "hardware-address", "dhcp-client-identifier",
162  "known" or "client-hostname". */
163 
165  dhcpctl_handle h, const char *value_name)
166 {
167  isc_result_t status;
168  omapi_value_t *tv = (omapi_value_t *)0;
169  unsigned len;
170  int ip;
171 
172  status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv);
173  if (status != ISC_R_SUCCESS)
174  return status;
175 
176  switch (tv -> value -> type) {
177  case omapi_datatype_int:
178  len = sizeof (int);
179  break;
180 
182  case omapi_datatype_data:
183  len = tv -> value -> u.buffer.len;
184  break;
185 
187  len = sizeof (omapi_handle_t);
188  break;
189 
190  default:
192  return ISC_R_UNEXPECTED;
193  }
194 
195  status = omapi_data_string_new (result, len, MDL);
196  if (status != ISC_R_SUCCESS) {
198  return status;
199  }
200 
201  switch (tv -> value -> type) {
202  case omapi_datatype_int:
203  ip = htonl (tv -> value -> u.integer);
204  memcpy ((*result) -> value, &ip, sizeof ip);
205  break;
206 
208  case omapi_datatype_data:
209  memcpy ((*result) -> value,
210  tv -> value -> u.buffer.value,
211  tv -> value -> u.buffer.len);
212  break;
213 
215  ip = htonl (tv -> value -> u.object -> handle);
216  memcpy ((*result) -> value, &ip, sizeof ip);
217  break;
218  }
219 
221  return ISC_R_SUCCESS;
222 }
223 
224 /* dhcpctl_get_boolean
225 
226  like dhcpctl_get_value, but more convenient for boolean
227  values, since no data_string needs to be dealt with. */
228 
230  dhcpctl_handle h, const char *value_name)
231 {
232  isc_result_t status;
234  int rv;
235 
236  status = dhcpctl_get_value (&data, h, value_name);
237  if (status != ISC_R_SUCCESS)
238  return status;
239  if (data -> len != sizeof rv) {
241  return ISC_R_UNEXPECTED;
242  }
243  memcpy (&rv, data -> value, sizeof rv);
244  *result = ntohl (rv);
246  return ISC_R_SUCCESS;
247 }
248 
249 /* dhcpctl_set_value
250 
251  Sets a value on an object referred to by a dhcpctl_handle.
252  The opposite of dhcpctl_get_value. Does not update the
253  server - just sets the value on the handle. */
254 
256  const char *value_name)
257 {
258  isc_result_t status;
261 
262  status = omapi_data_string_new (&name, strlen (value_name), MDL);
263  if (status != ISC_R_SUCCESS)
264  return status;
265  memcpy (name -> value, value_name, strlen (value_name));
266 
268  value -> len);
269  if (status != ISC_R_SUCCESS) {
271  return status;
272  }
273  memcpy (tv -> u.buffer.value, value -> value, value -> len);
274 
275  status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
278  return status;
279 }
280 
281 /* dhcpctl_set_string_value
282 
283  Sets a NUL-terminated ASCII value on an object referred to by
284  a dhcpctl_handle. like dhcpctl_set_value, but saves the
285  trouble of creating a data_string for a NUL-terminated string.
286  Does not update the server - just sets the value on the handle. */
287 
289  const char *value_name)
290 {
291  isc_result_t status;
294 
295  status = omapi_data_string_new (&name, strlen (value_name), MDL);
296  if (status != ISC_R_SUCCESS)
297  return status;
298  memcpy (name -> value, value_name, strlen (value_name));
299 
301  if (status != ISC_R_SUCCESS) {
303  return status;
304  }
305 
306  status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
309  return status;
310 }
311 
312 /* dhcpctl_set_buffer_value
313 
314  Sets a value on an object referred to by a dhcpctl_handle. like
315  dhcpctl_set_value, but saves the trouble of creating a data_string
316  for string for which we have a buffer and length. Does not update
317  the server - just sets the value on the handle. */
318 
320  const char *value, unsigned len,
321  const char *value_name)
322 {
323  isc_result_t status;
326  unsigned ll;
327 
328  ll = strlen (value_name);
329  status = omapi_data_string_new (&name, ll, MDL);
330  if (status != ISC_R_SUCCESS)
331  return status;
332  memcpy (name -> value, value_name, ll);
333 
334  status = omapi_typed_data_new (MDL, &tv,
335  omapi_datatype_data, len, value);
336  if (status != ISC_R_SUCCESS) {
338  return status;
339  }
340  memcpy (tv -> u.buffer.value, value, len);
341 
342  status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
345  return status;
346 }
347 
348 /* dhcpctl_set_null_value
349 
350  Sets a null value on an object referred to by a dhcpctl_handle. */
351 
353  const char *value_name)
354 {
355  isc_result_t status;
357  unsigned ll;
358 
359  ll = strlen (value_name);
360  status = omapi_data_string_new (&name, ll, MDL);
361  if (status != ISC_R_SUCCESS)
362  return status;
363  memcpy (name -> value, value_name, ll);
364 
365  status = omapi_set_value (h, (omapi_object_t *)0, name,
366  (omapi_typed_data_t *)0);
368  return status;
369 }
370 
371 /* dhcpctl_set_boolean_value
372 
373  Sets a boolean value on an object - like dhcpctl_set_value,
374  only more convenient for booleans. */
375 
377  const char *value_name)
378 {
379  isc_result_t status;
382 
383  status = omapi_data_string_new (&name, strlen (value_name), MDL);
384  if (status != ISC_R_SUCCESS)
385  return status;
386  memcpy (name -> value, value_name, strlen (value_name));
387 
389  if (status != ISC_R_SUCCESS) {
391  return status;
392  }
393 
394  status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
397  return status;
398 }
399 
400 /* dhcpctl_set_int_value
401 
402  Sets a boolean value on an object - like dhcpctl_set_value,
403  only more convenient for booleans. */
404 
406  const char *value_name)
407 {
408  isc_result_t status;
411 
412  status = omapi_data_string_new (&name, strlen (value_name), MDL);
413  if (status != ISC_R_SUCCESS)
414  return status;
415  memcpy (name -> value, value_name, strlen (value_name));
416 
418  if (status != ISC_R_SUCCESS) {
420  return status;
421  }
422 
423  status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
426  return status;
427 }
428 
429 /* dhcpctl_object_update
430 
431  Queues an update on the object referenced by the handle (there
432  can't be any other work in progress on the handle). An
433  update means local parameters will be sent to the server. */
434 
436  dhcpctl_handle h)
437 {
438  isc_result_t status;
439  omapi_object_t *message = (omapi_object_t *)0;
441 
442  if (h -> type != dhcpctl_remote_type)
443  return DHCP_R_INVALIDARG;
444  ro = (dhcpctl_remote_object_t *)h;
445 
446  status = omapi_message_new (&message, MDL);
447  if (status != ISC_R_SUCCESS) {
448  omapi_object_dereference (&message, MDL);
449  return status;
450  }
451  status = omapi_set_int_value (message, (omapi_object_t *)0,
452  "op", OMAPI_OP_UPDATE);
453  if (status != ISC_R_SUCCESS) {
454  omapi_object_dereference (&message, MDL);
455  return status;
456  }
457 
458  status = omapi_set_object_value (message, (omapi_object_t *)0,
459  "object", h);
460  if (status != ISC_R_SUCCESS) {
461  omapi_object_dereference (&message, MDL);
462  return status;
463  }
464 
465  status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
466  (int)(ro -> remote_handle));
467  if (status != ISC_R_SUCCESS) {
468  omapi_object_dereference (&message, MDL);
469  return status;
470  }
471 
472  omapi_message_register (message);
473  status = omapi_protocol_send_message (connection -> outer,
474  (omapi_object_t *)0,
475  message, (omapi_object_t *)0);
476  omapi_object_dereference (&message, MDL);
477  return status;
478 }
479 
480 /* Requests a refresh on the object referenced by the handle (there
481  can't be any other work in progress on the handle). A
482  refresh means local parameters are updated from the server. */
483 
485  dhcpctl_handle h)
486 {
487  isc_result_t status;
488  omapi_object_t *message = (omapi_object_t *)0;
490 
491  if (h -> type != dhcpctl_remote_type)
492  return DHCP_R_INVALIDARG;
493  ro = (dhcpctl_remote_object_t *)h;
494 
495  status = omapi_message_new (&message, MDL);
496  if (status != ISC_R_SUCCESS) {
497  omapi_object_dereference (&message, MDL);
498  return status;
499  }
500  status = omapi_set_int_value (message, (omapi_object_t *)0,
501  "op", OMAPI_OP_REFRESH);
502  if (status != ISC_R_SUCCESS) {
503  omapi_object_dereference (&message, MDL);
504  return status;
505  }
506  status = omapi_set_int_value (message, (omapi_object_t *)0,
507  "handle", (int)(ro -> remote_handle));
508  if (status != ISC_R_SUCCESS) {
509  omapi_object_dereference (&message, MDL);
510  return status;
511  }
512 
513  omapi_message_register (message);
514  status = omapi_protocol_send_message (connection -> outer,
515  (omapi_object_t *)0,
516  message, (omapi_object_t *)0);
517 
518  /* We don't want to send the contents of the object down the
519  wire, but we do need to reference it so that we know what
520  to do with the update. */
521  status = omapi_set_object_value (message, (omapi_object_t *)0,
522  "object", h);
523  if (status != ISC_R_SUCCESS) {
524  omapi_object_dereference (&message, MDL);
525  return status;
526  }
527 
528  omapi_object_dereference (&message, MDL);
529  return status;
530 }
531 
532 /* Requests the removal of the object referenced by the handle (there
533  can't be any other work in progress on the handle). A
534  removal means that all searchable references to the object on the
535  server are deleted. */
536 
538  dhcpctl_handle h)
539 {
540  isc_result_t status;
541  omapi_object_t *message = (omapi_object_t *)0;
543 
544  if (h -> type != dhcpctl_remote_type)
545  return DHCP_R_INVALIDARG;
546  ro = (dhcpctl_remote_object_t *)h;
547 
548  status = omapi_message_new (&message, MDL);
549  if (status != ISC_R_SUCCESS) {
550  omapi_object_dereference (&message, MDL);
551  return status;
552  }
553  status = omapi_set_int_value (message, (omapi_object_t *)0,
554  "op", OMAPI_OP_DELETE);
555  if (status != ISC_R_SUCCESS) {
556  omapi_object_dereference (&message, MDL);
557  return status;
558  }
559 
560  status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
561  (int)(ro -> remote_handle));
562  if (status != ISC_R_SUCCESS) {
563  omapi_object_dereference (&message, MDL);
564  return status;
565  }
566 
567  status = omapi_set_object_value (message, (omapi_object_t *)0,
568  "notify-object", h);
569  if (status != ISC_R_SUCCESS) {
570  omapi_object_dereference (&message, MDL);
571  return status;
572  }
573 
574  omapi_message_register (message);
575  status = omapi_protocol_send_message (connection -> outer,
576  (omapi_object_t *)0,
577  message, (omapi_object_t *)0);
578  omapi_object_dereference (&message, MDL);
579  return status;
580 }
581 
583  const char *file, int line)
584 {
586 }
isc_result_t dhcpctl_callback_stuff_values(omapi_object_t *c, omapi_object_t *id, omapi_object_t *p)
Definition: callback.c:150
isc_result_t omapi_typed_data_new(const char *, int, omapi_typed_data_t **, omapi_datatype_t,...)
Definition: alloc.c:803
const char int line
Definition: dhcpd.h:3793
dhcpctl_status dhcpctl_get_value(dhcpctl_data_string *result, dhcpctl_handle h, const char *value_name)
Definition: dhcpctl.c:164
Definition: data.h:205
isc_result_t omapi_message_new(omapi_object_t **, const char *, int)
#define OMAPI_OP_UPDATE
Definition: omapip_p.h:90
isc_result_t omapi_data_string_dereference(omapi_data_string_t **, const char *, int)
Definition: alloc.c:988
dhcpctl_status dhcpctl_get_boolean(int *result, dhcpctl_handle h, const char *value_name)
Definition: dhcpctl.c:229
isc_result_t omapi_message_register(omapi_object_t *)
Definition: message.c:267
dhcpctl_status dhcpctl_set_null_value(dhcpctl_handle h, const char *value_name)
Definition: dhcpctl.c:352
isc_result_t dhcpctl_remote_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
Definition: remote.c:251
dhcpctl_status dhcpctl_connect(dhcpctl_handle *connection, const char *server_name, int port, dhcpctl_handle authinfo)
Definition: dhcpctl.c:95
#define OMAPI_OP_REFRESH
Definition: omapip_p.h:89
#define MDL
Definition: omapip.h:567
isc_result_t dhcpctl_callback_destroy(omapi_object_t *h, const char *file, int line)
Definition: callback.c:134
#define DHCP_R_INVALIDARG
Definition: result.h:49
isc_result_t omapi_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
Definition: support.c:303
#define DHCP_CONTEXT_PRE_DB
Definition: isclib.h:134
isc_result_t dhcpctl_remote_destroy(omapi_object_t *, const char *, int)
Definition: remote.c:324
isc_result_t omapi_set_object_value(omapi_object_t *, omapi_object_t *, const char *, omapi_object_t *)
Definition: support.c:419
isc_result_t dhcpctl_data_string_dereference(dhcpctl_data_string *vp, const char *file, int line)
Definition: dhcpctl.c:582
Definition: data.h:289
dhcpctl_status dhcpctl_set_boolean_value(dhcpctl_handle h, int value, const char *value_name)
Definition: dhcpctl.c:376
isc_result_t dhcpctl_callback_get_value(omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_value_t **value)
Definition: callback.c:89
dhcpctl_status dhcpctl_initialize()
Definition: dhcpctl.c:40
#define DHCP_CONTEXT_POST_DB
Definition: isclib.h:135
struct omapi_typed_data_t::@3::@4 buffer
dhcpctl_status dhcpctl_wait_for_completion(dhcpctl_handle h, dhcpctl_status *s)
Definition: dhcpctl.c:137
isc_result_t dhcp_context_create(int flags, struct in_addr *local4, struct in6_addr *local6)
Definition: isclib.c:167
isc_result_t omapi_get_value_str(omapi_object_t *, omapi_object_t *, const char *, omapi_value_t **)
Definition: support.c:482
dhcpctl_status dhcpctl_set_value(dhcpctl_handle h, dhcpctl_data_string value, const char *value_name)
Definition: dhcpctl.c:255
dhcpctl_status dhcpctl_set_data_value(dhcpctl_handle h, const char *value, unsigned len, const char *value_name)
Definition: dhcpctl.c:319
isc_result_t dhcpctl_status
Definition: dhcpctl.h:34
isc_result_t omapi_object_dereference(omapi_object_t **, const char *, int)
Definition: alloc.c:593
isc_result_t omapi_generic_new(omapi_object_t **, const char *, int)
dhcpctl_status dhcpctl_set_int_value(dhcpctl_handle h, int value, const char *value_name)
Definition: dhcpctl.c:405
Definition: ip.h:47
isc_result_t dhcpctl_callback_signal_handler(omapi_object_t *o, const char *name, va_list ap)
Definition: callback.c:103
isc_result_t omapi_protocol_send_message(omapi_object_t *, omapi_object_t *, omapi_object_t *, omapi_object_t *)
Definition: protocol.c:148
dhcpctl_status dhcpctl_object_remove(dhcpctl_handle connection, dhcpctl_handle h)
Definition: dhcpctl.c:537
omapi_object_type_t * dhcpctl_remote_type
Definition: dhcpctl.c:34
isc_result_t omapi_protocol_connect(omapi_object_t *, const char *, unsigned, omapi_object_t *)
#define ISC_R_SUCCESS
unsigned int omapi_handle_t
Definition: omapip.h:36
isc_result_t dhcpctl_remote_signal_handler(omapi_object_t *, const char *, va_list)
Definition: remote.c:291
isc_result_t omapi_value_dereference(omapi_value_t **, const char *, int)
Definition: alloc.c:1060
isc_result_t omapi_object_type_register(omapi_object_type_t **, const char *, isc_result_t(*)(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *), isc_result_t(*)(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **), isc_result_t(*)(omapi_object_t *, const char *, int), isc_result_t(*)(omapi_object_t *, const char *, va_list), isc_result_t(*)(omapi_object_t *, omapi_object_t *, omapi_object_t *), isc_result_t(*)(omapi_object_t **, omapi_object_t *, omapi_object_t *), isc_result_t(*)(omapi_object_t **, omapi_object_t *), isc_result_t(*)(omapi_object_t *, omapi_object_t *), isc_result_t(*)(omapi_object_t *, const char *, int), isc_result_t(*)(omapi_object_t **, const char *, int), isc_result_t(*)(size_t), size_t, isc_result_t(*)(omapi_object_t *, const char *, int), int)
Definition: support.c:193
isc_result_t omapi_wait_for_completion(omapi_object_t *, struct timeval *)
Definition: dispatch.c:420
const char int
Definition: omapip.h:442
dhcpctl_status dhcpctl_object_refresh(dhcpctl_handle connection, dhcpctl_handle h)
Definition: dhcpctl.c:484
isc_result_t omapi_data_string_new(omapi_data_string_t **, unsigned, const char *, int)
Definition: alloc.c:950
omapi_object_type_t * dhcpctl_callback_type
Definition: dhcpctl.c:33
isc_result_t dhcpctl_remote_stuff_values(omapi_object_t *, omapi_object_t *, omapi_object_t *)
Definition: remote.c:343
isc_result_t omapi_set_int_value(omapi_object_t *, omapi_object_t *, const char *, int)
Definition: support.c:395
isc_result_t dhcpctl_callback_set_value(omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value)
Definition: callback.c:75
dhcpctl_status dhcpctl_set_string_value(dhcpctl_handle h, const char *value, const char *value_name)
Definition: dhcpctl.c:288
#define DHCP_R_INCOMPLETE
Definition: result.h:58
const char * file
Definition: dhcpd.h:3793
isc_result_t dhcpctl_remote_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
Definition: remote.c:277
dhcpctl_status dhcpctl_object_update(dhcpctl_handle connection, dhcpctl_handle h)
Definition: dhcpctl.c:435
omapi_data_string_t * dhcpctl_data_string
Definition: dhcpctl.h:36
#define RC_MISC
Definition: alloc.h:56
isc_result_t omapi_typed_data_dereference(omapi_typed_data_t **, const char *, int)
Definition: alloc.c:901
#define OMAPI_OP_DELETE
Definition: omapip_p.h:93
isc_result_t omapi_init(void)
Definition: support.c:61