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