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