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