]> git.ipfire.org Git - thirdparty/dhcp.git/blob - dhcpctl/cltest2.c
Update README - added section on Release status which was in the TOC
[thirdparty/dhcp.git] / dhcpctl / cltest2.c
1 /* cltest2.c
2
3 Example program that uses the dhcpctl library. */
4
5 /*
6 * Copyright (c) 2020 by Internet Systems Consortium, Inc. ("ISC")
7 *
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/.
11 *
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.
19 *
20 * Internet Systems Consortium, Inc.
21 * 950 Charter Street
22 * Redwood City, CA 94063
23 * <info@isc.org>
24 * https://www.isc.org/
25 *
26 * This software was contributed to Internet Systems Consortium
27 * by Brian Murrell.
28 */
29
30 #include "config.h"
31
32 #include <time.h>
33 #include <sys/time.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdarg.h>
38 #include "omapip/result.h"
39 #include "dhcpctl.h"
40 #include "dhcpd.h"
41
42 int main (int, char **);
43
44 static void usage (char *s) {
45 fprintf (stderr,
46 "Usage: %s [-s <server ip>] [-p <port>]", s);
47 exit (1);
48 }
49
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));
54 exit (1);
55 }
56 }
57
58 isc_result_t wait_with_retry(dhcpctl_handle handle, struct timeval* timeout, int retries);
59
60 void print_object(char *msg, dhcpctl_handle handle);
61
62 /* Simple test program that exercises dhcpctl calls as follows:
63 *
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
68 * 5. Disconnect
69 * 6. Reconnect
70 * 7. Refresh the host object
71 * 8. Disconnect
72 * 9. Time connect
73 * 10. Time connect retry
74 *
75 * Note that this program tests dhcpctl_timed_wait_for_completion() by calling
76 * it with extremely small timeouts.
77 */
78
79 int main (argc, argv)
80 int argc;
81 char **argv;
82 {
83 isc_result_t status;
84 dhcpctl_handle connection;
85 dhcpctl_handle host;
86 char* ip_address = "127.0.0.1";
87 int port = 7911;
88 char* hostname = "cltest2.host";
89 struct timeval timeout;
90 int i;
91
92 for (i = 1; i < argc; i++) {
93 if (!strcmp (argv[i], "-s")) {
94 ip_address = argv[i];
95 } else if (!strcmp (argv [i], "-p")) {
96 port=atoi(argv[i]);
97 } else if (argv[i][0] == '-') {
98 usage(argv[0]);
99 }
100 }
101
102 /* Initialize dhcpctl */
103 status = dhcpctl_initialize ();
104 fail_on_error(status ,"can't initialize dhcpctl");
105
106 /* Connect */
107 connection = 0;
108 status = dhcpctl_connect (&connection, ip_address, port, 0);
109 fail_on_error(status ,"connect failed");
110
111 /* Create the host object */
112 host = 0;
113 status = dhcpctl_new_object (&host, connection, "host");
114 fail_on_error(status ,"new oject failed");
115
116 status = dhcpctl_set_string_value (host, hostname, "name");
117 fail_on_error(status ,"cant set host name");
118
119 /* Attempt to open the object */
120 status = dhcpctl_open_object (host, connection, 0);
121 timeout.tv_sec = 0;
122 timeout.tv_usec = 20;
123 status = wait_with_retry(host, &timeout, 2);
124 switch (status) {
125 case ISC_R_NOTFOUND:
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");
129
130 status = dhcpctl_open_object (host, connection,
131 DHCPCTL_CREATE | DHCPCTL_EXCL);
132 fail_on_error(status, "open(create) failed");
133
134 status = wait_with_retry(host, &timeout, 2);
135 fail_on_error(status, "wait after open(create)");
136
137 print_object("Host created", host);
138 break;
139
140 case ISC_R_SUCCESS:
141 print_object("Host exists", host);
142 break;
143
144 default:
145 fail_on_error(status, "initial open failed, waiting for completion");
146 break;
147 }
148
149 /* Now we'll test disconnect */
150 status = dhcpctl_disconnect(&connection, 0);
151 fail_on_error(status, "can't disconnect");
152
153 /* Reconnect */
154 status = dhcpctl_connect (&connection, ip_address, port, 0);
155 fail_on_error(status ,"can't reconnect");
156
157 /* Refresh the object */
158 status = dhcpctl_object_refresh (connection, host);
159 fail_on_error(status , "can't refresh");
160
161 status = wait_with_retry(host, &timeout, 2);
162 fail_on_error(status , "wait after refresh failed");
163
164 print_object("After reconnect/refresh", host);
165
166 /* Now we'll disconnect */
167 status = dhcpctl_disconnect(&connection, 0);
168 fail_on_error(status, "can't disconnect");
169
170 /* Try a timed connect */
171 timeout.tv_sec = 0;
172 timeout.tv_usec = 1;
173 status = dhcpctl_timed_connect (&connection, ip_address, port, 0, &timeout);
174
175 /* Try again if we time out */
176 if (status == ISC_R_TIMEDOUT) {
177 printf ("Retry timed connect\n");
178 timeout.tv_sec = 10;
179 status = dhcpctl_timed_connect (&connection, ip_address, port, 0,
180 &timeout);
181 }
182
183 fail_on_error(status ,"can't reconnect");
184
185 /* Lastly we'll disconnect to clean up */
186 status = dhcpctl_disconnect(&connection, 0);
187 fail_on_error(status ,"can't disconnect");
188
189 exit (0);
190 }
191
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) {
194 isc_result_t status;
195 isc_result_t waitstatus;
196 struct timeval use_timeout;
197
198 if (timeout) {
199 use_timeout.tv_sec = timeout->tv_sec;
200 use_timeout.tv_usec = timeout->tv_usec;
201 } else {
202 retries = 0;
203 }
204
205 int tries = 0;
206 do {
207 if (tries++) {
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;
212 }
213
214 // Call timed wait.
215 status = dhcpctl_timed_wait_for_completion (handle, &waitstatus,
216 (timeout ? &use_timeout: 0));
217 if (status == ISC_R_SUCCESS) {
218 return(waitstatus);
219 }
220
221 if (status != ISC_R_TIMEDOUT) {
222 fprintf (stderr, "timed wait failed: %s\n", isc_result_totext (status));
223 exit (1);
224 }
225 } while (--retries > 0);
226
227 return (ISC_R_TIMEDOUT);
228 }
229
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);
235 char hex_buf[4096];
236 int i;
237
238 printf ("%s:\n",msg);
239 for (i = 0; i < object->nvalues; i++) {
240 omapi_value_t *v = object->values[i];
241
242 if (!object->values[i])
243 continue;
244
245 printf ("\t%.*s = ", (int)v->name->len, v->name->value);
246
247 if (!v->value) {
248 printf ("<null>\n");
249 continue;
250 }
251
252 switch (v->value->type) {
253 case omapi_datatype_int:
254 printf ("%d\n", v->value->u.integer);
255 break;
256
257 case omapi_datatype_string:
258 printf ("\"%.*s\"\n", (int)v->value->u.buffer.len,
259 v->value->u.buffer.value);
260 break;
261
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);
267 break;
268
269 case omapi_datatype_object:
270 printf ("<obj>\n");
271 break;
272 }
273 }
274 }
275
276 /* Dummy functions to appease linker */
277 isc_result_t find_class (struct class **c, const char *n, const char *f, int l)
278 {
279 return 0;
280 }
281 int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag)
282 {
283 return 0;
284 }
285 void dhcp (struct packet *packet) { }
286 void bootp (struct packet *packet) { }
287
288 #ifdef DHCPv6
289 void dhcpv6(struct packet *packet) { }
290
291 #ifdef DHCP4o6
292 isc_result_t dhcpv4o6_handler(omapi_object_t *h)
293 {
294 return ISC_R_NOTIMPLEMENTED;
295 }
296 #endif /* DHCP4o6 */
297 #endif /* DHCPv6 */
298
299 int check_collection (struct packet *p, struct lease *l, struct collection *c)
300 {
301 return 0;
302 }
303 void classify (struct packet *packet, struct class *class) { }
304
305 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
306 control_object_state_t newstate)
307 {
308 return ISC_R_SUCCESS;
309 }
310