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