Annotation of embedaddon/dhcp/dhcpctl/omshell.c, revision 1.1
1.1 ! misho 1: /* omshell.c
! 2:
! 3: Examine and modify omapi objects. */
! 4:
! 5: /*
! 6: * Copyright (c) 2009-2011 by Internet Systems Consortium, Inc. ("ISC")
! 7: * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
! 8: * Copyright (c) 2001-2003 by Internet Software Consortium
! 9: *
! 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.
! 13: *
! 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.
! 21: *
! 22: * Internet Systems Consortium, Inc.
! 23: * 950 Charter Street
! 24: * Redwood City, CA 94063
! 25: * <info@isc.org>
! 26: * https://www.isc.org/
! 27: *
! 28: * This software has been written for Internet Systems Consortium
! 29: * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
! 30: * To learn more about Internet Systems Consortium, see
! 31: * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
! 32: * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
! 33: * ``http://www.nominum.com''.
! 34: */
! 35:
! 36: #include "config.h"
! 37:
! 38: #include <time.h>
! 39: #include <sys/time.h>
! 40: #include <stdio.h>
! 41: #include <stdlib.h>
! 42: #include <stdarg.h>
! 43: #include <string.h>
! 44: #include <isc-dhcp/result.h>
! 45: #include <syslog.h>
! 46: #include "dhcpctl.h"
! 47: #include "dhcpd.h"
! 48:
! 49: /* Fixups */
! 50: isc_result_t find_class (struct class **c, const char *n, const char *f, int l)
! 51: {
! 52: return 0;
! 53: }
! 54: int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag)
! 55: {
! 56: return 0;
! 57: }
! 58: void dhcp (struct packet *packet) { }
! 59: void bootp (struct packet *packet) { }
! 60:
! 61: #ifdef DHCPv6
! 62: /* XXX: should we warn or something here? */
! 63: void dhcpv6(struct packet *packet) { }
! 64: #endif /* DHCPv6 */
! 65:
! 66: int check_collection (struct packet *p, struct lease *l, struct collection *c)
! 67: {
! 68: return 0;
! 69: }
! 70: void classify (struct packet *packet, struct class *class) { }
! 71:
! 72: static void usage (char *s) {
! 73: fprintf (stderr, "Usage: %s\n", s);
! 74: exit (1);
! 75: }
! 76:
! 77: static 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:
! 84: int
! 85: main(int argc, char **argv) {
! 86: isc_result_t status, waitstatus;
! 87: dhcpctl_handle connection;
! 88: dhcpctl_handle authenticator;
! 89: dhcpctl_handle oh;
! 90: struct data_string secret;
! 91: const char *name = 0, *algorithm = "hmac-md5";
! 92: int i;
! 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;
! 98: char *s;
! 99: char buf[1024];
! 100: char s1[1024];
! 101: int connected = 0;
! 102: char hex_buf[1025];
! 103:
! 104: for (i = 1; i < argc; i++) {
! 105: usage(argv[0]);
! 106: }
! 107:
! 108: /* Initially, log errors to stderr as well as to syslogd. */
! 109: openlog ("omshell", LOG_NDELAY, DHCPD_LOG_FACILITY);
! 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:
! 117: memset (&oh, 0, sizeof oh);
! 118:
! 119: do {
! 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:
! 128: printf ("obj: ");
! 129:
! 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:
! 141: if (!g -> values [i])
! 142: continue;
! 143:
! 144: printf ("%.*s = ", (int)v -> name -> len,
! 145: v -> name -> value);
! 146:
! 147: if (!v -> value) {
! 148: printf ("<null>\n");
! 149: continue;
! 150: }
! 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:
! 164: print_hex_or_string(v->value->u.buffer.len,
! 165: v->value->u.buffer.value,
! 166: sizeof(hex_buf), hex_buf);
! 167: printf("%s\n", hex_buf);
! 168: break;
! 169:
! 170: case omapi_datatype_object:
! 171: printf ("<obj>\n");
! 172: break;
! 173: }
! 174: }
! 175: }
! 176:
! 177: fputs ("> ", stdout);
! 178: fflush (stdout);
! 179: if (fgets (buf, sizeof(buf), stdin) == NULL)
! 180: break;
! 181:
! 182: status = new_parse (&cfile, -1, buf, strlen(buf), "<STDIN>", 1);
! 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 ENDOFLINE: /* EOL: */
! 194: break;
! 195:
! 196: case TOKEN_HELP:
! 197: case QUESTIONMARK: /* '?': */
! 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");
! 207: printf (" update\n");
! 208: printf (" unset <name>\n");
! 209: printf (" refresh\n");
! 210: printf (" remove\n");
! 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 {
! 222: printf ("unknown service name: %s\n", val);
! 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:
! 240: case TOKEN_SERVER:
! 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);
! 252: break;
! 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) {
! 301: printf ("no memory to store server name.\n");
! 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:
! 317: token = next_token (&val, (unsigned *)0, cfile);
! 318: if (!is_identifier (token)) {
! 319: printf ("usage: key <name> <value>\n");
! 320: skip_to_semi (cfile);
! 321: break;
! 322: }
! 323: s = dmalloc (strlen (val) + 1, MDL);
! 324: if (!s) {
! 325: printf ("no memory for key name.\n");
! 326: skip_to_semi (cfile);
! 327: break;
! 328: }
! 329: strcpy (s, val);
! 330: name = s;
! 331: memset (&secret, 0, sizeof secret);
! 332: if (!parse_base64 (&secret, cfile)) {
! 333: skip_to_semi (cfile);
! 334: break;
! 335: }
! 336: token = next_token (&val, (unsigned *)0, cfile);
! 337: if (token != END_OF_FILE && token != EOL) {
! 338: printf ("usage: key <name> <secret>\n");
! 339: skip_to_semi (cfile);
! 340: break;
! 341: }
! 342: break;
! 343:
! 344: case CONNECT:
! 345: token = next_token (&val, (unsigned *)0, cfile);
! 346: if (token != END_OF_FILE && token != EOL) {
! 347: printf ("usage: connect\n");
! 348: skip_to_semi (cfile);
! 349: break;
! 350: }
! 351:
! 352: authenticator = dhcpctl_null_handle;
! 353:
! 354: if (name) {
! 355: status = dhcpctl_new_authenticator (&authenticator,
! 356: name, algorithm,
! 357: secret.data,
! 358: secret.len);
! 359:
! 360: if (status != ISC_R_SUCCESS) {
! 361: fprintf (stderr,
! 362: "Cannot create authenticator: %s\n",
! 363: isc_result_totext (status));
! 364: break;
! 365: }
! 366: }
! 367:
! 368: memset (&connection, 0, sizeof connection);
! 369: status = dhcpctl_connect (&connection,
! 370: server, port, authenticator);
! 371: if (status != ISC_R_SUCCESS) {
! 372: fprintf (stderr, "dhcpctl_connect: %s\n",
! 373: isc_result_totext (status));
! 374: break;
! 375: }
! 376: connected = 1;
! 377: break;
! 378:
! 379: case TOKEN_NEW:
! 380: token = next_token (&val, (unsigned *)0, cfile);
! 381: if ((!is_identifier (token) && token != STRING)) {
! 382: printf ("usage: new <object-type>\n");
! 383: break;
! 384: }
! 385:
! 386: if (oh) {
! 387: printf ("an object is already open.\n");
! 388: skip_to_semi (cfile);
! 389: break;
! 390: }
! 391:
! 392: if (!connected) {
! 393: printf ("not connected.\n");
! 394: skip_to_semi (cfile);
! 395: break;
! 396: }
! 397:
! 398: status = dhcpctl_new_object (&oh, connection, val);
! 399: if (status != ISC_R_SUCCESS) {
! 400: printf ("can't create object: %s\n",
! 401: isc_result_totext (status));
! 402: break;
! 403: }
! 404:
! 405: token = next_token (&val, (unsigned *)0, cfile);
! 406: if (token != END_OF_FILE && token != EOL) {
! 407: printf ("usage: new <object-type>\n");
! 408: skip_to_semi (cfile);
! 409: break;
! 410: }
! 411: break;
! 412:
! 413: case TOKEN_CLOSE:
! 414: token = next_token (&val, (unsigned *)0, cfile);
! 415: if (token != END_OF_FILE && token != EOL) {
! 416: printf ("usage: close\n");
! 417: skip_to_semi (cfile);
! 418: break;
! 419: }
! 420:
! 421: if (!connected) {
! 422: printf ("not connected.\n");
! 423: skip_to_semi (cfile);
! 424: break;
! 425: }
! 426:
! 427: if (!oh) {
! 428: printf ("not open.\n");
! 429: skip_to_semi (cfile);
! 430: break;
! 431: }
! 432: omapi_object_dereference (&oh, MDL);
! 433:
! 434: break;
! 435:
! 436: case TOKEN_SET:
! 437: token = next_token (&val, (unsigned *)0, cfile);
! 438:
! 439: if ((!is_identifier (token) && token != STRING)) {
! 440: set_usage:
! 441: printf ("usage: set <name> = <value>\n");
! 442: skip_to_semi (cfile);
! 443: break;
! 444: }
! 445:
! 446: if (oh == NULL) {
! 447: printf ("no open object.\n");
! 448: skip_to_semi (cfile);
! 449: break;
! 450: }
! 451:
! 452: if (!connected) {
! 453: printf ("not connected.\n");
! 454: skip_to_semi (cfile);
! 455: break;
! 456: }
! 457:
! 458: s1[0] = '\0';
! 459: strncat (s1, val, sizeof(s1)-1);
! 460:
! 461: token = next_token (&val, (unsigned *)0, cfile);
! 462: if (token != EQUAL)
! 463: goto set_usage;
! 464:
! 465: token = next_token (&val, (unsigned *)0, cfile);
! 466: switch (token) {
! 467: case STRING:
! 468: dhcpctl_set_string_value (oh, val, s1);
! 469: token = next_token (&val, (unsigned *)0, cfile);
! 470: break;
! 471:
! 472: case NUMBER:
! 473: strcpy (buf, val);
! 474: token = peek_token (&val, (unsigned *)0, cfile);
! 475: /* Colon-separated hex list? */
! 476: if (token == COLON)
! 477: goto cshl;
! 478: else if (token == DOT) {
! 479: s = buf;
! 480: val = buf;
! 481: do {
! 482: int intval = atoi (val);
! 483: if (intval > 255) {
! 484: parse_warn (cfile,
! 485: "dotted octet > 255: %s",
! 486: val);
! 487: skip_to_semi (cfile);
! 488: goto badnum;
! 489: }
! 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;
! 504: }
! 505: dhcpctl_set_int_value (oh, atoi (buf), s1);
! 506: token = next_token (&val, (unsigned *)0, cfile);
! 507: badnum:
! 508: break;
! 509:
! 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;
! 530:
! 531: default:
! 532: printf ("invalid value.\n");
! 533: skip_to_semi (cfile);
! 534: }
! 535:
! 536: if (token != END_OF_FILE && token != EOL)
! 537: goto set_usage;
! 538: break;
! 539:
! 540: case UNSET:
! 541: token = next_token (&val, (unsigned *)0, cfile);
! 542:
! 543: if ((!is_identifier (token) && token != STRING)) {
! 544: unset_usage:
! 545: printf ("usage: unset <name>\n");
! 546: skip_to_semi (cfile);
! 547: break;
! 548: }
! 549:
! 550: if (!oh) {
! 551: printf ("no open object.\n");
! 552: skip_to_semi (cfile);
! 553: break;
! 554: }
! 555:
! 556: if (!connected) {
! 557: printf ("not connected.\n");
! 558: skip_to_semi (cfile);
! 559: break;
! 560: }
! 561:
! 562: s1[0] = '\0';
! 563: strncat (s1, val, sizeof(s1)-1);
! 564:
! 565: token = next_token (&val, (unsigned *)0, cfile);
! 566: if (token != END_OF_FILE && token != EOL)
! 567: goto unset_usage;
! 568:
! 569: dhcpctl_set_null_value (oh, s1);
! 570: break;
! 571:
! 572:
! 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;
! 581: }
! 582:
! 583: if (!connected) {
! 584: printf ("not connected.\n");
! 585: skip_to_semi (cfile);
! 586: break;
! 587: }
! 588:
! 589: if (!oh) {
! 590: printf ("you must make a new object first!\n");
! 591: skip_to_semi (cfile);
! 592: break;
! 593: }
! 594:
! 595: if (i == TOKEN_CREATE)
! 596: i = DHCPCTL_CREATE | DHCPCTL_EXCL;
! 597: else
! 598: i = 0;
! 599:
! 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;
! 610: }
! 611:
! 612: break;
! 613:
! 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;
! 620: }
! 621:
! 622: if (!connected) {
! 623: printf ("not connected.\n");
! 624: skip_to_semi (cfile);
! 625: break;
! 626: }
! 627:
! 628: if (!oh) {
! 629: printf ("you haven't opened an object yet!\n");
! 630: skip_to_semi (cfile);
! 631: break;
! 632: }
! 633:
! 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;
! 644: }
! 645:
! 646: break;
! 647:
! 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;
! 654: }
! 655:
! 656: if (!connected) {
! 657: printf ("not connected.\n");
! 658: break;
! 659: }
! 660:
! 661: if (!oh) {
! 662: printf ("no object.\n");
! 663: break;
! 664: }
! 665:
! 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;
! 676: }
! 677: omapi_object_dereference (&oh, MDL);
! 678: break;
! 679:
! 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;
! 686: }
! 687:
! 688: if (!connected) {
! 689: printf ("not connected.\n");
! 690: break;
! 691: }
! 692:
! 693: if (!oh) {
! 694: printf ("no object.\n");
! 695: break;
! 696: }
! 697:
! 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;
! 708: }
! 709:
! 710: break;
! 711: }
! 712: end_parse (&cfile);
! 713: } while (1);
! 714:
! 715: exit (0);
! 716: }
! 717:
! 718: /* Sigh */
! 719: isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
! 720: control_object_state_t newstate)
! 721: {
! 722: return ISC_R_SUCCESS;
! 723: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>