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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright (c) 2018, Joyent, Inc. 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <stddef.h> 33 #include <errno.h> 34 #include <ctype.h> 35 #include <stdarg.h> 36 #include <fcntl.h> 37 #include <unistd.h> 38 #include <net/if.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <sys/wait.h> 42 #include <sys/ipc.h> 43 #include <sys/ddi.h> 44 #include <stropts.h> 45 #include <assert.h> 46 #include <termios.h> 47 #include <time.h> 48 #include <string.h> 49 #include <strings.h> 50 #include <auth_attr.h> 51 #include <auth_list.h> 52 #include <libdevinfo.h> 53 #include <secdb.h> 54 #include <priv.h> 55 #include <pwd.h> 56 #include <umem.h> 57 #include <locale.h> 58 #include <libintl.h> 59 #include <dirent.h> 60 #include <inet/wifi_ioctl.h> 61 62 /* 63 * Debug information 64 */ 65 #ifdef DEBUG 66 int wifi_debug = 0; 67 void wifi_dbgprintf(char *fmt, ...); 68 #define PRTDBG(msg) if (wifi_debug > 1) wifi_dbgprintf msg 69 #else /* DEBUG */ 70 #define PRTDBG(msg) 71 #endif /* DEBUG */ 72 73 #define MAX_HISTORY_NUM 10 74 #define MAX_PREFERENCE_NUM 10 75 #define MAX_SCANBUF_LEN 256 76 #define MAX_CONFIG_FILE_LENGTH 256 77 #define MAX_LOADPF_LENGTH 256 78 #define LOADPROFILE_TIMEOUT 10 79 #define RECORD_ADD 0 80 #define RECORD_DEL 1 81 /* 82 * Wificonfig exit status 83 */ 84 #define WIFI_EXIT_DEF 0 85 #define WIFI_FATAL_ERR 1 86 #define WIFI_IMPROPER_USE 2 87 #define WIFI_MINOR_ERR 3 88 89 #define WIFI_LOCKF "/var/run/lockf_wifi" 90 91 typedef enum { 92 PREFERENCE, 93 HISTORY, 94 ACTIVEP, 95 PROFILE, 96 OTHER 97 } list_type_t; 98 99 #define WIFI_PREFER "{preference}" 100 #define WIFI_HISTORY "{history}" 101 #define WIFI_ACTIVEP "{active_profile}" 102 103 typedef enum { 104 LINKSTATUS = 0, 105 BSSID, 106 ESSID, 107 BSSTYPE, 108 CREATEIBSS, 109 CHANNEL, 110 RATES, 111 POWERMODE, 112 AUTHMODE, 113 ENCRYPTION, 114 WEPKEYID, 115 WEPKEY, 116 SIGNAL, 117 RADIOON, 118 WLANLIST, 119 CONFIG_ITEM_END /* 15 */ 120 } config_item_t; 121 typedef struct ae { 122 struct ae *ae_next; 123 char *ae_arg; 124 }ae_t; 125 typedef struct aelist { 126 int ael_argc; 127 ae_t *ael_head, *ael_tail; 128 list_type_t type; 129 }aelist_t; 130 typedef struct section { 131 struct section *section_next; 132 aelist_t *list; 133 char *section_id; 134 }section_t; 135 136 /* 137 * config_file_t is an abstract of configration file, 138 * either/etc/inet/wifi/wifi.<interface> or /etc/inet/secret/ 139 * wifi/wifiwepkey.<interface> 140 */ 141 typedef struct config_file { 142 int section_argc; 143 section_t *section_head, *section_tail; 144 }config_file_t; 145 146 static config_file_t *gp_config_file = NULL; 147 static config_file_t *gp_wepkey_file = NULL; 148 static char *p_file_wifi = "/etc/inet/wifi"; 149 static char *p_file_wifiwepkey = "/etc/inet/secret/wifiwepkey"; 150 151 typedef enum { 152 AUTH_WEP = 0, 153 AUTH_OTHER = 1 154 } wifi_auth_t; 155 156 static char *p_auth_string[] = { 157 WIFI_WEP_AUTH, 158 WIFI_CONFIG_AUTH 159 }; 160 161 /* 162 * gbuf: is a global buf, which is used to communicate between the user and 163 * the driver 164 */ 165 static wldp_t *gbuf = NULL; 166 static char *gExecName = NULL; 167 168 static void print_error(uint32_t); 169 static void *safe_malloc(size_t); 170 static void *safe_calloc(size_t, size_t); 171 static char *safe_strdup(const char *s1); 172 static void safe_snprintf(char *s, size_t n, 173 const char *format, ...); 174 static void safe_fclose(FILE *stream); 175 static void new_ae(aelist_t *ael, const char *arg); 176 static aelist_t *new_ael(list_type_t type); 177 static config_file_t *new_config_file(); 178 static void new_section(config_file_t *p_config_file, aelist_t *p_list, 179 const char *section_id); 180 static void destroy_config(config_file_t *p_config_file); 181 static config_file_t *parse_file(const char *pfile); 182 static char **aeltoargv(aelist_t *ael, int *ael_num); 183 static boolean_t fprint_config_file(config_file_t *p_config_file, 184 const char *file_name); 185 static char *append_pa(const char *arg); 186 static section_t *find_section(config_file_t *p_config_file, 187 const char *section_id); 188 static ae_t *find_ae(aelist_t *plist, const char *arg); 189 static void update_aelist(aelist_t *plist, const char *arg); 190 static const char *get_value(const char *arg); 191 static char *find_active_profile(int); 192 static const char *essid_of_profile(const char *profile); 193 static boolean_t search_interface(char *interface); 194 static int open_dev(char *devname); 195 static boolean_t call_ioctl(int, int, uint32_t, uint32_t); 196 static boolean_t del_prefer(config_file_t *p_config_file, const char *prefer, 197 boolean_t rflag); 198 static boolean_t del_section(config_file_t *p_config_file, char *section_id); 199 static boolean_t set_prefer(config_file_t *p_config_file, const char *prefer, 200 int rank); 201 static void add_to_history(config_file_t *p_config_file, 202 int argc, char **argv); 203 static boolean_t check_authority(wifi_auth_t type); 204 static void heuristic_load(int fd, uint32_t ess_num, wl_ess_conf_t **); 205 static char *select_profile(int fd, int readonly, int timeout); 206 static char *construct_format(uint32_t nt); 207 static void print_gbuf(config_item_t index); 208 static boolean_t items_in_profile(aelist_t *, aelist_t *, int, char **); 209 static char *get_commit_key(int, int, char **); 210 static void print_wepkey_info(const char *id, const char *wepkeyn); 211 static void do_print_usage(); 212 static boolean_t do_print_support_params(int fd); 213 static boolean_t do_autoconf(int fd, int argc, char **argv); 214 static boolean_t do_startconf(int fd, int argc, char **argv); 215 static boolean_t do_loadpf(int fd, int argc, char **argv); 216 static boolean_t do_disconnect(int fd, int argc, char **argv); 217 static boolean_t do_printpf(int fd, int argc, char **argv); 218 static boolean_t do_restoredef(int fd, int argc, char **argv); 219 static boolean_t do_history(int fd, int argc, char **argv); 220 static boolean_t do_deletepf(int fd, int argc, char **argv); 221 static boolean_t do_wepkey(int fd, int argc, char **argv); 222 static boolean_t do_setprefer(int fd, int argc, char **arg); 223 static boolean_t do_rmprefer(int fd, int argc, char **argv); 224 static boolean_t do_lsprefer(int fd, int argc, char **argv); 225 static boolean_t do_wlanlist(int fd, int argc, char **argv); 226 static boolean_t do_showstatus(int fd, int argc, char **argv); 227 static boolean_t do_getprofparam(int fd, int argc, char **argv); 228 static boolean_t do_setprofparam(int fd, int argc, char **argv); 229 static boolean_t do_setprofwepkey(int fd, int argc, char **argv); 230 static boolean_t is_rates_support(int fd, int num, uint8_t *rates); 231 static boolean_t do_set_bsstype(int fd, const char *arg); 232 static boolean_t do_set_essid(int fd, const char *arg); 233 static boolean_t do_set_powermode(int fd, const char *arg); 234 static boolean_t do_set_rates(int fd, const char *arg); 235 static boolean_t do_set_channel(int fd, const char *arg); 236 static boolean_t do_set_createibss(int fd, const char *arg); 237 static boolean_t do_set_radioon(int fd, const char *arg); 238 static boolean_t do_set_wepkeyid(int fd, const char *arg); 239 static boolean_t do_set_encryption(int fd, const char *arg); 240 static boolean_t do_set_authmode(int fd, const char *arg); 241 static boolean_t do_set_wepkey(int fd, const char *pbuf); 242 static boolean_t do_get_createibss(int fd); 243 static boolean_t do_get_bsstype(int fd); 244 static boolean_t do_get_essid(int fd); 245 static boolean_t do_get_bssid(int fd); 246 static boolean_t do_get_radioon(int fd); 247 static boolean_t do_get_signal(int fd); 248 static boolean_t do_get_wepkeyid(int fd); 249 static boolean_t do_get_encryption(int fd); 250 static boolean_t do_get_authmode(int fd); 251 static boolean_t do_get_powermode(int fd); 252 static boolean_t do_get_rates(int fd); 253 static boolean_t do_get_wlanlist(int fd); 254 static boolean_t do_get_linkstatus(int fd); 255 static boolean_t do_get_channel(int fd); 256 static boolean_t do_get(int fd, int argc, char **argv); 257 static boolean_t do_set(int fd, int argc, char **argv); 258 static boolean_t do_createprofile(int fd, int argc, char **argv); 259 static boolean_t value_is_valid(config_item_t item, const char *value); 260 261 typedef struct cmd_ops { 262 char cmd[32]; 263 boolean_t (*p_do_func)(int fd, int argc, char **argv); 264 boolean_t b_auth; 265 boolean_t b_fileonly; /* operation only on the config file */ 266 boolean_t b_readonly; /* only read from the card or config file */ 267 } cmd_ops_t; 268 static cmd_ops_t do_func[] = { 269 { 270 "autoconf", 271 do_autoconf, 272 B_TRUE, 273 B_FALSE, 274 B_FALSE 275 }, 276 { 277 "startconf", 278 do_startconf, 279 B_TRUE, 280 B_FALSE, 281 B_TRUE 282 }, 283 { 284 "connect", 285 do_loadpf, 286 B_TRUE, 287 B_FALSE, 288 B_FALSE 289 }, 290 { 291 "disconnect", 292 do_disconnect, 293 B_TRUE, 294 B_FALSE, 295 B_FALSE 296 }, 297 { 298 "showprofile", 299 do_printpf, 300 B_FALSE, 301 B_TRUE, 302 B_TRUE 303 }, 304 { 305 "deleteprofile", 306 do_deletepf, 307 B_TRUE, 308 B_TRUE, 309 B_FALSE 310 }, 311 { 312 "history", 313 do_history, 314 B_FALSE, 315 B_TRUE, 316 B_TRUE 317 }, 318 { 319 "listprefer", 320 do_lsprefer, 321 B_FALSE, 322 B_TRUE, 323 B_TRUE 324 }, 325 { 326 "removeprefer", 327 do_rmprefer, 328 B_TRUE, 329 B_TRUE, 330 B_FALSE 331 }, 332 { 333 "setprefer", 334 do_setprefer, 335 B_TRUE, 336 B_TRUE, 337 B_FALSE 338 }, 339 { 340 "setwepkey", 341 do_wepkey, 342 B_TRUE, 343 B_FALSE, 344 B_FALSE 345 }, 346 { 347 "restoredef", 348 do_restoredef, 349 B_TRUE, 350 B_FALSE, 351 B_FALSE 352 }, 353 { 354 "getparam", 355 do_get, 356 B_FALSE, 357 B_FALSE, 358 B_TRUE 359 }, 360 { 361 "setparam", 362 do_set, 363 B_TRUE, 364 B_FALSE, 365 B_FALSE 366 }, 367 { 368 "createprofile", 369 do_createprofile, 370 B_TRUE, 371 B_TRUE, 372 B_FALSE 373 }, 374 { 375 "scan", 376 do_wlanlist, 377 B_FALSE, 378 B_FALSE, 379 B_FALSE 380 }, 381 { 382 "showstatus", 383 do_showstatus, 384 B_FALSE, 385 B_FALSE, 386 B_TRUE 387 }, 388 { 389 "setprofileparam", 390 do_setprofparam, 391 B_TRUE, 392 B_TRUE, 393 B_FALSE 394 }, 395 { 396 "getprofileparam", 397 do_getprofparam, 398 B_FALSE, 399 B_TRUE, 400 B_TRUE 401 }, 402 { 403 "setprofilewepkey", 404 do_setprofwepkey, 405 B_TRUE, 406 B_TRUE, 407 B_FALSE 408 } 409 }; 410 411 412 typedef enum {RW, RO, WO} rw_property_t; 413 typedef struct gs_ops { 414 config_item_t index; 415 char cmd[32]; 416 boolean_t (*p_do_get_func)(int fd); 417 boolean_t (*p_do_set_func)(int fd, const char *arg); 418 rw_property_t rw; 419 } gs_ops_t; 420 static gs_ops_t do_gs_func[] = { 421 {LINKSTATUS, "linkstatus", NULL, NULL, RO}, 422 {BSSID, "bssid", do_get_bssid, NULL, RO}, 423 {ESSID, "essid", do_get_essid, do_set_essid, RW}, 424 {BSSTYPE, "bsstype", do_get_bsstype, do_set_bsstype, RW}, 425 {CREATEIBSS, "createibss", do_get_createibss, do_set_createibss, RW}, 426 {CHANNEL, "channel", do_get_channel, do_set_channel, RW}, 427 {RATES, "rates", do_get_rates, do_set_rates, RW}, 428 {POWERMODE, "powermode", do_get_powermode, do_set_powermode, RW}, 429 {AUTHMODE, "authmode", do_get_authmode, do_set_authmode, RW}, 430 {ENCRYPTION, "encryption", do_get_encryption, do_set_encryption, RW}, 431 {WEPKEYID, "wepkeyindex", do_get_wepkeyid, do_set_wepkeyid, RW}, 432 {WEPKEY, "wepkey|1-4", NULL, do_set_wepkey, WO}, 433 {SIGNAL, "signal", do_get_signal, NULL, RO}, 434 {RADIOON, "radio", do_get_radioon, do_set_radioon, RW}, 435 }; 436 437 #define N_FUNC sizeof (do_func) / sizeof (cmd_ops_t) 438 #define N_GS_FUNC sizeof (do_gs_func) / sizeof (gs_ops_t) 439 440 /* 441 * valid rate value 442 */ 443 typedef struct wifi_rates_tab { 444 char *rates_s; 445 uint8_t rates_i; 446 uint8_t rates_reserve0; 447 uint8_t rates_reserve1; 448 uint8_t rates_reserve2; 449 } wifi_rates_tab_t; 450 451 /* 452 * the rates value is in increments of 500kb/s. 453 * according to the 802.11 a/b/g specs(IEEE): 454 * 802.11b(IEEE Std 802.11b-1999) page35, rates should be: 455 * X02, X04, X0b, X16 456 * 802.11a(IEEE Std 802.11a-1999) page47, rates should be: 457 * 6,9,12,18,24,36,48,54 Mb/s 458 * 802.11g(IEEE Std 802.11g-2003) page44, rates should be: 459 * 1,2,5.5,11,6,9,12,18,22,24,33,36,48,54 Mb/s 460 */ 461 #define WIFI_RATES_NUM 14 462 static wifi_rates_tab_t wifi_rates_s[WIFI_RATES_NUM] = { 463 {"1", WL_RATE_1M, 0, 0, 0}, 464 {"2", WL_RATE_2M, 0, 0, 0}, 465 {"5.5", WL_RATE_5_5M, 0, 0, 0}, 466 {"6", WL_RATE_6M, 0, 0, 0}, 467 {"9", WL_RATE_9M, 0, 0, 0}, 468 {"11", WL_RATE_11M, 0, 0, 0}, 469 {"12", WL_RATE_12M, 0, 0, 0}, 470 {"18", WL_RATE_18M, 0, 0, 0}, 471 {"22", WL_RATE_22M, 0, 0, 0}, 472 {"24", WL_RATE_24M, 0, 0, 0}, 473 {"33", WL_RATE_33M, 0, 0, 0}, 474 {"36", WL_RATE_36M, 0, 0, 0}, 475 {"48", WL_RATE_48M, 0, 0, 0}, 476 {"54", WL_RATE_54M, 0, 0, 0} 477 }; 478 /* print the error message on why set or get ioctl command failed. */ 479 static void 480 print_error(uint32_t errorno) 481 { 482 char *buf; 483 484 switch (errorno) { 485 case WL_SUCCESS: 486 buf = gettext("command succeeded"); 487 break; 488 case WL_NOTSUPPORTED: 489 case WL_LACK_FEATURE: 490 case WL_HW_ERROR: 491 case WL_ACCESS_DENIED: 492 buf = strerror(errorno); 493 break; 494 case WL_READONLY: 495 buf = gettext("parameter read-only"); 496 break; 497 case WL_WRITEONLY: 498 buf = gettext("parameter write-only"); 499 break; 500 case WL_NOAP: 501 buf = gettext("no access point available"); 502 break; 503 default: 504 buf = gettext("unknown error"); 505 break; 506 } 507 (void) fprintf(stderr, "%s\n", buf); 508 } 509 510 static void * 511 safe_malloc(size_t size) 512 { 513 void *buf; 514 515 buf = malloc(size); 516 if (buf == NULL) { 517 (void) fprintf(stderr, gettext("%s: malloc: %s\n"), 518 gExecName, strerror(errno)); 519 exit(WIFI_FATAL_ERR); 520 } 521 return (buf); 522 } 523 524 static void * 525 safe_calloc(size_t nelem, size_t elsize) 526 { 527 void *buf; 528 529 buf = calloc(nelem, elsize); 530 if (buf == NULL) { 531 (void) fprintf(stderr, gettext("%s: calloc: %s\n"), 532 gExecName, strerror(errno)); 533 exit(WIFI_FATAL_ERR); 534 } 535 return (buf); 536 } 537 538 static char * 539 safe_strdup(const char *s1) 540 { 541 char *p; 542 543 p = strdup(s1); 544 if (p == NULL) { 545 (void) fprintf(stderr, gettext("%s: strdup: %s\n"), 546 gExecName, strerror(errno)); 547 exit(WIFI_FATAL_ERR); 548 } 549 return (p); 550 } 551 552 static void 553 safe_snprintf(char *s, size_t n, const char *format, ...) 554 { 555 int len; 556 va_list ap; 557 va_start(ap, format); 558 559 len = vsnprintf(s, n, format, ap); 560 if ((len <= 0) || (len > n - 1)) { 561 (void) fprintf(stderr, 562 gettext("%s: snprintf: %s\n"), 563 gExecName, strerror(errno)); 564 exit(WIFI_FATAL_ERR); 565 } 566 va_end(ap); 567 } 568 569 static void 570 safe_fclose(FILE *stream) 571 { 572 int err; 573 574 err = fclose(stream); 575 if (err == EOF) { 576 (void) fprintf(stderr, gettext("%s: fclose: %s\n"), 577 gExecName, strerror(errno)); 578 exit(WIFI_FATAL_ERR); 579 } 580 } 581 /* 582 * new_ae: Add an element with content pointed by arg to the list *ael. 583 */ 584 static void 585 new_ae(aelist_t *ael, const char *arg) 586 { 587 ae_t *pae = NULL; 588 589 PRTDBG(("new_ae(0x%x, \"%s\")\n", ael, arg)); 590 assert((ael != NULL) && (arg != NULL)); 591 592 pae = safe_calloc(sizeof (*pae), 1); 593 pae->ae_arg = safe_strdup(arg); 594 pae->ae_next = NULL; 595 596 if (ael->ael_tail == NULL) { 597 ael->ael_head = pae; 598 } else { 599 ael->ael_tail->ae_next = pae; 600 } 601 ael->ael_tail = pae; 602 ael->ael_argc++; 603 } 604 /* 605 * new_ael: Create a new aelist with list_type "type" 606 * and return the list pointer. 607 */ 608 static aelist_t * 609 new_ael(list_type_t type) 610 { 611 aelist_t *plist; 612 613 plist = safe_calloc(sizeof (*plist), 1); 614 plist->type = type; 615 plist->ael_argc = 0; 616 plist->ael_head = plist->ael_tail = NULL; 617 618 PRTDBG(("new_ael(%d) = 0x%x\n", type, plist)); 619 return (plist); 620 } 621 622 /* 623 * new_config_file: Creates a new config_file_t struct which is counterpart of 624 * of the configration file, and return the pointer. 625 */ 626 static config_file_t * 627 new_config_file() 628 { 629 config_file_t *p_config_file; 630 631 p_config_file = safe_calloc(sizeof (config_file_t), 1); 632 p_config_file->section_argc = 0; 633 p_config_file->section_head = p_config_file->section_tail = NULL; 634 635 PRTDBG(("new_config_file() = 0x%x\n", p_config_file)); 636 return (p_config_file); 637 } 638 639 /* 640 * new_section: Add a list pointed by "p_list", with identity "section_id" to 641 * the config_file_t struct pointed by "p_config_file" 642 */ 643 static void 644 new_section(config_file_t *p_config_file, aelist_t *p_list, 645 const char *section_id) 646 { 647 section_t *p_section = NULL; 648 649 PRTDBG(("new_section(0x%x, 0x%x, \"%s\")\n", p_config_file, p_list, 650 section_id)); 651 assert((p_config_file != NULL) && (p_list != NULL) && 652 (section_id != NULL)); 653 654 p_section = safe_calloc(sizeof (*p_section), 1); 655 p_section->list = p_list; 656 p_section->section_next = NULL; 657 p_section->section_id = safe_strdup(section_id); 658 659 if (p_config_file->section_tail == NULL) { 660 p_config_file->section_head = p_section; 661 } else { 662 p_config_file->section_tail->section_next = p_section; 663 } 664 p_config_file->section_tail = p_section; 665 p_config_file->section_argc++; 666 } 667 668 /* 669 * destroy_config:Destroy the config_file struct 670 */ 671 static void 672 destroy_config(config_file_t *p_config_file) 673 { 674 section_t *p_section = NULL; 675 aelist_t *p_list = NULL; 676 ae_t *pae = NULL; 677 678 PRTDBG(("destory_config(0x%x)\n", p_config_file)); 679 assert(p_config_file != NULL); 680 681 p_section = p_config_file->section_head; 682 while (p_section != NULL) { 683 p_list = p_section->list; 684 if (p_list != NULL) { 685 pae = p_list->ael_head; 686 while (pae != NULL) { 687 if (pae->ae_arg != NULL) 688 free(pae->ae_arg); 689 pae->ae_arg = NULL; 690 pae = pae->ae_next; 691 free(p_list->ael_head); 692 p_list->ael_head = pae; 693 } 694 free(p_list); 695 p_list = NULL; 696 } 697 if (p_section->section_id != NULL) 698 free(p_section->section_id); 699 p_section->section_id = NULL; 700 p_section = p_section->section_next; 701 free(p_config_file->section_head); 702 p_config_file->section_head = p_section; 703 } 704 free(p_config_file); 705 p_config_file = NULL; 706 } 707 708 /* 709 * parse_file: Parse each section of the configration file 710 * and construct the config_file_t structure. 711 * Example: 712 * A config file has contents below: 713 * 714 * {preferrence} 715 * essid=ap7-3 716 * essid=linksys 717 * 718 * {history} 719 * essid=ap7-3 720 * essid=ap7-2 721 * 722 * [ap7-3] 723 * essid=ap7-3 724 * wepkeyid=3 725 * channel=11 726 * rates=1,2 727 * 728 * [linksys] 729 * essid=linksys 730 * createibss=BSS 731 * authmode=OPENSYSTEM 732 * wepkeyid=1 733 * 734 * then its config_file_t structure will be: 735 * 736 * config_file_t 737 * |~~~~~~~~~~~~~~~~~~~~~~~~~~| 738 * | section_argc=5 | 739 * |~~~~~~~~~~~~T~~~~~~~~~~~~~| 740 * /| *head | *tail |\ 741 * / ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \ 742 * / \ 743 * / \ 744 * / \ 745 * / \ 746 * / \ 747 * section_t V section_t V section_t 748 * |~~~~~~~~~~~~~~~|~~| |~~~~~~~~~~~~~~~|~~| |~~~~~~~~~~~~~~|~~| 749 * |"{preferrence}"| | | "{history}" | | | "[linksys]" | | 750 * |~~~~~~~~~~~~~~~| -+---->|~~~~~~~~~~~~~~~| -+->..->|~~~~~~~~~~~~~~| -+->NULL 751 * | *list | | | *list | | | *list | | 752 * ~~T~~~~~~~~~~~~~~~~~ ~~~T~~~~~~~~~~~~~~~~ ~~~T~~~~~~~~~~~~~~~ 753 * | | | 754 * | | | 755 * V aelist_t V aelist_t V aelist_t 756 * |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| 757 * | argc=2 | | argc=3 | | argc=4 | 758 * |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| 759 * |PREFFERRENCE | | HISTORY | | PROFILE | 760 * |~~~~~~T~~~~~~| |~~~~~~T~~~~~~| |~~~~~~T~~~~~~| 761 * |*head |*tail |\ |*head |*tail |\ |*head |*tail | 762 * ~~T~~~~~~~~~~~~ \ ~~T~~~~~~~~~~~~ \ /~~~~~~~~~~~~~~~\ 763 * | \ V V / \ 764 * | \ ... ... / \ 765 * V ae_t V ae_t ae_t V ae_t V 766 * |~~~~~~~~~T~~| |~~~~~~~~~T~~| |~~~~~~~~~T~~| |~~~~~~~~~T~~| 767 * |"essid= | -+->|"essid= | -+->NULL |"essid= | -+->..->|"wepkeyid| -+->NULL 768 * | ap7-3" | | | linksys"| | | linksys"| | | =1" | | 769 * ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ 770 * 771 */ 772 773 static config_file_t * 774 parse_file(const char *pfile) 775 { 776 FILE *file = NULL; 777 int fd = 0; 778 char buf_line[256]; 779 config_file_t *p_config_file; 780 list_type_t cur_list = OTHER; 781 aelist_t *prefer_list = NULL; 782 aelist_t *history_list = NULL; 783 aelist_t *profile_list = NULL; 784 aelist_t *activep_list = NULL; 785 786 assert(pfile != NULL); 787 /* 788 * The files /etc/inet/wifi and /etc/inet/secret/wifiwepkey should 789 * be opened with "r" attribute. If these two files do not exist, 790 * create them here. 791 */ 792 file = fopen(pfile, "r"); 793 794 if (file == NULL) { 795 fd = open(pfile, O_CREAT|O_EXCL|O_RDWR, 0600); 796 if (fd < 0) { 797 (void) fprintf(stderr, gettext("%s: failed to open %s" 798 "\n"), gExecName, pfile); 799 goto error1; 800 } 801 file = fdopen(fd, "w"); 802 (void) chmod(pfile, S_IRUSR); 803 } 804 805 p_config_file = new_config_file(); 806 807 while (fgets(buf_line, sizeof (buf_line), file) != NULL) { 808 if ((buf_line[0] == '\n') || (buf_line[0] == ' ')) 809 continue; 810 /* replace the old '\n' to '\0' */ 811 buf_line[strlen(buf_line) - 1] = '\0'; 812 if (strstr(buf_line, WIFI_PREFER) == buf_line) { 813 if (prefer_list == NULL) { 814 cur_list = PREFERENCE; 815 prefer_list = new_ael(PREFERENCE); 816 new_section(p_config_file, prefer_list, 817 WIFI_PREFER); 818 } else { 819 (void) fprintf(stderr, gettext("%s: " 820 "%s : duplicated %s section\n"), 821 gExecName, pfile, WIFI_PREFER); 822 goto error; 823 } 824 } else if (strstr(buf_line, WIFI_HISTORY) == buf_line) { 825 if (history_list == NULL) { 826 cur_list = HISTORY; 827 history_list = new_ael(HISTORY); 828 new_section(p_config_file, history_list, 829 WIFI_HISTORY); 830 } else { 831 (void) fprintf(stderr, gettext("%s: " 832 "%s : duplicated %s section\n"), 833 gExecName, pfile, WIFI_HISTORY); 834 goto error; 835 } 836 } else if (strstr(buf_line, WIFI_ACTIVEP) == buf_line) { 837 if (activep_list == NULL) { 838 cur_list = ACTIVEP; 839 activep_list = new_ael(ACTIVEP); 840 new_section(p_config_file, activep_list, 841 WIFI_ACTIVEP); 842 } else { 843 (void) fprintf(stderr, gettext("%s: " 844 "%s : duplicated %s section\n"), 845 gExecName, pfile, WIFI_ACTIVEP); 846 goto error; 847 } 848 } else if ((strchr(buf_line, '[') == buf_line) && 849 (buf_line[strlen(buf_line) - 1] == ']')) { 850 cur_list = PROFILE; 851 profile_list = new_ael(PROFILE); 852 new_section(p_config_file, profile_list, 853 buf_line); 854 } else { 855 switch (cur_list) { 856 case PREFERENCE: 857 if (prefer_list->ael_argc <= 858 MAX_PREFERENCE_NUM) 859 new_ae(prefer_list, buf_line); 860 break; 861 case HISTORY: 862 if (history_list->ael_argc <= 863 MAX_HISTORY_NUM) 864 new_ae(history_list, buf_line); 865 break; 866 case ACTIVEP: 867 if ((activep_list->ael_argc <= 1) && 868 (strpbrk(buf_line, "=") != NULL)) 869 new_ae(activep_list, buf_line); 870 break; 871 case PROFILE: 872 if (strpbrk(buf_line, "=") != NULL) 873 new_ae(profile_list, buf_line); 874 break; 875 default: 876 (void) fprintf(stderr, 877 gettext("%s: %s: file format error\n"), 878 gExecName, pfile); 879 goto error; 880 } 881 } 882 } 883 PRTDBG(("parse_file(\"%s\")=0x%x\n", pfile, p_config_file)); 884 (void) fclose(file); 885 return (p_config_file); 886 error: 887 destroy_config(p_config_file); 888 (void) fclose(file); 889 error1: 890 return (NULL); 891 } 892 /* 893 * construct an argument vector from an aelist 894 */ 895 static char ** 896 aeltoargv(aelist_t *ael, int *ael_num) 897 { 898 ae_t *ae = NULL; 899 char **argv = NULL; 900 int argc = 0; 901 902 PRTDBG(("aeltoargv(%x)\n", ael)); 903 assert(ael != NULL); 904 905 argv = safe_calloc(sizeof (*argv), ael->ael_argc); 906 907 for (argc = 0, ae = ael->ael_head; ae; ae = ae->ae_next) { 908 /* skip bssid since it can not be set */ 909 if (strncmp(ae->ae_arg, "bssid=", strlen("bssid=")) == 0) 910 continue; 911 argv[argc] = safe_strdup(ae->ae_arg); 912 argc++; 913 if (ae == ael->ael_tail) 914 break; 915 } 916 917 PRTDBG(("aeltoargv(0x%x) = 0x%x\n\n", ael, argv)); 918 *ael_num = argc; 919 return (argv); 920 } 921 922 /* 923 * archived contents into a file 924 */ 925 static boolean_t 926 fprint_config_file(config_file_t *p_config_file, const char *file_name) 927 { 928 FILE *file = NULL; 929 int fd = 0; 930 int len; 931 section_t *p_section = NULL; 932 aelist_t *p_list = NULL; 933 ae_t *pae = NULL; 934 char temp_file[256]; 935 struct stat buf; 936 937 PRTDBG(("fprint_config_file(0x%x, \"%s\")\n", p_config_file, 938 file_name)); 939 assert((p_config_file != NULL)&&(strcmp(file_name, "") != 0)); 940 941 safe_snprintf(temp_file, sizeof (temp_file), 942 "%s.tmp", file_name); 943 fd = open(temp_file, O_CREAT|O_WRONLY|O_TRUNC, 0600); 944 if (fd < 0) { 945 (void) fprintf(stderr, gettext("%s: failed to open %s\n"), 946 gExecName, temp_file); 947 return (B_FALSE); 948 } 949 file = fdopen(fd, "w"); 950 951 p_section = p_config_file->section_head; 952 while (p_section != NULL) { 953 p_list = p_section->list; 954 if (p_list != NULL) { 955 PRTDBG(("fprint_config_file: section_id=%s\n", 956 p_section->section_id)); 957 len = fprintf(file, "\n%s\n", p_section->section_id); 958 if (len < 0) { 959 (void) fprintf(stderr, gettext("%s: " 960 "failed to update %s: %s\n"), 961 gExecName, file_name, strerror(errno)); 962 safe_fclose(file); 963 return (B_FALSE); 964 } 965 pae = p_list->ael_head; 966 while (pae != NULL) { 967 if (pae->ae_arg != NULL) { 968 len = fprintf(file, "%s\n", 969 pae->ae_arg); 970 if (len < 0) { 971 (void) fprintf(stderr, 972 gettext("%s: failed to " 973 "update %s: %s\n"), 974 gExecName, file_name, 975 strerror(errno)); 976 safe_fclose(file); 977 return (B_FALSE); 978 } 979 } 980 pae = pae->ae_next; 981 } 982 } 983 p_section = p_section->section_next; 984 } 985 safe_fclose(file); 986 /* 987 * The attribute of the file /etc/inet/wifi and 988 * /etc/inet/security/wifiwepkey should be retained. 989 * if those file do not exist, set default file mode. 990 */ 991 if (stat(file_name, &buf) != 0) { 992 if (errno == ENOENT) { 993 buf.st_mode = 0600; 994 } else { 995 (void) fprintf(stderr, gettext("%s: failed to get " 996 "file %s stat: %s\n"), 997 gExecName, file_name, strerror(errno)); 998 return (B_FALSE); 999 } 1000 } 1001 if (rename(temp_file, file_name) != 0) { 1002 (void) fprintf(stderr, gettext("%s: failed to update %s: %s" 1003 "\n"), gExecName, file_name, strerror(errno)); 1004 return (B_FALSE); 1005 } 1006 (void) chmod(file_name, buf.st_mode); 1007 return (B_TRUE); 1008 } 1009 /* 1010 * append_pa: Each section holds a section_id which identifies a section 1011 * a profile uses its essid appending "[]" to denote its section_id. 1012 * note: new memory is allocated, remember to free. 1013 */ 1014 static char * 1015 append_pa(const char *arg) 1016 { 1017 char *pbuf = NULL; 1018 int len; 1019 1020 assert(arg != NULL); 1021 1022 len = strlen(arg) + 3; 1023 pbuf = safe_malloc(len); 1024 safe_snprintf(pbuf, len, "[%s]", arg); 1025 PRTDBG(("append_pa(\"%s\") = \"%s\"\n", arg, pbuf)); 1026 return (pbuf); 1027 } 1028 /* 1029 * find a section by section_id from p_config_file, 1030 * return the section pointer. 1031 */ 1032 static section_t * 1033 find_section(config_file_t *p_config_file, const char *section_id) 1034 { 1035 section_t *p_section = NULL; 1036 1037 PRTDBG(("find_section(0x%x, \"%s\")\n", p_config_file, section_id)); 1038 assert((section_id != NULL)&&(p_config_file != NULL)); 1039 1040 p_section = p_config_file->section_head; 1041 1042 while (p_section != NULL) { 1043 if ((p_section->section_id != NULL) && 1044 (strcmp(p_section->section_id, section_id) == 0)) 1045 return (p_section); 1046 p_section = p_section->section_next; 1047 } 1048 return (NULL); 1049 } 1050 1051 /* 1052 * get_value: Get rid of "parameter=" from a "parameter=value", for example: 1053 * when we read an line from file, we gets "essid=ap7-2", this function 1054 * returns the pointer to string "ap7-2"; 1055 */ 1056 1057 static const char * 1058 get_value(const char *arg) 1059 { 1060 char *p; 1061 assert(arg != NULL); 1062 1063 p = strchr(arg, '='); 1064 PRTDBG(("get_value(\"%s\") = \"%s\"\n", arg, p + 1)); 1065 if (p != NULL) 1066 return (p + 1); 1067 else 1068 return (NULL); 1069 } 1070 1071 /* 1072 * search /dev/wifi to see which interface is available 1073 */ 1074 static boolean_t 1075 search_interface(char *interface) 1076 { 1077 DIR *dirp; 1078 struct dirent *dp; 1079 char buf[256]; 1080 int fd; 1081 1082 PRTDBG(("search interface\n")); 1083 assert(interface != NULL); 1084 1085 /* 1086 * Try to return the first found wifi interface. 1087 * If no wifi interface is available, return B_FALSE 1088 */ 1089 1090 if ((dirp = opendir("/dev/wifi")) == NULL) { 1091 PRTDBG(("failed to open '/dev/wifi'\n")); 1092 return (B_FALSE); 1093 } 1094 while ((dp = readdir(dirp)) != NULL) { 1095 if (strcmp(dp->d_name, ".") == 0 || 1096 strcmp(dp->d_name, "..") == 0) 1097 continue; 1098 if (dp->d_name[strlen(dp->d_name) - 1] < '0' || 1099 dp->d_name[strlen(dp->d_name) - 1] > '9') 1100 continue; 1101 safe_snprintf(buf, sizeof (buf), "%s%s", 1102 "/dev/wifi/", dp->d_name); 1103 fd = open(buf, O_RDWR); 1104 if (fd == -1) { 1105 PRTDBG(("interface %s doesn't exist\n", dp->d_name)); 1106 continue; 1107 } else { 1108 PRTDBG(("interface %s is the first found interface\n", 1109 dp->d_name)); 1110 (void) strlcpy(interface, buf, LIFNAMSIZ); 1111 (void) close(fd); 1112 (void) closedir(dirp); 1113 return (B_TRUE); 1114 } 1115 } 1116 1117 PRTDBG(("failed to find available wireless interface\n")); 1118 (void) closedir(dirp); 1119 return (B_FALSE); 1120 1121 } 1122 /* 1123 * open_dev: Open the driver. 1124 * if the 'devname' has format like 'ath0', we should add the path to that 1125 * device(/dev/ath0) and open it; if the 'devname' has format like 1126 * '/dev/wifi/ath0', we open it directly. 1127 */ 1128 static int 1129 open_dev(char *devname) 1130 { 1131 int fd; 1132 int len; 1133 char *pbuf = NULL; 1134 1135 PRTDBG(("open_dev(\"%s\")\n", devname)); 1136 assert(devname != NULL); 1137 /* 1138 * If the devname is got from the user input, we 1139 * add '/dev/' to that relative devname. If it 1140 * is got from the 'search interface', it is an 1141 * absolute path. 1142 */ 1143 if (strncmp(devname, "/dev/wifi/", strlen("/dev/wifi/")) == 0) { 1144 pbuf = safe_strdup(devname); 1145 } else { 1146 len = strlen(devname) + strlen("/dev/") + 1; 1147 pbuf = safe_malloc(len); 1148 safe_snprintf(pbuf, len, "/dev/%s", devname); 1149 } 1150 fd = open(pbuf, O_RDWR); 1151 free(pbuf); 1152 1153 if (fd == -1) { 1154 (void) fprintf(stderr, gettext("%s: failed to open '%s': %s" 1155 "\n"), gExecName, devname, strerror(errno)); 1156 return (-1); 1157 } 1158 if (!isastream(fd)) { 1159 (void) fprintf(stderr, gettext("%s: %s is " 1160 "not a stream device\n"), 1161 gExecName, devname); 1162 (void) close(fd); 1163 return (-1); 1164 } 1165 return (fd); 1166 } 1167 /* 1168 * call_ioctl: Fill strioctl structure and issue an ioctl system call 1169 */ 1170 static boolean_t 1171 call_ioctl(int fd, int cmd, uint32_t params, uint32_t buf_len) 1172 { 1173 struct strioctl stri; 1174 1175 PRTDBG(("call_ioctl_gs(%d, 0x%x, 0x%x, 0x%x)\n", 1176 fd, cmd, params, buf_len)); 1177 1178 switch (cmd) { 1179 case WLAN_GET_PARAM: 1180 (void) memset(gbuf, 0, MAX_BUF_LEN); 1181 stri.ic_len = MAX_BUF_LEN; 1182 break; 1183 case WLAN_SET_PARAM: 1184 gbuf->wldp_length = buf_len + WIFI_BUF_OFFSET; 1185 stri.ic_len = gbuf->wldp_length; 1186 break; 1187 case WLAN_COMMAND: 1188 gbuf->wldp_length = sizeof (wldp_t); 1189 stri.ic_len = gbuf->wldp_length; 1190 break; 1191 default: 1192 (void) fprintf(stderr, gettext("%s: ioctl : " 1193 "unsupported ioctl command\n"), gExecName); 1194 return (B_FALSE); 1195 } 1196 gbuf->wldp_type = NET_802_11; 1197 gbuf->wldp_id = params; 1198 1199 stri.ic_cmd = cmd; 1200 stri.ic_timout = 0; 1201 stri.ic_dp = (char *)gbuf; 1202 1203 if (ioctl(fd, I_STR, &stri) == -1) { 1204 gbuf->wldp_result = 0xffff; 1205 return (B_FALSE); 1206 } 1207 if (cmd == WLAN_COMMAND) { 1208 return (B_TRUE); 1209 } else { 1210 return (gbuf->wldp_result != WL_SUCCESS ? 1211 B_FALSE:B_TRUE); 1212 } 1213 } 1214 1215 /* 1216 * del_prefer: Delete an item from the {preferrence} list, the idea is 1217 * simply free the ae_t element, and set ae_arg to NULL, then when archive 1218 * the config_file_t struct to the file, it will be delete. 1219 * The last flag is used to identify whether this function is invoked due to 1220 * the 'removeprefer' subcommand or due to 'deleteprofile' subcommand. 1221 */ 1222 static boolean_t 1223 del_prefer(config_file_t *p_config_file, const char *prefer, boolean_t rflag) 1224 { 1225 section_t *p_section = NULL; 1226 aelist_t *plist = NULL; 1227 ae_t *pae = NULL; 1228 int i = 0, position = 0; 1229 int number; 1230 ae_t *prm_ae = NULL; 1231 1232 PRTDBG(("del_prefer(0x%x, \"%s\")\n", p_config_file, prefer)); 1233 assert((prefer != NULL)&&(p_config_file != NULL)); 1234 1235 p_section = find_section(p_config_file, WIFI_PREFER); 1236 if (p_section != NULL) 1237 plist = p_section->list; 1238 1239 if ((p_section == NULL) || (plist == NULL)) 1240 return (B_FALSE); 1241 1242 number = plist->ael_argc; 1243 pae = plist->ael_head; 1244 prm_ae = plist->ael_head; 1245 while (pae != NULL) { 1246 if (strcmp(prefer, pae->ae_arg) == 0) { 1247 free(pae->ae_arg); 1248 pae->ae_arg = NULL; /* mark */ 1249 if (!position) { 1250 plist->ael_head = pae->ae_next; 1251 if (pae->ae_next == NULL) 1252 plist->ael_tail = NULL; 1253 } else { 1254 for (i = 0; i < position - 1; i++) 1255 prm_ae = prm_ae->ae_next; 1256 prm_ae->ae_next = pae->ae_next; 1257 if (pae->ae_next == NULL) 1258 plist->ael_tail = prm_ae; 1259 } 1260 free(pae); 1261 pae = NULL; 1262 plist->ael_argc--; 1263 break; 1264 } 1265 position++; 1266 pae = pae->ae_next; 1267 } 1268 if ((number == plist->ael_argc) && (rflag == B_TRUE)) { 1269 (void) fprintf(stderr, gettext("%s: removeprefer : " 1270 "no such profile: '%s' in the preference list\n"), 1271 gExecName, prefer); 1272 return (B_FALSE); 1273 } 1274 return (B_TRUE); 1275 } 1276 1277 /* 1278 * del_section: Delete an section from p_config_file, the idea is 1279 * simply free the aelist_t struct and set it to NULL, when archiving 1280 * config_file_t struct to the file, we will find section list is NULL, 1281 * and will not write it to file, so it will be deleted. 1282 */ 1283 static boolean_t 1284 del_section(config_file_t *p_config_file, char *section_id) 1285 { 1286 section_t *p_section = NULL; 1287 section_t *prm_section = NULL; 1288 aelist_t *plist = NULL; 1289 ae_t *pae = NULL; 1290 int i = 0, position = 0; 1291 1292 PRTDBG(("del_section(0x%x, \"%s\")\n", p_config_file, section_id)); 1293 PRTDBG(("del_section: %d section(s) in config file\n", 1294 p_config_file->section_argc)); 1295 assert((section_id != NULL)&&(p_config_file != NULL)); 1296 1297 if (find_section(p_config_file, section_id) == NULL) { 1298 return (B_FALSE); 1299 } 1300 p_section = p_config_file->section_head; 1301 prm_section = p_config_file->section_head; 1302 while (p_section != NULL) { 1303 if (p_section->section_id != NULL) { 1304 if (strcmp(p_section->section_id, section_id) == 0) { 1305 plist = p_section->list; 1306 pae = plist->ael_head; 1307 while (pae != NULL) { 1308 free(pae->ae_arg); 1309 pae->ae_arg = NULL; 1310 pae = pae->ae_next; 1311 free(plist->ael_head); 1312 plist->ael_head = pae; 1313 } 1314 free(plist); 1315 p_section->list = NULL; 1316 free(p_section->section_id); 1317 p_section->section_id = NULL; 1318 1319 if (!position) { 1320 p_config_file->section_head = 1321 p_section->section_next; 1322 if (p_section->section_next == NULL) 1323 p_config_file->section_tail = 1324 NULL; 1325 } else { 1326 for (i = 0; i < position - 1; i++) { 1327 prm_section = 1328 prm_section->section_next; 1329 } 1330 prm_section->section_next = 1331 p_section->section_next; 1332 if (p_section->section_next == NULL) 1333 p_config_file->section_tail = 1334 prm_section; 1335 } 1336 free(p_section); 1337 p_config_file->section_argc--; 1338 break; 1339 } 1340 position++; 1341 } 1342 p_section = p_section->section_next; 1343 } 1344 return (B_TRUE); 1345 } 1346 1347 /* 1348 * set_prefer: Reorder the preferrence list. 1349 */ 1350 static boolean_t 1351 set_prefer(config_file_t *p_config_file, const char *prefer, int rank) 1352 { 1353 char *pbuf = NULL; 1354 aelist_t *plist = NULL; 1355 section_t *p_section = NULL; 1356 ae_t *pae = NULL; 1357 int i = 0, position = 0; 1358 ae_t *pae_move = NULL; 1359 1360 assert(prefer != NULL); 1361 PRTDBG(("set_prefer(0x%x, \"%s\", %d)\n", p_config_file, prefer, rank)); 1362 1363 pbuf = append_pa(prefer); 1364 if (find_section(p_config_file, pbuf) == NULL) { 1365 (void) fprintf(stderr, gettext("%s: setprefer: " 1366 "no such profile: '%s'\n"), 1367 gExecName, prefer); 1368 free(pbuf); 1369 return (B_FALSE); 1370 } 1371 free(pbuf); 1372 1373 p_section = find_section(p_config_file, WIFI_PREFER); 1374 1375 if (p_section == NULL) { 1376 plist = new_ael(PREFERENCE); 1377 new_section(p_config_file, plist, WIFI_PREFER); 1378 new_ae(plist, prefer); 1379 return (B_TRUE); 1380 } else { 1381 plist = p_section->list; 1382 } 1383 1384 pae = plist->ael_head; 1385 pae_move = plist->ael_head; 1386 while (pae != NULL) { 1387 if (strcmp(prefer, pae->ae_arg) == 0) { 1388 free(pae->ae_arg); 1389 pae->ae_arg = NULL; 1390 if (!position) { 1391 plist->ael_head = pae->ae_next; 1392 if (pae->ae_next == NULL) 1393 plist->ael_tail = NULL; 1394 } else { 1395 for (i = 0; i < position - 1; i++) 1396 pae_move = pae_move->ae_next; 1397 pae_move->ae_next = pae->ae_next; 1398 if (pae->ae_next == NULL) 1399 plist->ael_tail = pae_move; 1400 } 1401 free(pae); 1402 plist->ael_argc--; 1403 break; 1404 } 1405 position++; 1406 pae = pae->ae_next; 1407 } 1408 PRTDBG(("set_prefer: %d Profiles in prefer list\n", plist->ael_argc)); 1409 if (rank > plist->ael_argc) { 1410 new_ae(plist, prefer); 1411 } else if (rank <= 1) { 1412 pae = safe_calloc(sizeof (ae_t), 1); 1413 pae->ae_arg = safe_strdup(prefer); 1414 pae->ae_next = plist->ael_head; 1415 plist->ael_head = pae; 1416 plist->ael_argc++; 1417 } else { 1418 pae_move = plist->ael_head; 1419 for (i = 1; i < rank-1; i++) { 1420 pae_move = pae_move->ae_next; 1421 } 1422 pae = safe_calloc(sizeof (ae_t), 1); 1423 pae->ae_arg = safe_strdup(prefer); 1424 pae->ae_next = pae_move->ae_next; 1425 pae_move->ae_next = pae; 1426 plist->ael_argc++; 1427 } 1428 /* 1429 * If number of prefer list items is larger than the MAX_PREFERENCE_NUM 1430 * delete those items whose No is larger than MAX_PREFERENCE_NUM. 1431 */ 1432 if (plist->ael_argc > MAX_PREFERENCE_NUM) { 1433 pae = plist->ael_head; 1434 while (pae->ae_next != plist->ael_tail) 1435 pae = pae->ae_next; 1436 free(plist->ael_tail->ae_arg); 1437 plist->ael_tail->ae_arg = NULL; 1438 free(plist->ael_tail); 1439 plist->ael_tail = pae; 1440 plist->ael_tail->ae_next = NULL; 1441 plist->ael_argc--; 1442 } 1443 PRTDBG(("set_prefer: %d Profiles in prefer list\n", plist->ael_argc)); 1444 return (B_TRUE); 1445 } 1446 /* 1447 * add_to_history: Save the scanlist argv into history section 1448 */ 1449 static void 1450 add_to_history(config_file_t *p_config_file, int argc, char **argv) 1451 { 1452 int i = 0, j = 0, pos = 0; 1453 aelist_t *plist = NULL; 1454 section_t *p_section = NULL; 1455 ae_t *pae = NULL; 1456 ae_t *pae_m = NULL; 1457 char item[256]; 1458 time_t cltime; 1459 1460 PRTDBG(("add_to_history(0x%x, %d, 0x%x)\n", p_config_file, argc, argv)); 1461 assert(p_config_file != NULL); 1462 1463 p_section = find_section(p_config_file, WIFI_HISTORY); 1464 1465 if (p_section == NULL) { 1466 plist = new_ael(HISTORY); 1467 new_section(p_config_file, plist, WIFI_HISTORY); 1468 } else { 1469 plist = p_section->list; 1470 } 1471 1472 if (plist != NULL) { 1473 for (i = 0; i < argc; i++) { 1474 if (!strlen(argv[i])) 1475 continue; 1476 pos = 0; 1477 pae = plist->ael_head; 1478 pae_m = plist->ael_head; 1479 /* 1480 * add time stamp to the history record 1481 */ 1482 cltime = time(&cltime); 1483 (void) snprintf(item, sizeof (item), "%s%c%ld", 1484 argv[i], ',', cltime); 1485 while (pae != NULL) { 1486 if (strncmp(item, pae->ae_arg, 1487 strlen(argv[i])) == 0) { 1488 free(pae->ae_arg); 1489 pae->ae_arg = NULL; 1490 if (!pos) { 1491 plist->ael_head = pae->ae_next; 1492 if (pae->ae_next == NULL) 1493 plist->ael_tail = NULL; 1494 } else { 1495 for (j = 0; j < pos - 1; j++) 1496 pae_m = pae_m->ae_next; 1497 pae_m->ae_next = pae->ae_next; 1498 if (pae->ae_next == NULL) 1499 plist->ael_tail = pae_m; 1500 } 1501 free(pae); 1502 plist->ael_argc--; 1503 break; 1504 } 1505 pos++; 1506 pae = pae->ae_next; 1507 } 1508 new_ae(plist, item); 1509 } 1510 1511 if (plist->ael_argc > MAX_HISTORY_NUM) { 1512 for (i = 0; i < plist->ael_argc - MAX_HISTORY_NUM; 1513 i++) { 1514 pae = plist->ael_head; 1515 free(pae->ae_arg); 1516 plist->ael_head = pae->ae_next; 1517 free(pae); 1518 } 1519 plist->ael_argc = MAX_HISTORY_NUM; 1520 } 1521 } 1522 } 1523 1524 static void 1525 do_print_usage() 1526 { 1527 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1528 " autoconf [wait={n|forever}]\n"), gExecName); 1529 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1530 " connect profile [wait={n|forever}]\n"), gExecName); 1531 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1532 " connect essid [wait={n|forever}]\n"), gExecName); 1533 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1534 " disconnect\n"), gExecName); 1535 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1536 " getparam [parameter [...]]\n"), gExecName); 1537 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1538 " setparam [parameter=value [...]]\n"), gExecName); 1539 (void) fprintf(stderr, gettext( 1540 "\tparameters:\n" 1541 "\t\tbssid\t\t - read only: 6 byte mac address of " 1542 "base station\n" 1543 "\t\tessid\t\t - name of the network, a string of up " 1544 "to 32 chars\n" 1545 "\t\tbsstype\t\t - bss(ap, infrastructure), ibss(ad-hoc)" 1546 " or auto\n" 1547 "\t\tcreateibss\t - flag to identify whether a ibss is to be\n" 1548 "\t\t\t\t created when the network to connect is\n" 1549 "\t\t\t\t not available, yes or no\n" 1550 "\t\tchannel\t\t - channel(used only when creating an ibss)\n" 1551 "\t\t\t\t valid value:\n" 1552 "\t\t\t\t\t 802.11a: 0-99\n" 1553 "\t\t\t\t\t 802.11b: 1-14\n" 1554 "\t\t\t\t\t 802.11g: 1-14\n" 1555 "\t\trates\t\t - set of rates, seperated by ',' valid rates:\n" 1556 "\t\t\t\t 1,2,5.5,6,9,11,12,18,22,24,33,36,48 and 54\n" 1557 "\t\tpowermode\t - off, mps or fast\n" 1558 "\t\tauthmode\t - opensystem or shared_key\n" 1559 "\t\tencryption\t - none or wep\n" 1560 "\t\twepkey|1-4\t - write only:\n" 1561 "\t\t\t\t 5 chars or 10 hex digits for 40bit wepkey;\n" 1562 "\t\t\t\t 13 chars or 26 hex digits for 128bit wepkey\n" 1563 "\t\twepkeyindex\t - an integer within the range 1-4\n" 1564 "\t\tsignal\t\t - read only: signal strength from 0 to 15\n" 1565 "\t\tradio\t\t - on or off\n")); 1566 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1567 " restoredef\n"), gExecName); 1568 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1569 " scan\n"), gExecName); 1570 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1571 " showstatus\n"), gExecName); 1572 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]" 1573 " setwepkey 1|2|3|4\n"), gExecName); 1574 1575 (void) fprintf(stderr, "\n"); 1576 1577 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1578 " createprofile profile parameter=value [...]\n"), gExecName); 1579 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1580 " deleteprofile profile1 [profile2 [...]]\n"), gExecName); 1581 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1582 " showprofile profile1 [profile2 [...]]\n"), gExecName); 1583 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1584 " setprofilewepkey profile 1|2|3|4\n"), gExecName); 1585 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1586 " getprofileparam profile [parameter [...]]\n"), gExecName); 1587 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1588 " setprofileparam profile [parameter=value [...]]\n"), gExecName); 1589 1590 (void) fprintf(stderr, "\n"); 1591 1592 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1593 " history\n"), gExecName); 1594 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1595 " listprefer\n"), gExecName); 1596 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1597 " removeprefer profile\n"), gExecName); 1598 (void) fprintf(stderr, gettext("\t%s [-R root_path]" 1599 " setprefer profile [n]\n"), gExecName); 1600 } 1601 1602 /* 1603 * do_print_support_params: Query interface which cmd is supported 1604 */ 1605 static boolean_t 1606 do_print_support_params(int fd) 1607 { 1608 int i = 0, n = 0; 1609 1610 PRTDBG(("do_print_support_params(\"%d\")\n", fd)); 1611 assert(fd != -1); 1612 1613 (void) printf(gettext("\t parameter\tproperty\n")); 1614 for (i = 0; i < N_GS_FUNC; i++) { 1615 gbuf->wldp_result = WL_LACK_FEATURE; 1616 if ((do_gs_func[i].p_do_get_func != NULL) && 1617 (do_gs_func[i].p_do_get_func(fd) != B_TRUE)) { 1618 continue; 1619 } 1620 if (gbuf->wldp_result == WL_SUCCESS) { 1621 (void) printf("\t%11s", do_gs_func[i].cmd); 1622 if (do_gs_func[i].rw == RO) 1623 (void) printf(gettext("\tread only\n")); 1624 else 1625 (void) printf(gettext("\tread/write\n")); 1626 n++; 1627 } 1628 } 1629 1630 return (n ? B_TRUE : B_FALSE); 1631 } 1632 1633 /* 1634 * check_authority: Check if command is permitted. 1635 */ 1636 static boolean_t 1637 check_authority(wifi_auth_t type) 1638 { 1639 struct passwd *pw = NULL; 1640 1641 PRTDBG(("check_authority()\n")); 1642 1643 pw = getpwuid(getuid()); 1644 if (pw == NULL) 1645 return (B_FALSE); 1646 if (chkauthattr(p_auth_string[type], pw->pw_name) == 0) { 1647 if (type == AUTH_WEP) 1648 (void) fprintf(stderr, gettext("%s: " 1649 "privilege '%s' is required for setting " 1650 "wepkey.\n"), gExecName, WIFI_WEP_AUTH); 1651 else 1652 (void) fprintf(stderr, gettext("%s: " 1653 "privilege '%s' is required.\n"), 1654 gExecName, WIFI_CONFIG_AUTH); 1655 return (B_FALSE); 1656 } else { 1657 return (B_TRUE); 1658 } 1659 } 1660 1661 /* 1662 * construct the 'history' and 'scan' output format 1663 * memory allocated. need to free after the function is invoked. 1664 */ 1665 static char * 1666 construct_format(uint32_t nt) 1667 { 1668 char *format; 1669 int len = 0, i; 1670 1671 #define FORMAT_LEN 256 1672 assert((nt >= 1) && (nt <= 4)); 1673 format = safe_malloc(FORMAT_LEN); 1674 1675 for (i = 0; i < nt; i++) 1676 len += snprintf(format + len, FORMAT_LEN - len, "\t"); 1677 if ((len <= 0) || (len > FORMAT_LEN - 1)) { 1678 return ("\t\t\t\t"); 1679 } 1680 return (format); 1681 } 1682 1683 /* 1684 * find the essid of the named profile. 1685 * gp_config_file is golable, so the return is gloable too. 1686 */ 1687 static const char * 1688 essid_of_profile(const char *profile) 1689 { 1690 section_t *p_section = NULL; 1691 aelist_t *plist = NULL; 1692 ae_t *pae = NULL; 1693 char *pbuf; 1694 1695 PRTDBG(("essid_of_profile: profile = %s\n", profile)); 1696 pbuf = append_pa(profile); 1697 p_section = find_section(gp_config_file, pbuf); 1698 free(pbuf); 1699 1700 if (p_section == NULL) { 1701 return (NULL); 1702 } else { 1703 plist = p_section->list; 1704 } 1705 pae = plist->ael_head; 1706 while (pae != NULL) { 1707 if (strncmp(pae->ae_arg, "essid=", strlen("essid=")) == 0) { 1708 PRTDBG(("essid_of_profile: essid = %s\n", 1709 pae->ae_arg)); 1710 return (get_value(pae->ae_arg)); 1711 } 1712 pae = pae->ae_next; 1713 } 1714 return (NULL); 1715 } 1716 1717 /* 1718 * If we don't know which profile is our favorate in 'autoconf', 1719 * we select the wifi network based on the following heuristic 1720 * 1. the network without wep. 1721 * 2. the network with the strongst signal. 1722 * 3. the network with the faster speed(not implemented since signal affects 1723 * the speed in some degree). 1724 */ 1725 static void 1726 heuristic_load(int fd, uint32_t ess_num, wl_ess_conf_t **p_ess_conf) 1727 { 1728 int i = 0; 1729 char *flag = NULL; 1730 int have_nowep_wlan = 0; 1731 wl_rssi_t maxsignal = 0; 1732 char essid[34]; 1733 int timeout = LOADPROFILE_TIMEOUT; 1734 1735 PRTDBG(("heuristic_load: enter\n")); 1736 (void) call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0); 1737 flag = calloc(sizeof (char), ess_num); 1738 for (i = 0; i < ess_num; i++) { /* extract none-wep network */ 1739 if (p_ess_conf[i]->wl_ess_conf_wepenabled == B_FALSE) { 1740 flag[i] = 1; 1741 have_nowep_wlan = 1; 1742 } 1743 } 1744 /* 1745 * if all the wlans are weped, we select the one with strongest signal 1746 * in all of them, otherwise we just select in the none weped ones. 1747 */ 1748 if (!have_nowep_wlan) 1749 (void) memset(flag, 1, ess_num); 1750 for (i = 0; i < ess_num; i++) { /* extract the strongest signal ones */ 1751 if (flag[i] == 1) { 1752 if (p_ess_conf[i]->wl_ess_conf_sl > maxsignal) { 1753 maxsignal = p_ess_conf[i]->wl_ess_conf_sl; 1754 (void) memset(flag, 0, i); 1755 } else if (p_ess_conf[i]->wl_ess_conf_sl == maxsignal) 1756 continue; 1757 else 1758 flag[i] = 0; 1759 } 1760 } 1761 for (i = 0; i < ess_num; i++) { 1762 if (flag[i] == 1) 1763 break; 1764 } 1765 free(flag); 1766 PRTDBG(("heuristic_load: %s is selected\n", 1767 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid)); 1768 /* select one in all the networks which meet the preceding stardands */ 1769 if (i == ess_num) 1770 (void) do_set_essid(fd, ""); 1771 else 1772 (void) do_set_essid(fd, 1773 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid); 1774 1775 if ((ess_num == 0) || (do_get_essid(fd) == B_FALSE)) { 1776 (void) fprintf(stderr, gettext("%s: autoconf:" 1777 " failed to connect to any essid\n"), 1778 gExecName); 1779 exit(WIFI_MINOR_ERR); 1780 } 1781 (void) strlcpy(essid, ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid, 1782 sizeof (essid)); 1783 (void) printf(gettext("%s: autoconf: essid '%s' is selected%s\n"), 1784 gExecName, essid, 1785 have_nowep_wlan ? "" : ": this is a WEPed " 1786 "access point"); 1787 1788 if (!have_nowep_wlan) 1789 exit(WIFI_FATAL_ERR); 1790 1791 while (timeout > 0) { 1792 if ((do_get_linkstatus(fd) == B_TRUE) && 1793 (*(wl_linkstatus_t *)(gbuf->wldp_buf) == WL_CONNECTED)) { 1794 (void) printf(gettext("%s: connecting to " 1795 "essid '%s'\n"), gExecName, essid); 1796 return; 1797 } 1798 (void) sleep(1); 1799 timeout--; 1800 } 1801 (void) fprintf(stderr, gettext("%s: failed to connect to " 1802 "essid '%s'\n"), gExecName, essid); 1803 exit(WIFI_FATAL_ERR); 1804 } 1805 1806 /* 1807 * Called in autoconf and startconf to find which 'profile' is selected. 1808 * The process is: check profile names in the prefer list item by item, 1809 * if the essid of the profile is in the scan list, then it is the wanted. 1810 * readonly: 1 for startconf 1811 * 0 for autoconf 1812 * for autoconf, the scan result will be recorded in the history list. 1813 */ 1814 static char * 1815 select_profile(int fd, int readonly, int timeout) 1816 { 1817 uint32_t ess_num = 0; 1818 int nprefer = 1; 1819 char **ess_argv; 1820 char **hisess_argv; 1821 wl_ess_conf_t **p_ess_conf; 1822 section_t *p_section = NULL; 1823 aelist_t *plist = NULL; 1824 ae_t *pae = NULL; 1825 int i; 1826 const char *parg; 1827 char *selected = NULL; 1828 boolean_t flag = B_FALSE; 1829 1830 if ((call_ioctl(fd, WLAN_COMMAND, WL_SCAN, 0) == B_FALSE) || 1831 (do_get_wlanlist(fd) == B_FALSE)) { 1832 (void) fprintf(stderr, gettext("%s: " 1833 "autoconf : failed to scan\n"), gExecName); 1834 exit(WIFI_FATAL_ERR); 1835 } 1836 ess_num = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num; 1837 ess_argv = safe_calloc(sizeof (char *), ess_num); 1838 hisess_argv = safe_calloc(sizeof (char *), ess_num); 1839 p_ess_conf = safe_calloc(sizeof (wl_ess_list_t *), ess_num); 1840 for (i = 0; i < ess_num; i++) { 1841 p_ess_conf[i] = ((wl_ess_list_t *)gbuf->wldp_buf) 1842 ->wl_ess_list_ess + i; 1843 ess_argv[i] = safe_malloc(MAX_SCANBUF_LEN); 1844 if (readonly == 0) { 1845 hisess_argv[i] = safe_malloc(MAX_SCANBUF_LEN); 1846 (void) snprintf(hisess_argv[i], MAX_SCANBUF_LEN, 1847 "%s%c%02x:%02x:%02x:%02x:%02x:%02x%c%s", 1848 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid, 1849 ',', 1850 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[0]), 1851 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[1]), 1852 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[2]), 1853 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[3]), 1854 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[4]), 1855 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[5]), ',', 1856 (p_ess_conf[i]->wl_ess_conf_wepenabled == B_TRUE 1857 ? "wep":"none")); 1858 } 1859 (void) snprintf(ess_argv[i], MAX_SCANBUF_LEN, "%s", 1860 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid); 1861 } 1862 if (readonly == 0) { 1863 add_to_history(gp_config_file, ess_num, hisess_argv); 1864 for (i = 0; i < ess_num; i++) { 1865 free(hisess_argv[i]); 1866 } 1867 free(hisess_argv); 1868 } 1869 1870 p_section = find_section(gp_config_file, WIFI_PREFER); 1871 if (p_section == NULL) { 1872 if (ess_num > 0) { 1873 heuristic_load(fd, ess_num, p_ess_conf); 1874 exit(WIFI_EXIT_DEF); 1875 } 1876 goto done; 1877 } 1878 plist = p_section->list; 1879 assert(plist != NULL); 1880 if (plist != NULL) { 1881 nprefer = plist->ael_argc; 1882 if (nprefer == 0) { 1883 if (ess_num > 0) { 1884 heuristic_load(fd, ess_num, p_ess_conf); 1885 exit(WIFI_EXIT_DEF); 1886 } 1887 goto done; 1888 } 1889 } 1890 pae = plist->ael_head; 1891 while ((pae != NULL) && (flag != B_TRUE)) { 1892 parg = essid_of_profile(pae->ae_arg); 1893 if (parg != NULL) { 1894 for (i = 0; i < ess_num; i++) { 1895 if (strcmp(parg, ess_argv[i]) == 0) { 1896 selected = pae->ae_arg; 1897 flag = B_TRUE; 1898 break; 1899 } 1900 } 1901 } 1902 pae = pae->ae_next; 1903 } 1904 done: 1905 if ((selected == NULL) && (timeout == 0)) { 1906 heuristic_load(fd, ess_num, p_ess_conf); 1907 } 1908 for (i = 0; i < ess_num; i++) { 1909 free(ess_argv[i]); 1910 } 1911 free(ess_argv); 1912 free(p_ess_conf); 1913 return (selected); 1914 } 1915 1916 static boolean_t 1917 is_waittime_valid(char *pbuf) 1918 { 1919 int i; 1920 1921 i = atoi(pbuf); 1922 if (i == -1) 1923 return (B_TRUE); 1924 for (i = 0; i < strlen(pbuf); i++) { 1925 if (isdigit(pbuf[i]) == 0) { 1926 return (B_FALSE); 1927 } 1928 } 1929 return (B_TRUE); 1930 } 1931 /* 1932 * do_autoconf: First scan the wlanlist, and select one essid from scan result 1933 * by the order in {preferrence} list. If no match, then heuristic_load; 1934 */ 1935 /*ARGSUSED*/ 1936 static boolean_t 1937 do_autoconf(int fd, int argc, char **argv) 1938 { 1939 const char *selected = NULL; 1940 int timeout = LOADPROFILE_TIMEOUT, forever = 0, len = 0; 1941 char *pequal, *param; 1942 char **ld_argv = NULL; 1943 boolean_t ret = B_TRUE; 1944 1945 PRTDBG(("do_autoconf(%d, 0x%x)\n", argc, argv)); 1946 assert(fd > 0); 1947 if (argc > 0) { 1948 param = safe_strdup(argv[0]); 1949 pequal = strchr(param, '='); 1950 if (pequal != NULL) { 1951 *pequal++ = '\0'; 1952 } else { 1953 do_print_usage(); 1954 exit(WIFI_IMPROPER_USE); 1955 } 1956 if (strcmp(param, "wait") != 0) { 1957 do_print_usage(); 1958 exit(WIFI_IMPROPER_USE); 1959 } else { 1960 if (strcmp(pequal, "forever") == 0) { 1961 forever = 1; 1962 } else { 1963 if (is_waittime_valid(pequal) == B_FALSE) { 1964 (void) fprintf(stderr, gettext("%s: " 1965 "invalid value %s for 'wait'\n"), 1966 gExecName, pequal); 1967 exit(WIFI_FATAL_ERR); 1968 } 1969 if (sscanf(pequal, "%d", &timeout) != 1) { 1970 do_print_usage(); 1971 exit(WIFI_IMPROPER_USE); 1972 } 1973 if (timeout == -1) { 1974 forever = 1; 1975 } 1976 } 1977 } 1978 free(param); 1979 if (argc > 1) { 1980 (void) fprintf(stderr, gettext("%s: trailing " 1981 "useless tokens after '%s'\n"), 1982 gExecName, argv[0]); 1983 } 1984 } 1985 1986 while ((forever == 1) || (timeout > 0)) { 1987 timeout--; 1988 selected = select_profile(fd, 0, max(timeout, forever)); 1989 if (selected != NULL) 1990 break; 1991 (void) sleep(1); 1992 } 1993 if (selected == NULL) { 1994 return (B_TRUE); 1995 } 1996 (void) printf(gettext("%s: autoconf: profile [%s]" 1997 " is selected\n"), gExecName, selected); 1998 ld_argv = safe_calloc(sizeof (char *), argc+1); 1999 ld_argv[0] = safe_strdup(selected); 2000 if (argc > 0) { 2001 len = max(strlen(argv[0]), strlen("wait=forever")); 2002 ld_argv[1] = safe_malloc(len); 2003 safe_snprintf(ld_argv[1], len + 1, forever == 1 ? 2004 "wait=forever" : "wait=%d", timeout); 2005 } 2006 ret = do_loadpf(fd, argc+1, ld_argv); 2007 free(ld_argv[0]); 2008 if (argc > 0) { 2009 free(ld_argv[1]); 2010 } 2011 free(ld_argv); 2012 return (ret); 2013 } 2014 2015 /* 2016 * do_startconf: almost the same as the do_autoconf, except that doesn't 2017 * write file. 2018 */ 2019 /*ARGSUSED*/ 2020 static boolean_t 2021 do_startconf(int fd, int argc, char **argv) 2022 { 2023 int i = 0, ael_num = 0; 2024 section_t *p_section = NULL; 2025 section_t *p_wep_section = NULL; 2026 aelist_t *plist = NULL; 2027 const char *selected = NULL; 2028 ae_t *pae = NULL; 2029 char *pbuf = NULL; 2030 char **argvnew = NULL; 2031 2032 PRTDBG(("do_startconf(%d, 0x%x)\n", argc, argv)); 2033 assert(fd > 0); 2034 2035 selected = select_profile(fd, 1, 0); 2036 if (selected == NULL) { 2037 return (B_TRUE); 2038 } 2039 2040 (void) call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0); 2041 2042 pbuf = append_pa(selected); 2043 p_wep_section = find_section(gp_wepkey_file, pbuf); 2044 p_section = find_section(gp_config_file, pbuf); 2045 free(pbuf); 2046 2047 if (p_wep_section != NULL) { 2048 plist = p_wep_section->list; 2049 pae = plist->ael_head; 2050 while (pae != NULL) { 2051 if (pae->ae_arg != NULL) 2052 (void) do_set_wepkey(fd, pae->ae_arg); 2053 pae = pae->ae_next; 2054 } 2055 } 2056 2057 if (p_section != NULL) { 2058 plist = p_section->list; 2059 if (plist->ael_argc == 0) { 2060 return (B_TRUE); 2061 } 2062 argvnew = aeltoargv(plist, &ael_num); 2063 (void) do_set(fd, ael_num, argvnew); 2064 2065 for (i = 0; i < ael_num; i++) 2066 free(argvnew[i]); 2067 free(argvnew); 2068 } 2069 return (B_TRUE); 2070 } 2071 2072 static char * 2073 find_active_profile(int fd) 2074 { 2075 section_t *p_section = NULL, *activep_section = NULL; 2076 aelist_t *plist = NULL; 2077 ae_t *pae = NULL; 2078 const char *pessid = NULL, *pbssid = NULL; 2079 char essid[34], bssid[32]; 2080 const char *activeprofile = NULL; 2081 2082 PRTDBG(("find_active_profile: %d\n", fd)); 2083 if (do_get_essid(fd) == B_FALSE) { 2084 return (NULL); 2085 } 2086 (void) strlcpy(essid, ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid, 2087 sizeof (essid)); 2088 if (do_get_bssid(fd) == B_FALSE) { 2089 return (NULL); 2090 } 2091 safe_snprintf(bssid, sizeof (bssid), "%02x:%02x:%02x:%02x:%02x:%02x", 2092 ((uint8_t *)gbuf->wldp_buf)[0], 2093 ((uint8_t *)gbuf->wldp_buf)[1], 2094 ((uint8_t *)gbuf->wldp_buf)[2], 2095 ((uint8_t *)gbuf->wldp_buf)[3], 2096 ((uint8_t *)gbuf->wldp_buf)[4], 2097 ((uint8_t *)gbuf->wldp_buf)[5]); 2098 activep_section = find_section(gp_config_file, WIFI_ACTIVEP); 2099 if (activep_section == NULL) 2100 return (NULL); 2101 activeprofile = get_value(activep_section->list-> 2102 ael_head->ae_arg); 2103 if (activeprofile == NULL) 2104 return (NULL); 2105 p_section = gp_config_file->section_head; 2106 while (p_section != NULL) { 2107 if (((plist = p_section->list) != NULL) && 2108 (plist->type == PROFILE) && 2109 (strcmp(p_section->section_id, activeprofile) == 0)) { 2110 pae = plist->ael_head; 2111 while (pae != NULL) { 2112 if (strncmp(pae->ae_arg, "essid=", 2113 strlen("essid=")) == 0) { 2114 pessid = get_value(pae->ae_arg); 2115 } 2116 if (strncmp(pae->ae_arg, "bssid=", 2117 strlen("bssid=")) == 0) { 2118 pbssid = get_value(pae->ae_arg); 2119 } 2120 pae = pae->ae_next; 2121 } 2122 if (pessid && pbssid && 2123 (strcmp(essid, pessid) == 0) && 2124 (strcmp(bssid, pbssid) == 0)) { 2125 return (p_section->section_id); 2126 } 2127 } 2128 p_section = p_section->section_next; 2129 } 2130 return (NULL); 2131 } 2132 2133 static void 2134 record_active_profile(char *pname, int action) 2135 { 2136 section_t *p_section = NULL; 2137 aelist_t *plist = NULL; 2138 char pbuf[256]; 2139 2140 p_section = find_section(gp_config_file, WIFI_ACTIVEP); 2141 if (p_section == NULL) { 2142 plist = new_ael(ACTIVEP); 2143 new_section(gp_config_file, plist, WIFI_ACTIVEP); 2144 } else { 2145 plist = p_section->list; 2146 } 2147 2148 if (action == RECORD_ADD) { 2149 assert(pname != NULL); 2150 safe_snprintf(pbuf, sizeof (pbuf), "activep=%s", pname); 2151 update_aelist(plist, pbuf); 2152 } else if (action == RECORD_DEL) { 2153 assert(pname == NULL); 2154 update_aelist(plist, "activep= "); 2155 } 2156 } 2157 2158 /* 2159 * do_loadpf: load a profile, set related parameters both in wifi 2160 * and in wifiwepkey, if network name is not exist in the 2161 * configration files, then we clean all parameters and set essid only 2162 */ 2163 static boolean_t 2164 do_loadpf(int fd, int argc, char ** argv) 2165 { 2166 int i = 0, ael_num = 0; 2167 int timeout = LOADPROFILE_TIMEOUT, forever = 0; 2168 section_t *p_section = NULL; 2169 section_t *p_wep_section = NULL; 2170 aelist_t *plist = NULL; 2171 ae_t *pae = NULL; 2172 char *pbuf = NULL; 2173 char **argvnew = NULL; 2174 char *connect; 2175 char *pequal, *param; 2176 2177 PRTDBG(("do_loadpf(%d, %x)\n", argc, argv)); 2178 assert(fd > 0); 2179 if (argc == 0) { 2180 (void) fprintf(stderr, gettext("%s: connect: " 2181 "profile name missing\n"), gExecName); 2182 return (B_FALSE); 2183 } 2184 if (argc > 1) { 2185 param = safe_strdup(argv[1]); 2186 pequal = strchr(param, '='); 2187 if (pequal != NULL) { 2188 *pequal++ = '\0'; 2189 } else { 2190 do_print_usage(); 2191 exit(WIFI_IMPROPER_USE); 2192 } 2193 if (strcmp(param, "wait") != 0) { 2194 do_print_usage(); 2195 exit(WIFI_IMPROPER_USE); 2196 } else { 2197 if (strcmp(pequal, "forever") == 0) { 2198 forever = 1; 2199 } else { 2200 if (is_waittime_valid(pequal) == B_FALSE) { 2201 (void) fprintf(stderr, gettext("%s: " 2202 "invalid value %s for 'wait'\n"), 2203 gExecName, pequal); 2204 exit(WIFI_FATAL_ERR); 2205 } 2206 if (sscanf(pequal, "%d", &timeout) != 1) { 2207 do_print_usage(); 2208 exit(WIFI_IMPROPER_USE); 2209 } 2210 if (timeout == -1) { 2211 forever = 1; 2212 } 2213 } 2214 } 2215 free(param); 2216 if (argc > 2) { 2217 (void) fprintf(stderr, gettext("%s: trailing " 2218 "useless tokens after '%s'\n"), 2219 gExecName, argv[1]); 2220 } 2221 } 2222 (void) call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0); 2223 2224 pbuf = append_pa(argv[0]); 2225 p_wep_section = find_section(gp_wepkey_file, pbuf); 2226 p_section = find_section(gp_config_file, pbuf); 2227 2228 if (p_wep_section != NULL) { 2229 (void) set_prefer(gp_config_file, argv[0], 1); 2230 plist = p_wep_section->list; 2231 pae = plist->ael_head; 2232 while (pae != NULL) { 2233 if (pae->ae_arg != NULL) { 2234 (void) do_set_wepkey(fd, pae->ae_arg); 2235 } 2236 pae = pae->ae_next; 2237 } 2238 } 2239 2240 if (p_section != NULL) { 2241 connect = "profile"; 2242 2243 (void) set_prefer(gp_config_file, argv[0], 1); 2244 plist = p_section->list; 2245 if (plist->ael_argc == 0) { 2246 free(pbuf); 2247 return (B_TRUE); 2248 } 2249 argvnew = aeltoargv(plist, &ael_num); 2250 /* 2251 * if there is no 'essid' item in argvnew, the profile 2252 * name(argv[0]) is treated as essid. 2253 */ 2254 for (i = 0; i < ael_num; i++) { 2255 if (strncmp(argvnew[i], "essid=", strlen("essid=")) 2256 == 0) 2257 break; 2258 } 2259 if (i == ael_num) 2260 (void) do_set_essid(fd, argv[0]); 2261 2262 (void) do_set(fd, ael_num, argvnew); 2263 2264 for (i = 0; i < ael_num; i++) 2265 free(argvnew[i]); 2266 free(argvnew); 2267 2268 /* 2269 * set flag in {active_profile} so that showprofile knows 2270 * which profile is active when more than one profiles are 2271 * created for the same WLAN. 2272 */ 2273 record_active_profile(pbuf, RECORD_ADD); 2274 } else { 2275 (void) do_set_essid(fd, argv[0]); 2276 connect = "essid"; 2277 } 2278 2279 while ((forever == 1) || (timeout > 0)) { 2280 if ((do_get_linkstatus(fd) == B_TRUE) && 2281 (*(wl_linkstatus_t *)(gbuf->wldp_buf) == WL_CONNECTED)) { 2282 section_t *p_section = NULL; 2283 aelist_t *plist = NULL; 2284 char bssid[32]; 2285 /* record bssid in the profile */ 2286 if (do_get_bssid(fd) == B_FALSE) { 2287 free(pbuf); 2288 return (B_TRUE); 2289 } 2290 safe_snprintf(bssid, sizeof (bssid), 2291 "bssid=%02x:%02x:%02x:%02x:%02x:%02x", 2292 ((uint8_t *)gbuf->wldp_buf)[0], 2293 ((uint8_t *)gbuf->wldp_buf)[1], 2294 ((uint8_t *)gbuf->wldp_buf)[2], 2295 ((uint8_t *)gbuf->wldp_buf)[3], 2296 ((uint8_t *)gbuf->wldp_buf)[4], 2297 ((uint8_t *)gbuf->wldp_buf)[5]); 2298 2299 p_section = find_section(gp_config_file, pbuf); 2300 if (p_section != NULL) { 2301 plist = p_section->list; 2302 update_aelist(plist, bssid); 2303 } 2304 free(pbuf); 2305 (void) printf(gettext("%s: connecting to " 2306 "%s '%s'\n"), gExecName, connect, argv[0]); 2307 return (B_TRUE); 2308 } 2309 (void) sleep(1); 2310 timeout--; 2311 PRTDBG(("connect counting:......%d\n", timeout)); 2312 } 2313 (void) fprintf(stderr, gettext("%s: failed to connect to " 2314 "%s '%s'\n"), gExecName, connect, argv[0]); 2315 free(pbuf); 2316 return (B_FALSE); 2317 } 2318 2319 /* 2320 * if wepkey is set in the profile, display wepkey|n=***** 2321 * when showprofile and getprofilewepkey. 2322 * if wepkeyn is NULL, all the wepkeys will be display, 2323 * otherwise, just display the matching one. 2324 */ 2325 static void 2326 print_wepkey_info(const char *id, const char *wepkeyn) 2327 { 2328 char *pequal, *param; 2329 section_t *p_section = NULL; 2330 aelist_t *plist = NULL; 2331 ae_t *pae = NULL; 2332 2333 p_section = find_section(gp_wepkey_file, id); 2334 if (p_section != NULL) { 2335 plist = p_section->list; 2336 pae = plist->ael_head; 2337 while (pae != NULL) { 2338 if (pae->ae_arg != NULL) { 2339 param = safe_strdup(pae->ae_arg); 2340 pequal = strchr(param, '='); 2341 if (pequal == NULL) 2342 return; 2343 *pequal = '\0'; 2344 if (wepkeyn != NULL) { 2345 if (strcmp(wepkeyn, param) == 0) 2346 (void) printf("\t%s=*****\n", 2347 param); 2348 free(param); 2349 return; 2350 } else { 2351 (void) printf("\t%s=*****\n", param); 2352 free(param); 2353 } 2354 } 2355 pae = pae->ae_next; 2356 } 2357 } 2358 } 2359 2360 /* 2361 * do_printpf: print each parameters of the profile, if no network name 2362 * assigned, then print all profile saved in configration file. 2363 */ 2364 /*ARGSUSED*/ 2365 static boolean_t 2366 do_printpf(int fd, int argc, char ** argv) 2367 { 2368 section_t *p_section = NULL; 2369 aelist_t *plist = NULL; 2370 ae_t *pae = NULL; 2371 char *pbuf = NULL; 2372 int i; 2373 2374 PRTDBG(("do_printpf(%d, %x)\n", argc, argv)); 2375 2376 /* 2377 * if no profile name is inputted, all the profiles will be displayed. 2378 */ 2379 if (argc == 0) { 2380 p_section = gp_config_file->section_head; 2381 while (p_section != NULL) { 2382 plist = p_section->list; 2383 if (plist->type == PROFILE) { 2384 (void) printf("%s\n", p_section->section_id); 2385 pae = plist->ael_head; 2386 while (pae != NULL) { 2387 if (pae->ae_arg != NULL) { 2388 (void) printf("\t%s\n", 2389 pae->ae_arg); 2390 } 2391 pae = pae->ae_next; 2392 } 2393 /* 2394 * identify whether wepkey is set 2395 * in the profile 2396 */ 2397 print_wepkey_info(p_section->section_id, NULL); 2398 } 2399 p_section = p_section->section_next; 2400 } 2401 return (B_TRUE); 2402 } 2403 2404 for (i = 0; i < argc; i++) { 2405 pbuf = append_pa(argv[i]); 2406 p_section = find_section(gp_config_file, pbuf); 2407 free(pbuf); 2408 if (p_section != NULL) { 2409 (void) printf("%s\n", p_section->section_id); 2410 plist = p_section->list; 2411 if (plist != NULL) { 2412 pae = plist->ael_head; 2413 while (pae != NULL) { 2414 if (pae->ae_arg != NULL) { 2415 (void) printf("\t%s\n", 2416 pae->ae_arg); 2417 } 2418 pae = pae->ae_next; 2419 } 2420 /* 2421 * identify whether wepkey is set 2422 * in the profile 2423 */ 2424 print_wepkey_info(p_section->section_id, NULL); 2425 } 2426 } else { 2427 (void) fprintf(stderr, 2428 gettext("%s: showprofile : " 2429 "no such profile: '%s'\n"), 2430 gExecName, argv[i]); 2431 return (B_FALSE); 2432 } 2433 } 2434 return (B_TRUE); 2435 } 2436 /* 2437 * find_ae: Find an ae by its contents, return its pointer. 2438 */ 2439 static ae_t * 2440 find_ae(aelist_t *plist, const char *arg) 2441 { 2442 char *param = NULL; 2443 char *pnext = NULL; 2444 ae_t *pae = NULL; 2445 2446 if ((arg == NULL) || (plist == NULL)) { 2447 PRTDBG(("find_ae: arg= NULL or plist=NULL\n")); 2448 return (NULL); 2449 } 2450 PRTDBG(("find_ae(0x%x, \"%s\")\n", plist, arg)); 2451 param = safe_strdup(arg); 2452 pnext = strchr(param, '='); 2453 if (pnext != NULL) { 2454 *pnext = '\0'; 2455 } else { 2456 PRTDBG(("find_ae: param = \"%s\"\n", param)); 2457 free(param); 2458 return (NULL); 2459 } 2460 2461 pae = plist->ael_head; 2462 while (pae != NULL) { 2463 if ((pae->ae_arg != NULL) && 2464 (strncmp(pae->ae_arg, param, strlen(param)) == 0)) { 2465 PRTDBG(("find_ae: param = \"%s\"\n", param)); 2466 free(param); 2467 return (pae); 2468 } 2469 pae = pae->ae_next; 2470 } 2471 free(param); 2472 return (NULL); 2473 } 2474 2475 /* 2476 * update_aelist: Update an aelist by arg, for example: 2477 * there are an item with content"essid=ap7-2", 2478 * update_aelist(0x..., "essid=myssid2") will update it as "essid=myssid2" 2479 */ 2480 static void 2481 update_aelist(aelist_t *plist, const char *arg) 2482 { 2483 ae_t *pae = NULL; 2484 2485 assert((arg != NULL)&&(plist != NULL)); 2486 PRTDBG(("update_aelist(0x%x, \"%s\")\n", plist, arg)); 2487 pae = find_ae(plist, arg); 2488 if (pae == NULL) { 2489 new_ae(plist, arg); 2490 } else { 2491 free(pae->ae_arg); 2492 pae->ae_arg = safe_strdup(arg); 2493 } 2494 } 2495 2496 /* 2497 * do_deletepf: delete a profile in configration files. 2498 */ 2499 /*ARGSUSED*/ 2500 static boolean_t 2501 do_deletepf(int fd, int argc, char **argv) 2502 { 2503 int i = 0; 2504 char *section_id; 2505 char *prefer; 2506 section_t *p_section = NULL, *p_sectionbak = NULL; 2507 aelist_t *plist = NULL; 2508 2509 PRTDBG(("do_deletepf(%d, \"%s\")\n", argc, argv)); 2510 if (argc <= 0) { 2511 do_print_usage(); 2512 exit(WIFI_IMPROPER_USE); 2513 } 2514 2515 /* 2516 * if a "all" is inputted, all the profiles will be deleted. 2517 */ 2518 if (strcasecmp(argv[0], "all") == 0) { 2519 p_section = gp_config_file->section_head; 2520 while ((p_section != NULL) && 2521 ((plist = p_section->list) != NULL)) { 2522 if (plist->type == PROFILE) { 2523 p_sectionbak = p_section->section_next; 2524 section_id = safe_strdup(p_section->section_id); 2525 (void) del_section(gp_config_file, section_id); 2526 (void) del_section(gp_wepkey_file, section_id); 2527 /* 2528 * remove the '[]' of the [section_id] 2529 */ 2530 prefer = section_id + 1; 2531 *(prefer + strlen(section_id) - 2) = '\0'; 2532 (void) del_prefer(gp_config_file, prefer, 2533 B_FALSE); 2534 free(section_id); 2535 p_section = p_sectionbak; 2536 continue; 2537 } 2538 p_section = p_section->section_next; 2539 } 2540 return (B_TRUE); 2541 } 2542 if (gp_config_file != NULL) { 2543 for (i = 0; i < argc; i++) { 2544 section_id = append_pa(argv[i]); 2545 if (del_section(gp_config_file, section_id) 2546 == B_FALSE) { 2547 if (del_section(gp_wepkey_file, section_id) 2548 == B_TRUE) { 2549 (void) del_prefer(gp_config_file, 2550 argv[i], B_FALSE); 2551 free(section_id); 2552 return (B_TRUE); 2553 } else { 2554 (void) fprintf(stderr, 2555 gettext("%s: deleteprofile" 2556 ": no such profile: '%s'\n"), 2557 gExecName, argv[i]); 2558 free(section_id); 2559 return (B_FALSE); 2560 } 2561 } 2562 (void) del_prefer(gp_config_file, argv[i], B_FALSE); 2563 (void) del_section(gp_wepkey_file, section_id); 2564 free(section_id); 2565 } 2566 } 2567 return (B_TRUE); 2568 } 2569 2570 /* 2571 * do_history: Print the list in {history} section. 2572 */ 2573 /*ARGSUSED*/ 2574 static boolean_t 2575 do_history(int fd, int argc, char **argv) 2576 { 2577 section_t *p_section = NULL; 2578 aelist_t *plist = NULL; 2579 ae_t *pae = NULL; 2580 char *param, *param_bak, *pcomma; 2581 uint32_t maxessidlen = 0, ulen; 2582 char format[256], *ntstr; 2583 uint32_t nt = 0, cnt = 0; 2584 int len; 2585 time_t cltime; 2586 2587 PRTDBG(("do_history(%d, 0x%x)\n", argc, argv)); 2588 if (argc > 0) { 2589 (void) fprintf(stderr, gettext("%s: trailing useless tokens " 2590 "after 'history'\n"), gExecName); 2591 } 2592 p_section = find_section(gp_config_file, WIFI_HISTORY); 2593 if (p_section == NULL) { 2594 PRTDBG(("no history section\n")); 2595 return (B_FALSE); 2596 } 2597 plist = p_section->list; 2598 2599 /* 2600 * If history section is empty, directly return. 2601 */ 2602 if (plist == NULL) 2603 return (B_TRUE); 2604 /* 2605 * construct the output format in terms of the 2606 * maxmium essid length 2607 */ 2608 pae = NULL; 2609 pae = plist->ael_head; 2610 while (pae != NULL) { 2611 if (pae->ae_arg != NULL) { 2612 param = safe_strdup(pae->ae_arg); 2613 pcomma = strchr(param, ','); 2614 if (pcomma == NULL) { 2615 (void) fprintf(stderr, 2616 gettext("%s: history : " 2617 "data format error\n"), 2618 gExecName); 2619 free(param); 2620 return (B_FALSE); 2621 } 2622 *pcomma = '\0'; 2623 ulen = strlen(param); 2624 maxessidlen = (maxessidlen > ulen 2625 ? maxessidlen:ulen); 2626 free(param); 2627 } 2628 pae = pae->ae_next; 2629 } 2630 if ((nt = (maxessidlen / 8 + 1)) > 4) 2631 nt = 4; 2632 len = snprintf(format, sizeof (format), gettext("essid")); 2633 ntstr = construct_format(nt); 2634 assert((ntstr != NULL) && (strlen(ntstr) <= 4)); 2635 len += snprintf(format + len, sizeof (format) - len, "%s", ntstr); 2636 len += snprintf(format + len, sizeof (format) - len, 2637 gettext("bssid\t\t encryption\tlast seen\n")); 2638 2639 if ((len <= 0) || (len > sizeof (format) - 1)) { 2640 (void) printf(gettext("essid\t\t\t\tbssid\t\t encryption" 2641 "\tlast seen\n")); 2642 } else { 2643 (void) printf("%s", format); 2644 } 2645 /* 2646 * output the contents of the history section. 2647 */ 2648 pae = plist->ael_head; 2649 while (pae != NULL) { 2650 if (pae->ae_arg != NULL) { 2651 param = safe_strdup(pae->ae_arg); 2652 param_bak = param; 2653 if ((pcomma = strchr(param, ',')) != NULL) { 2654 *pcomma = '\0'; 2655 cnt = nt - (min((strlen(param)/8 + 1), 4) - 1); 2656 ntstr = construct_format(cnt); 2657 assert(ntstr != NULL); 2658 /* display essid */ 2659 (void) printf("%s%s", param, ntstr); 2660 free(ntstr); 2661 } 2662 param = pcomma + 1; 2663 if ((pcomma = strchr(param, ',')) != NULL) { 2664 *pcomma = '\0'; 2665 /* display bssid */ 2666 (void) printf("%s ", param); 2667 } 2668 param = pcomma + 1; 2669 if ((pcomma = strchr(param, ',')) != NULL) { 2670 *pcomma = '\0'; 2671 /* display wep */ 2672 (void) printf("%s\t\t", param); 2673 } 2674 param = pcomma + 1; 2675 /* display time stamp */ 2676 cltime = (time_t)atol(param); 2677 (void) printf("%s", ctime(&cltime)); 2678 free(param_bak); 2679 } 2680 pae = pae->ae_next; 2681 } 2682 2683 return (B_TRUE); 2684 } 2685 2686 /* 2687 * do_lsprefer: Print the list in {preferrence} section 2688 */ 2689 /*ARGSUSED*/ 2690 static boolean_t 2691 do_lsprefer(int fd, int argc, char **argv) 2692 { 2693 int i = 0; 2694 section_t *p_section = NULL; 2695 aelist_t *plist = NULL; 2696 ae_t *pae = NULL; 2697 char *pbuf; 2698 2699 PRTDBG(("do_lsprefer(%d, 0x%x)\n", argc, argv)); 2700 if (argc > 0) { 2701 (void) fprintf(stderr, gettext("%s: trailing useless tokens " 2702 "after 'listprefer'\n"), gExecName); 2703 } 2704 p_section = find_section(gp_config_file, WIFI_PREFER); 2705 if (p_section != NULL) { 2706 plist = p_section->list; 2707 if (plist != NULL) { 2708 pae = NULL; 2709 pae = plist->ael_head; 2710 while (pae != NULL) { 2711 if (pae->ae_arg != NULL) { 2712 pbuf = append_pa(pae->ae_arg); 2713 (void) printf("%d\t%s\n", ++i, pbuf); 2714 } 2715 pae = pae->ae_next; 2716 } 2717 } 2718 return (B_TRUE); 2719 } else { 2720 PRTDBG(("no preference section\n")); 2721 return (B_FALSE); 2722 } 2723 } 2724 2725 /* 2726 * do_rmprefer: Remove an item in {preferrence} list 2727 */ 2728 /*ARGSUSED*/ 2729 static boolean_t 2730 do_rmprefer(int fd, int argc, char **argv) 2731 { 2732 int i = 0; 2733 section_t *p_section = NULL; 2734 aelist_t *plist = NULL; 2735 ae_t *pae = NULL; 2736 2737 PRTDBG(("do_rmprefer(%d, 0x%x)\n", argc, argv)); 2738 if (argc <= 0) { 2739 do_print_usage(); 2740 exit(WIFI_IMPROPER_USE); 2741 } 2742 2743 /* 2744 * if a "all" is inputted, all the items in the preference 2745 * list will be deleted. 2746 */ 2747 if (strcasecmp(argv[0], "all") == 0) { 2748 p_section = find_section(gp_config_file, WIFI_PREFER); 2749 if (p_section != NULL) 2750 plist = p_section->list; 2751 2752 if ((p_section == NULL) || (plist == NULL)) 2753 return (B_FALSE); 2754 pae = plist->ael_head; 2755 while (pae != NULL) { 2756 ae_t *next = pae->ae_next; 2757 free(pae); 2758 pae = next; 2759 } 2760 plist->ael_head = plist->ael_tail = NULL; 2761 plist->ael_argc = 0; 2762 } else if (gp_config_file != NULL) { 2763 for (i = 0; i < argc; i++) { 2764 if (del_prefer(gp_config_file, argv[i], B_TRUE) 2765 == B_FALSE) { 2766 return (B_FALSE); 2767 } 2768 } 2769 } 2770 return (B_TRUE); 2771 } 2772 2773 static boolean_t 2774 is_prefer_rank_valid(const char *pbuf) 2775 { 2776 int i; 2777 boolean_t ret = B_FALSE; 2778 2779 for (i = 0; i < strlen(pbuf); i++) { 2780 if (isdigit(pbuf[i]) == 0) { 2781 ret = B_FALSE; 2782 goto exit0; 2783 } 2784 } 2785 i = atoi(pbuf); 2786 if ((i >= 1) && (i <= MAX_PREFERENCE_NUM)) 2787 ret = B_TRUE; 2788 exit0: 2789 return (ret); 2790 } 2791 2792 /* 2793 * do_setprefer: Set network preferrence 2794 */ 2795 /*ARGSUSED*/ 2796 static boolean_t 2797 do_setprefer(int fd, int argc, char **argv) 2798 { 2799 int rank = 0; 2800 2801 PRTDBG(("do_setprefer(%d, 0x%x)\n", argc, argv)); 2802 if (argc <= 0) { 2803 do_print_usage(); 2804 exit(WIFI_IMPROPER_USE); 2805 } 2806 if (argc == 1) { 2807 rank = 1; 2808 } else { 2809 if (is_prefer_rank_valid(argv[1]) == B_FALSE) { 2810 (void) fprintf(stderr, gettext("%s: preference rank " 2811 "should be an integer within 1-10\n"), gExecName); 2812 return (B_FALSE); 2813 } 2814 rank = atoi(argv[1]); 2815 } 2816 return (set_prefer(gp_config_file, argv[0], rank)); 2817 } 2818 2819 static boolean_t 2820 is_wepkeyindex_valid(const char *pbuf) 2821 { 2822 int i; 2823 boolean_t ret = B_FALSE; 2824 2825 for (i = 0; i < strlen(pbuf); i++) { 2826 if (isdigit(pbuf[i]) == 0) { 2827 ret = B_FALSE; 2828 goto exit0; 2829 } 2830 } 2831 i = atoi(pbuf); 2832 if ((i >= 1) && (i <= MAX_NWEPKEYS)) 2833 ret = B_TRUE; 2834 exit0: 2835 return (ret); 2836 } 2837 2838 static boolean_t 2839 is_channel_valid(const char *pbuf) 2840 { 2841 int i; 2842 boolean_t ret = B_FALSE; 2843 2844 for (i = 0; i < strlen(pbuf); i++) { 2845 if (isdigit(pbuf[i]) == 0) { 2846 ret = B_FALSE; 2847 goto exit0; 2848 } 2849 } 2850 i = atoi(pbuf); 2851 if ((i >= 0) && (i <= MAX_CHANNEL_NUM)) 2852 ret = B_TRUE; 2853 exit0: 2854 return (ret); 2855 } 2856 2857 static boolean_t 2858 is_wepkey_valid(const char *pbuf, uint32_t length) 2859 { 2860 int i; 2861 boolean_t ret = B_FALSE; 2862 2863 switch (length) { 2864 case 10: 2865 case 26: 2866 for (i = 0; i < length; i++) { 2867 if (isxdigit(pbuf[i]) == 0) { 2868 ret = B_FALSE; 2869 goto exit0; 2870 } 2871 } 2872 ret = B_TRUE; 2873 break; 2874 case 5: 2875 case 13: 2876 ret = B_TRUE; 2877 break; 2878 default: 2879 ret = B_FALSE; 2880 break; 2881 } 2882 exit0: 2883 if (ret == B_FALSE) { 2884 (void) fprintf(stderr, gettext("%s: " 2885 "wepkey should be:\n" 2886 "\t 40bits: 5 char or 10 hex digits.\n" 2887 "\t 128bits: 13 char or 26 hex digits.\n"), 2888 gExecName); 2889 } 2890 return (ret); 2891 } 2892 2893 /* 2894 * get_valid_wepkey: get an valid wepkey from stdin 2895 */ 2896 static char * 2897 get_valid_wepkey() 2898 { 2899 int i = 0; 2900 char *buf = NULL; 2901 uint8_t length = 0; 2902 struct termios stored_settings; 2903 struct termios new_settings; 2904 2905 PRTDBG(("get_valid_wepkey()\n")); 2906 buf = safe_calloc(sizeof (char), MAX_KEY_LENGTH + 2); 2907 /* 2908 * Because we need to get single char from terminal, so we need to 2909 * disable canonical mode and set buffer size to 1 tyte. And because 2910 * wepkey should not be see by others, so we disable echo too. 2911 */ 2912 (void) fflush(stdin); 2913 (void) tcgetattr(0, &stored_settings); 2914 new_settings = stored_settings; 2915 new_settings.c_lflag &= (~ICANON); 2916 new_settings.c_lflag &= (~ECHO); 2917 new_settings.c_cc[VTIME] = 0; 2918 new_settings.c_cc[VMIN] = 1; 2919 /* Set new terminal attributes */ 2920 (void) tcsetattr(0, TCSANOW, &new_settings); 2921 while (((buf[i++] = getchar()) != '\n') && (i < MAX_KEY_LENGTH + 1)) { 2922 (void) putchar('*'); 2923 } 2924 (void) putchar('\n'); 2925 /* Restore terminal attributes */ 2926 (void) tcsetattr(0, TCSANOW, &stored_settings); 2927 (void) fflush(stdin); 2928 2929 if (buf[--i] != '\n') { 2930 (void) fprintf(stderr, gettext("%s: wepkey length " 2931 "exceeds 26 hex digits\n"), gExecName); 2932 free(buf); 2933 return (NULL); 2934 } 2935 /* Replace last char '\n' with '\0' */ 2936 buf[i] = '\0'; 2937 length = (uint8_t)i; 2938 return ((is_wepkey_valid(buf, length) == B_TRUE)? 2939 buf : NULL); 2940 } 2941 2942 /* 2943 * do_set_wepkey: Set parameters in wepkey, and call ioctl 2944 */ 2945 static boolean_t 2946 do_set_wepkey(int fd, const char *pbuf) 2947 { 2948 int id = 0; 2949 char i = 0; 2950 uint8_t len = 0; 2951 uint8_t length; 2952 const char *wepkey = NULL; 2953 char key[MAX_KEY_LENGTH] = {0}; 2954 unsigned int keytmp; 2955 wl_wep_key_tab_t wepkey_tab; 2956 2957 PRTDBG(("do_set_wepkey(%d, \"%s\")\n", fd, pbuf)); 2958 if (!check_authority(AUTH_WEP)) { 2959 exit(WIFI_FATAL_ERR); 2960 } 2961 id = pbuf[strlen("wepkeyn") - 1] - '0'; 2962 wepkey = get_value(pbuf); 2963 length = strlen(wepkey); 2964 switch (length) { 2965 case 10: 2966 case 26: 2967 for (i = 0; i < length / 2; i++) { 2968 (void) sscanf(wepkey + i * 2, "%2x", &keytmp); 2969 key[i] = (char)keytmp; 2970 } 2971 len = length / 2; 2972 break; 2973 case 5: 2974 case 13: 2975 (void) strlcpy(key, wepkey, MAX_KEY_LENGTH); 2976 len = length; 2977 break; 2978 default: 2979 PRTDBG(("do_set_wepkey: error pbuf size\n")); 2980 (void) fprintf(stderr, gettext("%s: " 2981 "wepkey should be:\n" 2982 "\t 40bits: 5 char or 10 hex digits.\n" 2983 "\t 128bits: 13 char or 26 hex digits.\n"), 2984 gExecName); 2985 exit(WIFI_FATAL_ERR); 2986 } 2987 2988 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab)); 2989 for (i = 0; i < MAX_NWEPKEYS; i++) { 2990 wepkey_tab[i].wl_wep_operation = WL_NUL; 2991 } 2992 2993 if (id > 0 && id <= MAX_NWEPKEYS) { 2994 wepkey_tab[id-1].wl_wep_operation = WL_ADD; 2995 wepkey_tab[id-1].wl_wep_length = len; 2996 (void) memcpy(wepkey_tab[id-1].wl_wep_key, key, len); 2997 } else { 2998 (void) fprintf(stderr, gettext("%s: wepkeyindex " 2999 "should be an integer within the range 1-4\n"), gExecName); 3000 exit(WIFI_FATAL_ERR); 3001 } 3002 (void) memmove(gbuf->wldp_buf, &wepkey_tab, sizeof (wl_wep_key_tab_t)); 3003 return (call_ioctl(fd, WLAN_SET_PARAM, WL_WEP_KEY_TAB, 3004 sizeof (wl_wep_key_tab_t))); 3005 } 3006 3007 /* 3008 * get the committed wepkey. the return form is like wepkey1=*****; 3009 */ 3010 /*ARGSUSED*/ 3011 static char * 3012 get_commit_key(int fd, int argc, char **argv) 3013 { 3014 int key; 3015 int len; 3016 char *wepkey = NULL; 3017 char *wepkey_confirm = NULL; 3018 char *pbuf = NULL; 3019 3020 key = atoi(argv[0]); 3021 if (key <= 0 || key > MAX_NWEPKEYS) { 3022 (void) fprintf(stderr, gettext("%s: wepkeyindex " 3023 "should be an integer within the range 1-4\n"), gExecName); 3024 goto exit0; 3025 } 3026 (void) printf(gettext("input wepkey%d:"), key); 3027 wepkey = get_valid_wepkey(); 3028 if (wepkey == NULL) { 3029 goto exit0; 3030 } 3031 (void) printf(gettext("confirm wepkey%d:"), key); 3032 wepkey_confirm = get_valid_wepkey(); 3033 if (wepkey_confirm == NULL) { 3034 free(wepkey); 3035 goto exit0; 3036 } 3037 if (strcmp(wepkey, wepkey_confirm) != 0) { 3038 free(wepkey); 3039 free(wepkey_confirm); 3040 (void) fprintf(stderr, 3041 gettext("%s: wepkey: " 3042 "two inputs are not identical\n"), gExecName); 3043 goto exit0; 3044 } 3045 free(wepkey_confirm); /* wepkey_confirm is no longer used */ 3046 3047 len = MAX_KEY_LENGTH + strlen("wepkey1=\n") + 1; 3048 pbuf = safe_malloc(len); 3049 safe_snprintf(pbuf, len, "%s%d=%s", "wepkey", key, wepkey); 3050 3051 free(wepkey); /* wepkey is no longer used */ 3052 return (pbuf); 3053 exit0: 3054 return (NULL); 3055 } 3056 3057 /* 3058 * do_wepkey: Get input from user, call do_set_wepkey 3059 */ 3060 /*ARGSUSED*/ 3061 static boolean_t 3062 do_wepkey(int fd, int argc, char **argv) 3063 { 3064 char *pbuf; 3065 3066 PRTDBG(("do_wepkey(%d, 0x%x)\n", argc, argv)); 3067 assert(fd > 0); 3068 if (argc <= 0) { 3069 do_print_usage(); 3070 exit(WIFI_IMPROPER_USE); 3071 } 3072 if (argc > 1) { 3073 (void) fprintf(stderr, gettext("%s: trailing useless tokens " 3074 "after 'setwepkey'\n"), gExecName); 3075 } 3076 pbuf = get_commit_key(fd, argc, argv); 3077 if ((pbuf != NULL) && (do_set_wepkey(fd, pbuf) == B_TRUE)) { 3078 free(pbuf); 3079 return (B_TRUE); 3080 } 3081 free(pbuf); 3082 return (B_FALSE); 3083 } 3084 3085 /*ARGSUSED*/ 3086 static boolean_t 3087 do_setprofwepkey(int fd, int argc, char **argv) 3088 { 3089 char *pbuf; 3090 char *section_id = NULL; 3091 section_t *p_section = NULL; 3092 aelist_t *plist = NULL; 3093 3094 PRTDBG(("do_setprofwepkey(%d, 0x%x)\n", argc, argv)); 3095 if (argc < 2) { 3096 do_print_usage(); 3097 exit(WIFI_IMPROPER_USE); 3098 } 3099 if (argc > 2) { 3100 (void) fprintf(stderr, gettext("%s: trailing useless tokens " 3101 "after 'setprofwepkey'\n"), gExecName); 3102 } 3103 3104 section_id = append_pa(argv[0]); 3105 p_section = find_section(gp_wepkey_file, section_id); 3106 free(section_id); 3107 if (p_section == NULL) { 3108 (void) fprintf(stderr, gettext("%s: " 3109 "no such profile: '%s'\n"), 3110 gExecName, argv[0]); 3111 return (B_FALSE); 3112 } 3113 3114 argc--; 3115 argv++; 3116 pbuf = get_commit_key(fd, argc, argv); 3117 if (pbuf == NULL) 3118 return (B_FALSE); 3119 plist = p_section->list; 3120 update_aelist(plist, pbuf); 3121 3122 return (B_TRUE); 3123 } 3124 3125 /* 3126 * do_wlanlist: Scan for wlanlist 3127 */ 3128 /*ARGSUSED*/ 3129 static boolean_t 3130 do_wlanlist(int fd, int argc, char **argv) 3131 { 3132 PRTDBG(("do_wlanlist(%d, 0x%x)\n", argc, argv)); 3133 assert(fd > 0); 3134 if (argc > 0) { 3135 (void) fprintf(stderr, gettext("%s: trailing useless tokens " 3136 "after 'scan'\n"), gExecName); 3137 } 3138 if (call_ioctl(fd, WLAN_COMMAND, WL_SCAN, 0) == B_FALSE) { 3139 (void) fprintf(stderr, gettext("%s: failed to scan\n"), 3140 gExecName); 3141 return (B_FALSE); 3142 } 3143 if (do_get_wlanlist(fd) == B_TRUE) { 3144 print_gbuf(WLANLIST); 3145 } 3146 return (B_TRUE); 3147 } 3148 3149 /* 3150 * do_showstatus: show the basic status of the interface, including 3151 * linkstatus, essid, encryption and signal strength. 3152 */ 3153 /*ARGSUSED*/ 3154 static boolean_t 3155 do_showstatus(int fd, int argc, char **argv) 3156 { 3157 wl_rssi_t signal; 3158 char *active_profile = NULL; 3159 3160 PRTDBG(("do_showstatus(%d, 0x%x)\n", argc, argv)); 3161 assert(fd > 0); 3162 3163 if (argc > 0) { 3164 (void) fprintf(stderr, gettext("%s: trailing useless tokens " 3165 "after 'showstatus'\n"), gExecName); 3166 } 3167 if (do_get_linkstatus(fd) == B_TRUE) { 3168 print_gbuf(LINKSTATUS); 3169 if (*(wl_linkstatus_t *)(gbuf->wldp_buf) == WL_NOTCONNECTED) { 3170 return (B_TRUE); 3171 } 3172 } 3173 active_profile = find_active_profile(fd); 3174 (void) printf("\tactive profile: %s\n", 3175 active_profile ? active_profile : "none"); 3176 if (do_get_essid(fd) == B_TRUE) { 3177 print_gbuf(ESSID); 3178 } 3179 if (do_get_bssid(fd) == B_TRUE) { 3180 print_gbuf(BSSID); 3181 } 3182 if (do_get_encryption(fd) == B_TRUE) { 3183 print_gbuf(ENCRYPTION); 3184 } 3185 if (do_get_signal(fd) == B_TRUE) { 3186 signal = *(wl_rssi_t *)(gbuf->wldp_buf); 3187 if (signal < 4) { 3188 (void) printf("\tsignal strength: weak(%d)\n", 3189 signal); 3190 } else if ((signal >= 4) && (signal <= 11)) { 3191 (void) printf("\tsignal strength: medium(%d)\n", 3192 signal); 3193 } else { 3194 (void) printf("\tsignal strength: strong(%d)\n", 3195 signal); 3196 } 3197 } 3198 3199 return (B_TRUE); 3200 } 3201 3202 3203 /* 3204 * do_restoredef: Ask driver for loading default parameters 3205 */ 3206 /*ARGSUSED*/ 3207 static boolean_t 3208 do_restoredef(int fd, int argc, char **argv) 3209 { 3210 PRTDBG(("do_restoredef(%d, 0x%x)\n", argc, argv)); 3211 assert(fd > 0); 3212 3213 if (argc > 0) { 3214 (void) fprintf(stderr, gettext("%s: trailing useless tokens " 3215 "after 'restoredef'\n"), gExecName); 3216 } 3217 record_active_profile(NULL, RECORD_DEL); 3218 if (call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0) == B_FALSE) { 3219 return (B_FALSE); 3220 } else { 3221 return (B_TRUE); 3222 } 3223 } 3224 3225 /* 3226 * do_disconnect: disconnect from the current connectted network 3227 */ 3228 /*ARGSUSED*/ 3229 static boolean_t 3230 do_disconnect(int fd, int argc, char **argv) 3231 { 3232 PRTDBG(("do_disconnect(%d, 0x%x)\n", argc, argv)); 3233 assert(fd > 0); 3234 3235 if (argc > 0) { 3236 (void) fprintf(stderr, gettext("%s: trailing useless tokens " 3237 "after 'disconnect'\n"), gExecName); 3238 } 3239 record_active_profile(NULL, RECORD_DEL); 3240 if (call_ioctl(fd, WLAN_COMMAND, WL_DISASSOCIATE, 0) == B_FALSE) { 3241 return (B_FALSE); 3242 } else { 3243 return (B_TRUE); 3244 } 3245 } 3246 3247 static boolean_t 3248 do_set_essid(int fd, const char *arg) 3249 { 3250 wl_essid_t essid; 3251 3252 PRTDBG(("do_set_essid(%d, \"%s\")\n", fd, arg)); 3253 3254 /* 3255 * a trick here: clean the active_profile flag 3256 * in section{active_profile} 3257 */ 3258 record_active_profile(NULL, RECORD_DEL); 3259 3260 (void) memset(&essid, 0x0, sizeof (essid)); 3261 3262 if (arg == NULL || strcmp(arg, "") == 0) { 3263 essid.wl_essid_length = 0; 3264 essid.wl_essid_essid[0] = '\0'; 3265 } else { 3266 essid.wl_essid_length = strlen(arg); 3267 if (essid.wl_essid_length > MAX_ESSID_LENGTH - 1) { 3268 (void) fprintf(stderr, gettext("%s: " 3269 "essid exceeds 32 bytes\n"), gExecName); 3270 exit(WIFI_FATAL_ERR); 3271 } 3272 (void) strcpy(essid.wl_essid_essid, arg); 3273 } 3274 (void) memmove(gbuf->wldp_buf, &essid, sizeof (wl_essid_t)); 3275 return (call_ioctl(fd, WLAN_SET_PARAM, WL_ESSID, sizeof (wl_essid_t))); 3276 } 3277 3278 static boolean_t 3279 do_set_bsstype(int fd, const char *arg) 3280 { 3281 wl_bss_type_t bsstype; 3282 3283 assert(arg != NULL); 3284 3285 PRTDBG(("do_set_bsstype(%d, \"%s\")\n", fd, arg)); 3286 3287 (void) memset(&bsstype, 0xff, sizeof (bsstype)); 3288 3289 if ((strcasecmp(arg, "BSS") == 0) || 3290 (strcasecmp(arg, "AP") == 0) || 3291 (strcasecmp(arg, "INFRASTRUCTURE") == 0)) { 3292 bsstype = WL_BSS_BSS; 3293 } else if ((strcasecmp(arg, "IBSS") == 0) || 3294 (strcasecmp(arg, "AD-HOC") == 0)) { 3295 bsstype = WL_BSS_IBSS; 3296 } else if (strcasecmp(arg, "AUTO") == 0) { 3297 bsstype = WL_BSS_ANY; 3298 } else { 3299 (void) fprintf(stderr, gettext("%s: bsstype: " 3300 "bss(ap,infrastructure) ibss(ad-hoc) or auto\n"), 3301 gExecName); 3302 exit(WIFI_FATAL_ERR); 3303 } 3304 3305 (void) memmove(gbuf->wldp_buf, &bsstype, sizeof (wl_bss_type_t)); 3306 return (call_ioctl(fd, WLAN_SET_PARAM, WL_BSS_TYPE, 3307 sizeof (wl_bss_type_t))); 3308 } 3309 3310 static boolean_t 3311 do_set_createibss(int fd, const char *arg) 3312 { 3313 wl_create_ibss_t create_ibss; 3314 3315 assert(arg != NULL); 3316 3317 PRTDBG(("do_set_createibss(%d, \"%s\")\n", fd, arg)); 3318 3319 (void) memset(&create_ibss, 0x0, sizeof (create_ibss)); 3320 3321 if (strcasecmp(arg, "YES") == 0) { 3322 create_ibss = B_TRUE; 3323 } else if (strcasecmp(arg, "NO") == 0) { 3324 create_ibss = B_FALSE; 3325 } else { 3326 (void) fprintf(stderr, gettext("%s: " 3327 "createibss: yes or no\n"), gExecName); 3328 exit(WIFI_FATAL_ERR); 3329 } 3330 3331 (void) memmove(gbuf->wldp_buf, &create_ibss, 3332 sizeof (wl_create_ibss_t)); 3333 return (call_ioctl(fd, WLAN_SET_PARAM, WL_CREATE_IBSS, 3334 sizeof (wl_create_ibss_t))); 3335 } 3336 3337 static boolean_t 3338 do_set_channel(int fd, const char *arg) 3339 { 3340 wl_phy_conf_t phy_conf; 3341 3342 assert(arg != NULL); 3343 PRTDBG(("do_set_channel(%d, \"%s\")\n", fd, arg)); 3344 3345 (void) memset(&phy_conf, 0xff, sizeof (phy_conf)); 3346 3347 if (is_channel_valid(arg) == B_FALSE) { 3348 (void) fprintf(stderr, gettext("%s: channel No. " 3349 "should be:\n" 3350 "\t802.11a: 0-99\n" 3351 "\t802.11b: 1-14\n" 3352 "\t802.11g: 1-14\n"), gExecName); 3353 exit(WIFI_FATAL_ERR); 3354 } 3355 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = atoi(arg); 3356 PRTDBG(("channel=%d\n", phy_conf.wl_phy_dsss_conf.wl_dsss_channel)); 3357 3358 (void) memmove(gbuf->wldp_buf, &phy_conf, sizeof (wl_phy_conf_t)); 3359 return (call_ioctl(fd, WLAN_SET_PARAM, WL_PHY_CONFIG, 3360 sizeof (wl_phy_conf_t))); 3361 } 3362 /* 3363 * is_rates_support: Querying driver about supported rates. 3364 */ 3365 static boolean_t 3366 is_rates_support(int fd, int num, uint8_t *rates) 3367 { 3368 int rates_num = 0; 3369 int i = 0, j = 0; 3370 uint8_t value = 0; 3371 3372 assert((rates != NULL)&&(num != 0)); 3373 PRTDBG(("is_rates_support(%d, %d, 0x%x)\n", fd, num, rates)); 3374 3375 if (call_ioctl(fd, WLAN_GET_PARAM, WL_SUPPORTED_RATES, 0) 3376 == B_TRUE) { 3377 rates_num = ((wl_rates_t *)(gbuf->wldp_buf))->wl_rates_num; 3378 3379 for (i = 0; i < num; i++) { 3380 PRTDBG(("rates[%d] = %d\n", i, rates[i])); 3381 for (j = 0; j < rates_num; j++) { 3382 value = ((wl_rates_t *)gbuf->wldp_buf) 3383 ->wl_rates_rates[j]; 3384 PRTDBG(("supported rates[%d]=%d\n", j, value)); 3385 if (value == rates[i]) { 3386 break; 3387 } 3388 } 3389 if (j == rates_num) { 3390 if (rates[i] == 11) { 3391 (void) fprintf(stderr, 3392 gettext("%s: " 3393 "rate 5.5M is not supported\n"), 3394 gExecName); 3395 } else { 3396 (void) fprintf(stderr, 3397 gettext("%s: " 3398 "rate %dM is not supported\n"), 3399 gExecName, rates[i]/2); 3400 } 3401 return (B_FALSE); 3402 } 3403 } 3404 return (B_TRUE); 3405 } 3406 return (B_FALSE); 3407 } 3408 3409 /* 3410 * 3411 */ 3412 static uint8_t 3413 rates_convert(const char *rates) 3414 { 3415 int i; 3416 uint8_t ret; 3417 3418 for (i = 0; i < WIFI_RATES_NUM; i++) { 3419 if (strcmp(rates, wifi_rates_s[i].rates_s) == 0) { 3420 ret = wifi_rates_s[i].rates_i; 3421 break; 3422 } 3423 } 3424 if (i == WIFI_RATES_NUM) { 3425 (void) fprintf(stderr, gettext("%s: " 3426 "invalid rates '%s'\n"), gExecName, rates); 3427 exit(WIFI_FATAL_ERR); 3428 } 3429 return (ret); 3430 } 3431 3432 /* 3433 * get_rates: convert string value arg into uint8_t array, 3434 * array length will be save into *len[i]. 3435 * for example: 3436 * arg = "1,2,5.5,11" 3437 * then after call, rates[] = {2,4,11,22} will be returned. 3438 * and *len will equal to 4 3439 */ 3440 static uint8_t * 3441 get_rates(const char *arg, uint32_t *len) 3442 { 3443 int i = 1, j = 0; 3444 uint8_t *rates = NULL; 3445 char *pnext = NULL; 3446 char *token; 3447 char *pstart; 3448 char *pstart_bak; 3449 3450 assert(arg != NULL); 3451 3452 if (strlen(arg) == 0) { 3453 PRTDBG(("get_rates: empty rates string\n")); 3454 return (NULL); 3455 } 3456 PRTDBG(("get_rates(\"%s\", 0x%x)\n", arg, len)); 3457 pstart = safe_strdup(arg); 3458 pstart_bak = pstart; 3459 while ((pnext = strchr(pstart, ',')) != NULL) { 3460 pstart = pnext + 1; 3461 i++; 3462 } 3463 *len = i; 3464 rates = safe_calloc(sizeof (uint8_t), i); 3465 3466 pstart = pstart_bak; 3467 if ((token = strtok(pstart, ",")) != NULL) { 3468 PRTDBG(("rates[0]: %s\n", token)); 3469 rates[0] = rates_convert(token); 3470 i = 1; 3471 while ((token = strtok(NULL, ",")) != NULL) { 3472 PRTDBG(("rates[%d]: %s\n", i, token)); 3473 rates[i++] = rates_convert(token); 3474 } 3475 } 3476 free(pstart_bak); 3477 for (i = 0; i < *len; i++) { 3478 for (j = 0; j < i; j++) 3479 if (rates[j] == rates[i]) { 3480 (void) fprintf(stderr, 3481 gettext("%s: rates duplicated\n"), 3482 gExecName); 3483 free(rates); 3484 return (NULL); 3485 } 3486 } 3487 3488 return (rates); 3489 } 3490 3491 static boolean_t 3492 do_set_rates(int fd, const char *arg) 3493 { 3494 int i = 0; 3495 uint32_t num = 0; 3496 uint8_t *rates; 3497 3498 assert(arg != NULL); 3499 3500 PRTDBG(("do_set_rates(%d, \"%s\")\n", fd, arg)); 3501 3502 rates = get_rates(arg, &num); 3503 if ((rates == NULL) || 3504 is_rates_support(fd, num, rates) == B_FALSE) { 3505 exit(WIFI_FATAL_ERR); 3506 } 3507 3508 ((wl_rates_t *)(gbuf->wldp_buf))->wl_rates_num = num; 3509 for (i = 0; i < num; i++) { 3510 ((wl_rates_t *)gbuf->wldp_buf)->wl_rates_rates[i] 3511 = rates[i]; 3512 } 3513 free(rates); 3514 return (call_ioctl(fd, WLAN_SET_PARAM, WL_DESIRED_RATES, 3515 offsetof(wl_rates_t, wl_rates_rates) + 3516 num*sizeof (char))); 3517 } 3518 3519 static boolean_t 3520 do_set_powermode(int fd, const char *arg) 3521 { 3522 wl_ps_mode_t ps_mode; 3523 3524 assert(arg != NULL); 3525 3526 PRTDBG(("do_set_powermode(%d, \"%s\")\n", fd, arg)); 3527 3528 (void) memset(&ps_mode, 0xff, sizeof (ps_mode)); 3529 3530 if ((strcasecmp(arg, "OFF") == 0) || 3531 (strcasecmp(arg, "MPS") == 0) || 3532 (strcasecmp(arg, "FAST") == 0)) { 3533 switch (arg[0]) { 3534 case 'O': 3535 case 'o': 3536 ps_mode.wl_ps_mode = WL_PM_AM; 3537 break; 3538 case 'M': 3539 case 'm': 3540 ps_mode.wl_ps_mode = WL_PM_MPS; 3541 break; 3542 case 'F': 3543 case 'f': 3544 ps_mode.wl_ps_mode = WL_PM_FAST; 3545 break; 3546 default: 3547 break; 3548 } 3549 } else { 3550 (void) fprintf(stderr, 3551 gettext("%s: powermode: off mps or fast\n"), gExecName); 3552 exit(WIFI_FATAL_ERR); 3553 } 3554 3555 (void) memmove(gbuf->wldp_buf, &ps_mode, sizeof (wl_ps_mode_t)); 3556 return (call_ioctl(fd, WLAN_SET_PARAM, WL_POWER_MODE, 3557 sizeof (wl_ps_mode_t))); 3558 } 3559 3560 static boolean_t 3561 do_set_authmode(int fd, const char *arg) 3562 { 3563 wl_authmode_t auth_mode; 3564 3565 assert(arg != NULL); 3566 PRTDBG(("do_set_authmode(%d, \"%s\")\n", fd, arg)); 3567 3568 (void) memset(&auth_mode, 0xff, sizeof (auth_mode)); 3569 /* Mark */ 3570 if (strcasecmp(arg, "OPENSYSTEM") == 0) { 3571 auth_mode = WL_OPENSYSTEM; 3572 } else if (strcasecmp(arg, "SHARED_KEY") == 0) { 3573 auth_mode = WL_SHAREDKEY; 3574 } else { 3575 (void) fprintf(stderr, 3576 gettext("%s: authmode: " 3577 "opensystem or shared_key\n"), gExecName); 3578 exit(WIFI_FATAL_ERR); 3579 } 3580 3581 (void) memmove(gbuf->wldp_buf, &auth_mode, sizeof (wl_authmode_t)); 3582 return (call_ioctl(fd, WLAN_SET_PARAM, WL_AUTH_MODE, 3583 sizeof (wl_authmode_t))); 3584 } 3585 3586 static boolean_t 3587 do_set_encryption(int fd, const char *arg) 3588 { 3589 wl_encryption_t encryption; 3590 3591 assert(arg != NULL); 3592 PRTDBG(("do_set_encryption(%d, \"%s\")\n", fd, arg)); 3593 3594 (void) memset(&encryption, 0xff, sizeof (encryption)); 3595 3596 if (strcasecmp(arg, "NONE") == 0) { 3597 encryption = WL_NOENCRYPTION; 3598 } else if (strcasecmp(arg, "WEP") == 0) { 3599 encryption = WL_ENC_WEP; 3600 } else { 3601 (void) fprintf(stderr, gettext("%s: encryption: " 3602 "none or wep\n"), gExecName); 3603 exit(WIFI_FATAL_ERR); 3604 } 3605 3606 (void) memmove(gbuf->wldp_buf, &encryption, sizeof (wl_encryption_t)); 3607 return (call_ioctl(fd, WLAN_SET_PARAM, WL_ENCRYPTION, 3608 sizeof (wl_encryption_t))); 3609 } 3610 3611 static boolean_t 3612 do_set_wepkeyid(int fd, const char *arg) 3613 { 3614 wl_wep_key_id_t wep_key_id; 3615 3616 assert(arg != NULL); 3617 PRTDBG(("do_set_wepkeyid(%d, \"%s\")\n", fd, arg)); 3618 3619 (void) memset(&wep_key_id, 0xff, sizeof (wep_key_id)); 3620 if (is_wepkeyindex_valid(arg) == B_FALSE) { 3621 (void) fprintf(stderr, gettext("%s: wepkeyindex " 3622 "should be an integer within the range 1-4\n"), gExecName); 3623 exit(WIFI_FATAL_ERR); 3624 } 3625 wep_key_id = atoi(arg) - 1; 3626 3627 (void) memmove(gbuf->wldp_buf, &wep_key_id, sizeof (wl_wep_key_id_t)); 3628 return (call_ioctl(fd, WLAN_SET_PARAM, WL_WEP_KEY_ID, 3629 sizeof (wl_wep_key_id_t))); 3630 } 3631 3632 static boolean_t 3633 do_set_radioon(int fd, const char *arg) 3634 { 3635 wl_radio_t radio; 3636 3637 assert(arg != NULL); 3638 PRTDBG(("do_set_radioon(%d, \"%s\")\n", fd, arg)); 3639 3640 (void) memset(&radio, 0xff, sizeof (radio)); 3641 3642 if (strcasecmp(arg, "ON") == 0) { 3643 radio = B_TRUE; 3644 } else if (strcasecmp(arg, "OFF") == 0) { 3645 radio = B_FALSE; 3646 } else { 3647 (void) fprintf(stderr, 3648 gettext("%s: radio : on or off\n"), gExecName); 3649 exit(WIFI_FATAL_ERR); 3650 } 3651 3652 (void) memmove(gbuf->wldp_buf, &radio, sizeof (wl_radio_t)); 3653 return (call_ioctl(fd, WLAN_SET_PARAM, WL_RADIO, sizeof (wl_radio_t))); 3654 } 3655 /* 3656 * print_gbuf: After each ioctl system call, gbuf will contain result, gbuf 3657 * contents's format varies from each kind of ioctl system call. 3658 */ 3659 static void 3660 print_gbuf(config_item_t index) 3661 { 3662 int i = 0, j = 0; 3663 uint32_t ess_num; 3664 char **ess_argv; 3665 uint32_t rates_num; 3666 uint32_t subtype; 3667 wl_bss_type_t bsstype; 3668 wl_create_ibss_t createibss; 3669 wl_ps_mode_t *ps_mode; 3670 wl_authmode_t authmode; 3671 wl_encryption_t encryption; 3672 wl_wep_key_id_t wepkeyid; 3673 wl_rssi_t signal; 3674 wl_radio_t radioon; 3675 wl_ess_conf_t **p_ess_conf; 3676 wl_linkstatus_t linkstatus; 3677 char format[256], *ntstr; 3678 uint32_t maxessidlen = 0, nt = 0, cnt = 0; 3679 int len; 3680 uint8_t bssid[6]; 3681 3682 PRTDBG(("print_gbuf(%d)\n", index)); 3683 assert(gbuf->wldp_length < MAX_BUF_LEN); 3684 3685 switch (index) { 3686 case BSSID: 3687 (void) printf("\tbssid: "); 3688 (void) memset(bssid, 0, sizeof (bssid)); 3689 if (memcmp((uint8_t *)gbuf->wldp_buf, bssid, sizeof (bssid)) 3690 == 0) { 3691 (void) printf("none\n"); 3692 break; 3693 } 3694 (void) memset(bssid, 0xff, sizeof (bssid)); 3695 if (memcmp((uint8_t *)gbuf->wldp_buf, bssid, sizeof (bssid)) 3696 == 0) { 3697 (void) printf("none\n"); 3698 break; 3699 } 3700 for (i = 0; i < 5; i++) 3701 (void) printf("%02x:", ((uint8_t *)gbuf->wldp_buf)[i]); 3702 (void) printf("%02x\n", ((uint8_t *)gbuf->wldp_buf)[i]); 3703 break; 3704 case ESSID: 3705 (void) printf("\tessid: %s\n", ((wl_essid_t *)(gbuf->wldp_buf)) 3706 ->wl_essid_essid); 3707 break; 3708 case BSSTYPE: 3709 bsstype = *(wl_bss_type_t *)(gbuf->wldp_buf); 3710 switch (bsstype) { 3711 case WL_BSS_BSS: 3712 (void) printf("\tbsstype: bss(ap, infrastructure)\n"); 3713 break; 3714 case WL_BSS_IBSS: 3715 (void) printf("\tbsstype: ibss(ad-hoc)\n"); 3716 break; 3717 case WL_BSS_ANY: 3718 (void) printf("\tbsstype: auto\n"); 3719 break; 3720 default: 3721 (void) fprintf(stderr, 3722 gettext("%s: " 3723 "invalid bsstype value\n"), gExecName); 3724 } 3725 break; 3726 case CREATEIBSS: 3727 createibss = *(wl_create_ibss_t *)(gbuf->wldp_buf); 3728 switch (createibss) { 3729 case B_TRUE: 3730 (void) printf("\tcreateibss: yes\n"); 3731 break; 3732 case B_FALSE: 3733 (void) printf("\tcreateibss: no\n"); 3734 break; 3735 default: 3736 (void) fprintf(stderr, 3737 gettext("%s: " 3738 "invalid createibss value\n"), gExecName); 3739 } 3740 break; 3741 case CHANNEL: 3742 subtype = ((wl_fhss_t *)(gbuf->wldp_buf))->wl_fhss_subtype; 3743 switch (subtype) { 3744 case WL_FHSS: 3745 case WL_DSSS: 3746 case WL_IRBASE: 3747 case WL_HRDS: 3748 case WL_ERP: 3749 (void) printf("\tchannel: %d\n", ((wl_fhss_t *) 3750 (gbuf->wldp_buf))->wl_fhss_channel); 3751 break; 3752 case WL_OFDM: 3753 (void) printf("\tchannel: %d\n", ((wl_ofdm_t *) 3754 (gbuf->wldp_buf)) 3755 ->wl_ofdm_frequency); 3756 break; 3757 default: 3758 (void) fprintf(stderr, gettext("%s: " 3759 "invalid subtype\n"), gExecName); 3760 break; 3761 } 3762 break; 3763 case RATES: 3764 rates_num = ((wl_rates_t *)(gbuf->wldp_buf))->wl_rates_num; 3765 (void) printf("\trates: "); 3766 for (i = 0; i < rates_num; i++) { 3767 char rate; 3768 rate = ((wl_rates_t *)gbuf->wldp_buf) 3769 ->wl_rates_rates[i]; 3770 if (rate == WL_RATE_5_5M) 3771 (void) printf("5.5"); 3772 else 3773 (void) printf("%d", (uint8_t)(rate / 2)); 3774 3775 if (i == (rates_num - 1)) 3776 (void) printf("\n"); 3777 else 3778 (void) printf(","); 3779 } 3780 break; 3781 case POWERMODE: 3782 ps_mode = (wl_ps_mode_t *)(gbuf->wldp_buf); 3783 switch (ps_mode->wl_ps_mode) { 3784 case WL_PM_AM: 3785 (void) printf("\tpowermode: off\n"); 3786 break; 3787 case WL_PM_MPS: 3788 (void) printf("\tpowermode: mps\n"); 3789 break; 3790 case WL_PM_FAST: 3791 (void) printf("\tpowermode: fast\n"); 3792 break; 3793 default: 3794 (void) fprintf(stderr, 3795 gettext("%s: " 3796 "invalid powermode value\n"), gExecName); 3797 break; 3798 } 3799 break; 3800 case AUTHMODE: 3801 authmode = *(wl_authmode_t *)(gbuf->wldp_buf); 3802 switch (authmode) { 3803 case WL_OPENSYSTEM: 3804 (void) printf("\tauthmode: opensystem\n"); 3805 break; 3806 case WL_SHAREDKEY: 3807 (void) printf("\tauthmode: shared_key\n"); 3808 break; 3809 default: 3810 (void) fprintf(stderr, 3811 gettext("%s: " 3812 "invalid authmode value\n"), gExecName); 3813 break; 3814 } 3815 break; 3816 case ENCRYPTION: 3817 encryption = *(wl_encryption_t *)(gbuf->wldp_buf); 3818 switch (encryption) { 3819 case WL_NOENCRYPTION: 3820 (void) printf("\tencryption: none\n"); 3821 break; 3822 case WL_ENC_WEP: 3823 (void) printf("\tencryption: wep\n"); 3824 break; 3825 default: 3826 (void) fprintf(stderr, 3827 gettext("%s: " 3828 "invalid encryption value\n"), gExecName); 3829 break; 3830 } 3831 break; 3832 case WEPKEYID: 3833 wepkeyid = *(wl_wep_key_id_t *)(gbuf->wldp_buf); 3834 (void) printf("\twepkeyindex: %d\n", wepkeyid + 1); 3835 break; 3836 case SIGNAL: 3837 signal = *(wl_rssi_t *)(gbuf->wldp_buf); 3838 (void) printf("\tsignal: %d\n", signal); 3839 break; 3840 case RADIOON: 3841 radioon = *(wl_radio_t *)(gbuf->wldp_buf); 3842 switch (radioon) { 3843 case B_TRUE: 3844 (void) printf("\tradio: on\n"); 3845 break; 3846 case B_FALSE: 3847 (void) printf("\tradio: off\n"); 3848 break; 3849 default: /* Mark */ 3850 (void) fprintf(stderr, 3851 gettext("%s: " 3852 "invalid radioon value\n"), gExecName); 3853 } 3854 break; 3855 case LINKSTATUS: 3856 linkstatus = *(wl_linkstatus_t *)(gbuf->wldp_buf); 3857 switch (linkstatus) { 3858 case WL_CONNECTED: 3859 (void) printf("\tlinkstatus: connected\n"); 3860 break; 3861 case WL_NOTCONNECTED: 3862 (void) printf("\tlinkstatus: not connected\n"); 3863 break; 3864 default: /* Mark */ 3865 (void) fprintf(stderr, 3866 gettext("%s: " 3867 "invalid linkstatus value\n"), gExecName); 3868 } 3869 break; 3870 case WLANLIST: 3871 ess_num = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num; 3872 ess_argv = safe_calloc(sizeof (char *), ess_num); 3873 p_ess_conf = safe_calloc(sizeof (wl_ess_conf_t *), ess_num); 3874 for (i = 0; i < ess_num; i++) { 3875 p_ess_conf[i] = ((wl_ess_list_t *)gbuf->wldp_buf) 3876 ->wl_ess_list_ess + i; 3877 maxessidlen = (maxessidlen > 3878 strlen(p_ess_conf[i] 3879 ->wl_ess_conf_essid.wl_essid_essid) ? 3880 maxessidlen : 3881 strlen(p_ess_conf[i] 3882 ->wl_ess_conf_essid.wl_essid_essid)); 3883 } 3884 /* 3885 * construct the output format. 3886 */ 3887 if ((nt = (maxessidlen / 8 + 1)) > 4) 3888 nt = 4; 3889 len = snprintf(format, sizeof (format), gettext("essid")); 3890 ntstr = construct_format(nt); 3891 assert(ntstr != NULL); 3892 len += snprintf(format + len, sizeof (format) - len, "%s", 3893 ntstr); 3894 len += snprintf(format + len, sizeof (format) - len, 3895 gettext("bssid\t\t type\t\tencryption\tsignallevel\n")); 3896 3897 if ((len <= 0) || (len > sizeof (format) - 1)) { 3898 (void) printf("essid\t\t\t\tbssid\t\t type\t\t" 3899 "encryption\tsignallevel\n"); 3900 } else { 3901 (void) printf("%s", format); 3902 } 3903 3904 for (i = 0; i < ess_num; i++) { 3905 ess_argv[i] = safe_malloc(MAX_SCANBUF_LEN); 3906 safe_snprintf(ess_argv[i], MAX_SCANBUF_LEN, 3907 "%s%c%02x:%02x:%02x:%02x:%02x:%02x%c%s", 3908 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid, 3909 ',', 3910 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[0]), 3911 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[1]), 3912 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[2]), 3913 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[3]), 3914 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[4]), 3915 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[5]), ',', 3916 (p_ess_conf[i]->wl_ess_conf_wepenabled == 3917 B_TRUE ? "wep":"none")); 3918 len = strlen(p_ess_conf[i]->wl_ess_conf_essid. 3919 wl_essid_essid); 3920 cnt = nt - (min(len /8 + 1, 4) - 1); 3921 ntstr = construct_format(cnt); 3922 assert(ntstr != NULL); 3923 (void) printf("%s%s", p_ess_conf[i]->wl_ess_conf_essid. 3924 wl_essid_essid, ntstr); 3925 free(ntstr); 3926 for (j = 0; j < 5; j++) { 3927 (void) printf("%02x:", (uint8_t)(p_ess_conf[i] 3928 ->wl_ess_conf_bssid[j])); 3929 } 3930 (void) printf("%02x ", (uint8_t)(p_ess_conf[i] 3931 ->wl_ess_conf_bssid[j])); 3932 3933 if (p_ess_conf[i]->wl_ess_conf_bsstype == 3934 WL_BSS_BSS) 3935 (void) printf("access point"); 3936 else 3937 (void) printf("ad-hoc"); 3938 if (p_ess_conf[i]->wl_ess_conf_wepenabled == 3939 WL_ENC_WEP) 3940 (void) printf("\twep\t"); 3941 else 3942 (void) printf("\tnone\t"); 3943 (void) printf("\t%d\n", p_ess_conf[i]->wl_ess_conf_sl); 3944 } 3945 add_to_history(gp_config_file, ess_num, ess_argv); 3946 free(p_ess_conf); 3947 for (i = 0; i < ess_num; i++) { 3948 free(ess_argv[i]); 3949 } 3950 free(ess_argv); 3951 break; 3952 default: 3953 (void) fprintf(stderr, gettext("%s: " 3954 "invalid parameter type\n"), gExecName); 3955 break; 3956 } 3957 } 3958 /* 3959 * do_get_xxx: will send ioctl to driver, then the driver will fill gbuf 3960 * with related value. gbuf has a format of wldp_t structure. 3961 */ 3962 static boolean_t 3963 do_get_bssid(int fd) 3964 { 3965 PRTDBG(("do_get_bssid(%d)\n", fd)); 3966 return (call_ioctl(fd, WLAN_GET_PARAM, WL_BSSID, 0)); 3967 } 3968 3969 static boolean_t 3970 do_get_essid(int fd) 3971 { 3972 PRTDBG(("do_get_essid(%d)\n", fd)); 3973 return (call_ioctl(fd, WLAN_GET_PARAM, WL_ESSID, 0)); 3974 } 3975 3976 static boolean_t 3977 do_get_bsstype(int fd) 3978 { 3979 PRTDBG(("do_get_bsstype(%d)\n", fd)); 3980 return (call_ioctl(fd, WLAN_GET_PARAM, WL_BSS_TYPE, 0)); 3981 } 3982 3983 static boolean_t 3984 do_get_createibss(int fd) 3985 { 3986 PRTDBG(("do_get_createibss(%d)\n", fd)); 3987 return (call_ioctl(fd, WLAN_GET_PARAM, WL_CREATE_IBSS, 0)); 3988 } 3989 3990 static boolean_t 3991 do_get_channel(int fd) 3992 { 3993 PRTDBG(("do_get_channel(%d)\n", fd)); 3994 return (call_ioctl(fd, WLAN_GET_PARAM, WL_PHY_CONFIG, 0)); 3995 } 3996 3997 static boolean_t 3998 do_get_wlanlist(int fd) 3999 { 4000 PRTDBG(("do_get_wlanlist(%d)\n", fd)); 4001 return (call_ioctl(fd, WLAN_GET_PARAM, WL_ESS_LIST, 0)); 4002 } 4003 4004 static boolean_t 4005 do_get_linkstatus(int fd) 4006 { 4007 PRTDBG(("do_get_linkstatus(%d)\n", fd)); 4008 return (call_ioctl(fd, WLAN_GET_PARAM, WL_LINKSTATUS, 0)); 4009 } 4010 4011 static boolean_t 4012 do_get_rates(int fd) 4013 { 4014 PRTDBG(("do_get_rates(%d)\n", fd)); 4015 return (call_ioctl(fd, WLAN_GET_PARAM, WL_DESIRED_RATES, 0)); 4016 } 4017 4018 static boolean_t 4019 do_get_powermode(int fd) 4020 { 4021 PRTDBG(("do_get_powermode(%d)\n", fd)); 4022 return (call_ioctl(fd, WLAN_GET_PARAM, WL_POWER_MODE, 0)); 4023 } 4024 4025 static boolean_t 4026 do_get_authmode(int fd) 4027 { 4028 PRTDBG(("do_get_authmode(%d)\n", fd)); 4029 return (call_ioctl(fd, WLAN_GET_PARAM, WL_AUTH_MODE, 0)); 4030 } 4031 4032 static boolean_t 4033 do_get_encryption(int fd) 4034 { 4035 PRTDBG(("do_get_encryption(%d)\n", fd)); 4036 return (call_ioctl(fd, WLAN_GET_PARAM, WL_ENCRYPTION, 0)); 4037 } 4038 4039 static boolean_t 4040 do_get_wepkeyid(int fd) 4041 { 4042 PRTDBG(("do_get_wepkeyid(%d)\n", fd)); 4043 return (call_ioctl(fd, WLAN_GET_PARAM, WL_WEP_KEY_ID, 0)); 4044 } 4045 static boolean_t 4046 do_get_signal(int fd) 4047 { 4048 PRTDBG(("do_get_signal(%d)\n", fd)); 4049 return (call_ioctl(fd, WLAN_GET_PARAM, WL_RSSI, 0)); 4050 } 4051 4052 static boolean_t 4053 do_get_radioon(int fd) 4054 { 4055 PRTDBG(("do_get_radioon(%d)\n", fd)); 4056 return (call_ioctl(fd, WLAN_GET_PARAM, WL_RADIO, 0)); 4057 } 4058 4059 /* 4060 * param has two kinds of forms: 4061 * 'wepkeyn=*****' (when equalflag == B_TRUE), 4062 * 'wepkeyn' (when equalflag == B_FALSE) 4063 */ 4064 static boolean_t 4065 param_is_wepkey(char *param, boolean_t equalflag) 4066 { 4067 if ((equalflag == B_FALSE) && 4068 (strcmp(param, "wepkey1") == 0) || 4069 (strcmp(param, "wepkey2") == 0) || 4070 (strcmp(param, "wepkey3") == 0) || 4071 (strcmp(param, "wepkey4") == 0)) 4072 return (B_TRUE); 4073 else if ((equalflag == B_TRUE) && 4074 (strncmp(param, "wepkey1=", strlen("wepkey1="))) == 0 || 4075 (strncmp(param, "wepkey2=", strlen("wepkey2="))) == 0 || 4076 (strncmp(param, "wepkey3=", strlen("wepkey3="))) == 0 || 4077 (strncmp(param, "wepkey4=", strlen("wepkey4="))) == 0) 4078 return (B_TRUE); 4079 else 4080 return (B_FALSE); 4081 } 4082 4083 /* 4084 * update/add items in the profile 4085 */ 4086 static boolean_t 4087 items_in_profile(aelist_t *cplist, aelist_t *wplist, int argc, char **argv) 4088 { 4089 int i = 0, j = 0; 4090 char *param; 4091 char *pequal; 4092 const char *wepkey; 4093 4094 for (i = 0; i < argc; i++) { 4095 if (param_is_wepkey(argv[i], B_TRUE) == B_TRUE) { 4096 wepkey = get_value(argv[i]); 4097 if (value_is_valid(WEPKEY, wepkey) == B_FALSE) { 4098 (void) fprintf(stderr, gettext("%s: " 4099 "invalid value '%s' for parameter " 4100 "'wepkey'\n"), gExecName, wepkey); 4101 return (B_FALSE); 4102 } 4103 update_aelist(wplist, argv[i]); 4104 continue; 4105 } 4106 param = safe_strdup(argv[i]); 4107 pequal = strchr(param, '='); 4108 if (pequal == NULL) { 4109 (void) fprintf(stderr, gettext("%s: " 4110 "invalid argument '%s', use " 4111 "parameter=value'\n"), 4112 gExecName, argv[i]); 4113 free(param); 4114 return (B_FALSE); 4115 } 4116 4117 *pequal++ = '\0'; 4118 for (j = 0; j < N_GS_FUNC; j++) { 4119 if (strcmp(param, do_gs_func[j].cmd) == 0) { 4120 break; 4121 } 4122 } 4123 if (j == N_GS_FUNC) { 4124 (void) fprintf(stderr, gettext("%s: " 4125 "unrecognized parameter '%s'\n"), 4126 gExecName, param); 4127 free(param); 4128 return (B_FALSE); 4129 } 4130 if (value_is_valid(do_gs_func[j].index, pequal) == 4131 B_FALSE) { 4132 (void) fprintf(stderr, gettext("%s: " 4133 "invalid value '%s' for parameter '%s'\n"), 4134 gExecName, pequal, param); 4135 return (B_FALSE); 4136 } 4137 free(param); 4138 update_aelist(cplist, argv[i]); 4139 } 4140 return (B_TRUE); 4141 } 4142 4143 /* 4144 * do_createprofile: Called when create a profile off-line. 4145 */ 4146 /*ARGSUSED*/ 4147 static boolean_t 4148 do_createprofile(int fd, int argc, char **argv) 4149 { 4150 int i = 0; 4151 char *pbuf = NULL; 4152 char *pfbuf = NULL; 4153 const char *profilename; 4154 aelist_t *plist_config = NULL, *plist_wepkey = NULL; 4155 4156 PRTDBG(("do_createprofile(%d, 0x%x)\n", argc, argv)); 4157 if (argc <= 0) { 4158 do_print_usage(); 4159 exit(WIFI_IMPROPER_USE); 4160 } 4161 /* 4162 * When creating a profile, if the profile name is not specified, 4163 * the essid is selected as the profile name. the paramters are 4164 * saved into the section. 4165 */ 4166 if (strchr(argv[0], '=') == NULL) { 4167 pfbuf = safe_strdup(argv[0]); 4168 argc--; 4169 argv++; 4170 } 4171 for (i = 0; i < argc; i++) { 4172 if (strncmp(argv[i], "essid=", strlen("essid=")) == 0) { 4173 break; 4174 } 4175 } 4176 if (i == argc) { 4177 (void) fprintf(stderr, 4178 gettext("%s: " 4179 "essid required when creating profile\n"), 4180 gExecName); 4181 goto exit0; 4182 } 4183 profilename = (pfbuf ? pfbuf : get_value(argv[i])); 4184 if (strlen(profilename) == 0) { 4185 (void) fprintf(stderr, 4186 gettext("%s: " 4187 "non-empty essid required\n"), 4188 gExecName); 4189 goto exit0; 4190 } 4191 /* 4192 * 'all', '{preference}', '{history}', '{active_profile}' 4193 * and any string with '[' as start and ']' as end should 4194 * not be a profile name 4195 */ 4196 if ((strcasecmp(profilename, "all") == 0) || 4197 (strcmp(profilename, WIFI_HISTORY) == 0) || 4198 (strcmp(profilename, WIFI_PREFER) == 0) || 4199 (strcmp(profilename, WIFI_ACTIVEP) == 0) || 4200 ((profilename[0] == '[') && 4201 (profilename[strlen(profilename) - 1] == ']'))) { 4202 (void) fprintf(stderr, gettext("%s: " 4203 "'%s' is an invalid profile name\n"), 4204 gExecName, profilename); 4205 goto exit0; 4206 } 4207 pbuf = append_pa(profilename); 4208 4209 PRTDBG(("do_createprofile: profile_name = %s\n", pbuf)); 4210 if ((find_section(gp_config_file, pbuf) != NULL) || 4211 find_section(gp_wepkey_file, pbuf) != NULL) { 4212 (void) fprintf(stderr, 4213 gettext("%s: " 4214 "profile '%s' already exists\n"), 4215 gExecName, profilename); 4216 goto exit1; 4217 } 4218 /* 4219 * Save each parameters in the profile. 4220 */ 4221 plist_config = new_ael(PROFILE); 4222 new_section(gp_config_file, plist_config, pbuf); 4223 plist_wepkey = new_ael(PROFILE); 4224 new_section(gp_wepkey_file, plist_wepkey, pbuf); 4225 free(pfbuf); 4226 free(pbuf); 4227 return (items_in_profile(plist_config, plist_wepkey, 4228 argc, argv)); 4229 exit1: 4230 free(pbuf); 4231 exit0: 4232 free(pfbuf); 4233 return (B_FALSE); 4234 } 4235 4236 /*ARGSUSED*/ 4237 static boolean_t 4238 do_setprofparam(int fd, int argc, char **argv) 4239 { 4240 char *pbuf = NULL; 4241 section_t *psection_config = NULL, *psection_wep = NULL; 4242 aelist_t *plist_config = NULL, *plist_wepkey = NULL; 4243 4244 PRTDBG(("do_setprofparam(%d, 0x%x)\n", argc, argv)); 4245 if (argc < 1) { 4246 do_print_usage(); 4247 exit(WIFI_IMPROPER_USE); 4248 } 4249 pbuf = append_pa(argv[0]); 4250 4251 psection_config = find_section(gp_config_file, pbuf); 4252 psection_wep = find_section(gp_wepkey_file, pbuf); 4253 if ((psection_config == NULL) || (psection_wep == NULL)) { 4254 (void) fprintf(stderr, gettext("%s: " 4255 "profile '%s' doesn't exist\n"), 4256 gExecName, argv[0]); 4257 free(pbuf); 4258 return (B_FALSE); 4259 } 4260 free(pbuf); 4261 /* 4262 * modify each parameters in the profile. 4263 */ 4264 plist_config = psection_config->list; 4265 plist_wepkey = psection_wep->list; 4266 argc--; 4267 argv++; 4268 return (items_in_profile(plist_config, plist_wepkey, 4269 argc, argv)); 4270 } 4271 4272 /*ARGSUSED*/ 4273 static boolean_t 4274 do_getprofparam(int fd, int argc, char **argv) 4275 { 4276 int i = 0, j = 0; 4277 int flag; 4278 boolean_t ret = B_TRUE; 4279 section_t *p_section = NULL; 4280 aelist_t *plist = NULL; 4281 ae_t *pae = NULL; 4282 char *pbuf = NULL; 4283 4284 PRTDBG(("do_getprofparam(%d, 0x%x)\n", argc, argv)); 4285 if (argc < 1) { 4286 do_print_usage(); 4287 exit(WIFI_IMPROPER_USE); 4288 } 4289 pbuf = append_pa(argv[0]); 4290 p_section = find_section(gp_config_file, pbuf); 4291 if (p_section == NULL) { 4292 (void) fprintf(stderr, gettext("%s: " 4293 "profile '%s' doesn't exist\n"), 4294 gExecName, argv[0]); 4295 ret = B_FALSE; 4296 goto exit0; 4297 } 4298 argc--; 4299 argv++; 4300 4301 plist = p_section->list; 4302 assert(plist != NULL); 4303 /* 4304 * If no specific parameter typed, we print out all parameters 4305 */ 4306 if (argc == 0) { 4307 pae = plist->ael_head; 4308 while (pae != NULL) { 4309 if (pae->ae_arg != NULL) { 4310 (void) printf("\t%s\n", pae->ae_arg); 4311 } 4312 pae = pae->ae_next; 4313 } 4314 print_wepkey_info(p_section->section_id, NULL); 4315 ret = B_TRUE; 4316 goto exit0; 4317 } 4318 4319 /* 4320 * Match function with do_gs_func[] table, and print its result 4321 */ 4322 for (i = 0; i < argc; i++) { 4323 flag = 0; 4324 for (j = 0; j < N_GS_FUNC; j++) { 4325 if (strcmp(argv[i], do_gs_func[j].cmd) == 0) { 4326 break; 4327 } 4328 if (param_is_wepkey(argv[i], B_FALSE) == B_TRUE) { 4329 j = WEPKEY; 4330 print_wepkey_info(p_section->section_id, 4331 argv[i]); 4332 flag++; 4333 break; 4334 } 4335 } 4336 if (j == N_GS_FUNC) { 4337 (void) fprintf(stderr, 4338 gettext("wificonifg: unrecognized parameter: " 4339 "%s\n"), argv[i]); 4340 ret = B_FALSE; 4341 goto exit0; 4342 } 4343 4344 pae = plist->ael_head; 4345 while ((pae != NULL) && (!flag)) { 4346 if ((pae->ae_arg != NULL) && 4347 (strncmp(pae->ae_arg, argv[i], 4348 strlen(argv[i])) == 0)) { 4349 (void) printf("\t%s\n", pae->ae_arg); 4350 flag++; 4351 } 4352 pae = pae->ae_next; 4353 } 4354 if (!flag) { 4355 (void) fprintf(stderr, gettext("%s: " 4356 "parameter '%s' has not been set in profile %s\n"), 4357 gExecName, argv[i], pbuf); 4358 ret = B_FALSE; 4359 goto exit0; 4360 } 4361 } 4362 exit0: 4363 free(pbuf); 4364 return (ret); 4365 } 4366 4367 /* 4368 * Verify whether the value in the parameter=value pair is valid or not. 4369 * For the channel, since we donot know what kind of wifi card(a,b,or g) 4370 * is in the system, so we just leave to verify the validity of the value 4371 * when the value is set to the card. 4372 * The same goes for the rates. 4373 */ 4374 static boolean_t 4375 value_is_valid(config_item_t item, const char *value) 4376 { 4377 uint32_t num = 0; 4378 uint8_t *rates; 4379 boolean_t ret; 4380 4381 assert(value != NULL); 4382 switch (item) { 4383 case ESSID: 4384 if (strlen(value) > 32) 4385 ret = B_FALSE; 4386 else 4387 ret = B_TRUE; 4388 break; 4389 case BSSTYPE: 4390 if ((strcasecmp(value, "bss") == 0) || 4391 (strcasecmp(value, "ap") == 0) || 4392 (strcasecmp(value, "infrastructure") == 0) || 4393 (strcasecmp(value, "ibss") == 0) || 4394 (strcasecmp(value, "ad-hoc") == 0) || 4395 (strcasecmp(value, "auto") == 0)) 4396 ret = B_TRUE; 4397 else 4398 ret = B_FALSE; 4399 break; 4400 case CREATEIBSS: 4401 if ((strcasecmp(value, "yes") == 0) || 4402 (strcasecmp(value, "no") == 0)) 4403 ret = B_TRUE; 4404 else 4405 ret = B_FALSE; 4406 break; 4407 case AUTHMODE: 4408 if ((strcasecmp(value, "opensystem") == 0) || 4409 (strcasecmp(value, "shared_key") == 0)) 4410 ret = B_TRUE; 4411 else 4412 ret = B_FALSE; 4413 break; 4414 case POWERMODE: 4415 if ((strcasecmp(value, "off") == 0) || 4416 (strcasecmp(value, "mps") == 0) || 4417 (strcasecmp(value, "fast") == 0)) 4418 ret = B_TRUE; 4419 else 4420 ret = B_FALSE; 4421 break; 4422 case ENCRYPTION: 4423 if ((strcasecmp(value, "wep") == 0) || 4424 (strcasecmp(value, "none") == 0)) 4425 ret = B_TRUE; 4426 else 4427 ret = B_FALSE; 4428 break; 4429 case RADIOON: 4430 if ((strcasecmp(value, "on") == 0) || 4431 (strcasecmp(value, "off") == 0)) 4432 ret = B_TRUE; 4433 else 4434 ret = B_FALSE; 4435 break; 4436 case WEPKEYID: 4437 ret = is_wepkeyindex_valid(value); 4438 break; 4439 case WEPKEY: 4440 ret = is_wepkey_valid(value, strlen(value)); 4441 break; 4442 case CHANNEL: 4443 ret = is_channel_valid(value); 4444 break; 4445 case RATES: 4446 rates = get_rates(value, &num); 4447 if (rates == NULL) { 4448 ret = B_FALSE; 4449 } else { 4450 free(rates); 4451 ret = B_TRUE; 4452 } 4453 break; 4454 default: 4455 ret = B_FALSE; 4456 break; 4457 } 4458 4459 return (ret); 4460 } 4461 4462 /* 4463 * do_set: Called when set a parameter, the format should be 4464 * parameter=value. 4465 */ 4466 static boolean_t 4467 do_set(int fd, int argc, char **argv) 4468 { 4469 int i = 0, j = 0; 4470 char *param; 4471 char *pequal; 4472 char *value; 4473 boolean_t ret; 4474 4475 PRTDBG(("do_set(%d, 0x%x)\n", argc, argv)); 4476 assert(fd > 0); 4477 if (argc <= 0) { 4478 (void) do_print_support_params(fd); 4479 ret = B_FALSE; 4480 goto exit0; 4481 } 4482 /* 4483 * Set each parameters, if one failed, others behind it will 4484 * not be set 4485 */ 4486 for (i = 0; i < argc; i++) { 4487 /* 4488 * Separate param and its value, if the user types "param=", 4489 * then value will be set to "";if the user types "param", 4490 * it is an error. 4491 */ 4492 param = safe_strdup(argv[i]); 4493 pequal = strchr(param, '='); 4494 value = NULL; 4495 if (pequal != NULL) { 4496 *pequal = '\0'; 4497 value = pequal + 1; 4498 } else { 4499 (void) fprintf(stderr, 4500 gettext("%s: invalid setparam argument " 4501 "'%s', use 'parameter=value'\n"), 4502 gExecName, argv[i]); 4503 free(param); 4504 ret = B_FALSE; 4505 goto exit0; 4506 } 4507 PRTDBG(("do_set: param = \"%s\", value = \"%s\"\n", 4508 param, value)); 4509 for (j = 0; j < N_GS_FUNC; j++) { 4510 /* 4511 * Match each parameters with do_gs_func table, 4512 */ 4513 if (strcmp(param, do_gs_func[j].cmd) == 0) 4514 break; 4515 if (param_is_wepkey(param, B_FALSE) == B_TRUE) { 4516 value = argv[i]; 4517 j = WEPKEY; 4518 break; 4519 } 4520 } 4521 if (j == N_GS_FUNC) { 4522 (void) fprintf(stderr, 4523 gettext("%s: unrecognized parameter: " 4524 "%s\n"), gExecName, param); 4525 free(param); 4526 ret = B_FALSE; 4527 goto exit0; 4528 } 4529 4530 if (do_gs_func[j].p_do_set_func == NULL) { 4531 (void) fprintf(stderr, 4532 gettext("%s: parameter '%s' is read-only\n"), 4533 gExecName, do_gs_func[j].cmd); 4534 free(param); 4535 ret = B_FALSE; 4536 goto exit0; 4537 } 4538 if (do_gs_func[j].p_do_set_func(fd, value) 4539 == B_TRUE) { 4540 ret = B_TRUE; 4541 } else { 4542 if (gbuf->wldp_result != WL_SUCCESS) { 4543 (void) fprintf(stderr, 4544 gettext("%s: " 4545 "failed to set '%s' for "), 4546 gExecName, param); 4547 print_error(gbuf->wldp_result); 4548 } 4549 free(param); 4550 ret = B_FALSE; 4551 goto exit0; 4552 } 4553 free(param); 4554 } 4555 exit0: 4556 return (ret); 4557 } 4558 4559 static boolean_t 4560 do_get(int fd, int argc, char **argv) 4561 { 4562 int i = 0, j = 0, n = 0; 4563 boolean_t ret = B_TRUE; 4564 4565 PRTDBG(("do_get(%d, 0x%x)\n", argc, argv)); 4566 assert(fd > 0); 4567 /* 4568 * If no specific parameter typed, we print out all parameters 4569 */ 4570 if (argc <= 0) { 4571 for (i = 0; i < N_GS_FUNC; i++) { 4572 if ((do_gs_func[i].p_do_get_func != NULL) && 4573 (do_gs_func[i].p_do_get_func(fd) 4574 == B_TRUE)) { 4575 print_gbuf(do_gs_func[i].index); 4576 n++; 4577 } 4578 } 4579 ret = n ? B_TRUE:B_FALSE; 4580 goto exit0; 4581 } 4582 /* 4583 * Match function with do_gs_func[] table, and print its result 4584 */ 4585 for (i = 0; i < argc; i++) { 4586 for (j = 0; j < N_GS_FUNC; j++) { 4587 if (strcmp(argv[i], do_gs_func[j].cmd) == 0) { 4588 break; 4589 } 4590 if (param_is_wepkey(argv[i], B_FALSE) == B_TRUE) { 4591 j = WEPKEY; 4592 break; 4593 } 4594 } 4595 if (j == N_GS_FUNC) { 4596 (void) fprintf(stderr, 4597 gettext("wificonifg: unrecognized parameter: " 4598 "%s\n"), argv[i]); 4599 ret = B_FALSE; 4600 goto exit0; 4601 } 4602 if (do_gs_func[j].p_do_get_func == NULL) { 4603 (void) fprintf(stderr, 4604 gettext("%s: parameter '%s' is write-only\n"), 4605 gExecName, do_gs_func[j].cmd); 4606 ret = B_FALSE; 4607 goto exit0; 4608 } 4609 if (do_gs_func[j].p_do_get_func(fd) == B_TRUE) { 4610 print_gbuf(do_gs_func[j].index); 4611 ret = B_TRUE; 4612 } else { 4613 (void) fprintf(stderr, 4614 gettext("%s: " 4615 "failed to read parameter '%s' : "), 4616 gExecName, argv[i]); 4617 print_error(gbuf->wldp_result); 4618 ret = B_FALSE; 4619 } 4620 } 4621 exit0: 4622 return (ret); 4623 } 4624 4625 /* 4626 * Only one wificonfig is running at one time. 4627 * The following wificonfig which tries to be run will return error, 4628 * and the pid of the process will own the filelock will be printed out. 4629 */ 4630 static pid_t 4631 enter_wifi_lock(int *fd) 4632 { 4633 int fd0 = -1; 4634 struct flock lock; 4635 4636 fd0 = open(WIFI_LOCKF, O_CREAT|O_WRONLY, 0600); 4637 if (fd0 < 0) { 4638 (void) fprintf(stderr, gettext("%s: failed to open lockfile" 4639 " '"WIFI_LOCKF"': %s\n"), gExecName, strerror(errno)); 4640 exit(WIFI_FATAL_ERR); 4641 } 4642 4643 *fd = fd0; 4644 lock.l_type = F_WRLCK; 4645 lock.l_whence = SEEK_SET; 4646 lock.l_start = 0; 4647 lock.l_len = 0; 4648 4649 if ((fcntl(fd0, F_SETLK, &lock) == -1) && 4650 (errno == EAGAIN || errno == EDEADLK)) { 4651 if (fcntl(fd0, F_GETLK, &lock) == -1) { 4652 (void) fprintf(stderr, 4653 gettext("%s: enter_filelock")); 4654 exit(WIFI_FATAL_ERR); 4655 } 4656 (void) fprintf(stderr, gettext("%s:" 4657 "enter_filelock:filelock is owned " 4658 "by 'process %d'\n"), gExecName, lock.l_pid); 4659 return (lock.l_pid); 4660 } 4661 4662 return (getpid()); 4663 } 4664 4665 static void 4666 exit_wifi_lock(int fd) 4667 { 4668 struct flock lock; 4669 4670 lock.l_type = F_UNLCK; 4671 lock.l_whence = SEEK_SET; 4672 lock.l_start = 0; 4673 lock.l_len = 0; 4674 if (fcntl(fd, F_SETLK, &lock) == -1) { 4675 (void) fprintf(stderr, gettext("%s: failed to" 4676 " exit_filelock: %s\n"), 4677 gExecName, strerror(errno)); 4678 } 4679 (void) close(fd); 4680 } 4681 4682 int 4683 main(int argc, char **argv) 4684 { 4685 int i, ret; 4686 int fddev = -1; 4687 int c, iflag = 0, rflag = 0, fileonly = 0, readonly = 0; 4688 int fd; 4689 char *iname = NULL; 4690 char *path = NULL; 4691 extern char *optarg; 4692 extern int optind; 4693 char interface[LIFNAMSIZ]; 4694 char file_wifi[MAX_CONFIG_FILE_LENGTH]; 4695 char file_wifiwepkey[MAX_CONFIG_FILE_LENGTH]; 4696 priv_set_t *ppriv; 4697 wifi_auth_t autht; 4698 4699 PRTDBG(("main(%d, 0x%x)\n", argc, argv)); 4700 PRTDBG(("uid=%d\n", getuid())); 4701 PRTDBG(("euid=%d\n", geteuid())); 4702 4703 #ifdef DEBUG 4704 if (wifi_debug == 1) { /* for debuf purpose only */ 4705 (void) printf("Press RETURN to continue...\n"); 4706 (void) getchar(); 4707 } 4708 #endif 4709 ret = WIFI_EXIT_DEF; 4710 4711 (void) setlocale(LC_ALL, ""); 4712 (void) textdomain(TEXT_DOMAIN); 4713 4714 gExecName = argv[0]; 4715 4716 gbuf = safe_malloc(MAX_BUF_LEN); 4717 4718 if ((ppriv = priv_str_to_set("basic", ",", NULL)) == NULL) { 4719 PRTDBG(("main: priviledge init error\n")); 4720 (void) fprintf(stderr, gettext("%s: " 4721 "set priviledge to 'basic' error\n"), 4722 gExecName); 4723 ret = WIFI_FATAL_ERR; 4724 goto exit0; 4725 } 4726 (void) priv_addset(ppriv, PRIV_NET_RAWACCESS); 4727 (void) priv_addset(ppriv, PRIV_SYS_NET_CONFIG); 4728 if (setppriv(PRIV_SET, PRIV_PERMITTED, ppriv) == -1) { 4729 (void) fprintf(stderr, gettext("%s: " 4730 "set permitted priviledge: %s\n"), 4731 gExecName, strerror(errno)); 4732 ret = WIFI_FATAL_ERR; 4733 goto exit0; 4734 } 4735 if (setppriv(PRIV_SET, PRIV_LIMIT, ppriv) == -1) { 4736 (void) fprintf(stderr, gettext("%s: " 4737 "set limit priviledge: %s\n"), 4738 gExecName, strerror(errno)); 4739 ret = WIFI_FATAL_ERR; 4740 goto exit0; 4741 } 4742 if (setppriv(PRIV_SET, PRIV_INHERITABLE, ppriv) == -1) { 4743 (void) fprintf(stderr, gettext("%s: " 4744 "set inherit priviledge: %s\n"), 4745 gExecName, strerror(errno)); 4746 ret = WIFI_FATAL_ERR; 4747 goto exit0; 4748 } 4749 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, ppriv) == -1) { 4750 (void) fprintf(stderr, gettext("%s: " 4751 "set effective priviledge: %s\n"), 4752 gExecName, strerror(errno)); 4753 ret = WIFI_FATAL_ERR; 4754 goto exit0; 4755 } 4756 priv_freeset(ppriv); 4757 4758 for (i = 0; i < argc; i++) { 4759 PRTDBG(("%d\t\t\"%s\"\n", i, argv[i])); 4760 } 4761 4762 while ((c = getopt(argc, argv, "i:R:")) != EOF) { 4763 switch (c) { 4764 case 'i': 4765 if (iflag) { 4766 do_print_usage(); 4767 ret = WIFI_IMPROPER_USE; 4768 goto exit0; 4769 } 4770 iflag = 1; 4771 iname = optarg; 4772 break; 4773 case 'R': 4774 if (rflag) { 4775 do_print_usage(); 4776 ret = WIFI_IMPROPER_USE; 4777 goto exit0; 4778 } 4779 rflag = 1; 4780 path = optarg; 4781 break; 4782 case '?': 4783 default: 4784 do_print_usage(); 4785 ret = WIFI_IMPROPER_USE; 4786 goto exit0; 4787 } 4788 } 4789 argc -= optind; 4790 argv += optind; 4791 4792 if (argc <= 0) { 4793 if (iname) { 4794 if ((fddev = open_dev(iname)) == -1) { 4795 ret = WIFI_FATAL_ERR; 4796 goto exit0; 4797 } 4798 if (do_print_support_params(fddev) == 4799 B_TRUE) 4800 ret = WIFI_EXIT_DEF; 4801 else 4802 ret = WIFI_FATAL_ERR; 4803 goto exit1; 4804 } else { 4805 do_print_usage(); 4806 ret = WIFI_IMPROPER_USE; 4807 goto exit0; 4808 } 4809 } 4810 4811 for (i = 0; i < N_FUNC; i++) { 4812 if (strcmp(argv[0], do_func[i].cmd) == 0) { 4813 autht = ((strcmp(argv[0], "setwepkey") == 0) || 4814 (strcmp(argv[0], "setprofwepkey") == 0)) ? 4815 AUTH_WEP:AUTH_OTHER; 4816 if (do_func[i].b_auth && 4817 !check_authority(autht)) { 4818 ret = WIFI_FATAL_ERR; 4819 goto exit0; 4820 } 4821 if (do_func[i].b_fileonly) 4822 fileonly++; 4823 if (do_func[i].b_readonly) 4824 readonly++; 4825 break; 4826 } 4827 } 4828 if (i == N_FUNC) { 4829 (void) fprintf(stderr, gettext("%s: unrecognized " 4830 "subcommand: %s\n"), gExecName, argv[0]); 4831 do_print_usage(); 4832 ret = WIFI_IMPROPER_USE; 4833 goto exit0; 4834 } 4835 if ((fileonly) && (iname)) { 4836 do_print_usage(); 4837 ret = WIFI_IMPROPER_USE; 4838 goto exit0; 4839 } 4840 if ((!fileonly) && (!iname)) { 4841 if (search_interface(interface) != B_TRUE) { 4842 (void) fprintf(stderr, gettext("%s: " 4843 "failed to find the default wifi interface;" 4844 " -i option should be used to specify the " 4845 "wifi interface\n"), gExecName); 4846 ret = WIFI_FATAL_ERR; 4847 goto exit0; 4848 } 4849 iname = interface; 4850 } 4851 if (iname) { 4852 if ((fddev = open_dev(iname)) == -1) { 4853 ret = WIFI_FATAL_ERR; 4854 goto exit0; 4855 } 4856 } 4857 if (rflag) { 4858 safe_snprintf(file_wifi, sizeof (file_wifi), 4859 "%s%s", path, p_file_wifi); 4860 safe_snprintf(file_wifiwepkey, sizeof (file_wifiwepkey), 4861 "%s%s", path, p_file_wifiwepkey); 4862 } else { 4863 safe_snprintf(file_wifi, sizeof (file_wifi), 4864 "%s", p_file_wifi); 4865 safe_snprintf(file_wifiwepkey, sizeof (file_wifiwepkey), 4866 "%s", p_file_wifiwepkey); 4867 } 4868 /* 4869 * There is an occasion when more than one wificonfig processes 4870 * which attempt to write the <wifi> and <wifiwepkey> files are 4871 * running. We must be able to avoid this. 4872 * We use file lock here to implement this. 4873 */ 4874 if ((!readonly) && (enter_wifi_lock(&fd) != getpid())) { 4875 ret = WIFI_FATAL_ERR; 4876 goto exit1; 4877 } 4878 gp_config_file = parse_file(file_wifi); 4879 if (gp_config_file == NULL) { 4880 ret = WIFI_FATAL_ERR; 4881 goto exit2; 4882 } 4883 4884 gp_wepkey_file = parse_file(file_wifiwepkey); 4885 if (gp_wepkey_file == NULL) { 4886 destroy_config(gp_config_file); 4887 ret = WIFI_FATAL_ERR; 4888 goto exit2; 4889 } 4890 if (do_func[i].p_do_func(fddev, argc-1, argv+1) 4891 == B_TRUE) { 4892 /* 4893 * can not write file when startconfing 4894 * during boot 4895 */ 4896 if (do_func[i].b_readonly) 4897 ret = WIFI_EXIT_DEF; 4898 else if ((fprint_config_file(gp_config_file, 4899 file_wifi) != B_TRUE) || 4900 (fprint_config_file(gp_wepkey_file, 4901 file_wifiwepkey) != B_TRUE)) 4902 ret = WIFI_FATAL_ERR; 4903 else 4904 ret = WIFI_EXIT_DEF; 4905 } else { 4906 PRTDBG(("Command %s failed\n", argv[0])); 4907 ret = WIFI_FATAL_ERR; 4908 } 4909 destroy_config(gp_wepkey_file); 4910 destroy_config(gp_config_file); 4911 exit2: 4912 if (!readonly) 4913 exit_wifi_lock(fd); 4914 exit1: 4915 if (iname) 4916 (void) close(fddev); 4917 exit0: 4918 free(gbuf); 4919 return (ret); 4920 } 4921 4922 #ifdef DEBUG 4923 static void 4924 wifi_dbgprintf(char *fmt, ...) 4925 { 4926 va_list ap; 4927 va_start(ap, fmt); 4928 (void) vfprintf(stdout, fmt, ap); 4929 va_end(ap); 4930 } 4931 #endif 4932