xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/wificonfig/wificonfig.c (revision 995:044a1b7c2e14)
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