1/*	$NetBSD: cltest.c,v 1.3 2022/04/03 01:10:58 christos Exp $	*/
2
3/* cltest.c
4
5   Example program that uses the dhcpctl library. */
6
7/*
8 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 2000-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 * This software was contributed to Internet Systems Consortium
30 * by Brian Murrell.
31 */
32
33#include <sys/cdefs.h>
34__RCSID("$NetBSD: cltest.c,v 1.3 2022/04/03 01:10:58 christos Exp $");
35
36#include "config.h"
37
38#include <time.h>
39#include <sys/time.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <stdarg.h>
44#include "omapip/result.h"
45#include "dhcpctl.h"
46#include "dhcpd.h"
47
48/* Fixups */
49isc_result_t find_class (struct class **c, const char *n, const char *f, int l)
50{
51	return 0;
52}
53int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag)
54{
55	return 0;
56}
57void dhcp (struct packet *packet) { }
58void bootp (struct packet *packet) { }
59
60#ifdef DHCPv6
61/* XXX: should we warn or something here? */
62void dhcpv6(struct packet *packet) { }
63#ifdef DHCP4o6
64isc_result_t dhcpv4o6_handler(omapi_object_t *h)
65{
66	return ISC_R_NOTIMPLEMENTED;
67}
68#endif /* DHCP4o6 */
69#endif /* DHCPv6 */
70
71int check_collection (struct packet *p, struct lease *l, struct collection *c)
72{
73	return 0;
74}
75void classify (struct packet *packet, struct class *class) { }
76
77isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
78				     control_object_state_t newstate)
79{
80	return ISC_R_SUCCESS;
81}
82
83uint16_t local_port = 0;
84uint16_t remote_port = 0;
85libdhcp_callbacks_t cltest_callbacks = {
86	&local_port,
87	&remote_port,
88	classify,
89	check_collection,
90	dhcp,
91#ifdef DHCPv6
92	dhcpv6,
93#endif /* DHCPv6 */
94	bootp,
95	find_class,
96	parse_allow_deny,
97	dhcp_set_control_state,
98};
99
100int main (int, char **);
101
102enum modes { up, down, undefined };
103
104static void usage (char *s) {
105	fprintf (stderr,
106		 "Usage: %s [-n <username>] [-p <password>] [-a <algorithm>]"
107		 "(-u | -d) <if>\n", s);
108	exit (1);
109}
110
111int main (argc, argv)
112	int argc;
113	char **argv;
114{
115	isc_result_t status, waitstatus;
116	dhcpctl_handle authenticator;
117	dhcpctl_handle connection;
118	dhcpctl_handle interface_handle;
119	dhcpctl_data_string result;
120	int i;
121	int mode = undefined;
122	const char *interface = 0;
123	const char *action;
124
125	libdhcp_callbacks_register(&cltest_callbacks);
126
127	for (i = 1; i < argc; i++) {
128		if (!strcmp (argv[i], "-u")) {
129			mode = up;
130		} else if (!strcmp (argv [i], "-d")) {
131			mode = down;
132		} else if (argv[i][0] == '-') {
133			usage(argv[0]);
134		} else {
135			interface = argv[i];
136		}
137	}
138
139	if (!interface)
140		usage(argv[0]);
141	if (mode == undefined)
142		usage(argv[0]);
143
144	status = dhcpctl_initialize ();
145	if (status != ISC_R_SUCCESS) {
146		fprintf (stderr, "dhcpctl_initialize: %s\n",
147			 isc_result_totext (status));
148		exit (1);
149	}
150
151	authenticator = dhcpctl_null_handle;
152	connection = dhcpctl_null_handle;
153
154	status = dhcpctl_connect (&connection, "127.0.0.1", 7911,
155				  authenticator);
156	if (status != ISC_R_SUCCESS) {
157		fprintf (stderr, "dhcpctl_connect: %s\n",
158			 isc_result_totext (status));
159		exit (1);
160	}
161
162	interface_handle = dhcpctl_null_handle;
163	status = dhcpctl_new_object (&interface_handle,
164				     connection, "interface");
165	if (status != ISC_R_SUCCESS) {
166		fprintf (stderr, "dhcpctl_new_object: %s\n",
167			 isc_result_totext (status));
168		exit (1);
169	}
170
171	status = dhcpctl_set_string_value (interface_handle,
172					   interface, "name");
173	if (status != ISC_R_SUCCESS) {
174		fprintf (stderr, "dhcpctl_set_value: %s\n",
175			 isc_result_totext (status));
176		exit (1);
177	}
178
179	if (mode == up) {
180		/* "up" the interface */
181		printf ("upping interface %s\n", interface);
182		action = "create";
183		status = dhcpctl_open_object (interface_handle, connection,
184					      DHCPCTL_CREATE | DHCPCTL_EXCL);
185		if (status != ISC_R_SUCCESS) {
186			fprintf (stderr, "dhcpctl_open_object: %s\n",
187				 isc_result_totext (status));
188			exit (1);
189		}
190	} else {
191		/* down the interface */
192		printf ("downing interface %s\n", interface);
193		action = "remove";
194		status = dhcpctl_open_object (interface_handle, connection, 0);
195		if (status != ISC_R_SUCCESS) {
196			fprintf (stderr, "dhcpctl_open_object: %s\n",
197				 isc_result_totext (status));
198			exit (1);
199		}
200		status = dhcpctl_wait_for_completion (interface_handle,
201						      &waitstatus);
202		if (status != ISC_R_SUCCESS) {
203			fprintf (stderr, "dhcpctl_wait_for_completion: %s\n",
204				 isc_result_totext (status));
205			exit (1);
206		}
207		if (waitstatus != ISC_R_SUCCESS) {
208			fprintf (stderr, "dhcpctl_wait_for_completion: %s\n",
209				 isc_result_totext (waitstatus));
210			exit (1);
211		}
212		status = dhcpctl_object_remove (connection, interface_handle);
213		if (status != ISC_R_SUCCESS) {
214			fprintf (stderr, "dhcpctl_open_object: %s\n",
215				 isc_result_totext (status));
216			exit (1);
217		}
218	}
219
220	status = dhcpctl_wait_for_completion (interface_handle, &waitstatus);
221	if (status != ISC_R_SUCCESS) {
222		fprintf (stderr, "dhcpctl_wait_for_completion: %s\n",
223			 isc_result_totext (status));
224		exit (1);
225	}
226	if (waitstatus != ISC_R_SUCCESS) {
227		fprintf (stderr, "interface object %s: %s\n", action,
228			 isc_result_totext (waitstatus));
229		exit (1);
230	}
231
232	memset (&result, 0, sizeof result);
233	status = dhcpctl_get_value (&result, interface_handle, "state");
234	if (status != ISC_R_SUCCESS) {
235		fprintf (stderr, "dhcpctl_get_value: %s\n",
236			 isc_result_totext (status));
237		exit (1);
238	}
239
240	exit (0);
241}
242