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