3 Example program that uses the dhcpctl library. */
6 * Copyright (c) 2020 by Internet Systems Consortium, Inc. ("ISC")
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * Internet Systems Consortium, Inc.
22 * Redwood City, CA 94063
24 * https://www.isc.org/
26 * This software was contributed to Internet Systems Consortium
38 #include "omapip/result.h"
42 int main (int, char **);
44 static void usage (char *s
) {
46 "Usage: %s [-s <server ip>] [-p <port>]", s
);
50 static void fail_on_error(isc_result_t status
, const char* message
) {
51 if (status
!= ISC_R_SUCCESS
) {
52 fprintf (stderr
, "%s: %s\n",
53 message
, isc_result_totext (status
));
58 isc_result_t
wait_with_retry(dhcpctl_handle handle
, struct timeval
* timeout
, int retries
);
60 void print_object(char *msg
, dhcpctl_handle handle
);
62 /* Simple test program that exercises dhcpctl calls as follows:
64 * 1. Connect to the given server
65 * 2. Create a local host object with hostname "cltest2.host"
66 * 3. Attempt to open the remote host object
67 * 4. If the host does not exist, add a client id and create it
70 * 7. Refresh the host object
73 * 10. Time connect retry
75 * Note that this program tests dhcpctl_timed_wait_for_completion() by calling
76 * it with extremely small timeouts.
84 dhcpctl_handle connection
;
86 char* ip_address
= "127.0.0.1";
88 char* hostname
= "cltest2.host";
89 struct timeval timeout
;
92 for (i
= 1; i
< argc
; i
++) {
93 if (!strcmp (argv
[i
], "-s")) {
95 } else if (!strcmp (argv
[i
], "-p")) {
97 } else if (argv
[i
][0] == '-') {
102 /* Initialize dhcpctl */
103 status
= dhcpctl_initialize ();
104 fail_on_error(status
,"can't initialize dhcpctl");
108 status
= dhcpctl_connect (&connection
, ip_address
, port
, 0);
109 fail_on_error(status
,"connect failed");
111 /* Create the host object */
113 status
= dhcpctl_new_object (&host
, connection
, "host");
114 fail_on_error(status
,"new oject failed");
116 status
= dhcpctl_set_string_value (host
, hostname
, "name");
117 fail_on_error(status
,"cant set host name");
119 /* Attempt to open the object */
120 status
= dhcpctl_open_object (host
, connection
, 0);
122 timeout
.tv_usec
= 20;
123 status
= wait_with_retry(host
, &timeout
, 2);
126 /* Host doesn't exist add it. We set an id so the create will be valid. */
127 status
= dhcpctl_set_string_value (host
, "abcdefg", "dhcp-client-identifier");
128 fail_on_error(status
,"can't set client id");
130 status
= dhcpctl_open_object (host
, connection
,
131 DHCPCTL_CREATE
| DHCPCTL_EXCL
);
132 fail_on_error(status
, "open(create) failed");
134 status
= wait_with_retry(host
, &timeout
, 2);
135 fail_on_error(status
, "wait after open(create)");
137 print_object("Host created", host
);
141 print_object("Host exists", host
);
145 fail_on_error(status
, "initial open failed, waiting for completion");
149 /* Now we'll test disconnect */
150 status
= dhcpctl_disconnect(&connection
, 0);
151 fail_on_error(status
, "can't disconnect");
154 status
= dhcpctl_connect (&connection
, ip_address
, port
, 0);
155 fail_on_error(status
,"can't reconnect");
157 /* Refresh the object */
158 status
= dhcpctl_object_refresh (connection
, host
);
159 fail_on_error(status
, "can't refresh");
161 status
= wait_with_retry(host
, &timeout
, 2);
162 fail_on_error(status
, "wait after refresh failed");
164 print_object("After reconnect/refresh", host
);
166 /* Now we'll disconnect */
167 status
= dhcpctl_disconnect(&connection
, 0);
168 fail_on_error(status
, "can't disconnect");
170 /* Try a timed connect */
173 status
= dhcpctl_timed_connect (&connection
, ip_address
, port
, 0, &timeout
);
175 /* Try again if we time out */
176 if (status
== ISC_R_TIMEDOUT
) {
177 printf ("Retry timed connect\n");
179 status
= dhcpctl_timed_connect (&connection
, ip_address
, port
, 0,
183 fail_on_error(status
,"can't reconnect");
185 /* Lastly we'll disconnect to clean up */
186 status
= dhcpctl_disconnect(&connection
, 0);
187 fail_on_error(status
,"can't disconnect");
192 /* Function to call and optionally retry dhcp_timed_wait_for_completion() */
193 isc_result_t
wait_with_retry(dhcpctl_handle handle
, struct timeval
* timeout
, int retries
) {
195 isc_result_t waitstatus
;
196 struct timeval use_timeout
;
199 use_timeout
.tv_sec
= timeout
->tv_sec
;
200 use_timeout
.tv_usec
= timeout
->tv_usec
;
208 printf ("wait retry #%d\n", tries
);
209 /* Set the timeout value to 30 secs */
210 use_timeout
.tv_sec
= 30;
211 use_timeout
.tv_usec
= 0;
215 status
= dhcpctl_timed_wait_for_completion (handle
, &waitstatus
,
216 (timeout
? &use_timeout
: 0));
217 if (status
== ISC_R_SUCCESS
) {
221 if (status
!= ISC_R_TIMEDOUT
) {
222 fprintf (stderr
, "timed wait failed: %s\n", isc_result_totext (status
));
225 } while (--retries
> 0);
227 return (ISC_R_TIMEDOUT
);
230 /* Function to print out the values contained in an object. Largely
231 * stolen from omshell.c */
232 void print_object(char* msg
, dhcpctl_handle handle
) {
233 dhcpctl_remote_object_t
*r
= (dhcpctl_remote_object_t
*)handle
;
234 omapi_generic_object_t
*object
= (omapi_generic_object_t
*)(r
->inner
);
238 printf ("%s:\n",msg
);
239 for (i
= 0; i
< object
->nvalues
; i
++) {
240 omapi_value_t
*v
= object
->values
[i
];
242 if (!object
->values
[i
])
245 printf ("\t%.*s = ", (int)v
->name
->len
, v
->name
->value
);
252 switch (v
->value
->type
) {
253 case omapi_datatype_int
:
254 printf ("%d\n", v
->value
->u
.integer
);
257 case omapi_datatype_string
:
258 printf ("\"%.*s\"\n", (int)v
->value
->u
.buffer
.len
,
259 v
->value
->u
.buffer
.value
);
262 case omapi_datatype_data
:
263 print_hex_or_string(v
->value
->u
.buffer
.len
,
264 v
->value
->u
.buffer
.value
,
265 sizeof(hex_buf
), hex_buf
);
266 printf("%s\n", hex_buf
);
269 case omapi_datatype_object
:
276 /* Dummy functions to appease linker */
277 isc_result_t
find_class (struct class **c
, const char *n
, const char *f
, int l
)
281 int parse_allow_deny (struct option_cache
**oc
, struct parse
*cfile
, int flag
)
285 void dhcp (struct packet
*packet
) { }
286 void bootp (struct packet
*packet
) { }
289 void dhcpv6(struct packet
*packet
) { }
292 isc_result_t
dhcpv4o6_handler(omapi_object_t
*h
)
294 return ISC_R_NOTIMPLEMENTED
;
299 int check_collection (struct packet
*p
, struct lease
*l
, struct collection
*c
)
303 void classify (struct packet
*packet
, struct class *class) { }
305 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
306 control_object_state_t newstate
)
308 return ISC_R_SUCCESS
;