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