00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "config.h"
00031
00032 #include <time.h>
00033 #include <sys/time.h>
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <stdarg.h>
00037 #include <string.h>
00038
00039 #include <syslog.h>
00040 #include "dhcpctl.h"
00041 #include "dhcpd.h"
00042
00043
00044 isc_result_t find_class (struct class **c, const char *n, const char *f, int l)
00045 {
00046 return 0;
00047 }
00048 int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag)
00049 {
00050 return 0;
00051 }
00052 void dhcp (struct packet *packet) { }
00053 void bootp (struct packet *packet) { }
00054
00055 #ifdef DHCPv6
00056
00057 void dhcpv6(struct packet *packet) { }
00058 #endif
00059
00060 int check_collection (struct packet *p, struct lease *l, struct collection *c)
00061 {
00062 return 0;
00063 }
00064 void classify (struct packet *packet, struct class *class) { }
00065
00066 static void usage (char *s) {
00067 fprintf (stderr, "Usage: %s\n", s);
00068 exit (1);
00069 }
00070
00071 static void check (isc_result_t status, const char *func) {
00072 if (status != ISC_R_SUCCESS) {
00073 fprintf (stderr, "%s: %s\n", func, isc_result_totext (status));
00074 exit (1);
00075 }
00076 }
00077
00078 int
00079 main(int argc, char **argv) {
00080 isc_result_t status, waitstatus;
00081 dhcpctl_handle connection;
00082 dhcpctl_handle authenticator;
00083 dhcpctl_handle oh;
00084 struct data_string secret;
00085 const char *name = 0, *algorithm = "hmac-md5";
00086 int i;
00087 int port = 7911;
00088 const char *server = "127.0.0.1";
00089 struct parse *cfile;
00090 enum dhcp_token token;
00091 const char *val;
00092 char *s;
00093 char buf[1024];
00094 char s1[1024];
00095 int connected = 0;
00096 char hex_buf[1025];
00097
00098 for (i = 1; i < argc; i++) {
00099 usage(argv[0]);
00100 }
00101
00102
00103 openlog ("omshell", LOG_NDELAY, DHCPD_LOG_FACILITY);
00104 status = dhcpctl_initialize ();
00105 if (status != ISC_R_SUCCESS) {
00106 fprintf (stderr, "dhcpctl_initialize: %s\n",
00107 isc_result_totext (status));
00108 exit (1);
00109 }
00110
00111 memset (&oh, 0, sizeof oh);
00112
00113 do {
00114 if (!connected) {
00115 } else if (oh == NULL) {
00116 printf ("obj: <null>\n");
00117 } else {
00118 dhcpctl_remote_object_t *r = (dhcpctl_remote_object_t *)oh;
00119 omapi_generic_object_t *g =
00120 (omapi_generic_object_t *)(r -> inner);
00121
00122 printf ("obj: ");
00123
00124 if (r -> rtype -> type != omapi_datatype_string) {
00125 printf ("?\n");
00126 } else {
00127 printf ("%.*s\n",
00128 (int)(r -> rtype -> u . buffer . len),
00129 r -> rtype -> u . buffer . value);
00130 }
00131
00132 for (i = 0; i < g -> nvalues; i++) {
00133 omapi_value_t *v = g -> values [i];
00134
00135 if (!g -> values [i])
00136 continue;
00137
00138 printf ("%.*s = ", (int)v -> name -> len,
00139 v -> name -> value);
00140
00141 if (!v -> value) {
00142 printf ("<null>\n");
00143 continue;
00144 }
00145 switch (v -> value -> type) {
00146 case omapi_datatype_int:
00147 printf ("%d\n",
00148 v -> value -> u . integer);
00149 break;
00150
00151 case omapi_datatype_string:
00152 printf ("\"%.*s\"\n",
00153 (int) v -> value -> u.buffer.len,
00154 v -> value -> u.buffer.value);
00155 break;
00156
00157 case omapi_datatype_data:
00158 print_hex_or_string(v->value->u.buffer.len,
00159 v->value->u.buffer.value,
00160 sizeof(hex_buf), hex_buf);
00161 printf("%s\n", hex_buf);
00162 break;
00163
00164 case omapi_datatype_object:
00165 printf ("<obj>\n");
00166 break;
00167 }
00168 }
00169 }
00170
00171 fputs ("> ", stdout);
00172 fflush (stdout);
00173 if (fgets (buf, sizeof(buf), stdin) == NULL)
00174 break;
00175
00176 status = new_parse (&cfile, -1, buf, strlen(buf), "<STDIN>", 1);
00177 check(status, "new_parse()");
00178
00179 token = next_token (&val, (unsigned *)0, cfile);
00180 switch (token) {
00181 default:
00182 parse_warn (cfile, "unknown token: %s", val);
00183 skip_to_semi (cfile);
00184 break;
00185
00186 case END_OF_FILE:
00187 case ENDOFLINE:
00188 break;
00189
00190 case TOKEN_HELP:
00191 case QUESTIONMARK:
00192 printf ("Commands:\n");
00193 printf (" port <server omapi port>\n");
00194 printf (" server <server address>\n");
00195 printf (" key <key name> <key value>\n");
00196 printf (" connect\n");
00197 printf (" new <object-type>\n");
00198 printf (" set <name> = <value>\n");
00199 printf (" create\n");
00200 printf (" open\n");
00201 printf (" update\n");
00202 printf (" unset <name>\n");
00203 printf (" refresh\n");
00204 printf (" remove\n");
00205 skip_to_semi (cfile);
00206 break;
00207
00208 case PORT:
00209 token = next_token (&val, (unsigned *)0, cfile);
00210 if (is_identifier (token)) {
00211 struct servent *se;
00212 se = getservbyname (val, "tcp");
00213 if (se)
00214 port = ntohs (se -> s_port);
00215 else {
00216 printf ("unknown service name: %s\n", val);
00217 break;
00218 }
00219 } else if (token == NUMBER) {
00220 port = atoi (val);
00221 } else {
00222 skip_to_semi (cfile);
00223 printf ("usage: port <port>\n");
00224 break;
00225 }
00226 token = next_token (&val, (unsigned *)0, cfile);
00227 if (token != END_OF_FILE && token != EOL) {
00228 printf ("usage: port <server>\n");
00229 skip_to_semi (cfile);
00230 break;
00231 }
00232 break;
00233
00234 case TOKEN_SERVER:
00235 token = next_token (&val, (unsigned *)0, cfile);
00236 if (token == NUMBER) {
00237 int alen = (sizeof buf) - 1;
00238 int len;
00239
00240 s = &buf [0];
00241 len = strlen (val);
00242 if (len + 1 > alen) {
00243 baddq:
00244 printf ("usage: server <server>\n");
00245 skip_to_semi (cfile);
00246 break;
00247 } strcpy (buf, val);
00248 s += len;
00249 token = next_token (&val, (unsigned *)0, cfile);
00250 if (token != DOT)
00251 goto baddq;
00252 *s++ = '.';
00253 token = next_token (&val, (unsigned *)0, cfile);
00254 if (token != NUMBER)
00255 goto baddq;
00256 len = strlen (val);
00257 if (len + 1 > alen)
00258 goto baddq;
00259 strcpy (s, val);
00260 s += len;
00261 token = next_token (&val, (unsigned *)0, cfile);
00262 if (token != DOT)
00263 goto baddq;
00264 *s++ = '.';
00265 token = next_token (&val, (unsigned *)0, cfile);
00266 if (token != NUMBER)
00267 goto baddq;
00268 len = strlen (val);
00269 if (len + 1 > alen)
00270 goto baddq;
00271 strcpy (s, val);
00272 s += len;
00273 token = next_token (&val, (unsigned *)0, cfile);
00274 if (token != DOT)
00275 goto baddq;
00276 *s++ = '.';
00277 token = next_token (&val, (unsigned *)0, cfile);
00278 if (token != NUMBER)
00279 goto baddq;
00280 len = strlen (val);
00281 if (len + 1 > alen)
00282 goto baddq;
00283 strcpy (s, val);
00284 val = &buf [0];
00285 } else if (is_identifier (token)) {
00286
00287 } else {
00288 printf ("usage: server <server>\n");
00289 skip_to_semi (cfile);
00290 break;
00291 }
00292
00293 s = dmalloc (strlen (val) + 1, MDL);
00294 if (!server) {
00295 printf ("no memory to store server name.\n");
00296 skip_to_semi (cfile);
00297 break;
00298 }
00299 strcpy (s, val);
00300 server = s;
00301
00302 token = next_token (&val, (unsigned *)0, cfile);
00303 if (token != END_OF_FILE && token != EOL) {
00304 printf ("usage: server <server>\n");
00305 skip_to_semi (cfile);
00306 break;
00307 }
00308 break;
00309
00310 case KEY:
00311 token = peek_token(&val, (unsigned *)0, cfile);
00312 if (token == STRING) {
00313 token = next_token (&val, (unsigned *)0, cfile);
00314 if (!is_identifier (token)) {
00315 printf ("usage: key <name> <value>\n");
00316 skip_to_semi (cfile);
00317 break;
00318 }
00319 s = dmalloc (strlen (val) + 1, MDL);
00320 if (!s) {
00321 printf ("no memory for key name.\n");
00322 skip_to_semi (cfile);
00323 break;
00324 }
00325 strcpy (s, val);
00326 } else {
00327 s = parse_host_name(cfile);
00328 if (s == NULL) {
00329 printf ("usage: key <name> <value>\n");
00330 skip_to_semi(cfile);
00331 break;
00332 }
00333 }
00334 name = s;
00335
00336 memset (&secret, 0, sizeof secret);
00337 if (!parse_base64 (&secret, cfile)) {
00338 skip_to_semi (cfile);
00339 break;
00340 }
00341 token = next_token (&val, (unsigned *)0, cfile);
00342 if (token != END_OF_FILE && token != EOL) {
00343 printf ("usage: key <name> <secret>\n");
00344 skip_to_semi (cfile);
00345 break;
00346 }
00347 break;
00348
00349 case CONNECT:
00350 token = next_token (&val, (unsigned *)0, cfile);
00351 if (token != END_OF_FILE && token != EOL) {
00352 printf ("usage: connect\n");
00353 skip_to_semi (cfile);
00354 break;
00355 }
00356
00357 authenticator = dhcpctl_null_handle;
00358
00359 if (name) {
00360 status = dhcpctl_new_authenticator (&authenticator,
00361 name, algorithm,
00362 secret.data,
00363 secret.len);
00364
00365 if (status != ISC_R_SUCCESS) {
00366 fprintf (stderr,
00367 "Cannot create authenticator: %s\n",
00368 isc_result_totext (status));
00369 break;
00370 }
00371 }
00372
00373 memset (&connection, 0, sizeof connection);
00374 status = dhcpctl_connect (&connection,
00375 server, port, authenticator);
00376 if (status != ISC_R_SUCCESS) {
00377 fprintf (stderr, "dhcpctl_connect: %s\n",
00378 isc_result_totext (status));
00379 break;
00380 }
00381 connected = 1;
00382 break;
00383
00384 case TOKEN_NEW:
00385 token = next_token (&val, (unsigned *)0, cfile);
00386 if ((!is_identifier (token) && token != STRING)) {
00387 printf ("usage: new <object-type>\n");
00388 break;
00389 }
00390
00391 if (oh) {
00392 printf ("an object is already open.\n");
00393 skip_to_semi (cfile);
00394 break;
00395 }
00396
00397 if (!connected) {
00398 printf ("not connected.\n");
00399 skip_to_semi (cfile);
00400 break;
00401 }
00402
00403 status = dhcpctl_new_object (&oh, connection, val);
00404 if (status != ISC_R_SUCCESS) {
00405 printf ("can't create object: %s\n",
00406 isc_result_totext (status));
00407 break;
00408 }
00409
00410 token = next_token (&val, (unsigned *)0, cfile);
00411 if (token != END_OF_FILE && token != EOL) {
00412 printf ("usage: new <object-type>\n");
00413 skip_to_semi (cfile);
00414 break;
00415 }
00416 break;
00417
00418 case TOKEN_CLOSE:
00419 token = next_token (&val, (unsigned *)0, cfile);
00420 if (token != END_OF_FILE && token != EOL) {
00421 printf ("usage: close\n");
00422 skip_to_semi (cfile);
00423 break;
00424 }
00425
00426 if (!connected) {
00427 printf ("not connected.\n");
00428 skip_to_semi (cfile);
00429 break;
00430 }
00431
00432 if (!oh) {
00433 printf ("not open.\n");
00434 skip_to_semi (cfile);
00435 break;
00436 }
00437 omapi_object_dereference (&oh, MDL);
00438
00439 break;
00440
00441 case TOKEN_SET:
00442 token = next_token (&val, (unsigned *)0, cfile);
00443
00444 if ((!is_identifier (token) && token != STRING)) {
00445 set_usage:
00446 printf ("usage: set <name> = <value>\n");
00447 skip_to_semi (cfile);
00448 break;
00449 }
00450
00451 if (oh == NULL) {
00452 printf ("no open object.\n");
00453 skip_to_semi (cfile);
00454 break;
00455 }
00456
00457 if (!connected) {
00458 printf ("not connected.\n");
00459 skip_to_semi (cfile);
00460 break;
00461 }
00462
00463 #ifdef HAVE_STRLCPY
00464 strlcpy (s1, val, sizeof(s1));
00465 #else
00466 s1[0] = 0;
00467 strncat (s1, val, sizeof(s1)-strlen(s1)-1);
00468 #endif
00469
00470 token = next_token (&val, (unsigned *)0, cfile);
00471 if (token != EQUAL)
00472 goto set_usage;
00473
00474 token = next_token (&val, (unsigned *)0, cfile);
00475 switch (token) {
00476 case STRING:
00477 dhcpctl_set_string_value (oh, val, s1);
00478 token = next_token (&val, (unsigned *)0, cfile);
00479 break;
00480
00481 case NUMBER:
00482 strcpy (buf, val);
00483 token = peek_token (&val, (unsigned *)0, cfile);
00484
00485 if (token == COLON)
00486 goto cshl;
00487 else if (token == DOT) {
00488 s = buf;
00489 val = buf;
00490 do {
00491 int intval = atoi (val);
00492 if (intval > 255) {
00493 parse_warn (cfile,
00494 "dotted octet > 255: %s",
00495 val);
00496 skip_to_semi (cfile);
00497 goto badnum;
00498 }
00499 *s++ = intval;
00500 token = next_token (&val,
00501 (unsigned *)0, cfile);
00502 if (token != DOT)
00503 break;
00504
00505 while ((token = next_token (&val,
00506 (unsigned *)0, cfile)) == DOT)
00507 *s++ = 0;
00508 } while (token == NUMBER);
00509 dhcpctl_set_data_value (oh, buf,
00510 (unsigned)(s - buf),
00511 s1);
00512 break;
00513 }
00514 dhcpctl_set_int_value (oh, atoi (buf), s1);
00515 token = next_token (&val, (unsigned *)0, cfile);
00516 badnum:
00517 break;
00518
00519 case NUMBER_OR_NAME:
00520 strcpy (buf, val);
00521 cshl:
00522 s = buf;
00523 val = buf;
00524 do {
00525 convert_num (cfile, (unsigned char *)s,
00526 val, 16, 8);
00527 ++s;
00528 token = next_token (&val,
00529 (unsigned *)0, cfile);
00530 if (token != COLON)
00531 break;
00532 token = next_token (&val,
00533 (unsigned *)0, cfile);
00534 } while (token == NUMBER ||
00535 token == NUMBER_OR_NAME);
00536 dhcpctl_set_data_value (oh, buf,
00537 (unsigned)(s - buf), s1);
00538 break;
00539
00540 default:
00541 printf ("invalid value.\n");
00542 skip_to_semi (cfile);
00543 }
00544
00545 if (token != END_OF_FILE && token != EOL)
00546 goto set_usage;
00547 break;
00548
00549 case UNSET:
00550 token = next_token (&val, (unsigned *)0, cfile);
00551
00552 if ((!is_identifier (token) && token != STRING)) {
00553 unset_usage:
00554 printf ("usage: unset <name>\n");
00555 skip_to_semi (cfile);
00556 break;
00557 }
00558
00559 if (!oh) {
00560 printf ("no open object.\n");
00561 skip_to_semi (cfile);
00562 break;
00563 }
00564
00565 if (!connected) {
00566 printf ("not connected.\n");
00567 skip_to_semi (cfile);
00568 break;
00569 }
00570
00571 #if HAVE_STRLCPY
00572 strlcpy (s1, val, sizeof(s1));
00573 #else
00574 s1[0] = 0;
00575 strncat (s1, val, sizeof(s1)-strlen(s1)-1);
00576 #endif
00577
00578 token = next_token (&val, (unsigned *)0, cfile);
00579 if (token != END_OF_FILE && token != EOL)
00580 goto unset_usage;
00581
00582 dhcpctl_set_null_value (oh, s1);
00583 break;
00584
00585
00586 case TOKEN_CREATE:
00587 case TOKEN_OPEN:
00588 i = token;
00589 token = next_token (&val, (unsigned *)0, cfile);
00590 if (token != END_OF_FILE && token != EOL) {
00591 printf ("usage: %s\n", val);
00592 skip_to_semi (cfile);
00593 break;
00594 }
00595
00596 if (!connected) {
00597 printf ("not connected.\n");
00598 skip_to_semi (cfile);
00599 break;
00600 }
00601
00602 if (!oh) {
00603 printf ("you must make a new object first!\n");
00604 skip_to_semi (cfile);
00605 break;
00606 }
00607
00608 if (i == TOKEN_CREATE)
00609 i = DHCPCTL_CREATE | DHCPCTL_EXCL;
00610 else
00611 i = 0;
00612
00613 status = dhcpctl_open_object (oh, connection, i);
00614 if (status == ISC_R_SUCCESS)
00615 status = dhcpctl_wait_for_completion
00616 (oh, &waitstatus);
00617 if (status == ISC_R_SUCCESS)
00618 status = waitstatus;
00619 if (status != ISC_R_SUCCESS) {
00620 printf ("can't open object: %s\n",
00621 isc_result_totext (status));
00622 break;
00623 }
00624
00625 break;
00626
00627 case UPDATE:
00628 token = next_token (&val, (unsigned *)0, cfile);
00629 if (token != END_OF_FILE && token != EOL) {
00630 printf ("usage: %s\n", val);
00631 skip_to_semi (cfile);
00632 break;
00633 }
00634
00635 if (!connected) {
00636 printf ("not connected.\n");
00637 skip_to_semi (cfile);
00638 break;
00639 }
00640
00641 if (!oh) {
00642 printf ("you haven't opened an object yet!\n");
00643 skip_to_semi (cfile);
00644 break;
00645 }
00646
00647 status = dhcpctl_object_update(connection, oh);
00648 if (status == ISC_R_SUCCESS)
00649 status = dhcpctl_wait_for_completion
00650 (oh, &waitstatus);
00651 if (status == ISC_R_SUCCESS)
00652 status = waitstatus;
00653 if (status != ISC_R_SUCCESS) {
00654 printf ("can't update object: %s\n",
00655 isc_result_totext (status));
00656 break;
00657 }
00658
00659 break;
00660
00661 case REMOVE:
00662 token = next_token (&val, (unsigned *)0, cfile);
00663 if (token != END_OF_FILE && token != EOL) {
00664 printf ("usage: remove\n");
00665 skip_to_semi (cfile);
00666 break;
00667 }
00668
00669 if (!connected) {
00670 printf ("not connected.\n");
00671 break;
00672 }
00673
00674 if (!oh) {
00675 printf ("no object.\n");
00676 break;
00677 }
00678
00679 status = dhcpctl_object_remove(connection, oh);
00680 if (status == ISC_R_SUCCESS)
00681 status = dhcpctl_wait_for_completion
00682 (oh, &waitstatus);
00683 if (status == ISC_R_SUCCESS)
00684 status = waitstatus;
00685 if (status != ISC_R_SUCCESS) {
00686 printf ("can't destroy object: %s\n",
00687 isc_result_totext (status));
00688 break;
00689 }
00690 omapi_object_dereference (&oh, MDL);
00691 break;
00692
00693 case REFRESH:
00694 token = next_token (&val, (unsigned *)0, cfile);
00695 if (token != END_OF_FILE && token != EOL) {
00696 printf ("usage: refresh\n");
00697 skip_to_semi (cfile);
00698 break;
00699 }
00700
00701 if (!connected) {
00702 printf ("not connected.\n");
00703 break;
00704 }
00705
00706 if (!oh) {
00707 printf ("no object.\n");
00708 break;
00709 }
00710
00711 status = dhcpctl_object_refresh(connection, oh);
00712 if (status == ISC_R_SUCCESS)
00713 status = dhcpctl_wait_for_completion
00714 (oh, &waitstatus);
00715 if (status == ISC_R_SUCCESS)
00716 status = waitstatus;
00717 if (status != ISC_R_SUCCESS) {
00718 printf ("can't refresh object: %s\n",
00719 isc_result_totext (status));
00720 break;
00721 }
00722
00723 break;
00724 }
00725 end_parse (&cfile);
00726 } while (1);
00727
00728 exit (0);
00729 }
00730
00731
00732 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
00733 control_object_state_t newstate)
00734 {
00735 if (newstate != server_shutdown)
00736 return ISC_R_SUCCESS;
00737 exit (0);
00738 }