dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.sbin / nwamcfg / nwamcfg.c
blob16e53da7008540ed9aea7eac6f6cc4e211af59ff
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
27 * nwamcfg is a lex/yacc based command interpreter used to manage network
28 * configurations. The lexer (see nwamcfg_lex.l) builds up tokens, which
29 * the grammar (see nwamcfg_grammar.y) builds up into commands, some of
30 * which takes resources and/or properties as arguments.
33 #include <arpa/inet.h>
34 #include <assert.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <libnwam.h>
38 #include <libtecla.h>
39 #include <locale.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <sys/stat.h>
44 #include <sys/sysmacros.h>
45 #include <sys/types.h>
46 #include <unistd.h>
48 #include "nwamcfg.h"
50 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
51 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
52 #endif
54 struct help {
55 uint_t cmd_num;
56 const char *cmd_name;
57 const char *cmd_usage;
60 extern int yyparse(void);
61 extern int lex_lineno;
63 #define MAX_LINE_LEN 1024
64 #define MAX_CMD_HIST 1024
66 /* usage of commands */
67 #define SHELP_CANCEL "cancel"
68 #define SHELP_CLEAR "clear <prop-name>"
69 #define SHELP_COMMIT "commit"
70 #define SHELP_CREATE "create [-t <template>] <object-type> [<class>] " \
71 "<object-name>"
72 #define SHELP_DESTROY "destroy {-a | <object-type> [<class>] <object-name>}"
73 #define SHELP_END "end"
74 #define SHELP_EXIT "exit"
75 #define SHELP_EXPORT "export [-d] [-f <output-file>] " \
76 "[<object-type> [<class>] <object-name>]"
77 #define SHELP_GET "get [-V] <prop-name>"
78 #define SHELP_HELP "help [command-name]"
79 #define SHELP_LIST "list [-a] [<object-type> [<class>] <object-name>]"
80 #define SHELP_REVERT "revert"
81 #define SHELP_SELECT "select <object-type> [<class>] <object-name>"
82 #define SHELP_SET "set <prop-name>=<value1>[,<value2>...]"
83 #define SHELP_VERIFY "verify"
84 #define SHELP_WALK "walkprop [-a]"
87 * Scope Definitions:
88 * Locations, ENMs, NCPs and Known WLANs are one scope level below global (GBL).
89 * NCUs are one more level beneath the NCP scope.
90 * Because the commands in Locations/ENM/Known WLAN and NCP level are different,
91 * the scope are divided accordingly.
92 * GBL->LOC, GBL->ENM, GBL->WLAN or GBL->NCP->NCU
94 #define NWAM_SCOPE_GBL 0
95 #define NWAM_SCOPE_LOC 1
96 #define NWAM_SCOPE_ENM 2
97 #define NWAM_SCOPE_WLAN 3
98 #define NWAM_SCOPE_NCP 4
99 #define NWAM_SCOPE_NCU 5
101 /* delimiter used for list of values */
102 #define NWAM_VALUE_DELIMITER_CHAR ','
103 #define NWAM_VALUE_DELIMITER_STR ","
105 /* the max number of values for an enum used by some properties in libnwam */
108 * All arrays/tables are null-terminated, rather than defining the length of
109 * the array. When looping, check for NULL rather than using the size.
112 static struct help helptab[] = {
113 { CMD_CANCEL, "cancel", SHELP_CANCEL },
114 { CMD_CLEAR, "clear", SHELP_CLEAR },
115 { CMD_COMMIT, "commit", SHELP_COMMIT },
116 { CMD_CREATE, "create", SHELP_CREATE },
117 { CMD_DESTROY, "destroy", SHELP_DESTROY },
118 { CMD_END, "end", SHELP_END },
119 { CMD_EXIT, "exit", SHELP_EXIT },
120 { CMD_EXPORT, "export", SHELP_EXPORT },
121 { CMD_GET, "get", SHELP_GET },
122 { CMD_HELP, "help", SHELP_HELP },
123 { CMD_LIST, "list", SHELP_LIST },
124 { CMD_REVERT, "revert", SHELP_REVERT },
125 { CMD_SELECT, "select", SHELP_SELECT },
126 { CMD_SET, "set", SHELP_SET },
127 { CMD_VERIFY, "verify", SHELP_VERIFY },
128 { CMD_WALKPROP, "walkprop", SHELP_WALK },
129 { 0, NULL, NULL }
132 /* These *must* match the order of the RT1_ define's from nwamcfg.h */
133 static char *res1_types[] = {
134 "unknown",
135 "loc",
136 "ncp",
137 "enm",
138 "wlan",
139 NULL
142 /* These *must* match the order of the RT2_ define's from nwamcfg.h */
143 static char *res2_types[] = {
144 "unknown",
145 "ncu",
146 NULL
150 * No array for NCU_CLASS_. The #define's in nwamcfg.h matches the
151 * enum nwam_ncu_class_t in libnwam and thus uses libnwam functions to
152 * retrieve the string representation.
155 /* These *MUST* match the order of the PT_ define's from nwamcfg.h */
156 static char *pt_types[] = {
157 "unknown",
158 NWAM_NCU_PROP_ACTIVATION_MODE,
159 NWAM_NCU_PROP_ENABLED,
160 NWAM_NCU_PROP_TYPE,
161 NWAM_NCU_PROP_CLASS,
162 NWAM_NCU_PROP_PARENT_NCP,
163 NWAM_NCU_PROP_PRIORITY_GROUP,
164 NWAM_NCU_PROP_PRIORITY_MODE,
165 NWAM_NCU_PROP_LINK_MAC_ADDR,
166 NWAM_NCU_PROP_LINK_AUTOPUSH,
167 NWAM_NCU_PROP_LINK_MTU,
168 NWAM_NCU_PROP_IP_VERSION,
169 NWAM_NCU_PROP_IPV4_ADDRSRC,
170 NWAM_NCU_PROP_IPV4_ADDR,
171 NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE,
172 NWAM_NCU_PROP_IPV6_ADDRSRC,
173 NWAM_NCU_PROP_IPV6_ADDR,
174 NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE,
175 NWAM_LOC_PROP_CONDITIONS,
176 NWAM_ENM_PROP_FMRI,
177 NWAM_ENM_PROP_START,
178 NWAM_ENM_PROP_STOP,
179 NWAM_LOC_PROP_NAMESERVICES,
180 NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE,
181 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
182 NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN,
183 NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS,
184 NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH,
185 NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
186 NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS,
187 NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
188 NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS,
189 NWAM_LOC_PROP_DEFAULT_DOMAIN,
190 NWAM_LOC_PROP_NFSV4_DOMAIN,
191 NWAM_LOC_PROP_IPFILTER_CONFIG_FILE,
192 NWAM_LOC_PROP_IPFILTER_V6_CONFIG_FILE,
193 NWAM_LOC_PROP_IPNAT_CONFIG_FILE,
194 NWAM_LOC_PROP_IPPOOL_CONFIG_FILE,
195 NWAM_LOC_PROP_IKE_CONFIG_FILE,
196 NWAM_LOC_PROP_IPSECPOLICY_CONFIG_FILE,
197 NWAM_KNOWN_WLAN_PROP_BSSIDS,
198 NWAM_KNOWN_WLAN_PROP_PRIORITY,
199 NWAM_KNOWN_WLAN_PROP_KEYNAME,
200 NWAM_KNOWN_WLAN_PROP_KEYSLOT,
201 NWAM_KNOWN_WLAN_PROP_SECURITY_MODE
204 /* properties table: maps PT_* constants to property names */
205 typedef struct prop_table_entry {
206 int pte_type;
207 const char *pte_name;
208 } prop_table_entry_t;
210 /* NCU properties table */
211 static prop_table_entry_t ncu_prop_table[] = {
212 { PT_TYPE, NWAM_NCU_PROP_TYPE },
213 { PT_CLASS, NWAM_NCU_PROP_CLASS },
214 { PT_PARENT, NWAM_NCU_PROP_PARENT_NCP },
215 { PT_ACTIVATION_MODE, NWAM_NCU_PROP_ACTIVATION_MODE },
216 { PT_ENABLED, NWAM_NCU_PROP_ENABLED },
217 { PT_PRIORITY_GROUP, NWAM_NCU_PROP_PRIORITY_GROUP },
218 { PT_PRIORITY_MODE, NWAM_NCU_PROP_PRIORITY_MODE },
219 { PT_LINK_MACADDR, NWAM_NCU_PROP_LINK_MAC_ADDR },
220 { PT_LINK_AUTOPUSH, NWAM_NCU_PROP_LINK_AUTOPUSH },
221 { PT_LINK_MTU, NWAM_NCU_PROP_LINK_MTU },
222 { PT_IP_VERSION, NWAM_NCU_PROP_IP_VERSION },
223 { PT_IPV4_ADDRSRC, NWAM_NCU_PROP_IPV4_ADDRSRC },
224 { PT_IPV4_ADDR, NWAM_NCU_PROP_IPV4_ADDR },
225 { PT_IPV4_DEFAULT_ROUTE, NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE },
226 { PT_IPV6_ADDRSRC, NWAM_NCU_PROP_IPV6_ADDRSRC },
227 { PT_IPV6_ADDR, NWAM_NCU_PROP_IPV6_ADDR },
228 { PT_IPV6_DEFAULT_ROUTE, NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE },
229 { 0, NULL }
232 /* ENM properties table */
233 static prop_table_entry_t enm_prop_table[] = {
234 { PT_ENM_FMRI, NWAM_ENM_PROP_FMRI },
235 { PT_ENM_START, NWAM_ENM_PROP_START },
236 { PT_ENM_STOP, NWAM_ENM_PROP_STOP },
237 { PT_ACTIVATION_MODE, NWAM_ENM_PROP_ACTIVATION_MODE },
238 { PT_CONDITIONS, NWAM_ENM_PROP_CONDITIONS },
239 { PT_ENABLED, NWAM_ENM_PROP_ENABLED },
240 { 0, NULL }
243 /* LOCation properties table */
244 static prop_table_entry_t loc_prop_table[] = {
245 { PT_ACTIVATION_MODE, NWAM_LOC_PROP_ACTIVATION_MODE },
246 { PT_CONDITIONS, NWAM_LOC_PROP_CONDITIONS },
247 { PT_ENABLED, NWAM_LOC_PROP_ENABLED },
248 { PT_LOC_NAMESERVICES, NWAM_LOC_PROP_NAMESERVICES },
249 { PT_LOC_NAMESERVICES_CONFIG, NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE },
250 { PT_LOC_DNS_CONFIGSRC, NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC },
251 { PT_LOC_DNS_DOMAIN, NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN },
252 { PT_LOC_DNS_SERVERS, NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS },
253 { PT_LOC_DNS_SEARCH, NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH },
254 { PT_LOC_NIS_CONFIGSRC, NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC },
255 { PT_LOC_NIS_SERVERS, NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS },
256 { PT_LOC_LDAP_CONFIGSRC, NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC },
257 { PT_LOC_LDAP_SERVERS, NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS },
258 { PT_LOC_DEFAULT_DOMAIN, NWAM_LOC_PROP_DEFAULT_DOMAIN },
259 { PT_LOC_NFSV4_DOMAIN, NWAM_LOC_PROP_NFSV4_DOMAIN },
260 { PT_LOC_IPF_CONFIG, NWAM_LOC_PROP_IPFILTER_CONFIG_FILE },
261 { PT_LOC_IPF_V6_CONFIG, NWAM_LOC_PROP_IPFILTER_V6_CONFIG_FILE },
262 { PT_LOC_IPNAT_CONFIG, NWAM_LOC_PROP_IPNAT_CONFIG_FILE },
263 { PT_LOC_IPPOOL_CONFIG, NWAM_LOC_PROP_IPPOOL_CONFIG_FILE },
264 { PT_LOC_IKE_CONFIG, NWAM_LOC_PROP_IKE_CONFIG_FILE },
265 { PT_LOC_IPSECPOL_CONFIG, NWAM_LOC_PROP_IPSECPOLICY_CONFIG_FILE },
266 { 0, NULL }
269 /* Known WLAN properties table */
270 static prop_table_entry_t wlan_prop_table[] = {
271 { PT_WLAN_BSSIDS, NWAM_KNOWN_WLAN_PROP_BSSIDS },
272 { PT_WLAN_PRIORITY, NWAM_KNOWN_WLAN_PROP_PRIORITY },
273 { PT_WLAN_KEYNAME, NWAM_KNOWN_WLAN_PROP_KEYNAME },
274 { PT_WLAN_KEYSLOT, NWAM_KNOWN_WLAN_PROP_KEYSLOT },
275 { PT_WLAN_SECURITY_MODE, NWAM_KNOWN_WLAN_PROP_SECURITY_MODE },
276 { 0, NULL }
279 /* Returns the appropriate properties table for the given object type */
280 static prop_table_entry_t *
281 get_prop_table(nwam_object_type_t object_type)
283 switch (object_type) {
284 case NWAM_OBJECT_TYPE_NCU:
285 return (ncu_prop_table);
286 case NWAM_OBJECT_TYPE_LOC:
287 return (loc_prop_table);
288 case NWAM_OBJECT_TYPE_ENM:
289 return (enm_prop_table);
290 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
291 return (wlan_prop_table);
293 return (NULL);
296 /* Global variables */
298 /* set early in main(), never modified thereafter, used all over the place */
299 static char *execname;
301 /* set in modifying functions, checked in read_input() */
302 boolean_t saw_error = B_FALSE;
304 /* set in yacc parser, checked in read_input() */
305 boolean_t newline_terminated;
307 /* set in main(), checked in lex error handler */
308 boolean_t cmd_file_mode = B_FALSE;
310 /* set in exit_func(), checked in read_input() */
311 static boolean_t time_to_exit = B_FALSE;
313 /* used in nerr() and nwamerr() */
314 static char *cmd_file_name = NULL;
316 /* used with cmd_file to destroy all configurations */
317 static boolean_t remove_all_configurations = B_FALSE;
319 /* checked in read_input() and other places */
320 static boolean_t ok_to_prompt = B_FALSE;
322 /* initialized in do_interactive(), checked in initialize() */
323 static boolean_t interactive_mode;
325 static boolean_t need_to_commit = B_FALSE;
327 /* The gl_get_line() resource object */
328 static GetLine *gl;
330 /* set when create or read objects, used by other func */
331 static nwam_loc_handle_t loc_h = NULL;
332 static nwam_enm_handle_t enm_h = NULL;
333 static nwam_known_wlan_handle_t wlan_h = NULL;
334 static nwam_ncu_handle_t ncu_h = NULL;
335 static nwam_ncp_handle_t ncp_h = NULL;
337 static int current_scope = NWAM_SCOPE_GBL;
339 /* obj1_* are used in NWAM_SCOPE_{NCP,LOC,ENM,WLAN} */
340 static int obj1_type;
341 static char obj1_name[NWAM_MAX_NAME_LEN + 1];
343 /* obj2_* are used in NWAM_SCOPE_NCU only */
344 static int obj2_type;
345 static char obj2_name[NWAM_MAX_NAME_LEN + 1];
347 /* arrays for tab-completion */
348 /* commands at NWAM_SCOPE_GBL */
349 static const char *global_scope_cmds[] = {
350 "create ",
351 "destroy ",
352 "end ",
353 "exit ",
354 "export ",
355 "help ",
356 "list ",
357 "select ",
358 NULL
361 static const char *global_create_cmds[] = {
362 "create loc ",
363 "create enm ",
364 "create ncp ",
365 "create wlan ",
366 "create -t ", /* template */
367 NULL
370 static const char *global_destroy_cmds[] = {
371 "destroy -a ",
372 "destroy loc ",
373 "destroy enm ",
374 "destroy ncp ",
375 "destroy wlan ",
376 NULL
379 static const char *global_export_cmds[] = {
380 "export ",
381 "export -d ", /* add destroy -a */
382 "export -f ", /* to file */
383 "export -d -f ", /* add destroy -a to file */
384 "export loc ",
385 "export enm ",
386 "export ncp ",
387 "export wlan ",
388 NULL
391 static const char *global_list_cmds[] = {
392 "list ",
393 "list loc ",
394 "list enm ",
395 "list ncp ",
396 "list wlan ",
397 "list -a loc ",
398 "list -a enm ",
399 "list -a wlan ",
400 NULL
403 static const char *global_select_cmds[] = {
404 "select loc ",
405 "select enm ",
406 "select ncp ",
407 "select wlan ",
408 NULL
411 /* commands at NWAM_SCOPE_LOC, _ENM, _WLAN and _NCU */
412 static const char *non_ncp_scope_cmds[] = {
413 "cancel ",
414 "clear ",
415 "commit ",
416 "end ",
417 "exit ",
418 "export ",
419 "export -f ",
420 "get ",
421 "get -V ", /* value only */
422 "help ",
423 "list ",
424 "list -a ", /* all properties */
425 "revert ",
426 "set ",
427 "verify ",
428 "walkprop ",
429 "walkprop -a ", /* all properties */
430 NULL
433 /* commands at NWAM_SCOPE_NCP */
434 static const char *ncp_scope_cmds[] = {
435 "cancel ",
436 "create ",
437 "destroy ",
438 "end ",
439 "exit ",
440 "export ",
441 "help ",
442 "list ",
443 "select ",
444 NULL
447 static const char *ncp_create_cmds[] = {
448 "create ncu ip ",
449 "create ncu phys ",
450 "create -t ", /* template */
451 NULL
454 static const char *ncp_destroy_cmds[] = {
455 "destroy ncu ",
456 "destroy ncu ip ",
457 "destroy ncu phys ",
458 NULL
461 static const char *ncp_export_cmds[] = {
462 "export ",
463 "export -f ", /* to file */
464 "export ncu ",
465 "export ncu ip ",
466 "export ncu phys ",
467 NULL
470 static const char *ncp_list_cmds[] = {
471 "list ",
472 "list ncu ",
473 "list ncu ip ",
474 "list ncu phys ",
475 "list -a ncu ",
476 "list -a ncu ip ",
477 "list -a ncu phys ",
478 NULL
481 static const char *ncp_select_cmds[] = {
482 "select ncu ",
483 "select ncu ip ",
484 "select ncu phys ",
485 NULL
488 /* Functions begin here */
490 cmd_t *
491 alloc_cmd(void)
493 cmd_t *cmd = calloc(1, sizeof (cmd_t));
494 if (cmd == NULL) {
495 nerr("Out of memory");
496 return (NULL);
498 cmd->cmd_argc = 0;
499 cmd->cmd_argv[0] = NULL;
501 return (cmd);
504 void
505 free_cmd(cmd_t *cmd)
507 int i;
509 for (i = 0; i < cmd->cmd_argc; i++)
510 free(cmd->cmd_argv[i]);
511 free(cmd);
514 void
515 array_free(void **array, int nelem)
517 int i;
518 for (i = 0; i < nelem; i++)
519 free(array[i]);
520 free(array);
523 static boolean_t
524 initial_match(const char *line1, const char *line2, int word_end)
526 if (word_end <= 0)
527 return (B_TRUE);
528 return (strncmp(line1, line2, word_end) == 0);
531 static int
532 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
533 int word_end)
535 int i, err;
537 for (i = 0; list[i] != NULL; i++) {
538 if (initial_match(line1, list[i], word_end)) {
539 err = cpl_add_completion(cpl, line1, 0, word_end,
540 list[i] + word_end, "", "");
541 if (err != 0)
542 return (err);
545 return (0);
549 * To fill in the rest of a string when user types the tab key.
550 * First digital number is the length of the string, the second digital number
551 * is the min number of chars that is needed to uniquely identify a string.
553 #define MINI_STR(l, s, m, n) strncmp(l, s, MAX(MIN(sizeof (s) - 1, m), n))
555 /* ARGSUSED */
556 static
557 CPL_MATCH_FN(cmd_cpl_fn)
559 /* tab-complete according to the current scope */
560 switch (current_scope) {
561 case NWAM_SCOPE_GBL:
562 if (MINI_STR(line, "create ", word_end, 2) == 0)
563 return (add_stuff(cpl, line, global_create_cmds,
564 word_end));
565 if (MINI_STR(line, "destroy ", word_end, 1) == 0)
566 return (add_stuff(cpl, line, global_destroy_cmds,
567 word_end));
568 if (MINI_STR(line, "export ", word_end, 3) == 0)
569 return (add_stuff(cpl, line, global_export_cmds,
570 word_end));
571 if (MINI_STR(line, "list ", word_end, 1) == 0)
572 return (add_stuff(cpl, line, global_list_cmds,
573 word_end));
574 if (MINI_STR(line, "select ", word_end, 1) == 0)
575 return (add_stuff(cpl, line, global_select_cmds,
576 word_end));
577 return (add_stuff(cpl, line, global_scope_cmds, word_end));
578 case NWAM_SCOPE_LOC:
579 case NWAM_SCOPE_ENM:
580 case NWAM_SCOPE_WLAN:
581 case NWAM_SCOPE_NCU:
582 return (add_stuff(cpl, line, non_ncp_scope_cmds, word_end));
583 case NWAM_SCOPE_NCP:
584 if (MINI_STR(line, "create ", word_end, 2) == 0)
585 return (add_stuff(cpl, line, ncp_create_cmds,
586 word_end));
587 if (MINI_STR(line, "destroy ", word_end, 1) == 0)
588 return (add_stuff(cpl, line, ncp_destroy_cmds,
589 word_end));
590 if (MINI_STR(line, "export ", word_end, 3) == 0)
591 return (add_stuff(cpl, line, ncp_export_cmds,
592 word_end));
593 if (MINI_STR(line, "list ", word_end, 1) == 0)
594 return (add_stuff(cpl, line, ncp_list_cmds, word_end));
595 if (MINI_STR(line, "select ", word_end, 1) == 0)
596 return (add_stuff(cpl, line, ncp_select_cmds,
597 word_end));
598 return (add_stuff(cpl, line, ncp_scope_cmds, word_end));
600 /* should never get here */
601 return (0);
604 const char *
605 cmd_to_str(int cmd_num)
607 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
608 return (helptab[cmd_num].cmd_name);
611 /* Returns "loc", "enm", "wlan" or "ncp" as string */
612 static const char *
613 rt1_to_str(int res_type)
615 assert(res_type >= RT1_MIN && res_type <= RT1_MAX);
616 return (res1_types[res_type]);
619 /* Returns "ncu" as string */
620 static const char *
621 rt2_to_str(int res_type)
623 assert(res_type >= RT2_MIN && res_type <= RT2_MAX);
624 return (res2_types[res_type]);
627 /* Returns "ncp, "ncu", "loc", "enm", or "wlan" according to the scope */
628 static const char *
629 scope_to_str(int scope) {
630 switch (scope) {
631 case NWAM_SCOPE_GBL:
632 return ("global");
633 case NWAM_SCOPE_NCP:
634 return ("ncp");
635 case NWAM_SCOPE_NCU:
636 return ("ncu");
637 case NWAM_SCOPE_LOC:
638 return ("loc");
639 case NWAM_SCOPE_ENM:
640 return ("enm");
641 case NWAM_SCOPE_WLAN:
642 return ("wlan");
643 default:
644 return ("invalid");
648 /* Given an enm property and value, returns it as a string */
649 static const char *
650 propval_to_str(const char *propname, uint64_t value)
652 const char *str;
654 if (nwam_uint64_get_value_string(propname, value, &str) == NWAM_SUCCESS)
655 return (str);
656 return (NULL);
659 /* Given an int for a prop, returns it as string */
660 static const char *
661 pt_to_str(int prop_type)
663 assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
664 return (pt_types[prop_type]);
667 /* Return B_TRUE if string starts with "t" or is 1, B_FALSE otherwise */
668 static boolean_t
669 str_to_boolean(const char *str)
671 if (strncasecmp(str, "t", 1) == 0 || atoi(str) == 1)
672 return (B_TRUE);
673 else
674 return (B_FALSE);
678 * This is a separate function rather than a set of define's because of the
679 * gettext() wrapping.
683 * TRANSLATION_NOTE
684 * Each string below should have \t follow \n whenever needed; the
685 * initial \t and the terminal \n will be provided by the calling function.
688 static const char *
689 long_help(int cmd_num)
691 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
692 switch (cmd_num) {
693 case CMD_CANCEL:
694 return (gettext("Cancels the current configuration "
695 "changes."));
696 case CMD_CLEAR:
697 return (gettext("Clears the value for the specified "
698 "property."));
699 case CMD_COMMIT:
700 return (gettext("Commits the current configuration."));
701 case CMD_CREATE:
702 return (gettext("Creates a new profile or resource."));
703 case CMD_DESTROY:
704 return (gettext("Destroys the specified profile or "
705 "resource."));
706 case CMD_END:
707 return (gettext("Ends specification of a resource."));
708 case CMD_EXIT:
709 return (gettext("Exits the program."));
710 case CMD_EXPORT:
711 return (gettext("Exports the configuration."));
712 case CMD_GET:
713 return (gettext("Gets the value of the specified "
714 "property."));
715 case CMD_HELP:
716 return (gettext("Prints help message."));
717 case CMD_LIST:
718 return (gettext("Lists existing objects."));
719 case CMD_REVERT:
720 return (gettext("Reverts to the previous "
721 "configuration."));
722 case CMD_SELECT:
723 return (gettext("Selects a resource to modify."));
724 case CMD_SET:
725 return (gettext("Sets the value of the specified "
726 "property."));
727 case CMD_VERIFY:
728 return (gettext("Verifies an object."));
729 case CMD_WALKPROP:
730 return (gettext("Iterates over properties."));
731 default:
732 return (gettext("Unknown command."));
736 void
737 command_usage(int command)
739 if (command < CMD_MIN || command > CMD_MAX) {
740 nerr("Unknown command");
741 } else {
742 nerr("%s: %s: %s", gettext("Error"), gettext("usage"),
743 helptab[command].cmd_usage);
747 static void
748 long_usage(uint_t cmd_num)
750 (void) printf("%s: %s\n", gettext("usage"),
751 helptab[cmd_num].cmd_usage);
752 (void) printf("\t%s\n", long_help(cmd_num));
755 /* Prints usage for command line options */
756 static void
757 cmd_line_usage()
759 (void) printf("%s:\t%s\t\t\t\t(%s)\n", gettext("usage"), execname,
760 gettext("interactive-mode"));
761 (void) printf("\t%s <%s> [%s...]\n", execname, gettext("command"),
762 gettext("options"));
763 (void) printf("\t%s [-d] -f <%s>\n", execname, gettext("command-file"));
764 (void) printf("\t%s %s [<%s>]\n", execname, cmd_to_str(CMD_HELP),
765 gettext("command"));
768 /* Prints the line number of the current command if in command-file mode */
769 static void
770 print_lineno()
772 static int last_lineno;
774 /* lex_lineno has already been incremented in the lexer; compensate */
775 if (cmd_file_mode && lex_lineno > last_lineno) {
776 if (strcmp(cmd_file_name, "-") == 0)
777 (void) fprintf(stderr, gettext("On line %d:\n"),
778 lex_lineno - 1);
779 else
780 (void) fprintf(stderr, gettext("On line %d of %s:\n"),
781 lex_lineno - 1, cmd_file_name);
782 last_lineno = lex_lineno;
786 /* PRINTFLIKE1 */
787 void
788 nerr(const char *format, ...)
790 va_list alist;
792 print_lineno();
794 format = gettext(format);
795 va_start(alist, format);
796 (void) vfprintf(stderr, format, alist);
797 va_end(alist);
798 (void) fprintf(stderr, "\n");
800 saw_error = B_TRUE;
803 /* PRINTFLIKE2 */
804 static void
805 nwamerr(nwam_error_t err, const char *format, ...)
807 va_list alist;
809 print_lineno();
811 format = gettext(format);
812 va_start(alist, format);
813 (void) vfprintf(stderr, format, alist);
814 va_end(alist);
815 (void) fprintf(stderr, ": %s\n", nwam_strerror(err));
817 saw_error = B_TRUE;
820 void
821 properr(const char *prop)
823 nerr("Invalid property: '%s'", prop);
827 * If free_ncu_only == B_TRUE, only ncu handle is freed, ncp handle remains the
828 * same. Since nwam_ncp_free() takes care of its ncus, no need to explicitly
829 * call nwam_ncu_free() afterwards.
831 static void
832 free_handle(boolean_t free_ncu_only)
834 if (ncp_h != NULL) {
835 if (!free_ncu_only) {
836 nwam_ncp_free(ncp_h);
837 ncp_h = NULL;
838 ncu_h = NULL;
839 } else if (ncu_h != NULL) {
840 nwam_ncu_free(ncu_h);
841 ncu_h = NULL;
845 if (enm_h != NULL) {
846 nwam_enm_free(enm_h);
847 enm_h = NULL;
850 if (loc_h != NULL) {
851 nwam_loc_free(loc_h);
852 loc_h = NULL;
855 if (wlan_h != NULL) {
856 nwam_known_wlan_free(wlan_h);
857 wlan_h = NULL;
862 * On input, TRUE => yes, FALSE => no.
863 * On return, TRUE => 1, FALSE => no, could not ask => -1.
865 static int
866 ask_yesno(boolean_t default_answer, const char *question)
868 char line[64]; /* should be enough to answer yes or no */
870 if (!ok_to_prompt) {
871 saw_error = B_TRUE;
872 return (-1);
874 for (;;) {
875 if (printf("%s (%s)? ", gettext(question),
876 default_answer ? "[y]/n" : "y/[n]") < 0)
877 return (-1);
878 if (fgets(line, sizeof (line), stdin) == NULL)
879 return (-1);
881 if (line[0] == '\n')
882 return (default_answer ? 1 : 0);
883 if (tolower(line[0]) == 'y')
884 return (1);
885 if (tolower(line[0]) == 'n')
886 return (0);
890 /* This is the back-end helper function for read_input() below. */
891 static int
892 cleanup()
894 int answer;
896 if (!interactive_mode && !cmd_file_mode) {
898 * If we're not in interactive mode, and we're not in command
899 * file mode, then we must be in commands-from-the-command-line
900 * mode. As such, we can't loop back and ask for more input.
901 * It was OK to prompt for such things as whether or not to
902 * really delete something in the command handler called from
903 * yyparse() above, but "really quit?" makes no sense in this
904 * context. So disable prompting.
906 ok_to_prompt = B_FALSE;
908 if (need_to_commit) {
909 answer = ask_yesno(B_FALSE,
910 "Configuration not saved; really quit");
911 switch (answer) {
912 case -1:
913 /* issue error here */
914 return (NWAM_ERR);
915 case 1:
917 * don't want to save, just exit. handles are freed at
918 * end_func() or exit_func().
920 return (NWAM_OK);
921 default:
922 /* loop back to read input */
923 time_to_exit = B_FALSE;
924 yyin = stdin;
925 return (NWAM_REPEAT);
928 return (saw_error ? NWAM_ERR : NWAM_OK);
931 static int
932 string_to_yyin(char *string)
934 if ((yyin = tmpfile()) == NULL)
935 goto error;
936 if (fwrite(string, strlen(string), 1, yyin) != 1)
937 goto error;
938 if (fseek(yyin, 0, SEEK_SET) != 0)
939 goto error;
941 return (NWAM_OK);
943 error:
944 nerr("problem creating temporary file");
945 return (NWAM_ERR);
949 * read_input() is the driver of this program. It is a wrapper around
950 * yyparse(), printing appropriate prompts when needed, checking for
951 * exit conditions and reacting appropriately. This function is
952 * called when in interactive mode or command-file mode.
954 static int
955 read_input(void)
957 boolean_t yyin_is_a_tty = isatty(fileno(yyin));
959 * The prompt is "e> " or "e:t1:o1> " or "e:t1:o1:t2:o2> " where e is
960 * execname, t is resource type, o is object name.
962 char prompt[MAXPATHLEN + (2 * (NWAM_MAX_TYPE_LEN + NWAM_MAX_NAME_LEN))
963 + sizeof ("::::> ")];
964 char *line;
966 /* yyin should have been set to the appropriate (FILE *) if not stdin */
967 newline_terminated = B_TRUE;
968 for (;;) {
969 if (yyin_is_a_tty) {
970 if (newline_terminated) {
971 switch (current_scope) {
972 case NWAM_SCOPE_GBL:
973 (void) snprintf(prompt, sizeof (prompt),
974 "%s> ", execname);
975 break;
976 case NWAM_SCOPE_LOC:
977 case NWAM_SCOPE_ENM:
978 case NWAM_SCOPE_WLAN:
979 case NWAM_SCOPE_NCP:
980 (void) snprintf(prompt, sizeof (prompt),
981 "%s:%s:%s> ", execname,
982 rt1_to_str(obj1_type), obj1_name);
984 break;
985 case NWAM_SCOPE_NCU:
986 (void) snprintf(prompt, sizeof (prompt),
987 "%s:%s:%s:%s:%s> ", execname,
988 rt1_to_str(obj1_type), obj1_name,
989 rt2_to_str(obj2_type), obj2_name);
993 * If the user hits ^C then we want to catch it and
994 * start over. If the user hits EOF then we want to
995 * bail out.
997 line = gl_get_line(gl, prompt, NULL, -1);
998 if (gl_return_status(gl) == GLR_SIGNAL) {
999 gl_abandon_line(gl);
1000 continue;
1002 if (line == NULL)
1003 break;
1004 if (string_to_yyin(line) != NWAM_OK)
1005 break;
1006 while (!feof(yyin)) {
1007 yyparse();
1010 * If any command on a list of commands
1011 * give an error, don't continue with the
1012 * remaining commands.
1014 if (saw_error || time_to_exit)
1015 break;
1017 } else {
1018 yyparse();
1021 /* Bail out on an error in command-file mode. */
1022 if (saw_error && cmd_file_mode && !interactive_mode)
1023 time_to_exit = B_TRUE;
1024 if (time_to_exit || (!yyin_is_a_tty && feof(yyin)))
1025 break;
1027 return (cleanup());
1031 * This function is used in the interactive-mode scenario: it just calls
1032 * read_input() until we are done.
1034 static int
1035 do_interactive(void)
1037 int err;
1039 interactive_mode = B_TRUE;
1040 do {
1041 err = read_input();
1042 } while (err == NWAM_REPEAT);
1043 return (err);
1046 /* Calls the help_func() to print the usage of all commands */
1047 void
1048 help_wrap()
1050 cmd_t *help_cmd;
1052 if ((help_cmd = alloc_cmd()) == NULL)
1053 exit(NWAM_ERR);
1054 help_func(help_cmd);
1055 free_cmd(help_cmd);
1058 /* Check if the given command is allowed in the current scope */
1059 boolean_t
1060 check_scope(int cmd)
1062 /* allowed in all scopes */
1063 switch (cmd) {
1064 case CMD_END:
1065 case CMD_EXIT:
1066 case CMD_HELP:
1067 case CMD_LIST:
1068 case CMD_EXPORT:
1069 return (B_TRUE);
1071 /* scope-specific */
1072 switch (current_scope) {
1073 case NWAM_SCOPE_GBL:
1074 switch (cmd) {
1075 case CMD_CREATE:
1076 case CMD_DESTROY:
1077 case CMD_SELECT:
1078 return (B_TRUE);
1080 break;
1081 case NWAM_SCOPE_LOC:
1082 case NWAM_SCOPE_ENM:
1083 case NWAM_SCOPE_WLAN:
1084 case NWAM_SCOPE_NCU:
1085 switch (cmd) {
1086 case CMD_CANCEL:
1087 case CMD_CLEAR:
1088 case CMD_COMMIT:
1089 case CMD_GET:
1090 case CMD_REVERT:
1091 case CMD_SET:
1092 case CMD_VERIFY:
1093 case CMD_WALKPROP:
1094 return (B_TRUE);
1096 break;
1097 case NWAM_SCOPE_NCP:
1098 switch (cmd) {
1099 case CMD_CANCEL:
1100 case CMD_CREATE:
1101 case CMD_DESTROY:
1102 case CMD_SELECT:
1103 return (B_TRUE);
1105 break;
1106 default:
1107 nerr("Invalid scope");
1109 nerr("'%s' is not allowed at this scope", cmd_to_str(cmd));
1110 return (B_FALSE);
1113 /* Returns the active object type depending on which handle is not NULL */
1114 static nwam_object_type_t
1115 active_object_type()
1117 /* Check ncu_h before ncp_h, ncp_h must be loaded before ncu_h */
1118 if (ncu_h != NULL)
1119 return (NWAM_OBJECT_TYPE_NCU);
1120 else if (ncp_h != NULL)
1121 return (NWAM_OBJECT_TYPE_NCP);
1122 else if (loc_h != NULL)
1123 return (NWAM_OBJECT_TYPE_LOC);
1124 else if (enm_h != NULL)
1125 return (NWAM_OBJECT_TYPE_ENM);
1126 else if (wlan_h != NULL)
1127 return (NWAM_OBJECT_TYPE_KNOWN_WLAN);
1128 else
1129 return (NWAM_OBJECT_TYPE_UNKNOWN);
1132 /* Retrive the name of the object from its handle */
1133 static nwam_error_t
1134 object_name_from_handle(nwam_object_type_t object_type, void *handle,
1135 char **namep)
1137 switch (object_type) {
1138 case NWAM_OBJECT_TYPE_NCP:
1139 return (nwam_ncp_get_name(handle, namep));
1140 case NWAM_OBJECT_TYPE_NCU:
1141 return (nwam_ncu_get_name(handle, namep));
1142 case NWAM_OBJECT_TYPE_LOC:
1143 return (nwam_loc_get_name(handle, namep));
1144 case NWAM_OBJECT_TYPE_ENM:
1145 return (nwam_enm_get_name(handle, namep));
1146 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1147 return (nwam_known_wlan_get_name(handle, namep));
1149 return (NWAM_INVALID_ARG);
1152 static void
1153 do_commit()
1155 nwam_error_t ret = NWAM_SUCCESS;
1156 const char *errprop;
1158 if (!need_to_commit)
1159 return;
1161 switch (active_object_type()) {
1162 case NWAM_OBJECT_TYPE_NCU:
1163 ret = nwam_ncu_commit(ncu_h, 0);
1164 break;
1165 case NWAM_OBJECT_TYPE_ENM:
1166 ret = nwam_enm_commit(enm_h, 0);
1167 break;
1168 case NWAM_OBJECT_TYPE_LOC:
1169 ret = nwam_loc_commit(loc_h, 0);
1170 break;
1171 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1172 ret = nwam_known_wlan_commit(wlan_h, 0);
1173 break;
1176 if (ret == NWAM_SUCCESS) {
1177 need_to_commit = B_FALSE;
1178 if (interactive_mode)
1179 (void) printf(gettext("Committed changes\n"));
1180 } else {
1181 nwam_error_t verr;
1183 /* Find property that caused failure */
1184 switch (active_object_type()) {
1185 case NWAM_OBJECT_TYPE_NCU:
1186 verr = nwam_ncu_validate(ncu_h, &errprop);
1187 break;
1188 case NWAM_OBJECT_TYPE_ENM:
1189 verr = nwam_enm_validate(enm_h, &errprop);
1190 break;
1191 case NWAM_OBJECT_TYPE_LOC:
1192 verr = nwam_loc_validate(loc_h, &errprop);
1193 break;
1194 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1195 verr = nwam_known_wlan_validate(wlan_h, &errprop);
1196 break;
1199 if (verr != NWAM_SUCCESS)
1200 nwamerr(ret, "Commit error on property '%s'", errprop);
1201 else
1202 nwamerr(ret, "Commit error");
1207 * Saves the current configuration to persistent storage.
1209 /* ARGSUSED */
1210 void
1211 commit_func(cmd_t *cmd)
1213 if (!need_to_commit) {
1214 if (interactive_mode)
1215 (void) printf(gettext("Nothing to commit\n"));
1216 } else {
1217 do_commit();
1221 static void
1222 do_cancel()
1224 switch (current_scope) {
1225 case NWAM_SCOPE_NCU:
1226 current_scope = NWAM_SCOPE_NCP;
1227 obj2_type = 0;
1228 free_handle(B_TRUE);
1229 break;
1230 case NWAM_SCOPE_NCP:
1231 case NWAM_SCOPE_ENM:
1232 case NWAM_SCOPE_WLAN:
1233 case NWAM_SCOPE_LOC:
1234 current_scope = NWAM_SCOPE_GBL;
1235 obj1_type = 0;
1236 free_handle(B_FALSE);
1237 break;
1238 case NWAM_SCOPE_GBL:
1239 free_handle(B_FALSE);
1240 break;
1241 default:
1242 nerr("Invalid scope");
1243 return;
1245 need_to_commit = B_FALSE;
1249 * End operation on current scope and go up one scope.
1250 * Changes are not saved, no prompt either.
1252 /* ARGSUSED */
1253 void
1254 cancel_func(cmd_t *cmd)
1256 do_cancel();
1260 * Removes leading and trailing quotes from a string.
1261 * Caller must free returned string.
1263 static char *
1264 trim_quotes(const char *quoted_str)
1266 char *str;
1267 int end;
1269 /* export_func() and list_func() can pass NULL here */
1270 if (quoted_str == NULL)
1271 return (NULL);
1273 /* remove leading quote */
1274 if (quoted_str[0] == '"')
1275 str = strdup(quoted_str + 1);
1276 else
1277 str = strdup(quoted_str);
1278 if (str == NULL)
1279 return (NULL);
1281 /* remove trailing quote and newline */
1282 end = strlen(str) - 1;
1283 while (end >= 0 && (str[end] == '"' || str[end] == '\n'))
1284 end--;
1285 str[end+1] = 0;
1287 return (str);
1291 * Creates a new resource and enters the scope of that resource.
1292 * The new resource can also be a copy of an existing resource (-t option).
1293 * If in interactive mode, then after creation call walkprop_func()
1294 * to do walk the properties for the new object.
1296 void
1297 create_func(cmd_t *cmd)
1299 nwam_error_t ret = NWAM_SUCCESS;
1300 int c;
1301 boolean_t template = B_FALSE;
1302 char *newname = NULL, *oldname = NULL;
1303 cmd_t *walkprop_cmd;
1305 /* make sure right command at the right scope */
1306 if (current_scope == NWAM_SCOPE_GBL &&
1307 cmd->cmd_res2_type == RT2_NCU) {
1308 nerr("cannot create ncu at global scope");
1309 return;
1311 if (current_scope == NWAM_SCOPE_NCP &&
1312 cmd->cmd_res2_type != RT2_NCU) {
1313 nerr("Cannot create given object at this scope");
1314 return;
1317 assert(cmd->cmd_argc > 0);
1318 optind = 0;
1319 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "t:")) != EOF) {
1320 switch (c) {
1321 case 't':
1322 template = B_TRUE;
1323 break;
1324 default:
1325 command_usage(CMD_CREATE);
1326 return;
1330 if (!template) {
1331 /* no template given */
1332 /* argv[0] is name */
1333 newname = trim_quotes(cmd->cmd_argv[0]);
1334 if (cmd->cmd_res1_type == RT1_ENM) {
1335 ret = nwam_enm_create(newname, NULL, &enm_h);
1336 } else if (cmd->cmd_res1_type == RT1_LOC) {
1337 ret = nwam_loc_create(newname, &loc_h);
1338 } else if (cmd->cmd_res1_type == RT1_WLAN) {
1339 ret = nwam_known_wlan_create(newname, &wlan_h);
1340 } else if (cmd->cmd_res1_type == RT1_NCP &&
1341 current_scope == NWAM_SCOPE_GBL) {
1342 ret = nwam_ncp_create(newname, 0, &ncp_h);
1343 } else if (cmd->cmd_res2_type == RT2_NCU) {
1344 nwam_ncu_type_t ncu_type;
1345 nwam_ncu_class_t ncu_class;
1347 /* ncp must already be read */
1348 if (ncp_h == NULL) {
1349 nerr("Create error: NCP has not been read");
1350 goto done;
1353 ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
1354 ncu_type = nwam_ncu_class_to_type(ncu_class);
1355 ret = nwam_ncu_create(ncp_h, newname, ncu_type,
1356 ncu_class, &ncu_h);
1359 if (ret != NWAM_SUCCESS) {
1360 nwamerr(ret, "Create error");
1361 goto done;
1364 } else {
1365 /* template given */
1366 /* argv[0] is -t, argv[1] is old name, argv[2] is new name */
1367 oldname = trim_quotes(cmd->cmd_argv[1]);
1368 newname = trim_quotes(cmd->cmd_argv[2]);
1369 if (cmd->cmd_res1_type == RT1_ENM) {
1370 nwam_enm_handle_t oldenm_h;
1372 ret = nwam_enm_read(oldname, 0, &oldenm_h);
1373 if (ret != NWAM_SUCCESS)
1374 goto read_error;
1375 ret = nwam_enm_copy(oldenm_h, newname, &enm_h);
1376 nwam_enm_free(oldenm_h);
1377 } else if (cmd->cmd_res1_type == RT1_LOC) {
1378 nwam_loc_handle_t oldloc_h;
1380 ret = nwam_loc_read(oldname, 0, &oldloc_h);
1381 if (ret != NWAM_SUCCESS)
1382 goto read_error;
1383 ret = nwam_loc_copy(oldloc_h, newname, &loc_h);
1384 nwam_loc_free(oldloc_h);
1385 } else if (cmd->cmd_res1_type == RT1_WLAN) {
1386 nwam_known_wlan_handle_t oldwlan_h;
1388 ret = nwam_known_wlan_read(oldname, 0, &oldwlan_h);
1389 if (ret != NWAM_SUCCESS)
1390 goto read_error;
1391 ret = nwam_known_wlan_copy(oldwlan_h, newname, &wlan_h);
1392 nwam_known_wlan_free(oldwlan_h);
1393 } else if (cmd->cmd_res1_type == RT1_NCP &&
1394 current_scope == NWAM_SCOPE_GBL) {
1395 nwam_ncp_handle_t oldncp_h;
1397 ret = nwam_ncp_read(oldname, 0, &oldncp_h);
1398 if (ret != NWAM_SUCCESS)
1399 goto read_error;
1400 ret = nwam_ncp_copy(oldncp_h, newname, &ncp_h);
1401 nwam_ncp_free(oldncp_h);
1402 } else if (cmd->cmd_res2_type == RT2_NCU) {
1403 nwam_ncu_handle_t oldncu_h;
1404 nwam_ncu_type_t ncu_type;
1405 nwam_ncu_class_t ncu_class;
1407 /* ncp must already be read */
1408 if (ncp_h == NULL) {
1409 nerr("Copy error: NCP has not been read");
1410 goto done;
1412 ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
1413 ncu_type = nwam_ncu_class_to_type(ncu_class);
1414 ret = nwam_ncu_read(ncp_h, oldname, ncu_type, 0,
1415 &oldncu_h);
1416 if (ret != NWAM_SUCCESS)
1417 goto read_error;
1418 ret = nwam_ncu_copy(oldncu_h, newname, &ncu_h);
1419 nwam_ncu_free(oldncu_h);
1422 if (ret != NWAM_SUCCESS) {
1423 nwamerr(ret, "Copy error");
1424 goto done;
1428 if (current_scope == NWAM_SCOPE_GBL) {
1429 (void) strlcpy(obj1_name, newname, sizeof (obj1_name));
1430 obj1_type = cmd->cmd_res1_type;
1431 if (obj1_type == RT1_ENM)
1432 current_scope = NWAM_SCOPE_ENM;
1433 else if (obj1_type == RT1_LOC)
1434 current_scope = NWAM_SCOPE_LOC;
1435 else if (obj1_type == RT1_WLAN)
1436 current_scope = NWAM_SCOPE_WLAN;
1437 else if (obj1_type == RT1_NCP)
1438 current_scope = NWAM_SCOPE_NCP;
1439 } else {
1440 (void) strlcpy(obj2_name, newname, sizeof (obj2_name));
1441 current_scope = NWAM_SCOPE_NCU;
1442 obj2_type = cmd->cmd_res2_type;
1444 if (current_scope != NWAM_SCOPE_NCP)
1445 need_to_commit = B_TRUE;
1447 /* do a walk of the properties if in interactive mode */
1448 if (interactive_mode && current_scope != NWAM_SCOPE_NCP) {
1449 (void) printf(gettext("Created %s '%s'. "
1450 "Walking properties ...\n"),
1451 scope_to_str(current_scope), newname);
1452 if ((walkprop_cmd = alloc_cmd()) == NULL)
1453 goto done;
1454 walkprop_func(walkprop_cmd);
1455 free(walkprop_cmd);
1458 read_error:
1459 if (ret != NWAM_SUCCESS)
1460 nwamerr(ret, "Copy error reading '%s'", oldname);
1462 done:
1463 free(oldname);
1464 free(newname);
1467 /* Processing of return value for destroy_*_callback() */
1468 static int
1469 destroy_ret(nwam_object_type_t object_type, nwam_error_t ret, void *handle)
1471 if (ret == NWAM_ENTITY_NOT_DESTROYABLE) {
1472 /* log a message to stderr, but don't consider it an error */
1473 char *name;
1474 if (object_name_from_handle(object_type, handle, &name)
1475 == NWAM_SUCCESS) {
1476 (void) fprintf(stderr,
1477 gettext("%s '%s' cannot be removed\n"),
1478 nwam_object_type_to_string(object_type), name);
1479 free(name);
1481 return (0);
1484 if (ret == NWAM_SUCCESS || ret == NWAM_ENTITY_IN_USE)
1485 return (0);
1487 return (1);
1491 * NWAM_FLAG_DO_NOT_FREE is passed to nwam_*_destory() so that it does not
1492 * free the handle. The calling nwam_walk_*() function frees this handle
1493 * as it is the function that created the handle.
1495 * Objects that are not destroyable or are active cannot be destroyed.
1496 * Don't return error in these situations so the walk can continue.
1498 /* ARGSUSED */
1499 static int
1500 destroy_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
1502 /* The file is deleted, so NCUs are also removed */
1503 nwam_error_t ret = nwam_ncp_destroy(ncp, NWAM_FLAG_DO_NOT_FREE);
1504 return (destroy_ret(NWAM_OBJECT_TYPE_NCP, ret, ncp));
1507 /* ARGSUSED */
1508 static int
1509 destroy_loc_callback(nwam_loc_handle_t loc, void *arg)
1511 nwam_error_t ret = nwam_loc_destroy(loc, NWAM_FLAG_DO_NOT_FREE);
1512 return (destroy_ret(NWAM_OBJECT_TYPE_LOC, ret, loc));
1515 /* ARGSUSED */
1516 static int
1517 destroy_enm_callback(nwam_enm_handle_t enm, void *arg)
1519 nwam_error_t ret = nwam_enm_destroy(enm, NWAM_FLAG_DO_NOT_FREE);
1520 return (destroy_ret(NWAM_OBJECT_TYPE_ENM, ret, enm));
1523 /* ARGSUSED */
1524 static int
1525 destroy_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
1527 nwam_error_t ret = nwam_known_wlan_destroy(wlan, NWAM_FLAG_DO_NOT_FREE);
1528 return (destroy_ret(NWAM_OBJECT_TYPE_KNOWN_WLAN, ret, wlan));
1532 * Remove all existing configuration that are not read-only.
1533 * walk through all ncps, locs, enms, wlans and destroy each one.
1535 static nwam_error_t
1536 destroy_all(void)
1538 nwam_error_t ret;
1540 assert(remove_all_configurations);
1542 ret = nwam_walk_ncps(destroy_ncp_callback, NULL, 0, NULL);
1543 if (ret != NWAM_SUCCESS)
1544 goto done;
1546 ret = nwam_walk_enms(destroy_enm_callback, NULL,
1547 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
1548 if (ret != NWAM_SUCCESS)
1549 goto done;
1551 ret = nwam_walk_locs(destroy_loc_callback, NULL,
1552 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
1553 if (ret != NWAM_SUCCESS)
1554 goto done;
1556 ret = nwam_walk_known_wlans(destroy_wlan_callback, NULL, 0, NULL);
1557 if (ret != NWAM_SUCCESS)
1558 goto done;
1560 if (interactive_mode)
1561 (void) printf(gettext("All user-defined entities destroyed\n"));
1562 remove_all_configurations = B_FALSE;
1564 done:
1565 if (ret != NWAM_SUCCESS) {
1566 nwamerr(ret, "Destroy error: "
1567 "could not destroy all configurations");
1569 return (ret);
1573 * Destroys an instance in persistent repository, and is permanent.
1574 * If interactive mode, it is allowed at global scope only
1575 * option -a destroys everything.
1577 void
1578 destroy_func(cmd_t *cmd)
1580 nwam_error_t ret;
1581 char *name, *realname = NULL;
1583 if (current_scope == NWAM_SCOPE_NCP &&
1584 (cmd->cmd_res1_type == RT1_ENM || cmd->cmd_res1_type == RT1_LOC ||
1585 cmd->cmd_res1_type == RT1_WLAN)) {
1586 nerr("Destroy error: only NCUs can be destroyed in NCP scope");
1587 return;
1590 assert(cmd->cmd_argc > 0);
1592 /* res1_type is -1 if -a flag is used */
1593 if (cmd->cmd_res1_type == -1) {
1594 int c;
1596 if (current_scope != NWAM_SCOPE_GBL) {
1597 nerr("Cannot destroy all configurations in a "
1598 "non-global scope");
1599 return;
1602 optind = 0;
1603 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "a")) != EOF) {
1604 switch (c) {
1605 case 'a':
1606 remove_all_configurations = B_TRUE;
1607 break;
1608 default:
1609 command_usage(CMD_DESTROY);
1610 return;
1613 if (remove_all_configurations) {
1614 (void) destroy_all();
1615 return;
1619 /* argv[0] is name */
1620 name = trim_quotes(cmd->cmd_argv[0]);
1621 if (cmd->cmd_res2_type == RT2_NCU) {
1622 nwam_ncu_type_t ncu_type;
1623 nwam_ncu_class_t ncu_class;
1625 /* ncp must already be read */
1626 if (ncp_h == NULL) {
1627 nerr("Destroy ncu error: NCP has not been read");
1628 return;
1630 ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
1631 ncu_type = nwam_ncu_class_to_type(ncu_class);
1632 ret = nwam_ncu_read(ncp_h, name, ncu_type, 0, &ncu_h);
1633 if (ret != NWAM_SUCCESS)
1634 goto done;
1635 (void) object_name_from_handle(NWAM_OBJECT_TYPE_NCU, ncu_h,
1636 &realname);
1637 ret = nwam_ncu_destroy(ncu_h, 0);
1638 ncu_h = NULL;
1639 } else if (cmd->cmd_res1_type == RT1_ENM) {
1640 if ((ret = nwam_enm_read(name, 0, &enm_h)) != NWAM_SUCCESS)
1641 goto done;
1642 (void) object_name_from_handle(NWAM_OBJECT_TYPE_ENM, enm_h,
1643 &realname);
1644 ret = nwam_enm_destroy(enm_h, 0);
1645 enm_h = NULL;
1646 } else if (cmd->cmd_res1_type == RT1_LOC) {
1647 if ((ret = nwam_loc_read(name, 0, &loc_h)) != NWAM_SUCCESS)
1648 goto done;
1649 (void) object_name_from_handle(NWAM_OBJECT_TYPE_LOC, loc_h,
1650 &realname);
1651 ret = nwam_loc_destroy(loc_h, 0);
1652 loc_h = NULL;
1653 } else if (cmd->cmd_res1_type == RT1_WLAN) {
1654 if ((ret = nwam_known_wlan_read(name, 0, &wlan_h))
1655 != NWAM_SUCCESS)
1656 goto done;
1657 (void) object_name_from_handle(NWAM_OBJECT_TYPE_KNOWN_WLAN,
1658 wlan_h, &realname);
1659 ret = nwam_known_wlan_destroy(wlan_h, 0);
1660 wlan_h = NULL;
1661 } else if (cmd->cmd_res1_type == RT1_NCP) {
1662 if ((ret = nwam_ncp_read(name, 0, &ncp_h)) != NWAM_SUCCESS)
1663 goto done;
1664 (void) object_name_from_handle(NWAM_OBJECT_TYPE_NCP, ncp_h,
1665 &realname);
1666 ret = nwam_ncp_destroy(ncp_h, 0);
1667 ncp_h = NULL;
1668 } else {
1669 nerr("Destroy error: unknown object-type");
1672 done:
1673 if (ret == NWAM_ENTITY_IN_USE) {
1674 nerr("Destroy error: active entity cannot be destroyed");
1675 } else if (ret != NWAM_SUCCESS) {
1676 nwamerr(ret, "Destroy error");
1677 } else if (interactive_mode) {
1678 (void) printf(gettext("Destroyed %s '%s'\n"),
1679 (cmd->cmd_res2_type == RT2_NCU ?
1680 rt2_to_str(cmd->cmd_res2_type) :
1681 rt1_to_str(cmd->cmd_res1_type)),
1682 realname != NULL ? realname : name);
1684 free(name);
1685 free(realname);
1689 * End operation on current scope and go up one scope.
1690 * Changes are saved.
1692 /* ARGSUSED */
1693 void
1694 end_func(cmd_t *cmd)
1696 /* if need_to_commit is set, commit changes */
1697 if (need_to_commit)
1698 do_commit();
1701 * Call do_cancel() to go up one scope. If commit fails,
1702 * need_to_commit is not reset and users are asked if they want to end.
1704 if (!need_to_commit ||
1705 (need_to_commit && (ask_yesno(B_FALSE,
1706 "Configuration not saved; really end")) == 1)) {
1707 /* set time_to_exit if in global scope */
1708 if (current_scope == NWAM_SCOPE_GBL)
1709 time_to_exit = B_TRUE;
1710 /* call do_cancel() to go up one scope */
1711 do_cancel();
1716 * Exit immediately. Configuration changes are saved by calling end_func().
1718 /* ARGSUSED */
1719 void
1720 exit_func(cmd_t *cmd)
1722 cmd_t *end_cmd;
1724 if (need_to_commit) {
1725 if ((end_cmd = alloc_cmd()) == NULL) {
1726 nerr("Exit error");
1727 return;
1729 end_func(end_cmd);
1730 free_cmd(end_cmd);
1734 * If need_to_commit is still set, then the commit failed.
1735 * Otherwise, exit.
1737 if (!need_to_commit)
1738 time_to_exit = B_TRUE;
1741 void
1742 help_func(cmd_t *cmd)
1744 int i;
1746 if (cmd->cmd_argc == 0) {
1747 (void) printf(gettext("commands:\n"));
1748 for (i = CMD_MIN; i <= CMD_MAX; i++)
1749 (void) printf("\t%s\n", helptab[i].cmd_usage);
1750 return;
1753 for (i = CMD_MIN; i <= CMD_MAX; i++) {
1754 if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) {
1755 long_usage(i);
1756 return;
1759 (void) fprintf(stderr, gettext("Unknown command: '%s'\n"),
1760 cmd->cmd_argv[0]);
1761 help_wrap();
1765 * Revert configuration of an instance to latest previous version.
1766 * Free the handle and read again.
1768 /* ARGSUSED */
1769 void
1770 revert_func(cmd_t *cmd)
1772 nwam_error_t ret;
1773 char *name = NULL;
1774 nwam_ncu_type_t ncu_type;
1775 nwam_object_type_t object_type = active_object_type();
1777 switch (object_type) {
1778 case NWAM_OBJECT_TYPE_NCU:
1779 /* retrieve name and type to use later */
1780 if ((ret = nwam_ncu_get_ncu_type(ncu_h, &ncu_type))
1781 != NWAM_SUCCESS) {
1782 nwamerr(ret, "Revert error: Get ncu type error");
1783 return;
1785 if ((ret = nwam_ncu_get_name(ncu_h, &name)) != NWAM_SUCCESS)
1786 goto name_error;
1787 nwam_ncu_free(ncu_h);
1788 ncu_h = NULL;
1789 ret = nwam_ncu_read(ncp_h, name, ncu_type, 0, &ncu_h);
1790 break;
1791 case NWAM_OBJECT_TYPE_ENM:
1792 if ((ret = nwam_enm_get_name(enm_h, &name)) != NWAM_SUCCESS)
1793 goto name_error;
1794 nwam_enm_free(enm_h);
1795 enm_h = NULL;
1796 ret = nwam_enm_read(name, 0, &enm_h);
1797 break;
1798 case NWAM_OBJECT_TYPE_LOC:
1799 if ((ret = nwam_loc_get_name(loc_h, &name)) != NWAM_SUCCESS)
1800 goto name_error;
1801 nwam_loc_free(loc_h);
1802 loc_h = NULL;
1803 ret = nwam_loc_read(name, 0, &loc_h);
1804 break;
1805 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1806 if ((ret = nwam_known_wlan_get_name(wlan_h, &name))
1807 != NWAM_SUCCESS)
1808 goto name_error;
1809 nwam_known_wlan_free(wlan_h);
1810 wlan_h = NULL;
1811 ret = nwam_known_wlan_read(name, 0, &wlan_h);
1812 break;
1815 /* Exit this scope because handle already freed (call do_cancel()) */
1816 need_to_commit = B_FALSE;
1818 if (ret != NWAM_SUCCESS) {
1819 if (ret == NWAM_ENTITY_NOT_FOUND) {
1820 nerr("%s '%s' does not exist to revert to, removing it",
1821 nwam_object_type_to_string(object_type), name);
1822 } else {
1823 nwamerr(ret, "Revert error");
1825 do_cancel();
1827 free(name);
1828 return;
1830 name_error:
1831 if (ret != NWAM_SUCCESS)
1832 nwamerr(ret, "Revert error: get name error");
1836 * Load a resource from persistent repository and enter the scope
1837 * of that resource.
1839 void
1840 select_func(cmd_t *cmd)
1842 nwam_error_t ret;
1843 char *name, *realname = NULL;
1845 assert(cmd->cmd_argc > 0);
1846 if (current_scope == NWAM_SCOPE_NCP && cmd->cmd_res2_type != RT2_NCU) {
1847 nerr("cannot select '%s' at this scope",
1848 rt1_to_str(cmd->cmd_res1_type));
1849 return;
1852 /* argv[0] is name */
1853 name = trim_quotes(cmd->cmd_argv[0]);
1854 switch (cmd->cmd_res1_type) {
1855 case RT1_LOC:
1856 ret = nwam_loc_read(name, 0, &loc_h);
1857 if (ret == NWAM_SUCCESS) {
1858 current_scope = NWAM_SCOPE_LOC;
1859 (void) object_name_from_handle(NWAM_OBJECT_TYPE_LOC,
1860 loc_h, &realname);
1862 break;
1863 case RT1_ENM:
1864 ret = nwam_enm_read(name, 0, &enm_h);
1865 if (ret == NWAM_SUCCESS) {
1866 current_scope = NWAM_SCOPE_ENM;
1867 (void) object_name_from_handle(NWAM_OBJECT_TYPE_ENM,
1868 enm_h, &realname);
1870 break;
1871 case RT1_WLAN:
1872 ret = nwam_known_wlan_read(name, 0, &wlan_h);
1873 if (ret == NWAM_SUCCESS) {
1874 current_scope = NWAM_SCOPE_WLAN;
1875 (void) object_name_from_handle
1876 (NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan_h, &realname);
1878 break;
1879 case RT1_NCP:
1880 if (cmd->cmd_res2_type == RT2_NCU) {
1881 nwam_ncu_type_t ncu_type;
1882 nwam_ncu_class_t ncu_class;
1884 /* ncp must already be read */
1885 if (ncp_h == NULL) {
1886 nerr("Select error: NCP has not been read");
1887 free(name);
1888 return;
1890 ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
1891 ncu_type = nwam_ncu_class_to_type(ncu_class);
1892 ret = nwam_ncu_read(ncp_h, name, ncu_type, 0, &ncu_h);
1893 if (ret == NWAM_SUCCESS) {
1894 current_scope = NWAM_SCOPE_NCU;
1895 (void) object_name_from_handle
1896 (NWAM_OBJECT_TYPE_NCU, ncu_h, &realname);
1898 } else {
1899 ret = nwam_ncp_read(name, 0, &ncp_h);
1900 if (ret == NWAM_SUCCESS) {
1901 current_scope = NWAM_SCOPE_NCP;
1902 (void) object_name_from_handle
1903 (NWAM_OBJECT_TYPE_NCP, ncp_h, &realname);
1906 break;
1907 default:
1908 nerr("Select error: unknown object-type");
1909 free(name);
1910 return;
1913 if (ret != NWAM_SUCCESS) {
1914 nwamerr(ret, "Select error");
1915 } else {
1916 /* set the obj*_name or obj*_type depending on current scope */
1917 if (current_scope == NWAM_SCOPE_NCU) {
1918 obj2_type = RT2_NCU;
1919 (void) strlcpy(obj2_name,
1920 realname != NULL ? realname : name,
1921 sizeof (obj2_name));
1922 } else {
1923 (void) strlcpy(obj1_name,
1924 realname != NULL ? realname : name,
1925 sizeof (obj1_name));
1926 obj1_type = cmd->cmd_res1_type;
1929 free(name);
1930 free(realname);
1933 /* Given an int for prop, returns it as string */
1934 static const char *
1935 pt_to_prop_name(nwam_object_type_t object_type, int pt_type)
1937 int i;
1938 prop_table_entry_t *prop_table = get_prop_table(object_type);
1940 for (i = 0; prop_table[i].pte_name != NULL; i++) {
1941 if (pt_type == prop_table[i].pte_type)
1942 return (prop_table[i].pte_name);
1944 return (NULL);
1947 /* Given a prop as a string, returns it as an int */
1948 static int
1949 prop_to_pt(nwam_object_type_t object_type, const char *prop)
1951 int i;
1952 prop_table_entry_t *prop_table = get_prop_table(object_type);
1954 for (i = 0; prop_table[i].pte_name != NULL; i++) {
1955 if (strcmp(prop, prop_table[i].pte_name) == 0)
1956 return (prop_table[i].pte_type);
1958 return (-1);
1961 /* Given a prop as an int, returns its type (nwam_value_type_t) */
1962 static nwam_value_type_t
1963 prop_value_type(nwam_object_type_t object_type, const char *prop)
1965 nwam_error_t ret;
1966 nwam_value_type_t value_type;
1968 switch (object_type) {
1969 case NWAM_OBJECT_TYPE_NCU:
1970 ret = nwam_ncu_get_prop_type(prop, &value_type);
1971 break;
1972 case NWAM_OBJECT_TYPE_LOC:
1973 ret = nwam_loc_get_prop_type(prop, &value_type);
1974 break;
1975 case NWAM_OBJECT_TYPE_ENM:
1976 ret = nwam_enm_get_prop_type(prop, &value_type);
1977 break;
1978 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1979 ret = nwam_known_wlan_get_prop_type(prop, &value_type);
1980 break;
1983 if (ret != NWAM_SUCCESS)
1984 value_type = NWAM_VALUE_TYPE_UNKNOWN;
1986 return (value_type);
1990 * Converts input_str to an array nwam_value.
1991 * If is_list_prop, break input_str into array of strings first.
1993 static nwam_value_t
1994 str_to_nwam_value(nwam_object_type_t object_type, char *input_str, int pt_type,
1995 boolean_t is_list_prop)
1997 int i, n = 0, ret;
1998 nwam_value_t data;
1999 char **val;
2000 int max_str_num;
2002 nwam_value_type_t value_type;
2003 int64_t *int_vals;
2004 uint64_t *uint_vals;
2005 boolean_t *boolean_vals;
2008 * Worst case is that each char separated by DELIMITER, so the
2009 * max number of sub strings is half of string length + 1.
2011 max_str_num = strlen(input_str) / 2 + 1;
2013 val = calloc(max_str_num, sizeof (char *));
2014 if (val == NULL) {
2015 nerr("Out of memory");
2016 return (NULL);
2019 if (is_list_prop) {
2020 char *tmp, *next;
2022 * Break down input_str and save as array of sub strings.
2023 * Set num as the number of the sub strings.
2024 * Use nwam_tokenize_by_unescaped_delim() rather than strtok()
2025 * because DELIMITER may be escaped
2027 tmp = (char *)input_str;
2028 while ((tmp = nwam_tokenize_by_unescaped_delim(tmp,
2029 NWAM_VALUE_DELIMITER_CHAR, &next)) != NULL) {
2030 val[n++] = trim_quotes(tmp);
2031 tmp = next;
2033 } else {
2034 val[n++] = trim_quotes(input_str);
2037 /* initialize int_vals or booleans_vals depending on pt_type */
2038 value_type = prop_value_type(object_type,
2039 pt_to_prop_name(object_type, pt_type));
2040 if (value_type == NWAM_VALUE_TYPE_INT64) {
2041 int_vals = calloc(n, sizeof (int64_t));
2042 if (int_vals == NULL) {
2043 nerr("Out of memory");
2044 array_free((void **)val, max_str_num);
2045 return (NULL);
2047 } else if (value_type == NWAM_VALUE_TYPE_UINT64) {
2048 uint_vals = calloc(n, sizeof (uint64_t));
2049 if (uint_vals == NULL) {
2050 nerr("Out of memory");
2051 array_free((void **)val, max_str_num);
2052 return (NULL);
2054 } else if (value_type == NWAM_VALUE_TYPE_BOOLEAN) {
2055 boolean_vals = calloc(n, sizeof (boolean_t));
2056 if (boolean_vals == NULL) {
2057 nerr("Out of memory");
2058 array_free((void **)val, max_str_num);
2059 return (NULL);
2062 /* set the appropriate array */
2063 for (i = 0; i < n; i++) {
2064 switch (value_type) {
2065 case NWAM_VALUE_TYPE_STRING:
2066 /* nothing to do - val already has the char** array */
2067 break;
2068 case NWAM_VALUE_TYPE_INT64:
2070 int_vals[i] = (int64_t)atoi(val[i]);
2071 break;
2073 case NWAM_VALUE_TYPE_UINT64:
2075 uint64_t str_as_enum;
2076 char *endptr;
2078 ret = nwam_value_string_get_uint64(
2079 pt_to_prop_name(object_type, pt_type),
2080 val[i], &str_as_enum);
2082 * Returns _SUCCESS if value for enum is valid.
2083 * Returns _INVALID_ARG if property is not an enum.
2085 if (ret == NWAM_SUCCESS) {
2086 uint_vals[i] = str_as_enum;
2087 } else if (ret == NWAM_INVALID_ARG) {
2088 uint_vals[i] = strtoul(val[i], &endptr, 10);
2089 /* verify conversion is valid */
2090 if (endptr == val[i]) {
2091 free(uint_vals);
2092 array_free((void **)val, max_str_num);
2093 return (NULL);
2095 } else {
2096 free(uint_vals);
2097 array_free((void **)val, max_str_num);
2098 return (NULL);
2100 break;
2102 case NWAM_VALUE_TYPE_BOOLEAN:
2103 boolean_vals[i] = str_to_boolean(val[i]);
2104 break;
2105 default:
2106 array_free((void **)val, max_str_num);
2107 return (NULL);
2111 /* create nwam_value_t */
2112 if (value_type == NWAM_VALUE_TYPE_STRING) {
2113 ret = nwam_value_create_string_array(val, n, &data);
2114 } else if (value_type == NWAM_VALUE_TYPE_INT64) {
2115 ret = nwam_value_create_int64_array(int_vals, n, &data);
2116 free(int_vals);
2117 } else if (value_type == NWAM_VALUE_TYPE_UINT64) {
2118 ret = nwam_value_create_uint64_array(uint_vals, n, &data);
2119 free(uint_vals);
2120 } else if (value_type == NWAM_VALUE_TYPE_BOOLEAN) {
2121 ret = nwam_value_create_boolean_array(boolean_vals, n, &data);
2122 free(boolean_vals);
2124 array_free((void **)val, max_str_num);
2126 if (ret != NWAM_SUCCESS) {
2127 nwamerr(ret, "Failed creating nwam_value");
2128 return (NULL);
2131 return (data);
2135 * Displaying/Skipping of properties
2136 * ---------------------------------
2138 * This table shows if a specific property should be shown if some
2139 * other property has a specific value. This table is used by
2140 * show_prop_test(), which is called by set_func() and walkprop_func().
2142 * An entry in the table looks like:
2143 * { property1, property2, { val1, val2, -1 } }
2144 * This is read as:
2145 * "show property1 only if property2 has value val1 or val2"
2147 * NB: If a property does not appear in this table, then that implies
2148 * that the property is always shown.
2150 * A property can have more than one rule. In such a case, the property is
2151 * displayed only any of the rules is satisfied. This checking, however,
2152 * is recursive. If a rule says that a property can be displayed, then the
2153 * property that's checked should also satisfy its rules. In the above
2154 * example, if property1 is to be displayed, then property2 should also
2155 * satisfy its rules and be displayable. This recursion is necessary as
2156 * properties that are not displayed (because rules are not satisfied) are
2157 * not deleted.
2160 /* The most number of values in pde_checkvals below */
2161 #define NWAM_CHECKVALS_MAX 5
2163 typedef struct prop_display_entry {
2164 const char *pde_name; /* property to show */
2165 const char *pde_checkname; /* property to check */
2166 int64_t pde_checkvals[NWAM_CHECKVALS_MAX]; /* show prop for these */
2167 } prop_display_entry_t;
2169 /* Rules for showing properties: commented for clarity */
2172 * Rules for NCUs
2173 * NB: There is no need to have an entry if a property is for IP only.
2174 * This is taken care of in libnwam_ncp.c
2176 static prop_display_entry_t ncu_prop_display_entry_table[] = {
2177 /* show priority-{group,mode} if activation == prioritized */
2178 { NWAM_NCU_PROP_PRIORITY_GROUP, NWAM_NCU_PROP_ACTIVATION_MODE,
2179 { NWAM_ACTIVATION_MODE_PRIORITIZED, -1 } },
2180 { NWAM_NCU_PROP_PRIORITY_MODE, NWAM_NCU_PROP_ACTIVATION_MODE,
2181 { NWAM_ACTIVATION_MODE_PRIORITIZED, -1 } },
2182 /* show ipv4-addrsrc if ip-version == ipv4 */
2183 { NWAM_NCU_PROP_IPV4_ADDRSRC, NWAM_NCU_PROP_IP_VERSION,
2184 { IPV4_VERSION, -1 } },
2185 /* show ipv4-addr if ipv4-addrsrc == static */
2186 { NWAM_NCU_PROP_IPV4_ADDR, NWAM_NCU_PROP_IPV4_ADDRSRC,
2187 { NWAM_ADDRSRC_STATIC, -1 } },
2188 /* show ipv4-default-route if ip-version == ipv4 */
2189 { NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE, NWAM_NCU_PROP_IP_VERSION,
2190 { IPV4_VERSION, -1 } },
2191 /* show ipv6-addrsrc if ip-version == ipv6 */
2192 { NWAM_NCU_PROP_IPV6_ADDRSRC, NWAM_NCU_PROP_IP_VERSION,
2193 { IPV6_VERSION, -1 } },
2194 /* show ipv6-addr if ipv6-addrsrc == static */
2195 { NWAM_NCU_PROP_IPV6_ADDR, NWAM_NCU_PROP_IPV6_ADDRSRC,
2196 { NWAM_ADDRSRC_STATIC, -1 } },
2197 /* show ipv6-default-route if ip-version == ipv6 */
2198 { NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE, NWAM_NCU_PROP_IP_VERSION,
2199 { IPV6_VERSION, -1 } },
2200 { NULL, NULL, { -1 } }
2203 /* Rules for ENMs */
2204 static prop_display_entry_t enm_prop_display_entry_table[] = {
2205 /* show conditions if activation-mode == conditional-{all,any} */
2206 { NWAM_ENM_PROP_CONDITIONS, NWAM_ENM_PROP_ACTIVATION_MODE,
2207 { NWAM_ACTIVATION_MODE_CONDITIONAL_ALL,
2208 NWAM_ACTIVATION_MODE_CONDITIONAL_ANY, -1 } },
2209 { NULL, NULL, { -1 } }
2212 /* Rules for LOCations */
2213 static prop_display_entry_t loc_prop_display_entry_table[] = {
2214 /* show conditions if activation-mode == conditional-{all,any} */
2215 { NWAM_LOC_PROP_CONDITIONS, NWAM_LOC_PROP_ACTIVATION_MODE,
2216 { NWAM_ACTIVATION_MODE_CONDITIONAL_ALL,
2217 NWAM_ACTIVATION_MODE_CONDITIONAL_ANY, -1 } },
2218 /* show dns-nameservice-configsrc if nameservices == dns */
2219 { NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC, NWAM_LOC_PROP_NAMESERVICES,
2220 { NWAM_NAMESERVICES_DNS, -1 } },
2221 /* show other DNS options if dns-nameservices-configsrc == manual */
2222 { NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN,
2223 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
2224 { NWAM_CONFIGSRC_MANUAL, -1 } },
2225 { NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS,
2226 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
2227 { NWAM_CONFIGSRC_MANUAL, -1 } },
2228 { NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH,
2229 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
2230 { NWAM_CONFIGSRC_MANUAL, -1 } },
2231 /* show nis-nameservice-configsrc if nameservices == nis */
2232 { NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC, NWAM_LOC_PROP_NAMESERVICES,
2233 { NWAM_NAMESERVICES_NIS, -1 } },
2234 /* show nis-nameservice-servers if nis-nameservice-configsrc = manual */
2235 { NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS,
2236 NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
2237 { NWAM_CONFIGSRC_MANUAL, -1 } },
2238 /* show ldap-nameservice-configsrc if nameservices == ldap */
2239 { NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC, NWAM_LOC_PROP_NAMESERVICES,
2240 { NWAM_NAMESERVICES_LDAP, -1 } },
2241 /* show ldap-nameservice-servers if ldap-nameservice-configsrc=manual */
2242 { NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS,
2243 NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
2244 { NWAM_CONFIGSRC_MANUAL, -1 } },
2245 /* show default-domain if {nis,ldap}-nameservice-configsrc == manual */
2246 { NWAM_LOC_PROP_DEFAULT_DOMAIN, NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
2247 { NWAM_CONFIGSRC_MANUAL, -1 } },
2248 { NWAM_LOC_PROP_DEFAULT_DOMAIN,
2249 NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
2250 { NWAM_CONFIGSRC_MANUAL, -1 } },
2251 { NULL, NULL, { -1 } }
2254 /* Rules for Known WLANs */
2255 static prop_display_entry_t wlan_prop_display_entry_table[] = {
2256 /* no rules for WLANs */
2257 { NULL, NULL, { -1 } }
2260 /* Returns the appropriate rules table for the given object type */
2261 static prop_display_entry_t *
2262 get_prop_display_table(nwam_object_type_t object_type)
2264 switch (object_type) {
2265 case NWAM_OBJECT_TYPE_NCU:
2266 return (ncu_prop_display_entry_table);
2267 case NWAM_OBJECT_TYPE_LOC:
2268 return (loc_prop_display_entry_table);
2269 case NWAM_OBJECT_TYPE_ENM:
2270 return (enm_prop_display_entry_table);
2271 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2272 return (wlan_prop_display_entry_table);
2274 return (NULL);
2278 * Tests whether prop must be shown during a walk depending on the
2279 * value of a different property.
2281 * This function is also used by set_func() to determine whether the
2282 * property being set should be allowed or not. If the property
2283 * would not be displayed in a walk, then it should not be set.
2285 * The checked_props and num_checked arguments are used to avoid circular
2286 * dependencies between properties. When this function recursively calls
2287 * itself, it adds the property that it just checked to the checked_props
2288 * list.
2290 static boolean_t
2291 show_prop_test(nwam_object_type_t object_type, const char *prop,
2292 prop_display_entry_t *display_list, char **checked_props, int num_checked)
2294 nwam_error_t ret;
2295 nwam_value_t prop_val;
2296 nwam_value_type_t prop_type;
2297 int i, j, k;
2298 boolean_t prop_found = B_FALSE, show_prop = B_FALSE;
2301 * Check if this property has already been checked previously in
2302 * the recursion. If so, return B_FALSE so that the initial prop
2303 * is not displayed.
2305 for (i = 0; i < num_checked; i++) {
2306 if (strcmp(prop, checked_props[i]) == 0) {
2307 free(checked_props);
2308 return (B_FALSE);
2312 for (i = 0; display_list[i].pde_name != NULL; i++) {
2313 if (strcmp(prop, display_list[i].pde_name) != 0)
2314 continue;
2315 prop_found = B_TRUE;
2317 /* get the value(s) of the (other) property to check */
2318 switch (object_type) {
2319 case NWAM_OBJECT_TYPE_NCU:
2320 ret = nwam_ncu_get_prop_value(ncu_h,
2321 display_list[i].pde_checkname, &prop_val);
2322 break;
2323 case NWAM_OBJECT_TYPE_LOC:
2324 ret = nwam_loc_get_prop_value(loc_h,
2325 display_list[i].pde_checkname, &prop_val);
2326 break;
2327 case NWAM_OBJECT_TYPE_ENM:
2328 ret = nwam_enm_get_prop_value(enm_h,
2329 display_list[i].pde_checkname, &prop_val);
2330 break;
2331 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2332 return (B_TRUE);
2334 if (ret != NWAM_SUCCESS)
2335 continue;
2337 /* prop_val may contain a uint64 array or a boolean */
2338 if (nwam_value_get_type(prop_val, &prop_type) != NWAM_SUCCESS)
2339 continue;
2341 if (prop_type == NWAM_VALUE_TYPE_UINT64) {
2342 uint64_t *prop_uvals;
2343 int64_t *check_uvals;
2344 uint_t numvals;
2346 if (nwam_value_get_uint64_array(prop_val, &prop_uvals,
2347 &numvals) != NWAM_SUCCESS) {
2348 nwam_value_free(prop_val);
2349 continue;
2352 /* for each value in uvals, check each value in table */
2353 for (j = 0; j < numvals; j++) {
2354 check_uvals = display_list[i].pde_checkvals;
2355 for (k = 0; check_uvals[k] != -1; k++) {
2356 /* show if uvals[j] matches */
2357 if (prop_uvals[j] ==
2358 (uint64_t)check_uvals[k]) {
2359 show_prop = B_TRUE;
2360 goto next_rule;
2364 } else if (prop_type == NWAM_VALUE_TYPE_BOOLEAN) {
2365 boolean_t bval;
2367 if (nwam_value_get_boolean(prop_val, &bval) !=
2368 NWAM_SUCCESS) {
2369 nwam_value_free(prop_val);
2370 continue;
2373 for (k = 0;
2374 display_list[i].pde_checkvals[k] != -1;
2375 k++) {
2376 /* show if bval matches */
2377 if (bval == (boolean_t)
2378 display_list[i].pde_checkvals[k]) {
2379 show_prop = B_TRUE;
2380 goto next_rule;
2385 next_rule:
2386 nwam_value_free(prop_val);
2388 * If show_prop is set, then a rule is satisfied; no need to
2389 * check other rules for this prop. However, recursively
2390 * check if the checked prop (pde_checkname) satisfies its
2391 * rules. Also, update the check_props array with this prop.
2393 if (show_prop) {
2394 char **newprops = reallocarray(checked_props,
2395 ++num_checked, sizeof (char *));
2396 if (newprops == NULL) {
2397 free(checked_props);
2398 return (B_FALSE);
2400 checked_props = newprops;
2401 checked_props[num_checked - 1] = (char *)prop;
2403 return (show_prop_test(object_type,
2404 display_list[i].pde_checkname, display_list,
2405 checked_props, num_checked));
2410 * If we are here and prop_found is set, it means that no rules were
2411 * satisfied by prop; return B_FALSE. If prop_found is not set, then
2412 * prop did not have a rule so it must be displayed; return B_TRUE.
2414 free(checked_props);
2415 if (prop_found)
2416 return (B_FALSE);
2417 else
2418 return (B_TRUE);
2422 * Returns true if the given property is read-only and cannot be modified.
2424 static boolean_t
2425 is_prop_read_only(nwam_object_type_t object_type, const char *prop)
2427 boolean_t ro;
2429 switch (object_type) {
2430 case NWAM_OBJECT_TYPE_NCU:
2431 if (nwam_ncu_prop_read_only(prop, &ro) == NWAM_SUCCESS && ro)
2432 return (B_TRUE);
2433 break;
2434 case NWAM_OBJECT_TYPE_ENM:
2435 if (nwam_enm_prop_read_only(prop, &ro) == NWAM_SUCCESS && ro)
2436 return (B_TRUE);
2437 break;
2438 case NWAM_OBJECT_TYPE_LOC:
2439 if (nwam_loc_prop_read_only(prop, &ro) == NWAM_SUCCESS && ro)
2440 return (B_TRUE);
2441 break;
2442 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2443 /* no read-only properties for WLANs */
2444 return (B_FALSE);
2446 return (B_FALSE);
2449 /* Returns true if the property is multi-valued */
2450 static boolean_t
2451 is_prop_multivalued(nwam_object_type_t object_type, const char *prop)
2453 nwam_error_t ret;
2454 boolean_t multi;
2456 switch (object_type) {
2457 case NWAM_OBJECT_TYPE_NCU:
2458 ret = nwam_ncu_prop_multivalued(prop, &multi);
2459 break;
2460 case NWAM_OBJECT_TYPE_LOC:
2461 ret = nwam_loc_prop_multivalued(prop, &multi);
2462 break;
2463 case NWAM_OBJECT_TYPE_ENM:
2464 ret = nwam_enm_prop_multivalued(prop, &multi);
2465 break;
2466 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2467 ret = nwam_known_wlan_prop_multivalued(prop, &multi);
2468 break;
2471 if (ret != NWAM_SUCCESS)
2472 multi = B_FALSE;
2473 return (multi);
2477 * Prints out error message specific to property that could not be set.
2478 * Property description is used to help guide user in entering correct value.
2480 static void
2481 invalid_set_prop_msg(const char *prop, nwam_error_t err)
2483 const char *description;
2485 if (err == NWAM_SUCCESS)
2486 return;
2488 if (err != NWAM_ENTITY_INVALID_VALUE) {
2489 nwamerr(err, "Set error");
2490 return;
2493 switch (active_object_type()) {
2494 case NWAM_OBJECT_TYPE_NCU:
2495 (void) nwam_ncu_get_prop_description(prop, &description);
2496 break;
2497 case NWAM_OBJECT_TYPE_LOC:
2498 (void) nwam_loc_get_prop_description(prop, &description);
2499 break;
2500 case NWAM_OBJECT_TYPE_ENM:
2501 (void) nwam_enm_get_prop_description(prop, &description);
2502 break;
2503 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2504 (void) nwam_known_wlan_get_prop_description(prop,
2505 &description);
2506 break;
2508 nerr("Set error: invalid value\n'%s' %s", prop, description);
2512 * Sets the property value.
2513 * Read-only properties and objects cannot be set.
2514 * "read-only" is a special in that it can be set on a read-only object.
2515 * The object has to be committed before other properties can be set.
2516 * Also uses show_prop_test() to test if the property being set would
2517 * be skipped during a walk (as determined by the value of some other
2518 * property). If so, then it cannot be set.
2520 void
2521 set_func(cmd_t *cmd)
2523 int pt_type = cmd->cmd_prop_type;
2524 nwam_error_t ret = NWAM_SUCCESS;
2525 nwam_value_t prop_value;
2526 const char *prop;
2527 boolean_t is_listprop = B_FALSE;
2528 nwam_object_type_t object_type;
2529 prop_display_entry_t *prop_table;
2530 char **checked = NULL;
2532 assert(cmd->cmd_argc > 0);
2534 object_type = active_object_type();
2535 prop_table = get_prop_display_table(object_type);
2537 /* argv[0] is property value */
2538 if ((prop = pt_to_prop_name(object_type, pt_type)) == NULL) {
2539 nerr("Set error: invalid %s property: '%s'",
2540 scope_to_str(current_scope), pt_to_str(pt_type));
2541 return;
2544 /* check if property can be set */
2545 if (is_prop_read_only(object_type, prop)) {
2546 nerr("Set error: property '%s' is read-only", prop);
2547 return;
2549 if (!show_prop_test(object_type, prop, prop_table, checked, 0)) {
2550 if (interactive_mode) {
2551 (void) printf(gettext("setting property '%s' "
2552 "has no effect\n"), prop);
2556 is_listprop = is_prop_multivalued(object_type, prop);
2557 prop_value = str_to_nwam_value(object_type, cmd->cmd_argv[0], pt_type,
2558 is_listprop);
2559 if (prop_value == NULL) {
2560 invalid_set_prop_msg(prop, NWAM_ENTITY_INVALID_VALUE);
2561 return;
2564 /* set the property value */
2565 switch (object_type) {
2566 case NWAM_OBJECT_TYPE_NCU:
2567 ret = nwam_ncu_set_prop_value(ncu_h, prop, prop_value);
2568 break;
2569 case NWAM_OBJECT_TYPE_LOC:
2570 ret = nwam_loc_set_prop_value(loc_h, prop, prop_value);
2571 break;
2572 case NWAM_OBJECT_TYPE_ENM:
2573 ret = nwam_enm_set_prop_value(enm_h, prop, prop_value);
2574 break;
2575 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2576 ret = nwam_known_wlan_set_prop_value(wlan_h, prop, prop_value);
2577 break;
2579 nwam_value_free(prop_value);
2581 /* delete other properties if needed */
2582 if (ret == NWAM_SUCCESS)
2583 need_to_commit = B_TRUE;
2584 else
2585 invalid_set_prop_msg(prop, ret);
2588 static int
2589 list_callback(nwam_object_type_t object_type, void *handle,
2590 boolean_t *list_msgp, const char *msg)
2592 nwam_error_t ret;
2593 char *name;
2594 nwam_ncu_class_t class;
2596 if (*list_msgp) {
2597 (void) printf("%s:\n", msg);
2598 *list_msgp = B_FALSE;
2601 ret = object_name_from_handle(object_type, handle, &name);
2602 if (ret != NWAM_SUCCESS) {
2603 nwamerr(ret, "List error: failed to get name");
2604 return (1);
2607 /* If NCU, get its class and print */
2608 if (object_type == NWAM_OBJECT_TYPE_NCU) {
2609 if ((ret = nwam_ncu_get_ncu_class(handle, &class))
2610 != NWAM_SUCCESS) {
2611 nwamerr(ret, "List error: failed to get ncu class");
2612 free(name);
2613 return (1);
2614 } else {
2615 (void) printf("\t%s",
2616 propval_to_str(NWAM_NCU_PROP_CLASS, class));
2619 (void) printf("\t%s\n", name);
2621 free(name);
2622 return (0);
2625 /* Print out name, type and status */
2626 static int
2627 list_loc_callback(nwam_loc_handle_t loc, void *arg)
2629 return (list_callback(NWAM_OBJECT_TYPE_LOC, loc, arg, "Locations"));
2632 static int
2633 list_enm_callback(nwam_enm_handle_t enm, void *arg)
2635 return (list_callback(NWAM_OBJECT_TYPE_ENM, enm, arg, "ENMs"));
2638 static int
2639 list_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
2641 return (list_callback(NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan, arg, "WLANs"));
2644 static int
2645 list_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
2647 return (list_callback(NWAM_OBJECT_TYPE_NCP, ncp, arg, "NCPs"));
2650 static int
2651 list_ncu_callback(nwam_ncu_handle_t ncu, void *arg)
2653 return (list_callback(NWAM_OBJECT_TYPE_NCU, ncu, arg, "NCUs"));
2656 /* functions to convert a value to a string */
2657 /* ARGSUSED */
2658 static const char *
2659 str2str(void *s, const char *prop, char *str)
2661 (void) snprintf(str, NWAM_MAX_VALUE_LEN, "%s", s);
2662 return (str);
2665 /* ARGSUSED */
2666 static const char *
2667 str2qstr(void *s, const char *prop, char *qstr)
2669 /* quoted strings */
2670 (void) snprintf(qstr, NWAM_MAX_VALUE_LEN, "\"%s\"", s);
2671 return (qstr);
2674 /* ARGSUSED */
2675 static const char *
2676 int2str(void *in, const char *prop, char *instr)
2678 (void) snprintf(instr, NWAM_MAX_VALUE_LEN, "%lld", *((int64_t *)in));
2679 return (instr);
2682 static const char *
2683 uint2str(void *uin, const char *prop, char *uintstr)
2685 /* returns NWAM_SUCCESS if prop is enum with string in uintstr */
2686 if (nwam_uint64_get_value_string(prop, *((uint64_t *)uin),
2687 (const char **)&uintstr) != NWAM_SUCCESS) {
2688 (void) snprintf(uintstr, NWAM_MAX_VALUE_LEN, "%lld",
2689 *((uint64_t *)uin));
2691 return (uintstr);
2694 /* ARGSUSED */
2695 static const char *
2696 bool2str(void *bool, const char *prop, char *boolstr)
2698 (void) snprintf(boolstr, NWAM_MAX_VALUE_LEN, "%s",
2699 *((boolean_t *)bool) ? "true" : "false");
2700 return (boolstr);
2704 * Print the value (enums are converted to string), use DELIMITER for
2705 * array. If strings are to be "quoted", pass B_TRUE for quoted_strings.
2707 static void
2708 output_prop_val(const char *prop_name, nwam_value_t value, FILE *wf,
2709 boolean_t quoted_strings)
2711 nwam_value_type_t value_type;
2712 uint_t num;
2714 /* arrays for values retrieved according to the type of value */
2715 char **svals;
2716 uint64_t *uvals;
2717 int64_t *ivals;
2718 boolean_t *bvals;
2720 /* pointer to function to generate string representation of value */
2721 const char *(*tostr)(void *, const char *, char *);
2722 char str[NWAM_MAX_VALUE_LEN]; /* to store the string */
2723 int i;
2725 if (nwam_value_get_type(value, &value_type) != NWAM_SUCCESS) {
2726 nerr("Get value type error");
2727 return;
2730 if (value_type == NWAM_VALUE_TYPE_STRING) {
2731 if (nwam_value_get_string_array(value, &svals, &num) !=
2732 NWAM_SUCCESS) {
2733 nerr("Get string array error");
2734 return;
2736 tostr = quoted_strings ? str2qstr : str2str;
2737 } else if (value_type == NWAM_VALUE_TYPE_INT64) {
2738 if (nwam_value_get_int64_array(value, &ivals, &num) !=
2739 NWAM_SUCCESS) {
2740 nerr("Get int64 array error");
2741 return;
2743 tostr = int2str;
2744 } else if (value_type == NWAM_VALUE_TYPE_UINT64) {
2745 if (nwam_value_get_uint64_array(value, &uvals, &num) !=
2746 NWAM_SUCCESS) {
2747 nerr("Get uint64 array error");
2748 return;
2750 tostr = uint2str;
2751 } else if (value_type == NWAM_VALUE_TYPE_BOOLEAN) {
2752 if (nwam_value_get_boolean_array(value, &bvals, &num) !=
2753 NWAM_SUCCESS) {
2754 nerr("Get boolean array error");
2755 return;
2757 tostr = bool2str;
2760 /* now, loop and print each value */
2761 for (i = 0; i < num; i++) {
2762 void *val;
2764 /* get the pointer to the ith value to pass to func() */
2765 if (value_type == NWAM_VALUE_TYPE_STRING)
2766 val = svals[i];
2767 else if (value_type == NWAM_VALUE_TYPE_UINT64)
2768 val = &(uvals[i]);
2769 else if (value_type == NWAM_VALUE_TYPE_INT64)
2770 val = &(ivals[i]);
2771 else if (value_type == NWAM_VALUE_TYPE_BOOLEAN)
2772 val = &(bvals[i]);
2774 (void) fprintf(wf, "%s%s", tostr(val, prop_name, str),
2775 i != num-1 ? NWAM_VALUE_DELIMITER_STR : "");
2779 /* Prints the property names aligned (for list/get) or "prop=" (for export) */
2780 static int
2781 output_propname_common(const char *prop, nwam_value_t values, void *arg,
2782 int width)
2784 FILE *of = (arg == NULL) ? stdout : arg;
2786 /* arg is NULL for list/get, not NULL for export */
2787 if (arg == NULL)
2788 (void) fprintf(of, "\t%-*s\t", width, prop);
2789 else
2790 (void) fprintf(of, "%s=", prop);
2792 if (values != NULL)
2793 output_prop_val(prop, values, of, B_TRUE);
2795 (void) fprintf(of, "\n");
2796 return (0);
2799 static int
2800 output_propname(const char *prop, nwam_value_t values, void *arg)
2802 return (output_propname_common(prop, values, arg, 16));
2805 /* For locations because of longer property names */
2806 static int
2807 output_loc_propname(const char *prop, nwam_value_t values, void *arg)
2809 return (output_propname_common(prop, values, arg, 25));
2813 * all_props specifies whether properties that have not been set should be
2814 * printed or not. ncp and ncu_type are used only when the object_type is
2815 * NCU.
2817 static nwam_error_t
2818 listprop(nwam_object_type_t object_type, void *handle, const char *name,
2819 boolean_t all_props, nwam_ncp_handle_t ncp, nwam_ncu_type_t ncu_type)
2821 nwam_error_t ret;
2822 char *lname = NULL, *realname = NULL;
2823 boolean_t lhandle = B_FALSE;
2824 const char **props = NULL;
2825 uint_t prop_num;
2826 int i;
2827 nwam_value_t vals;
2830 * handle is NULL if called from a scope higher than the object's
2831 * scope, but name must be given; so get the handle.
2833 if (handle == NULL) {
2834 lname = trim_quotes(name); /* name may have quotes */
2835 switch (object_type) {
2836 case NWAM_OBJECT_TYPE_NCP:
2837 if ((ret = nwam_ncp_read(lname, 0,
2838 (nwam_ncp_handle_t *)&handle)) != NWAM_SUCCESS)
2839 goto readfail;
2840 break;
2841 case NWAM_OBJECT_TYPE_NCU:
2842 ret = nwam_ncu_read(ncp, lname, ncu_type, 0,
2843 (nwam_ncu_handle_t *)&handle);
2844 if (ret == NWAM_ENTITY_MULTIPLE_VALUES) {
2846 * Multiple NCUs with the given name exists.
2847 * Call listprop() for each NCU type.
2849 if ((ret = listprop(object_type, NULL, lname,
2850 all_props, ncp, NWAM_NCU_TYPE_LINK))
2851 != NWAM_SUCCESS)
2852 goto done;
2853 ret = listprop(object_type, NULL, lname,
2854 all_props, ncp, NWAM_NCU_TYPE_INTERFACE);
2855 goto done;
2856 } else if (ret != NWAM_SUCCESS) {
2857 goto readfail;
2859 break;
2860 case NWAM_OBJECT_TYPE_LOC:
2861 if ((ret = nwam_loc_read(lname, 0,
2862 (nwam_loc_handle_t *)&handle)) != NWAM_SUCCESS)
2863 goto readfail;
2864 break;
2865 case NWAM_OBJECT_TYPE_ENM:
2866 if ((ret = nwam_enm_read(lname, 0,
2867 (nwam_enm_handle_t *)&handle)) != NWAM_SUCCESS)
2868 goto readfail;
2869 break;
2870 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2871 if ((ret = nwam_known_wlan_read(lname, 0,
2872 (nwam_known_wlan_handle_t *)&handle))
2873 != NWAM_SUCCESS)
2874 goto readfail;
2875 break;
2877 lhandle = B_TRUE;
2880 if ((ret = object_name_from_handle(object_type, handle, &realname))
2881 != NWAM_SUCCESS)
2882 goto done;
2884 /* get the property list */
2885 switch (object_type) {
2886 case NWAM_OBJECT_TYPE_NCP:
2888 /* walk NCUs */
2889 boolean_t list_msg = B_TRUE;
2890 ret = nwam_ncp_walk_ncus(handle, list_ncu_callback, &list_msg,
2891 NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
2892 goto done;
2894 case NWAM_OBJECT_TYPE_NCU:
2896 nwam_ncu_type_t ncu_type;
2897 nwam_ncu_class_t ncu_class;
2899 if ((ret = nwam_ncu_get_ncu_type(handle, &ncu_type))
2900 != NWAM_SUCCESS)
2901 goto done;
2902 if ((ret = nwam_ncu_get_ncu_class(handle, &ncu_class))
2903 != NWAM_SUCCESS)
2904 goto done;
2906 ret = nwam_ncu_get_default_proplist(ncu_type, ncu_class, &props,
2907 &prop_num);
2908 break;
2910 case NWAM_OBJECT_TYPE_LOC:
2911 ret = nwam_loc_get_default_proplist(&props, &prop_num);
2912 break;
2913 case NWAM_OBJECT_TYPE_ENM:
2914 ret = nwam_enm_get_default_proplist(&props, &prop_num);
2915 break;
2916 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2917 ret = nwam_known_wlan_get_default_proplist(&props, &prop_num);
2918 break;
2920 if (ret != NWAM_SUCCESS)
2921 goto done;
2923 /* print object type and name */
2924 (void) printf("%s:%s\n", nwam_object_type_to_string(object_type),
2925 realname);
2927 /* Loop through the properties and print */
2928 for (i = 0; i < prop_num; i++) {
2929 /* get the existing value for this property */
2930 switch (object_type) {
2931 case NWAM_OBJECT_TYPE_NCU:
2932 ret = nwam_ncu_get_prop_value(handle, props[i], &vals);
2933 break;
2934 case NWAM_OBJECT_TYPE_LOC:
2935 ret = nwam_loc_get_prop_value(handle, props[i], &vals);
2936 break;
2937 case NWAM_OBJECT_TYPE_ENM:
2938 ret = nwam_enm_get_prop_value(handle, props[i], &vals);
2939 break;
2940 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2941 ret = nwam_known_wlan_get_prop_value(handle, props[i],
2942 &vals);
2943 break;
2945 if (ret != NWAM_SUCCESS) {
2946 /* _ENTITY_NOT_FOUND is ok if listing for all props */
2947 if (!all_props)
2948 continue;
2949 else if (ret != NWAM_ENTITY_NOT_FOUND)
2950 continue;
2953 /* print property and value */
2954 if (object_type == NWAM_OBJECT_TYPE_LOC)
2955 output_loc_propname(props[i], vals, NULL);
2956 else
2957 output_propname(props[i], vals, NULL);
2958 nwam_value_free(vals);
2961 done:
2962 free(lname);
2963 free(realname);
2964 free(props);
2965 if (lhandle) {
2966 switch (object_type) {
2967 case NWAM_OBJECT_TYPE_NCP:
2968 nwam_ncp_free(handle);
2969 break;
2970 case NWAM_OBJECT_TYPE_NCU:
2971 nwam_ncu_free(handle);
2972 break;
2973 case NWAM_OBJECT_TYPE_LOC:
2974 nwam_loc_free(handle);
2975 break;
2976 case NWAM_OBJECT_TYPE_ENM:
2977 nwam_enm_free(handle);
2978 break;
2979 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2980 nwam_known_wlan_free(handle);
2981 break;
2984 /* don't treat _ENTITY_NOT_FOUND as an error */
2985 if (ret == NWAM_ENTITY_NOT_FOUND)
2986 ret = NWAM_SUCCESS;
2987 return (ret);
2989 readfail:
2990 /* When nwam_*_read() fails */
2991 free(lname);
2992 return (ret);
2996 * List profiles or property and its values.
2997 * If the -a option is specified, all properties are listed.
2999 void
3000 list_func(cmd_t *cmd)
3002 nwam_error_t ret = NWAM_SUCCESS;
3003 boolean_t list_msg = B_TRUE;
3005 boolean_t list_loc = B_FALSE, list_enm = B_FALSE;
3006 boolean_t list_ncp = B_FALSE, list_ncu = B_FALSE;
3007 boolean_t list_wlan = B_FALSE;
3009 /* whether all properties should be listed, given by the -a option */
3010 boolean_t all_props = B_FALSE;
3013 * list_props says whether the properties should be listed.
3014 * Note that, here NCUs are treated as properties of NCPs.
3016 boolean_t list_props = B_FALSE;
3018 /* determine which properties to list, also validity tests */
3019 if (current_scope == NWAM_SCOPE_GBL) {
3020 /* res1_type is -1 if only "list -a" is used */
3021 if (cmd->cmd_res1_type == -1) {
3022 nerr("'list' requires an object to be specified with "
3023 "the -a option in the global scope");
3024 return;
3026 if (cmd->cmd_res1_type == RT1_LOC) {
3027 list_props = B_TRUE;
3028 list_loc = B_TRUE;
3029 } else if (cmd->cmd_res1_type == RT1_ENM) {
3030 list_props = B_TRUE;
3031 list_enm = B_TRUE;
3032 } else if (cmd->cmd_res1_type == RT1_WLAN) {
3033 list_props = B_TRUE;
3034 list_wlan = B_TRUE;
3035 } else if (cmd->cmd_res1_type == RT1_NCP) {
3036 list_ncp = B_TRUE;
3037 list_props = B_TRUE;
3038 } else {
3039 list_loc = B_TRUE;
3040 list_enm = B_TRUE;
3041 list_wlan = B_TRUE;
3042 list_ncp = B_TRUE;
3045 if ((current_scope == NWAM_SCOPE_LOC ||
3046 current_scope == NWAM_SCOPE_ENM ||
3047 current_scope == NWAM_SCOPE_WLAN ||
3048 current_scope == NWAM_SCOPE_NCU) &&
3049 (cmd->cmd_argc >= 1 && cmd->cmd_res1_type != -1)) {
3050 nerr("Additional options are not allowed with the -a option "
3051 "at this scope");
3052 return;
3054 if (current_scope == NWAM_SCOPE_LOC) {
3055 list_loc = B_TRUE;
3056 list_props = B_TRUE;
3058 if (current_scope == NWAM_SCOPE_ENM) {
3059 list_enm = B_TRUE;
3060 list_props = B_TRUE;
3062 if (current_scope == NWAM_SCOPE_WLAN) {
3063 list_wlan = B_TRUE;
3064 list_props = B_TRUE;
3066 if (current_scope == NWAM_SCOPE_NCP) {
3067 if (cmd->cmd_res1_type == RT1_ENM ||
3068 cmd->cmd_res1_type == RT1_LOC ||
3069 cmd->cmd_res1_type == RT1_WLAN) {
3070 nerr("only ncu can be listed at this scope");
3071 return;
3073 if (cmd->cmd_res2_type == RT2_NCU) {
3074 list_ncu = B_TRUE;
3075 list_props = B_TRUE;
3076 } else {
3077 list_ncp = B_TRUE;
3078 list_props = B_TRUE;
3081 if (current_scope == NWAM_SCOPE_NCU) {
3082 list_ncu = B_TRUE;
3083 list_props = B_TRUE;
3086 /* Check if the -a option is specified to list all properties */
3087 if (cmd->cmd_res1_type == -1 || cmd->cmd_argc == 2) {
3088 int c, argc = 1;
3089 char **argv;
3090 optind = 0;
3092 /* if res1_type is -1, option is in argv[0], else in argv[1] */
3093 if (cmd->cmd_res1_type == -1)
3094 argv = cmd->cmd_argv;
3095 else
3096 argv = &(cmd->cmd_argv[1]);
3097 while ((c = getopt(argc, argv, "a")) != EOF) {
3098 switch (c) {
3099 case 'a':
3100 all_props = B_TRUE;
3101 break;
3102 default:
3103 command_usage(CMD_LIST);
3104 return;
3107 if (cmd->cmd_res1_type == -1)
3108 cmd->cmd_argv[0] = NULL;
3112 * Now, print objects and/or according to the flags set.
3113 * name, if requested, is in argv[0].
3115 if (list_ncp) {
3116 list_msg = B_TRUE;
3117 if (list_props) {
3118 ret = listprop(NWAM_OBJECT_TYPE_NCP, ncp_h,
3119 cmd->cmd_argv[0], all_props, NULL, -1);
3120 } else {
3121 ret = nwam_walk_ncps(list_ncp_callback, &list_msg, 0,
3122 NULL);
3124 if (ret != NWAM_SUCCESS)
3125 goto done;
3128 if (list_ncu) {
3129 list_msg = B_TRUE;
3130 if (ncp_h == NULL) {
3131 nerr("NCP has not been read");
3132 return;
3134 if (list_props) {
3135 nwam_ncu_class_t ncu_class;
3136 nwam_ncu_type_t ncu_type;
3138 /* determine the NCU type first */
3139 if (ncu_h == NULL) {
3140 ncu_class = (nwam_ncu_class_t)
3141 cmd->cmd_ncu_class_type;
3142 ncu_type = nwam_ncu_class_to_type(ncu_class);
3143 } else {
3144 if ((ret = nwam_ncu_get_ncu_type(ncu_h,
3145 &ncu_type)) != NWAM_SUCCESS)
3146 goto done;
3148 ret = listprop(NWAM_OBJECT_TYPE_NCU, ncu_h,
3149 cmd->cmd_argv[0], all_props, ncp_h, ncu_type);
3150 if (ret != NWAM_SUCCESS)
3151 goto done;
3155 if (list_loc) {
3156 list_msg = B_TRUE;
3157 if (list_props) {
3158 ret = listprop(NWAM_OBJECT_TYPE_LOC, loc_h,
3159 cmd->cmd_argv[0], all_props, NULL, -1);
3160 } else {
3161 ret = nwam_walk_locs(list_loc_callback, &list_msg,
3162 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3164 if (ret != NWAM_SUCCESS)
3165 goto done;
3168 if (list_enm) {
3169 list_msg = B_TRUE;
3170 if (list_props) {
3171 ret = listprop(NWAM_OBJECT_TYPE_ENM, enm_h,
3172 cmd->cmd_argv[0], all_props, NULL, -1);
3173 } else {
3174 ret = nwam_walk_enms(list_enm_callback, &list_msg,
3175 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3177 if (ret != NWAM_SUCCESS)
3178 goto done;
3181 if (list_wlan) {
3182 list_msg = B_TRUE;
3183 if (list_props) {
3184 ret = listprop(NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan_h,
3185 cmd->cmd_argv[0], all_props, NULL, -1);
3186 } else {
3187 ret = nwam_walk_known_wlans(list_wlan_callback,
3188 &list_msg, NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER,
3189 NULL);
3191 if (ret != NWAM_SUCCESS)
3192 goto done;
3195 done:
3196 if (ret != NWAM_SUCCESS)
3197 nwamerr(ret, "List error");
3200 static int
3201 write_export_command(nwam_object_type_t object_type, const char *prop,
3202 nwam_value_t values, FILE *of)
3204 /* exclude read-only properties */
3205 if (is_prop_read_only(object_type, prop))
3206 return (0);
3208 (void) fprintf(of, "set ");
3209 output_propname(prop, values, of);
3210 return (0);
3213 static int
3214 export_ncu_callback(nwam_ncu_handle_t ncu, void *arg)
3216 char *name;
3217 const char **props;
3218 nwam_ncu_type_t type;
3219 nwam_ncu_class_t class;
3220 nwam_value_t vals;
3221 nwam_error_t ret;
3222 uint_t num;
3223 int i;
3224 FILE *of = arg;
3226 assert(of != NULL);
3228 /* get the NCU's type and class */
3229 if ((ret = nwam_ncu_get_ncu_type(ncu, &type)) != NWAM_SUCCESS)
3230 return (ret);
3231 if ((ret = nwam_ncu_get_ncu_class(ncu, &class)) != NWAM_SUCCESS)
3232 return (ret);
3234 if ((ret = nwam_ncu_get_name(ncu, &name)) != NWAM_SUCCESS)
3235 return (ret);
3237 (void) fprintf(of, "create ncu %s \"%s\"\n",
3238 propval_to_str(NWAM_NCU_PROP_CLASS, class), name);
3239 free(name);
3241 * Because of dependencies between properties, they have to be
3242 * exported in the same order as when they are walked.
3244 if ((ret = nwam_ncu_get_default_proplist(type, class, &props, &num))
3245 != NWAM_SUCCESS)
3246 return (ret);
3247 for (i = 0; i < num; i++) {
3248 ret = nwam_ncu_get_prop_value(ncu, props[i], &vals);
3249 if (ret == NWAM_SUCCESS) {
3250 write_export_command(NWAM_OBJECT_TYPE_NCU, props[i],
3251 vals, of);
3252 nwam_value_free(vals);
3255 (void) fprintf(of, "end\n");
3257 free(props);
3258 return (0);
3261 static int
3262 export_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
3264 char *name;
3265 nwam_error_t ret;
3266 FILE *of = arg;
3268 assert(of != NULL);
3270 if ((ret = nwam_ncp_get_name(ncp, &name)) != NWAM_SUCCESS)
3271 return (ret);
3273 /* Do not export "automatic" NCP */
3274 if (NWAM_NCP_AUTOMATIC(name)) {
3275 free(name);
3276 return (0);
3279 (void) fprintf(of, "create ncp \"%s\"\n", name);
3280 free(name);
3282 /* now walk NCUs for this ncp */
3283 ret = nwam_ncp_walk_ncus(ncp, export_ncu_callback, of,
3284 NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
3285 if (ret != NWAM_SUCCESS) {
3286 nwamerr(ret, "Export ncp error: failed to walk ncus");
3287 return (ret);
3289 (void) fprintf(of, "end\n");
3290 return (0);
3293 static int
3294 export_enm_callback(nwam_enm_handle_t enm, void *arg)
3296 char *name;
3297 const char **props;
3298 nwam_value_t vals;
3299 nwam_error_t ret;
3300 uint_t num;
3301 int i;
3302 FILE *of = arg;
3304 assert(of != NULL);
3306 if ((ret = nwam_enm_get_name(enm, &name)) != NWAM_SUCCESS)
3307 return (ret);
3309 (void) fprintf(of, "create enm \"%s\"\n", name);
3310 free(name);
3312 * Because of dependencies between properties, they have to be
3313 * exported in the same order as when they are walked.
3315 if ((ret = nwam_enm_get_default_proplist(&props, &num)) != NWAM_SUCCESS)
3316 return (ret);
3317 for (i = 0; i < num; i++) {
3318 ret = nwam_enm_get_prop_value(enm, props[i], &vals);
3319 if (ret == NWAM_SUCCESS) {
3320 write_export_command(NWAM_OBJECT_TYPE_ENM, props[i],
3321 vals, of);
3322 nwam_value_free(vals);
3325 (void) fprintf(of, "end\n");
3327 free(props);
3328 return (0);
3331 static int
3332 export_loc_callback(nwam_loc_handle_t loc, void *arg)
3334 char *name;
3335 const char **props;
3336 nwam_value_t vals;
3337 nwam_error_t ret;
3338 uint_t num;
3339 int i;
3340 FILE *of = arg;
3342 assert(of != NULL);
3344 if ((ret = nwam_loc_get_name(loc, &name)) != NWAM_SUCCESS)
3345 return (ret);
3347 /* Do not export Automatic, NoNet or Legacy locations */
3348 if (NWAM_LOC_NAME_PRE_DEFINED(name)) {
3349 free(name);
3350 return (0);
3353 (void) fprintf(of, "create loc \"%s\"\n", name);
3354 free(name);
3356 * Because of dependencies between properties, they have to be
3357 * exported in the same order as when they are walked.
3359 if ((ret = nwam_loc_get_default_proplist(&props, &num)) != NWAM_SUCCESS)
3360 return (ret);
3361 for (i = 0; i < num; i++) {
3362 ret = nwam_loc_get_prop_value(loc, props[i], &vals);
3363 if (ret == NWAM_SUCCESS) {
3364 write_export_command(NWAM_OBJECT_TYPE_LOC, props[i],
3365 vals, of);
3366 nwam_value_free(vals);
3369 (void) fprintf(of, "end\n");
3371 free(props);
3372 return (0);
3375 static int
3376 export_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
3378 char *name;
3379 const char **props;
3380 nwam_value_t vals;
3381 nwam_error_t ret;
3382 uint_t num;
3383 int i;
3384 FILE *of = arg;
3386 assert(of != NULL);
3388 if ((ret = nwam_known_wlan_get_name(wlan, &name)) != NWAM_SUCCESS)
3389 return (ret);
3391 (void) fprintf(of, "create wlan \"%s\"\n", name);
3392 free(name);
3394 * Because of dependencies between properties, they have to be
3395 * exported in the same order as when they are walked.
3397 if ((ret = nwam_known_wlan_get_default_proplist(&props, &num))
3398 != NWAM_SUCCESS)
3399 return (ret);
3400 for (i = 0; i < num; i++) {
3401 ret = nwam_known_wlan_get_prop_value(wlan, props[i], &vals);
3402 if (ret == NWAM_SUCCESS) {
3403 write_export_command(NWAM_OBJECT_TYPE_KNOWN_WLAN,
3404 props[i], vals, of);
3405 nwam_value_free(vals);
3408 (void) fprintf(of, "end\n");
3410 free(props);
3411 return (0);
3415 * Writes configuration to screen or file (with -f option).
3416 * Writes a "destroy -a" if option -d is given.
3418 void
3419 export_func(cmd_t *cmd)
3421 int c;
3422 boolean_t need_to_close = B_FALSE, write_to_file = B_FALSE;
3423 boolean_t add_destroy = B_FALSE, lhandle = B_FALSE;
3424 char filepath[MAXPATHLEN];
3425 nwam_error_t ret = NWAM_SUCCESS;
3426 FILE *of = NULL; /* either filename or stdout */
3428 /* what to export */
3429 boolean_t export_ncp = B_FALSE, export_ncu = B_FALSE;
3430 boolean_t export_loc = B_FALSE, export_enm = B_FALSE;
3431 boolean_t export_wlan = B_FALSE;
3432 char *name = NULL;
3434 /* check for -d and -f flags */
3435 filepath[0] = '\0';
3436 optind = 0;
3437 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "df:")) != EOF) {
3438 switch (c) {
3439 case 'f':
3440 write_to_file = B_TRUE;
3441 break;
3442 case 'd':
3443 add_destroy = B_TRUE;
3444 break;
3445 default:
3446 command_usage(CMD_EXPORT);
3447 return;
3451 /* determine where to export */
3452 if (!write_to_file) {
3453 of = stdout;
3454 } else {
3456 * If -d was specified with -f, then argv[2] is filename,
3457 * otherwise, argv[1] is filename.
3459 (void) strlcpy(filepath,
3460 (add_destroy ? cmd->cmd_argv[2] : cmd->cmd_argv[1]),
3461 sizeof (filepath));
3462 if ((of = fopen(filepath, "w")) == NULL) {
3463 nerr(gettext("opening file '%s': %s"), filepath,
3464 strerror(errno));
3465 goto done;
3467 setbuf(of, NULL);
3468 need_to_close = B_TRUE;
3471 if (add_destroy) {
3472 /* only possible in global scope */
3473 if (current_scope == NWAM_SCOPE_GBL) {
3474 (void) fprintf(of, "destroy -a\n");
3475 } else {
3476 nerr("Option -d is not allowed in non-global scope");
3477 goto done;
3481 /* In the following scopes, only the -f argument is valid */
3482 if (((current_scope == NWAM_SCOPE_LOC ||
3483 current_scope == NWAM_SCOPE_ENM ||
3484 current_scope == NWAM_SCOPE_WLAN ||
3485 current_scope == NWAM_SCOPE_NCU) &&
3486 cmd->cmd_argc != 0 && !write_to_file)) {
3487 nerr("'export' does not take arguments at this scope");
3488 goto done;
3490 if (current_scope == NWAM_SCOPE_NCP) {
3491 if (cmd->cmd_res1_type == RT1_ENM ||
3492 cmd->cmd_res1_type == RT1_LOC ||
3493 cmd->cmd_res1_type == RT1_WLAN) {
3494 nerr("only ncu can be exported at this scope");
3495 goto done;
3500 * Determine what objects to export depending on scope and command
3501 * arguments. If -f is specified, then the object name is argv[2].
3502 * Otherwise, argv[0] is name, unless exporting all in global
3503 * scope in which case name is set back to NULL.
3505 switch (current_scope) {
3506 case NWAM_SCOPE_GBL:
3507 name = (write_to_file ? trim_quotes(cmd->cmd_argv[2]) :
3508 trim_quotes(cmd->cmd_argv[0]));
3509 switch (cmd->cmd_res1_type) {
3510 case RT1_LOC:
3511 export_loc = B_TRUE;
3512 break;
3513 case RT1_ENM:
3514 export_enm = B_TRUE;
3515 break;
3516 case RT1_WLAN:
3517 export_wlan = B_TRUE;
3518 break;
3519 case RT1_NCP:
3520 export_ncp = B_TRUE;
3521 if (cmd->cmd_res2_type == RT2_NCU) {
3522 nerr("cannot export ncu at from global scope");
3523 goto done;
3525 break;
3526 default:
3527 /* export everything */
3528 export_loc = B_TRUE;
3529 export_enm = B_TRUE;
3530 export_wlan = B_TRUE;
3531 export_ncp = B_TRUE; /* NCP will export the NCUs */
3532 free(name);
3533 name = NULL; /* exporting all, undo name */
3534 break;
3536 break;
3537 case NWAM_SCOPE_LOC:
3538 export_loc = B_TRUE;
3539 ret = nwam_loc_get_name(loc_h, &name);
3540 if (ret != NWAM_SUCCESS)
3541 goto fail;
3542 break;
3543 case NWAM_SCOPE_ENM:
3544 export_enm = B_TRUE;
3545 ret = nwam_enm_get_name(enm_h, &name);
3546 if (ret != NWAM_SUCCESS)
3547 goto fail;
3548 break;
3549 case NWAM_SCOPE_WLAN:
3550 export_wlan = B_TRUE;
3551 ret = nwam_known_wlan_get_name(wlan_h, &name);
3552 if (ret != NWAM_SUCCESS)
3553 goto fail;
3554 break;
3555 case NWAM_SCOPE_NCP:
3556 if (cmd->cmd_res2_type == RT2_NCU) {
3557 export_ncu = B_TRUE;
3558 name = (write_to_file ? trim_quotes(cmd->cmd_argv[2]) :
3559 trim_quotes(cmd->cmd_argv[0]));
3560 } else {
3561 export_ncp = B_TRUE;
3562 ret = nwam_ncp_get_name(ncp_h, &name);
3563 if (ret != NWAM_SUCCESS)
3564 goto fail;
3566 break;
3567 case NWAM_SCOPE_NCU:
3568 export_ncu = B_TRUE;
3569 ret = nwam_ncu_get_name(ncu_h, &name);
3570 if (ret != NWAM_SUCCESS)
3571 goto fail;
3572 break;
3573 default:
3574 nerr("Invalid scope");
3575 goto done;
3578 /* Now, export objects according to the flags set */
3579 if (export_ncp) {
3580 lhandle = B_FALSE;
3581 if (name == NULL) {
3582 /* export all NCPs */
3583 ret = nwam_walk_ncps(export_ncp_callback, of, 0, NULL);
3584 } else if (NWAM_NCP_AUTOMATIC(name)) {
3585 nerr("'%s' ncp cannot be exported", name);
3586 goto fail;
3587 } else {
3588 if (ncp_h == NULL) {
3589 ret = nwam_ncp_read(name, 0, &ncp_h);
3590 if (ret != NWAM_SUCCESS)
3591 goto fail;
3592 lhandle = B_TRUE;
3594 /* will export NCUs also */
3595 ret = export_ncp_callback(ncp_h, of);
3596 if (lhandle) {
3597 nwam_ncp_free(ncp_h);
3598 ncp_h = NULL;
3601 if (ret != NWAM_SUCCESS)
3602 goto fail;
3605 if (export_ncu) {
3606 if (name == NULL) {
3607 /* export all NCUs */
3608 ret = nwam_ncp_walk_ncus(ncp_h, export_ncu_callback, of,
3609 NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
3610 } else {
3611 if (ncu_h == NULL) {
3612 /* no NCU handle -> called from NCP scope */
3613 nwam_ncu_type_t ncu_type;
3614 nwam_ncu_class_t ncu_class;
3616 ncu_class = (nwam_ncu_class_t)
3617 cmd->cmd_ncu_class_type;
3618 ncu_type = nwam_ncu_class_to_type(ncu_class);
3619 ret = nwam_ncu_read(ncp_h, name,
3620 ncu_type, 0, &ncu_h);
3621 if (ret == NWAM_SUCCESS) {
3622 /* one NCU with given name */
3623 ret = export_ncu_callback(ncu_h, of);
3624 nwam_ncu_free(ncu_h);
3625 ncu_h = NULL;
3626 } else if (ret == NWAM_ENTITY_MULTIPLE_VALUES) {
3627 /* multiple NCUs with given name */
3628 ret = nwam_ncu_read(ncp_h, name,
3629 NWAM_NCU_TYPE_LINK, 0, &ncu_h);
3630 if (ret != NWAM_SUCCESS)
3631 goto fail;
3632 ret = export_ncu_callback(ncu_h, of);
3633 nwam_ncu_free(ncu_h);
3634 ncu_h = NULL;
3636 ret = nwam_ncu_read(ncp_h, name,
3637 NWAM_NCU_TYPE_INTERFACE, 0, &ncu_h);
3638 if (ret != NWAM_SUCCESS)
3639 goto fail;
3640 ret = export_ncu_callback(ncu_h, of);
3641 nwam_ncu_free(ncu_h);
3642 ncu_h = NULL;
3643 } else {
3644 goto fail;
3646 } else {
3647 /* NCU handle exists */
3648 ret = export_ncu_callback(ncu_h, of);
3651 if (ret != NWAM_SUCCESS)
3652 goto fail;
3655 if (export_loc) {
3656 lhandle = B_FALSE;
3657 if (name == NULL) {
3658 /* export all locations */
3659 ret = nwam_walk_locs(export_loc_callback, of,
3660 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3661 } else if (NWAM_LOC_NAME_PRE_DEFINED(name)) {
3662 nerr("'%s' loc cannot be exported", name);
3663 goto fail;
3664 } else {
3665 if (loc_h == NULL) {
3666 ret = nwam_loc_read(name, 0, &loc_h);
3667 if (ret != NWAM_SUCCESS)
3668 goto fail;
3669 lhandle = B_TRUE;
3671 ret = export_loc_callback(loc_h, of);
3672 if (lhandle) {
3673 nwam_loc_free(loc_h);
3674 loc_h = NULL;
3677 if (ret != NWAM_SUCCESS)
3678 goto fail;
3681 if (export_enm) {
3682 lhandle = B_FALSE;
3683 if (name == NULL) {
3684 /* export all ENMs */
3685 ret = nwam_walk_enms(export_enm_callback, of,
3686 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3687 } else {
3688 if (enm_h == NULL) {
3689 ret = nwam_enm_read(name, 0, &enm_h);
3690 if (ret != NWAM_SUCCESS)
3691 goto fail;
3692 lhandle = B_TRUE;
3694 ret = export_enm_callback(enm_h, of);
3695 if (lhandle) {
3696 nwam_enm_free(enm_h);
3697 enm_h = NULL;
3700 if (ret != NWAM_SUCCESS)
3701 goto fail;
3704 if (export_wlan) {
3705 lhandle = B_FALSE;
3706 if (name == NULL) {
3707 /* export all WLANs */
3708 ret = nwam_walk_known_wlans(export_wlan_callback, of,
3709 NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER, NULL);
3710 } else {
3711 if (wlan_h == NULL) {
3712 ret = nwam_known_wlan_read(name, 0,
3713 &wlan_h);
3714 if (ret != NWAM_SUCCESS)
3715 goto fail;
3716 lhandle = B_TRUE;
3718 ret = export_wlan_callback(wlan_h, of);
3719 if (lhandle) {
3720 nwam_known_wlan_free(wlan_h);
3721 wlan_h = NULL;
3724 if (ret != NWAM_SUCCESS)
3725 goto fail;
3728 fail:
3729 free(name);
3730 if (ret != NWAM_SUCCESS)
3731 nwamerr(ret, "Export error");
3733 done:
3734 if (need_to_close)
3735 (void) fclose(of);
3739 * Get property value. If the -V option is specified, only the value is
3740 * printed without the property name.
3742 void
3743 get_func(cmd_t *cmd)
3745 nwam_error_t ret = NWAM_SUCCESS;
3746 nwam_value_t prop_value;
3747 const char *prop;
3748 boolean_t value_only = B_FALSE;
3749 nwam_object_type_t object_type = active_object_type();
3751 /* check if option is -V to print value only */
3752 if (cmd->cmd_argc == 1) {
3753 int c;
3755 optind = 0;
3756 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "V")) != EOF) {
3757 switch (c) {
3758 case 'V':
3759 value_only = B_TRUE;
3760 break;
3761 default:
3762 command_usage(CMD_GET);
3763 return;
3768 /* property to get is in cmd->cmd_prop_type */
3769 if ((prop = pt_to_prop_name(object_type, cmd->cmd_prop_type)) == NULL) {
3770 nerr("Get error: invalid %s property: '%s'",
3771 scope_to_str(current_scope), pt_to_str(cmd->cmd_prop_type));
3772 return;
3775 switch (object_type) {
3776 case NWAM_OBJECT_TYPE_NCU:
3777 ret = nwam_ncu_get_prop_value(ncu_h, prop, &prop_value);
3778 break;
3779 case NWAM_OBJECT_TYPE_LOC:
3780 ret = nwam_loc_get_prop_value(loc_h, prop, &prop_value);
3781 break;
3782 case NWAM_OBJECT_TYPE_ENM:
3783 ret = nwam_enm_get_prop_value(enm_h, prop, &prop_value);
3784 break;
3785 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
3786 ret = nwam_known_wlan_get_prop_value(wlan_h, prop, &prop_value);
3787 break;
3790 if (ret != NWAM_SUCCESS) {
3791 if (ret == NWAM_ENTITY_NOT_FOUND)
3792 nerr("Get error: property '%s' has not been set", prop);
3793 else
3794 nwamerr(ret, "Get error");
3795 return;
3798 if (value_only) {
3799 output_prop_val(prop, prop_value, stdout, B_FALSE);
3800 (void) printf("\n");
3801 } else {
3802 output_propname(prop, prop_value, NULL);
3804 nwam_value_free(prop_value);
3808 * Clears value of a property.
3809 * Read-only properties cannot be cleared.
3810 * If clearing a property invalidates the object, then that property
3811 * cannot be cleared.
3813 void
3814 clear_func(cmd_t *cmd)
3816 nwam_error_t ret;
3817 const char *prop;
3818 nwam_object_type_t object_type = active_object_type();
3820 /* property to clear is in cmd->cmd_prop_type */
3821 if ((prop = pt_to_prop_name(object_type, cmd->cmd_prop_type)) == NULL) {
3822 nerr("Clear error: invalid %s property: '%s'",
3823 scope_to_str(current_scope), pt_to_str(cmd->cmd_prop_type));
3824 return;
3826 if (is_prop_read_only(object_type, prop)) {
3827 nerr("Clear error: property '%s' is read-only", prop);
3828 return;
3831 switch (object_type) {
3832 case NWAM_OBJECT_TYPE_NCU:
3833 ret = nwam_ncu_delete_prop(ncu_h, prop);
3834 break;
3835 case NWAM_OBJECT_TYPE_LOC:
3836 ret = nwam_loc_delete_prop(loc_h, prop);
3837 break;
3838 case NWAM_OBJECT_TYPE_ENM:
3839 ret = nwam_enm_delete_prop(enm_h, prop);
3840 break;
3841 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
3842 ret = nwam_known_wlan_delete_prop(wlan_h, prop);
3843 break;
3846 if (ret != NWAM_SUCCESS) {
3847 if (ret == NWAM_INVALID_ARG || ret == NWAM_ENTITY_NOT_FOUND) {
3848 nerr("Clear error: property '%s' has not been set",
3849 prop);
3850 } else {
3851 nwamerr(ret, "Clear error");
3853 return;
3856 need_to_commit = B_TRUE;
3860 * Prints all the choices available for an enum property [c1|c2|c3].
3861 * Prints [true|false] for a boolean property.
3863 static void
3864 print_all_prop_choices(nwam_object_type_t object_type, const char *prop)
3866 uint64_t i = 0;
3867 const char *str;
3868 boolean_t choices = B_FALSE;
3869 nwam_value_type_t value_type;
3870 nwam_error_t ret;
3872 /* Special case: print object-specific options for activation-mode */
3873 if (strcmp(prop, NWAM_NCU_PROP_ACTIVATION_MODE) == 0) {
3874 /* "manual" for all objects */
3875 (void) printf(" [%s|",
3876 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3877 NWAM_ACTIVATION_MODE_MANUAL));
3878 if (object_type == NWAM_OBJECT_TYPE_NCU) {
3879 (void) printf("%s]",
3880 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3881 NWAM_ACTIVATION_MODE_PRIORITIZED));
3882 } else {
3883 (void) printf("%s|%s]",
3884 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3885 NWAM_ACTIVATION_MODE_CONDITIONAL_ANY),
3886 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3887 NWAM_ACTIVATION_MODE_CONDITIONAL_ALL));
3889 return;
3892 /* Special case: only "manual" configsrc is allowed for LDAP */
3893 if (strcmp(prop, NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC) == 0) {
3894 (void) printf(" [%s]",
3895 propval_to_str(NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
3896 NWAM_CONFIGSRC_MANUAL));
3897 return;
3900 value_type = prop_value_type(object_type, prop);
3901 switch (value_type) {
3902 case NWAM_VALUE_TYPE_UINT64:
3903 /* uint64 may be an enum, will print nothing if not an enum */
3904 while ((ret = nwam_uint64_get_value_string(prop, i++, &str))
3905 == NWAM_SUCCESS || ret == NWAM_ENTITY_INVALID_VALUE) {
3906 /* No string representation for i, continue. */
3907 if (ret == NWAM_ENTITY_INVALID_VALUE)
3908 continue;
3910 if (!choices)
3911 (void) printf("%s", " [");
3912 (void) printf("%s%s", choices ? "|" : "", str);
3913 choices = B_TRUE;
3915 if (choices)
3916 (void) putchar(']');
3917 break;
3918 case NWAM_VALUE_TYPE_BOOLEAN:
3919 (void) printf(" [%s|%s]", "true", "false");
3920 break;
3921 case NWAM_VALUE_TYPE_STRING:
3922 break;
3927 * Walk through object properties.
3928 * For newly-created object, the property name with no value is displayed, and
3929 * the user can input a value for each property.
3930 * For existing object, the current value is displayed and user input overwrites
3931 * the existing one. If no input is given, the existing value remains.
3932 * Read-only properties are not displayed.
3933 * Read-only objects cannot be walked.
3934 * If the -a option is specified, no properties are skipped.
3936 void
3937 walkprop_func(cmd_t *cmd)
3939 nwam_error_t ret = NWAM_SUCCESS;
3940 nwam_value_t vals = NULL; /* freed in _wait_input() */
3941 int i;
3942 uint_t prop_num;
3943 const char **props;
3944 boolean_t read_only = B_FALSE, all_props = B_FALSE;
3946 nwam_object_type_t object_type;
3947 prop_display_entry_t *prop_table;
3949 if (!interactive_mode) {
3950 nerr("'walkprop' is only allowed in interactive mode");
3951 return;
3954 /* check if option -a is specified to show all properties */
3955 if (cmd->cmd_argc == 1) {
3956 int c;
3957 optind = 0;
3958 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "a")) != EOF) {
3959 switch (c) {
3960 case 'a':
3961 all_props = B_TRUE;
3962 break;
3963 default:
3964 command_usage(CMD_WALKPROP);
3965 return;
3970 /* read-only objects cannot be walked */
3971 if (obj1_type == RT1_NCP) {
3972 /* must be in NCU scope, NCP scope doesn't get here */
3973 (void) nwam_ncu_get_read_only(ncu_h, &read_only);
3975 if (read_only) {
3976 nerr("'walkprop' cannot be used in read-only objects");
3977 return;
3980 /* get the current object type and the prop_display_table */
3981 object_type = active_object_type();
3982 prop_table = get_prop_display_table(object_type);
3984 /* get the property list depending on the object type */
3985 switch (object_type) {
3986 case NWAM_OBJECT_TYPE_NCU:
3988 nwam_ncu_type_t ncu_type;
3989 nwam_ncu_class_t ncu_class;
3991 if ((ret = nwam_ncu_get_ncu_type(ncu_h, &ncu_type))
3992 != NWAM_SUCCESS)
3993 break;
3994 if ((ret = nwam_ncu_get_ncu_class(ncu_h, &ncu_class))
3995 != NWAM_SUCCESS)
3996 break;
3998 ret = nwam_ncu_get_default_proplist(ncu_type, ncu_class, &props,
3999 &prop_num);
4000 break;
4002 case NWAM_OBJECT_TYPE_LOC:
4003 ret = nwam_loc_get_default_proplist(&props, &prop_num);
4004 break;
4005 case NWAM_OBJECT_TYPE_ENM:
4006 ret = nwam_enm_get_default_proplist(&props, &prop_num);
4007 break;
4008 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4009 ret = nwam_known_wlan_get_default_proplist(&props, &prop_num);
4010 break;
4012 if (ret != NWAM_SUCCESS) {
4013 nwamerr(ret, "Walkprop error: could not get property list");
4014 return;
4017 /* Loop through the properties */
4018 if (all_props)
4019 (void) printf(gettext("Walking all properties ...\n"));
4020 for (i = 0; i < prop_num; i++) {
4021 char line[NWAM_MAX_VALUE_LEN];
4022 char **checked = NULL;
4024 /* check if this property should be displayed */
4025 if (is_prop_read_only(object_type, props[i]))
4026 continue;
4027 if (!all_props &&
4028 !show_prop_test(object_type, props[i], prop_table,
4029 checked, 0))
4030 continue;
4032 /* get the existing value for this property */
4033 switch (object_type) {
4034 case NWAM_OBJECT_TYPE_NCU:
4035 ret = nwam_ncu_get_prop_value(ncu_h, props[i], &vals);
4036 break;
4037 case NWAM_OBJECT_TYPE_LOC:
4038 ret = nwam_loc_get_prop_value(loc_h, props[i], &vals);
4039 break;
4040 case NWAM_OBJECT_TYPE_ENM:
4041 ret = nwam_enm_get_prop_value(enm_h, props[i], &vals);
4042 break;
4043 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4044 ret = nwam_known_wlan_get_prop_value(wlan_h, props[i],
4045 &vals);
4046 break;
4048 /* returns NWAM_ENTITY_NOT_FOUND if no existing value */
4049 if (ret != NWAM_SUCCESS && ret != NWAM_ENTITY_NOT_FOUND)
4050 continue;
4052 /* print property */
4053 (void) printf("%s", props[i]);
4054 /* print the existing value(s) if they exist */
4055 if (ret == NWAM_SUCCESS) {
4056 (void) printf(" (");
4057 output_prop_val(props[i], vals, stdout, B_TRUE);
4058 (void) putchar(')');
4059 nwam_value_free(vals);
4061 /* print choices, won't print anything if there aren't any */
4062 print_all_prop_choices(object_type, props[i]);
4063 (void) printf("> ");
4065 /* wait for user input */
4066 if (fgets(line, sizeof (line), stdin) == NULL)
4067 continue;
4069 /* if user input new value, existing value is overrode */
4070 if (line[0] != '\n') {
4071 boolean_t is_listprop;
4072 int pt_type = prop_to_pt(object_type, props[i]);
4074 is_listprop = is_prop_multivalued(object_type,
4075 props[i]);
4076 vals = str_to_nwam_value(object_type, line, pt_type,
4077 is_listprop);
4078 if (vals == NULL) {
4079 ret = NWAM_ENTITY_INVALID_VALUE;
4080 goto repeat;
4083 /* set the new value for the property */
4084 switch (object_type) {
4085 case NWAM_OBJECT_TYPE_NCU:
4086 ret = nwam_ncu_set_prop_value(ncu_h, props[i],
4087 vals);
4088 break;
4089 case NWAM_OBJECT_TYPE_LOC:
4090 ret = nwam_loc_set_prop_value(loc_h, props[i],
4091 vals);
4092 break;
4093 case NWAM_OBJECT_TYPE_ENM:
4094 ret = nwam_enm_set_prop_value(enm_h, props[i],
4095 vals);
4096 break;
4097 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4098 ret = nwam_known_wlan_set_prop_value(wlan_h,
4099 props[i], vals);
4100 break;
4102 nwam_value_free(vals);
4104 if (ret != NWAM_SUCCESS)
4105 goto repeat;
4107 need_to_commit = B_TRUE;
4108 continue;
4110 repeat:
4111 invalid_set_prop_msg(props[i], ret);
4112 i--; /* decrement i to repeat */
4116 free(props);
4120 * Verify whether all properties of a resource are valid.
4122 /* ARGSUSED */
4123 void
4124 verify_func(cmd_t *cmd)
4126 nwam_error_t ret;
4127 const char *errprop;
4129 switch (active_object_type()) {
4130 case NWAM_OBJECT_TYPE_NCU:
4131 ret = nwam_ncu_validate(ncu_h, &errprop);
4132 break;
4133 case NWAM_OBJECT_TYPE_LOC:
4134 ret = nwam_loc_validate(loc_h, &errprop);
4135 break;
4136 case NWAM_OBJECT_TYPE_ENM:
4137 ret = nwam_enm_validate(enm_h, &errprop);
4138 break;
4139 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4140 ret = nwam_known_wlan_validate(wlan_h, &errprop);
4141 break;
4143 if (ret != NWAM_SUCCESS)
4144 nwamerr(ret, "Verify error on property '%s'", errprop);
4145 else if (interactive_mode)
4146 (void) printf(gettext("All properties verified\n"));
4150 * command-line mode (# nwamcfg list or # nwamcfg "select loc test; list")
4152 static int
4153 one_command_at_a_time(int argc, char *argv[])
4155 char *command;
4156 size_t len = 2; /* terminal \n\0 */
4157 int i, err;
4159 for (i = 0; i < argc; i++)
4160 len += strlen(argv[i]) + 1;
4161 if ((command = malloc(len)) == NULL) {
4162 nerr("Out of memory");
4163 return (NWAM_ERR);
4165 (void) strlcpy(command, argv[0], len);
4166 for (i = 1; i < argc; i++) {
4167 (void) strlcat(command, " ", len);
4168 (void) strlcat(command, argv[i], len);
4170 (void) strlcat(command, "\n", len);
4171 err = string_to_yyin(command);
4172 free(command);
4173 if (err != NWAM_OK)
4174 return (err);
4175 while (!feof(yyin)) {
4176 yyparse();
4179 * If any command on a list of commands give an error,
4180 * don't continue with the remaining commands.
4182 if (saw_error || time_to_exit)
4183 return (cleanup());
4186 /* if there are changes to commit, commit it */
4187 if (need_to_commit) {
4188 do_commit();
4189 /* if need_to_commit is not set, then there was a error */
4190 if (need_to_commit)
4191 return (NWAM_ERR);
4194 if (!interactive_mode)
4195 return (cleanup());
4196 else {
4197 yyin = stdin;
4198 return (read_input());
4203 * cmd_file is slightly more complicated, as it has to open the command file
4204 * and set yyin appropriately. Once that is done, though, it just calls
4205 * read_input(), and only once, since prompting is not possible.
4207 static int
4208 cmd_file(char *file)
4210 FILE *infile;
4211 int err;
4212 struct stat statbuf;
4213 boolean_t using_real_file = (strcmp(file, "-") != 0);
4215 if (using_real_file) {
4217 * nerr() prints a line number in cmd_file_mode, which we do
4218 * not want here, so temporarily unset it.
4220 cmd_file_mode = B_FALSE;
4221 if ((infile = fopen(file, "r")) == NULL) {
4222 nerr(gettext("could not open file '%s': %s"),
4223 file, strerror(errno));
4224 return (1);
4226 if ((err = fstat(fileno(infile), &statbuf)) != 0) {
4227 nerr(gettext("could not stat file '%s': %s"),
4228 file, strerror(errno));
4229 err = 1;
4230 goto done;
4232 if (!S_ISREG(statbuf.st_mode)) {
4233 nerr(gettext("'%s' is not a regular file."), file);
4234 err = 1;
4235 goto done;
4239 * If -d was passed on the command-line, we need to
4240 * start by removing any existing configuration.
4241 * Alternatively, the file may begin with 'destroy -a';
4242 * but in that case, the line will go through the lexer
4243 * and be processed as it's encountered in the file.
4245 if (remove_all_configurations && destroy_all() != NWAM_SUCCESS)
4246 goto done;
4248 /* set up for lexer */
4249 yyin = infile;
4250 cmd_file_mode = B_TRUE;
4251 ok_to_prompt = B_FALSE;
4252 } else {
4254 * "-f -" is essentially the same as interactive mode,
4255 * so treat it that way.
4257 interactive_mode = B_TRUE;
4259 /* NWAM_REPEAT is for interactive mode; treat it like NWAM_ERR here. */
4260 if ((err = read_input()) == NWAM_REPEAT)
4261 err = NWAM_ERR;
4262 if (err == NWAM_OK)
4263 (void) printf(gettext("Configuration read.\n"));
4265 done:
4266 if (using_real_file)
4267 (void) fclose(infile);
4268 return (err);
4272 main(int argc, char *argv[])
4274 int err;
4275 char c;
4277 /* This must be before anything goes to stdout. */
4278 setbuf(stdout, NULL);
4280 if ((execname = strrchr(argv[0], '/')) == NULL)
4281 execname = argv[0];
4282 else
4283 execname++;
4285 (void) setlocale(LC_ALL, "");
4286 (void) textdomain(TEXT_DOMAIN);
4288 while ((c = getopt(argc, argv, "?hf:d")) != EOF) {
4289 switch (c) {
4290 case 'f':
4291 cmd_file_name = optarg;
4292 cmd_file_mode = B_TRUE;
4293 break;
4294 case '?':
4295 case 'h':
4296 cmd_line_usage();
4297 return (NWAM_OK);
4298 case 'd':
4299 remove_all_configurations = B_TRUE;
4300 break;
4301 default:
4302 cmd_line_usage();
4303 return (NWAM_ERR);
4306 /* -d can only be used with -f */
4307 if (remove_all_configurations && !cmd_file_mode) {
4308 nerr("Option -d can only be used with -f");
4309 return (NWAM_ERR);
4313 * This may get set back to FALSE again in cmd_file() if cmd_file_name
4314 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
4316 if (isatty(STDIN_FILENO))
4317 ok_to_prompt = B_TRUE;
4318 if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
4319 exit(NWAM_ERR);
4320 if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
4321 exit(NWAM_ERR);
4322 (void) sigset(SIGINT, SIG_IGN);
4324 if (optind == argc) {
4325 /* interactive or command-file mode */
4326 if (!cmd_file_mode)
4327 err = do_interactive();
4328 else
4329 err = cmd_file(cmd_file_name);
4330 } else {
4331 /* command-line mode */
4332 err = one_command_at_a_time(argc - optind, &(argv[optind]));
4334 (void) del_GetLine(gl);
4336 return (err);