1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
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.
31 */
32
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>
47
48 #include "nwamcfg.h"
49
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
53
54 struct help {
55 uint_t cmd_num;
56 const char *cmd_name;
57 const char *cmd_usage;
58 };
59
60 extern int yyparse(void);
61 extern int lex_lineno;
62
63 #define MAX_LINE_LEN 1024
64 #define MAX_CMD_HIST 1024
65
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]"
85
86 /*
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
93 */
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
100
101 /* delimiter used for list of values */
102 #define NWAM_VALUE_DELIMITER_CHAR ','
103 #define NWAM_VALUE_DELIMITER_STR ","
104
105 /* the max number of values for an enum used by some properties in libnwam */
106
107 /*
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.
110 */
111
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 }
130 };
131
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
140 };
141
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
147 };
148
149 /*
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.
153 */
154
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
202 };
203
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;
209
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 }
230 };
231
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 }
241 };
242
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 }
267 };
268
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 }
277 };
278
279 /* Returns the appropriate properties table for the given object type */
280 static prop_table_entry_t *
get_prop_table(nwam_object_type_t object_type)281 get_prop_table(nwam_object_type_t object_type)
282 {
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);
292 }
293 return (NULL);
294 }
295
296 /* Global variables */
297
298 /* set early in main(), never modified thereafter, used all over the place */
299 static char *execname;
300
301 /* set in modifying functions, checked in read_input() */
302 boolean_t saw_error = B_FALSE;
303
304 /* set in yacc parser, checked in read_input() */
305 boolean_t newline_terminated;
306
307 /* set in main(), checked in lex error handler */
308 boolean_t cmd_file_mode = B_FALSE;
309
310 /* set in exit_func(), checked in read_input() */
311 static boolean_t time_to_exit = B_FALSE;
312
313 /* used in nerr() and nwamerr() */
314 static char *cmd_file_name = NULL;
315
316 /* used with cmd_file to destroy all configurations */
317 static boolean_t remove_all_configurations = B_FALSE;
318
319 /* checked in read_input() and other places */
320 static boolean_t ok_to_prompt = B_FALSE;
321
322 /* initialized in do_interactive(), checked in initialize() */
323 static boolean_t interactive_mode;
324
325 static boolean_t need_to_commit = B_FALSE;
326
327 /* The gl_get_line() resource object */
328 static GetLine *gl;
329
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;
336
337 static int current_scope = NWAM_SCOPE_GBL;
338
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];
342
343 /* obj2_* are used in NWAM_SCOPE_NCU only */
344 static int obj2_type;
345 static char obj2_name[NWAM_MAX_NAME_LEN + 1];
346
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
359 };
360
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
368 };
369
370 static const char *global_destroy_cmds[] = {
371 "destroy -a ",
372 "destroy loc ",
373 "destroy enm ",
374 "destroy ncp ",
375 "destroy wlan ",
376 NULL
377 };
378
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
389 };
390
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
401 };
402
403 static const char *global_select_cmds[] = {
404 "select loc ",
405 "select enm ",
406 "select ncp ",
407 "select wlan ",
408 NULL
409 };
410
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
431 };
432
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
445 };
446
447 static const char *ncp_create_cmds[] = {
448 "create ncu ip ",
449 "create ncu phys ",
450 "create -t ", /* template */
451 NULL
452 };
453
454 static const char *ncp_destroy_cmds[] = {
455 "destroy ncu ",
456 "destroy ncu ip ",
457 "destroy ncu phys ",
458 NULL
459 };
460
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
468 };
469
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
479 };
480
481 static const char *ncp_select_cmds[] = {
482 "select ncu ",
483 "select ncu ip ",
484 "select ncu phys ",
485 NULL
486 };
487
488 /* Functions begin here */
489
490 cmd_t *
alloc_cmd(void)491 alloc_cmd(void)
492 {
493 cmd_t *cmd = calloc(1, sizeof (cmd_t));
494 if (cmd == NULL) {
495 nerr("Out of memory");
496 return (NULL);
497 }
498 cmd->cmd_argc = 0;
499 cmd->cmd_argv[0] = NULL;
500
501 return (cmd);
502 }
503
504 void
free_cmd(cmd_t * cmd)505 free_cmd(cmd_t *cmd)
506 {
507 int i;
508
509 for (i = 0; i < cmd->cmd_argc; i++)
510 free(cmd->cmd_argv[i]);
511 free(cmd);
512 }
513
514 void
array_free(void ** array,int nelem)515 array_free(void **array, int nelem)
516 {
517 int i;
518 for (i = 0; i < nelem; i++)
519 free(array[i]);
520 free(array);
521 }
522
523 static boolean_t
initial_match(const char * line1,const char * line2,int word_end)524 initial_match(const char *line1, const char *line2, int word_end)
525 {
526 if (word_end <= 0)
527 return (B_TRUE);
528 return (strncmp(line1, line2, word_end) == 0);
529 }
530
531 static int
add_stuff(WordCompletion * cpl,const char * line1,const char ** list,int word_end)532 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
533 int word_end)
534 {
535 int i, err;
536
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);
543 }
544 }
545 return (0);
546 }
547
548 /*
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.
552 */
553 #define MINI_STR(l, s, m, n) strncmp(l, s, MAX(MIN(sizeof (s) - 1, m), n))
554
555 /* ARGSUSED */
556 static
CPL_MATCH_FN(cmd_cpl_fn)557 CPL_MATCH_FN(cmd_cpl_fn)
558 {
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));
599 }
600 /* should never get here */
601 return (NULL);
602 }
603
604 const char *
cmd_to_str(int cmd_num)605 cmd_to_str(int cmd_num)
606 {
607 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
608 return (helptab[cmd_num].cmd_name);
609 }
610
611 /* Returns "loc", "enm", "wlan" or "ncp" as string */
612 static const char *
rt1_to_str(int res_type)613 rt1_to_str(int res_type)
614 {
615 assert(res_type >= RT1_MIN && res_type <= RT1_MAX);
616 return (res1_types[res_type]);
617 }
618
619 /* Returns "ncu" as string */
620 static const char *
rt2_to_str(int res_type)621 rt2_to_str(int res_type)
622 {
623 assert(res_type >= RT2_MIN && res_type <= RT2_MAX);
624 return (res2_types[res_type]);
625 }
626
627 /* Returns "ncp, "ncu", "loc", "enm", or "wlan" according to the scope */
628 static const char *
scope_to_str(int scope)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");
645 }
646 }
647
648 /* Given an enm property and value, returns it as a string */
649 static const char *
propval_to_str(const char * propname,uint64_t value)650 propval_to_str(const char *propname, uint64_t value)
651 {
652 const char *str;
653
654 if (nwam_uint64_get_value_string(propname, value, &str) == NWAM_SUCCESS)
655 return (str);
656 return (NULL);
657 }
658
659 /* Given an int for a prop, returns it as string */
660 static const char *
pt_to_str(int prop_type)661 pt_to_str(int prop_type)
662 {
663 assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
664 return (pt_types[prop_type]);
665 }
666
667 /* Return B_TRUE if string starts with "t" or is 1, B_FALSE otherwise */
668 static boolean_t
str_to_boolean(const char * str)669 str_to_boolean(const char *str)
670 {
671 if (strncasecmp(str, "t", 1) == 0 || atoi(str) == 1)
672 return (B_TRUE);
673 else
674 return (B_FALSE);
675 }
676
677 /*
678 * This is a separate function rather than a set of define's because of the
679 * gettext() wrapping.
680 */
681
682 /*
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.
686 */
687
688 static const char *
long_help(int cmd_num)689 long_help(int cmd_num)
690 {
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."));
733 }
734 }
735
736 void
command_usage(int command)737 command_usage(int command)
738 {
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);
744 }
745 }
746
747 static void
long_usage(uint_t cmd_num)748 long_usage(uint_t cmd_num)
749 {
750 (void) printf("%s: %s\n", gettext("usage"),
751 helptab[cmd_num].cmd_usage);
752 (void) printf("\t%s\n", long_help(cmd_num));
753 }
754
755 /* Prints usage for command line options */
756 static void
cmd_line_usage()757 cmd_line_usage()
758 {
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"));
766 }
767
768 /* Prints the line number of the current command if in command-file mode */
769 static void
print_lineno()770 print_lineno()
771 {
772 static int last_lineno;
773
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;
783 }
784 }
785
786 /* PRINTFLIKE1 */
787 void
nerr(const char * format,...)788 nerr(const char *format, ...)
789 {
790 va_list alist;
791
792 print_lineno();
793
794 format = gettext(format);
795 va_start(alist, format);
796 (void) vfprintf(stderr, format, alist);
797 va_end(alist);
798 (void) fprintf(stderr, "\n");
799
800 saw_error = B_TRUE;
801 }
802
803 /* PRINTFLIKE2 */
804 static void
nwamerr(nwam_error_t err,const char * format,...)805 nwamerr(nwam_error_t err, const char *format, ...)
806 {
807 va_list alist;
808
809 print_lineno();
810
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));
816
817 saw_error = B_TRUE;
818 }
819
820 void
properr(const char * prop)821 properr(const char *prop)
822 {
823 nerr("Invalid property: '%s'", prop);
824 }
825
826 /*
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.
830 */
831 static void
free_handle(boolean_t free_ncu_only)832 free_handle(boolean_t free_ncu_only)
833 {
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;
842 }
843 }
844
845 if (enm_h != NULL) {
846 nwam_enm_free(enm_h);
847 enm_h = NULL;
848 }
849
850 if (loc_h != NULL) {
851 nwam_loc_free(loc_h);
852 loc_h = NULL;
853 }
854
855 if (wlan_h != NULL) {
856 nwam_known_wlan_free(wlan_h);
857 wlan_h = NULL;
858 }
859 }
860
861 /*
862 * On input, TRUE => yes, FALSE => no.
863 * On return, TRUE => 1, FALSE => no, could not ask => -1.
864 */
865 static int
ask_yesno(boolean_t default_answer,const char * question)866 ask_yesno(boolean_t default_answer, const char *question)
867 {
868 char line[64]; /* should be enough to answer yes or no */
869
870 if (!ok_to_prompt) {
871 saw_error = B_TRUE;
872 return (-1);
873 }
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);
880
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);
887 }
888 }
889
890 /* This is the back-end helper function for read_input() below. */
891 static int
cleanup()892 cleanup()
893 {
894 int answer;
895
896 if (!interactive_mode && !cmd_file_mode) {
897 /*
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.
905 */
906 ok_to_prompt = B_FALSE;
907 }
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:
916 /*
917 * don't want to save, just exit. handles are freed at
918 * end_func() or exit_func().
919 */
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);
926 }
927 }
928 return (saw_error ? NWAM_ERR : NWAM_OK);
929 }
930
931 static int
string_to_yyin(char * string)932 string_to_yyin(char *string)
933 {
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;
940
941 return (NWAM_OK);
942
943 error:
944 nerr("problem creating temporary file");
945 return (NWAM_ERR);
946 }
947
948 /*
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.
953 */
954 static int
read_input(void)955 read_input(void)
956 {
957 boolean_t yyin_is_a_tty = isatty(fileno(yyin));
958 /*
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.
961 */
962 char prompt[MAXPATHLEN + (2 * (NWAM_MAX_TYPE_LEN + NWAM_MAX_NAME_LEN))
963 + sizeof ("::::> ")];
964 char *line;
965
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);
983
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);
990 }
991 }
992 /*
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.
996 */
997 line = gl_get_line(gl, prompt, NULL, -1);
998 if (gl_return_status(gl) == GLR_SIGNAL) {
999 gl_abandon_line(gl);
1000 continue;
1001 }
1002 if (line == NULL)
1003 break;
1004 if (string_to_yyin(line) != NWAM_OK)
1005 break;
1006 while (!feof(yyin)) {
1007 yyparse();
1008
1009 /*
1010 * If any command on a list of commands
1011 * give an error, don't continue with the
1012 * remaining commands.
1013 */
1014 if (saw_error || time_to_exit)
1015 break;
1016 }
1017 } else {
1018 yyparse();
1019 }
1020
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;
1026 }
1027 return (cleanup());
1028 }
1029
1030 /*
1031 * This function is used in the interactive-mode scenario: it just calls
1032 * read_input() until we are done.
1033 */
1034 static int
do_interactive(void)1035 do_interactive(void)
1036 {
1037 int err;
1038
1039 interactive_mode = B_TRUE;
1040 do {
1041 err = read_input();
1042 } while (err == NWAM_REPEAT);
1043 return (err);
1044 }
1045
1046 /* Calls the help_func() to print the usage of all commands */
1047 void
help_wrap()1048 help_wrap()
1049 {
1050 cmd_t *help_cmd;
1051
1052 if ((help_cmd = alloc_cmd()) == NULL)
1053 exit(NWAM_ERR);
1054 help_func(help_cmd);
1055 free_cmd(help_cmd);
1056 }
1057
1058 /* Check if the given command is allowed in the current scope */
1059 boolean_t
check_scope(int cmd)1060 check_scope(int cmd)
1061 {
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);
1070 }
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);
1079 }
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);
1095 }
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);
1104 }
1105 break;
1106 default:
1107 nerr("Invalid scope");
1108 }
1109 nerr("'%s' is not allowed at this scope", cmd_to_str(cmd));
1110 return (B_FALSE);
1111 }
1112
1113 /* Returns the active object type depending on which handle is not NULL */
1114 static nwam_object_type_t
active_object_type()1115 active_object_type()
1116 {
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);
1130 }
1131
1132 /* Retrive the name of the object from its handle */
1133 static nwam_error_t
object_name_from_handle(nwam_object_type_t object_type,void * handle,char ** namep)1134 object_name_from_handle(nwam_object_type_t object_type, void *handle,
1135 char **namep)
1136 {
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));
1148 }
1149 return (NWAM_INVALID_ARG);
1150 }
1151
1152 static void
do_commit()1153 do_commit()
1154 {
1155 nwam_error_t ret = NWAM_SUCCESS;
1156 const char *errprop;
1157
1158 if (!need_to_commit)
1159 return;
1160
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;
1174 }
1175
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;
1182
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;
1197 }
1198
1199 if (verr != NWAM_SUCCESS)
1200 nwamerr(ret, "Commit error on property '%s'", errprop);
1201 else
1202 nwamerr(ret, "Commit error");
1203 }
1204 }
1205
1206 /*
1207 * Saves the current configuration to persistent storage.
1208 */
1209 /* ARGSUSED */
1210 void
commit_func(cmd_t * cmd)1211 commit_func(cmd_t *cmd)
1212 {
1213 if (!need_to_commit) {
1214 if (interactive_mode)
1215 (void) printf(gettext("Nothing to commit\n"));
1216 } else {
1217 do_commit();
1218 }
1219 }
1220
1221 static void
do_cancel()1222 do_cancel()
1223 {
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;
1244 }
1245 need_to_commit = B_FALSE;
1246 }
1247
1248 /*
1249 * End operation on current scope and go up one scope.
1250 * Changes are not saved, no prompt either.
1251 */
1252 /* ARGSUSED */
1253 void
cancel_func(cmd_t * cmd)1254 cancel_func(cmd_t *cmd)
1255 {
1256 do_cancel();
1257 }
1258
1259 /*
1260 * Removes leading and trailing quotes from a string.
1261 * Caller must free returned string.
1262 */
1263 static char *
trim_quotes(const char * quoted_str)1264 trim_quotes(const char *quoted_str)
1265 {
1266 char *str;
1267 int end;
1268
1269 /* export_func() and list_func() can pass NULL here */
1270 if (quoted_str == NULL)
1271 return (NULL);
1272
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);
1280
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;
1286
1287 return (str);
1288 }
1289
1290 /*
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.
1295 */
1296 void
create_func(cmd_t * cmd)1297 create_func(cmd_t *cmd)
1298 {
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;
1304
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;
1310 }
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;
1315 }
1316
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;
1327 }
1328 }
1329
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;
1346
1347 /* ncp must already be read */
1348 if (ncp_h == NULL) {
1349 nerr("Create error: NCP has not been read");
1350 goto done;
1351 }
1352
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);
1357 }
1358
1359 if (ret != NWAM_SUCCESS) {
1360 nwamerr(ret, "Create error");
1361 goto done;
1362 }
1363
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;
1371
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;
1379
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;
1387
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;
1396
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;
1406
1407 /* ncp must already be read */
1408 if (ncp_h == NULL) {
1409 nerr("Copy error: NCP has not been read");
1410 goto done;
1411 }
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);
1420 }
1421
1422 if (ret != NWAM_SUCCESS) {
1423 nwamerr(ret, "Copy error");
1424 goto done;
1425 }
1426 }
1427
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;
1443 }
1444 if (current_scope != NWAM_SCOPE_NCP)
1445 need_to_commit = B_TRUE;
1446
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);
1456 }
1457
1458 read_error:
1459 if (ret != NWAM_SUCCESS)
1460 nwamerr(ret, "Copy error reading '%s'", oldname);
1461
1462 done:
1463 free(oldname);
1464 free(newname);
1465 }
1466
1467 /* Processing of return value for destroy_*_callback() */
1468 static int
destroy_ret(nwam_object_type_t object_type,nwam_error_t ret,void * handle)1469 destroy_ret(nwam_object_type_t object_type, nwam_error_t ret, void *handle)
1470 {
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);
1480 }
1481 return (0);
1482 }
1483
1484 if (ret == NWAM_SUCCESS || ret == NWAM_ENTITY_IN_USE)
1485 return (0);
1486
1487 return (1);
1488 }
1489
1490 /*
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.
1494 *
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.
1497 */
1498 /* ARGSUSED */
1499 static int
destroy_ncp_callback(nwam_ncp_handle_t ncp,void * arg)1500 destroy_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
1501 {
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));
1505 }
1506
1507 /* ARGSUSED */
1508 static int
destroy_loc_callback(nwam_loc_handle_t loc,void * arg)1509 destroy_loc_callback(nwam_loc_handle_t loc, void *arg)
1510 {
1511 nwam_error_t ret = nwam_loc_destroy(loc, NWAM_FLAG_DO_NOT_FREE);
1512 return (destroy_ret(NWAM_OBJECT_TYPE_LOC, ret, loc));
1513 }
1514
1515 /* ARGSUSED */
1516 static int
destroy_enm_callback(nwam_enm_handle_t enm,void * arg)1517 destroy_enm_callback(nwam_enm_handle_t enm, void *arg)
1518 {
1519 nwam_error_t ret = nwam_enm_destroy(enm, NWAM_FLAG_DO_NOT_FREE);
1520 return (destroy_ret(NWAM_OBJECT_TYPE_ENM, ret, enm));
1521 }
1522
1523 /* ARGSUSED */
1524 static int
destroy_wlan_callback(nwam_known_wlan_handle_t wlan,void * arg)1525 destroy_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
1526 {
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));
1529 }
1530
1531 /*
1532 * Remove all existing configuration that are not read-only.
1533 * walk through all ncps, locs, enms, wlans and destroy each one.
1534 */
1535 static nwam_error_t
destroy_all(void)1536 destroy_all(void)
1537 {
1538 nwam_error_t ret;
1539
1540 assert(remove_all_configurations);
1541
1542 ret = nwam_walk_ncps(destroy_ncp_callback, NULL, 0, NULL);
1543 if (ret != NWAM_SUCCESS)
1544 goto done;
1545
1546 ret = nwam_walk_enms(destroy_enm_callback, NULL,
1547 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
1548 if (ret != NWAM_SUCCESS)
1549 goto done;
1550
1551 ret = nwam_walk_locs(destroy_loc_callback, NULL,
1552 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
1553 if (ret != NWAM_SUCCESS)
1554 goto done;
1555
1556 ret = nwam_walk_known_wlans(destroy_wlan_callback, NULL, 0, NULL);
1557 if (ret != NWAM_SUCCESS)
1558 goto done;
1559
1560 if (interactive_mode)
1561 (void) printf(gettext("All user-defined entities destroyed\n"));
1562 remove_all_configurations = B_FALSE;
1563
1564 done:
1565 if (ret != NWAM_SUCCESS) {
1566 nwamerr(ret, "Destroy error: "
1567 "could not destroy all configurations");
1568 }
1569 return (ret);
1570 }
1571
1572 /*
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.
1576 */
1577 void
destroy_func(cmd_t * cmd)1578 destroy_func(cmd_t *cmd)
1579 {
1580 nwam_error_t ret;
1581 char *name, *realname = NULL;
1582
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;
1588 }
1589
1590 assert(cmd->cmd_argc > 0);
1591
1592 /* res1_type is -1 if -a flag is used */
1593 if (cmd->cmd_res1_type == -1) {
1594 int c;
1595
1596 if (current_scope != NWAM_SCOPE_GBL) {
1597 nerr("Cannot destroy all configurations in a "
1598 "non-global scope");
1599 return;
1600 }
1601
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;
1611 }
1612 }
1613 if (remove_all_configurations) {
1614 (void) destroy_all();
1615 return;
1616 }
1617 }
1618
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;
1624
1625 /* ncp must already be read */
1626 if (ncp_h == NULL) {
1627 nerr("Destroy ncu error: NCP has not been read");
1628 return;
1629 }
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");
1670 }
1671
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);
1683 }
1684 free(name);
1685 free(realname);
1686 }
1687
1688 /*
1689 * End operation on current scope and go up one scope.
1690 * Changes are saved.
1691 */
1692 /* ARGSUSED */
1693 void
end_func(cmd_t * cmd)1694 end_func(cmd_t *cmd)
1695 {
1696 /* if need_to_commit is set, commit changes */
1697 if (need_to_commit)
1698 do_commit();
1699
1700 /*
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.
1703 */
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();
1712 }
1713 }
1714
1715 /*
1716 * Exit immediately. Configuration changes are saved by calling end_func().
1717 */
1718 /* ARGSUSED */
1719 void
exit_func(cmd_t * cmd)1720 exit_func(cmd_t *cmd)
1721 {
1722 cmd_t *end_cmd;
1723
1724 if (need_to_commit) {
1725 if ((end_cmd = alloc_cmd()) == NULL) {
1726 nerr("Exit error");
1727 return;
1728 }
1729 end_func(end_cmd);
1730 free_cmd(end_cmd);
1731 }
1732
1733 /*
1734 * If need_to_commit is still set, then the commit failed.
1735 * Otherwise, exit.
1736 */
1737 if (!need_to_commit)
1738 time_to_exit = B_TRUE;
1739 }
1740
1741 void
help_func(cmd_t * cmd)1742 help_func(cmd_t *cmd)
1743 {
1744 int i;
1745
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;
1751 }
1752
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;
1757 }
1758 }
1759 (void) fprintf(stderr, gettext("Unknown command: '%s'\n"),
1760 cmd->cmd_argv[0]);
1761 help_wrap();
1762 }
1763
1764 /*
1765 * Revert configuration of an instance to latest previous version.
1766 * Free the handle and read again.
1767 */
1768 /* ARGSUSED */
1769 void
revert_func(cmd_t * cmd)1770 revert_func(cmd_t *cmd)
1771 {
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();
1776
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;
1784 }
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;
1813 }
1814
1815 /* Exit this scope because handle already freed (call do_cancel()) */
1816 need_to_commit = B_FALSE;
1817
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");
1824 }
1825 do_cancel();
1826 }
1827 free(name);
1828 return;
1829
1830 name_error:
1831 if (ret != NWAM_SUCCESS)
1832 nwamerr(ret, "Revert error: get name error");
1833 }
1834
1835 /*
1836 * Load a resource from persistent repository and enter the scope
1837 * of that resource.
1838 */
1839 void
select_func(cmd_t * cmd)1840 select_func(cmd_t *cmd)
1841 {
1842 nwam_error_t ret;
1843 char *name, *realname = NULL;
1844
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;
1850 }
1851
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);
1861 }
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);
1869 }
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);
1877 }
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;
1883
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;
1889 }
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);
1897 }
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);
1904 }
1905 }
1906 break;
1907 default:
1908 nerr("Select error: unknown object-type");
1909 free(name);
1910 return;
1911 }
1912
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;
1927 }
1928 }
1929 free(name);
1930 free(realname);
1931 }
1932
1933 /* Given an int for prop, returns it as string */
1934 static const char *
pt_to_prop_name(nwam_object_type_t object_type,int pt_type)1935 pt_to_prop_name(nwam_object_type_t object_type, int pt_type)
1936 {
1937 int i;
1938 prop_table_entry_t *prop_table = get_prop_table(object_type);
1939
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);
1943 }
1944 return (NULL);
1945 }
1946
1947 /* Given a prop as a string, returns it as an int */
1948 static int
prop_to_pt(nwam_object_type_t object_type,const char * prop)1949 prop_to_pt(nwam_object_type_t object_type, const char *prop)
1950 {
1951 int i;
1952 prop_table_entry_t *prop_table = get_prop_table(object_type);
1953
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);
1957 }
1958 return (-1);
1959 }
1960
1961 /* Given a prop as an int, returns its type (nwam_value_type_t) */
1962 static nwam_value_type_t
prop_value_type(nwam_object_type_t object_type,const char * prop)1963 prop_value_type(nwam_object_type_t object_type, const char *prop)
1964 {
1965 nwam_error_t ret;
1966 nwam_value_type_t value_type;
1967
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;
1981 }
1982
1983 if (ret != NWAM_SUCCESS)
1984 value_type = NWAM_VALUE_TYPE_UNKNOWN;
1985
1986 return (value_type);
1987 }
1988
1989 /*
1990 * Converts input_str to an array nwam_value.
1991 * If is_list_prop, break input_str into array of strings first.
1992 */
1993 static nwam_value_t
str_to_nwam_value(nwam_object_type_t object_type,char * input_str,int pt_type,boolean_t is_list_prop)1994 str_to_nwam_value(nwam_object_type_t object_type, char *input_str, int pt_type,
1995 boolean_t is_list_prop)
1996 {
1997 int i, n = 0, ret;
1998 nwam_value_t data;
1999 char **val;
2000 int max_str_num;
2001
2002 nwam_value_type_t value_type;
2003 int64_t *int_vals;
2004 uint64_t *uint_vals;
2005 boolean_t *boolean_vals;
2006
2007 /*
2008 * Worst case is that each char separated by DELIMITER, so the
2009 * max number of sub strings is half of string length + 1.
2010 */
2011 max_str_num = strlen(input_str) / 2 + 1;
2012
2013 val = calloc(max_str_num, sizeof (char *));
2014 if (val == NULL) {
2015 nerr("Out of memory");
2016 return (NULL);
2017 }
2018
2019 if (is_list_prop) {
2020 char *tmp, *next;
2021 /*
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
2026 */
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;
2032 }
2033 } else {
2034 val[n++] = trim_quotes(input_str);
2035 }
2036
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);
2046 }
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);
2053 }
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);
2060 }
2061 }
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:
2069 {
2070 int_vals[i] = (int64_t)atoi(val[i]);
2071 break;
2072 }
2073 case NWAM_VALUE_TYPE_UINT64:
2074 {
2075 uint64_t str_as_enum;
2076 char *endptr;
2077
2078 ret = nwam_value_string_get_uint64(
2079 pt_to_prop_name(object_type, pt_type),
2080 val[i], &str_as_enum);
2081 /*
2082 * Returns _SUCCESS if value for enum is valid.
2083 * Returns _INVALID_ARG if property is not an enum.
2084 */
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);
2094 }
2095 } else {
2096 free(uint_vals);
2097 array_free((void **)val, max_str_num);
2098 return (NULL);
2099 }
2100 break;
2101 }
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);
2108 }
2109 }
2110
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);
2123 }
2124 array_free((void **)val, max_str_num);
2125
2126 if (ret != NWAM_SUCCESS) {
2127 nwamerr(ret, "Failed creating nwam_value");
2128 return (NULL);
2129 }
2130
2131 return (data);
2132 }
2133
2134 /*
2135 * Displaying/Skipping of properties
2136 * ---------------------------------
2137 *
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().
2141 *
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"
2146 *
2147 * NB: If a property does not appear in this table, then that implies
2148 * that the property is always shown.
2149 *
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.
2158 */
2159
2160 /* The most number of values in pde_checkvals below */
2161 #define NWAM_CHECKVALS_MAX 5
2162
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;
2168
2169 /* Rules for showing properties: commented for clarity */
2170
2171 /*
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
2175 */
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 } }
2201 };
2202
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 } }
2210 };
2211
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 } }
2252 };
2253
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 } }
2258 };
2259
2260 /* Returns the appropriate rules table for the given object type */
2261 static prop_display_entry_t *
get_prop_display_table(nwam_object_type_t object_type)2262 get_prop_display_table(nwam_object_type_t object_type)
2263 {
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);
2273 }
2274 return (NULL);
2275 }
2276
2277 /*
2278 * Tests whether prop must be shown during a walk depending on the
2279 * value of a different property.
2280 *
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.
2284 *
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.
2289 */
2290 static boolean_t
show_prop_test(nwam_object_type_t object_type,const char * prop,prop_display_entry_t * display_list,char ** checked_props,int num_checked)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)
2293 {
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;
2299
2300 /*
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.
2304 */
2305 for (i = 0; i < num_checked; i++) {
2306 if (strcmp(prop, checked_props[i]) == 0) {
2307 free(checked_props);
2308 return (B_FALSE);
2309 }
2310 }
2311
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;
2316
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);
2333 }
2334 if (ret != NWAM_SUCCESS)
2335 continue;
2336
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;
2340
2341 if (prop_type == NWAM_VALUE_TYPE_UINT64) {
2342 uint64_t *prop_uvals;
2343 int64_t *check_uvals;
2344 uint_t numvals;
2345
2346 if (nwam_value_get_uint64_array(prop_val, &prop_uvals,
2347 &numvals) != NWAM_SUCCESS) {
2348 nwam_value_free(prop_val);
2349 continue;
2350 }
2351
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;
2361 }
2362 }
2363 }
2364 } else if (prop_type == NWAM_VALUE_TYPE_BOOLEAN) {
2365 boolean_t bval;
2366
2367 if (nwam_value_get_boolean(prop_val, &bval) !=
2368 NWAM_SUCCESS) {
2369 nwam_value_free(prop_val);
2370 continue;
2371 }
2372
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;
2381 }
2382 }
2383 }
2384
2385 next_rule:
2386 nwam_value_free(prop_val);
2387 /*
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.
2392 */
2393 if (show_prop) {
2394 char **newprops = realloc(checked_props,
2395 ++num_checked * sizeof (char *));
2396 if (newprops == NULL) {
2397 free(checked_props);
2398 return (B_FALSE);
2399 }
2400 checked_props = newprops;
2401 checked_props[num_checked - 1] = (char *)prop;
2402
2403 return (show_prop_test(object_type,
2404 display_list[i].pde_checkname, display_list,
2405 checked_props, num_checked));
2406 }
2407 }
2408
2409 /*
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.
2413 */
2414 free(checked_props);
2415 if (prop_found)
2416 return (B_FALSE);
2417 else
2418 return (B_TRUE);
2419 }
2420
2421 /*
2422 * Returns true if the given property is read-only and cannot be modified.
2423 */
2424 static boolean_t
is_prop_read_only(nwam_object_type_t object_type,const char * prop)2425 is_prop_read_only(nwam_object_type_t object_type, const char *prop)
2426 {
2427 boolean_t ro;
2428
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);
2445 }
2446 return (B_FALSE);
2447 }
2448
2449 /* Returns true if the property is multi-valued */
2450 static boolean_t
is_prop_multivalued(nwam_object_type_t object_type,const char * prop)2451 is_prop_multivalued(nwam_object_type_t object_type, const char *prop)
2452 {
2453 nwam_error_t ret;
2454 boolean_t multi;
2455
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;
2469 }
2470
2471 if (ret != NWAM_SUCCESS)
2472 multi = B_FALSE;
2473 return (multi);
2474 }
2475
2476 /*
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.
2479 */
2480 static void
invalid_set_prop_msg(const char * prop,nwam_error_t err)2481 invalid_set_prop_msg(const char *prop, nwam_error_t err)
2482 {
2483 const char *description;
2484
2485 if (err == NWAM_SUCCESS)
2486 return;
2487
2488 if (err != NWAM_ENTITY_INVALID_VALUE) {
2489 nwamerr(err, "Set error");
2490 return;
2491 }
2492
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;
2507 }
2508 nerr("Set error: invalid value\n'%s' %s", prop, description);
2509 }
2510
2511 /*
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.
2519 */
2520 void
set_func(cmd_t * cmd)2521 set_func(cmd_t *cmd)
2522 {
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;
2531
2532 assert(cmd->cmd_argc > 0);
2533
2534 object_type = active_object_type();
2535 prop_table = get_prop_display_table(object_type);
2536
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;
2542 }
2543
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;
2548 }
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);
2553 }
2554 }
2555
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;
2562 }
2563
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;
2578 }
2579 nwam_value_free(prop_value);
2580
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);
2586 }
2587
2588 static int
list_callback(nwam_object_type_t object_type,void * handle,boolean_t * list_msgp,const char * msg)2589 list_callback(nwam_object_type_t object_type, void *handle,
2590 boolean_t *list_msgp, const char *msg)
2591 {
2592 nwam_error_t ret;
2593 char *name;
2594 nwam_ncu_class_t class;
2595
2596 if (*list_msgp) {
2597 (void) printf("%s:\n", msg);
2598 *list_msgp = B_FALSE;
2599 }
2600
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);
2605 }
2606
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));
2617 }
2618 }
2619 (void) printf("\t%s\n", name);
2620
2621 free(name);
2622 return (0);
2623 }
2624
2625 /* Print out name, type and status */
2626 static int
list_loc_callback(nwam_loc_handle_t loc,void * arg)2627 list_loc_callback(nwam_loc_handle_t loc, void *arg)
2628 {
2629 return (list_callback(NWAM_OBJECT_TYPE_LOC, loc, arg, "Locations"));
2630 }
2631
2632 static int
list_enm_callback(nwam_enm_handle_t enm,void * arg)2633 list_enm_callback(nwam_enm_handle_t enm, void *arg)
2634 {
2635 return (list_callback(NWAM_OBJECT_TYPE_ENM, enm, arg, "ENMs"));
2636 }
2637
2638 static int
list_wlan_callback(nwam_known_wlan_handle_t wlan,void * arg)2639 list_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
2640 {
2641 return (list_callback(NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan, arg, "WLANs"));
2642 }
2643
2644 static int
list_ncp_callback(nwam_ncp_handle_t ncp,void * arg)2645 list_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
2646 {
2647 return (list_callback(NWAM_OBJECT_TYPE_NCP, ncp, arg, "NCPs"));
2648 }
2649
2650 static int
list_ncu_callback(nwam_ncu_handle_t ncu,void * arg)2651 list_ncu_callback(nwam_ncu_handle_t ncu, void *arg)
2652 {
2653 return (list_callback(NWAM_OBJECT_TYPE_NCU, ncu, arg, "NCUs"));
2654 }
2655
2656 /* functions to convert a value to a string */
2657 /* ARGSUSED */
2658 static const char *
str2str(void * s,const char * prop,char * str)2659 str2str(void *s, const char *prop, char *str)
2660 {
2661 (void) snprintf(str, NWAM_MAX_VALUE_LEN, "%s", s);
2662 return (str);
2663 }
2664
2665 /* ARGSUSED */
2666 static const char *
str2qstr(void * s,const char * prop,char * qstr)2667 str2qstr(void *s, const char *prop, char *qstr)
2668 {
2669 /* quoted strings */
2670 (void) snprintf(qstr, NWAM_MAX_VALUE_LEN, "\"%s\"", s);
2671 return (qstr);
2672 }
2673
2674 /* ARGSUSED */
2675 static const char *
int2str(void * in,const char * prop,char * instr)2676 int2str(void *in, const char *prop, char *instr)
2677 {
2678 (void) snprintf(instr, NWAM_MAX_VALUE_LEN, "%lld", *((int64_t *)in));
2679 return (instr);
2680 }
2681
2682 static const char *
uint2str(void * uin,const char * prop,char * uintstr)2683 uint2str(void *uin, const char *prop, char *uintstr)
2684 {
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));
2690 }
2691 return (uintstr);
2692 }
2693
2694 /* ARGSUSED */
2695 static const char *
bool2str(void * bool,const char * prop,char * boolstr)2696 bool2str(void *bool, const char *prop, char *boolstr)
2697 {
2698 (void) snprintf(boolstr, NWAM_MAX_VALUE_LEN, "%s",
2699 *((boolean_t *)bool) ? "true" : "false");
2700 return (boolstr);
2701 }
2702
2703 /*
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.
2706 */
2707 static void
output_prop_val(const char * prop_name,nwam_value_t value,FILE * wf,boolean_t quoted_strings)2708 output_prop_val(const char *prop_name, nwam_value_t value, FILE *wf,
2709 boolean_t quoted_strings)
2710 {
2711 nwam_value_type_t value_type;
2712 uint_t num;
2713
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;
2719
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;
2724
2725 if (nwam_value_get_type(value, &value_type) != NWAM_SUCCESS) {
2726 nerr("Get value type error");
2727 return;
2728 }
2729
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;
2735 }
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;
2742 }
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;
2749 }
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;
2756 }
2757 tostr = bool2str;
2758 }
2759
2760 /* now, loop and print each value */
2761 for (i = 0; i < num; i++) {
2762 void *val;
2763
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]);
2773
2774 (void) fprintf(wf, "%s%s", tostr(val, prop_name, str),
2775 i != num-1 ? NWAM_VALUE_DELIMITER_STR : "");
2776 }
2777 }
2778
2779 /* Prints the property names aligned (for list/get) or "prop=" (for export) */
2780 static int
output_propname_common(const char * prop,nwam_value_t values,void * arg,int width)2781 output_propname_common(const char *prop, nwam_value_t values, void *arg,
2782 int width)
2783 {
2784 FILE *of = (arg == NULL) ? stdout : arg;
2785
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);
2791
2792 if (values != NULL)
2793 output_prop_val(prop, values, of, B_TRUE);
2794
2795 (void) fprintf(of, "\n");
2796 return (0);
2797 }
2798
2799 static int
output_propname(const char * prop,nwam_value_t values,void * arg)2800 output_propname(const char *prop, nwam_value_t values, void *arg)
2801 {
2802 return (output_propname_common(prop, values, arg, 16));
2803 }
2804
2805 /* For locations because of longer property names */
2806 static int
output_loc_propname(const char * prop,nwam_value_t values,void * arg)2807 output_loc_propname(const char *prop, nwam_value_t values, void *arg)
2808 {
2809 return (output_propname_common(prop, values, arg, 25));
2810 }
2811
2812 /*
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.
2816 */
2817 static nwam_error_t
listprop(nwam_object_type_t object_type,void * handle,const char * name,boolean_t all_props,nwam_ncp_handle_t ncp,nwam_ncu_type_t ncu_type)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)
2820 {
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;
2828
2829 /*
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.
2832 */
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) {
2845 /*
2846 * Multiple NCUs with the given name exists.
2847 * Call listprop() for each NCU type.
2848 */
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;
2858 }
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;
2876 }
2877 lhandle = B_TRUE;
2878 }
2879
2880 if ((ret = object_name_from_handle(object_type, handle, &realname))
2881 != NWAM_SUCCESS)
2882 goto done;
2883
2884 /* get the property list */
2885 switch (object_type) {
2886 case NWAM_OBJECT_TYPE_NCP:
2887 {
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;
2893 }
2894 case NWAM_OBJECT_TYPE_NCU:
2895 {
2896 nwam_ncu_type_t ncu_type;
2897 nwam_ncu_class_t ncu_class;
2898
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;
2905
2906 ret = nwam_ncu_get_default_proplist(ncu_type, ncu_class, &props,
2907 &prop_num);
2908 break;
2909 }
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;
2919 }
2920 if (ret != NWAM_SUCCESS)
2921 goto done;
2922
2923 /* print object type and name */
2924 (void) printf("%s:%s\n", nwam_object_type_to_string(object_type),
2925 realname);
2926
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;
2944 }
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;
2951 }
2952
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);
2959 }
2960
2961 done:
2962 free(lname);
2963 free(realname);
2964 if (props != NULL)
2965 free(props);
2966 if (lhandle) {
2967 switch (object_type) {
2968 case NWAM_OBJECT_TYPE_NCP:
2969 nwam_ncp_free(handle);
2970 break;
2971 case NWAM_OBJECT_TYPE_NCU:
2972 nwam_ncu_free(handle);
2973 break;
2974 case NWAM_OBJECT_TYPE_LOC:
2975 nwam_loc_free(handle);
2976 break;
2977 case NWAM_OBJECT_TYPE_ENM:
2978 nwam_enm_free(handle);
2979 break;
2980 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2981 nwam_known_wlan_free(handle);
2982 break;
2983 }
2984 }
2985 /* don't treat _ENTITY_NOT_FOUND as an error */
2986 if (ret == NWAM_ENTITY_NOT_FOUND)
2987 ret = NWAM_SUCCESS;
2988 return (ret);
2989
2990 readfail:
2991 /* When nwam_*_read() fails */
2992 free(lname);
2993 return (ret);
2994 }
2995
2996 /*
2997 * List profiles or property and its values.
2998 * If the -a option is specified, all properties are listed.
2999 */
3000 void
list_func(cmd_t * cmd)3001 list_func(cmd_t *cmd)
3002 {
3003 nwam_error_t ret = NWAM_SUCCESS;
3004 boolean_t list_msg = B_TRUE;
3005
3006 boolean_t list_loc = B_FALSE, list_enm = B_FALSE;
3007 boolean_t list_ncp = B_FALSE, list_ncu = B_FALSE;
3008 boolean_t list_wlan = B_FALSE;
3009
3010 /* whether all properties should be listed, given by the -a option */
3011 boolean_t all_props = B_FALSE;
3012
3013 /*
3014 * list_props says whether the properties should be listed.
3015 * Note that, here NCUs are treated as properties of NCPs.
3016 */
3017 boolean_t list_props = B_FALSE;
3018
3019 /* determine which properties to list, also validity tests */
3020 if (current_scope == NWAM_SCOPE_GBL) {
3021 /* res1_type is -1 if only "list -a" is used */
3022 if (cmd->cmd_res1_type == -1) {
3023 nerr("'list' requires an object to be specified with "
3024 "the -a option in the global scope");
3025 return;
3026 }
3027 if (cmd->cmd_res1_type == RT1_LOC) {
3028 list_props = B_TRUE;
3029 list_loc = B_TRUE;
3030 } else if (cmd->cmd_res1_type == RT1_ENM) {
3031 list_props = B_TRUE;
3032 list_enm = B_TRUE;
3033 } else if (cmd->cmd_res1_type == RT1_WLAN) {
3034 list_props = B_TRUE;
3035 list_wlan = B_TRUE;
3036 } else if (cmd->cmd_res1_type == RT1_NCP) {
3037 list_ncp = B_TRUE;
3038 list_props = B_TRUE;
3039 } else {
3040 list_loc = B_TRUE;
3041 list_enm = B_TRUE;
3042 list_wlan = B_TRUE;
3043 list_ncp = B_TRUE;
3044 }
3045 }
3046 if ((current_scope == NWAM_SCOPE_LOC ||
3047 current_scope == NWAM_SCOPE_ENM ||
3048 current_scope == NWAM_SCOPE_WLAN ||
3049 current_scope == NWAM_SCOPE_NCU) &&
3050 (cmd->cmd_argc >= 1 && cmd->cmd_res1_type != -1)) {
3051 nerr("Additional options are not allowed with the -a option "
3052 "at this scope");
3053 return;
3054 }
3055 if (current_scope == NWAM_SCOPE_LOC) {
3056 list_loc = B_TRUE;
3057 list_props = B_TRUE;
3058 }
3059 if (current_scope == NWAM_SCOPE_ENM) {
3060 list_enm = B_TRUE;
3061 list_props = B_TRUE;
3062 }
3063 if (current_scope == NWAM_SCOPE_WLAN) {
3064 list_wlan = B_TRUE;
3065 list_props = B_TRUE;
3066 }
3067 if (current_scope == NWAM_SCOPE_NCP) {
3068 if (cmd->cmd_res1_type == RT1_ENM ||
3069 cmd->cmd_res1_type == RT1_LOC ||
3070 cmd->cmd_res1_type == RT1_WLAN) {
3071 nerr("only ncu can be listed at this scope");
3072 return;
3073 }
3074 if (cmd->cmd_res2_type == RT2_NCU) {
3075 list_ncu = B_TRUE;
3076 list_props = B_TRUE;
3077 } else {
3078 list_ncp = B_TRUE;
3079 list_props = B_TRUE;
3080 }
3081 }
3082 if (current_scope == NWAM_SCOPE_NCU) {
3083 list_ncu = B_TRUE;
3084 list_props = B_TRUE;
3085 }
3086
3087 /* Check if the -a option is specified to list all properties */
3088 if (cmd->cmd_res1_type == -1 || cmd->cmd_argc == 2) {
3089 int c, argc = 1;
3090 char **argv;
3091 optind = 0;
3092
3093 /* if res1_type is -1, option is in argv[0], else in argv[1] */
3094 if (cmd->cmd_res1_type == -1)
3095 argv = cmd->cmd_argv;
3096 else
3097 argv = &(cmd->cmd_argv[1]);
3098 while ((c = getopt(argc, argv, "a")) != EOF) {
3099 switch (c) {
3100 case 'a':
3101 all_props = B_TRUE;
3102 break;
3103 default:
3104 command_usage(CMD_LIST);
3105 return;
3106 }
3107 }
3108 if (cmd->cmd_res1_type == -1)
3109 cmd->cmd_argv[0] = NULL;
3110 }
3111
3112 /*
3113 * Now, print objects and/or according to the flags set.
3114 * name, if requested, is in argv[0].
3115 */
3116 if (list_ncp) {
3117 list_msg = B_TRUE;
3118 if (list_props) {
3119 ret = listprop(NWAM_OBJECT_TYPE_NCP, ncp_h,
3120 cmd->cmd_argv[0], all_props, NULL, -1);
3121 } else {
3122 ret = nwam_walk_ncps(list_ncp_callback, &list_msg, 0,
3123 NULL);
3124 }
3125 if (ret != NWAM_SUCCESS)
3126 goto done;
3127 }
3128
3129 if (list_ncu) {
3130 list_msg = B_TRUE;
3131 if (ncp_h == NULL) {
3132 nerr("NCP has not been read");
3133 return;
3134 }
3135 if (list_props) {
3136 nwam_ncu_class_t ncu_class;
3137 nwam_ncu_type_t ncu_type;
3138
3139 /* determine the NCU type first */
3140 if (ncu_h == NULL) {
3141 ncu_class = (nwam_ncu_class_t)
3142 cmd->cmd_ncu_class_type;
3143 ncu_type = nwam_ncu_class_to_type(ncu_class);
3144 } else {
3145 if ((ret = nwam_ncu_get_ncu_type(ncu_h,
3146 &ncu_type)) != NWAM_SUCCESS)
3147 goto done;
3148 }
3149 ret = listprop(NWAM_OBJECT_TYPE_NCU, ncu_h,
3150 cmd->cmd_argv[0], all_props, ncp_h, ncu_type);
3151 if (ret != NWAM_SUCCESS)
3152 goto done;
3153 }
3154 }
3155
3156 if (list_loc) {
3157 list_msg = B_TRUE;
3158 if (list_props) {
3159 ret = listprop(NWAM_OBJECT_TYPE_LOC, loc_h,
3160 cmd->cmd_argv[0], all_props, NULL, -1);
3161 } else {
3162 ret = nwam_walk_locs(list_loc_callback, &list_msg,
3163 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3164 }
3165 if (ret != NWAM_SUCCESS)
3166 goto done;
3167 }
3168
3169 if (list_enm) {
3170 list_msg = B_TRUE;
3171 if (list_props) {
3172 ret = listprop(NWAM_OBJECT_TYPE_ENM, enm_h,
3173 cmd->cmd_argv[0], all_props, NULL, -1);
3174 } else {
3175 ret = nwam_walk_enms(list_enm_callback, &list_msg,
3176 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3177 }
3178 if (ret != NWAM_SUCCESS)
3179 goto done;
3180 }
3181
3182 if (list_wlan) {
3183 list_msg = B_TRUE;
3184 if (list_props) {
3185 ret = listprop(NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan_h,
3186 cmd->cmd_argv[0], all_props, NULL, -1);
3187 } else {
3188 ret = nwam_walk_known_wlans(list_wlan_callback,
3189 &list_msg, NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER,
3190 NULL);
3191 }
3192 if (ret != NWAM_SUCCESS)
3193 goto done;
3194 }
3195
3196 done:
3197 if (ret != NWAM_SUCCESS)
3198 nwamerr(ret, "List error");
3199 }
3200
3201 static int
write_export_command(nwam_object_type_t object_type,const char * prop,nwam_value_t values,FILE * of)3202 write_export_command(nwam_object_type_t object_type, const char *prop,
3203 nwam_value_t values, FILE *of)
3204 {
3205 /* exclude read-only properties */
3206 if (is_prop_read_only(object_type, prop))
3207 return (0);
3208
3209 (void) fprintf(of, "set ");
3210 output_propname(prop, values, of);
3211 return (0);
3212 }
3213
3214 static int
export_ncu_callback(nwam_ncu_handle_t ncu,void * arg)3215 export_ncu_callback(nwam_ncu_handle_t ncu, void *arg)
3216 {
3217 char *name;
3218 const char **props;
3219 nwam_ncu_type_t type;
3220 nwam_ncu_class_t class;
3221 nwam_value_t vals;
3222 nwam_error_t ret;
3223 uint_t num;
3224 int i;
3225 FILE *of = arg;
3226
3227 assert(of != NULL);
3228
3229 /* get the NCU's type and class */
3230 if ((ret = nwam_ncu_get_ncu_type(ncu, &type)) != NWAM_SUCCESS)
3231 return (ret);
3232 if ((ret = nwam_ncu_get_ncu_class(ncu, &class)) != NWAM_SUCCESS)
3233 return (ret);
3234
3235 if ((ret = nwam_ncu_get_name(ncu, &name)) != NWAM_SUCCESS)
3236 return (ret);
3237
3238 (void) fprintf(of, "create ncu %s \"%s\"\n",
3239 propval_to_str(NWAM_NCU_PROP_CLASS, class), name);
3240 free(name);
3241 /*
3242 * Because of dependencies between properties, they have to be
3243 * exported in the same order as when they are walked.
3244 */
3245 if ((ret = nwam_ncu_get_default_proplist(type, class, &props, &num))
3246 != NWAM_SUCCESS)
3247 return (ret);
3248 for (i = 0; i < num; i++) {
3249 ret = nwam_ncu_get_prop_value(ncu, props[i], &vals);
3250 if (ret == NWAM_SUCCESS) {
3251 write_export_command(NWAM_OBJECT_TYPE_NCU, props[i],
3252 vals, of);
3253 nwam_value_free(vals);
3254 }
3255 }
3256 (void) fprintf(of, "end\n");
3257
3258 free(props);
3259 return (0);
3260 }
3261
3262 static int
export_ncp_callback(nwam_ncp_handle_t ncp,void * arg)3263 export_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
3264 {
3265 char *name;
3266 nwam_error_t ret;
3267 FILE *of = arg;
3268
3269 assert(of != NULL);
3270
3271 if ((ret = nwam_ncp_get_name(ncp, &name)) != NWAM_SUCCESS)
3272 return (ret);
3273
3274 /* Do not export "automatic" NCP */
3275 if (NWAM_NCP_AUTOMATIC(name)) {
3276 free(name);
3277 return (0);
3278 }
3279
3280 (void) fprintf(of, "create ncp \"%s\"\n", name);
3281 free(name);
3282
3283 /* now walk NCUs for this ncp */
3284 ret = nwam_ncp_walk_ncus(ncp, export_ncu_callback, of,
3285 NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
3286 if (ret != NWAM_SUCCESS) {
3287 nwamerr(ret, "Export ncp error: failed to walk ncus");
3288 return (ret);
3289 }
3290 (void) fprintf(of, "end\n");
3291 return (0);
3292 }
3293
3294 static int
export_enm_callback(nwam_enm_handle_t enm,void * arg)3295 export_enm_callback(nwam_enm_handle_t enm, void *arg)
3296 {
3297 char *name;
3298 const char **props;
3299 nwam_value_t vals;
3300 nwam_error_t ret;
3301 uint_t num;
3302 int i;
3303 FILE *of = arg;
3304
3305 assert(of != NULL);
3306
3307 if ((ret = nwam_enm_get_name(enm, &name)) != NWAM_SUCCESS)
3308 return (ret);
3309
3310 (void) fprintf(of, "create enm \"%s\"\n", name);
3311 free(name);
3312 /*
3313 * Because of dependencies between properties, they have to be
3314 * exported in the same order as when they are walked.
3315 */
3316 if ((ret = nwam_enm_get_default_proplist(&props, &num)) != NWAM_SUCCESS)
3317 return (ret);
3318 for (i = 0; i < num; i++) {
3319 ret = nwam_enm_get_prop_value(enm, props[i], &vals);
3320 if (ret == NWAM_SUCCESS) {
3321 write_export_command(NWAM_OBJECT_TYPE_ENM, props[i],
3322 vals, of);
3323 nwam_value_free(vals);
3324 }
3325 }
3326 (void) fprintf(of, "end\n");
3327
3328 free(props);
3329 return (0);
3330 }
3331
3332 static int
export_loc_callback(nwam_loc_handle_t loc,void * arg)3333 export_loc_callback(nwam_loc_handle_t loc, void *arg)
3334 {
3335 char *name;
3336 const char **props;
3337 nwam_value_t vals;
3338 nwam_error_t ret;
3339 uint_t num;
3340 int i;
3341 FILE *of = arg;
3342
3343 assert(of != NULL);
3344
3345 if ((ret = nwam_loc_get_name(loc, &name)) != NWAM_SUCCESS)
3346 return (ret);
3347
3348 /* Do not export Automatic, NoNet or Legacy locations */
3349 if (NWAM_LOC_NAME_PRE_DEFINED(name)) {
3350 free(name);
3351 return (0);
3352 }
3353
3354 (void) fprintf(of, "create loc \"%s\"\n", name);
3355 free(name);
3356 /*
3357 * Because of dependencies between properties, they have to be
3358 * exported in the same order as when they are walked.
3359 */
3360 if ((ret = nwam_loc_get_default_proplist(&props, &num)) != NWAM_SUCCESS)
3361 return (ret);
3362 for (i = 0; i < num; i++) {
3363 ret = nwam_loc_get_prop_value(loc, props[i], &vals);
3364 if (ret == NWAM_SUCCESS) {
3365 write_export_command(NWAM_OBJECT_TYPE_LOC, props[i],
3366 vals, of);
3367 nwam_value_free(vals);
3368 }
3369 }
3370 (void) fprintf(of, "end\n");
3371
3372 free(props);
3373 return (0);
3374 }
3375
3376 static int
export_wlan_callback(nwam_known_wlan_handle_t wlan,void * arg)3377 export_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
3378 {
3379 char *name;
3380 const char **props;
3381 nwam_value_t vals;
3382 nwam_error_t ret;
3383 uint_t num;
3384 int i;
3385 FILE *of = arg;
3386
3387 assert(of != NULL);
3388
3389 if ((ret = nwam_known_wlan_get_name(wlan, &name)) != NWAM_SUCCESS)
3390 return (ret);
3391
3392 (void) fprintf(of, "create wlan \"%s\"\n", name);
3393 free(name);
3394 /*
3395 * Because of dependencies between properties, they have to be
3396 * exported in the same order as when they are walked.
3397 */
3398 if ((ret = nwam_known_wlan_get_default_proplist(&props, &num))
3399 != NWAM_SUCCESS)
3400 return (ret);
3401 for (i = 0; i < num; i++) {
3402 ret = nwam_known_wlan_get_prop_value(wlan, props[i], &vals);
3403 if (ret == NWAM_SUCCESS) {
3404 write_export_command(NWAM_OBJECT_TYPE_KNOWN_WLAN,
3405 props[i], vals, of);
3406 nwam_value_free(vals);
3407 }
3408 }
3409 (void) fprintf(of, "end\n");
3410
3411 free(props);
3412 return (0);
3413 }
3414
3415 /*
3416 * Writes configuration to screen or file (with -f option).
3417 * Writes a "destroy -a" if option -d is given.
3418 */
3419 void
export_func(cmd_t * cmd)3420 export_func(cmd_t *cmd)
3421 {
3422 int c;
3423 boolean_t need_to_close = B_FALSE, write_to_file = B_FALSE;
3424 boolean_t add_destroy = B_FALSE, lhandle = B_FALSE;
3425 char filepath[MAXPATHLEN];
3426 nwam_error_t ret = NWAM_SUCCESS;
3427 FILE *of = NULL; /* either filename or stdout */
3428
3429 /* what to export */
3430 boolean_t export_ncp = B_FALSE, export_ncu = B_FALSE;
3431 boolean_t export_loc = B_FALSE, export_enm = B_FALSE;
3432 boolean_t export_wlan = B_FALSE;
3433 char *name = NULL;
3434
3435 /* check for -d and -f flags */
3436 filepath[0] = '\0';
3437 optind = 0;
3438 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "df:")) != EOF) {
3439 switch (c) {
3440 case 'f':
3441 write_to_file = B_TRUE;
3442 break;
3443 case 'd':
3444 add_destroy = B_TRUE;
3445 break;
3446 default:
3447 command_usage(CMD_EXPORT);
3448 return;
3449 }
3450 }
3451
3452 /* determine where to export */
3453 if (!write_to_file) {
3454 of = stdout;
3455 } else {
3456 /*
3457 * If -d was specified with -f, then argv[2] is filename,
3458 * otherwise, argv[1] is filename.
3459 */
3460 (void) strlcpy(filepath,
3461 (add_destroy ? cmd->cmd_argv[2] : cmd->cmd_argv[1]),
3462 sizeof (filepath));
3463 if ((of = fopen(filepath, "w")) == NULL) {
3464 nerr(gettext("opening file '%s': %s"), filepath,
3465 strerror(errno));
3466 goto done;
3467 }
3468 setbuf(of, NULL);
3469 need_to_close = B_TRUE;
3470 }
3471
3472 if (add_destroy) {
3473 /* only possible in global scope */
3474 if (current_scope == NWAM_SCOPE_GBL) {
3475 (void) fprintf(of, "destroy -a\n");
3476 } else {
3477 nerr("Option -d is not allowed in non-global scope");
3478 goto done;
3479 }
3480 }
3481
3482 /* In the following scopes, only the -f argument is valid */
3483 if (((current_scope == NWAM_SCOPE_LOC ||
3484 current_scope == NWAM_SCOPE_ENM ||
3485 current_scope == NWAM_SCOPE_WLAN ||
3486 current_scope == NWAM_SCOPE_NCU) &&
3487 cmd->cmd_argc != 0 && !write_to_file)) {
3488 nerr("'export' does not take arguments at this scope");
3489 goto done;
3490 }
3491 if (current_scope == NWAM_SCOPE_NCP) {
3492 if (cmd->cmd_res1_type == RT1_ENM ||
3493 cmd->cmd_res1_type == RT1_LOC ||
3494 cmd->cmd_res1_type == RT1_WLAN) {
3495 nerr("only ncu can be exported at this scope");
3496 goto done;
3497 }
3498 }
3499
3500 /*
3501 * Determine what objects to export depending on scope and command
3502 * arguments. If -f is specified, then the object name is argv[2].
3503 * Otherwise, argv[0] is name, unless exporting all in global
3504 * scope in which case name is set back to NULL.
3505 */
3506 switch (current_scope) {
3507 case NWAM_SCOPE_GBL:
3508 name = (write_to_file ? trim_quotes(cmd->cmd_argv[2]) :
3509 trim_quotes(cmd->cmd_argv[0]));
3510 switch (cmd->cmd_res1_type) {
3511 case RT1_LOC:
3512 export_loc = B_TRUE;
3513 break;
3514 case RT1_ENM:
3515 export_enm = B_TRUE;
3516 break;
3517 case RT1_WLAN:
3518 export_wlan = B_TRUE;
3519 break;
3520 case RT1_NCP:
3521 export_ncp = B_TRUE;
3522 if (cmd->cmd_res2_type == RT2_NCU) {
3523 nerr("cannot export ncu at from global scope");
3524 goto done;
3525 }
3526 break;
3527 default:
3528 /* export everything */
3529 export_loc = B_TRUE;
3530 export_enm = B_TRUE;
3531 export_wlan = B_TRUE;
3532 export_ncp = B_TRUE; /* NCP will export the NCUs */
3533 free(name);
3534 name = NULL; /* exporting all, undo name */
3535 break;
3536 }
3537 break;
3538 case NWAM_SCOPE_LOC:
3539 export_loc = B_TRUE;
3540 ret = nwam_loc_get_name(loc_h, &name);
3541 if (ret != NWAM_SUCCESS)
3542 goto fail;
3543 break;
3544 case NWAM_SCOPE_ENM:
3545 export_enm = B_TRUE;
3546 ret = nwam_enm_get_name(enm_h, &name);
3547 if (ret != NWAM_SUCCESS)
3548 goto fail;
3549 break;
3550 case NWAM_SCOPE_WLAN:
3551 export_wlan = B_TRUE;
3552 ret = nwam_known_wlan_get_name(wlan_h, &name);
3553 if (ret != NWAM_SUCCESS)
3554 goto fail;
3555 break;
3556 case NWAM_SCOPE_NCP:
3557 if (cmd->cmd_res2_type == RT2_NCU) {
3558 export_ncu = B_TRUE;
3559 name = (write_to_file ? trim_quotes(cmd->cmd_argv[2]) :
3560 trim_quotes(cmd->cmd_argv[0]));
3561 } else {
3562 export_ncp = B_TRUE;
3563 ret = nwam_ncp_get_name(ncp_h, &name);
3564 if (ret != NWAM_SUCCESS)
3565 goto fail;
3566 }
3567 break;
3568 case NWAM_SCOPE_NCU:
3569 export_ncu = B_TRUE;
3570 ret = nwam_ncu_get_name(ncu_h, &name);
3571 if (ret != NWAM_SUCCESS)
3572 goto fail;
3573 break;
3574 default:
3575 nerr("Invalid scope");
3576 goto done;
3577 }
3578
3579 /* Now, export objects according to the flags set */
3580 if (export_ncp) {
3581 lhandle = B_FALSE;
3582 if (name == NULL) {
3583 /* export all NCPs */
3584 ret = nwam_walk_ncps(export_ncp_callback, of, 0, NULL);
3585 } else if (NWAM_NCP_AUTOMATIC(name)) {
3586 nerr("'%s' ncp cannot be exported", name);
3587 goto fail;
3588 } else {
3589 if (ncp_h == NULL) {
3590 ret = nwam_ncp_read(name, 0, &ncp_h);
3591 if (ret != NWAM_SUCCESS)
3592 goto fail;
3593 lhandle = B_TRUE;
3594 }
3595 /* will export NCUs also */
3596 ret = export_ncp_callback(ncp_h, of);
3597 if (lhandle) {
3598 nwam_ncp_free(ncp_h);
3599 ncp_h = NULL;
3600 }
3601 }
3602 if (ret != NWAM_SUCCESS)
3603 goto fail;
3604 }
3605
3606 if (export_ncu) {
3607 if (name == NULL) {
3608 /* export all NCUs */
3609 ret = nwam_ncp_walk_ncus(ncp_h, export_ncu_callback, of,
3610 NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
3611 } else {
3612 if (ncu_h == NULL) {
3613 /* no NCU handle -> called from NCP scope */
3614 nwam_ncu_type_t ncu_type;
3615 nwam_ncu_class_t ncu_class;
3616
3617 ncu_class = (nwam_ncu_class_t)
3618 cmd->cmd_ncu_class_type;
3619 ncu_type = nwam_ncu_class_to_type(ncu_class);
3620 ret = nwam_ncu_read(ncp_h, name,
3621 ncu_type, 0, &ncu_h);
3622 if (ret == NWAM_SUCCESS) {
3623 /* one NCU with given name */
3624 ret = export_ncu_callback(ncu_h, of);
3625 nwam_ncu_free(ncu_h);
3626 ncu_h = NULL;
3627 } else if (ret == NWAM_ENTITY_MULTIPLE_VALUES) {
3628 /* multiple NCUs with given name */
3629 ret = nwam_ncu_read(ncp_h, name,
3630 NWAM_NCU_TYPE_LINK, 0, &ncu_h);
3631 if (ret != NWAM_SUCCESS)
3632 goto fail;
3633 ret = export_ncu_callback(ncu_h, of);
3634 nwam_ncu_free(ncu_h);
3635 ncu_h = NULL;
3636
3637 ret = nwam_ncu_read(ncp_h, name,
3638 NWAM_NCU_TYPE_INTERFACE, 0, &ncu_h);
3639 if (ret != NWAM_SUCCESS)
3640 goto fail;
3641 ret = export_ncu_callback(ncu_h, of);
3642 nwam_ncu_free(ncu_h);
3643 ncu_h = NULL;
3644 } else {
3645 goto fail;
3646 }
3647 } else {
3648 /* NCU handle exists */
3649 ret = export_ncu_callback(ncu_h, of);
3650 }
3651 }
3652 if (ret != NWAM_SUCCESS)
3653 goto fail;
3654 }
3655
3656 if (export_loc) {
3657 lhandle = B_FALSE;
3658 if (name == NULL) {
3659 /* export all locations */
3660 ret = nwam_walk_locs(export_loc_callback, of,
3661 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3662 } else if (NWAM_LOC_NAME_PRE_DEFINED(name)) {
3663 nerr("'%s' loc cannot be exported", name);
3664 goto fail;
3665 } else {
3666 if (loc_h == NULL) {
3667 ret = nwam_loc_read(name, 0, &loc_h);
3668 if (ret != NWAM_SUCCESS)
3669 goto fail;
3670 lhandle = B_TRUE;
3671 }
3672 ret = export_loc_callback(loc_h, of);
3673 if (lhandle) {
3674 nwam_loc_free(loc_h);
3675 loc_h = NULL;
3676 }
3677 }
3678 if (ret != NWAM_SUCCESS)
3679 goto fail;
3680 }
3681
3682 if (export_enm) {
3683 lhandle = B_FALSE;
3684 if (name == NULL) {
3685 /* export all ENMs */
3686 ret = nwam_walk_enms(export_enm_callback, of,
3687 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3688 } else {
3689 if (enm_h == NULL) {
3690 ret = nwam_enm_read(name, 0, &enm_h);
3691 if (ret != NWAM_SUCCESS)
3692 goto fail;
3693 lhandle = B_TRUE;
3694 }
3695 ret = export_enm_callback(enm_h, of);
3696 if (lhandle) {
3697 nwam_enm_free(enm_h);
3698 enm_h = NULL;
3699 }
3700 }
3701 if (ret != NWAM_SUCCESS)
3702 goto fail;
3703 }
3704
3705 if (export_wlan) {
3706 lhandle = B_FALSE;
3707 if (name == NULL) {
3708 /* export all WLANs */
3709 ret = nwam_walk_known_wlans(export_wlan_callback, of,
3710 NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER, NULL);
3711 } else {
3712 if (wlan_h == NULL) {
3713 ret = nwam_known_wlan_read(name, 0,
3714 &wlan_h);
3715 if (ret != NWAM_SUCCESS)
3716 goto fail;
3717 lhandle = B_TRUE;
3718 }
3719 ret = export_wlan_callback(wlan_h, of);
3720 if (lhandle) {
3721 nwam_known_wlan_free(wlan_h);
3722 wlan_h = NULL;
3723 }
3724 }
3725 if (ret != NWAM_SUCCESS)
3726 goto fail;
3727 }
3728
3729 fail:
3730 free(name);
3731 if (ret != NWAM_SUCCESS)
3732 nwamerr(ret, "Export error");
3733
3734 done:
3735 if (need_to_close)
3736 (void) fclose(of);
3737 }
3738
3739 /*
3740 * Get property value. If the -V option is specified, only the value is
3741 * printed without the property name.
3742 */
3743 void
get_func(cmd_t * cmd)3744 get_func(cmd_t *cmd)
3745 {
3746 nwam_error_t ret = NWAM_SUCCESS;
3747 nwam_value_t prop_value;
3748 const char *prop;
3749 boolean_t value_only = B_FALSE;
3750 nwam_object_type_t object_type = active_object_type();
3751
3752 /* check if option is -V to print value only */
3753 if (cmd->cmd_argc == 1) {
3754 int c;
3755
3756 optind = 0;
3757 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "V")) != EOF) {
3758 switch (c) {
3759 case 'V':
3760 value_only = B_TRUE;
3761 break;
3762 default:
3763 command_usage(CMD_GET);
3764 return;
3765 }
3766 }
3767 }
3768
3769 /* property to get is in cmd->cmd_prop_type */
3770 if ((prop = pt_to_prop_name(object_type, cmd->cmd_prop_type)) == NULL) {
3771 nerr("Get error: invalid %s property: '%s'",
3772 scope_to_str(current_scope), pt_to_str(cmd->cmd_prop_type));
3773 return;
3774 }
3775
3776 switch (object_type) {
3777 case NWAM_OBJECT_TYPE_NCU:
3778 ret = nwam_ncu_get_prop_value(ncu_h, prop, &prop_value);
3779 break;
3780 case NWAM_OBJECT_TYPE_LOC:
3781 ret = nwam_loc_get_prop_value(loc_h, prop, &prop_value);
3782 break;
3783 case NWAM_OBJECT_TYPE_ENM:
3784 ret = nwam_enm_get_prop_value(enm_h, prop, &prop_value);
3785 break;
3786 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
3787 ret = nwam_known_wlan_get_prop_value(wlan_h, prop, &prop_value);
3788 break;
3789 }
3790
3791 if (ret != NWAM_SUCCESS) {
3792 if (ret == NWAM_ENTITY_NOT_FOUND)
3793 nerr("Get error: property '%s' has not been set", prop);
3794 else
3795 nwamerr(ret, "Get error");
3796 return;
3797 }
3798
3799 if (value_only) {
3800 output_prop_val(prop, prop_value, stdout, B_FALSE);
3801 (void) printf("\n");
3802 } else {
3803 output_propname(prop, prop_value, NULL);
3804 }
3805 nwam_value_free(prop_value);
3806 }
3807
3808 /*
3809 * Clears value of a property.
3810 * Read-only properties cannot be cleared.
3811 * If clearing a property invalidates the object, then that property
3812 * cannot be cleared.
3813 */
3814 void
clear_func(cmd_t * cmd)3815 clear_func(cmd_t *cmd)
3816 {
3817 nwam_error_t ret;
3818 const char *prop;
3819 nwam_object_type_t object_type = active_object_type();
3820
3821 /* property to clear is in cmd->cmd_prop_type */
3822 if ((prop = pt_to_prop_name(object_type, cmd->cmd_prop_type)) == NULL) {
3823 nerr("Clear error: invalid %s property: '%s'",
3824 scope_to_str(current_scope), pt_to_str(cmd->cmd_prop_type));
3825 return;
3826 }
3827 if (is_prop_read_only(object_type, prop)) {
3828 nerr("Clear error: property '%s' is read-only", prop);
3829 return;
3830 }
3831
3832 switch (object_type) {
3833 case NWAM_OBJECT_TYPE_NCU:
3834 ret = nwam_ncu_delete_prop(ncu_h, prop);
3835 break;
3836 case NWAM_OBJECT_TYPE_LOC:
3837 ret = nwam_loc_delete_prop(loc_h, prop);
3838 break;
3839 case NWAM_OBJECT_TYPE_ENM:
3840 ret = nwam_enm_delete_prop(enm_h, prop);
3841 break;
3842 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
3843 ret = nwam_known_wlan_delete_prop(wlan_h, prop);
3844 break;
3845 }
3846
3847 if (ret != NWAM_SUCCESS) {
3848 if (ret == NWAM_INVALID_ARG || ret == NWAM_ENTITY_NOT_FOUND) {
3849 nerr("Clear error: property '%s' has not been set",
3850 prop);
3851 } else {
3852 nwamerr(ret, "Clear error");
3853 }
3854 return;
3855 }
3856
3857 need_to_commit = B_TRUE;
3858 }
3859
3860 /*
3861 * Prints all the choices available for an enum property [c1|c2|c3].
3862 * Prints [true|false] for a boolean property.
3863 */
3864 static void
print_all_prop_choices(nwam_object_type_t object_type,const char * prop)3865 print_all_prop_choices(nwam_object_type_t object_type, const char *prop)
3866 {
3867 uint64_t i = 0;
3868 const char *str;
3869 boolean_t choices = B_FALSE;
3870 nwam_value_type_t value_type;
3871 nwam_error_t ret;
3872
3873 /* Special case: print object-specific options for activation-mode */
3874 if (strcmp(prop, NWAM_NCU_PROP_ACTIVATION_MODE) == 0) {
3875 /* "manual" for all objects */
3876 (void) printf(" [%s|",
3877 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3878 NWAM_ACTIVATION_MODE_MANUAL));
3879 if (object_type == NWAM_OBJECT_TYPE_NCU) {
3880 (void) printf("%s]",
3881 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3882 NWAM_ACTIVATION_MODE_PRIORITIZED));
3883 } else {
3884 (void) printf("%s|%s]",
3885 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3886 NWAM_ACTIVATION_MODE_CONDITIONAL_ANY),
3887 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3888 NWAM_ACTIVATION_MODE_CONDITIONAL_ALL));
3889 }
3890 return;
3891 }
3892
3893 /* Special case: only "manual" configsrc is allowed for LDAP */
3894 if (strcmp(prop, NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC) == 0) {
3895 (void) printf(" [%s]",
3896 propval_to_str(NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
3897 NWAM_CONFIGSRC_MANUAL));
3898 return;
3899 }
3900
3901 value_type = prop_value_type(object_type, prop);
3902 switch (value_type) {
3903 case NWAM_VALUE_TYPE_UINT64:
3904 /* uint64 may be an enum, will print nothing if not an enum */
3905 while ((ret = nwam_uint64_get_value_string(prop, i++, &str))
3906 == NWAM_SUCCESS || ret == NWAM_ENTITY_INVALID_VALUE) {
3907 /* No string representation for i, continue. */
3908 if (ret == NWAM_ENTITY_INVALID_VALUE)
3909 continue;
3910
3911 if (!choices)
3912 (void) printf("%s", " [");
3913 (void) printf("%s%s", choices ? "|" : "", str);
3914 choices = B_TRUE;
3915 }
3916 if (choices)
3917 (void) putchar(']');
3918 break;
3919 case NWAM_VALUE_TYPE_BOOLEAN:
3920 (void) printf(" [%s|%s]", "true", "false");
3921 break;
3922 case NWAM_VALUE_TYPE_STRING:
3923 break;
3924 }
3925 }
3926
3927 /*
3928 * Walk through object properties.
3929 * For newly-created object, the property name with no value is displayed, and
3930 * the user can input a value for each property.
3931 * For existing object, the current value is displayed and user input overwrites
3932 * the existing one. If no input is given, the existing value remains.
3933 * Read-only properties are not displayed.
3934 * Read-only objects cannot be walked.
3935 * If the -a option is specified, no properties are skipped.
3936 */
3937 void
walkprop_func(cmd_t * cmd)3938 walkprop_func(cmd_t *cmd)
3939 {
3940 nwam_error_t ret = NWAM_SUCCESS;
3941 nwam_value_t vals = NULL; /* freed in _wait_input() */
3942 int i;
3943 uint_t prop_num;
3944 const char **props;
3945 boolean_t read_only = B_FALSE, all_props = B_FALSE;
3946
3947 nwam_object_type_t object_type;
3948 prop_display_entry_t *prop_table;
3949
3950 if (!interactive_mode) {
3951 nerr("'walkprop' is only allowed in interactive mode");
3952 return;
3953 }
3954
3955 /* check if option -a is specified to show all properties */
3956 if (cmd->cmd_argc == 1) {
3957 int c;
3958 optind = 0;
3959 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "a")) != EOF) {
3960 switch (c) {
3961 case 'a':
3962 all_props = B_TRUE;
3963 break;
3964 default:
3965 command_usage(CMD_WALKPROP);
3966 return;
3967 }
3968 }
3969 }
3970
3971 /* read-only objects cannot be walked */
3972 if (obj1_type == RT1_NCP) {
3973 /* must be in NCU scope, NCP scope doesn't get here */
3974 (void) nwam_ncu_get_read_only(ncu_h, &read_only);
3975 }
3976 if (read_only) {
3977 nerr("'walkprop' cannot be used in read-only objects");
3978 return;
3979 }
3980
3981 /* get the current object type and the prop_display_table */
3982 object_type = active_object_type();
3983 prop_table = get_prop_display_table(object_type);
3984
3985 /* get the property list depending on the object type */
3986 switch (object_type) {
3987 case NWAM_OBJECT_TYPE_NCU:
3988 {
3989 nwam_ncu_type_t ncu_type;
3990 nwam_ncu_class_t ncu_class;
3991
3992 if ((ret = nwam_ncu_get_ncu_type(ncu_h, &ncu_type))
3993 != NWAM_SUCCESS)
3994 break;
3995 if ((ret = nwam_ncu_get_ncu_class(ncu_h, &ncu_class))
3996 != NWAM_SUCCESS)
3997 break;
3998
3999 ret = nwam_ncu_get_default_proplist(ncu_type, ncu_class, &props,
4000 &prop_num);
4001 break;
4002 }
4003 case NWAM_OBJECT_TYPE_LOC:
4004 ret = nwam_loc_get_default_proplist(&props, &prop_num);
4005 break;
4006 case NWAM_OBJECT_TYPE_ENM:
4007 ret = nwam_enm_get_default_proplist(&props, &prop_num);
4008 break;
4009 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4010 ret = nwam_known_wlan_get_default_proplist(&props, &prop_num);
4011 break;
4012 }
4013 if (ret != NWAM_SUCCESS) {
4014 nwamerr(ret, "Walkprop error: could not get property list");
4015 return;
4016 }
4017
4018 /* Loop through the properties */
4019 if (all_props)
4020 (void) printf(gettext("Walking all properties ...\n"));
4021 for (i = 0; i < prop_num; i++) {
4022 char line[NWAM_MAX_VALUE_LEN];
4023 char **checked = NULL;
4024
4025 /* check if this property should be displayed */
4026 if (is_prop_read_only(object_type, props[i]))
4027 continue;
4028 if (!all_props &&
4029 !show_prop_test(object_type, props[i], prop_table,
4030 checked, 0))
4031 continue;
4032
4033 /* get the existing value for this property */
4034 switch (object_type) {
4035 case NWAM_OBJECT_TYPE_NCU:
4036 ret = nwam_ncu_get_prop_value(ncu_h, props[i], &vals);
4037 break;
4038 case NWAM_OBJECT_TYPE_LOC:
4039 ret = nwam_loc_get_prop_value(loc_h, props[i], &vals);
4040 break;
4041 case NWAM_OBJECT_TYPE_ENM:
4042 ret = nwam_enm_get_prop_value(enm_h, props[i], &vals);
4043 break;
4044 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4045 ret = nwam_known_wlan_get_prop_value(wlan_h, props[i],
4046 &vals);
4047 break;
4048 }
4049 /* returns NWAM_ENTITY_NOT_FOUND if no existing value */
4050 if (ret != NWAM_SUCCESS && ret != NWAM_ENTITY_NOT_FOUND)
4051 continue;
4052
4053 /* print property */
4054 (void) printf("%s", props[i]);
4055 /* print the existing value(s) if they exist */
4056 if (ret == NWAM_SUCCESS) {
4057 (void) printf(" (");
4058 output_prop_val(props[i], vals, stdout, B_TRUE);
4059 (void) putchar(')');
4060 nwam_value_free(vals);
4061 }
4062 /* print choices, won't print anything if there aren't any */
4063 print_all_prop_choices(object_type, props[i]);
4064 (void) printf("> ");
4065
4066 /* wait for user input */
4067 if (fgets(line, sizeof (line), stdin) == NULL)
4068 continue;
4069
4070 /* if user input new value, existing value is overrode */
4071 if (line[0] != '\n') {
4072 boolean_t is_listprop;
4073 int pt_type = prop_to_pt(object_type, props[i]);
4074
4075 is_listprop = is_prop_multivalued(object_type,
4076 props[i]);
4077 vals = str_to_nwam_value(object_type, line, pt_type,
4078 is_listprop);
4079 if (vals == NULL) {
4080 ret = NWAM_ENTITY_INVALID_VALUE;
4081 goto repeat;
4082 }
4083
4084 /* set the new value for the property */
4085 switch (object_type) {
4086 case NWAM_OBJECT_TYPE_NCU:
4087 ret = nwam_ncu_set_prop_value(ncu_h, props[i],
4088 vals);
4089 break;
4090 case NWAM_OBJECT_TYPE_LOC:
4091 ret = nwam_loc_set_prop_value(loc_h, props[i],
4092 vals);
4093 break;
4094 case NWAM_OBJECT_TYPE_ENM:
4095 ret = nwam_enm_set_prop_value(enm_h, props[i],
4096 vals);
4097 break;
4098 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4099 ret = nwam_known_wlan_set_prop_value(wlan_h,
4100 props[i], vals);
4101 break;
4102 }
4103 nwam_value_free(vals);
4104
4105 if (ret != NWAM_SUCCESS)
4106 goto repeat;
4107
4108 need_to_commit = B_TRUE;
4109 continue;
4110
4111 repeat:
4112 invalid_set_prop_msg(props[i], ret);
4113 i--; /* decrement i to repeat */
4114 }
4115 }
4116
4117 free(props);
4118 }
4119
4120 /*
4121 * Verify whether all properties of a resource are valid.
4122 */
4123 /* ARGSUSED */
4124 void
verify_func(cmd_t * cmd)4125 verify_func(cmd_t *cmd)
4126 {
4127 nwam_error_t ret;
4128 const char *errprop;
4129
4130 switch (active_object_type()) {
4131 case NWAM_OBJECT_TYPE_NCU:
4132 ret = nwam_ncu_validate(ncu_h, &errprop);
4133 break;
4134 case NWAM_OBJECT_TYPE_LOC:
4135 ret = nwam_loc_validate(loc_h, &errprop);
4136 break;
4137 case NWAM_OBJECT_TYPE_ENM:
4138 ret = nwam_enm_validate(enm_h, &errprop);
4139 break;
4140 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4141 ret = nwam_known_wlan_validate(wlan_h, &errprop);
4142 break;
4143 }
4144 if (ret != NWAM_SUCCESS)
4145 nwamerr(ret, "Verify error on property '%s'", errprop);
4146 else if (interactive_mode)
4147 (void) printf(gettext("All properties verified\n"));
4148 }
4149
4150 /*
4151 * command-line mode (# nwamcfg list or # nwamcfg "select loc test; list")
4152 */
4153 static int
one_command_at_a_time(int argc,char * argv[])4154 one_command_at_a_time(int argc, char *argv[])
4155 {
4156 char *command;
4157 size_t len = 2; /* terminal \n\0 */
4158 int i, err;
4159
4160 for (i = 0; i < argc; i++)
4161 len += strlen(argv[i]) + 1;
4162 if ((command = malloc(len)) == NULL) {
4163 nerr("Out of memory");
4164 return (NWAM_ERR);
4165 }
4166 (void) strlcpy(command, argv[0], len);
4167 for (i = 1; i < argc; i++) {
4168 (void) strlcat(command, " ", len);
4169 (void) strlcat(command, argv[i], len);
4170 }
4171 (void) strlcat(command, "\n", len);
4172 err = string_to_yyin(command);
4173 free(command);
4174 if (err != NWAM_OK)
4175 return (err);
4176 while (!feof(yyin)) {
4177 yyparse();
4178
4179 /*
4180 * If any command on a list of commands give an error,
4181 * don't continue with the remaining commands.
4182 */
4183 if (saw_error || time_to_exit)
4184 return (cleanup());
4185 }
4186
4187 /* if there are changes to commit, commit it */
4188 if (need_to_commit) {
4189 do_commit();
4190 /* if need_to_commit is not set, then there was a error */
4191 if (need_to_commit)
4192 return (NWAM_ERR);
4193 }
4194
4195 if (!interactive_mode)
4196 return (cleanup());
4197 else {
4198 yyin = stdin;
4199 return (read_input());
4200 }
4201 }
4202
4203 /*
4204 * cmd_file is slightly more complicated, as it has to open the command file
4205 * and set yyin appropriately. Once that is done, though, it just calls
4206 * read_input(), and only once, since prompting is not possible.
4207 */
4208 static int
cmd_file(char * file)4209 cmd_file(char *file)
4210 {
4211 FILE *infile;
4212 int err;
4213 struct stat statbuf;
4214 boolean_t using_real_file = (strcmp(file, "-") != 0);
4215
4216 if (using_real_file) {
4217 /*
4218 * nerr() prints a line number in cmd_file_mode, which we do
4219 * not want here, so temporarily unset it.
4220 */
4221 cmd_file_mode = B_FALSE;
4222 if ((infile = fopen(file, "r")) == NULL) {
4223 nerr(gettext("could not open file '%s': %s"),
4224 file, strerror(errno));
4225 return (1);
4226 }
4227 if ((err = fstat(fileno(infile), &statbuf)) != 0) {
4228 nerr(gettext("could not stat file '%s': %s"),
4229 file, strerror(errno));
4230 err = 1;
4231 goto done;
4232 }
4233 if (!S_ISREG(statbuf.st_mode)) {
4234 nerr(gettext("'%s' is not a regular file."), file);
4235 err = 1;
4236 goto done;
4237 }
4238
4239 /*
4240 * If -d was passed on the command-line, we need to
4241 * start by removing any existing configuration.
4242 * Alternatively, the file may begin with 'destroy -a';
4243 * but in that case, the line will go through the lexer
4244 * and be processed as it's encountered in the file.
4245 */
4246 if (remove_all_configurations && destroy_all() != NWAM_SUCCESS)
4247 goto done;
4248
4249 /* set up for lexer */
4250 yyin = infile;
4251 cmd_file_mode = B_TRUE;
4252 ok_to_prompt = B_FALSE;
4253 } else {
4254 /*
4255 * "-f -" is essentially the same as interactive mode,
4256 * so treat it that way.
4257 */
4258 interactive_mode = B_TRUE;
4259 }
4260 /* NWAM_REPEAT is for interactive mode; treat it like NWAM_ERR here. */
4261 if ((err = read_input()) == NWAM_REPEAT)
4262 err = NWAM_ERR;
4263 if (err == NWAM_OK)
4264 (void) printf(gettext("Configuration read.\n"));
4265
4266 done:
4267 if (using_real_file)
4268 (void) fclose(infile);
4269 return (err);
4270 }
4271
4272 int
main(int argc,char * argv[])4273 main(int argc, char *argv[])
4274 {
4275 int err;
4276 char c;
4277
4278 /* This must be before anything goes to stdout. */
4279 setbuf(stdout, NULL);
4280
4281 if ((execname = strrchr(argv[0], '/')) == NULL)
4282 execname = argv[0];
4283 else
4284 execname++;
4285
4286 (void) setlocale(LC_ALL, "");
4287 (void) textdomain(TEXT_DOMAIN);
4288
4289 while ((c = getopt(argc, argv, "?hf:d")) != EOF) {
4290 switch (c) {
4291 case 'f':
4292 cmd_file_name = optarg;
4293 cmd_file_mode = B_TRUE;
4294 break;
4295 case '?':
4296 case 'h':
4297 cmd_line_usage();
4298 return (NWAM_OK);
4299 case 'd':
4300 remove_all_configurations = B_TRUE;
4301 break;
4302 default:
4303 cmd_line_usage();
4304 return (NWAM_ERR);
4305 }
4306 }
4307 /* -d can only be used with -f */
4308 if (remove_all_configurations && !cmd_file_mode) {
4309 nerr("Option -d can only be used with -f");
4310 return (NWAM_ERR);
4311 }
4312
4313 /*
4314 * This may get set back to FALSE again in cmd_file() if cmd_file_name
4315 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
4316 */
4317 if (isatty(STDIN_FILENO))
4318 ok_to_prompt = B_TRUE;
4319 if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
4320 exit(NWAM_ERR);
4321 if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
4322 exit(NWAM_ERR);
4323 (void) sigset(SIGINT, SIG_IGN);
4324
4325 if (optind == argc) {
4326 /* interactive or command-file mode */
4327 if (!cmd_file_mode)
4328 err = do_interactive();
4329 else
4330 err = cmd_file(cmd_file_name);
4331 } else {
4332 /* command-line mode */
4333 err = one_command_at_a_time(argc - optind, &(argv[optind]));
4334 }
4335 (void) del_GetLine(gl);
4336
4337 return (err);
4338 }
4339