ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
cltest2.c
Go to the documentation of this file.
1/* cltest2.c
2
3 Example program that uses the dhcpctl library. */
4
5/*
6 * Copyright (C) 2020-2022 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
42int main (int, char **);
43
44static void usage (char *s) {
45 fprintf (stderr,
46 "Usage: %s [-s <server ip>] [-p <port>]", s);
47 exit (1);
48}
49
50static 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
58isc_result_t wait_with_retry(dhcpctl_handle handle, struct timeval* timeout, int retries);
59
60void 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
79int 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,
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() */
193isc_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 */
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) {
254 printf ("%d\n", v->value->u.integer);
255 break;
256
258 printf ("\"%.*s\"\n", (int)v->value->u.buffer.len,
259 v->value->u.buffer.value);
260 break;
261
264 v->value->u.buffer.value,
265 sizeof(hex_buf), hex_buf);
266 printf("%s\n", hex_buf);
267 break;
268
270 printf ("<obj>\n");
271 break;
272 }
273 }
274}
275
276/* Dummy functions to appease linker */
277isc_result_t find_class (struct class **c, const char *n, const char *f, int l)
278{
279 return 0;
280}
281int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag)
282{
283 return 0;
284}
285void dhcp (struct packet *packet) { }
286void bootp (struct packet *packet) { }
287
288#ifdef DHCPv6
289void dhcpv6(struct packet *packet) { }
290
291#ifdef DHCP4o6
292isc_result_t dhcpv4o6_handler(omapi_object_t *h)
293{
295}
296#endif /* DHCP4o6 */
297#endif /* DHCPv6 */
298
299int check_collection (struct packet *p, struct lease *l, struct collection *c)
300{
301 return 0;
302}
303void classify (struct packet *packet, struct class *class) { }
304
306 control_object_state_t newstate)
307{
308 return ISC_R_SUCCESS;
309}
310
void bootp(struct packet *packet)
Definition cltest2.c:286
void dhcp(struct packet *packet)
Definition cltest2.c:285
int main(int, char **)
Definition cltest2.c:79
int parse_allow_deny(struct option_cache **oc, struct parse *cfile, int flag)
Definition cltest2.c:281
int check_collection(struct packet *p, struct lease *l, struct collection *c)
Definition cltest2.c:299
isc_result_t wait_with_retry(dhcpctl_handle handle, struct timeval *timeout, int retries)
Definition cltest2.c:193
void print_object(char *msg, dhcpctl_handle handle)
Definition cltest2.c:232
void classify(struct packet *packet, struct class *class)
Definition cltest2.c:303
isc_result_t dhcp_set_control_state(control_object_state_t oldstate, control_object_state_t newstate)
Definition cltest2.c:305
isc_result_t find_class(struct class **c, const char *n, const char *f, int l)
Definition cltest2.c:277
void print_hex_or_string(unsigned len, const u_int8_t *data, unsigned limit, char *buf)
Definition print.c:419
dhcpctl_status dhcpctl_object_refresh(dhcpctl_handle connection, dhcpctl_handle h)
Definition dhcpctl.c:648
dhcpctl_status dhcpctl_connect(dhcpctl_handle *connection, const char *server_name, int port, dhcpctl_handle authinfo)
Definition dhcpctl.c:98
dhcpctl_status dhcpctl_timed_connect(dhcpctl_handle *connection, const char *server_name, int port, dhcpctl_handle authinfo, struct timeval *t)
Definition dhcpctl.c:161
dhcpctl_status dhcpctl_disconnect(dhcpctl_handle *connection, int force)
Definition dhcpctl.c:761
dhcpctl_status dhcpctl_timed_wait_for_completion(dhcpctl_handle h, dhcpctl_status *s, struct timeval *t)
Definition dhcpctl.c:247
dhcpctl_status dhcpctl_initialize()
Definition dhcpctl.c:43
dhcpctl_status dhcpctl_set_string_value(dhcpctl_handle h, const char *value, const char *value_name)
Definition dhcpctl.c:434
#define DHCPCTL_CREATE
Definition dhcpctl.h:40
dhcpctl_status dhcpctl_open_object(dhcpctl_handle, dhcpctl_handle, int)
Definition remote.c:171
dhcpctl_status dhcpctl_new_object(dhcpctl_handle *, dhcpctl_handle, const char *)
Definition remote.c:106
#define DHCPCTL_EXCL
Definition dhcpctl.h:42
omapi_object_t * dhcpctl_handle
Definition dhcpctl.h:35
control_object_state_t
Definition dhcpd.h:522
void dhcpv6(struct packet *)
#define ISC_R_NOTIMPLEMENTED
#define ISC_R_SUCCESS
struct __omapi_object omapi_object_t
Definition omapip.h:39
@ omapi_datatype_string
Definition omapip.h:43
@ omapi_datatype_object
Definition omapip.h:45
@ omapi_datatype_int
Definition omapip.h:42
@ omapi_datatype_data
Definition omapip.h:44
struct __omapi_generic_object omapi_generic_object_t
omapi_value_t ** values
Definition omapip_p.h:219
Definition data.h:289
Definition dhcpd.h:560
unsigned char value[1]
Definition omapip.h:84
struct omapi_typed_data_t::@005330231110240362320041053235346164005276246221::@131374275124060200224243254021133345104025056044 buffer
omapi_datatype_t type
Definition omapip.h:50
unsigned char value[1]
Definition omapip.h:57
union omapi_typed_data_t::@005330231110240362320041053235346164005276246221 u
unsigned len
Definition omapip.h:53
omapi_data_string_t * name
Definition omapip.h:89
omapi_typed_data_t * value
Definition omapip.h:90
Definition dhcpd.h:288