3 Examine and modify omapi objects. */
6 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 2001-2003 by Internet Software Consortium
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Newmarket, NH 03857 USA
25 * https://www.isc.org/
44 isc_result_t
find_class (struct class **c
, const char *n
, const char *f
, int l
)
48 int parse_allow_deny (struct option_cache
**oc
, struct parse
*cfile
, int flag
)
52 void dhcp (struct packet
*packet
) { }
53 void bootp (struct packet
*packet
) { }
56 /* XXX: should we warn or something here? */
57 void dhcpv6(struct packet
*packet
) { }
59 isc_result_t
dhcpv4o6_handler(omapi_object_t
*h
)
61 return ISC_R_NOTIMPLEMENTED
;
66 int check_collection (struct packet
*p
, struct lease
*l
, struct collection
*c
)
70 void classify (struct packet
*packet
, struct class *class) { }
72 static void usage (const char *s
) {
73 fprintf (stderr
, "Usage: %s\n", s
);
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
));
85 main(int argc
, char **argv
) {
86 isc_result_t status
, waitstatus
;
87 dhcpctl_handle connection
;
88 dhcpctl_handle authenticator
;
90 struct data_string secret
;
91 const char *name
= 0, *algorithm
= "hmac-md5";
94 const char *server
= "127.0.0.1";
96 enum dhcp_token token
;
106 progname
= "omshell";
111 for (i
= 1; i
< argc
; i
++) {
112 usage(isc_file_basename(progname
));
115 /* Initially, log errors to stderr as well as to syslogd. */
116 openlog (isc_file_basename(progname
),
117 DHCP_LOG_OPTIONS
, DHCPD_LOG_FACILITY
);
118 status
= dhcpctl_initialize ();
119 if (status
!= ISC_R_SUCCESS
) {
120 fprintf (stderr
, "dhcpctl_initialize: %s\n",
121 isc_result_totext (status
));
125 memset (&oh
, 0, sizeof oh
);
129 } else if (oh
== NULL
) {
130 printf ("obj: <null>\n");
132 dhcpctl_remote_object_t
*r
= (dhcpctl_remote_object_t
*)oh
;
133 omapi_generic_object_t
*g
=
134 (omapi_generic_object_t
*)(r
-> inner
);
138 if (r
-> rtype
-> type
!= omapi_datatype_string
) {
142 (int)(r
-> rtype
-> u
. buffer
. len
),
143 r
-> rtype
-> u
. buffer
. value
);
146 for (i
= 0; i
< g
-> nvalues
; i
++) {
147 omapi_value_t
*v
= g
-> values
[i
];
149 if (!g
-> values
[i
])
152 printf ("%.*s = ", (int)v
-> name
-> len
,
159 switch (v
-> value
-> type
) {
160 case omapi_datatype_int
:
162 v
-> value
-> u
. integer
);
165 case omapi_datatype_string
:
166 printf ("\"%.*s\"\n",
167 (int) v
-> value
-> u
.buffer
.len
,
168 v
-> value
-> u
.buffer
.value
);
171 case omapi_datatype_data
:
172 print_hex_or_string(v
->value
->u
.buffer
.len
,
173 v
->value
->u
.buffer
.value
,
174 sizeof(hex_buf
), hex_buf
);
175 printf("%s\n", hex_buf
);
178 case omapi_datatype_object
:
185 fputs ("> ", stdout
);
187 if (fgets (buf
, sizeof(buf
), stdin
) == NULL
)
190 status
= new_parse (&cfile
, -1, buf
, strlen(buf
), "<STDIN>", 1);
191 check(status
, "new_parse()");
193 token
= next_token (&val
, (unsigned *)0, cfile
);
196 parse_warn (cfile
, "unknown token: %s", val
);
197 skip_to_semi (cfile
);
201 case ENDOFLINE
: /* EOL: */
205 case QUESTIONMARK
: /* '?': */
206 printf ("Commands:\n");
207 printf (" port <server omapi port>\n");
208 printf (" server <server address>\n");
209 printf (" key <key name> <key value>\n");
210 printf (" connect\n");
211 printf (" disconnect\n");
212 printf (" new <object-type>\n");
213 printf (" set <name> = <value>\n");
214 printf (" create\n");
216 printf (" update\n");
217 printf (" unset <name>\n");
218 printf (" refresh\n");
219 printf (" remove\n");
220 skip_to_semi (cfile
);
224 token
= next_token (&val
, (unsigned *)0, cfile
);
225 if (is_identifier (token
)) {
227 se
= getservbyname (val
, "tcp");
229 port
= ntohs (se
-> s_port
);
231 printf ("unknown service name: %s\n", val
);
234 } else if (token
== NUMBER
) {
237 skip_to_semi (cfile
);
238 printf ("usage: port <port>\n");
241 token
= next_token (&val
, (unsigned *)0, cfile
);
242 if (token
!= END_OF_FILE
&& token
!= EOL
) {
243 printf ("usage: port <server>\n");
244 skip_to_semi (cfile
);
250 token
= next_token (&val
, (unsigned *)0, cfile
);
251 if (token
== NUMBER
) {
252 int alen
= (sizeof buf
) - 1;
257 if (len
+ 1 > alen
) {
259 printf ("usage: server <server>\n");
260 skip_to_semi (cfile
);
264 token
= next_token (&val
, (unsigned *)0, cfile
);
268 token
= next_token (&val
, (unsigned *)0, cfile
);
276 token
= next_token (&val
, (unsigned *)0, cfile
);
280 token
= next_token (&val
, (unsigned *)0, cfile
);
288 token
= next_token (&val
, (unsigned *)0, cfile
);
292 token
= next_token (&val
, (unsigned *)0, cfile
);
300 } else if (is_identifier (token
)) {
301 /* Use val directly. */
303 printf ("usage: server <server>\n");
304 skip_to_semi (cfile
);
308 s
= dmalloc (strlen (val
) + 1, MDL
);
310 printf ("no memory to store server name.\n");
311 skip_to_semi (cfile
);
317 token
= next_token (&val
, (unsigned *)0, cfile
);
318 if (token
!= END_OF_FILE
&& token
!= EOL
) {
319 printf ("usage: server <server>\n");
320 skip_to_semi (cfile
);
326 /* Algorithm is optional */
327 token
= next_token (&val
, (unsigned *)0, cfile
);
328 if (token
!= NAME
|| !is_identifier(token
)) {
329 printf ("missing or invalid algorithm name\n");
330 printf ("usage: key-algoritm <algorithm name>\n");
331 skip_to_semi (cfile
);
335 s
= dmalloc (strlen (val
) + 1, MDL
);
337 printf ("no memory for algorithm name.\n");
338 skip_to_semi (cfile
);
345 token
= next_token (&val
, (unsigned *)0, cfile
);
346 if (token
!= END_OF_FILE
&& token
!= EOL
) {
347 printf ("extra information after %s\n", algorithm
);
348 printf ("usage: key-algorithm <algorithm name>\n");
349 skip_to_semi (cfile
);
356 token
= peek_token(&val
, (unsigned *)0, cfile
);
357 if (token
== STRING
) {
358 token
= next_token (&val
, (unsigned *)0, cfile
);
359 if (!is_identifier (token
)) {
360 printf ("usage: key <name> <value>\n");
361 skip_to_semi (cfile
);
364 s
= dmalloc (strlen (val
) + 1, MDL
);
366 printf ("no memory for key name.\n");
367 skip_to_semi (cfile
);
372 s
= parse_host_name(cfile
);
374 printf ("usage: key <name> <value>\n");
381 memset (&secret
, 0, sizeof secret
);
382 if (!parse_base64 (&secret
, cfile
)) {
383 skip_to_semi (cfile
);
387 token
= next_token (&val
, (unsigned *)0, cfile
);
388 if (token
!= END_OF_FILE
&& token
!= EOL
) {
389 printf ("usage: key <name> <value>\n");
390 skip_to_semi (cfile
);
397 token
= next_token (&val
, (unsigned *)0, cfile
);
398 if (token
!= END_OF_FILE
&& token
!= EOL
) {
399 printf ("usage: connect\n");
400 skip_to_semi (cfile
);
404 authenticator
= dhcpctl_null_handle
;
407 status
= dhcpctl_new_authenticator (&authenticator
,
412 if (status
!= ISC_R_SUCCESS
) {
414 "Cannot create authenticator: %s\n",
415 isc_result_totext (status
));
420 memset (&connection
, 0, sizeof connection
);
421 status
= dhcpctl_connect (&connection
,
422 server
, port
, authenticator
);
423 if (status
!= ISC_R_SUCCESS
) {
424 fprintf (stderr
, "dhcpctl_connect: %s\n",
425 isc_result_totext (status
));
432 token
= next_token (&val
, (unsigned *)0, cfile
);
433 if (token
!= END_OF_FILE
&& token
!= EOL
) {
434 printf ("usage: disconnect\n");
435 skip_to_semi (cfile
);
439 if (!connected
|| !connection
) {
440 fprintf (stderr
, "not connected\n");
444 status
= dhcpctl_disconnect (&connection
, 0);
445 if (status
!= ISC_R_SUCCESS
) {
446 fprintf (stderr
, "dhcpctl_disconnect: %s\n",
447 isc_result_totext (status
));
454 token
= next_token (&val
, (unsigned *)0, cfile
);
455 if ((!is_identifier (token
) && token
!= STRING
)) {
456 printf ("usage: new <object-type>\n");
461 printf ("an object is already open.\n");
462 skip_to_semi (cfile
);
467 printf ("not connected.\n");
468 skip_to_semi (cfile
);
472 status
= dhcpctl_new_object (&oh
, connection
, val
);
473 if (status
!= ISC_R_SUCCESS
) {
474 printf ("can't create object: %s\n",
475 isc_result_totext (status
));
479 token
= next_token (&val
, (unsigned *)0, cfile
);
480 if (token
!= END_OF_FILE
&& token
!= EOL
) {
481 printf ("usage: new <object-type>\n");
482 skip_to_semi (cfile
);
488 token
= next_token (&val
, (unsigned *)0, cfile
);
489 if (token
!= END_OF_FILE
&& token
!= EOL
) {
490 printf ("usage: close\n");
491 skip_to_semi (cfile
);
496 printf ("not connected.\n");
497 skip_to_semi (cfile
);
502 printf ("not open.\n");
503 skip_to_semi (cfile
);
506 omapi_object_dereference (&oh
, MDL
);
511 token
= next_token (&val
, (unsigned *)0, cfile
);
513 if ((!is_identifier (token
) && token
!= STRING
)) {
515 printf ("usage: set <name> = <value>\n");
516 skip_to_semi (cfile
);
521 printf ("no open object.\n");
522 skip_to_semi (cfile
);
527 printf ("not connected.\n");
528 skip_to_semi (cfile
);
533 strlcpy (s1
, val
, sizeof(s1
));
536 strncat (s1
, val
, sizeof(s1
)-strlen(s1
)-1);
539 token
= next_token (&val
, (unsigned *)0, cfile
);
543 token
= next_token (&val
, (unsigned *)0, cfile
);
546 dhcpctl_set_string_value (oh
, val
, s1
);
547 token
= next_token (&val
, (unsigned *)0, cfile
);
552 token
= peek_token (&val
, (unsigned *)0, cfile
);
553 /* Colon-separated hex list? */
556 else if (token
== DOT
) {
560 int intval
= atoi (val
);
563 "dotted octet > 255: %s",
565 skip_to_semi (cfile
);
569 token
= next_token (&val
,
570 (unsigned *)0, cfile
);
574 while ((token
= next_token (&val
,
575 (unsigned *)0, cfile
)) == DOT
)
577 } while (token
== NUMBER
);
578 dhcpctl_set_data_value (oh
, buf
,
583 dhcpctl_set_int_value (oh
, atoi (buf
), s1
);
584 token
= next_token (&val
, (unsigned *)0, cfile
);
594 convert_num (cfile
, (unsigned char *)s
,
597 token
= next_token (&val
,
598 (unsigned *)0, cfile
);
601 token
= next_token (&val
,
602 (unsigned *)0, cfile
);
603 } while (token
== NUMBER
||
604 token
== NUMBER_OR_NAME
);
605 dhcpctl_set_data_value (oh
, buf
,
606 (unsigned)(s
- buf
), s1
);
610 printf ("invalid value.\n");
611 skip_to_semi (cfile
);
614 if (token
!= END_OF_FILE
&& token
!= EOL
)
619 token
= next_token (&val
, (unsigned *)0, cfile
);
621 if ((!is_identifier (token
) && token
!= STRING
)) {
623 printf ("usage: unset <name>\n");
624 skip_to_semi (cfile
);
629 printf ("no open object.\n");
630 skip_to_semi (cfile
);
635 printf ("not connected.\n");
636 skip_to_semi (cfile
);
641 strlcpy (s1
, val
, sizeof(s1
));
644 strncat (s1
, val
, sizeof(s1
)-strlen(s1
)-1);
647 token
= next_token (&val
, (unsigned *)0, cfile
);
648 if (token
!= END_OF_FILE
&& token
!= EOL
)
651 dhcpctl_set_null_value (oh
, s1
);
658 token
= next_token (&val
, (unsigned *)0, cfile
);
659 if (token
!= END_OF_FILE
&& token
!= EOL
) {
660 printf ("usage: %s\n", val
);
661 skip_to_semi (cfile
);
666 printf ("not connected.\n");
667 skip_to_semi (cfile
);
672 printf ("you must make a new object first!\n");
673 skip_to_semi (cfile
);
677 if (i
== TOKEN_CREATE
)
678 i
= DHCPCTL_CREATE
| DHCPCTL_EXCL
;
682 status
= dhcpctl_open_object (oh
, connection
, i
);
683 if (status
== ISC_R_SUCCESS
)
684 status
= dhcpctl_wait_for_completion
686 if (status
== ISC_R_SUCCESS
)
688 if (status
!= ISC_R_SUCCESS
) {
689 printf ("can't open object: %s\n",
690 isc_result_totext (status
));
697 token
= next_token (&val
, (unsigned *)0, cfile
);
698 if (token
!= END_OF_FILE
&& token
!= EOL
) {
699 printf ("usage: %s\n", val
);
700 skip_to_semi (cfile
);
705 printf ("not connected.\n");
706 skip_to_semi (cfile
);
711 printf ("you haven't opened an object yet!\n");
712 skip_to_semi (cfile
);
716 status
= dhcpctl_object_update(connection
, oh
);
717 if (status
== ISC_R_SUCCESS
)
718 status
= dhcpctl_wait_for_completion
720 if (status
== ISC_R_SUCCESS
)
722 if (status
!= ISC_R_SUCCESS
) {
723 printf ("can't update object: %s\n",
724 isc_result_totext (status
));
731 token
= next_token (&val
, (unsigned *)0, cfile
);
732 if (token
!= END_OF_FILE
&& token
!= EOL
) {
733 printf ("usage: remove\n");
734 skip_to_semi (cfile
);
739 printf ("not connected.\n");
744 printf ("no object.\n");
748 status
= dhcpctl_object_remove(connection
, oh
);
749 if (status
== ISC_R_SUCCESS
)
750 status
= dhcpctl_wait_for_completion
752 if (status
== ISC_R_SUCCESS
)
754 if (status
!= ISC_R_SUCCESS
) {
755 printf ("can't destroy object: %s\n",
756 isc_result_totext (status
));
759 omapi_object_dereference (&oh
, MDL
);
763 token
= next_token (&val
, (unsigned *)0, cfile
);
764 if (token
!= END_OF_FILE
&& token
!= EOL
) {
765 printf ("usage: refresh\n");
766 skip_to_semi (cfile
);
771 printf ("not connected.\n");
776 printf ("no object.\n");
780 status
= dhcpctl_object_refresh(connection
, oh
);
781 if (status
== ISC_R_SUCCESS
)
782 status
= dhcpctl_wait_for_completion
784 if (status
== ISC_R_SUCCESS
)
786 if (status
!= ISC_R_SUCCESS
) {
787 printf ("can't refresh object: %s\n",
788 isc_result_totext (status
));
801 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
802 control_object_state_t newstate
)
804 if (newstate
!= server_shutdown
)
805 return ISC_R_SUCCESS
;