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