s/Conatainer/Container/
[dragonfly.git] / contrib / dhcp-3.0 / dhcpctl / omshell.c
blobaabbe0419f51cafa19b99c10c7e069da041368b8
1 /* omshell.c
3 Examine and modify omapi objects. */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 2001-2003 by Internet Software Consortium
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.
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.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
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''.
35 #ifndef lint
36 static char copyright[] =
37 "$Id: omshell.c,v 1.7.2.17 2004/09/30 23:11:50 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
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 "dhcpctl.h"
48 #include "dhcpd.h"
50 /* Fixups */
51 isc_result_t find_class (struct class **c, const char *n, const char *f, int l)
53 return 0;
55 int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag)
57 return 0;
59 void dhcp (struct packet *packet) { }
60 void bootp (struct packet *packet) { }
61 int check_collection (struct packet *p, struct lease *l, struct collection *c)
63 return 0;
65 void classify (struct packet *packet, struct class *class) { }
67 static void usage (char *s) {
68 fprintf (stderr, "Usage: %s\n", s);
69 exit (1);
72 static void check (isc_result_t status, const char *func) {
73 if (status != ISC_R_SUCCESS) {
74 fprintf (stderr, "%s: %s\n", func, isc_result_totext (status));
75 exit (1);
79 int main (int argc, char **argv, char **envp)
81 isc_result_t status, waitstatus;
82 dhcpctl_handle connection;
83 dhcpctl_handle authenticator;
84 dhcpctl_handle oh;
85 dhcpctl_data_string cid, ip_addr;
86 dhcpctl_data_string result, groupname, identifier;
87 struct data_string secret;
88 const char *name = 0, *algorithm = "hmac-md5";
89 int i, j;
90 int port = 7911;
91 const char *server = "127.0.0.1";
92 struct parse *cfile;
93 enum dhcp_token token;
94 const char *val;
95 char *s;
96 char buf[1024];
97 char s1[1024];
98 int connected = 0;
100 for (i = 1; i < argc; i++) {
101 usage(argv[0]);
104 /* Initially, log errors to stderr as well as to syslogd. */
105 #ifdef SYSLOG_4_2
106 openlog ("omshell", LOG_NDELAY);
107 log_priority = DHCPD_LOG_FACILITY;
108 #else
109 openlog ("omshell", LOG_NDELAY, DHCPD_LOG_FACILITY);
110 #endif
111 status = dhcpctl_initialize ();
112 if (status != ISC_R_SUCCESS) {
113 fprintf (stderr, "dhcpctl_initialize: %s\n",
114 isc_result_totext (status));
115 exit (1);
118 memset (&oh, 0, sizeof oh);
120 do {
121 if (!connected) {
122 } else if (oh == NULL) {
123 printf ("obj: <null>\n");
124 } else {
125 dhcpctl_remote_object_t *r = (dhcpctl_remote_object_t *)oh;
126 omapi_generic_object_t *g =
127 (omapi_generic_object_t *)(r -> inner);
129 printf ("obj: ");
131 if (r -> rtype -> type != omapi_datatype_string) {
132 printf ("?\n");
133 } else {
134 printf ("%.*s\n",
135 (int)(r -> rtype -> u . buffer . len),
136 r -> rtype -> u . buffer . value);
139 for (i = 0; i < g -> nvalues; i++) {
140 omapi_value_t *v = g -> values [i];
142 if (!g -> values [i])
143 continue;
145 printf ("%.*s = ", (int)v -> name -> len,
146 v -> name -> value);
148 if (!v -> value) {
149 printf ("<null>\n");
150 continue;
152 switch (v -> value -> type) {
153 case omapi_datatype_int:
154 printf ("%d\n",
155 v -> value -> u . integer);
156 break;
158 case omapi_datatype_string:
159 printf ("\"%.*s\"\n",
160 (int) v -> value -> u.buffer.len,
161 v -> value -> u.buffer.value);
162 break;
164 case omapi_datatype_data:
165 printf ("%s\n",
166 print_hex_1 (v -> value -> u.buffer.len,
167 v -> value -> u.buffer.value,
168 60));
169 break;
171 case omapi_datatype_object:
172 printf ("<obj>\n");
173 break;
178 fputs ("> ", stdout);
179 fflush (stdout);
180 if (fgets (buf, sizeof(buf), stdin) == NULL)
181 break;
183 status = new_parse (&cfile, 0, buf, strlen(buf), "<STDIN>", 1);
184 check(status, "new_parse()");
186 token = next_token (&val, (unsigned *)0, cfile);
187 switch (token) {
188 default:
189 parse_warn (cfile, "unknown token: %s", val);
190 skip_to_semi (cfile);
191 break;
193 case END_OF_FILE:
194 case EOL:
195 break;
197 case TOKEN_HELP:
198 case '?':
199 printf ("Commands:\n");
200 printf (" port <server omapi port>\n");
201 printf (" server <server address>\n");
202 printf (" key <key name> <key value>\n");
203 printf (" connect\n");
204 printf (" new <object-type>\n");
205 printf (" set <name> = <value>\n");
206 printf (" create\n");
207 printf (" open\n");
208 printf (" update\n");
209 printf (" unset <name>\n");
210 printf (" refresh\n");
211 printf (" remove\n");
212 skip_to_semi (cfile);
213 break;
215 case PORT:
216 token = next_token (&val, (unsigned *)0, cfile);
217 if (is_identifier (token)) {
218 struct servent *se;
219 se = getservbyname (val, "tcp");
220 if (se)
221 port = ntohs (se -> s_port);
222 else {
223 printf ("unknown service name: %s\n", val);
224 break;
226 } else if (token == NUMBER) {
227 port = atoi (val);
228 } else {
229 skip_to_semi (cfile);
230 printf ("usage: port <port>\n");
231 break;
233 token = next_token (&val, (unsigned *)0, cfile);
234 if (token != END_OF_FILE && token != EOL) {
235 printf ("usage: port <server>\n");
236 skip_to_semi (cfile);
237 break;
239 break;
241 case SERVER:
242 token = next_token (&val, (unsigned *)0, cfile);
243 if (token == NUMBER) {
244 int alen = (sizeof buf) - 1;
245 int len;
247 s = &buf [0];
248 len = strlen (val);
249 if (len + 1 > alen) {
250 baddq:
251 printf ("usage: server <server>\n");
252 skip_to_semi (cfile);
253 break;
254 } strcpy (buf, val);
255 s += len;
256 token = next_token (&val, (unsigned *)0, cfile);
257 if (token != DOT)
258 goto baddq;
259 *s++ = '.';
260 token = next_token (&val, (unsigned *)0, cfile);
261 if (token != NUMBER)
262 goto baddq;
263 len = strlen (val);
264 if (len + 1 > alen)
265 goto baddq;
266 strcpy (s, val);
267 s += len;
268 token = next_token (&val, (unsigned *)0, cfile);
269 if (token != DOT)
270 goto baddq;
271 *s++ = '.';
272 token = next_token (&val, (unsigned *)0, cfile);
273 if (token != NUMBER)
274 goto baddq;
275 len = strlen (val);
276 if (len + 1 > alen)
277 goto baddq;
278 strcpy (s, val);
279 s += len;
280 token = next_token (&val, (unsigned *)0, cfile);
281 if (token != DOT)
282 goto baddq;
283 *s++ = '.';
284 token = next_token (&val, (unsigned *)0, cfile);
285 if (token != NUMBER)
286 goto baddq;
287 len = strlen (val);
288 if (len + 1 > alen)
289 goto baddq;
290 strcpy (s, val);
291 val = &buf [0];
292 } else if (is_identifier (token)) {
293 /* Use val directly. */
294 } else {
295 printf ("usage: server <server>\n");
296 skip_to_semi (cfile);
297 break;
300 s = dmalloc (strlen (val) + 1, MDL);
301 if (!server) {
302 printf ("no memory to store server name.\n");
303 skip_to_semi (cfile);
304 break;
306 strcpy (s, val);
307 server = s;
309 token = next_token (&val, (unsigned *)0, cfile);
310 if (token != END_OF_FILE && token != EOL) {
311 printf ("usage: server <server>\n");
312 skip_to_semi (cfile);
313 break;
315 break;
317 case KEY:
318 token = next_token (&val, (unsigned *)0, cfile);
319 if (!is_identifier (token)) {
320 printf ("usage: key <name> <value>\n");
321 skip_to_semi (cfile);
322 break;
324 s = dmalloc (strlen (val) + 1, MDL);
325 if (!s) {
326 printf ("no memory for key name.\n");
327 skip_to_semi (cfile);
328 break;
330 strcpy (s, val);
331 name = s;
332 memset (&secret, 0, sizeof secret);
333 if (!parse_base64 (&secret, cfile)) {
334 skip_to_semi (cfile);
335 break;
337 token = next_token (&val, (unsigned *)0, cfile);
338 if (token != END_OF_FILE && token != EOL) {
339 printf ("usage: key <name> <secret>\n");
340 skip_to_semi (cfile);
341 break;
343 break;
345 case CONNECT:
346 token = next_token (&val, (unsigned *)0, cfile);
347 if (token != END_OF_FILE && token != EOL) {
348 printf ("usage: connect\n");
349 skip_to_semi (cfile);
350 break;
353 authenticator = dhcpctl_null_handle;
355 if (name) {
356 status = dhcpctl_new_authenticator (&authenticator,
357 name, algorithm,
358 secret.data,
359 secret.len);
361 if (status != ISC_R_SUCCESS) {
362 fprintf (stderr,
363 "Cannot create authenticator: %s\n",
364 isc_result_totext (status));
365 break;
369 memset (&connection, 0, sizeof connection);
370 status = dhcpctl_connect (&connection,
371 server, port, authenticator);
372 if (status != ISC_R_SUCCESS) {
373 fprintf (stderr, "dhcpctl_connect: %s\n",
374 isc_result_totext (status));
375 break;
377 connected = 1;
378 break;
380 case TOKEN_NEW:
381 token = next_token (&val, (unsigned *)0, cfile);
382 if ((!is_identifier (token) && token != STRING)) {
383 printf ("usage: new <object-type>\n");
384 break;
387 if (oh) {
388 printf ("an object is already open.\n");
389 skip_to_semi (cfile);
390 break;
393 if (!connected) {
394 printf ("not connected.\n");
395 skip_to_semi (cfile);
396 break;
399 status = dhcpctl_new_object (&oh, connection, val);
400 if (status != ISC_R_SUCCESS) {
401 printf ("can't create object: %s\n",
402 isc_result_totext (status));
403 break;
406 token = next_token (&val, (unsigned *)0, cfile);
407 if (token != END_OF_FILE && token != EOL) {
408 printf ("usage: new <object-type>\n");
409 skip_to_semi (cfile);
410 break;
412 break;
414 case TOKEN_CLOSE:
415 token = next_token (&val, (unsigned *)0, cfile);
416 if (token != END_OF_FILE && token != EOL) {
417 printf ("usage: close\n");
418 skip_to_semi (cfile);
419 break;
422 if (!connected) {
423 printf ("not connected.\n");
424 skip_to_semi (cfile);
425 break;
428 if (!oh) {
429 printf ("not open.\n");
430 skip_to_semi (cfile);
431 break;
433 omapi_object_dereference (&oh, MDL);
435 break;
437 case TOKEN_SET:
438 token = next_token (&val, (unsigned *)0, cfile);
440 if ((!is_identifier (token) && token != STRING)) {
441 set_usage:
442 printf ("usage: set <name> = <value>\n");
443 skip_to_semi (cfile);
444 break;
447 if (oh == NULL) {
448 printf ("no open object.\n");
449 skip_to_semi (cfile);
450 break;
453 if (!connected) {
454 printf ("not connected.\n");
455 skip_to_semi (cfile);
456 break;
459 s1[0] = '\0';
460 strncat (s1, val, sizeof(s1)-1);
462 token = next_token (&val, (unsigned *)0, cfile);
463 if (token != EQUAL)
464 goto set_usage;
466 token = next_token (&val, (unsigned *)0, cfile);
467 switch (token) {
468 case STRING:
469 dhcpctl_set_string_value (oh, val, s1);
470 token = next_token (&val, (unsigned *)0, cfile);
471 break;
473 case NUMBER:
474 strcpy (buf, val);
475 token = peek_token (&val, (unsigned *)0, cfile);
476 /* Colon-seperated hex list? */
477 if (token == COLON)
478 goto cshl;
479 else if (token == DOT) {
480 s = buf;
481 val = buf;
482 do {
483 int intval = atoi (val);
484 dotiszero:
485 if (intval > 255) {
486 parse_warn (cfile,
487 "dotted octet > 255: %s",
488 val);
489 skip_to_semi (cfile);
490 goto badnum;
492 *s++ = intval;
493 token = next_token (&val,
494 (unsigned *)0, cfile);
495 if (token != DOT)
496 break;
497 /* DOT is zero. */
498 while ((token = next_token (&val,
499 (unsigned *)0, cfile)) == DOT)
500 *s++ = 0;
501 } while (token == NUMBER);
502 dhcpctl_set_data_value (oh, buf,
503 (unsigned)(s - buf),
504 s1);
505 break;
507 dhcpctl_set_int_value (oh, atoi (buf), s1);
508 token = next_token (&val, (unsigned *)0, cfile);
509 badnum:
510 break;
512 case NUMBER_OR_NAME:
513 strcpy (buf, val);
514 cshl:
515 s = buf;
516 val = buf;
517 do {
518 convert_num (cfile, (unsigned char *)s,
519 val, 16, 8);
520 ++s;
521 token = next_token (&val,
522 (unsigned *)0, cfile);
523 if (token != COLON)
524 break;
525 token = next_token (&val,
526 (unsigned *)0, cfile);
527 } while (token == NUMBER ||
528 token == NUMBER_OR_NAME);
529 dhcpctl_set_data_value (oh, buf,
530 (unsigned)(s - buf), s1);
531 break;
533 default:
534 printf ("invalid value.\n");
535 skip_to_semi (cfile);
538 if (token != END_OF_FILE && token != EOL)
539 goto set_usage;
540 break;
542 case UNSET:
543 token = next_token (&val, (unsigned *)0, cfile);
545 if ((!is_identifier (token) && token != STRING)) {
546 unset_usage:
547 printf ("usage: unset <name>\n");
548 skip_to_semi (cfile);
549 break;
552 if (!oh) {
553 printf ("no open object.\n");
554 skip_to_semi (cfile);
555 break;
558 if (!connected) {
559 printf ("not connected.\n");
560 skip_to_semi (cfile);
561 break;
564 s1[0] = '\0';
565 strncat (s1, val, sizeof(s1)-1);
567 token = next_token (&val, (unsigned *)0, cfile);
568 if (token != END_OF_FILE && token != EOL)
569 goto unset_usage;
571 dhcpctl_set_null_value (oh, s1);
572 break;
575 case TOKEN_CREATE:
576 case TOKEN_OPEN:
577 i = token;
578 token = next_token (&val, (unsigned *)0, cfile);
579 if (token != END_OF_FILE && token != EOL) {
580 printf ("usage: %s\n", val);
581 skip_to_semi (cfile);
582 break;
585 if (!connected) {
586 printf ("not connected.\n");
587 skip_to_semi (cfile);
588 break;
591 if (!oh) {
592 printf ("you must make a new object first!\n");
593 skip_to_semi (cfile);
594 break;
597 if (i == TOKEN_CREATE)
598 i = DHCPCTL_CREATE | DHCPCTL_EXCL;
599 else
600 i = 0;
602 status = dhcpctl_open_object (oh, connection, i);
603 if (status == ISC_R_SUCCESS)
604 status = dhcpctl_wait_for_completion
605 (oh, &waitstatus);
606 if (status == ISC_R_SUCCESS)
607 status = waitstatus;
608 if (status != ISC_R_SUCCESS) {
609 printf ("can't open object: %s\n",
610 isc_result_totext (status));
611 break;
614 break;
616 case UPDATE:
617 token = next_token (&val, (unsigned *)0, cfile);
618 if (token != END_OF_FILE && token != EOL) {
619 printf ("usage: %s\n", val);
620 skip_to_semi (cfile);
621 break;
624 if (!connected) {
625 printf ("not connected.\n");
626 skip_to_semi (cfile);
627 break;
630 if (!oh) {
631 printf ("you haven't opened an object yet!\n");
632 skip_to_semi (cfile);
633 break;
636 status = dhcpctl_object_update(connection, oh);
637 if (status == ISC_R_SUCCESS)
638 status = dhcpctl_wait_for_completion
639 (oh, &waitstatus);
640 if (status == ISC_R_SUCCESS)
641 status = waitstatus;
642 if (status != ISC_R_SUCCESS) {
643 printf ("can't update object: %s\n",
644 isc_result_totext (status));
645 break;
648 break;
650 case REMOVE:
651 token = next_token (&val, (unsigned *)0, cfile);
652 if (token != END_OF_FILE && token != EOL) {
653 printf ("usage: remove\n");
654 skip_to_semi (cfile);
655 break;
658 if (!connected) {
659 printf ("not connected.\n");
660 break;
663 if (!oh) {
664 printf ("no object.\n");
665 break;
668 status = dhcpctl_object_remove(connection, oh);
669 if (status == ISC_R_SUCCESS)
670 status = dhcpctl_wait_for_completion
671 (oh, &waitstatus);
672 if (status == ISC_R_SUCCESS)
673 status = waitstatus;
674 if (status != ISC_R_SUCCESS) {
675 printf ("can't destroy object: %s\n",
676 isc_result_totext (status));
677 break;
679 omapi_object_dereference (&oh, MDL);
680 break;
682 case REFRESH:
683 token = next_token (&val, (unsigned *)0, cfile);
684 if (token != END_OF_FILE && token != EOL) {
685 printf ("usage: refresh\n");
686 skip_to_semi (cfile);
687 break;
690 if (!connected) {
691 printf ("not connected.\n");
692 break;
695 if (!oh) {
696 printf ("no object.\n");
697 break;
700 status = dhcpctl_object_refresh(connection, oh);
701 if (status == ISC_R_SUCCESS)
702 status = dhcpctl_wait_for_completion
703 (oh, &waitstatus);
704 if (status == ISC_R_SUCCESS)
705 status = waitstatus;
706 if (status != ISC_R_SUCCESS) {
707 printf ("can't refresh object: %s\n",
708 isc_result_totext (status));
709 break;
712 break;
714 end_parse (&cfile);
715 } while (1);
717 exit (0);
720 /* Sigh */
721 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
722 control_object_state_t newstate)
724 return ISC_R_SUCCESS;