1 /* $NetBSD: dhcpctl.c,v 1.3 2022/04/03 01:10:58 christos Exp $ */
2
3 /* dhcpctl.c
4
5 Subroutines providing general support for objects. */
6
7 /*
8 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1999-2003 by Internet Software Consortium
10 *
11 * This Source Code Form is subject to the terms of the Mozilla Public
12 * License, v. 2.0. If a copy of the MPL was not distributed with this
13 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Internet Systems Consortium, Inc.
24 * PO Box 360
25 * Newmarket, NH 03857 USA
26 * <info@isc.org>
27 * https://www.isc.org/
28 *
29 */
30
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: dhcpctl.c,v 1.3 2022/04/03 01:10:58 christos Exp $");
33
34 #include "dhcpd.h"
35 #include <omapip/omapip_p.h>
36 #include "dhcpctl.h"
37 #include <sys/time.h>
38
39 /* #define DEBUG_DHCPCTL 1 */
40
41 omapi_object_type_t *dhcpctl_callback_type;
42 omapi_object_type_t *dhcpctl_remote_type;
43
44 /* dhcpctl_initialize ()
45
46 Must be called before any other dhcpctl function. */
47
dhcpctl_initialize()48 dhcpctl_status dhcpctl_initialize ()
49 {
50 isc_result_t status;
51
52 /* Set up the isc and dns library managers */
53 status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
54 NULL, NULL);
55 if (status != ISC_R_SUCCESS)
56 return status;
57
58 status = omapi_init();
59 if (status != ISC_R_SUCCESS)
60 return status;
61
62 status = omapi_object_type_register (&dhcpctl_callback_type,
63 "dhcpctl-callback",
64 dhcpctl_callback_set_value,
65 dhcpctl_callback_get_value,
66 dhcpctl_callback_destroy,
67 dhcpctl_callback_signal_handler,
68 dhcpctl_callback_stuff_values,
69 0, 0, 0, 0, 0, 0,
70 sizeof
71 (dhcpctl_callback_object_t), 0,
72 RC_MISC);
73 if (status != ISC_R_SUCCESS)
74 return status;
75
76 status = omapi_object_type_register (&dhcpctl_remote_type,
77 "dhcpctl-remote",
78 dhcpctl_remote_set_value,
79 dhcpctl_remote_get_value,
80 dhcpctl_remote_destroy,
81 dhcpctl_remote_signal_handler,
82 dhcpctl_remote_stuff_values,
83 0, 0, 0, 0, 0, 0,
84 sizeof (dhcpctl_remote_object_t),
85 0, RC_MISC);
86 if (status != ISC_R_SUCCESS)
87 return status;
88
89 return ISC_R_SUCCESS;
90 }
91
92 /* dhcpctl_connect
93
94 synchronous
95 returns nonzero status code if it didn't connect, zero otherwise
96 stores connection handle through connection, which can be used
97 for subsequent access to the specified server.
98 server_name is the name of the server, and port is the TCP
99 port on which it is listening.
100 authinfo is the handle to an object containing authentication
101 information. */
102
dhcpctl_connect(dhcpctl_handle * connection,const char * server_name,int port,dhcpctl_handle authinfo)103 dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
104 const char *server_name, int port,
105 dhcpctl_handle authinfo)
106 {
107 isc_result_t status;
108 #ifdef DEBUG_DHCPCTL
109 log_debug("dhcpctl_connect(%s:%d)", server_name, port);
110 #endif
111
112 status = omapi_generic_new (connection, MDL);
113 if (status != ISC_R_SUCCESS) {
114 return status;
115 }
116
117 status = omapi_protocol_connect (*connection, server_name,
118 (unsigned)port, authinfo);
119 if (status == ISC_R_SUCCESS) {
120 #ifdef DEBUG_DHCPCTL
121 log_debug("dhcpctl_connect success");
122 #endif
123 return status;
124 }
125
126 if (status != DHCP_R_INCOMPLETE) {
127 omapi_object_dereference (connection, MDL);
128 #ifdef DEBUG_DHCPCTL
129 log_debug("dhcpctl_connect failed:%s",
130 isc_result_totext (status));
131 #endif
132 return status;
133 }
134
135 status = omapi_wait_for_completion (*connection, 0);
136 if (status != ISC_R_SUCCESS) {
137 omapi_object_dereference (connection, MDL);
138 #ifdef DEBUG_DHCPCTL
139 log_debug("dhcpctl_connect, wait failed:%s",
140 isc_result_totext (status));
141 #endif
142 return status;
143 }
144
145 #ifdef DEBUG_DHCPCTL
146 log_debug("dhcpctl_connect success");
147 #endif
148 return status;
149 }
150
151 /* dhcpctl_timed_connect
152
153 synchronous
154 returns nonzero status code if it didn't connect, zero otherwise
155 stores connection handle through connection, which can be used
156 for subsequent access to the specified server.
157 server_name is the name of the server, and port is the TCP
158 port on which it is listening.
159 authinfo is the handle to an object containing authentication
160 information.
161 How long the function waits for the connection to complete is
162 dictated by the value of the parameter, t. If the value is nul,
163 it will wait indefinitely. Otherwise it will wait for the amount
164 of time specified by t (tv_sec:tv_usec). Values of zero for both
165 fields are valid but not recommended. */
dhcpctl_timed_connect(dhcpctl_handle * connection,const char * server_name,int port,dhcpctl_handle authinfo,struct timeval * t)166 dhcpctl_status dhcpctl_timed_connect (dhcpctl_handle *connection,
167 const char *server_name, int port,
168 dhcpctl_handle authinfo,
169 struct timeval *t)
170 {
171 isc_result_t status;
172 #ifdef DEBUG_DHCPCTL
173 log_debug("dhcpctl_timed_connect(%s:%d)", server_name, port);
174 #endif
175 status = omapi_generic_new (connection, MDL);
176 if (status != ISC_R_SUCCESS) {
177 return status;
178 }
179
180 status = omapi_protocol_connect (*connection, server_name,
181 (unsigned)port, authinfo);
182
183 if (status == ISC_R_SUCCESS) {
184 return status;
185 }
186
187 if (status == DHCP_R_INCOMPLETE) {
188 isc_result_t wait_status = ISC_R_SUCCESS;
189
190 /* Wait for it to complete */
191 status = dhcpctl_timed_wait_for_completion(*connection,
192 &wait_status, t);
193 if (status == ISC_R_SUCCESS) {
194 status = wait_status;
195 }
196 }
197
198 if (status != ISC_R_SUCCESS) {
199 omapi_object_dereference (connection, MDL);
200 }
201 return status;
202 }
203
204 /* dhcpctl_wait_for_completion
205
206 synchronous
207 returns zero if the callback completes, a nonzero status if
208 there was some problem relating to the wait operation. The
209 status of the queued request will be stored through s, and
210 will also be either zero for success or nonzero for some kind
211 of failure. Never returns until completion or until the
212 connection to the server is lost. This performs the same
213 function as dhcpctl_set_callback and the subsequent callback,
214 for programs that want to do inline execution instead of using
215 callbacks. */
216
dhcpctl_wait_for_completion(dhcpctl_handle h,dhcpctl_status * s)217 dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
218 dhcpctl_status *s)
219 {
220 #ifdef DEBUG_DHCPCTL
221 log_debug("dhcpctl_wait_for_completion");
222 #endif
223 isc_result_t status;
224 status = omapi_wait_for_completion (h, 0);
225 if (status != ISC_R_SUCCESS) {
226 return status;
227 }
228 if (h -> type == dhcpctl_remote_type)
229 *s = ((dhcpctl_remote_object_t *)h) -> waitstatus;
230
231 return ISC_R_SUCCESS;
232 }
233
234 /* dhcpctl_timed_wait_for_completion
235
236 synchronous
237 returns zero if the callback completes, a nonzero status if
238 there was some problem relating to the wait operation. The
239 status of the queued request will be stored through s, and
240 will also be either zero for success or nonzero for some kind
241 of failure. How long the function waits for a response is
242 dictated by the value of the parameter, t. If the value is nul,
243 it will wait indefinitely or until the connection is lost.
244 Otherwise it will wait for the amount of time specified by t
245 (tv_sec:tv_usec). Values of zero for both fields are valid
246 but not recommended. The result of the request as processed on the
247 server is returned via the parameter, s. This performs the same
248 function as dhcpctl_set_callback and the subsequent callback,
249 for programs that want to do inline execution instead of using
250 callbacks. */
251
dhcpctl_timed_wait_for_completion(dhcpctl_handle h,dhcpctl_status * s,struct timeval * t)252 dhcpctl_status dhcpctl_timed_wait_for_completion (dhcpctl_handle h,
253 dhcpctl_status *s,
254 struct timeval *t)
255 {
256 isc_result_t status;
257 struct timeval adjusted_t;
258
259 #ifdef DEBUG_DHCPCTL
260 if (t) {
261 log_debug ("dhcpctl_timed_wait_for_completion"
262 "(%u.%u secs.usecs)",
263 (unsigned int)(t->tv_sec),
264 (unsigned int)(t->tv_usec));
265 } else {
266 log_debug ("dhcpctl_timed_wait_for_completion(no timeout)");
267 }
268 #endif
269
270 if (t) {
271 struct timeval now;
272 gettimeofday (&now, (struct timezone *)0);
273 adjusted_t.tv_sec = now.tv_sec + t->tv_sec;
274 adjusted_t.tv_usec = now.tv_usec + t->tv_usec;
275 }
276
277 status = omapi_wait_for_completion (h, (t ? &adjusted_t : 0));
278 if (status != ISC_R_SUCCESS) {
279 return status;
280 }
281
282 if (h->type == dhcpctl_remote_type) {
283 *s = ((dhcpctl_remote_object_t *)h)->waitstatus;
284 }
285
286 return ISC_R_SUCCESS;
287 }
288
289
290 /* dhcpctl_get_value
291
292 synchronous
293 returns zero if the call succeeded, a nonzero status code if
294 it didn't.
295 result is the address of an empty data string (initialized
296 with bzero or cleared with data_string_forget). On
297 successful completion, the addressed data string will contain
298 the value that was fetched.
299 dhcpctl_handle refers to some dhcpctl item
300 value_name refers to some value related to that item - e.g.,
301 for a handle associated with a completed host lookup, value
302 could be one of "hardware-address", "dhcp-client-identifier",
303 "known" or "client-hostname". */
304
dhcpctl_get_value(dhcpctl_data_string * result,dhcpctl_handle h,const char * value_name)305 dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result,
306 dhcpctl_handle h, const char *value_name)
307 {
308 isc_result_t status;
309 omapi_value_t *tv = (omapi_value_t *)0;
310 unsigned len;
311 int ip;
312 #ifdef DEBUG_DHCPCTL
313 log_debug("dhcpctl_get_value(%s)", value_name);
314 #endif
315
316 status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv);
317 if (status != ISC_R_SUCCESS)
318 return status;
319
320 switch (tv -> value -> type) {
321 case omapi_datatype_int:
322 len = sizeof (int);
323 break;
324
325 case omapi_datatype_string:
326 case omapi_datatype_data:
327 len = tv -> value -> u.buffer.len;
328 break;
329
330 case omapi_datatype_object:
331 len = sizeof (omapi_handle_t);
332 break;
333
334 default:
335 omapi_typed_data_dereference (&tv -> value, MDL);
336 return ISC_R_UNEXPECTED;
337 }
338
339 status = omapi_data_string_new (result, len, MDL);
340 if (status != ISC_R_SUCCESS) {
341 omapi_typed_data_dereference (&tv -> value, MDL);
342 return status;
343 }
344
345 switch (tv -> value -> type) {
346 case omapi_datatype_int:
347 ip = htonl (tv -> value -> u.integer);
348 memcpy ((*result) -> value, &ip, sizeof ip);
349 break;
350
351 case omapi_datatype_string:
352 case omapi_datatype_data:
353 memcpy ((*result) -> value,
354 tv -> value -> u.buffer.value,
355 tv -> value -> u.buffer.len);
356 break;
357
358 case omapi_datatype_object:
359 ip = htonl (tv -> value -> u.object -> handle);
360 memcpy ((*result) -> value, &ip, sizeof ip);
361 break;
362 }
363
364 omapi_value_dereference (&tv, MDL);
365 return ISC_R_SUCCESS;
366 }
367
368 /* dhcpctl_get_boolean
369
370 like dhcpctl_get_value, but more convenient for boolean
371 values, since no data_string needs to be dealt with. */
372
dhcpctl_get_boolean(int * result,dhcpctl_handle h,const char * value_name)373 dhcpctl_status dhcpctl_get_boolean (int *result,
374 dhcpctl_handle h, const char *value_name)
375 {
376 isc_result_t status;
377 dhcpctl_data_string data = (dhcpctl_data_string)0;
378 int rv;
379
380 #ifdef DEBUG_DHCPCTL
381 log_debug("dhcpctl_get_boolean(%s)", value_name);
382 #endif
383
384 status = dhcpctl_get_value (&data, h, value_name);
385 if (status != ISC_R_SUCCESS)
386 return status;
387 if (data -> len != sizeof rv) {
388 omapi_data_string_dereference (&data, MDL);
389 return ISC_R_UNEXPECTED;
390 }
391 memcpy (&rv, data -> value, sizeof rv);
392 *result = ntohl (rv);
393 omapi_data_string_dereference (&data, MDL);
394 return ISC_R_SUCCESS;
395 }
396
397 /* dhcpctl_set_value
398
399 Sets a value on an object referred to by a dhcpctl_handle.
400 The opposite of dhcpctl_get_value. Does not update the
401 server - just sets the value on the handle. */
402
dhcpctl_set_value(dhcpctl_handle h,dhcpctl_data_string value,const char * value_name)403 dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, dhcpctl_data_string value,
404 const char *value_name)
405 {
406 isc_result_t status;
407 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
408 omapi_data_string_t *name = (omapi_data_string_t *)0;
409 #ifdef DEBUG_DHCPCTL
410 log_debug("dhcpctl_set_value(%s)", value_name);
411 #endif
412
413 status = omapi_data_string_new (&name, strlen (value_name), MDL);
414 if (status != ISC_R_SUCCESS)
415 return status;
416 memcpy (name -> value, value_name, strlen (value_name));
417
418 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data,
419 value -> len);
420 if (status != ISC_R_SUCCESS) {
421 omapi_data_string_dereference (&name, MDL);
422 return status;
423 }
424 memcpy (tv -> u.buffer.value, value -> value, value -> len);
425
426 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
427 omapi_data_string_dereference (&name, MDL);
428 omapi_typed_data_dereference (&tv, MDL);
429 return status;
430 }
431
432 /* dhcpctl_set_string_value
433
434 Sets a NUL-terminated ASCII value on an object referred to by
435 a dhcpctl_handle. like dhcpctl_set_value, but saves the
436 trouble of creating a data_string for a NUL-terminated string.
437 Does not update the server - just sets the value on the handle. */
438
dhcpctl_set_string_value(dhcpctl_handle h,const char * value,const char * value_name)439 dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, const char *value,
440 const char *value_name)
441 {
442 isc_result_t status;
443 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
444 omapi_data_string_t *name = (omapi_data_string_t *)0;
445 #ifdef DEBUG_DHCPCTL
446 log_debug("dhcpctl_set_string_value(%s)", value_name);
447 #endif
448
449 status = omapi_data_string_new (&name, strlen (value_name), MDL);
450 if (status != ISC_R_SUCCESS)
451 return status;
452 memcpy (name -> value, value_name, strlen (value_name));
453
454 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value);
455 if (status != ISC_R_SUCCESS) {
456 omapi_data_string_dereference (&name, MDL);
457 return status;
458 }
459
460 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
461 omapi_data_string_dereference (&name, MDL);
462 omapi_typed_data_dereference (&tv, MDL);
463 return status;
464 }
465
466 /* dhcpctl_set_buffer_value
467
468 Sets a value on an object referred to by a dhcpctl_handle. like
469 dhcpctl_set_value, but saves the trouble of creating a data_string
470 for string for which we have a buffer and length. Does not update
471 the server - just sets the value on the handle. */
472
dhcpctl_set_data_value(dhcpctl_handle h,const char * value,unsigned len,const char * value_name)473 dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h,
474 const char *value, unsigned len,
475 const char *value_name)
476 {
477 isc_result_t status;
478 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
479 omapi_data_string_t *name = (omapi_data_string_t *)0;
480 unsigned ll;
481 #ifdef DEBUG_DHCPCTL
482 log_debug("dhcpctl_set_data_value(%s)", value_name);
483 #endif
484
485 ll = strlen (value_name);
486 status = omapi_data_string_new (&name, ll, MDL);
487 if (status != ISC_R_SUCCESS)
488 return status;
489 memcpy (name -> value, value_name, ll);
490
491 status = omapi_typed_data_new (MDL, &tv,
492 omapi_datatype_data, len, value);
493 if (status != ISC_R_SUCCESS) {
494 omapi_data_string_dereference (&name, MDL);
495 return status;
496 }
497 memcpy (tv -> u.buffer.value, value, len);
498
499 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
500 omapi_data_string_dereference (&name, MDL);
501 omapi_typed_data_dereference (&tv, MDL);
502 return status;
503 }
504
505 /* dhcpctl_set_null_value
506
507 Sets a null value on an object referred to by a dhcpctl_handle. */
508
dhcpctl_set_null_value(dhcpctl_handle h,const char * value_name)509 dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h,
510 const char *value_name)
511 {
512 isc_result_t status;
513 omapi_data_string_t *name = (omapi_data_string_t *)0;
514 unsigned ll;
515 #ifdef DEBUG_DHCPCTL
516 log_debug("dhcpctl_set_null_value(%s)", value_name);
517 #endif
518
519 ll = strlen (value_name);
520 status = omapi_data_string_new (&name, ll, MDL);
521 if (status != ISC_R_SUCCESS)
522 return status;
523 memcpy (name -> value, value_name, ll);
524
525 status = omapi_set_value (h, (omapi_object_t *)0, name,
526 (omapi_typed_data_t *)0);
527 omapi_data_string_dereference (&name, MDL);
528 return status;
529 }
530
531 /* dhcpctl_set_boolean_value
532
533 Sets a boolean value on an object - like dhcpctl_set_value,
534 only more convenient for booleans. */
535
dhcpctl_set_boolean_value(dhcpctl_handle h,int value,const char * value_name)536 dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle h, int value,
537 const char *value_name)
538 {
539 isc_result_t status;
540 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
541 omapi_data_string_t *name = (omapi_data_string_t *)0;
542 #ifdef DEBUG_DHCPCTL
543 log_debug("dhcpctl_set_boolean_value(%s)", value_name);
544 #endif
545
546 status = omapi_data_string_new (&name, strlen (value_name), MDL);
547 if (status != ISC_R_SUCCESS)
548 return status;
549 memcpy (name -> value, value_name, strlen (value_name));
550
551 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
552 if (status != ISC_R_SUCCESS) {
553 omapi_data_string_dereference (&name, MDL);
554 return status;
555 }
556
557 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
558 omapi_data_string_dereference (&name, MDL);
559 omapi_typed_data_dereference (&tv, MDL);
560 return status;
561 }
562
563 /* dhcpctl_set_int_value
564
565 Sets a boolean value on an object - like dhcpctl_set_value,
566 only more convenient for booleans. */
567
dhcpctl_set_int_value(dhcpctl_handle h,int value,const char * value_name)568 dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value,
569 const char *value_name)
570 {
571 isc_result_t status;
572 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
573 omapi_data_string_t *name = (omapi_data_string_t *)0;
574 #ifdef DEBUG_DHCPCTL
575 log_debug("dhcpctl_set_int_value(%s)", value_name);
576 #endif
577
578 status = omapi_data_string_new (&name, strlen (value_name), MDL);
579 if (status != ISC_R_SUCCESS)
580 return status;
581 memcpy (name -> value, value_name, strlen (value_name));
582
583 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
584 if (status != ISC_R_SUCCESS) {
585 omapi_data_string_dereference (&name, MDL);
586 return status;
587 }
588
589 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
590 omapi_data_string_dereference (&name, MDL);
591 omapi_typed_data_dereference (&tv, MDL);
592 return status;
593 }
594
595 /* dhcpctl_object_update
596
597 Queues an update on the object referenced by the handle (there
598 can't be any other work in progress on the handle). An
599 update means local parameters will be sent to the server. */
600
dhcpctl_object_update(dhcpctl_handle connection,dhcpctl_handle h)601 dhcpctl_status dhcpctl_object_update (dhcpctl_handle connection,
602 dhcpctl_handle h)
603 {
604 isc_result_t status;
605 omapi_object_t *message = (omapi_object_t *)0;
606 dhcpctl_remote_object_t *ro;
607 #ifdef DEBUG_DHCPCTL
608 log_debug("dhcpctl_object_update");
609 #endif
610
611 if (h -> type != dhcpctl_remote_type)
612 return DHCP_R_INVALIDARG;
613 ro = (dhcpctl_remote_object_t *)h;
614
615 status = omapi_message_new (&message, MDL);
616 if (status != ISC_R_SUCCESS) {
617 omapi_object_dereference (&message, MDL);
618 return status;
619 }
620 status = omapi_set_int_value (message, (omapi_object_t *)0,
621 "op", OMAPI_OP_UPDATE);
622 if (status != ISC_R_SUCCESS) {
623 omapi_object_dereference (&message, MDL);
624 return status;
625 }
626
627 status = omapi_set_object_value (message, (omapi_object_t *)0,
628 "object", h);
629 if (status != ISC_R_SUCCESS) {
630 omapi_object_dereference (&message, MDL);
631 return status;
632 }
633
634 status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
635 (int)(ro -> remote_handle));
636 if (status != ISC_R_SUCCESS) {
637 omapi_object_dereference (&message, MDL);
638 return status;
639 }
640
641 omapi_message_register (message);
642 status = omapi_protocol_send_message (connection -> outer,
643 (omapi_object_t *)0,
644 message, (omapi_object_t *)0);
645 omapi_object_dereference (&message, MDL);
646 return status;
647 }
648
649 /* Requests a refresh on the object referenced by the handle (there
650 can't be any other work in progress on the handle). A
651 refresh means local parameters are updated from the server. */
652
dhcpctl_object_refresh(dhcpctl_handle connection,dhcpctl_handle h)653 dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle connection,
654 dhcpctl_handle h)
655 {
656 isc_result_t status;
657 omapi_object_t *message = (omapi_object_t *)0;
658 dhcpctl_remote_object_t *ro;
659 #ifdef DEBUG_DHCPCTL
660 log_debug("dhcpctl_object_refresh");
661 #endif
662
663 if (h -> type != dhcpctl_remote_type)
664 return DHCP_R_INVALIDARG;
665 ro = (dhcpctl_remote_object_t *)h;
666
667 status = omapi_message_new (&message, MDL);
668 if (status != ISC_R_SUCCESS) {
669 omapi_object_dereference (&message, MDL);
670 return status;
671 }
672 status = omapi_set_int_value (message, (omapi_object_t *)0,
673 "op", OMAPI_OP_REFRESH);
674 if (status != ISC_R_SUCCESS) {
675 omapi_object_dereference (&message, MDL);
676 return status;
677 }
678 status = omapi_set_int_value (message, (omapi_object_t *)0,
679 "handle", (int)(ro -> remote_handle));
680 if (status != ISC_R_SUCCESS) {
681 omapi_object_dereference (&message, MDL);
682 return status;
683 }
684
685 omapi_message_register (message);
686 status = omapi_protocol_send_message (connection -> outer,
687 (omapi_object_t *)0,
688 message, (omapi_object_t *)0);
689
690 /* We don't want to send the contents of the object down the
691 wire, but we do need to reference it so that we know what
692 to do with the update. */
693 status = omapi_set_object_value (message, (omapi_object_t *)0,
694 "object", h);
695 if (status != ISC_R_SUCCESS) {
696 omapi_object_dereference (&message, MDL);
697 return status;
698 }
699
700 omapi_object_dereference (&message, MDL);
701 return status;
702 }
703
704 /* Requests the removal of the object referenced by the handle (there
705 can't be any other work in progress on the handle). A
706 removal means that all searchable references to the object on the
707 server are deleted. */
708
dhcpctl_object_remove(dhcpctl_handle connection,dhcpctl_handle h)709 dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection,
710 dhcpctl_handle h)
711 {
712 isc_result_t status;
713 omapi_object_t *message = (omapi_object_t *)0;
714 dhcpctl_remote_object_t *ro;
715 #ifdef DEBUG_DHCPCTL
716 log_debug("dhcpctl_object_remove");
717 #endif
718
719 if (h -> type != dhcpctl_remote_type)
720 return DHCP_R_INVALIDARG;
721 ro = (dhcpctl_remote_object_t *)h;
722
723 status = omapi_message_new (&message, MDL);
724 if (status != ISC_R_SUCCESS) {
725 omapi_object_dereference (&message, MDL);
726 return status;
727 }
728 status = omapi_set_int_value (message, (omapi_object_t *)0,
729 "op", OMAPI_OP_DELETE);
730 if (status != ISC_R_SUCCESS) {
731 omapi_object_dereference (&message, MDL);
732 return status;
733 }
734
735 status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
736 (int)(ro -> remote_handle));
737 if (status != ISC_R_SUCCESS) {
738 omapi_object_dereference (&message, MDL);
739 return status;
740 }
741
742 status = omapi_set_object_value (message, (omapi_object_t *)0,
743 "notify-object", h);
744 if (status != ISC_R_SUCCESS) {
745 omapi_object_dereference (&message, MDL);
746 return status;
747 }
748
749 omapi_message_register (message);
750 status = omapi_protocol_send_message (connection -> outer,
751 (omapi_object_t *)0,
752 message, (omapi_object_t *)0);
753 omapi_object_dereference (&message, MDL);
754 return status;
755 }
756
dhcpctl_data_string_dereference(dhcpctl_data_string * vp,const char * file,int line)757 isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *vp,
758 const char *file, int line)
759 {
760 #ifdef DEBUG_DHCPCTL
761 log_debug("dhcpctl_data_string_dereference");
762 #endif
763 return omapi_data_string_dereference (vp, file, line);
764 }
765
dhcpctl_disconnect(dhcpctl_handle * connection,int force)766 dhcpctl_status dhcpctl_disconnect (dhcpctl_handle *connection,
767 int force)
768 {
769 isc_result_t status;
770 #ifdef DEBUG_DHCPCTL
771 log_debug("dhcpctl_disconnect()");
772 #endif
773 if (!connection || !((*connection)->outer) ||
774 !((*connection)->outer->type) ||
775 ((*connection)->outer->type != omapi_type_protocol) ||
776 !((*connection)->outer->outer)) {
777 log_debug("dhcpctl_disconnect detected invalid arg");
778 return DHCP_R_INVALIDARG;
779 }
780
781 status = omapi_disconnect ((*connection)->outer->outer, force);
782 if (status == ISC_R_SUCCESS) {
783 #ifdef DEBUG_DHCPCTL
784 log_debug("dhcpctl_disconnect success");
785 #endif
786 omapi_object_dereference (connection, MDL);
787 return status;
788 }
789
790 #ifdef DEBUG_DHCPCTL
791 log_debug("dhcpctl_disconnect failed:%s",
792 isc_result_totext (status));
793 #endif
794 return status;
795 }
796
797