Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / dhcp / dhcpctl / omshell.c
blob811e056b696ff45055da0d5686c20ad2793694f1
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.5 2005/08/11 17:13:21 drochner 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 struct data_string secret;
86 const char *name = 0, *algorithm = "hmac-md5";
87 int i;
88 int port = 7911;
89 const char *server = "127.0.0.1";
90 struct parse *cfile;
91 enum dhcp_token token;
92 const char *val;
93 char *s;
94 char buf[1024];
95 char s1[1024];
96 int connected = 0;
98 for (i = 1; i < argc; i++) {
99 usage(argv[0]);
102 /* Initially, log errors to stderr as well as to syslogd. */
103 #ifdef SYSLOG_4_2
104 openlog ("omshell", LOG_NDELAY);
105 log_priority = DHCPD_LOG_FACILITY;
106 #else
107 openlog ("omshell", LOG_NDELAY, DHCPD_LOG_FACILITY);
108 #endif
109 status = dhcpctl_initialize ();
110 if (status != ISC_R_SUCCESS) {
111 fprintf (stderr, "dhcpctl_initialize: %s\n",
112 isc_result_totext (status));
113 exit (1);
116 memset (&oh, 0, sizeof oh);
118 do {
119 if (!connected) {
120 } else if (oh == NULL) {
121 printf ("obj: <null>\n");
122 } else {
123 dhcpctl_remote_object_t *r = (dhcpctl_remote_object_t *)oh;
124 omapi_generic_object_t *g =
125 (omapi_generic_object_t *)(r -> inner);
127 printf ("obj: ");
129 if (r -> rtype -> type != omapi_datatype_string) {
130 printf ("?\n");
131 } else {
132 printf ("%.*s\n",
133 (int)(r -> rtype -> u . buffer . len),
134 r -> rtype -> u . buffer . value);
137 for (i = 0; i < g -> nvalues; i++) {
138 omapi_value_t *v = g -> values [i];
140 if (!g -> values [i])
141 continue;
143 printf ("%.*s = ", (int)v -> name -> len,
144 v -> name -> value);
146 if (!v -> value) {
147 printf ("<null>\n");
148 continue;
150 switch (v -> value -> type) {
151 case omapi_datatype_int:
152 printf ("%d\n",
153 v -> value -> u . integer);
154 break;
156 case omapi_datatype_string:
157 printf ("\"%.*s\"\n",
158 (int) v -> value -> u.buffer.len,
159 v -> value -> u.buffer.value);
160 break;
162 case omapi_datatype_data:
163 printf ("%s\n",
164 print_hex_1 (v -> value -> u.buffer.len,
165 v -> value -> u.buffer.value,
166 60));
167 break;
169 case omapi_datatype_object:
170 printf ("<obj>\n");
171 break;
176 fputs ("> ", stdout);
177 fflush (stdout);
178 if (fgets (buf, sizeof(buf), stdin) == NULL)
179 break;
181 status = new_parse (&cfile, 0, buf, strlen(buf), "<STDIN>", 1);
182 check(status, "new_parse()");
184 token = next_token (&val, (unsigned *)0, cfile);
185 switch (token) {
186 default:
187 parse_warn (cfile, "unknown token: %s", val);
188 skip_to_semi (cfile);
189 break;
191 case END_OF_FILE:
192 case EOL:
193 break;
195 case TOKEN_HELP:
196 case '?':
197 printf ("Commands:\n");
198 printf (" port <server omapi port>\n");
199 printf (" server <server address>\n");
200 printf (" key <key name> <key value>\n");
201 printf (" connect\n");
202 printf (" new <object-type>\n");
203 printf (" set <name> = <value>\n");
204 printf (" create\n");
205 printf (" open\n");
206 printf (" update\n");
207 printf (" unset <name>\n");
208 printf (" refresh\n");
209 printf (" remove\n");
210 skip_to_semi (cfile);
211 break;
213 case PORT:
214 token = next_token (&val, (unsigned *)0, cfile);
215 if (is_identifier (token)) {
216 struct servent *se;
217 se = getservbyname (val, "tcp");
218 if (se)
219 port = ntohs (se -> s_port);
220 else {
221 printf ("unknown service name: %s\n", val);
222 break;
224 } else if (token == NUMBER) {
225 port = atoi (val);
226 } else {
227 skip_to_semi (cfile);
228 printf ("usage: port <port>\n");
229 break;
231 token = next_token (&val, (unsigned *)0, cfile);
232 if (token != END_OF_FILE && token != EOL) {
233 printf ("usage: port <server>\n");
234 skip_to_semi (cfile);
235 break;
237 break;
239 case SERVER:
240 token = next_token (&val, (unsigned *)0, cfile);
241 if (token == NUMBER) {
242 int alen = (sizeof buf) - 1;
243 int len;
245 s = &buf [0];
246 len = strlen (val);
247 if (len + 1 > alen) {
248 baddq:
249 printf ("usage: server <server>\n");
250 skip_to_semi (cfile);
251 break;
252 } strcpy (buf, val);
253 s += len;
254 token = next_token (&val, (unsigned *)0, cfile);
255 if (token != DOT)
256 goto baddq;
257 *s++ = '.';
258 token = next_token (&val, (unsigned *)0, cfile);
259 if (token != NUMBER)
260 goto baddq;
261 len = strlen (val);
262 if (len + 1 > alen)
263 goto baddq;
264 strcpy (s, val);
265 s += len;
266 token = next_token (&val, (unsigned *)0, cfile);
267 if (token != DOT)
268 goto baddq;
269 *s++ = '.';
270 token = next_token (&val, (unsigned *)0, cfile);
271 if (token != NUMBER)
272 goto baddq;
273 len = strlen (val);
274 if (len + 1 > alen)
275 goto baddq;
276 strcpy (s, val);
277 s += len;
278 token = next_token (&val, (unsigned *)0, cfile);
279 if (token != DOT)
280 goto baddq;
281 *s++ = '.';
282 token = next_token (&val, (unsigned *)0, cfile);
283 if (token != NUMBER)
284 goto baddq;
285 len = strlen (val);
286 if (len + 1 > alen)
287 goto baddq;
288 strcpy (s, val);
289 val = &buf [0];
290 } else if (is_identifier (token)) {
291 /* Use val directly. */
292 } else {
293 printf ("usage: server <server>\n");
294 skip_to_semi (cfile);
295 break;
298 s = dmalloc (strlen (val) + 1, MDL);
299 if (!server) {
300 printf ("no memory to store server name.\n");
301 skip_to_semi (cfile);
302 break;
304 strcpy (s, val);
305 server = s;
307 token = next_token (&val, (unsigned *)0, cfile);
308 if (token != END_OF_FILE && token != EOL) {
309 printf ("usage: server <server>\n");
310 skip_to_semi (cfile);
311 break;
313 break;
315 case KEY:
316 token = next_token (&val, (unsigned *)0, cfile);
317 if (!is_identifier (token)) {
318 printf ("usage: key <name> <value>\n");
319 skip_to_semi (cfile);
320 break;
322 s = dmalloc (strlen (val) + 1, MDL);
323 if (!s) {
324 printf ("no memory for key name.\n");
325 skip_to_semi (cfile);
326 break;
328 strcpy (s, val);
329 name = s;
330 memset (&secret, 0, sizeof secret);
331 if (!parse_base64 (&secret, cfile)) {
332 skip_to_semi (cfile);
333 break;
335 token = next_token (&val, (unsigned *)0, cfile);
336 if (token != END_OF_FILE && token != EOL) {
337 printf ("usage: key <name> <secret>\n");
338 skip_to_semi (cfile);
339 break;
341 break;
343 case CONNECT:
344 token = next_token (&val, (unsigned *)0, cfile);
345 if (token != END_OF_FILE && token != EOL) {
346 printf ("usage: connect\n");
347 skip_to_semi (cfile);
348 break;
351 authenticator = dhcpctl_null_handle;
353 if (name) {
354 status = dhcpctl_new_authenticator (&authenticator,
355 name, algorithm,
356 secret.data,
357 secret.len);
359 if (status != ISC_R_SUCCESS) {
360 fprintf (stderr,
361 "Cannot create authenticator: %s\n",
362 isc_result_totext (status));
363 break;
367 memset (&connection, 0, sizeof connection);
368 status = dhcpctl_connect (&connection,
369 server, port, authenticator);
370 if (status != ISC_R_SUCCESS) {
371 fprintf (stderr, "dhcpctl_connect: %s\n",
372 isc_result_totext (status));
373 break;
375 connected = 1;
376 break;
378 case TOKEN_NEW:
379 token = next_token (&val, (unsigned *)0, cfile);
380 if ((!is_identifier (token) && token != STRING)) {
381 printf ("usage: new <object-type>\n");
382 break;
385 if (oh) {
386 printf ("an object is already open.\n");
387 skip_to_semi (cfile);
388 break;
391 if (!connected) {
392 printf ("not connected.\n");
393 skip_to_semi (cfile);
394 break;
397 status = dhcpctl_new_object (&oh, connection, val);
398 if (status != ISC_R_SUCCESS) {
399 printf ("can't create object: %s\n",
400 isc_result_totext (status));
401 break;
404 token = next_token (&val, (unsigned *)0, cfile);
405 if (token != END_OF_FILE && token != EOL) {
406 printf ("usage: new <object-type>\n");
407 skip_to_semi (cfile);
408 break;
410 break;
412 case TOKEN_CLOSE:
413 token = next_token (&val, (unsigned *)0, cfile);
414 if (token != END_OF_FILE && token != EOL) {
415 printf ("usage: close\n");
416 skip_to_semi (cfile);
417 break;
420 if (!connected) {
421 printf ("not connected.\n");
422 skip_to_semi (cfile);
423 break;
426 if (!oh) {
427 printf ("not open.\n");
428 skip_to_semi (cfile);
429 break;
431 omapi_object_dereference (&oh, MDL);
433 break;
435 case TOKEN_SET:
436 token = next_token (&val, (unsigned *)0, cfile);
438 if ((!is_identifier (token) && token != STRING)) {
439 set_usage:
440 printf ("usage: set <name> = <value>\n");
441 skip_to_semi (cfile);
442 break;
445 if (oh == NULL) {
446 printf ("no open object.\n");
447 skip_to_semi (cfile);
448 break;
451 if (!connected) {
452 printf ("not connected.\n");
453 skip_to_semi (cfile);
454 break;
457 s1[0] = '\0';
458 strncat (s1, val, sizeof(s1)-1);
460 token = next_token (&val, (unsigned *)0, cfile);
461 if (token != EQUAL)
462 goto set_usage;
464 token = next_token (&val, (unsigned *)0, cfile);
465 switch (token) {
466 case STRING:
467 dhcpctl_set_string_value (oh, val, s1);
468 token = next_token (&val, (unsigned *)0, cfile);
469 break;
471 case NUMBER:
472 strcpy (buf, val);
473 token = peek_token (&val, (unsigned *)0, cfile);
474 /* Colon-seperated hex list? */
475 if (token == COLON)
476 goto cshl;
477 else if (token == DOT) {
478 s = buf;
479 val = buf;
480 do {
481 int intval = atoi (val);
482 dotiszero:
483 if (intval > 255) {
484 parse_warn (cfile,
485 "dotted octet > 255: %s",
486 val);
487 skip_to_semi (cfile);
488 goto badnum;
490 *s++ = intval;
491 token = next_token (&val,
492 (unsigned *)0, cfile);
493 if (token != DOT)
494 break;
495 /* DOT is zero. */
496 while ((token = next_token (&val,
497 (unsigned *)0, cfile)) == DOT)
498 *s++ = 0;
499 } while (token == NUMBER);
500 dhcpctl_set_data_value (oh, buf,
501 (unsigned)(s - buf),
502 s1);
503 break;
505 dhcpctl_set_int_value (oh, atoi (buf), s1);
506 token = next_token (&val, (unsigned *)0, cfile);
507 badnum:
508 break;
510 case NUMBER_OR_NAME:
511 strcpy (buf, val);
512 cshl:
513 s = buf;
514 val = buf;
515 do {
516 convert_num (cfile, (unsigned char *)s,
517 val, 16, 8);
518 ++s;
519 token = next_token (&val,
520 (unsigned *)0, cfile);
521 if (token != COLON)
522 break;
523 token = next_token (&val,
524 (unsigned *)0, cfile);
525 } while (token == NUMBER ||
526 token == NUMBER_OR_NAME);
527 dhcpctl_set_data_value (oh, buf,
528 (unsigned)(s - buf), s1);
529 break;
531 default:
532 printf ("invalid value.\n");
533 skip_to_semi (cfile);
536 if (token != END_OF_FILE && token != EOL)
537 goto set_usage;
538 break;
540 case UNSET:
541 token = next_token (&val, (unsigned *)0, cfile);
543 if ((!is_identifier (token) && token != STRING)) {
544 unset_usage:
545 printf ("usage: unset <name>\n");
546 skip_to_semi (cfile);
547 break;
550 if (!oh) {
551 printf ("no open object.\n");
552 skip_to_semi (cfile);
553 break;
556 if (!connected) {
557 printf ("not connected.\n");
558 skip_to_semi (cfile);
559 break;
562 s1[0] = '\0';
563 strncat (s1, val, sizeof(s1)-1);
565 token = next_token (&val, (unsigned *)0, cfile);
566 if (token != END_OF_FILE && token != EOL)
567 goto unset_usage;
569 dhcpctl_set_null_value (oh, s1);
570 break;
573 case TOKEN_CREATE:
574 case TOKEN_OPEN:
575 i = token;
576 token = next_token (&val, (unsigned *)0, cfile);
577 if (token != END_OF_FILE && token != EOL) {
578 printf ("usage: %s\n", val);
579 skip_to_semi (cfile);
580 break;
583 if (!connected) {
584 printf ("not connected.\n");
585 skip_to_semi (cfile);
586 break;
589 if (!oh) {
590 printf ("you must make a new object first!\n");
591 skip_to_semi (cfile);
592 break;
595 if (i == TOKEN_CREATE)
596 i = DHCPCTL_CREATE | DHCPCTL_EXCL;
597 else
598 i = 0;
600 status = dhcpctl_open_object (oh, connection, i);
601 if (status == ISC_R_SUCCESS)
602 status = dhcpctl_wait_for_completion
603 (oh, &waitstatus);
604 if (status == ISC_R_SUCCESS)
605 status = waitstatus;
606 if (status != ISC_R_SUCCESS) {
607 printf ("can't open object: %s\n",
608 isc_result_totext (status));
609 break;
612 break;
614 case UPDATE:
615 token = next_token (&val, (unsigned *)0, cfile);
616 if (token != END_OF_FILE && token != EOL) {
617 printf ("usage: %s\n", val);
618 skip_to_semi (cfile);
619 break;
622 if (!connected) {
623 printf ("not connected.\n");
624 skip_to_semi (cfile);
625 break;
628 if (!oh) {
629 printf ("you haven't opened an object yet!\n");
630 skip_to_semi (cfile);
631 break;
634 status = dhcpctl_object_update(connection, oh);
635 if (status == ISC_R_SUCCESS)
636 status = dhcpctl_wait_for_completion
637 (oh, &waitstatus);
638 if (status == ISC_R_SUCCESS)
639 status = waitstatus;
640 if (status != ISC_R_SUCCESS) {
641 printf ("can't update object: %s\n",
642 isc_result_totext (status));
643 break;
646 break;
648 case REMOVE:
649 token = next_token (&val, (unsigned *)0, cfile);
650 if (token != END_OF_FILE && token != EOL) {
651 printf ("usage: remove\n");
652 skip_to_semi (cfile);
653 break;
656 if (!connected) {
657 printf ("not connected.\n");
658 break;
661 if (!oh) {
662 printf ("no object.\n");
663 break;
666 status = dhcpctl_object_remove(connection, oh);
667 if (status == ISC_R_SUCCESS)
668 status = dhcpctl_wait_for_completion
669 (oh, &waitstatus);
670 if (status == ISC_R_SUCCESS)
671 status = waitstatus;
672 if (status != ISC_R_SUCCESS) {
673 printf ("can't destroy object: %s\n",
674 isc_result_totext (status));
675 break;
677 omapi_object_dereference (&oh, MDL);
678 break;
680 case REFRESH:
681 token = next_token (&val, (unsigned *)0, cfile);
682 if (token != END_OF_FILE && token != EOL) {
683 printf ("usage: refresh\n");
684 skip_to_semi (cfile);
685 break;
688 if (!connected) {
689 printf ("not connected.\n");
690 break;
693 if (!oh) {
694 printf ("no object.\n");
695 break;
698 status = dhcpctl_object_refresh(connection, oh);
699 if (status == ISC_R_SUCCESS)
700 status = dhcpctl_wait_for_completion
701 (oh, &waitstatus);
702 if (status == ISC_R_SUCCESS)
703 status = waitstatus;
704 if (status != ISC_R_SUCCESS) {
705 printf ("can't refresh object: %s\n",
706 isc_result_totext (status));
707 break;
710 break;
712 end_parse (&cfile);
713 } while (1);
715 exit (0);
718 /* Sigh */
719 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
720 control_object_state_t newstate)
722 return ISC_R_SUCCESS;