3 Examine and modify omapi objects. */
6 * Copyright (c) 2009-2011,2013-2015 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
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.
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.
22 * Internet Systems Consortium, Inc.
24 * Redwood City, CA 94063
26 * https://www.isc.org/
45 isc_result_t
find_class (struct class **c
, const char *n
, const char *f
, int l
)
49 int parse_allow_deny (struct option_cache
**oc
, struct parse
*cfile
, int flag
)
53 void dhcp (struct packet
*packet
) { }
54 void bootp (struct packet
*packet
) { }
57 /* XXX: should we warn or something here? */
58 void dhcpv6(struct packet
*packet
) { }
61 int check_collection (struct packet
*p
, struct lease
*l
, struct collection
*c
)
65 void classify (struct packet
*packet
, struct class *class) { }
67 static void usage (const char *s
) {
68 fprintf (stderr
, "Usage: %s\n", s
);
72 static void check (isc_result_t status
, const char *func
) {
73 if (status
!= ISC_R_SUCCESS
) {
74 fprintf (stderr
, "%s: %s\n", func
, isc_result_totext (status
));
80 main(int argc
, char **argv
) {
81 isc_result_t status
, waitstatus
;
82 dhcpctl_handle connection
;
83 dhcpctl_handle authenticator
;
85 struct data_string secret
;
86 const char *name
= 0, *algorithm
= "hmac-md5";
89 const char *server
= "127.0.0.1";
91 enum dhcp_token token
;
101 progname
= "omshell";
106 for (i
= 1; i
< argc
; i
++) {
107 usage(isc_file_basename(progname
));
110 /* Initially, log errors to stderr as well as to syslogd. */
111 openlog (isc_file_basename(progname
),
112 DHCP_LOG_OPTIONS
, DHCPD_LOG_FACILITY
);
113 status
= dhcpctl_initialize ();
114 if (status
!= ISC_R_SUCCESS
) {
115 fprintf (stderr
, "dhcpctl_initialize: %s\n",
116 isc_result_totext (status
));
120 memset (&oh
, 0, sizeof oh
);
124 } else if (oh
== NULL
) {
125 printf ("obj: <null>\n");
127 dhcpctl_remote_object_t
*r
= (dhcpctl_remote_object_t
*)oh
;
128 omapi_generic_object_t
*g
=
129 (omapi_generic_object_t
*)(r
-> inner
);
133 if (r
-> rtype
-> type
!= omapi_datatype_string
) {
137 (int)(r
-> rtype
-> u
. buffer
. len
),
138 r
-> rtype
-> u
. buffer
. value
);
141 for (i
= 0; i
< g
-> nvalues
; i
++) {
142 omapi_value_t
*v
= g
-> values
[i
];
144 if (!g
-> values
[i
])
147 printf ("%.*s = ", (int)v
-> name
-> len
,
154 switch (v
-> value
-> type
) {
155 case omapi_datatype_int
:
157 v
-> value
-> u
. integer
);
160 case omapi_datatype_string
:
161 printf ("\"%.*s\"\n",
162 (int) v
-> value
-> u
.buffer
.len
,
163 v
-> value
-> u
.buffer
.value
);
166 case omapi_datatype_data
:
167 print_hex_or_string(v
->value
->u
.buffer
.len
,
168 v
->value
->u
.buffer
.value
,
169 sizeof(hex_buf
), hex_buf
);
170 printf("%s\n", hex_buf
);
173 case omapi_datatype_object
:
180 fputs ("> ", stdout
);
182 if (fgets (buf
, sizeof(buf
), stdin
) == NULL
)
185 status
= new_parse (&cfile
, -1, buf
, strlen(buf
), "<STDIN>", 1);
186 check(status
, "new_parse()");
188 token
= next_token (&val
, (unsigned *)0, cfile
);
191 parse_warn (cfile
, "unknown token: %s", val
);
192 skip_to_semi (cfile
);
196 case ENDOFLINE
: /* EOL: */
200 case QUESTIONMARK
: /* '?': */
201 printf ("Commands:\n");
202 printf (" port <server omapi port>\n");
203 printf (" server <server address>\n");
204 printf (" key <key name> <key value>\n");
205 printf (" connect\n");
206 printf (" new <object-type>\n");
207 printf (" set <name> = <value>\n");
208 printf (" create\n");
210 printf (" update\n");
211 printf (" unset <name>\n");
212 printf (" refresh\n");
213 printf (" remove\n");
214 skip_to_semi (cfile
);
218 token
= next_token (&val
, (unsigned *)0, cfile
);
219 if (is_identifier (token
)) {
221 se
= getservbyname (val
, "tcp");
223 port
= ntohs (se
-> s_port
);
225 printf ("unknown service name: %s\n", val
);
228 } else if (token
== NUMBER
) {
231 skip_to_semi (cfile
);
232 printf ("usage: port <port>\n");
235 token
= next_token (&val
, (unsigned *)0, cfile
);
236 if (token
!= END_OF_FILE
&& token
!= EOL
) {
237 printf ("usage: port <server>\n");
238 skip_to_semi (cfile
);
244 token
= next_token (&val
, (unsigned *)0, cfile
);
245 if (token
== NUMBER
) {
246 int alen
= (sizeof buf
) - 1;
251 if (len
+ 1 > alen
) {
253 printf ("usage: server <server>\n");
254 skip_to_semi (cfile
);
258 token
= next_token (&val
, (unsigned *)0, cfile
);
262 token
= next_token (&val
, (unsigned *)0, cfile
);
270 token
= next_token (&val
, (unsigned *)0, cfile
);
274 token
= next_token (&val
, (unsigned *)0, cfile
);
282 token
= next_token (&val
, (unsigned *)0, cfile
);
286 token
= next_token (&val
, (unsigned *)0, cfile
);
294 } else if (is_identifier (token
)) {
295 /* Use val directly. */
297 printf ("usage: server <server>\n");
298 skip_to_semi (cfile
);
302 s
= dmalloc (strlen (val
) + 1, MDL
);
304 printf ("no memory to store server name.\n");
305 skip_to_semi (cfile
);
311 token
= next_token (&val
, (unsigned *)0, cfile
);
312 if (token
!= END_OF_FILE
&& token
!= EOL
) {
313 printf ("usage: server <server>\n");
314 skip_to_semi (cfile
);
320 token
= peek_token(&val
, (unsigned *)0, cfile
);
321 if (token
== STRING
) {
322 token
= next_token (&val
, (unsigned *)0, cfile
);
323 if (!is_identifier (token
)) {
324 printf ("usage: key <name> <value>\n");
325 skip_to_semi (cfile
);
328 s
= dmalloc (strlen (val
) + 1, MDL
);
330 printf ("no memory for key name.\n");
331 skip_to_semi (cfile
);
336 s
= parse_host_name(cfile
);
338 printf ("usage: key <name> <value>\n");
345 memset (&secret
, 0, sizeof secret
);
346 if (!parse_base64 (&secret
, cfile
)) {
347 skip_to_semi (cfile
);
350 token
= next_token (&val
, (unsigned *)0, cfile
);
351 if (token
!= END_OF_FILE
&& token
!= EOL
) {
352 printf ("usage: key <name> <secret>\n");
353 skip_to_semi (cfile
);
359 token
= next_token (&val
, (unsigned *)0, cfile
);
360 if (token
!= END_OF_FILE
&& token
!= EOL
) {
361 printf ("usage: connect\n");
362 skip_to_semi (cfile
);
366 authenticator
= dhcpctl_null_handle
;
369 status
= dhcpctl_new_authenticator (&authenticator
,
374 if (status
!= ISC_R_SUCCESS
) {
376 "Cannot create authenticator: %s\n",
377 isc_result_totext (status
));
382 memset (&connection
, 0, sizeof connection
);
383 status
= dhcpctl_connect (&connection
,
384 server
, port
, authenticator
);
385 if (status
!= ISC_R_SUCCESS
) {
386 fprintf (stderr
, "dhcpctl_connect: %s\n",
387 isc_result_totext (status
));
394 token
= next_token (&val
, (unsigned *)0, cfile
);
395 if ((!is_identifier (token
) && token
!= STRING
)) {
396 printf ("usage: new <object-type>\n");
401 printf ("an object is already open.\n");
402 skip_to_semi (cfile
);
407 printf ("not connected.\n");
408 skip_to_semi (cfile
);
412 status
= dhcpctl_new_object (&oh
, connection
, val
);
413 if (status
!= ISC_R_SUCCESS
) {
414 printf ("can't create object: %s\n",
415 isc_result_totext (status
));
419 token
= next_token (&val
, (unsigned *)0, cfile
);
420 if (token
!= END_OF_FILE
&& token
!= EOL
) {
421 printf ("usage: new <object-type>\n");
422 skip_to_semi (cfile
);
428 token
= next_token (&val
, (unsigned *)0, cfile
);
429 if (token
!= END_OF_FILE
&& token
!= EOL
) {
430 printf ("usage: close\n");
431 skip_to_semi (cfile
);
436 printf ("not connected.\n");
437 skip_to_semi (cfile
);
442 printf ("not open.\n");
443 skip_to_semi (cfile
);
446 omapi_object_dereference (&oh
, MDL
);
451 token
= next_token (&val
, (unsigned *)0, cfile
);
453 if ((!is_identifier (token
) && token
!= STRING
)) {
455 printf ("usage: set <name> = <value>\n");
456 skip_to_semi (cfile
);
461 printf ("no open object.\n");
462 skip_to_semi (cfile
);
467 printf ("not connected.\n");
468 skip_to_semi (cfile
);
473 strlcpy (s1
, val
, sizeof(s1
));
476 strncat (s1
, val
, sizeof(s1
)-strlen(s1
)-1);
479 token
= next_token (&val
, (unsigned *)0, cfile
);
483 token
= next_token (&val
, (unsigned *)0, cfile
);
486 dhcpctl_set_string_value (oh
, val
, s1
);
487 token
= next_token (&val
, (unsigned *)0, cfile
);
492 token
= peek_token (&val
, (unsigned *)0, cfile
);
493 /* Colon-separated hex list? */
496 else if (token
== DOT
) {
500 int intval
= atoi (val
);
503 "dotted octet > 255: %s",
505 skip_to_semi (cfile
);
509 token
= next_token (&val
,
510 (unsigned *)0, cfile
);
514 while ((token
= next_token (&val
,
515 (unsigned *)0, cfile
)) == DOT
)
517 } while (token
== NUMBER
);
518 dhcpctl_set_data_value (oh
, buf
,
523 dhcpctl_set_int_value (oh
, atoi (buf
), s1
);
524 token
= next_token (&val
, (unsigned *)0, cfile
);
534 convert_num (cfile
, (unsigned char *)s
,
537 token
= next_token (&val
,
538 (unsigned *)0, cfile
);
541 token
= next_token (&val
,
542 (unsigned *)0, cfile
);
543 } while (token
== NUMBER
||
544 token
== NUMBER_OR_NAME
);
545 dhcpctl_set_data_value (oh
, buf
,
546 (unsigned)(s
- buf
), s1
);
550 printf ("invalid value.\n");
551 skip_to_semi (cfile
);
554 if (token
!= END_OF_FILE
&& token
!= EOL
)
559 token
= next_token (&val
, (unsigned *)0, cfile
);
561 if ((!is_identifier (token
) && token
!= STRING
)) {
563 printf ("usage: unset <name>\n");
564 skip_to_semi (cfile
);
569 printf ("no open object.\n");
570 skip_to_semi (cfile
);
575 printf ("not connected.\n");
576 skip_to_semi (cfile
);
581 strlcpy (s1
, val
, sizeof(s1
));
584 strncat (s1
, val
, sizeof(s1
)-strlen(s1
)-1);
587 token
= next_token (&val
, (unsigned *)0, cfile
);
588 if (token
!= END_OF_FILE
&& token
!= EOL
)
591 dhcpctl_set_null_value (oh
, s1
);
598 token
= next_token (&val
, (unsigned *)0, cfile
);
599 if (token
!= END_OF_FILE
&& token
!= EOL
) {
600 printf ("usage: %s\n", val
);
601 skip_to_semi (cfile
);
606 printf ("not connected.\n");
607 skip_to_semi (cfile
);
612 printf ("you must make a new object first!\n");
613 skip_to_semi (cfile
);
617 if (i
== TOKEN_CREATE
)
618 i
= DHCPCTL_CREATE
| DHCPCTL_EXCL
;
622 status
= dhcpctl_open_object (oh
, connection
, i
);
623 if (status
== ISC_R_SUCCESS
)
624 status
= dhcpctl_wait_for_completion
626 if (status
== ISC_R_SUCCESS
)
628 if (status
!= ISC_R_SUCCESS
) {
629 printf ("can't open object: %s\n",
630 isc_result_totext (status
));
637 token
= next_token (&val
, (unsigned *)0, cfile
);
638 if (token
!= END_OF_FILE
&& token
!= EOL
) {
639 printf ("usage: %s\n", val
);
640 skip_to_semi (cfile
);
645 printf ("not connected.\n");
646 skip_to_semi (cfile
);
651 printf ("you haven't opened an object yet!\n");
652 skip_to_semi (cfile
);
656 status
= dhcpctl_object_update(connection
, oh
);
657 if (status
== ISC_R_SUCCESS
)
658 status
= dhcpctl_wait_for_completion
660 if (status
== ISC_R_SUCCESS
)
662 if (status
!= ISC_R_SUCCESS
) {
663 printf ("can't update object: %s\n",
664 isc_result_totext (status
));
671 token
= next_token (&val
, (unsigned *)0, cfile
);
672 if (token
!= END_OF_FILE
&& token
!= EOL
) {
673 printf ("usage: remove\n");
674 skip_to_semi (cfile
);
679 printf ("not connected.\n");
684 printf ("no object.\n");
688 status
= dhcpctl_object_remove(connection
, oh
);
689 if (status
== ISC_R_SUCCESS
)
690 status
= dhcpctl_wait_for_completion
692 if (status
== ISC_R_SUCCESS
)
694 if (status
!= ISC_R_SUCCESS
) {
695 printf ("can't destroy object: %s\n",
696 isc_result_totext (status
));
699 omapi_object_dereference (&oh
, MDL
);
703 token
= next_token (&val
, (unsigned *)0, cfile
);
704 if (token
!= END_OF_FILE
&& token
!= EOL
) {
705 printf ("usage: refresh\n");
706 skip_to_semi (cfile
);
711 printf ("not connected.\n");
716 printf ("no object.\n");
720 status
= dhcpctl_object_refresh(connection
, oh
);
721 if (status
== ISC_R_SUCCESS
)
722 status
= dhcpctl_wait_for_completion
724 if (status
== ISC_R_SUCCESS
)
726 if (status
!= ISC_R_SUCCESS
) {
727 printf ("can't refresh object: %s\n",
728 isc_result_totext (status
));
741 isc_result_t
dhcp_set_control_state (control_object_state_t oldstate
,
742 control_object_state_t newstate
)
744 if (newstate
!= server_shutdown
)
745 return ISC_R_SUCCESS
;