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