xref: /netbsd-src/external/mpl/dhcp/dist/dhcpctl/dhcpctl.c (revision f407d9293b6650aa8c33d6a995f797bb6aaefd90)
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