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