1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * nwamadm is a command interpreter to administer NWAM profiles. It 28 * is all in C (i.e., no lex/yacc), and all the argument passing is 29 * argc/argv based. main() calls the command's handler function, 30 * which first calls parse_argv() to parse the input arguments and set 31 * approriate variables for each command. The rest of the program is 32 * helper functions for the handler functions. 33 */ 34 35 #include <arpa/inet.h> 36 #include <assert.h> 37 #include <errno.h> 38 #include <libdlwlan.h> 39 #include <libnwam.h> 40 #include <libscf.h> 41 #include <locale.h> 42 #include <netinet/in.h> 43 #include <ofmt.h> 44 #include <stdarg.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <strings.h> 49 #include <sys/socket.h> 50 #include <sys/types.h> 51 #include <unistd.h> 52 53 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ 54 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 55 #endif 56 57 typedef void (cmd_func_t)(int, char **); 58 59 struct cmd { 60 uint_t cmd_num; /* command number */ 61 const char *cmd_name; /* command name */ 62 cmd_func_t *cmd_handler; /* function to call */ 63 const char *cmd_usage; /* short form help */ 64 const char *cmd_desc; /* command description */ 65 boolean_t cmd_needs_nwamd; /* nwam needs to run */ 66 }; 67 68 /* constants for commands */ 69 #define CMD_HELP 0 70 #define CMD_ENABLE 1 71 #define CMD_DISABLE 2 72 #define CMD_LIST 3 73 #define CMD_SHOW_EVENTS 4 74 #define CMD_SCAN_WIFI 5 75 #define CMD_SELECT_WIFI 6 76 77 #define CMD_MIN CMD_HELP 78 #define CMD_MAX CMD_SELECT_WIFI 79 80 /* functions to call */ 81 static cmd_func_t help_func, enable_func, disable_func, list_func; 82 static cmd_func_t show_events_func, scan_wifi_func, select_wifi_func; 83 static ofmt_cb_t print_list_cb; 84 85 /* table of commands and usage */ 86 static struct cmd cmdtab[] = { 87 { CMD_HELP, "help", help_func, 88 "help", 89 "Print this usage message.", B_FALSE }, 90 { CMD_ENABLE, "enable", enable_func, 91 "enable [-p <profile-type>] [-c <ncu-class>] <object-name>", 92 "Enable the specified profile.", B_FALSE }, 93 { CMD_DISABLE, "disable", disable_func, 94 "disable [-p <profile-type>] [-c <ncu-class>] <object-name>", 95 "Disable the specified profile.", B_FALSE }, 96 { CMD_LIST, "list", list_func, 97 "list [-x] [-p <profile-type>] [-c <ncu-class>] [<object-name>]", 98 "List profiles and their current states.", B_TRUE }, 99 { CMD_SHOW_EVENTS, "show-events", show_events_func, 100 "show-events", 101 "Display all events.", B_TRUE }, 102 { CMD_SCAN_WIFI, "scan-wifi", scan_wifi_func, 103 "scan-wifi <link-name>", 104 "Request a WiFi scan for the selected link.", B_TRUE }, 105 { CMD_SELECT_WIFI, "select-wifi", select_wifi_func, 106 "select-wifi <link-name>", 107 "Make a WLAN selection from the last WiFi scan.", B_TRUE } 108 }; 109 110 /* Structure for "nwamadm list" output */ 111 112 typedef struct profile_entry { 113 nwam_object_type_t p_type; 114 nwam_ncu_class_t p_ncu_class; 115 char p_name[NWAM_MAX_NAME_LEN]; 116 nwam_state_t p_state; 117 nwam_aux_state_t p_aux_state; 118 } profile_entry_t; 119 120 /* widths of colums for printing */ 121 #define TYPE_WIDTH 12 /* width of TYPE column */ 122 #define PROFILE_WIDTH 15 /* width of PROFILE column */ 123 #define STATE_WIDTH 15 /* width of STATE column */ 124 #define AUXSTATE_WIDTH 36 /* width of AUXILIARY STATE column */ 125 126 #define EVENT_WIDTH 22 /* width of EVENT column */ 127 #define DESCRIPTION_WIDTH 56 /* width of DESCRIPTION column */ 128 129 /* id for columns of "nwamadm list" */ 130 typedef enum { 131 LIST_TYPE, 132 LIST_PROFILE, 133 LIST_STATE, 134 LIST_AUXSTATE 135 } list_field_id_t; 136 137 static const ofmt_field_t list_fields[] = { 138 /* header, width, id, callback */ 139 { "TYPE", TYPE_WIDTH, LIST_TYPE, print_list_cb }, 140 { "PROFILE", PROFILE_WIDTH, LIST_PROFILE, print_list_cb }, 141 { "STATE", STATE_WIDTH, LIST_STATE, print_list_cb }, 142 { "AUXILIARY STATE", AUXSTATE_WIDTH, LIST_AUXSTATE, print_list_cb }, 143 { NULL, 0, 0, NULL } 144 }; 145 146 /* Global variables */ 147 148 /* set early in main(), never modified thereafter, used all over the place */ 149 static char *execname; 150 151 /* whether the auxilary states are to be printed or not */ 152 static boolean_t extended_list = B_FALSE; 153 154 /* Functions */ 155 156 static const char * 157 cmd_to_str(int cmd_num) 158 { 159 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 160 return (cmdtab[cmd_num].cmd_name); 161 } 162 163 /* returns description of given command */ 164 static const char * 165 long_help(int cmd_num) 166 { 167 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 168 return (gettext(cmdtab[cmd_num].cmd_desc)); 169 } 170 171 /* 172 * Called with explicit B_TRUE when help is explicitly required, 173 * B_FALSE for errors 174 */ 175 static void 176 usage(boolean_t explicit) 177 { 178 int i; 179 FILE *fd = explicit ? stdout : stderr; 180 181 (void) fprintf(fd, gettext("usage: <subcommand> <args> ...\n")); 182 for (i = CMD_MIN; i <= CMD_MAX; i++) { 183 (void) fprintf(fd, "\t%s\n", cmdtab[i].cmd_usage); 184 if (explicit) 185 (void) fprintf(fd, "\t\t%s\n\n", long_help(i)); 186 } 187 } 188 189 /* PRINTFLIKE1 */ 190 static void 191 die(const char *format, ...) 192 { 193 va_list alist; 194 195 format = gettext(format); 196 (void) fprintf(stderr, "%s: ", execname); 197 198 va_start(alist, format); 199 (void) vfprintf(stderr, format, alist); 200 va_end(alist); 201 (void) fprintf(stderr, "\n"); 202 203 exit(EXIT_FAILURE); 204 } 205 206 /* PRINTFLIKE2 */ 207 static void 208 die_nwamerr(nwam_error_t err, const char *format, ...) 209 { 210 va_list alist; 211 212 format = gettext(format); 213 (void) fprintf(stderr, "%s: ", execname); 214 215 va_start(alist, format); 216 (void) vfprintf(stderr, format, alist); 217 va_end(alist); 218 (void) fprintf(stderr, ": %s\n", nwam_strerror(err)); 219 220 exit(EXIT_FAILURE); 221 } 222 223 /* prints the usage for cmd_num and exits */ 224 static void 225 die_usage(int cmd_num) 226 { 227 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 228 229 (void) fprintf(stderr, "%s: %s\n", gettext("usage"), 230 cmdtab[cmd_num].cmd_usage); 231 (void) fprintf(stderr, "\t%s\n", long_help(cmd_num)); 232 233 exit(EXIT_FAILURE); 234 } 235 236 /* 237 * Prints the usage and description of all commands 238 */ 239 /* ARGSUSED */ 240 static void 241 help_func(int argc, char *argv[]) 242 { 243 usage(B_TRUE); 244 } 245 246 /* determines if the NCP is active or not. If so, sets arg and halts walk. */ 247 static int 248 active_ncp_callback(nwam_ncp_handle_t ncph, void *arg) 249 { 250 char **namep = arg; 251 nwam_state_t state = NWAM_STATE_UNINITIALIZED; 252 nwam_aux_state_t aux; 253 254 (void) nwam_ncp_get_state(ncph, &state, &aux); 255 if (state == NWAM_STATE_ONLINE) { 256 if (nwam_ncp_get_name(ncph, namep) != NWAM_SUCCESS) 257 *namep = NULL; 258 return (1); 259 } 260 261 return (0); 262 } 263 264 /* find the currently active NCP and returns its handle */ 265 static nwam_ncp_handle_t 266 determine_active_ncp() 267 { 268 char *active_ncp; 269 nwam_ncp_handle_t ncph; 270 nwam_error_t ret; 271 272 if (nwam_walk_ncps(active_ncp_callback, &active_ncp, 0, NULL) 273 == NWAM_WALK_HALTED) { 274 if (active_ncp == NULL) 275 return (NULL); 276 277 /* retrieve the NCP handle */ 278 ret = nwam_ncp_read(active_ncp, 0, &ncph); 279 free(active_ncp); 280 if (ret == NWAM_SUCCESS) 281 return (ncph); 282 } 283 284 return (NULL); 285 } 286 287 /* check if the given name is a valid loc, test by reading the given loc */ 288 static boolean_t 289 valid_loc(const char *name) 290 { 291 nwam_loc_handle_t loch; 292 293 if (nwam_loc_read(name, 0, &loch) != NWAM_SUCCESS) 294 return (B_FALSE); 295 nwam_loc_free(loch); 296 return (B_TRUE); 297 } 298 299 static boolean_t 300 valid_enm(const char *name) 301 { 302 nwam_enm_handle_t enmh; 303 304 if (nwam_enm_read(name, 0, &enmh) != NWAM_SUCCESS) 305 return (B_FALSE); 306 nwam_enm_free(enmh); 307 return (B_TRUE); 308 } 309 310 static boolean_t 311 valid_ncp(const char *name) 312 { 313 nwam_ncp_handle_t ncph; 314 315 if (nwam_ncp_read(name, 0, &ncph) != NWAM_SUCCESS) 316 return (B_FALSE); 317 nwam_ncp_free(ncph); 318 return (B_TRUE); 319 } 320 321 static boolean_t 322 valid_ncu(const char *name) 323 { 324 nwam_ncp_handle_t ncph; 325 nwam_ncu_handle_t ncuh; 326 nwam_error_t ret; 327 328 if ((ncph = determine_active_ncp()) == NULL) 329 return (B_FALSE); 330 331 ret = nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_ANY, 0, &ncuh); 332 nwam_ncp_free(ncph); 333 if (ret != NWAM_SUCCESS && ret != NWAM_ENTITY_MULTIPLE_VALUES) 334 return (B_FALSE); 335 nwam_ncu_free(ncuh); 336 return (B_TRUE); 337 } 338 339 /* 340 * Given a name, returns object type (loc, enm, ncp, or ncu) and how many 341 * objects matched that name. 342 */ 343 static nwam_object_type_t 344 determine_object_type(const char *name, int *num) 345 { 346 nwam_object_type_t type; 347 int n = 0; 348 349 /* see if a valid loc, enm, ncp and/or ncu exists with given name */ 350 if (valid_loc(name)) { 351 n++; 352 type = NWAM_OBJECT_TYPE_LOC; 353 } 354 if (valid_enm(name)) { 355 n++; 356 type = NWAM_OBJECT_TYPE_ENM; 357 } 358 if (valid_ncp(name)) { 359 n++; 360 type = NWAM_OBJECT_TYPE_NCP; 361 } 362 if (valid_ncu(name)) { 363 n++; 364 type = NWAM_OBJECT_TYPE_NCU; 365 } 366 367 /* if n > 1, then it means *type was set multiple times, undo it */ 368 if (n != 1) 369 type = NWAM_OBJECT_TYPE_UNKNOWN; 370 371 *num = n; 372 return (type); 373 } 374 375 /* 376 * Parses argv array and populates object_type and name. 377 * Program exits on failure. 378 */ 379 static void 380 parse_argv(int argc, char *argv[], int cmd_num, nwam_object_type_t *object_type, 381 nwam_ncu_type_t *ncu_type, nwam_ncu_class_t *ncu_class, const char **name) 382 { 383 int arg; 384 nwam_object_type_t type = NWAM_OBJECT_TYPE_UNKNOWN; 385 uint64_t ncu = NWAM_NCU_TYPE_ANY; 386 uint64_t class = NWAM_NCU_CLASS_ANY; 387 388 /* check argv for option */ 389 optind = 0; 390 while ((arg = getopt(argc, argv, "?p:c:x")) != EOF) { 391 switch (arg) { 392 case 'p': 393 type = nwam_string_to_object_type(optarg); 394 if (type == NWAM_OBJECT_TYPE_UNKNOWN) 395 die("Invalid profile-type: %s", optarg); 396 break; 397 case 'c': 398 if (nwam_value_string_get_uint64(NWAM_NCU_PROP_CLASS, 399 optarg, &class) != NWAM_SUCCESS) { 400 die("Invalid ncu-class: %s", optarg); 401 } 402 ncu = nwam_ncu_class_to_type(class); 403 if (ncu == NWAM_NCU_TYPE_ANY || 404 ncu == NWAM_NCU_TYPE_UNKNOWN) 405 die("Invalid ncu-class: %s", optarg); 406 break; 407 case 'x': 408 /* -x is only for list */ 409 if (cmd_num != CMD_LIST) 410 die("-x can only be used with 'list'"); 411 extended_list = B_TRUE; 412 break; 413 case '?': 414 default: 415 die_usage(cmd_num); 416 } 417 } 418 419 if (ncu != NWAM_NCU_TYPE_ANY) { 420 /* If -c is given, -p must be NCU. If unspecified, assume NCU */ 421 if (type != NWAM_OBJECT_TYPE_UNKNOWN && 422 type != NWAM_OBJECT_TYPE_NCU) 423 die("'-c <ncu-class>' can only be used for ncu"); 424 425 type = NWAM_OBJECT_TYPE_NCU; 426 } 427 428 /* name is mandatory for enable and disable, but not for list */ 429 if (optind == (argc-1)) 430 *name = argv[optind]; 431 else if (argc != optind) 432 die("too many profile names given"); 433 else if (cmd_num != CMD_LIST) 434 die("no profile name given"); 435 436 /* 437 * No need to determine type for list. 438 * If -p is not given for enable or disable, then determine type. 439 */ 440 if (cmd_num != CMD_LIST && type == NWAM_OBJECT_TYPE_UNKNOWN) { 441 int num = 0; 442 443 type = determine_object_type(*name, &num); 444 if (num == 0) { 445 die("no profile matched '%s'", *name); 446 } else if (num > 1) { 447 die("more than one profile matched '%s' - use " 448 "'-p <profile-type>' to specify a profile type.", 449 *name); 450 } 451 } 452 453 *object_type = type; 454 *ncu_type = ncu; 455 *ncu_class = class; 456 } 457 458 /* Enables/Disables profiles depending on boolean */ 459 static nwam_error_t 460 loc_action(const char *name, boolean_t enable, char **realnamep) 461 { 462 nwam_loc_handle_t loch; 463 nwam_error_t ret; 464 465 if ((ret = nwam_loc_read(name, 0, &loch)) != NWAM_SUCCESS) 466 return (ret); 467 468 if (enable) 469 ret = nwam_loc_enable(loch); 470 else 471 ret = nwam_loc_disable(loch); 472 473 (void) nwam_loc_get_name(loch, realnamep); 474 nwam_loc_free(loch); 475 return (ret); 476 } 477 478 static nwam_error_t 479 enm_action(const char *name, boolean_t enable, char **realnamep) 480 { 481 nwam_enm_handle_t enmh; 482 nwam_error_t ret; 483 484 if ((ret = nwam_enm_read(name, 0, &enmh)) != NWAM_SUCCESS) 485 return (ret); 486 487 if (enable) 488 ret = nwam_enm_enable(enmh); 489 else 490 ret = nwam_enm_disable(enmh); 491 492 (void) nwam_enm_get_name(enmh, realnamep); 493 nwam_enm_free(enmh); 494 return (ret); 495 } 496 497 static nwam_error_t 498 ncu_action(const char *name, nwam_ncp_handle_t ncph, nwam_ncu_type_t type, 499 boolean_t enable, char **realnamep) 500 { 501 nwam_ncu_handle_t ncuh; 502 nwam_error_t ret; 503 boolean_t retrieved_ncph = B_FALSE; 504 505 if (ncph == NULL) { 506 if ((ncph = determine_active_ncp()) == NULL) 507 return (NWAM_ENTITY_NOT_FOUND); 508 retrieved_ncph = B_TRUE; 509 } 510 511 ret = nwam_ncu_read(ncph, name, type, 0, &ncuh); 512 switch (ret) { 513 case NWAM_SUCCESS: 514 if (enable) 515 ret = nwam_ncu_enable(ncuh); 516 else 517 ret = nwam_ncu_disable(ncuh); 518 (void) nwam_ncu_get_name(ncuh, realnamep); 519 nwam_ncu_free(ncuh); 520 break; 521 case NWAM_ENTITY_MULTIPLE_VALUES: 522 /* Call ncu_action() for link and interface types */ 523 ret = ncu_action(name, ncph, NWAM_NCU_TYPE_LINK, enable, 524 realnamep); 525 if (ret != NWAM_SUCCESS) 526 break; 527 528 ret = ncu_action(name, ncph, NWAM_NCU_TYPE_INTERFACE, enable, 529 realnamep); 530 break; 531 } 532 if (retrieved_ncph) 533 nwam_ncp_free(ncph); 534 535 return (ret); 536 } 537 538 /* 539 * If more than one type of profile with the same name, return error. 540 * In such situations, the -p option must be used. 541 * If a location is enabled when a different one is already enabled, then 542 * that location is disabled automatically by nwamd. 543 */ 544 static void 545 enable_func(int argc, char *argv[]) 546 { 547 nwam_error_t ret; 548 nwam_object_type_t type = NWAM_OBJECT_TYPE_UNKNOWN; 549 nwam_ncu_type_t ncu_type = NWAM_NCU_TYPE_ANY; 550 nwam_ncu_class_t ncu_class = NWAM_NCU_CLASS_ANY; 551 const char *name; 552 char *realname = NULL; 553 554 /* parse_argv() returns only on success */ 555 parse_argv(argc, argv, CMD_ENABLE, &type, &ncu_type, &ncu_class, &name); 556 557 /* 558 * NCPs and Locations don't need to disable the currently active 559 * profile - nwamd automatically switches to the new active profile. 560 * and will disable it if necessary. 561 */ 562 563 /* activate given profile */ 564 switch (type) { 565 case NWAM_OBJECT_TYPE_LOC: 566 ret = loc_action(name, B_TRUE, &realname); 567 break; 568 case NWAM_OBJECT_TYPE_ENM: 569 ret = enm_action(name, B_TRUE, &realname); 570 break; 571 case NWAM_OBJECT_TYPE_NCP: 572 { 573 nwam_ncp_handle_t ncph; 574 575 if ((ret = nwam_ncp_read(name, 0, &ncph)) != NWAM_SUCCESS) 576 break; 577 578 ret = nwam_ncp_enable(ncph); 579 (void) nwam_ncp_get_name(ncph, &realname); 580 nwam_ncp_free(ncph); 581 break; 582 } 583 case NWAM_OBJECT_TYPE_NCU: 584 ret = ncu_action(name, NULL, ncu_type, B_TRUE, &realname); 585 break; 586 } 587 588 switch (ret) { 589 case NWAM_SUCCESS: 590 (void) printf(gettext("Enabling %s '%s'\n"), 591 nwam_object_type_to_string(type), 592 realname != NULL ? realname : name); 593 break; 594 case NWAM_ENTITY_NOT_MANUAL: 595 die("Only profiles with manual activation-mode can be enabled"); 596 break; 597 default: 598 die_nwamerr(ret, "Could not enable %s '%s'", 599 nwam_object_type_to_string(type), 600 realname != NULL ? realname : name); 601 } 602 free(realname); 603 } 604 605 /* 606 * Disables a given profile. Similar to enable, the -p option must be used 607 * if more than one type of profile is matched by the given name. 608 */ 609 static void 610 disable_func(int argc, char *argv[]) 611 { 612 nwam_error_t ret; 613 nwam_object_type_t type = NWAM_OBJECT_TYPE_UNKNOWN; 614 nwam_ncu_type_t ncu_type = NWAM_NCU_TYPE_ANY; 615 nwam_ncu_class_t ncu_class = NWAM_NCU_CLASS_ANY; 616 const char *name; 617 char *realname = NULL; 618 619 /* parse_argv() returns only on success */ 620 parse_argv(argc, argv, CMD_DISABLE, &type, &ncu_type, &ncu_class, 621 &name); 622 623 /* deactivate the given profile */ 624 switch (type) { 625 case NWAM_OBJECT_TYPE_LOC: 626 ret = loc_action(name, B_FALSE, &realname); 627 break; 628 case NWAM_OBJECT_TYPE_ENM: 629 ret = enm_action(name, B_FALSE, &realname); 630 break; 631 case NWAM_OBJECT_TYPE_NCU: 632 ret = ncu_action(name, NULL, ncu_type, B_FALSE, &realname); 633 break; 634 case NWAM_OBJECT_TYPE_NCP: 635 die("ncp's cannot be disabled. Enable a different ncp to " 636 "switch to that ncp"); 637 } 638 639 switch (ret) { 640 case NWAM_SUCCESS: 641 (void) printf(gettext("Disabling %s '%s'\n"), 642 nwam_object_type_to_string(type), 643 realname != NULL ? realname : name); 644 break; 645 case NWAM_ENTITY_NOT_MANUAL: 646 die("Only profiles with manual activation-mode can be " 647 "disabled"); 648 break; 649 default: 650 die_nwamerr(ret, "Could not disable %s '%s'", 651 nwam_object_type_to_string(type), 652 realname != NULL ? realname : name); 653 } 654 free(realname); 655 } 656 657 /* prints each column */ 658 static boolean_t 659 print_list_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize) 660 { 661 profile_entry_t *pent = ofarg->ofmt_cbarg; 662 663 switch (ofarg->ofmt_id) { 664 case LIST_TYPE: 665 /* ncu:ip or ncu:phys for NCUs; ncp, loc, enm for others */ 666 if (pent->p_type == NWAM_OBJECT_TYPE_NCU) { 667 const char *class; 668 if (nwam_uint64_get_value_string(NWAM_NCU_PROP_CLASS, 669 pent->p_ncu_class, &class) != NWAM_SUCCESS) 670 class = ""; /* empty */ 671 (void) snprintf(buf, bufsize, "%s:%s", 672 nwam_object_type_to_string(pent->p_type), class); 673 } else { 674 (void) strlcpy(buf, 675 nwam_object_type_to_string(pent->p_type), bufsize); 676 } 677 break; 678 case LIST_PROFILE: 679 (void) strlcpy(buf, pent->p_name, bufsize); 680 break; 681 case LIST_STATE: 682 (void) strlcpy(buf, nwam_state_to_string(pent->p_state), 683 bufsize); 684 break; 685 case LIST_AUXSTATE: 686 (void) strlcpy(buf, 687 nwam_aux_state_to_string(pent->p_aux_state), bufsize); 688 break; 689 default: 690 die("invalid print_list_cb() input: %d", ofarg->ofmt_id); 691 break; 692 } 693 return (B_TRUE); 694 } 695 696 /* returns the state and auxilliary state of the object */ 697 static nwam_state_t 698 determine_object_state(nwam_object_type_t type, void *handle, 699 nwam_aux_state_t *aux_statep) 700 { 701 nwam_state_t state; 702 nwam_aux_state_t astate; 703 nwam_error_t ret; 704 705 switch (type) { 706 case NWAM_OBJECT_TYPE_ENM: 707 ret = nwam_enm_get_state(handle, &state, &astate); 708 break; 709 case NWAM_OBJECT_TYPE_LOC: 710 ret = nwam_loc_get_state(handle, &state, &astate); 711 break; 712 case NWAM_OBJECT_TYPE_NCP: 713 ret = nwam_ncp_get_state(handle, &state, &astate); 714 break; 715 case NWAM_OBJECT_TYPE_NCU: 716 ret = nwam_ncu_get_state(handle, &state, &astate); 717 break; 718 default: 719 /* NOTREACHED */ 720 break; 721 } 722 723 if (ret == NWAM_PERMISSION_DENIED) { 724 die_nwamerr(ret, "could not get object state"); 725 } else if (ret != NWAM_SUCCESS) { 726 state = NWAM_STATE_UNINITIALIZED; 727 astate = NWAM_AUX_STATE_UNINITIALIZED; 728 } 729 730 if (aux_statep != NULL) 731 *aux_statep = astate; 732 return (state); 733 } 734 735 /* populate profile_entry_t with values for object with given handle */ 736 static int 737 add_to_profile_entry(nwam_object_type_t type, void *handle, 738 profile_entry_t *pent) 739 { 740 char *name; 741 nwam_error_t ret; 742 743 pent->p_type = type; 744 if (type == NWAM_OBJECT_TYPE_NCU) { 745 nwam_ncu_class_t class; 746 if ((ret = nwam_ncu_get_ncu_class(handle, &class)) 747 != NWAM_SUCCESS) 748 return (ret); 749 pent->p_ncu_class = class; 750 } else { 751 pent->p_ncu_class = -1; 752 } 753 754 switch (type) { 755 case NWAM_OBJECT_TYPE_ENM: 756 ret = nwam_enm_get_name(handle, &name); 757 break; 758 case NWAM_OBJECT_TYPE_LOC: 759 ret = nwam_loc_get_name(handle, &name); 760 break; 761 case NWAM_OBJECT_TYPE_NCP: 762 ret = nwam_ncp_get_name(handle, &name); 763 break; 764 case NWAM_OBJECT_TYPE_NCU: 765 ret = nwam_ncu_get_name(handle, &name); 766 break; 767 default: 768 /* NOTREACHED */ 769 break; 770 } 771 if (ret != NWAM_SUCCESS) { 772 return (ret); 773 } 774 (void) strlcpy(pent->p_name, name, sizeof (pent->p_name)); 775 free(name); 776 777 pent->p_state = determine_object_state(type, handle, 778 &pent->p_aux_state); 779 780 return (NWAM_SUCCESS); 781 } 782 783 /* callback functions used by walk */ 784 785 static int 786 list_ncu_cb(nwam_ncu_handle_t ncuh, void *arg) 787 { 788 ofmt_handle_t ofmt = arg; 789 profile_entry_t pent; 790 nwam_error_t ret; 791 792 bzero(&pent, sizeof (profile_entry_t)); 793 ret = add_to_profile_entry(NWAM_OBJECT_TYPE_NCU, ncuh, &pent); 794 if (ret != NWAM_SUCCESS) 795 die_nwamerr(ret, "could not add ncu to list"); 796 ofmt_print(ofmt, &pent); 797 return (0); 798 } 799 800 static int 801 list_ncp_cb(nwam_ncp_handle_t ncph, void *arg) 802 { 803 ofmt_handle_t ofmt = arg; 804 profile_entry_t pent; 805 nwam_error_t ret; 806 nwam_state_t state; 807 808 bzero(&pent, sizeof (profile_entry_t)); 809 ret = add_to_profile_entry(NWAM_OBJECT_TYPE_NCP, ncph, &pent); 810 if (ret != NWAM_SUCCESS) 811 die_nwamerr(ret, "could not add ncp to list"); 812 ofmt_print(ofmt, &pent); 813 814 state = determine_object_state(NWAM_OBJECT_TYPE_NCP, ncph, NULL); 815 if (state == NWAM_STATE_ONLINE) { 816 (void) nwam_ncp_walk_ncus(ncph, list_ncu_cb, ofmt, 817 NWAM_FLAG_NCU_TYPE_ALL, NULL); 818 } 819 return (0); 820 } 821 822 static int 823 list_loc_cb(nwam_loc_handle_t loch, void *arg) 824 { 825 ofmt_handle_t ofmt = arg; 826 profile_entry_t pent; 827 nwam_error_t ret; 828 829 bzero(&pent, sizeof (profile_entry_t)); 830 ret = add_to_profile_entry(NWAM_OBJECT_TYPE_LOC, loch, &pent); 831 if (ret != NWAM_SUCCESS) 832 die_nwamerr(ret, "could not add loc to list"); 833 ofmt_print(ofmt, &pent); 834 return (0); 835 } 836 837 static int 838 list_enm_cb(nwam_enm_handle_t enmh, void *arg) 839 { 840 ofmt_handle_t ofmt = arg; 841 profile_entry_t pent; 842 nwam_error_t ret; 843 844 bzero(&pent, sizeof (profile_entry_t)); 845 ret = add_to_profile_entry(NWAM_OBJECT_TYPE_ENM, enmh, &pent); 846 if (ret != NWAM_SUCCESS) 847 die_nwamerr(ret, "could not add enm to list"); 848 ofmt_print(ofmt, &pent); 849 return (0); 850 } 851 852 /* 853 * lists all profiles and their state 854 */ 855 static void 856 list_func(int argc, char *argv[]) 857 { 858 nwam_error_t ret = NWAM_SUCCESS; 859 nwam_object_type_t type = NWAM_OBJECT_TYPE_UNKNOWN; 860 nwam_ncu_type_t ncu_type = NWAM_NCU_TYPE_ANY; 861 nwam_ncu_class_t ncu_class = NWAM_NCU_CLASS_ANY; 862 char *name = NULL; 863 864 ofmt_handle_t ofmt; 865 ofmt_status_t oferr; 866 char *default_fields = "type,profile,state"; 867 char *extended_fields = "type,profile,state,auxiliary state"; 868 char *fields = NULL; 869 870 /* parse_argv() returns only on success */ 871 parse_argv(argc, argv, CMD_LIST, &type, &ncu_type, &ncu_class, 872 (const char **)&name); 873 874 if (extended_list) 875 fields = extended_fields; 876 else 877 fields = default_fields; 878 oferr = ofmt_open(fields, list_fields, 0, 0, &ofmt); 879 if (oferr != OFMT_SUCCESS) { 880 char buf[OFMT_BUFSIZE]; 881 (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf)); 882 die("ofmt_open() failed: %s", buf); 883 } 884 885 /* object-name given in command-line */ 886 if (name != NULL) { 887 boolean_t found = B_FALSE; 888 889 /* 890 * If objects with different types have the same name 891 * (type = UNKNOWN), then try to open handle for each object 892 * and print if successful. 893 */ 894 if (type == NWAM_OBJECT_TYPE_NCP || 895 type == NWAM_OBJECT_TYPE_UNKNOWN) { 896 nwam_ncp_handle_t ncph; 897 if (nwam_ncp_read(name, 0, &ncph) == NWAM_SUCCESS) { 898 found = B_TRUE; 899 (void) list_ncp_cb(ncph, ofmt); 900 nwam_ncp_free(ncph); 901 } 902 } 903 if (type == NWAM_OBJECT_TYPE_NCU || 904 type == NWAM_OBJECT_TYPE_UNKNOWN) { 905 nwam_ncp_handle_t ncph; 906 nwam_ncu_handle_t ncuh; 907 908 if ((ncph = determine_active_ncp()) != NULL) { 909 ret = nwam_ncu_read(ncph, name, ncu_type, 0, 910 &ncuh); 911 if (ret == NWAM_ENTITY_MULTIPLE_VALUES) { 912 found = B_TRUE; 913 if (nwam_ncu_read(ncph, name, 914 NWAM_NCU_TYPE_LINK, 0, &ncuh) 915 == NWAM_SUCCESS) { 916 (void) list_ncu_cb(ncuh, ofmt); 917 nwam_ncu_free(ncuh); 918 } 919 if (nwam_ncu_read(ncph, name, 920 NWAM_NCU_TYPE_INTERFACE, 0, &ncuh) 921 == NWAM_SUCCESS) { 922 (void) list_ncu_cb(ncuh, ofmt); 923 nwam_ncu_free(ncuh); 924 } 925 } else if (ret == NWAM_SUCCESS) { 926 found = B_TRUE; 927 (void) list_ncu_cb(ncuh, ofmt); 928 nwam_ncu_free(ncuh); 929 } 930 nwam_ncp_free(ncph); 931 } 932 } 933 if (type == NWAM_OBJECT_TYPE_LOC || 934 type == NWAM_OBJECT_TYPE_UNKNOWN) { 935 nwam_loc_handle_t loch; 936 if (nwam_loc_read(name, 0, &loch) == NWAM_SUCCESS) { 937 found = B_TRUE; 938 (void) list_loc_cb(loch, ofmt); 939 nwam_loc_free(loch); 940 } 941 } 942 if (type == NWAM_OBJECT_TYPE_ENM || 943 type == NWAM_OBJECT_TYPE_UNKNOWN) { 944 nwam_enm_handle_t enmh; 945 if (nwam_enm_read(name, 0, &enmh) == NWAM_SUCCESS) { 946 found = B_TRUE; 947 (void) list_enm_cb(enmh, ofmt); 948 nwam_enm_free(enmh); 949 } 950 } 951 /* If at least object is found, don't return error */ 952 if (found) 953 ret = NWAM_SUCCESS; 954 else 955 ret = NWAM_ENTITY_NOT_FOUND; 956 } 957 958 /* object-name not given in command-line */ 959 if (name == NULL) { 960 /* 961 * If type given (type != UNKNOWN), just walk objects in that 962 * type. Otherwise, walk all ncp, ncu, loc and enm. 963 */ 964 if (type == NWAM_OBJECT_TYPE_NCP || 965 type == NWAM_OBJECT_TYPE_UNKNOWN) { 966 ret = nwam_walk_ncps(list_ncp_cb, ofmt, 0, NULL); 967 if (ret != NWAM_SUCCESS) 968 goto done; 969 } 970 /* no UNKNOWN for NCUs. They walked with active NCP above */ 971 if (type == NWAM_OBJECT_TYPE_NCU) { 972 nwam_ncp_handle_t ncph; 973 if ((ncph = determine_active_ncp()) != NULL) { 974 ret = nwam_ncp_walk_ncus(ncph, list_ncu_cb, 975 ofmt, nwam_ncu_class_to_flag(ncu_class), 976 NULL); 977 nwam_ncp_free(ncph); 978 if (ret != NWAM_SUCCESS) 979 goto done; 980 } 981 } 982 if (type == NWAM_OBJECT_TYPE_LOC || 983 type == NWAM_OBJECT_TYPE_UNKNOWN) { 984 ret = nwam_walk_locs(list_loc_cb, ofmt, 985 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL); 986 if (ret != NWAM_SUCCESS) 987 goto done; 988 } 989 if (type == NWAM_OBJECT_TYPE_ENM || 990 type == NWAM_OBJECT_TYPE_UNKNOWN) { 991 ret = nwam_walk_enms(list_enm_cb, ofmt, 992 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL); 993 if (ret != NWAM_SUCCESS) 994 goto done; 995 } 996 } 997 998 done: 999 ofmt_close(ofmt); 1000 if (ret == NWAM_ENTITY_NOT_FOUND && name != NULL) 1001 die("no profile matched '%s'", name); 1002 else if (ret != NWAM_SUCCESS) 1003 die_nwamerr(ret, "list failed during walk"); 1004 } 1005 1006 /* 1007 * Print NWAM events. 1008 */ 1009 static void 1010 eventhandler(nwam_event_t event) 1011 { 1012 char description[DESCRIPTION_WIDTH]; 1013 char statestr[DESCRIPTION_WIDTH]; 1014 char objstr[DESCRIPTION_WIDTH]; 1015 char *object = NULL; 1016 const char *action = NULL; 1017 char *state = NULL; 1018 boolean_t display = B_TRUE; 1019 int i; 1020 nwam_wlan_t *wlans; 1021 1022 (void) strlcpy(description, "-", sizeof (description)); 1023 1024 switch (event->nwe_type) { 1025 case NWAM_EVENT_TYPE_OBJECT_ACTION: 1026 action = nwam_action_to_string 1027 (event->nwe_data.nwe_object_action.nwe_action); 1028 (void) snprintf(objstr, sizeof (objstr), "%s %s", 1029 nwam_object_type_to_string 1030 (event->nwe_data.nwe_object_action.nwe_object_type), 1031 event->nwe_data.nwe_object_action.nwe_name); 1032 object = objstr; 1033 break; 1034 1035 case NWAM_EVENT_TYPE_OBJECT_STATE: 1036 (void) snprintf(statestr, sizeof (statestr), "%s, %s", 1037 nwam_state_to_string 1038 (event->nwe_data.nwe_object_state.nwe_state), 1039 nwam_aux_state_to_string 1040 (event->nwe_data.nwe_object_state.nwe_aux_state)); 1041 state = statestr; 1042 1043 (void) snprintf(objstr, sizeof (objstr), "%s %s", 1044 nwam_object_type_to_string 1045 (event->nwe_data.nwe_object_state.nwe_object_type), 1046 event->nwe_data.nwe_object_state.nwe_name); 1047 object = objstr; 1048 break; 1049 1050 case NWAM_EVENT_TYPE_PRIORITY_GROUP: 1051 (void) snprintf(description, DESCRIPTION_WIDTH, 1052 "priority-group: %d", 1053 event->nwe_data.nwe_priority_group_info.nwe_priority); 1054 break; 1055 1056 case NWAM_EVENT_TYPE_WLAN_SCAN_REPORT: 1057 (void) printf("%-*s \n", EVENT_WIDTH, 1058 nwam_event_type_to_string(event->nwe_type)); 1059 wlans = event->nwe_data.nwe_wlan_info.nwe_wlans; 1060 for (i = 0; 1061 i < event->nwe_data.nwe_wlan_info.nwe_num_wlans; 1062 i++) { 1063 (void) snprintf(description, DESCRIPTION_WIDTH, 1064 "%d: %c%c ESSID %s BSSID %s", i + 1, 1065 wlans[i].nww_selected ? 'S' : '-', 1066 wlans[i].nww_connected ? 'C' : '-', 1067 wlans[i].nww_essid, wlans[i].nww_bssid); 1068 (void) printf("%-*s %-*s\n", EVENT_WIDTH, "-", 1069 DESCRIPTION_WIDTH, description); 1070 } 1071 display = B_FALSE; 1072 break; 1073 1074 case NWAM_EVENT_TYPE_WLAN_NEED_CHOICE: 1075 (void) printf("%-*s \n", EVENT_WIDTH, 1076 nwam_event_type_to_string(event->nwe_type)); 1077 display = B_FALSE; 1078 break; 1079 1080 case NWAM_EVENT_TYPE_WLAN_NEED_KEY: 1081 (void) printf("%-*s \n", EVENT_WIDTH, 1082 nwam_event_type_to_string(event->nwe_type)); 1083 display = B_FALSE; 1084 break; 1085 1086 case NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT: 1087 (void) snprintf(description, DESCRIPTION_WIDTH, 1088 gettext("connect to WLAN ESSID %s, BSSID %s %s"), 1089 event->nwe_data.nwe_wlan_info.nwe_wlans[0].nww_essid, 1090 event->nwe_data.nwe_wlan_info.nwe_wlans[0].nww_bssid, 1091 event->nwe_data.nwe_wlan_info.nwe_connected ? 1092 "succeeded" : "failed"); 1093 break; 1094 1095 case NWAM_EVENT_TYPE_INFO: 1096 (void) snprintf(description, sizeof (description), 1097 "%s", event->nwe_data.nwe_info.nwe_message); 1098 break; 1099 1100 case NWAM_EVENT_TYPE_IF_ACTION: 1101 action = nwam_action_to_string 1102 (event->nwe_data.nwe_if_action.nwe_action); 1103 object = event->nwe_data.nwe_if_action.nwe_name; 1104 break; 1105 1106 case NWAM_EVENT_TYPE_IF_STATE: 1107 object = event->nwe_data.nwe_if_state.nwe_name; 1108 if (event->nwe_data.nwe_if_state.nwe_addr_valid) { 1109 struct sockaddr_storage *address = 1110 &(event->nwe_data.nwe_if_state.nwe_addr); 1111 struct sockaddr_in *v4addr; 1112 struct sockaddr_in6 *v6addr; 1113 char addrstr[NWAM_MAX_VALUE_LEN]; 1114 1115 switch (address->ss_family) { 1116 case AF_INET: 1117 v4addr = (struct sockaddr_in *)address; 1118 (void) inet_ntop(AF_INET, &v4addr->sin_addr, 1119 addrstr, sizeof (addrstr)); 1120 break; 1121 case AF_INET6: 1122 v6addr = (struct sockaddr_in6 *)address; 1123 (void) inet_ntop(AF_INET6, &v6addr->sin6_addr, 1124 addrstr, sizeof (addrstr)); 1125 break; 1126 } 1127 (void) snprintf(statestr, sizeof (statestr), 1128 "index %d flags 0x%x address %s", 1129 event->nwe_data.nwe_if_state.nwe_index, 1130 event->nwe_data.nwe_if_state.nwe_flags, addrstr); 1131 } else { 1132 (void) snprintf(statestr, sizeof (statestr), 1133 "(%d) flags %x", 1134 event->nwe_data.nwe_if_state.nwe_index, 1135 event->nwe_data.nwe_if_state.nwe_flags); 1136 } 1137 state = statestr; 1138 break; 1139 1140 case NWAM_EVENT_TYPE_LINK_ACTION: 1141 action = nwam_action_to_string 1142 (event->nwe_data.nwe_link_action.nwe_action); 1143 object = event->nwe_data.nwe_link_action.nwe_name; 1144 break; 1145 1146 case NWAM_EVENT_TYPE_LINK_STATE: 1147 state = event->nwe_data.nwe_link_state.nwe_link_up ? 1148 "up" : "down"; 1149 object = event->nwe_data.nwe_link_state.nwe_name; 1150 break; 1151 } 1152 1153 if (object != NULL && action != NULL) { 1154 (void) snprintf(description, sizeof (description), 1155 "%s -> action %s", object, action); 1156 } else if (object != NULL && state != NULL) { 1157 (void) snprintf(description, sizeof (description), 1158 "%s -> state %s", object, state); 1159 } 1160 1161 if (display) { 1162 (void) printf("%-*s %-*s\n", EVENT_WIDTH, 1163 nwam_event_type_to_string(event->nwe_type), 1164 DESCRIPTION_WIDTH, 1165 description); 1166 } 1167 } 1168 1169 /* 1170 * listens for events and displays them via the eventhandler() function above. 1171 */ 1172 /* ARGSUSED */ 1173 static void 1174 show_events_func(int argc, char *argv[]) 1175 { 1176 nwam_error_t err; 1177 nwam_event_t event; 1178 1179 err = nwam_events_init(); 1180 1181 if (err != NWAM_SUCCESS) 1182 die_nwamerr(err, "could not bind to receive events"); 1183 1184 /* print header */ 1185 (void) printf("%-*s %-*s\n", EVENT_WIDTH, "EVENT", 1186 DESCRIPTION_WIDTH, "DESCRIPTION"); 1187 1188 do { 1189 /* 1190 * Needed for stdout redirection to ensure event output is 1191 * regularly flushed to file. 1192 */ 1193 (void) fflush(stdout); 1194 err = nwam_event_wait(&event); 1195 if (err == NWAM_SUCCESS) { 1196 eventhandler(event); 1197 nwam_event_free(event); 1198 } 1199 } while (err == NWAM_SUCCESS); 1200 die_nwamerr(err, "event handling stopped"); 1201 } 1202 1203 /* May need to convert case-insensitive link name match to case-sensitive one */ 1204 static nwam_error_t 1205 name_to_linkname(char *name, char **linknamep) 1206 { 1207 nwam_error_t err; 1208 nwam_ncp_handle_t ncph = NULL; 1209 nwam_ncu_handle_t ncuh = NULL; 1210 1211 if ((ncph = determine_active_ncp()) == NULL) 1212 return (NWAM_ENTITY_NOT_FOUND); 1213 1214 err = nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_LINK, 0, &ncuh); 1215 if (err == NWAM_SUCCESS) 1216 err = nwam_ncu_get_name(ncuh, linknamep); 1217 1218 nwam_ncp_free(ncph); 1219 nwam_ncu_free(ncuh); 1220 return (err); 1221 } 1222 1223 static void 1224 scan_wifi_func(int argc, char *argv[]) 1225 { 1226 nwam_error_t err; 1227 char *linkname = NULL; 1228 1229 if (argc != 1) 1230 die_usage(CMD_SCAN_WIFI); 1231 1232 if ((err = name_to_linkname(argv[0], &linkname)) != NWAM_SUCCESS) 1233 die_nwamerr(err, "scan request failed for %s", argv[0]); 1234 1235 err = nwam_wlan_scan(linkname); 1236 1237 if (err != NWAM_SUCCESS) 1238 die_nwamerr(err, "scan request failed for %s", linkname); 1239 1240 free(linkname); 1241 } 1242 1243 static void 1244 select_wifi_func(int argc, char *argv[]) 1245 { 1246 nwam_error_t err; 1247 char *linkname = NULL; 1248 uint_t i, choice, num_wlans = 0; 1249 uint32_t security_mode; 1250 boolean_t have_key = B_FALSE; 1251 nwam_wlan_t *wlans = NULL; 1252 char choicestr[NWAM_MAX_VALUE_LEN]; 1253 char modestr[NWAM_MAX_VALUE_LEN]; 1254 char essid[NWAM_MAX_VALUE_LEN]; 1255 char bssid[NWAM_MAX_VALUE_LEN]; 1256 1257 if (argc != 1) 1258 die_usage(CMD_SELECT_WIFI); 1259 1260 if ((err = name_to_linkname(argv[0], &linkname)) != NWAM_SUCCESS) { 1261 die_nwamerr(err, "could not retrieve scan results for %s", 1262 argv[0]); 1263 } 1264 err = nwam_wlan_get_scan_results(linkname, &num_wlans, &wlans); 1265 1266 if (err != NWAM_SUCCESS) { 1267 die_nwamerr(err, "could not retrieve scan results for %s", 1268 linkname); 1269 } 1270 bssid[0] = '\0'; 1271 1272 /* Loop until valid selection made */ 1273 for (;;) { 1274 (void) printf("\n"); 1275 /* Display WLAN choices for user to select from */ 1276 for (i = 0; i < num_wlans; i++) { 1277 (void) printf("%d: ESSID %s BSSID %s\n", 1278 i + 1, wlans[i].nww_essid, wlans[i].nww_bssid); 1279 } 1280 (void) printf(gettext("%d: Other\n"), i + 1); 1281 1282 (void) printf(gettext("\nChoose WLAN to connect to [1-%d]: "), 1283 i + 1); 1284 1285 if (fgets(choicestr, sizeof (choicestr), stdin) != NULL && 1286 (choice = atoi(choicestr)) >= 1 && choice <= (i + 1)) 1287 break; 1288 } 1289 1290 if (choice == i + 1 || wlans[choice - 1].nww_essid[0] == '\0') { 1291 nwam_known_wlan_handle_t kwh = NULL; 1292 nwam_value_t keynameval = NULL; 1293 1294 /* If "Other" or a hidden WLAN is selected, ask for ESSID */ 1295 do { 1296 (void) printf(gettext("\nEnter WLAN name: ")); 1297 while (fgets(essid, sizeof (essid), stdin) == NULL) {} 1298 essid[strlen(essid) - 1] = '\0'; 1299 } while (strspn(essid, " \t") == strlen(essid)); 1300 1301 /* If "Other" was selected, secmode must be specified. */ 1302 if (choice == i + 1) { 1303 for (;;) { 1304 (void) printf(gettext("1: None\n")); 1305 (void) printf(gettext("2: WEP\n")); 1306 (void) printf(gettext("3: WPA\n")); 1307 (void) printf(gettext("Enter security mode: ")); 1308 if (fgets(modestr, sizeof (choicestr), stdin) 1309 != NULL && 1310 (security_mode = atoi(modestr)) >= 1 && 1311 security_mode <= 3) 1312 break; 1313 } 1314 } else { 1315 security_mode = wlans[choice - 1].nww_security_mode; 1316 have_key = wlans[choice - 1].nww_have_key; 1317 } 1318 1319 /* 1320 * We have to determine if we have a key for this ESSID from 1321 * the known WLAN list, since we cannot determine this from 1322 * the scan results. 1323 */ 1324 if (nwam_known_wlan_read(essid, 0, &kwh) == NWAM_SUCCESS && 1325 nwam_known_wlan_get_prop_value(kwh, 1326 NWAM_KNOWN_WLAN_PROP_KEYNAME, &keynameval) == NWAM_SUCCESS) 1327 have_key = B_TRUE; 1328 else 1329 have_key = B_FALSE; 1330 1331 nwam_value_free(keynameval); 1332 nwam_known_wlan_free(kwh); 1333 } else { 1334 (void) strlcpy(essid, wlans[choice - 1].nww_essid, 1335 sizeof (essid)); 1336 (void) strlcpy(bssid, wlans[choice - 1].nww_bssid, 1337 sizeof (bssid)); 1338 security_mode = wlans[choice - 1].nww_security_mode; 1339 have_key = wlans[choice - 1].nww_have_key; 1340 } 1341 1342 if (security_mode != DLADM_WLAN_SECMODE_NONE && !have_key) { 1343 uint_t keyslot = 1; 1344 char key[NWAM_MAX_VALUE_LEN]; 1345 char slotstr[NWAM_MAX_VALUE_LEN]; 1346 1347 do { 1348 (void) printf(gettext("\nEnter WLAN key for " 1349 "ESSID %s: "), essid); 1350 while (fgets(key, sizeof (key), stdin) == NULL) {} 1351 key[strlen(key) - 1] = '\0'; 1352 } while (strspn(key, " \t") == strlen(key)); 1353 1354 if (security_mode == DLADM_WLAN_SECMODE_WEP) { 1355 for (;;) { 1356 (void) printf( 1357 gettext("\nEnter key slot [1-4]: ")); 1358 if (fgets(slotstr, sizeof (slotstr), stdin) 1359 != NULL && (keyslot = atoi(slotstr)) >= 1 && 1360 keyslot <= 4) 1361 break; 1362 } 1363 } 1364 1365 err = nwam_wlan_set_key(linkname, essid, NULL, security_mode, 1366 keyslot, key); 1367 if (err != NWAM_SUCCESS) 1368 die_nwamerr(err, "could not set WiFi key"); 1369 } 1370 err = nwam_wlan_select(linkname, essid, bssid[0] != '\0' ? bssid : NULL, 1371 security_mode, B_TRUE); 1372 if (err != NWAM_SUCCESS) 1373 die_nwamerr(err, "could not select WLAN %s", essid); 1374 free(wlans); 1375 free(linkname); 1376 } 1377 1378 int 1379 main(int argc, char *argv[]) 1380 { 1381 int i; 1382 char *state; 1383 1384 (void) setlocale(LC_ALL, ""); 1385 (void) textdomain(TEXT_DOMAIN); 1386 1387 if ((execname = strrchr(argv[0], '/')) == NULL) 1388 execname = argv[0]; 1389 else 1390 execname++; 1391 1392 if (argc < 2) { 1393 usage(B_FALSE); 1394 exit(EXIT_FAILURE); 1395 } 1396 1397 for (i = CMD_MIN; i <= CMD_MAX; i++) { 1398 if (strcmp(argv[1], cmd_to_str(i)) == 0) { 1399 if (cmdtab[i].cmd_needs_nwamd) { 1400 state = smf_get_state(NWAM_FMRI); 1401 if (state == NULL || strcmp(state, 1402 SCF_STATE_STRING_ONLINE) != 0) { 1403 free(state); 1404 die("enable '%s' to use '%s %s'", 1405 NWAM_FMRI, execname, 1406 cmd_to_str(cmdtab[i].cmd_num)); 1407 } 1408 free(state); 1409 } 1410 1411 cmdtab[i].cmd_handler(argc - 2, &(argv[2])); 1412 1413 exit(EXIT_SUCCESS); 1414 } 1415 } 1416 1417 (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"), 1418 execname, argv[1]); 1419 usage(B_FALSE); 1420 1421 return (1); 1422 } 1423