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