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