omshell.c revision 1.1.1.2 1 1.1 christos /* $NetBSD: omshell.c,v 1.1.1.2 2022/04/03 01:08:36 christos Exp $ */
2 1.1 christos
3 1.1 christos /* omshell.c
4 1.1 christos
5 1.1 christos Examine and modify omapi objects. */
6 1.1 christos
7 1.1 christos /*
8 1.1.1.2 christos * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
9 1.1 christos * Copyright (c) 2001-2003 by Internet Software Consortium
10 1.1 christos *
11 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public
12 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this
13 1.1 christos * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 1.1 christos *
15 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 1.1 christos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 1.1 christos *
23 1.1 christos * Internet Systems Consortium, Inc.
24 1.1.1.2 christos * PO Box 360
25 1.1.1.2 christos * Newmarket, NH 03857 USA
26 1.1 christos * <info (at) isc.org>
27 1.1 christos * https://www.isc.org/
28 1.1 christos *
29 1.1 christos */
30 1.1 christos
31 1.1 christos #include <sys/cdefs.h>
32 1.1 christos __RCSID("$NetBSD: omshell.c,v 1.1.1.2 2022/04/03 01:08:36 christos Exp $");
33 1.1 christos
34 1.1 christos #include "config.h"
35 1.1 christos
36 1.1 christos #include <time.h>
37 1.1 christos #include <sys/time.h>
38 1.1 christos #include <stdio.h>
39 1.1 christos #include <stdlib.h>
40 1.1 christos #include <stdarg.h>
41 1.1 christos #include <string.h>
42 1.1 christos //#include "result.h"
43 1.1 christos #include <syslog.h>
44 1.1 christos #include "dhcpctl.h"
45 1.1 christos #include "dhcpd.h"
46 1.1 christos #include <isc/file.h>
47 1.1 christos
48 1.1 christos /* Fixups */
49 1.1 christos isc_result_t find_class (struct class **c, const char *n, const char *f, int l)
50 1.1 christos {
51 1.1 christos return 0;
52 1.1 christos }
53 1.1 christos int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag)
54 1.1 christos {
55 1.1 christos return 0;
56 1.1 christos }
57 1.1 christos void dhcp (struct packet *packet) { }
58 1.1 christos void bootp (struct packet *packet) { }
59 1.1 christos
60 1.1 christos #ifdef DHCPv6
61 1.1 christos /* XXX: should we warn or something here? */
62 1.1 christos void dhcpv6(struct packet *packet) { }
63 1.1 christos #ifdef DHCP4o6
64 1.1 christos isc_result_t dhcpv4o6_handler(omapi_object_t *h)
65 1.1 christos {
66 1.1 christos return ISC_R_NOTIMPLEMENTED;
67 1.1 christos }
68 1.1 christos #endif /* DHCP4o6 */
69 1.1 christos #endif /* DHCPv6 */
70 1.1 christos
71 1.1 christos int check_collection (struct packet *p, struct lease *l, struct collection *c)
72 1.1 christos {
73 1.1 christos return 0;
74 1.1 christos }
75 1.1 christos void classify (struct packet *packet, struct class *class) { }
76 1.1 christos
77 1.1 christos static void usage (const char *s) {
78 1.1 christos fprintf (stderr, "Usage: %s\n", s);
79 1.1 christos exit (1);
80 1.1 christos }
81 1.1 christos
82 1.1 christos static void check (isc_result_t status, const char *func) {
83 1.1 christos if (status != ISC_R_SUCCESS) {
84 1.1 christos fprintf (stderr, "%s: %s\n", func, isc_result_totext (status));
85 1.1 christos exit (1);
86 1.1 christos }
87 1.1 christos }
88 1.1 christos
89 1.1.1.2 christos int
90 1.1 christos main(int argc, char **argv) {
91 1.1 christos isc_result_t status, waitstatus;
92 1.1 christos dhcpctl_handle connection;
93 1.1 christos dhcpctl_handle authenticator;
94 1.1 christos dhcpctl_handle oh;
95 1.1 christos struct data_string secret;
96 1.1 christos const char *name = 0, *algorithm = "hmac-md5";
97 1.1 christos int i;
98 1.1 christos int port = 7911;
99 1.1 christos const char *server = "127.0.0.1";
100 1.1 christos struct parse *cfile;
101 1.1 christos enum dhcp_token token;
102 1.1 christos const char *val;
103 1.1 christos char *s;
104 1.1 christos char buf[1024];
105 1.1 christos char s1[1024];
106 1.1 christos int connected = 0;
107 1.1 christos char hex_buf[1025];
108 1.1 christos char *progname;
109 1.1 christos
110 1.1 christos #ifdef OLD_LOG_NAME
111 1.1 christos progname = "omshell";
112 1.1 christos #else
113 1.1 christos progname = argv[0];
114 1.1 christos #endif
115 1.1 christos
116 1.1 christos for (i = 1; i < argc; i++) {
117 1.1 christos usage(isc_file_basename(progname));
118 1.1 christos }
119 1.1 christos
120 1.1 christos /* Initially, log errors to stderr as well as to syslogd. */
121 1.1 christos openlog (isc_file_basename(progname),
122 1.1 christos DHCP_LOG_OPTIONS, DHCPD_LOG_FACILITY);
123 1.1 christos status = dhcpctl_initialize ();
124 1.1 christos if (status != ISC_R_SUCCESS) {
125 1.1 christos fprintf (stderr, "dhcpctl_initialize: %s\n",
126 1.1 christos isc_result_totext (status));
127 1.1 christos exit (1);
128 1.1 christos }
129 1.1 christos
130 1.1 christos memset (&oh, 0, sizeof oh);
131 1.1 christos
132 1.1 christos do {
133 1.1 christos if (!connected) {
134 1.1 christos } else if (oh == NULL) {
135 1.1 christos printf ("obj: <null>\n");
136 1.1 christos } else {
137 1.1 christos dhcpctl_remote_object_t *r = (dhcpctl_remote_object_t *)oh;
138 1.1 christos omapi_generic_object_t *g =
139 1.1 christos (omapi_generic_object_t *)(r -> inner);
140 1.1.1.2 christos
141 1.1 christos printf ("obj: ");
142 1.1 christos
143 1.1 christos if (r -> rtype -> type != omapi_datatype_string) {
144 1.1 christos printf ("?\n");
145 1.1 christos } else {
146 1.1 christos printf ("%.*s\n",
147 1.1 christos (int)(r -> rtype -> u . buffer . len),
148 1.1 christos r -> rtype -> u . buffer . value);
149 1.1 christos }
150 1.1.1.2 christos
151 1.1 christos for (i = 0; i < g -> nvalues; i++) {
152 1.1 christos omapi_value_t *v = g -> values [i];
153 1.1.1.2 christos
154 1.1 christos if (!g -> values [i])
155 1.1 christos continue;
156 1.1 christos
157 1.1 christos printf ("%.*s = ", (int)v -> name -> len,
158 1.1 christos v -> name -> value);
159 1.1.1.2 christos
160 1.1 christos if (!v -> value) {
161 1.1 christos printf ("<null>\n");
162 1.1 christos continue;
163 1.1 christos }
164 1.1 christos switch (v -> value -> type) {
165 1.1 christos case omapi_datatype_int:
166 1.1 christos printf ("%d\n",
167 1.1 christos v -> value -> u . integer);
168 1.1 christos break;
169 1.1.1.2 christos
170 1.1 christos case omapi_datatype_string:
171 1.1 christos printf ("\"%.*s\"\n",
172 1.1 christos (int) v -> value -> u.buffer.len,
173 1.1 christos v -> value -> u.buffer.value);
174 1.1 christos break;
175 1.1.1.2 christos
176 1.1 christos case omapi_datatype_data:
177 1.1 christos print_hex_or_string(v->value->u.buffer.len,
178 1.1 christos v->value->u.buffer.value,
179 1.1 christos sizeof(hex_buf), hex_buf);
180 1.1 christos printf("%s\n", hex_buf);
181 1.1 christos break;
182 1.1.1.2 christos
183 1.1 christos case omapi_datatype_object:
184 1.1 christos printf ("<obj>\n");
185 1.1 christos break;
186 1.1 christos }
187 1.1 christos }
188 1.1 christos }
189 1.1 christos
190 1.1 christos fputs ("> ", stdout);
191 1.1 christos fflush (stdout);
192 1.1 christos if (fgets (buf, sizeof(buf), stdin) == NULL)
193 1.1 christos break;
194 1.1 christos
195 1.1 christos status = new_parse (&cfile, -1, buf, strlen(buf), "<STDIN>", 1);
196 1.1 christos check(status, "new_parse()");
197 1.1.1.2 christos
198 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
199 1.1 christos switch (token) {
200 1.1 christos default:
201 1.1 christos parse_warn (cfile, "unknown token: %s", val);
202 1.1 christos skip_to_semi (cfile);
203 1.1 christos break;
204 1.1.1.2 christos
205 1.1 christos case END_OF_FILE:
206 1.1 christos case ENDOFLINE: /* EOL: */
207 1.1 christos break;
208 1.1.1.2 christos
209 1.1 christos case TOKEN_HELP:
210 1.1 christos case QUESTIONMARK: /* '?': */
211 1.1 christos printf ("Commands:\n");
212 1.1 christos printf (" port <server omapi port>\n");
213 1.1 christos printf (" server <server address>\n");
214 1.1 christos printf (" key <key name> <key value>\n");
215 1.1 christos printf (" connect\n");
216 1.1.1.2 christos printf (" disconnect\n");
217 1.1 christos printf (" new <object-type>\n");
218 1.1 christos printf (" set <name> = <value>\n");
219 1.1 christos printf (" create\n");
220 1.1 christos printf (" open\n");
221 1.1 christos printf (" update\n");
222 1.1 christos printf (" unset <name>\n");
223 1.1 christos printf (" refresh\n");
224 1.1 christos printf (" remove\n");
225 1.1 christos skip_to_semi (cfile);
226 1.1 christos break;
227 1.1.1.2 christos
228 1.1 christos case PORT:
229 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
230 1.1 christos if (is_identifier (token)) {
231 1.1 christos struct servent *se;
232 1.1 christos se = getservbyname (val, "tcp");
233 1.1 christos if (se)
234 1.1 christos port = ntohs (se -> s_port);
235 1.1 christos else {
236 1.1 christos printf ("unknown service name: %s\n", val);
237 1.1 christos break;
238 1.1 christos }
239 1.1 christos } else if (token == NUMBER) {
240 1.1 christos port = atoi (val);
241 1.1 christos } else {
242 1.1 christos skip_to_semi (cfile);
243 1.1 christos printf ("usage: port <port>\n");
244 1.1 christos break;
245 1.1 christos }
246 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
247 1.1 christos if (token != END_OF_FILE && token != EOL) {
248 1.1 christos printf ("usage: port <server>\n");
249 1.1 christos skip_to_semi (cfile);
250 1.1 christos break;
251 1.1 christos }
252 1.1 christos break;
253 1.1 christos
254 1.1 christos case TOKEN_SERVER:
255 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
256 1.1 christos if (token == NUMBER) {
257 1.1 christos int alen = (sizeof buf) - 1;
258 1.1 christos int len;
259 1.1 christos
260 1.1 christos s = &buf [0];
261 1.1 christos len = strlen (val);
262 1.1 christos if (len + 1 > alen) {
263 1.1 christos baddq:
264 1.1 christos printf ("usage: server <server>\n");
265 1.1 christos skip_to_semi (cfile);
266 1.1 christos break;
267 1.1 christos } strcpy (buf, val);
268 1.1 christos s += len;
269 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
270 1.1 christos if (token != DOT)
271 1.1 christos goto baddq;
272 1.1 christos *s++ = '.';
273 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
274 1.1 christos if (token != NUMBER)
275 1.1 christos goto baddq;
276 1.1 christos len = strlen (val);
277 1.1 christos if (len + 1 > alen)
278 1.1 christos goto baddq;
279 1.1 christos strcpy (s, val);
280 1.1 christos s += len;
281 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
282 1.1 christos if (token != DOT)
283 1.1 christos goto baddq;
284 1.1 christos *s++ = '.';
285 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
286 1.1 christos if (token != NUMBER)
287 1.1 christos goto baddq;
288 1.1 christos len = strlen (val);
289 1.1 christos if (len + 1 > alen)
290 1.1 christos goto baddq;
291 1.1 christos strcpy (s, val);
292 1.1 christos s += len;
293 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
294 1.1 christos if (token != DOT)
295 1.1 christos goto baddq;
296 1.1 christos *s++ = '.';
297 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
298 1.1 christos if (token != NUMBER)
299 1.1 christos goto baddq;
300 1.1 christos len = strlen (val);
301 1.1 christos if (len + 1 > alen)
302 1.1 christos goto baddq;
303 1.1 christos strcpy (s, val);
304 1.1 christos val = &buf [0];
305 1.1 christos } else if (is_identifier (token)) {
306 1.1 christos /* Use val directly. */
307 1.1 christos } else {
308 1.1 christos printf ("usage: server <server>\n");
309 1.1 christos skip_to_semi (cfile);
310 1.1 christos break;
311 1.1 christos }
312 1.1 christos
313 1.1 christos s = dmalloc (strlen (val) + 1, MDL);
314 1.1 christos if (!server) {
315 1.1 christos printf ("no memory to store server name.\n");
316 1.1 christos skip_to_semi (cfile);
317 1.1 christos break;
318 1.1 christos }
319 1.1 christos strcpy (s, val);
320 1.1 christos server = s;
321 1.1 christos
322 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
323 1.1 christos if (token != END_OF_FILE && token != EOL) {
324 1.1 christos printf ("usage: server <server>\n");
325 1.1 christos skip_to_semi (cfile);
326 1.1 christos break;
327 1.1 christos }
328 1.1 christos break;
329 1.1 christos
330 1.1 christos case KEY_ALGORITHM:
331 1.1 christos /* Algorithm is optional */
332 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
333 1.1 christos if (token != NAME || !is_identifier(token)) {
334 1.1 christos printf ("missing or invalid algorithm name\n");
335 1.1 christos printf ("usage: key-algoritm <algorithm name>\n");
336 1.1 christos skip_to_semi (cfile);
337 1.1 christos break;
338 1.1 christos }
339 1.1 christos
340 1.1 christos s = dmalloc (strlen (val) + 1, MDL);
341 1.1 christos if (!s) {
342 1.1 christos printf ("no memory for algorithm name.\n");
343 1.1 christos skip_to_semi (cfile);
344 1.1 christos break;
345 1.1 christos }
346 1.1 christos
347 1.1 christos strcpy (s, val);
348 1.1 christos algorithm = s;
349 1.1 christos
350 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
351 1.1 christos if (token != END_OF_FILE && token != EOL) {
352 1.1 christos printf ("extra information after %s\n", algorithm);
353 1.1 christos printf ("usage: key-algorithm <algorithm name>\n");
354 1.1 christos skip_to_semi (cfile);
355 1.1 christos break;
356 1.1 christos }
357 1.1 christos
358 1.1 christos break;
359 1.1 christos
360 1.1 christos case KEY:
361 1.1 christos token = peek_token(&val, (unsigned *)0, cfile);
362 1.1 christos if (token == STRING) {
363 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
364 1.1 christos if (!is_identifier (token)) {
365 1.1 christos printf ("usage: key <name> <value>\n");
366 1.1 christos skip_to_semi (cfile);
367 1.1 christos break;
368 1.1 christos }
369 1.1 christos s = dmalloc (strlen (val) + 1, MDL);
370 1.1 christos if (!s) {
371 1.1 christos printf ("no memory for key name.\n");
372 1.1 christos skip_to_semi (cfile);
373 1.1 christos break;
374 1.1 christos }
375 1.1 christos strcpy (s, val);
376 1.1 christos } else {
377 1.1 christos s = parse_host_name(cfile);
378 1.1 christos if (s == NULL) {
379 1.1 christos printf ("usage: key <name> <value>\n");
380 1.1 christos skip_to_semi(cfile);
381 1.1 christos break;
382 1.1 christos }
383 1.1 christos }
384 1.1 christos name = s;
385 1.1 christos
386 1.1 christos memset (&secret, 0, sizeof secret);
387 1.1 christos if (!parse_base64 (&secret, cfile)) {
388 1.1 christos skip_to_semi (cfile);
389 1.1 christos break;
390 1.1 christos }
391 1.1 christos
392 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
393 1.1 christos if (token != END_OF_FILE && token != EOL) {
394 1.1 christos printf ("usage: key <name> <value>\n");
395 1.1 christos skip_to_semi (cfile);
396 1.1 christos break;
397 1.1 christos }
398 1.1 christos
399 1.1 christos break;
400 1.1 christos
401 1.1 christos case CONNECT:
402 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
403 1.1 christos if (token != END_OF_FILE && token != EOL) {
404 1.1 christos printf ("usage: connect\n");
405 1.1 christos skip_to_semi (cfile);
406 1.1 christos break;
407 1.1 christos }
408 1.1 christos
409 1.1 christos authenticator = dhcpctl_null_handle;
410 1.1 christos
411 1.1 christos if (name) {
412 1.1 christos status = dhcpctl_new_authenticator (&authenticator,
413 1.1 christos name, algorithm,
414 1.1 christos secret.data,
415 1.1 christos secret.len);
416 1.1 christos
417 1.1 christos if (status != ISC_R_SUCCESS) {
418 1.1 christos fprintf (stderr,
419 1.1 christos "Cannot create authenticator: %s\n",
420 1.1 christos isc_result_totext (status));
421 1.1 christos break;
422 1.1 christos }
423 1.1 christos }
424 1.1 christos
425 1.1 christos memset (&connection, 0, sizeof connection);
426 1.1 christos status = dhcpctl_connect (&connection,
427 1.1 christos server, port, authenticator);
428 1.1 christos if (status != ISC_R_SUCCESS) {
429 1.1 christos fprintf (stderr, "dhcpctl_connect: %s\n",
430 1.1 christos isc_result_totext (status));
431 1.1 christos break;
432 1.1 christos }
433 1.1 christos connected = 1;
434 1.1 christos break;
435 1.1 christos
436 1.1.1.2 christos case DISCONNECT:
437 1.1.1.2 christos token = next_token (&val, (unsigned *)0, cfile);
438 1.1.1.2 christos if (token != END_OF_FILE && token != EOL) {
439 1.1.1.2 christos printf ("usage: disconnect\n");
440 1.1.1.2 christos skip_to_semi (cfile);
441 1.1.1.2 christos break;
442 1.1.1.2 christos }
443 1.1.1.2 christos
444 1.1.1.2 christos if (!connected || !connection) {
445 1.1.1.2 christos fprintf (stderr, "not connected\n");
446 1.1.1.2 christos break;
447 1.1.1.2 christos }
448 1.1.1.2 christos
449 1.1.1.2 christos status = dhcpctl_disconnect (&connection, 0);
450 1.1.1.2 christos if (status != ISC_R_SUCCESS) {
451 1.1.1.2 christos fprintf (stderr, "dhcpctl_disconnect: %s\n",
452 1.1.1.2 christos isc_result_totext (status));
453 1.1.1.2 christos break;
454 1.1.1.2 christos }
455 1.1.1.2 christos connected = 0;
456 1.1.1.2 christos break;
457 1.1.1.2 christos
458 1.1 christos case TOKEN_NEW:
459 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
460 1.1 christos if ((!is_identifier (token) && token != STRING)) {
461 1.1 christos printf ("usage: new <object-type>\n");
462 1.1 christos break;
463 1.1 christos }
464 1.1.1.2 christos
465 1.1 christos if (oh) {
466 1.1 christos printf ("an object is already open.\n");
467 1.1 christos skip_to_semi (cfile);
468 1.1 christos break;
469 1.1 christos }
470 1.1.1.2 christos
471 1.1 christos if (!connected) {
472 1.1 christos printf ("not connected.\n");
473 1.1 christos skip_to_semi (cfile);
474 1.1 christos break;
475 1.1 christos }
476 1.1 christos
477 1.1 christos status = dhcpctl_new_object (&oh, connection, val);
478 1.1 christos if (status != ISC_R_SUCCESS) {
479 1.1 christos printf ("can't create object: %s\n",
480 1.1 christos isc_result_totext (status));
481 1.1 christos break;
482 1.1 christos }
483 1.1.1.2 christos
484 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
485 1.1 christos if (token != END_OF_FILE && token != EOL) {
486 1.1 christos printf ("usage: new <object-type>\n");
487 1.1 christos skip_to_semi (cfile);
488 1.1 christos break;
489 1.1 christos }
490 1.1 christos break;
491 1.1 christos
492 1.1 christos case TOKEN_CLOSE:
493 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
494 1.1 christos if (token != END_OF_FILE && token != EOL) {
495 1.1 christos printf ("usage: close\n");
496 1.1 christos skip_to_semi (cfile);
497 1.1 christos break;
498 1.1 christos }
499 1.1 christos
500 1.1 christos if (!connected) {
501 1.1 christos printf ("not connected.\n");
502 1.1 christos skip_to_semi (cfile);
503 1.1 christos break;
504 1.1 christos }
505 1.1 christos
506 1.1 christos if (!oh) {
507 1.1 christos printf ("not open.\n");
508 1.1 christos skip_to_semi (cfile);
509 1.1 christos break;
510 1.1 christos }
511 1.1 christos omapi_object_dereference (&oh, MDL);
512 1.1.1.2 christos
513 1.1 christos break;
514 1.1 christos
515 1.1 christos case TOKEN_SET:
516 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
517 1.1 christos
518 1.1 christos if ((!is_identifier (token) && token != STRING)) {
519 1.1 christos set_usage:
520 1.1 christos printf ("usage: set <name> = <value>\n");
521 1.1 christos skip_to_semi (cfile);
522 1.1 christos break;
523 1.1 christos }
524 1.1.1.2 christos
525 1.1 christos if (oh == NULL) {
526 1.1 christos printf ("no open object.\n");
527 1.1 christos skip_to_semi (cfile);
528 1.1 christos break;
529 1.1 christos }
530 1.1.1.2 christos
531 1.1 christos if (!connected) {
532 1.1 christos printf ("not connected.\n");
533 1.1 christos skip_to_semi (cfile);
534 1.1 christos break;
535 1.1 christos }
536 1.1 christos
537 1.1 christos #ifdef HAVE_STRLCPY
538 1.1 christos strlcpy (s1, val, sizeof(s1));
539 1.1 christos #else
540 1.1 christos s1[0] = 0;
541 1.1 christos strncat (s1, val, sizeof(s1)-strlen(s1)-1);
542 1.1 christos #endif
543 1.1.1.2 christos
544 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
545 1.1 christos if (token != EQUAL)
546 1.1 christos goto set_usage;
547 1.1 christos
548 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
549 1.1 christos switch (token) {
550 1.1 christos case STRING:
551 1.1 christos dhcpctl_set_string_value (oh, val, s1);
552 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
553 1.1 christos break;
554 1.1.1.2 christos
555 1.1 christos case NUMBER:
556 1.1 christos strcpy (buf, val);
557 1.1 christos token = peek_token (&val, (unsigned *)0, cfile);
558 1.1 christos /* Colon-separated hex list? */
559 1.1 christos if (token == COLON)
560 1.1 christos goto cshl;
561 1.1 christos else if (token == DOT) {
562 1.1 christos s = buf;
563 1.1 christos val = buf;
564 1.1 christos do {
565 1.1 christos int intval = atoi (val);
566 1.1 christos if (intval > 255) {
567 1.1 christos parse_warn (cfile,
568 1.1 christos "dotted octet > 255: %s",
569 1.1 christos val);
570 1.1 christos skip_to_semi (cfile);
571 1.1 christos goto badnum;
572 1.1 christos }
573 1.1 christos *s++ = intval;
574 1.1 christos token = next_token (&val,
575 1.1 christos (unsigned *)0, cfile);
576 1.1 christos if (token != DOT)
577 1.1 christos break;
578 1.1 christos /* DOT is zero. */
579 1.1 christos while ((token = next_token (&val,
580 1.1 christos (unsigned *)0, cfile)) == DOT)
581 1.1 christos *s++ = 0;
582 1.1 christos } while (token == NUMBER);
583 1.1 christos dhcpctl_set_data_value (oh, buf,
584 1.1 christos (unsigned)(s - buf),
585 1.1 christos s1);
586 1.1 christos break;
587 1.1 christos }
588 1.1 christos dhcpctl_set_int_value (oh, atoi (buf), s1);
589 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
590 1.1 christos badnum:
591 1.1 christos break;
592 1.1.1.2 christos
593 1.1 christos case NUMBER_OR_NAME:
594 1.1 christos strcpy (buf, val);
595 1.1 christos cshl:
596 1.1 christos s = buf;
597 1.1 christos val = buf;
598 1.1 christos do {
599 1.1 christos convert_num (cfile, (unsigned char *)s,
600 1.1 christos val, 16, 8);
601 1.1 christos ++s;
602 1.1 christos token = next_token (&val,
603 1.1 christos (unsigned *)0, cfile);
604 1.1 christos if (token != COLON)
605 1.1 christos break;
606 1.1 christos token = next_token (&val,
607 1.1 christos (unsigned *)0, cfile);
608 1.1 christos } while (token == NUMBER ||
609 1.1 christos token == NUMBER_OR_NAME);
610 1.1 christos dhcpctl_set_data_value (oh, buf,
611 1.1 christos (unsigned)(s - buf), s1);
612 1.1 christos break;
613 1.1 christos
614 1.1 christos default:
615 1.1 christos printf ("invalid value.\n");
616 1.1 christos skip_to_semi (cfile);
617 1.1 christos }
618 1.1.1.2 christos
619 1.1 christos if (token != END_OF_FILE && token != EOL)
620 1.1 christos goto set_usage;
621 1.1 christos break;
622 1.1.1.2 christos
623 1.1 christos case UNSET:
624 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
625 1.1 christos
626 1.1 christos if ((!is_identifier (token) && token != STRING)) {
627 1.1 christos unset_usage:
628 1.1 christos printf ("usage: unset <name>\n");
629 1.1 christos skip_to_semi (cfile);
630 1.1 christos break;
631 1.1 christos }
632 1.1.1.2 christos
633 1.1 christos if (!oh) {
634 1.1 christos printf ("no open object.\n");
635 1.1 christos skip_to_semi (cfile);
636 1.1 christos break;
637 1.1 christos }
638 1.1.1.2 christos
639 1.1 christos if (!connected) {
640 1.1 christos printf ("not connected.\n");
641 1.1 christos skip_to_semi (cfile);
642 1.1 christos break;
643 1.1 christos }
644 1.1 christos
645 1.1 christos #if HAVE_STRLCPY
646 1.1 christos strlcpy (s1, val, sizeof(s1));
647 1.1 christos #else
648 1.1 christos s1[0] = 0;
649 1.1 christos strncat (s1, val, sizeof(s1)-strlen(s1)-1);
650 1.1 christos #endif
651 1.1.1.2 christos
652 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
653 1.1 christos if (token != END_OF_FILE && token != EOL)
654 1.1 christos goto unset_usage;
655 1.1 christos
656 1.1 christos dhcpctl_set_null_value (oh, s1);
657 1.1 christos break;
658 1.1 christos
659 1.1.1.2 christos
660 1.1 christos case TOKEN_CREATE:
661 1.1 christos case TOKEN_OPEN:
662 1.1 christos i = token;
663 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
664 1.1 christos if (token != END_OF_FILE && token != EOL) {
665 1.1 christos printf ("usage: %s\n", val);
666 1.1 christos skip_to_semi (cfile);
667 1.1 christos break;
668 1.1 christos }
669 1.1.1.2 christos
670 1.1 christos if (!connected) {
671 1.1 christos printf ("not connected.\n");
672 1.1 christos skip_to_semi (cfile);
673 1.1 christos break;
674 1.1 christos }
675 1.1 christos
676 1.1 christos if (!oh) {
677 1.1 christos printf ("you must make a new object first!\n");
678 1.1 christos skip_to_semi (cfile);
679 1.1 christos break;
680 1.1 christos }
681 1.1 christos
682 1.1 christos if (i == TOKEN_CREATE)
683 1.1 christos i = DHCPCTL_CREATE | DHCPCTL_EXCL;
684 1.1 christos else
685 1.1 christos i = 0;
686 1.1.1.2 christos
687 1.1 christos status = dhcpctl_open_object (oh, connection, i);
688 1.1 christos if (status == ISC_R_SUCCESS)
689 1.1 christos status = dhcpctl_wait_for_completion
690 1.1 christos (oh, &waitstatus);
691 1.1 christos if (status == ISC_R_SUCCESS)
692 1.1 christos status = waitstatus;
693 1.1 christos if (status != ISC_R_SUCCESS) {
694 1.1 christos printf ("can't open object: %s\n",
695 1.1 christos isc_result_totext (status));
696 1.1 christos break;
697 1.1 christos }
698 1.1.1.2 christos
699 1.1 christos break;
700 1.1 christos
701 1.1 christos case UPDATE:
702 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
703 1.1 christos if (token != END_OF_FILE && token != EOL) {
704 1.1 christos printf ("usage: %s\n", val);
705 1.1 christos skip_to_semi (cfile);
706 1.1 christos break;
707 1.1 christos }
708 1.1.1.2 christos
709 1.1 christos if (!connected) {
710 1.1 christos printf ("not connected.\n");
711 1.1 christos skip_to_semi (cfile);
712 1.1 christos break;
713 1.1 christos }
714 1.1 christos
715 1.1 christos if (!oh) {
716 1.1 christos printf ("you haven't opened an object yet!\n");
717 1.1 christos skip_to_semi (cfile);
718 1.1 christos break;
719 1.1 christos }
720 1.1 christos
721 1.1 christos status = dhcpctl_object_update(connection, oh);
722 1.1 christos if (status == ISC_R_SUCCESS)
723 1.1 christos status = dhcpctl_wait_for_completion
724 1.1 christos (oh, &waitstatus);
725 1.1 christos if (status == ISC_R_SUCCESS)
726 1.1 christos status = waitstatus;
727 1.1 christos if (status != ISC_R_SUCCESS) {
728 1.1 christos printf ("can't update object: %s\n",
729 1.1 christos isc_result_totext (status));
730 1.1 christos break;
731 1.1 christos }
732 1.1.1.2 christos
733 1.1 christos break;
734 1.1 christos
735 1.1 christos case REMOVE:
736 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
737 1.1 christos if (token != END_OF_FILE && token != EOL) {
738 1.1 christos printf ("usage: remove\n");
739 1.1 christos skip_to_semi (cfile);
740 1.1 christos break;
741 1.1 christos }
742 1.1.1.2 christos
743 1.1 christos if (!connected) {
744 1.1 christos printf ("not connected.\n");
745 1.1 christos break;
746 1.1 christos }
747 1.1 christos
748 1.1 christos if (!oh) {
749 1.1 christos printf ("no object.\n");
750 1.1 christos break;
751 1.1 christos }
752 1.1 christos
753 1.1 christos status = dhcpctl_object_remove(connection, oh);
754 1.1 christos if (status == ISC_R_SUCCESS)
755 1.1 christos status = dhcpctl_wait_for_completion
756 1.1 christos (oh, &waitstatus);
757 1.1 christos if (status == ISC_R_SUCCESS)
758 1.1 christos status = waitstatus;
759 1.1 christos if (status != ISC_R_SUCCESS) {
760 1.1 christos printf ("can't destroy object: %s\n",
761 1.1 christos isc_result_totext (status));
762 1.1 christos break;
763 1.1 christos }
764 1.1 christos omapi_object_dereference (&oh, MDL);
765 1.1 christos break;
766 1.1 christos
767 1.1 christos case REFRESH:
768 1.1 christos token = next_token (&val, (unsigned *)0, cfile);
769 1.1 christos if (token != END_OF_FILE && token != EOL) {
770 1.1 christos printf ("usage: refresh\n");
771 1.1 christos skip_to_semi (cfile);
772 1.1 christos break;
773 1.1 christos }
774 1.1.1.2 christos
775 1.1 christos if (!connected) {
776 1.1 christos printf ("not connected.\n");
777 1.1 christos break;
778 1.1 christos }
779 1.1 christos
780 1.1 christos if (!oh) {
781 1.1 christos printf ("no object.\n");
782 1.1 christos break;
783 1.1 christos }
784 1.1 christos
785 1.1 christos status = dhcpctl_object_refresh(connection, oh);
786 1.1 christos if (status == ISC_R_SUCCESS)
787 1.1 christos status = dhcpctl_wait_for_completion
788 1.1 christos (oh, &waitstatus);
789 1.1 christos if (status == ISC_R_SUCCESS)
790 1.1 christos status = waitstatus;
791 1.1 christos if (status != ISC_R_SUCCESS) {
792 1.1 christos printf ("can't refresh object: %s\n",
793 1.1 christos isc_result_totext (status));
794 1.1 christos break;
795 1.1 christos }
796 1.1.1.2 christos
797 1.1 christos break;
798 1.1 christos }
799 1.1 christos end_parse (&cfile);
800 1.1 christos } while (1);
801 1.1 christos
802 1.1 christos exit (0);
803 1.1 christos }
804 1.1 christos
805 1.1 christos /* Sigh */
806 1.1 christos isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
807 1.1 christos control_object_state_t newstate)
808 1.1 christos {
809 1.1 christos if (newstate != server_shutdown)
810 1.1 christos return ISC_R_SUCCESS;
811 1.1 christos exit (0);
812 1.1 christos }
813