1516fc7f3Shx147065 /*
2516fc7f3Shx147065 * CDDL HEADER START
3516fc7f3Shx147065 *
4516fc7f3Shx147065 * The contents of this file are subject to the terms of the
5*0d2f4bc9Sff224033 * Common Development and Distribution License (the "License").
6*0d2f4bc9Sff224033 * You may not use this file except in compliance with the License.
7516fc7f3Shx147065 *
8516fc7f3Shx147065 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9516fc7f3Shx147065 * or http://www.opensolaris.org/os/licensing.
10516fc7f3Shx147065 * See the License for the specific language governing permissions
11516fc7f3Shx147065 * and limitations under the License.
12516fc7f3Shx147065 *
13516fc7f3Shx147065 * When distributing Covered Code, include this CDDL HEADER in each
14516fc7f3Shx147065 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15516fc7f3Shx147065 * If applicable, add the following below this CDDL HEADER, with the
16516fc7f3Shx147065 * fields enclosed by brackets "[]" replaced with your own identifying
17516fc7f3Shx147065 * information: Portions Copyright [yyyy] [name of copyright owner]
18516fc7f3Shx147065 *
19516fc7f3Shx147065 * CDDL HEADER END
20516fc7f3Shx147065 */
21516fc7f3Shx147065 /*
22*0d2f4bc9Sff224033 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23516fc7f3Shx147065 * Use is subject to license terms.
24516fc7f3Shx147065 */
25516fc7f3Shx147065
26516fc7f3Shx147065 #pragma ident "%Z%%M% %I% %E% SMI"
27516fc7f3Shx147065
28516fc7f3Shx147065 #include <stdio.h>
29516fc7f3Shx147065 #include <stdlib.h>
30516fc7f3Shx147065 #include <stddef.h>
31516fc7f3Shx147065 #include <errno.h>
32516fc7f3Shx147065 #include <ctype.h>
33516fc7f3Shx147065 #include <stdarg.h>
34516fc7f3Shx147065 #include <fcntl.h>
35516fc7f3Shx147065 #include <unistd.h>
36516fc7f3Shx147065 #include <net/if.h>
37516fc7f3Shx147065 #include <sys/types.h>
38516fc7f3Shx147065 #include <sys/stat.h>
39516fc7f3Shx147065 #include <sys/wait.h>
40516fc7f3Shx147065 #include <sys/ipc.h>
41516fc7f3Shx147065 #include <sys/ddi.h>
42516fc7f3Shx147065 #include <stropts.h>
43516fc7f3Shx147065 #include <assert.h>
44516fc7f3Shx147065 #include <termios.h>
45516fc7f3Shx147065 #include <time.h>
46516fc7f3Shx147065 #include <string.h>
47516fc7f3Shx147065 #include <strings.h>
48516fc7f3Shx147065 #include <auth_attr.h>
49516fc7f3Shx147065 #include <auth_list.h>
50516fc7f3Shx147065 #include <libdevinfo.h>
51516fc7f3Shx147065 #include <secdb.h>
52516fc7f3Shx147065 #include <priv.h>
53516fc7f3Shx147065 #include <pwd.h>
54516fc7f3Shx147065 #include <umem.h>
55516fc7f3Shx147065 #include <locale.h>
56516fc7f3Shx147065 #include <libintl.h>
57516fc7f3Shx147065 #include <dirent.h>
58516fc7f3Shx147065 #include <inet/wifi_ioctl.h>
59516fc7f3Shx147065
60516fc7f3Shx147065 /*
61516fc7f3Shx147065 * Debug information
62516fc7f3Shx147065 */
63516fc7f3Shx147065 #ifdef DEBUG
64516fc7f3Shx147065 int wifi_debug = 0;
65516fc7f3Shx147065 void wifi_dbgprintf(char *fmt, ...);
66516fc7f3Shx147065 #define PRTDBG(msg) if (wifi_debug > 1) wifi_dbgprintf msg
67516fc7f3Shx147065 #else /* DEBUG */
68516fc7f3Shx147065 #define PRTDBG(msg)
69516fc7f3Shx147065 #endif /* DEBUG */
70516fc7f3Shx147065
71516fc7f3Shx147065 #define MAX_HISTORY_NUM 10
72516fc7f3Shx147065 #define MAX_PREFERENCE_NUM 10
73516fc7f3Shx147065 #define MAX_SCANBUF_LEN 256
74516fc7f3Shx147065 #define MAX_CONFIG_FILE_LENGTH 256
75516fc7f3Shx147065 #define MAX_LOADPF_LENGTH 256
76516fc7f3Shx147065 #define LOADPROFILE_TIMEOUT 10
77516fc7f3Shx147065 #define RECORD_ADD 0
78516fc7f3Shx147065 #define RECORD_DEL 1
79516fc7f3Shx147065 /*
80516fc7f3Shx147065 * Wificonfig exit status
81516fc7f3Shx147065 */
82516fc7f3Shx147065 #define WIFI_EXIT_DEF 0
83516fc7f3Shx147065 #define WIFI_FATAL_ERR 1
84516fc7f3Shx147065 #define WIFI_IMPROPER_USE 2
85516fc7f3Shx147065 #define WIFI_MINOR_ERR 3
86516fc7f3Shx147065
87516fc7f3Shx147065 #define WIFI_LOCKF "/var/run/lockf_wifi"
88516fc7f3Shx147065
89516fc7f3Shx147065 typedef enum {
90516fc7f3Shx147065 PREFERENCE,
91516fc7f3Shx147065 HISTORY,
92516fc7f3Shx147065 ACTIVEP,
93516fc7f3Shx147065 PROFILE,
94516fc7f3Shx147065 OTHER
95516fc7f3Shx147065 } list_type_t;
96516fc7f3Shx147065
97516fc7f3Shx147065 #define WIFI_PREFER "{preference}"
98516fc7f3Shx147065 #define WIFI_HISTORY "{history}"
99516fc7f3Shx147065 #define WIFI_ACTIVEP "{active_profile}"
100516fc7f3Shx147065
101516fc7f3Shx147065 typedef enum {
102516fc7f3Shx147065 LINKSTATUS = 0,
103516fc7f3Shx147065 BSSID,
104516fc7f3Shx147065 ESSID,
105516fc7f3Shx147065 BSSTYPE,
106516fc7f3Shx147065 CREATEIBSS,
107516fc7f3Shx147065 CHANNEL,
108516fc7f3Shx147065 RATES,
109516fc7f3Shx147065 POWERMODE,
110516fc7f3Shx147065 AUTHMODE,
111516fc7f3Shx147065 ENCRYPTION,
112516fc7f3Shx147065 WEPKEYID,
113516fc7f3Shx147065 WEPKEY,
114516fc7f3Shx147065 SIGNAL,
115516fc7f3Shx147065 RADIOON,
116516fc7f3Shx147065 WLANLIST,
117516fc7f3Shx147065 CONFIG_ITEM_END /* 15 */
118516fc7f3Shx147065 } config_item_t;
119516fc7f3Shx147065 typedef struct ae {
120516fc7f3Shx147065 struct ae *ae_next;
121516fc7f3Shx147065 char *ae_arg;
122516fc7f3Shx147065 }ae_t;
123516fc7f3Shx147065 typedef struct aelist {
124516fc7f3Shx147065 int ael_argc;
125516fc7f3Shx147065 ae_t *ael_head, *ael_tail;
126516fc7f3Shx147065 list_type_t type;
127516fc7f3Shx147065 }aelist_t;
128516fc7f3Shx147065 typedef struct section {
129516fc7f3Shx147065 struct section *section_next;
130516fc7f3Shx147065 aelist_t *list;
131516fc7f3Shx147065 char *section_id;
132516fc7f3Shx147065 }section_t;
133516fc7f3Shx147065
134516fc7f3Shx147065 /*
135516fc7f3Shx147065 * config_file_t is an abstract of configration file,
136516fc7f3Shx147065 * either/etc/inet/wifi/wifi.<interface> or /etc/inet/secret/
137516fc7f3Shx147065 * wifi/wifiwepkey.<interface>
138516fc7f3Shx147065 */
139516fc7f3Shx147065 typedef struct config_file {
140516fc7f3Shx147065 int section_argc;
141516fc7f3Shx147065 section_t *section_head, *section_tail;
142516fc7f3Shx147065 }config_file_t;
143516fc7f3Shx147065
144516fc7f3Shx147065 static config_file_t *gp_config_file = NULL;
145516fc7f3Shx147065 static config_file_t *gp_wepkey_file = NULL;
146516fc7f3Shx147065 static char *p_file_wifi = "/etc/inet/wifi";
147516fc7f3Shx147065 static char *p_file_wifiwepkey = "/etc/inet/secret/wifiwepkey";
148516fc7f3Shx147065
149516fc7f3Shx147065 typedef enum {
150516fc7f3Shx147065 AUTH_WEP = 0,
151516fc7f3Shx147065 AUTH_OTHER = 1
152516fc7f3Shx147065 } wifi_auth_t;
153516fc7f3Shx147065
154516fc7f3Shx147065 static char *p_auth_string[] = {
155516fc7f3Shx147065 WIFI_WEP_AUTH,
156516fc7f3Shx147065 WIFI_CONFIG_AUTH
157516fc7f3Shx147065 };
158516fc7f3Shx147065
159516fc7f3Shx147065 /*
160516fc7f3Shx147065 * gbuf: is a global buf, which is used to communicate between the user and
161516fc7f3Shx147065 * the driver
162516fc7f3Shx147065 */
163516fc7f3Shx147065 static wldp_t *gbuf = NULL;
164516fc7f3Shx147065 static char *gExecName = NULL;
165516fc7f3Shx147065
166516fc7f3Shx147065 static void print_error(uint32_t);
167516fc7f3Shx147065 static void *safe_malloc(size_t);
168516fc7f3Shx147065 static void *safe_calloc(size_t, size_t);
169516fc7f3Shx147065 static char *safe_strdup(const char *s1);
170516fc7f3Shx147065 static void safe_snprintf(char *s, size_t n,
171516fc7f3Shx147065 const char *format, ...);
172516fc7f3Shx147065 static void safe_fclose(FILE *stream);
173516fc7f3Shx147065 static void new_ae(aelist_t *ael, const char *arg);
174516fc7f3Shx147065 static aelist_t *new_ael(list_type_t type);
175516fc7f3Shx147065 static config_file_t *new_config_file();
176516fc7f3Shx147065 static void new_section(config_file_t *p_config_file, aelist_t *p_list,
177516fc7f3Shx147065 const char *section_id);
178516fc7f3Shx147065 static void destroy_config(config_file_t *p_config_file);
179516fc7f3Shx147065 static config_file_t *parse_file(const char *pfile);
180516fc7f3Shx147065 static char **aeltoargv(aelist_t *ael, int *ael_num);
181516fc7f3Shx147065 static boolean_t fprint_config_file(config_file_t *p_config_file,
182516fc7f3Shx147065 const char *file_name);
183516fc7f3Shx147065 static char *append_pa(const char *arg);
184516fc7f3Shx147065 static section_t *find_section(config_file_t *p_config_file,
185516fc7f3Shx147065 const char *section_id);
186516fc7f3Shx147065 static ae_t *find_ae(aelist_t *plist, const char *arg);
187516fc7f3Shx147065 static void update_aelist(aelist_t *plist, const char *arg);
188516fc7f3Shx147065 static const char *get_value(const char *arg);
189516fc7f3Shx147065 static char *find_active_profile(int);
190516fc7f3Shx147065 static const char *essid_of_profile(const char *profile);
191516fc7f3Shx147065 static boolean_t search_interface(char *interface);
192516fc7f3Shx147065 static int open_dev(char *devname);
193516fc7f3Shx147065 static boolean_t call_ioctl(int, int, uint32_t, uint32_t);
194516fc7f3Shx147065 static boolean_t del_prefer(config_file_t *p_config_file, const char *prefer,
195516fc7f3Shx147065 boolean_t rflag);
196516fc7f3Shx147065 static boolean_t del_section(config_file_t *p_config_file, char *section_id);
197516fc7f3Shx147065 static boolean_t set_prefer(config_file_t *p_config_file, const char *prefer,
198516fc7f3Shx147065 int rank);
199516fc7f3Shx147065 static void add_to_history(config_file_t *p_config_file,
200516fc7f3Shx147065 int argc, char **argv);
201516fc7f3Shx147065 static boolean_t check_authority(wifi_auth_t type);
202516fc7f3Shx147065 static void heuristic_load(int fd, uint32_t ess_num, wl_ess_conf_t **);
203516fc7f3Shx147065 static char *select_profile(int fd, int readonly, int timeout);
204516fc7f3Shx147065 static char *construct_format(uint32_t nt);
205516fc7f3Shx147065 static void print_gbuf(config_item_t index);
206516fc7f3Shx147065 static boolean_t items_in_profile(aelist_t *, aelist_t *, int, char **);
207516fc7f3Shx147065 static char *get_commit_key(int, int, char **);
208516fc7f3Shx147065 static void print_wepkey_info(const char *id, const char *wepkeyn);
209516fc7f3Shx147065 static void do_print_usage();
210516fc7f3Shx147065 static boolean_t do_print_support_params(int fd);
211516fc7f3Shx147065 static boolean_t do_autoconf(int fd, int argc, char **argv);
212516fc7f3Shx147065 static boolean_t do_startconf(int fd, int argc, char **argv);
213516fc7f3Shx147065 static boolean_t do_loadpf(int fd, int argc, char **argv);
214516fc7f3Shx147065 static boolean_t do_disconnect(int fd, int argc, char **argv);
215516fc7f3Shx147065 static boolean_t do_printpf(int fd, int argc, char **argv);
216516fc7f3Shx147065 static boolean_t do_restoredef(int fd, int argc, char **argv);
217516fc7f3Shx147065 static boolean_t do_history(int fd, int argc, char **argv);
218516fc7f3Shx147065 static boolean_t do_deletepf(int fd, int argc, char **argv);
219516fc7f3Shx147065 static boolean_t do_wepkey(int fd, int argc, char **argv);
220516fc7f3Shx147065 static boolean_t do_setprefer(int fd, int argc, char **arg);
221516fc7f3Shx147065 static boolean_t do_rmprefer(int fd, int argc, char **argv);
222516fc7f3Shx147065 static boolean_t do_lsprefer(int fd, int argc, char **argv);
223516fc7f3Shx147065 static boolean_t do_wlanlist(int fd, int argc, char **argv);
224516fc7f3Shx147065 static boolean_t do_showstatus(int fd, int argc, char **argv);
225516fc7f3Shx147065 static boolean_t do_getprofparam(int fd, int argc, char **argv);
226516fc7f3Shx147065 static boolean_t do_setprofparam(int fd, int argc, char **argv);
227516fc7f3Shx147065 static boolean_t do_setprofwepkey(int fd, int argc, char **argv);
228516fc7f3Shx147065 static boolean_t is_rates_support(int fd, int num, uint8_t *rates);
229516fc7f3Shx147065 static boolean_t do_set_bsstype(int fd, const char *arg);
230516fc7f3Shx147065 static boolean_t do_set_essid(int fd, const char *arg);
231516fc7f3Shx147065 static boolean_t do_set_powermode(int fd, const char *arg);
232516fc7f3Shx147065 static boolean_t do_set_rates(int fd, const char *arg);
233516fc7f3Shx147065 static boolean_t do_set_channel(int fd, const char *arg);
234516fc7f3Shx147065 static boolean_t do_set_createibss(int fd, const char *arg);
235516fc7f3Shx147065 static boolean_t do_set_radioon(int fd, const char *arg);
236516fc7f3Shx147065 static boolean_t do_set_wepkeyid(int fd, const char *arg);
237516fc7f3Shx147065 static boolean_t do_set_encryption(int fd, const char *arg);
238516fc7f3Shx147065 static boolean_t do_set_authmode(int fd, const char *arg);
239516fc7f3Shx147065 static boolean_t do_set_wepkey(int fd, const char *pbuf);
240516fc7f3Shx147065 static boolean_t do_get_createibss(int fd);
241516fc7f3Shx147065 static boolean_t do_get_bsstype(int fd);
242516fc7f3Shx147065 static boolean_t do_get_essid(int fd);
243516fc7f3Shx147065 static boolean_t do_get_bssid(int fd);
244516fc7f3Shx147065 static boolean_t do_get_radioon(int fd);
245516fc7f3Shx147065 static boolean_t do_get_signal(int fd);
246516fc7f3Shx147065 static boolean_t do_get_wepkeyid(int fd);
247516fc7f3Shx147065 static boolean_t do_get_encryption(int fd);
248516fc7f3Shx147065 static boolean_t do_get_authmode(int fd);
249516fc7f3Shx147065 static boolean_t do_get_powermode(int fd);
250516fc7f3Shx147065 static boolean_t do_get_rates(int fd);
251516fc7f3Shx147065 static boolean_t do_get_wlanlist(int fd);
252516fc7f3Shx147065 static boolean_t do_get_linkstatus(int fd);
253516fc7f3Shx147065 static boolean_t do_get_channel(int fd);
254516fc7f3Shx147065 static boolean_t do_get(int fd, int argc, char **argv);
255516fc7f3Shx147065 static boolean_t do_set(int fd, int argc, char **argv);
256516fc7f3Shx147065 static boolean_t do_createprofile(int fd, int argc, char **argv);
257516fc7f3Shx147065 static boolean_t value_is_valid(config_item_t item, const char *value);
258516fc7f3Shx147065
259516fc7f3Shx147065 typedef struct cmd_ops {
260516fc7f3Shx147065 char cmd[32];
261516fc7f3Shx147065 boolean_t (*p_do_func)(int fd, int argc, char **argv);
262516fc7f3Shx147065 boolean_t b_auth;
263516fc7f3Shx147065 boolean_t b_fileonly; /* operation only on the config file */
264516fc7f3Shx147065 boolean_t b_readonly; /* only read from the card or config file */
265516fc7f3Shx147065 } cmd_ops_t;
266516fc7f3Shx147065 static cmd_ops_t do_func[] = {
267516fc7f3Shx147065 {
268516fc7f3Shx147065 "autoconf",
269516fc7f3Shx147065 do_autoconf,
270516fc7f3Shx147065 B_TRUE,
271516fc7f3Shx147065 B_FALSE,
272516fc7f3Shx147065 B_FALSE
273516fc7f3Shx147065 },
274516fc7f3Shx147065 {
275516fc7f3Shx147065 "startconf",
276516fc7f3Shx147065 do_startconf,
277516fc7f3Shx147065 B_TRUE,
278516fc7f3Shx147065 B_FALSE,
279516fc7f3Shx147065 B_TRUE
280516fc7f3Shx147065 },
281516fc7f3Shx147065 {
282516fc7f3Shx147065 "connect",
283516fc7f3Shx147065 do_loadpf,
284516fc7f3Shx147065 B_TRUE,
285516fc7f3Shx147065 B_FALSE,
286516fc7f3Shx147065 B_FALSE
287516fc7f3Shx147065 },
288516fc7f3Shx147065 {
289516fc7f3Shx147065 "disconnect",
290516fc7f3Shx147065 do_disconnect,
291516fc7f3Shx147065 B_TRUE,
292516fc7f3Shx147065 B_FALSE,
293516fc7f3Shx147065 B_FALSE
294516fc7f3Shx147065 },
295516fc7f3Shx147065 {
296516fc7f3Shx147065 "showprofile",
297516fc7f3Shx147065 do_printpf,
298516fc7f3Shx147065 B_FALSE,
299516fc7f3Shx147065 B_TRUE,
300516fc7f3Shx147065 B_TRUE
301516fc7f3Shx147065 },
302516fc7f3Shx147065 {
303516fc7f3Shx147065 "deleteprofile",
304516fc7f3Shx147065 do_deletepf,
305516fc7f3Shx147065 B_TRUE,
306516fc7f3Shx147065 B_TRUE,
307516fc7f3Shx147065 B_FALSE
308516fc7f3Shx147065 },
309516fc7f3Shx147065 {
310516fc7f3Shx147065 "history",
311516fc7f3Shx147065 do_history,
312516fc7f3Shx147065 B_FALSE,
313516fc7f3Shx147065 B_TRUE,
314516fc7f3Shx147065 B_TRUE
315516fc7f3Shx147065 },
316516fc7f3Shx147065 {
317516fc7f3Shx147065 "listprefer",
318516fc7f3Shx147065 do_lsprefer,
319516fc7f3Shx147065 B_FALSE,
320516fc7f3Shx147065 B_TRUE,
321516fc7f3Shx147065 B_TRUE
322516fc7f3Shx147065 },
323516fc7f3Shx147065 {
324516fc7f3Shx147065 "removeprefer",
325516fc7f3Shx147065 do_rmprefer,
326516fc7f3Shx147065 B_TRUE,
327516fc7f3Shx147065 B_TRUE,
328516fc7f3Shx147065 B_FALSE
329516fc7f3Shx147065 },
330516fc7f3Shx147065 {
331516fc7f3Shx147065 "setprefer",
332516fc7f3Shx147065 do_setprefer,
333516fc7f3Shx147065 B_TRUE,
334516fc7f3Shx147065 B_TRUE,
335516fc7f3Shx147065 B_FALSE
336516fc7f3Shx147065 },
337516fc7f3Shx147065 {
338516fc7f3Shx147065 "setwepkey",
339516fc7f3Shx147065 do_wepkey,
340516fc7f3Shx147065 B_TRUE,
341516fc7f3Shx147065 B_FALSE,
342516fc7f3Shx147065 B_FALSE
343516fc7f3Shx147065 },
344516fc7f3Shx147065 {
345516fc7f3Shx147065 "restoredef",
346516fc7f3Shx147065 do_restoredef,
347516fc7f3Shx147065 B_TRUE,
348516fc7f3Shx147065 B_FALSE,
349516fc7f3Shx147065 B_FALSE
350516fc7f3Shx147065 },
351516fc7f3Shx147065 {
352516fc7f3Shx147065 "getparam",
353516fc7f3Shx147065 do_get,
354516fc7f3Shx147065 B_FALSE,
355516fc7f3Shx147065 B_FALSE,
356516fc7f3Shx147065 B_TRUE
357516fc7f3Shx147065 },
358516fc7f3Shx147065 {
359516fc7f3Shx147065 "setparam",
360516fc7f3Shx147065 do_set,
361516fc7f3Shx147065 B_TRUE,
362516fc7f3Shx147065 B_FALSE,
363516fc7f3Shx147065 B_FALSE
364516fc7f3Shx147065 },
365516fc7f3Shx147065 {
366516fc7f3Shx147065 "createprofile",
367516fc7f3Shx147065 do_createprofile,
368516fc7f3Shx147065 B_TRUE,
369516fc7f3Shx147065 B_TRUE,
370516fc7f3Shx147065 B_FALSE
371516fc7f3Shx147065 },
372516fc7f3Shx147065 {
373516fc7f3Shx147065 "scan",
374516fc7f3Shx147065 do_wlanlist,
375516fc7f3Shx147065 B_FALSE,
376516fc7f3Shx147065 B_FALSE,
377516fc7f3Shx147065 B_FALSE
378516fc7f3Shx147065 },
379516fc7f3Shx147065 {
380516fc7f3Shx147065 "showstatus",
381516fc7f3Shx147065 do_showstatus,
382516fc7f3Shx147065 B_FALSE,
383516fc7f3Shx147065 B_FALSE,
384516fc7f3Shx147065 B_TRUE
385516fc7f3Shx147065 },
386516fc7f3Shx147065 {
387516fc7f3Shx147065 "setprofileparam",
388516fc7f3Shx147065 do_setprofparam,
389516fc7f3Shx147065 B_TRUE,
390516fc7f3Shx147065 B_TRUE,
391516fc7f3Shx147065 B_FALSE
392516fc7f3Shx147065 },
393516fc7f3Shx147065 {
394516fc7f3Shx147065 "getprofileparam",
395516fc7f3Shx147065 do_getprofparam,
396516fc7f3Shx147065 B_FALSE,
397516fc7f3Shx147065 B_TRUE,
398516fc7f3Shx147065 B_TRUE
399516fc7f3Shx147065 },
400516fc7f3Shx147065 {
401516fc7f3Shx147065 "setprofilewepkey",
402516fc7f3Shx147065 do_setprofwepkey,
403516fc7f3Shx147065 B_TRUE,
404516fc7f3Shx147065 B_TRUE,
405516fc7f3Shx147065 B_FALSE
406516fc7f3Shx147065 }
407516fc7f3Shx147065 };
408516fc7f3Shx147065
409516fc7f3Shx147065
410516fc7f3Shx147065 typedef enum {RW, RO, WO} rw_property_t;
411516fc7f3Shx147065 typedef struct gs_ops {
412516fc7f3Shx147065 config_item_t index;
413516fc7f3Shx147065 char cmd[32];
414516fc7f3Shx147065 boolean_t (*p_do_get_func)(int fd);
415516fc7f3Shx147065 boolean_t (*p_do_set_func)(int fd, const char *arg);
416516fc7f3Shx147065 rw_property_t rw;
417516fc7f3Shx147065 } gs_ops_t;
418516fc7f3Shx147065 static gs_ops_t do_gs_func[] = {
419516fc7f3Shx147065 {LINKSTATUS, "linkstatus", NULL, NULL, RO},
420516fc7f3Shx147065 {BSSID, "bssid", do_get_bssid, NULL, RO},
421516fc7f3Shx147065 {ESSID, "essid", do_get_essid, do_set_essid, RW},
422516fc7f3Shx147065 {BSSTYPE, "bsstype", do_get_bsstype, do_set_bsstype, RW},
423516fc7f3Shx147065 {CREATEIBSS, "createibss", do_get_createibss, do_set_createibss, RW},
424516fc7f3Shx147065 {CHANNEL, "channel", do_get_channel, do_set_channel, RW},
425516fc7f3Shx147065 {RATES, "rates", do_get_rates, do_set_rates, RW},
426516fc7f3Shx147065 {POWERMODE, "powermode", do_get_powermode, do_set_powermode, RW},
427516fc7f3Shx147065 {AUTHMODE, "authmode", do_get_authmode, do_set_authmode, RW},
428516fc7f3Shx147065 {ENCRYPTION, "encryption", do_get_encryption, do_set_encryption, RW},
429516fc7f3Shx147065 {WEPKEYID, "wepkeyindex", do_get_wepkeyid, do_set_wepkeyid, RW},
430516fc7f3Shx147065 {WEPKEY, "wepkey|1-4", NULL, do_set_wepkey, WO},
431516fc7f3Shx147065 {SIGNAL, "signal", do_get_signal, NULL, RO},
432516fc7f3Shx147065 {RADIOON, "radio", do_get_radioon, do_set_radioon, RW},
433516fc7f3Shx147065 };
434516fc7f3Shx147065
435516fc7f3Shx147065 #define N_FUNC sizeof (do_func) / sizeof (cmd_ops_t)
436516fc7f3Shx147065 #define N_GS_FUNC sizeof (do_gs_func) / sizeof (gs_ops_t)
437516fc7f3Shx147065
438516fc7f3Shx147065 /*
439516fc7f3Shx147065 * valid rate value
440516fc7f3Shx147065 */
441516fc7f3Shx147065 typedef struct wifi_rates_tab {
442516fc7f3Shx147065 char *rates_s;
443516fc7f3Shx147065 uint8_t rates_i;
444516fc7f3Shx147065 uint8_t rates_reserve0;
445516fc7f3Shx147065 uint8_t rates_reserve1;
446516fc7f3Shx147065 uint8_t rates_reserve2;
447516fc7f3Shx147065 } wifi_rates_tab_t;
448516fc7f3Shx147065
449516fc7f3Shx147065 /*
450516fc7f3Shx147065 * the rates value is in increments of 500kb/s.
451516fc7f3Shx147065 * according to the 802.11 a/b/g specs(IEEE):
452516fc7f3Shx147065 * 802.11b(IEEE Std 802.11b-1999) page35, rates should be:
453516fc7f3Shx147065 * X02, X04, X0b, X16
454516fc7f3Shx147065 * 802.11a(IEEE Std 802.11a-1999) page47, rates should be:
455516fc7f3Shx147065 * 6,9,12,18,24,36,48,54 Mb/s
456516fc7f3Shx147065 * 802.11g(IEEE Std 802.11g-2003) page44, rates should be:
457516fc7f3Shx147065 * 1,2,5.5,11,6,9,12,18,22,24,33,36,48,54 Mb/s
458516fc7f3Shx147065 */
459516fc7f3Shx147065 #define WIFI_RATES_NUM 14
460516fc7f3Shx147065 static wifi_rates_tab_t wifi_rates_s[WIFI_RATES_NUM] = {
461516fc7f3Shx147065 {"1", WL_RATE_1M, 0, 0, 0},
462516fc7f3Shx147065 {"2", WL_RATE_2M, 0, 0, 0},
463516fc7f3Shx147065 {"5.5", WL_RATE_5_5M, 0, 0, 0},
464516fc7f3Shx147065 {"6", WL_RATE_6M, 0, 0, 0},
465516fc7f3Shx147065 {"9", WL_RATE_9M, 0, 0, 0},
466516fc7f3Shx147065 {"11", WL_RATE_11M, 0, 0, 0},
467516fc7f3Shx147065 {"12", WL_RATE_12M, 0, 0, 0},
468516fc7f3Shx147065 {"18", WL_RATE_18M, 0, 0, 0},
469516fc7f3Shx147065 {"22", WL_RATE_22M, 0, 0, 0},
470516fc7f3Shx147065 {"24", WL_RATE_24M, 0, 0, 0},
471516fc7f3Shx147065 {"33", WL_RATE_33M, 0, 0, 0},
472516fc7f3Shx147065 {"36", WL_RATE_36M, 0, 0, 0},
473516fc7f3Shx147065 {"48", WL_RATE_48M, 0, 0, 0},
474516fc7f3Shx147065 {"54", WL_RATE_54M, 0, 0, 0}
475516fc7f3Shx147065 };
476516fc7f3Shx147065 /* print the error message on why set or get ioctl command failed. */
477516fc7f3Shx147065 static void
print_error(uint32_t errorno)478516fc7f3Shx147065 print_error(uint32_t errorno)
479516fc7f3Shx147065 {
480516fc7f3Shx147065 char *buf;
481516fc7f3Shx147065
482516fc7f3Shx147065 switch (errorno) {
483516fc7f3Shx147065 case WL_SUCCESS:
484516fc7f3Shx147065 buf = gettext("command succeeded");
485516fc7f3Shx147065 break;
486516fc7f3Shx147065 case WL_NOTSUPPORTED:
487516fc7f3Shx147065 case WL_LACK_FEATURE:
488516fc7f3Shx147065 case WL_HW_ERROR:
489516fc7f3Shx147065 case WL_ACCESS_DENIED:
490516fc7f3Shx147065 buf = strerror(errorno);
491516fc7f3Shx147065 break;
492516fc7f3Shx147065 case WL_READONLY:
493516fc7f3Shx147065 buf = gettext("parameter read-only");
494516fc7f3Shx147065 break;
495516fc7f3Shx147065 case WL_WRITEONLY:
496516fc7f3Shx147065 buf = gettext("parameter write-only");
497516fc7f3Shx147065 break;
498516fc7f3Shx147065 case WL_NOAP:
499516fc7f3Shx147065 buf = gettext("no access point available");
500516fc7f3Shx147065 break;
501516fc7f3Shx147065 default:
502516fc7f3Shx147065 buf = gettext("unknown error");
503516fc7f3Shx147065 break;
504516fc7f3Shx147065 }
505516fc7f3Shx147065 (void) fprintf(stderr, "%s\n", buf);
506516fc7f3Shx147065 }
507516fc7f3Shx147065
508516fc7f3Shx147065 static void *
safe_malloc(size_t size)509516fc7f3Shx147065 safe_malloc(size_t size)
510516fc7f3Shx147065 {
511516fc7f3Shx147065 void *buf;
512516fc7f3Shx147065
513516fc7f3Shx147065 buf = malloc(size);
514516fc7f3Shx147065 if (buf == NULL) {
515516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: malloc: %s\n"),
516516fc7f3Shx147065 gExecName, strerror(errno));
517516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
518516fc7f3Shx147065 }
519516fc7f3Shx147065 return (buf);
520516fc7f3Shx147065 }
521516fc7f3Shx147065
522516fc7f3Shx147065 static void *
safe_calloc(size_t nelem,size_t elsize)523516fc7f3Shx147065 safe_calloc(size_t nelem, size_t elsize)
524516fc7f3Shx147065 {
525516fc7f3Shx147065 void *buf;
526516fc7f3Shx147065
527516fc7f3Shx147065 buf = calloc(nelem, elsize);
528516fc7f3Shx147065 if (buf == NULL) {
529516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: calloc: %s\n"),
530516fc7f3Shx147065 gExecName, strerror(errno));
531516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
532516fc7f3Shx147065 }
533516fc7f3Shx147065 return (buf);
534516fc7f3Shx147065 }
535516fc7f3Shx147065
536516fc7f3Shx147065 static char *
safe_strdup(const char * s1)537516fc7f3Shx147065 safe_strdup(const char *s1)
538516fc7f3Shx147065 {
539516fc7f3Shx147065 char *p;
540516fc7f3Shx147065
541516fc7f3Shx147065 p = strdup(s1);
542516fc7f3Shx147065 if (p == NULL) {
543516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: strdup: %s\n"),
544516fc7f3Shx147065 gExecName, strerror(errno));
545516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
546516fc7f3Shx147065 }
547516fc7f3Shx147065 return (p);
548516fc7f3Shx147065 }
549516fc7f3Shx147065
550516fc7f3Shx147065 static void
safe_snprintf(char * s,size_t n,const char * format,...)551516fc7f3Shx147065 safe_snprintf(char *s, size_t n, const char *format, ...)
552516fc7f3Shx147065 {
553516fc7f3Shx147065 int len;
554516fc7f3Shx147065 va_list ap;
555516fc7f3Shx147065 va_start(ap, format);
556516fc7f3Shx147065
557516fc7f3Shx147065 len = vsnprintf(s, n, format, ap);
558516fc7f3Shx147065 if ((len <= 0) || (len > n - 1)) {
559516fc7f3Shx147065 (void) fprintf(stderr,
560516fc7f3Shx147065 gettext("%s: snprintf: %s\n"),
561516fc7f3Shx147065 gExecName, strerror(errno));
562516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
563516fc7f3Shx147065 }
564516fc7f3Shx147065 va_end(ap);
565516fc7f3Shx147065 }
566516fc7f3Shx147065
567516fc7f3Shx147065 static void
safe_fclose(FILE * stream)568516fc7f3Shx147065 safe_fclose(FILE *stream)
569516fc7f3Shx147065 {
570516fc7f3Shx147065 int err;
571516fc7f3Shx147065
572516fc7f3Shx147065 err = fclose(stream);
573516fc7f3Shx147065 if (err == EOF) {
574516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: fclose: %s\n"),
575516fc7f3Shx147065 gExecName, strerror(errno));
576516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
577516fc7f3Shx147065 }
578516fc7f3Shx147065 }
579516fc7f3Shx147065 /*
580516fc7f3Shx147065 * new_ae: Add an element with content pointed by arg to the list *ael.
581516fc7f3Shx147065 */
582516fc7f3Shx147065 static void
new_ae(aelist_t * ael,const char * arg)583516fc7f3Shx147065 new_ae(aelist_t *ael, const char *arg)
584516fc7f3Shx147065 {
585516fc7f3Shx147065 ae_t *pae = NULL;
586516fc7f3Shx147065
587516fc7f3Shx147065 PRTDBG(("new_ae(0x%x, \"%s\")\n", ael, arg));
588516fc7f3Shx147065 assert((ael != NULL) && (arg != NULL));
589516fc7f3Shx147065
590516fc7f3Shx147065 pae = safe_calloc(sizeof (*pae), 1);
591516fc7f3Shx147065 pae->ae_arg = safe_strdup(arg);
592516fc7f3Shx147065 pae->ae_next = NULL;
593516fc7f3Shx147065
594516fc7f3Shx147065 if (ael->ael_tail == NULL) {
595516fc7f3Shx147065 ael->ael_head = pae;
596516fc7f3Shx147065 } else {
597516fc7f3Shx147065 ael->ael_tail->ae_next = pae;
598516fc7f3Shx147065 }
599516fc7f3Shx147065 ael->ael_tail = pae;
600516fc7f3Shx147065 ael->ael_argc++;
601516fc7f3Shx147065 }
602516fc7f3Shx147065 /*
603516fc7f3Shx147065 * new_ael: Create a new aelist with list_type "type"
604516fc7f3Shx147065 * and return the list pointer.
605516fc7f3Shx147065 */
606516fc7f3Shx147065 static aelist_t *
new_ael(list_type_t type)607516fc7f3Shx147065 new_ael(list_type_t type)
608516fc7f3Shx147065 {
609516fc7f3Shx147065 aelist_t *plist;
610516fc7f3Shx147065
611516fc7f3Shx147065 plist = safe_calloc(sizeof (*plist), 1);
612516fc7f3Shx147065 plist->type = type;
613516fc7f3Shx147065 plist->ael_argc = 0;
614516fc7f3Shx147065 plist->ael_head = plist->ael_tail = NULL;
615516fc7f3Shx147065
616516fc7f3Shx147065 PRTDBG(("new_ael(%d) = 0x%x\n", type, plist));
617516fc7f3Shx147065 return (plist);
618516fc7f3Shx147065 }
619516fc7f3Shx147065
620516fc7f3Shx147065 /*
621516fc7f3Shx147065 * new_config_file: Creates a new config_file_t struct which is counterpart of
622516fc7f3Shx147065 * of the configration file, and return the pointer.
623516fc7f3Shx147065 */
624516fc7f3Shx147065 static config_file_t *
new_config_file()625516fc7f3Shx147065 new_config_file()
626516fc7f3Shx147065 {
627516fc7f3Shx147065 config_file_t *p_config_file;
628516fc7f3Shx147065
629516fc7f3Shx147065 p_config_file = safe_calloc(sizeof (config_file_t), 1);
630516fc7f3Shx147065 p_config_file->section_argc = 0;
631516fc7f3Shx147065 p_config_file->section_head = p_config_file->section_tail = NULL;
632516fc7f3Shx147065
633516fc7f3Shx147065 PRTDBG(("new_config_file() = 0x%x\n", p_config_file));
634516fc7f3Shx147065 return (p_config_file);
635516fc7f3Shx147065 }
636516fc7f3Shx147065
637516fc7f3Shx147065 /*
638516fc7f3Shx147065 * new_section: Add a list pointed by "p_list", with identity "section_id" to
639516fc7f3Shx147065 * the config_file_t struct pointed by "p_config_file"
640516fc7f3Shx147065 */
641516fc7f3Shx147065 static void
new_section(config_file_t * p_config_file,aelist_t * p_list,const char * section_id)642516fc7f3Shx147065 new_section(config_file_t *p_config_file, aelist_t *p_list,
643516fc7f3Shx147065 const char *section_id)
644516fc7f3Shx147065 {
645516fc7f3Shx147065 section_t *p_section = NULL;
646516fc7f3Shx147065
647516fc7f3Shx147065 PRTDBG(("new_section(0x%x, 0x%x, \"%s\")\n", p_config_file, p_list,
648516fc7f3Shx147065 section_id));
649516fc7f3Shx147065 assert((p_config_file != NULL) && (p_list != NULL) &&
650516fc7f3Shx147065 (section_id != NULL));
651516fc7f3Shx147065
652516fc7f3Shx147065 p_section = safe_calloc(sizeof (*p_section), 1);
653516fc7f3Shx147065 p_section->list = p_list;
654516fc7f3Shx147065 p_section->section_next = NULL;
655516fc7f3Shx147065 p_section->section_id = safe_strdup(section_id);
656516fc7f3Shx147065
657516fc7f3Shx147065 if (p_config_file->section_tail == NULL) {
658516fc7f3Shx147065 p_config_file->section_head = p_section;
659516fc7f3Shx147065 } else {
660516fc7f3Shx147065 p_config_file->section_tail->section_next = p_section;
661516fc7f3Shx147065 }
662516fc7f3Shx147065 p_config_file->section_tail = p_section;
663516fc7f3Shx147065 p_config_file->section_argc++;
664516fc7f3Shx147065 }
665516fc7f3Shx147065
666516fc7f3Shx147065 /*
667516fc7f3Shx147065 * destroy_config:Destroy the config_file struct
668516fc7f3Shx147065 */
669516fc7f3Shx147065 static void
destroy_config(config_file_t * p_config_file)670516fc7f3Shx147065 destroy_config(config_file_t *p_config_file)
671516fc7f3Shx147065 {
672516fc7f3Shx147065 section_t *p_section = NULL;
673516fc7f3Shx147065 aelist_t *p_list = NULL;
674516fc7f3Shx147065 ae_t *pae = NULL;
675516fc7f3Shx147065
676516fc7f3Shx147065 PRTDBG(("destory_config(0x%x)\n", p_config_file));
677516fc7f3Shx147065 assert(p_config_file != NULL);
678516fc7f3Shx147065
679516fc7f3Shx147065 p_section = p_config_file->section_head;
680516fc7f3Shx147065 while (p_section != NULL) {
681516fc7f3Shx147065 p_list = p_section->list;
682516fc7f3Shx147065 if (p_list != NULL) {
683516fc7f3Shx147065 pae = p_list->ael_head;
684516fc7f3Shx147065 while (pae != NULL) {
685516fc7f3Shx147065 if (pae->ae_arg != NULL)
686516fc7f3Shx147065 free(pae->ae_arg);
687516fc7f3Shx147065 pae->ae_arg = NULL;
688516fc7f3Shx147065 pae = pae->ae_next;
689516fc7f3Shx147065 free(p_list->ael_head);
690516fc7f3Shx147065 p_list->ael_head = pae;
691516fc7f3Shx147065 }
692516fc7f3Shx147065 free(p_list);
693516fc7f3Shx147065 p_list = NULL;
694516fc7f3Shx147065 }
695516fc7f3Shx147065 if (p_section->section_id != NULL)
696516fc7f3Shx147065 free(p_section->section_id);
697516fc7f3Shx147065 p_section->section_id = NULL;
698516fc7f3Shx147065 p_section = p_section->section_next;
699516fc7f3Shx147065 free(p_config_file->section_head);
700516fc7f3Shx147065 p_config_file->section_head = p_section;
701516fc7f3Shx147065 }
702516fc7f3Shx147065 free(p_config_file);
703516fc7f3Shx147065 p_config_file = NULL;
704516fc7f3Shx147065 }
705516fc7f3Shx147065
706516fc7f3Shx147065 /*
707516fc7f3Shx147065 * parse_file: Parse each section of the configration file
708516fc7f3Shx147065 * and construct the config_file_t structure.
709516fc7f3Shx147065 * Example:
710516fc7f3Shx147065 * A config file has contents below:
711516fc7f3Shx147065 *
712516fc7f3Shx147065 * {preferrence}
713516fc7f3Shx147065 * essid=ap7-3
714516fc7f3Shx147065 * essid=linksys
715516fc7f3Shx147065 *
716516fc7f3Shx147065 * {history}
717516fc7f3Shx147065 * essid=ap7-3
718516fc7f3Shx147065 * essid=ap7-2
719516fc7f3Shx147065 *
720516fc7f3Shx147065 * [ap7-3]
721516fc7f3Shx147065 * essid=ap7-3
722516fc7f3Shx147065 * wepkeyid=3
723516fc7f3Shx147065 * channel=11
724516fc7f3Shx147065 * rates=1,2
725516fc7f3Shx147065 *
726516fc7f3Shx147065 * [linksys]
727516fc7f3Shx147065 * essid=linksys
728516fc7f3Shx147065 * createibss=BSS
729516fc7f3Shx147065 * authmode=OPENSYSTEM
730516fc7f3Shx147065 * wepkeyid=1
731516fc7f3Shx147065 *
732516fc7f3Shx147065 * then its config_file_t structure will be:
733516fc7f3Shx147065 *
734516fc7f3Shx147065 * config_file_t
735516fc7f3Shx147065 * |~~~~~~~~~~~~~~~~~~~~~~~~~~|
736516fc7f3Shx147065 * | section_argc=5 |
737516fc7f3Shx147065 * |~~~~~~~~~~~~T~~~~~~~~~~~~~|
738516fc7f3Shx147065 * /| *head | *tail |\
739516fc7f3Shx147065 * / ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \
740516fc7f3Shx147065 * / \
741516fc7f3Shx147065 * / \
742516fc7f3Shx147065 * / \
743516fc7f3Shx147065 * / \
744516fc7f3Shx147065 * / \
745516fc7f3Shx147065 * section_t V section_t V section_t
746516fc7f3Shx147065 * |~~~~~~~~~~~~~~~|~~| |~~~~~~~~~~~~~~~|~~| |~~~~~~~~~~~~~~|~~|
747516fc7f3Shx147065 * |"{preferrence}"| | | "{history}" | | | "[linksys]" | |
748516fc7f3Shx147065 * |~~~~~~~~~~~~~~~| -+---->|~~~~~~~~~~~~~~~| -+->..->|~~~~~~~~~~~~~~| -+->NULL
749516fc7f3Shx147065 * | *list | | | *list | | | *list | |
750516fc7f3Shx147065 * ~~T~~~~~~~~~~~~~~~~~ ~~~T~~~~~~~~~~~~~~~~ ~~~T~~~~~~~~~~~~~~~
751516fc7f3Shx147065 * | | |
752516fc7f3Shx147065 * | | |
753516fc7f3Shx147065 * V aelist_t V aelist_t V aelist_t
754516fc7f3Shx147065 * |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| |~~~~~~~~~~~~~|
755516fc7f3Shx147065 * | argc=2 | | argc=3 | | argc=4 |
756516fc7f3Shx147065 * |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| |~~~~~~~~~~~~~|
757516fc7f3Shx147065 * |PREFFERRENCE | | HISTORY | | PROFILE |
758516fc7f3Shx147065 * |~~~~~~T~~~~~~| |~~~~~~T~~~~~~| |~~~~~~T~~~~~~|
759516fc7f3Shx147065 * |*head |*tail |\ |*head |*tail |\ |*head |*tail |
760516fc7f3Shx147065 * ~~T~~~~~~~~~~~~ \ ~~T~~~~~~~~~~~~ \ /~~~~~~~~~~~~~~~\
761516fc7f3Shx147065 * | \ V V / \
762516fc7f3Shx147065 * | \ ... ... / \
763516fc7f3Shx147065 * V ae_t V ae_t ae_t V ae_t V
764516fc7f3Shx147065 * |~~~~~~~~~T~~| |~~~~~~~~~T~~| |~~~~~~~~~T~~| |~~~~~~~~~T~~|
765516fc7f3Shx147065 * |"essid= | -+->|"essid= | -+->NULL |"essid= | -+->..->|"wepkeyid| -+->NULL
766516fc7f3Shx147065 * | ap7-3" | | | linksys"| | | linksys"| | | =1" | |
767516fc7f3Shx147065 * ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
768516fc7f3Shx147065 *
769516fc7f3Shx147065 */
770516fc7f3Shx147065
771516fc7f3Shx147065 static config_file_t *
parse_file(const char * pfile)772516fc7f3Shx147065 parse_file(const char *pfile)
773516fc7f3Shx147065 {
774516fc7f3Shx147065 FILE *file = NULL;
775516fc7f3Shx147065 int fd = 0;
776516fc7f3Shx147065 char buf_line[256];
777516fc7f3Shx147065 config_file_t *p_config_file;
778516fc7f3Shx147065 list_type_t cur_list = OTHER;
779516fc7f3Shx147065 aelist_t *prefer_list = NULL;
780516fc7f3Shx147065 aelist_t *history_list = NULL;
781516fc7f3Shx147065 aelist_t *profile_list = NULL;
782516fc7f3Shx147065 aelist_t *activep_list = NULL;
783516fc7f3Shx147065
784516fc7f3Shx147065 assert(pfile != NULL);
785516fc7f3Shx147065 /*
786516fc7f3Shx147065 * The files /etc/inet/wifi and /etc/inet/secret/wifiwepkey should
787516fc7f3Shx147065 * be opened with "r" attribute. If these two files do not exist,
788516fc7f3Shx147065 * create them here.
789516fc7f3Shx147065 */
790516fc7f3Shx147065 file = fopen(pfile, "r");
791516fc7f3Shx147065
792516fc7f3Shx147065 if (file == NULL) {
793516fc7f3Shx147065 fd = open(pfile, O_CREAT|O_EXCL|O_RDWR, 0600);
794516fc7f3Shx147065 if (fd < 0) {
795516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to open %s"
796516fc7f3Shx147065 "\n"), gExecName, pfile);
797516fc7f3Shx147065 goto error1;
798516fc7f3Shx147065 }
799516fc7f3Shx147065 file = fdopen(fd, "w");
800516fc7f3Shx147065 (void) chmod(pfile, S_IRUSR);
801516fc7f3Shx147065 }
802516fc7f3Shx147065
803516fc7f3Shx147065 p_config_file = new_config_file();
804516fc7f3Shx147065
805516fc7f3Shx147065 while (fgets(buf_line, sizeof (buf_line), file) != NULL) {
806516fc7f3Shx147065 if ((buf_line[0] == '\n') || (buf_line[0] == ' '))
807516fc7f3Shx147065 continue;
808516fc7f3Shx147065 /* replace the old '\n' to '\0' */
809516fc7f3Shx147065 buf_line[strlen(buf_line) - 1] = '\0';
810516fc7f3Shx147065 if (strstr(buf_line, WIFI_PREFER) == buf_line) {
811516fc7f3Shx147065 if (prefer_list == NULL) {
812516fc7f3Shx147065 cur_list = PREFERENCE;
813516fc7f3Shx147065 prefer_list = new_ael(PREFERENCE);
814516fc7f3Shx147065 new_section(p_config_file, prefer_list,
815516fc7f3Shx147065 WIFI_PREFER);
816516fc7f3Shx147065 } else {
817516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
818516fc7f3Shx147065 "%s : duplicated %s section\n"),
819516fc7f3Shx147065 gExecName, pfile, WIFI_PREFER);
820516fc7f3Shx147065 goto error;
821516fc7f3Shx147065 }
822516fc7f3Shx147065 } else if (strstr(buf_line, WIFI_HISTORY) == buf_line) {
823516fc7f3Shx147065 if (history_list == NULL) {
824516fc7f3Shx147065 cur_list = HISTORY;
825516fc7f3Shx147065 history_list = new_ael(HISTORY);
826516fc7f3Shx147065 new_section(p_config_file, history_list,
827516fc7f3Shx147065 WIFI_HISTORY);
828516fc7f3Shx147065 } else {
829516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
830516fc7f3Shx147065 "%s : duplicated %s section\n"),
831516fc7f3Shx147065 gExecName, pfile, WIFI_HISTORY);
832516fc7f3Shx147065 goto error;
833516fc7f3Shx147065 }
834516fc7f3Shx147065 } else if (strstr(buf_line, WIFI_ACTIVEP) == buf_line) {
835516fc7f3Shx147065 if (activep_list == NULL) {
836516fc7f3Shx147065 cur_list = ACTIVEP;
837516fc7f3Shx147065 activep_list = new_ael(ACTIVEP);
838516fc7f3Shx147065 new_section(p_config_file, activep_list,
839516fc7f3Shx147065 WIFI_ACTIVEP);
840516fc7f3Shx147065 } else {
841516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
842516fc7f3Shx147065 "%s : duplicated %s section\n"),
843516fc7f3Shx147065 gExecName, pfile, WIFI_ACTIVEP);
844516fc7f3Shx147065 goto error;
845516fc7f3Shx147065 }
846516fc7f3Shx147065 } else if ((strchr(buf_line, '[') == buf_line) &&
847516fc7f3Shx147065 (buf_line[strlen(buf_line) - 1] == ']')) {
848516fc7f3Shx147065 cur_list = PROFILE;
849516fc7f3Shx147065 profile_list = new_ael(PROFILE);
850516fc7f3Shx147065 new_section(p_config_file, profile_list,
851516fc7f3Shx147065 buf_line);
852516fc7f3Shx147065 } else {
853516fc7f3Shx147065 switch (cur_list) {
854516fc7f3Shx147065 case PREFERENCE:
855516fc7f3Shx147065 if (prefer_list->ael_argc <=
856516fc7f3Shx147065 MAX_PREFERENCE_NUM)
857516fc7f3Shx147065 new_ae(prefer_list, buf_line);
858516fc7f3Shx147065 break;
859516fc7f3Shx147065 case HISTORY:
860516fc7f3Shx147065 if (history_list->ael_argc <=
861516fc7f3Shx147065 MAX_HISTORY_NUM)
862516fc7f3Shx147065 new_ae(history_list, buf_line);
863516fc7f3Shx147065 break;
864516fc7f3Shx147065 case ACTIVEP:
865516fc7f3Shx147065 if ((activep_list->ael_argc <= 1) &&
866516fc7f3Shx147065 (strpbrk(buf_line, "=") != NULL))
867516fc7f3Shx147065 new_ae(activep_list, buf_line);
868516fc7f3Shx147065 break;
869516fc7f3Shx147065 case PROFILE:
870516fc7f3Shx147065 if (strpbrk(buf_line, "=") != NULL)
871516fc7f3Shx147065 new_ae(profile_list, buf_line);
872516fc7f3Shx147065 break;
873516fc7f3Shx147065 default:
874516fc7f3Shx147065 (void) fprintf(stderr,
875516fc7f3Shx147065 gettext("%s: %s: file format error\n"),
876516fc7f3Shx147065 gExecName, pfile);
877516fc7f3Shx147065 goto error;
878516fc7f3Shx147065 }
879516fc7f3Shx147065 }
880516fc7f3Shx147065 }
881516fc7f3Shx147065 PRTDBG(("parse_file(\"%s\")=0x%x\n", pfile, p_config_file));
882516fc7f3Shx147065 (void) fclose(file);
883516fc7f3Shx147065 return (p_config_file);
884516fc7f3Shx147065 error:
885516fc7f3Shx147065 destroy_config(p_config_file);
886516fc7f3Shx147065 (void) fclose(file);
887516fc7f3Shx147065 error1:
888516fc7f3Shx147065 return (NULL);
889516fc7f3Shx147065 }
890516fc7f3Shx147065 /*
891516fc7f3Shx147065 * construct an argument vector from an aelist
892516fc7f3Shx147065 */
893516fc7f3Shx147065 static char **
aeltoargv(aelist_t * ael,int * ael_num)894516fc7f3Shx147065 aeltoargv(aelist_t *ael, int *ael_num)
895516fc7f3Shx147065 {
896516fc7f3Shx147065 ae_t *ae = NULL;
897516fc7f3Shx147065 char **argv = NULL;
898516fc7f3Shx147065 int argc = 0;
899516fc7f3Shx147065
900516fc7f3Shx147065 PRTDBG(("aeltoargv(%x)\n", ael));
901516fc7f3Shx147065 assert(ael != NULL);
902516fc7f3Shx147065
903516fc7f3Shx147065 argv = safe_calloc(sizeof (*argv), ael->ael_argc);
904516fc7f3Shx147065
905516fc7f3Shx147065 for (argc = 0, ae = ael->ael_head; ae; ae = ae->ae_next) {
906516fc7f3Shx147065 /* skip bssid since it can not be set */
907516fc7f3Shx147065 if (strncmp(ae->ae_arg, "bssid=", strlen("bssid=")) == 0)
908516fc7f3Shx147065 continue;
909516fc7f3Shx147065 argv[argc] = safe_strdup(ae->ae_arg);
910516fc7f3Shx147065 argc++;
911516fc7f3Shx147065 if (ae == ael->ael_tail)
912516fc7f3Shx147065 break;
913516fc7f3Shx147065 }
914516fc7f3Shx147065
915516fc7f3Shx147065 PRTDBG(("aeltoargv(0x%x) = 0x%x\n\n", ael, argv));
916516fc7f3Shx147065 *ael_num = argc;
917516fc7f3Shx147065 return (argv);
918516fc7f3Shx147065 }
919516fc7f3Shx147065
920516fc7f3Shx147065 /*
921516fc7f3Shx147065 * archived contents into a file
922516fc7f3Shx147065 */
923516fc7f3Shx147065 static boolean_t
fprint_config_file(config_file_t * p_config_file,const char * file_name)924516fc7f3Shx147065 fprint_config_file(config_file_t *p_config_file, const char *file_name)
925516fc7f3Shx147065 {
926516fc7f3Shx147065 FILE *file = NULL;
927516fc7f3Shx147065 int fd = 0;
928516fc7f3Shx147065 int len;
929516fc7f3Shx147065 section_t *p_section = NULL;
930516fc7f3Shx147065 aelist_t *p_list = NULL;
931516fc7f3Shx147065 ae_t *pae = NULL;
932516fc7f3Shx147065 char temp_file[256];
933516fc7f3Shx147065 struct stat buf;
934516fc7f3Shx147065
935516fc7f3Shx147065 PRTDBG(("fprint_config_file(0x%x, \"%s\")\n", p_config_file,
936516fc7f3Shx147065 file_name));
937516fc7f3Shx147065 assert((p_config_file != NULL)&&(strcmp(file_name, "") != 0));
938516fc7f3Shx147065
939516fc7f3Shx147065 safe_snprintf(temp_file, sizeof (temp_file),
940516fc7f3Shx147065 "%s.tmp", file_name);
941516fc7f3Shx147065 fd = open(temp_file, O_CREAT|O_WRONLY|O_TRUNC, 0600);
942516fc7f3Shx147065 if (fd < 0) {
943516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to open %s\n"),
944516fc7f3Shx147065 gExecName, temp_file);
945516fc7f3Shx147065 return (B_FALSE);
946516fc7f3Shx147065 }
947516fc7f3Shx147065 file = fdopen(fd, "w");
948516fc7f3Shx147065
949516fc7f3Shx147065 p_section = p_config_file->section_head;
950516fc7f3Shx147065 while (p_section != NULL) {
951516fc7f3Shx147065 p_list = p_section->list;
952516fc7f3Shx147065 if (p_list != NULL) {
953516fc7f3Shx147065 PRTDBG(("fprint_config_file: section_id=%s\n",
954516fc7f3Shx147065 p_section->section_id));
955516fc7f3Shx147065 len = fprintf(file, "\n%s\n", p_section->section_id);
956516fc7f3Shx147065 if (len < 0) {
957516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
958516fc7f3Shx147065 "failed to update %s: %s\n"),
959516fc7f3Shx147065 gExecName, file_name, strerror(errno));
960516fc7f3Shx147065 safe_fclose(file);
961516fc7f3Shx147065 return (B_FALSE);
962516fc7f3Shx147065 }
963516fc7f3Shx147065 pae = p_list->ael_head;
964516fc7f3Shx147065 while (pae != NULL) {
965516fc7f3Shx147065 if (pae->ae_arg != NULL) {
966516fc7f3Shx147065 len = fprintf(file, "%s\n",
967516fc7f3Shx147065 pae->ae_arg);
968516fc7f3Shx147065 if (len < 0) {
969516fc7f3Shx147065 (void) fprintf(stderr,
970516fc7f3Shx147065 gettext("%s: failed to "
971516fc7f3Shx147065 "update %s: %s\n"),
972516fc7f3Shx147065 gExecName, file_name,
973516fc7f3Shx147065 strerror(errno));
974516fc7f3Shx147065 safe_fclose(file);
975516fc7f3Shx147065 return (B_FALSE);
976516fc7f3Shx147065 }
977516fc7f3Shx147065 }
978516fc7f3Shx147065 pae = pae->ae_next;
979516fc7f3Shx147065 }
980516fc7f3Shx147065 }
981516fc7f3Shx147065 p_section = p_section->section_next;
982516fc7f3Shx147065 }
983516fc7f3Shx147065 safe_fclose(file);
984516fc7f3Shx147065 /*
985516fc7f3Shx147065 * The attribute of the file /etc/inet/wifi and
986516fc7f3Shx147065 * /etc/inet/security/wifiwepkey should be retained.
987516fc7f3Shx147065 * if those file do not exist, set default file mode.
988516fc7f3Shx147065 */
989516fc7f3Shx147065 if (stat(file_name, &buf) != 0) {
990516fc7f3Shx147065 if (errno == ENOENT) {
991516fc7f3Shx147065 buf.st_mode = 0600;
992516fc7f3Shx147065 } else {
993516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to get "
994516fc7f3Shx147065 "file %s stat: %s\n"),
995516fc7f3Shx147065 gExecName, file_name, strerror(errno));
996516fc7f3Shx147065 return (B_FALSE);
997516fc7f3Shx147065 }
998516fc7f3Shx147065 }
999516fc7f3Shx147065 if (rename(temp_file, file_name) != 0) {
1000516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to update %s: %s"
1001516fc7f3Shx147065 "\n"), gExecName, file_name, strerror(errno));
1002516fc7f3Shx147065 return (B_FALSE);
1003516fc7f3Shx147065 }
1004516fc7f3Shx147065 (void) chmod(file_name, buf.st_mode);
1005516fc7f3Shx147065 return (B_TRUE);
1006516fc7f3Shx147065 }
1007516fc7f3Shx147065 /*
1008516fc7f3Shx147065 * append_pa: Each section holds a section_id which identifies a section
1009516fc7f3Shx147065 * a profile uses its essid appending "[]" to denote its section_id.
1010516fc7f3Shx147065 * note: new memory is allocated, remember to free.
1011516fc7f3Shx147065 */
1012516fc7f3Shx147065 static char *
append_pa(const char * arg)1013516fc7f3Shx147065 append_pa(const char *arg)
1014516fc7f3Shx147065 {
1015516fc7f3Shx147065 char *pbuf = NULL;
1016516fc7f3Shx147065 int len;
1017516fc7f3Shx147065
1018516fc7f3Shx147065 assert(arg != NULL);
1019516fc7f3Shx147065
1020516fc7f3Shx147065 len = strlen(arg) + 3;
1021516fc7f3Shx147065 pbuf = safe_malloc(len);
1022516fc7f3Shx147065 safe_snprintf(pbuf, len, "[%s]", arg);
1023516fc7f3Shx147065 PRTDBG(("append_pa(\"%s\") = \"%s\"\n", arg, pbuf));
1024516fc7f3Shx147065 return (pbuf);
1025516fc7f3Shx147065 }
1026516fc7f3Shx147065 /*
1027516fc7f3Shx147065 * find a section by section_id from p_config_file,
1028516fc7f3Shx147065 * return the section pointer.
1029516fc7f3Shx147065 */
1030516fc7f3Shx147065 static section_t *
find_section(config_file_t * p_config_file,const char * section_id)1031516fc7f3Shx147065 find_section(config_file_t *p_config_file, const char *section_id)
1032516fc7f3Shx147065 {
1033516fc7f3Shx147065 section_t *p_section = NULL;
1034516fc7f3Shx147065
1035516fc7f3Shx147065 PRTDBG(("find_section(0x%x, \"%s\")\n", p_config_file, section_id));
1036516fc7f3Shx147065 assert((section_id != NULL)&&(p_config_file != NULL));
1037516fc7f3Shx147065
1038516fc7f3Shx147065 p_section = p_config_file->section_head;
1039516fc7f3Shx147065
1040516fc7f3Shx147065 while (p_section != NULL) {
1041516fc7f3Shx147065 if ((p_section->section_id != NULL) &&
1042516fc7f3Shx147065 (strcmp(p_section->section_id, section_id) == 0))
1043516fc7f3Shx147065 return (p_section);
1044516fc7f3Shx147065 p_section = p_section->section_next;
1045516fc7f3Shx147065 }
1046516fc7f3Shx147065 return (NULL);
1047516fc7f3Shx147065 }
1048516fc7f3Shx147065
1049516fc7f3Shx147065 /*
1050516fc7f3Shx147065 * get_value: Get rid of "parameter=" from a "parameter=value", for example:
1051516fc7f3Shx147065 * when we read an line from file, we gets "essid=ap7-2", this function
1052516fc7f3Shx147065 * returns the pointer to string "ap7-2";
1053516fc7f3Shx147065 */
1054516fc7f3Shx147065
1055516fc7f3Shx147065 static const char *
get_value(const char * arg)1056516fc7f3Shx147065 get_value(const char *arg)
1057516fc7f3Shx147065 {
1058516fc7f3Shx147065 char *p;
1059516fc7f3Shx147065 assert(arg != NULL);
1060516fc7f3Shx147065
1061516fc7f3Shx147065 p = strchr(arg, '=');
1062516fc7f3Shx147065 PRTDBG(("get_value(\"%s\") = \"%s\"\n", arg, p + 1));
1063516fc7f3Shx147065 if (p != NULL)
1064516fc7f3Shx147065 return (p + 1);
1065516fc7f3Shx147065 else
1066516fc7f3Shx147065 return (NULL);
1067516fc7f3Shx147065 }
1068516fc7f3Shx147065
1069516fc7f3Shx147065 /*
1070516fc7f3Shx147065 * search /dev/wifi to see which interface is available
1071516fc7f3Shx147065 */
1072516fc7f3Shx147065 static boolean_t
search_interface(char * interface)1073516fc7f3Shx147065 search_interface(char *interface)
1074516fc7f3Shx147065 {
1075516fc7f3Shx147065 DIR *dirp;
1076516fc7f3Shx147065 struct dirent *dp;
1077516fc7f3Shx147065 char buf[256];
1078516fc7f3Shx147065 int fd;
1079516fc7f3Shx147065
1080516fc7f3Shx147065 PRTDBG(("search interface\n"));
1081516fc7f3Shx147065 assert(interface != NULL);
1082516fc7f3Shx147065
1083516fc7f3Shx147065 /*
1084516fc7f3Shx147065 * Try to return the first found wifi interface.
1085516fc7f3Shx147065 * If no wifi interface is available, return B_FALSE
1086516fc7f3Shx147065 */
1087516fc7f3Shx147065
1088516fc7f3Shx147065 if ((dirp = opendir("/dev/wifi")) == NULL) {
1089516fc7f3Shx147065 PRTDBG(("failed to open '/dev/wifi'\n"));
1090516fc7f3Shx147065 return (B_FALSE);
1091516fc7f3Shx147065 }
1092516fc7f3Shx147065 while ((dp = readdir(dirp)) != NULL) {
1093516fc7f3Shx147065 if (strcmp(dp->d_name, ".") == 0 ||
1094516fc7f3Shx147065 strcmp(dp->d_name, "..") == 0)
1095516fc7f3Shx147065 continue;
1096516fc7f3Shx147065 if (dp->d_name[strlen(dp->d_name) - 1] < '0' ||
1097516fc7f3Shx147065 dp->d_name[strlen(dp->d_name) - 1] > '9')
1098516fc7f3Shx147065 continue;
1099516fc7f3Shx147065 safe_snprintf(buf, sizeof (buf), "%s%s",
1100516fc7f3Shx147065 "/dev/wifi/", dp->d_name);
1101516fc7f3Shx147065 fd = open(buf, O_RDWR);
1102516fc7f3Shx147065 if (fd == -1) {
1103516fc7f3Shx147065 PRTDBG(("interface %s doesn't exist\n", dp->d_name));
1104516fc7f3Shx147065 continue;
1105516fc7f3Shx147065 } else {
1106516fc7f3Shx147065 PRTDBG(("interface %s is the first found interface\n",
1107516fc7f3Shx147065 dp->d_name));
1108516fc7f3Shx147065 (void) strlcpy(interface, buf, LIFNAMSIZ);
1109516fc7f3Shx147065 (void) close(fd);
1110516fc7f3Shx147065 (void) closedir(dirp);
1111516fc7f3Shx147065 return (B_TRUE);
1112516fc7f3Shx147065 }
1113516fc7f3Shx147065 }
1114516fc7f3Shx147065
1115516fc7f3Shx147065 PRTDBG(("failed to find available wireless interface\n"));
1116516fc7f3Shx147065 (void) closedir(dirp);
1117516fc7f3Shx147065 return (B_FALSE);
1118516fc7f3Shx147065
1119516fc7f3Shx147065 }
1120516fc7f3Shx147065 /*
1121516fc7f3Shx147065 * open_dev: Open the driver.
1122516fc7f3Shx147065 * if the 'devname' has format like 'ath0', we should add the path to that
1123516fc7f3Shx147065 * device(/dev/ath0) and open it; if the 'devname' has format like
1124516fc7f3Shx147065 * '/dev/wifi/ath0', we open it directly.
1125516fc7f3Shx147065 */
1126516fc7f3Shx147065 static int
open_dev(char * devname)1127516fc7f3Shx147065 open_dev(char *devname)
1128516fc7f3Shx147065 {
1129516fc7f3Shx147065 int fd;
1130516fc7f3Shx147065 int len;
1131516fc7f3Shx147065 char *pbuf = NULL;
1132516fc7f3Shx147065
1133516fc7f3Shx147065 PRTDBG(("open_dev(\"%s\")\n", devname));
1134516fc7f3Shx147065 assert(devname != NULL);
1135516fc7f3Shx147065 /*
1136516fc7f3Shx147065 * If the devname is got from the user input, we
1137516fc7f3Shx147065 * add '/dev/' to that relative devname. If it
1138516fc7f3Shx147065 * is got from the 'search interface', it is an
1139516fc7f3Shx147065 * absolute path.
1140516fc7f3Shx147065 */
1141516fc7f3Shx147065 if (strncmp(devname, "/dev/wifi/", strlen("/dev/wifi/")) == 0) {
1142516fc7f3Shx147065 pbuf = safe_strdup(devname);
1143516fc7f3Shx147065 } else {
1144516fc7f3Shx147065 len = strlen(devname) + strlen("/dev/") + 1;
1145516fc7f3Shx147065 pbuf = safe_malloc(len);
1146516fc7f3Shx147065 safe_snprintf(pbuf, len, "/dev/%s", devname);
1147516fc7f3Shx147065 }
1148516fc7f3Shx147065 fd = open(pbuf, O_RDWR);
1149516fc7f3Shx147065 free(pbuf);
1150516fc7f3Shx147065
1151516fc7f3Shx147065 if (fd == -1) {
1152516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to open '%s': %s"
1153516fc7f3Shx147065 "\n"), gExecName, devname, strerror(errno));
1154516fc7f3Shx147065 return (-1);
1155516fc7f3Shx147065 }
1156516fc7f3Shx147065 if (!isastream(fd)) {
1157516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: %s is "
1158516fc7f3Shx147065 "not a stream device\n"),
1159516fc7f3Shx147065 gExecName, devname);
1160516fc7f3Shx147065 (void) close(fd);
1161516fc7f3Shx147065 return (-1);
1162516fc7f3Shx147065 }
1163516fc7f3Shx147065 return (fd);
1164516fc7f3Shx147065 }
1165516fc7f3Shx147065 /*
1166516fc7f3Shx147065 * call_ioctl: Fill strioctl structure and issue an ioctl system call
1167516fc7f3Shx147065 */
1168516fc7f3Shx147065 static boolean_t
call_ioctl(int fd,int cmd,uint32_t params,uint32_t buf_len)1169516fc7f3Shx147065 call_ioctl(int fd, int cmd, uint32_t params, uint32_t buf_len)
1170516fc7f3Shx147065 {
1171516fc7f3Shx147065 struct strioctl stri;
1172516fc7f3Shx147065
1173516fc7f3Shx147065 PRTDBG(("call_ioctl_gs(%d, 0x%x, 0x%x, 0x%x)\n",
1174516fc7f3Shx147065 fd, cmd, params, buf_len));
1175516fc7f3Shx147065
1176516fc7f3Shx147065 switch (cmd) {
1177516fc7f3Shx147065 case WLAN_GET_PARAM:
1178516fc7f3Shx147065 (void) memset(gbuf, 0, MAX_BUF_LEN);
1179516fc7f3Shx147065 stri.ic_len = MAX_BUF_LEN;
1180516fc7f3Shx147065 break;
1181516fc7f3Shx147065 case WLAN_SET_PARAM:
1182516fc7f3Shx147065 gbuf->wldp_length = buf_len + WIFI_BUF_OFFSET;
1183516fc7f3Shx147065 stri.ic_len = gbuf->wldp_length;
1184516fc7f3Shx147065 break;
1185516fc7f3Shx147065 case WLAN_COMMAND:
1186516fc7f3Shx147065 gbuf->wldp_length = sizeof (wldp_t);
1187516fc7f3Shx147065 stri.ic_len = gbuf->wldp_length;
1188516fc7f3Shx147065 break;
1189516fc7f3Shx147065 default:
1190516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: ioctl : "
1191516fc7f3Shx147065 "unsupported ioctl command\n"), gExecName);
1192516fc7f3Shx147065 return (B_FALSE);
1193516fc7f3Shx147065 }
1194516fc7f3Shx147065 gbuf->wldp_type = NET_802_11;
1195516fc7f3Shx147065 gbuf->wldp_id = params;
1196516fc7f3Shx147065
1197516fc7f3Shx147065 stri.ic_cmd = cmd;
1198516fc7f3Shx147065 stri.ic_timout = 0;
1199516fc7f3Shx147065 stri.ic_dp = (char *)gbuf;
1200516fc7f3Shx147065
1201516fc7f3Shx147065 if (ioctl(fd, I_STR, &stri) == -1) {
1202516fc7f3Shx147065 gbuf->wldp_result = 0xffff;
1203516fc7f3Shx147065 return (B_FALSE);
1204516fc7f3Shx147065 }
1205516fc7f3Shx147065 if (cmd == WLAN_COMMAND) {
1206516fc7f3Shx147065 return (B_TRUE);
1207516fc7f3Shx147065 } else {
1208516fc7f3Shx147065 return (gbuf->wldp_result != WL_SUCCESS ?
1209516fc7f3Shx147065 B_FALSE:B_TRUE);
1210516fc7f3Shx147065 }
1211516fc7f3Shx147065 }
1212516fc7f3Shx147065
1213516fc7f3Shx147065 /*
1214516fc7f3Shx147065 * del_prefer: Delete an item from the {preferrence} list, the idea is
1215516fc7f3Shx147065 * simply free the ae_t element, and set ae_arg to NULL, then when archive
1216516fc7f3Shx147065 * the config_file_t struct to the file, it will be delete.
1217516fc7f3Shx147065 * The last flag is used to identify whether this function is invoked due to
1218516fc7f3Shx147065 * the 'removeprefer' subcommand or due to 'deleteprofile' subcommand.
1219516fc7f3Shx147065 */
1220516fc7f3Shx147065 static boolean_t
del_prefer(config_file_t * p_config_file,const char * prefer,boolean_t rflag)1221516fc7f3Shx147065 del_prefer(config_file_t *p_config_file, const char *prefer, boolean_t rflag)
1222516fc7f3Shx147065 {
1223516fc7f3Shx147065 section_t *p_section = NULL;
1224516fc7f3Shx147065 aelist_t *plist = NULL;
1225516fc7f3Shx147065 ae_t *pae = NULL;
1226516fc7f3Shx147065 int i = 0, position = 0;
1227516fc7f3Shx147065 int number;
1228516fc7f3Shx147065 ae_t *prm_ae = NULL;
1229516fc7f3Shx147065
1230516fc7f3Shx147065 PRTDBG(("del_prefer(0x%x, \"%s\")\n", p_config_file, prefer));
1231516fc7f3Shx147065 assert((prefer != NULL)&&(p_config_file != NULL));
1232516fc7f3Shx147065
1233516fc7f3Shx147065 p_section = find_section(p_config_file, WIFI_PREFER);
1234516fc7f3Shx147065 if (p_section != NULL)
1235516fc7f3Shx147065 plist = p_section->list;
1236516fc7f3Shx147065
1237516fc7f3Shx147065 if ((p_section == NULL) || (plist == NULL))
1238516fc7f3Shx147065 return (B_FALSE);
1239516fc7f3Shx147065
1240516fc7f3Shx147065 number = plist->ael_argc;
1241516fc7f3Shx147065 pae = plist->ael_head;
1242516fc7f3Shx147065 prm_ae = plist->ael_head;
1243516fc7f3Shx147065 while (pae != NULL) {
1244516fc7f3Shx147065 if (strcmp(prefer, pae->ae_arg) == 0) {
1245516fc7f3Shx147065 free(pae->ae_arg);
1246516fc7f3Shx147065 pae->ae_arg = NULL; /* mark */
1247516fc7f3Shx147065 if (!position) {
1248516fc7f3Shx147065 plist->ael_head = pae->ae_next;
1249516fc7f3Shx147065 if (pae->ae_next == NULL)
1250516fc7f3Shx147065 plist->ael_tail = NULL;
1251516fc7f3Shx147065 } else {
1252516fc7f3Shx147065 for (i = 0; i < position - 1; i++)
1253516fc7f3Shx147065 prm_ae = prm_ae->ae_next;
1254516fc7f3Shx147065 prm_ae->ae_next = pae->ae_next;
1255516fc7f3Shx147065 if (pae->ae_next == NULL)
1256516fc7f3Shx147065 plist->ael_tail = prm_ae;
1257516fc7f3Shx147065 }
1258516fc7f3Shx147065 free(pae);
1259516fc7f3Shx147065 pae = NULL;
1260516fc7f3Shx147065 plist->ael_argc--;
1261516fc7f3Shx147065 break;
1262516fc7f3Shx147065 }
1263516fc7f3Shx147065 position++;
1264516fc7f3Shx147065 pae = pae->ae_next;
1265516fc7f3Shx147065 }
1266516fc7f3Shx147065 if ((number == plist->ael_argc) && (rflag == B_TRUE)) {
1267516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: removeprefer : "
1268516fc7f3Shx147065 "no such profile: '%s' in the preference list\n"),
1269516fc7f3Shx147065 gExecName, prefer);
1270516fc7f3Shx147065 return (B_FALSE);
1271516fc7f3Shx147065 }
1272516fc7f3Shx147065 return (B_TRUE);
1273516fc7f3Shx147065 }
1274516fc7f3Shx147065
1275516fc7f3Shx147065 /*
1276516fc7f3Shx147065 * del_section: Delete an section from p_config_file, the idea is
1277516fc7f3Shx147065 * simply free the aelist_t struct and set it to NULL, when archiving
1278516fc7f3Shx147065 * config_file_t struct to the file, we will find section list is NULL,
1279516fc7f3Shx147065 * and will not write it to file, so it will be deleted.
1280516fc7f3Shx147065 */
1281516fc7f3Shx147065 static boolean_t
del_section(config_file_t * p_config_file,char * section_id)1282516fc7f3Shx147065 del_section(config_file_t *p_config_file, char *section_id)
1283516fc7f3Shx147065 {
1284516fc7f3Shx147065 section_t *p_section = NULL;
1285516fc7f3Shx147065 section_t *prm_section = NULL;
1286516fc7f3Shx147065 aelist_t *plist = NULL;
1287516fc7f3Shx147065 ae_t *pae = NULL;
1288516fc7f3Shx147065 int i = 0, position = 0;
1289516fc7f3Shx147065
1290516fc7f3Shx147065 PRTDBG(("del_section(0x%x, \"%s\")\n", p_config_file, section_id));
1291516fc7f3Shx147065 PRTDBG(("del_section: %d section(s) in config file\n",
1292516fc7f3Shx147065 p_config_file->section_argc));
1293516fc7f3Shx147065 assert((section_id != NULL)&&(p_config_file != NULL));
1294516fc7f3Shx147065
1295516fc7f3Shx147065 if (find_section(p_config_file, section_id) == NULL) {
1296516fc7f3Shx147065 return (B_FALSE);
1297516fc7f3Shx147065 }
1298516fc7f3Shx147065 p_section = p_config_file->section_head;
1299516fc7f3Shx147065 prm_section = p_config_file->section_head;
1300516fc7f3Shx147065 while (p_section != NULL) {
1301516fc7f3Shx147065 if (p_section->section_id != NULL) {
1302516fc7f3Shx147065 if (strcmp(p_section->section_id, section_id) == 0) {
1303516fc7f3Shx147065 plist = p_section->list;
1304516fc7f3Shx147065 pae = plist->ael_head;
1305516fc7f3Shx147065 while (pae != NULL) {
1306516fc7f3Shx147065 free(pae->ae_arg);
1307516fc7f3Shx147065 pae->ae_arg = NULL;
1308516fc7f3Shx147065 pae = pae->ae_next;
1309516fc7f3Shx147065 free(plist->ael_head);
1310516fc7f3Shx147065 plist->ael_head = pae;
1311516fc7f3Shx147065 }
1312516fc7f3Shx147065 free(plist);
1313516fc7f3Shx147065 p_section->list = NULL;
1314516fc7f3Shx147065 free(p_section->section_id);
1315516fc7f3Shx147065 p_section->section_id = NULL;
1316516fc7f3Shx147065
1317516fc7f3Shx147065 if (!position) {
1318516fc7f3Shx147065 p_config_file->section_head =
1319516fc7f3Shx147065 p_section->section_next;
1320516fc7f3Shx147065 if (p_section->section_next == NULL)
1321516fc7f3Shx147065 p_config_file->section_tail =
1322516fc7f3Shx147065 NULL;
1323516fc7f3Shx147065 } else {
1324516fc7f3Shx147065 for (i = 0; i < position - 1; i++) {
1325516fc7f3Shx147065 prm_section =
1326516fc7f3Shx147065 prm_section->section_next;
1327516fc7f3Shx147065 }
1328516fc7f3Shx147065 prm_section->section_next =
1329516fc7f3Shx147065 p_section->section_next;
1330516fc7f3Shx147065 if (p_section->section_next == NULL)
1331516fc7f3Shx147065 p_config_file->section_tail =
1332516fc7f3Shx147065 prm_section;
1333516fc7f3Shx147065 }
1334516fc7f3Shx147065 free(p_section);
1335516fc7f3Shx147065 p_config_file->section_argc--;
1336516fc7f3Shx147065 break;
1337516fc7f3Shx147065 }
1338516fc7f3Shx147065 position++;
1339516fc7f3Shx147065 }
1340516fc7f3Shx147065 p_section = p_section->section_next;
1341516fc7f3Shx147065 }
1342516fc7f3Shx147065 return (B_TRUE);
1343516fc7f3Shx147065 }
1344516fc7f3Shx147065
1345516fc7f3Shx147065 /*
1346516fc7f3Shx147065 * set_prefer: Reorder the preferrence list.
1347516fc7f3Shx147065 */
1348516fc7f3Shx147065 static boolean_t
set_prefer(config_file_t * p_config_file,const char * prefer,int rank)1349516fc7f3Shx147065 set_prefer(config_file_t *p_config_file, const char *prefer, int rank)
1350516fc7f3Shx147065 {
1351516fc7f3Shx147065 char *pbuf = NULL;
1352516fc7f3Shx147065 aelist_t *plist = NULL;
1353516fc7f3Shx147065 section_t *p_section = NULL;
1354516fc7f3Shx147065 ae_t *pae = NULL;
1355516fc7f3Shx147065 int i = 0, position = 0;
1356516fc7f3Shx147065 ae_t *pae_move = NULL;
1357516fc7f3Shx147065
1358516fc7f3Shx147065 assert(prefer != NULL);
1359516fc7f3Shx147065 PRTDBG(("set_prefer(0x%x, \"%s\", %d)\n", p_config_file, prefer, rank));
1360516fc7f3Shx147065
1361516fc7f3Shx147065 pbuf = append_pa(prefer);
1362516fc7f3Shx147065 if (find_section(p_config_file, pbuf) == NULL) {
1363516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: setprefer: "
1364516fc7f3Shx147065 "no such profile: '%s'\n"),
1365516fc7f3Shx147065 gExecName, prefer);
1366516fc7f3Shx147065 free(pbuf);
1367516fc7f3Shx147065 return (B_FALSE);
1368516fc7f3Shx147065 }
1369516fc7f3Shx147065 free(pbuf);
1370516fc7f3Shx147065
1371516fc7f3Shx147065 p_section = find_section(p_config_file, WIFI_PREFER);
1372516fc7f3Shx147065
1373516fc7f3Shx147065 if (p_section == NULL) {
1374516fc7f3Shx147065 plist = new_ael(PREFERENCE);
1375516fc7f3Shx147065 new_section(p_config_file, plist, WIFI_PREFER);
1376516fc7f3Shx147065 new_ae(plist, prefer);
1377516fc7f3Shx147065 return (B_TRUE);
1378516fc7f3Shx147065 } else {
1379516fc7f3Shx147065 plist = p_section->list;
1380516fc7f3Shx147065 }
1381516fc7f3Shx147065
1382516fc7f3Shx147065 pae = plist->ael_head;
1383516fc7f3Shx147065 pae_move = plist->ael_head;
1384516fc7f3Shx147065 while (pae != NULL) {
1385516fc7f3Shx147065 if (strcmp(prefer, pae->ae_arg) == 0) {
1386516fc7f3Shx147065 free(pae->ae_arg);
1387516fc7f3Shx147065 pae->ae_arg = NULL;
1388516fc7f3Shx147065 if (!position) {
1389516fc7f3Shx147065 plist->ael_head = pae->ae_next;
1390516fc7f3Shx147065 if (pae->ae_next == NULL)
1391516fc7f3Shx147065 plist->ael_tail = NULL;
1392516fc7f3Shx147065 } else {
1393516fc7f3Shx147065 for (i = 0; i < position - 1; i++)
1394516fc7f3Shx147065 pae_move = pae_move->ae_next;
1395516fc7f3Shx147065 pae_move->ae_next = pae->ae_next;
1396516fc7f3Shx147065 if (pae->ae_next == NULL)
1397516fc7f3Shx147065 plist->ael_tail = pae_move;
1398516fc7f3Shx147065 }
1399516fc7f3Shx147065 free(pae);
1400516fc7f3Shx147065 plist->ael_argc--;
1401516fc7f3Shx147065 break;
1402516fc7f3Shx147065 }
1403516fc7f3Shx147065 position++;
1404516fc7f3Shx147065 pae = pae->ae_next;
1405516fc7f3Shx147065 }
1406516fc7f3Shx147065 PRTDBG(("set_prefer: %d Profiles in prefer list\n", plist->ael_argc));
1407516fc7f3Shx147065 if (rank > plist->ael_argc) {
1408516fc7f3Shx147065 new_ae(plist, prefer);
1409516fc7f3Shx147065 } else if (rank <= 1) {
1410516fc7f3Shx147065 pae = safe_calloc(sizeof (ae_t), 1);
1411516fc7f3Shx147065 pae->ae_arg = safe_strdup(prefer);
1412516fc7f3Shx147065 pae->ae_next = plist->ael_head;
1413516fc7f3Shx147065 plist->ael_head = pae;
1414516fc7f3Shx147065 plist->ael_argc++;
1415516fc7f3Shx147065 } else {
1416516fc7f3Shx147065 pae_move = plist->ael_head;
1417516fc7f3Shx147065 for (i = 1; i < rank-1; i++) {
1418516fc7f3Shx147065 pae_move = pae_move->ae_next;
1419516fc7f3Shx147065 }
1420516fc7f3Shx147065 pae = safe_calloc(sizeof (ae_t), 1);
1421516fc7f3Shx147065 pae->ae_arg = safe_strdup(prefer);
1422516fc7f3Shx147065 pae->ae_next = pae_move->ae_next;
1423516fc7f3Shx147065 pae_move->ae_next = pae;
1424516fc7f3Shx147065 plist->ael_argc++;
1425516fc7f3Shx147065 }
1426516fc7f3Shx147065 /*
1427516fc7f3Shx147065 * If number of prefer list items is larger than the MAX_PREFERENCE_NUM
1428516fc7f3Shx147065 * delete those items whose No is larger than MAX_PREFERENCE_NUM.
1429516fc7f3Shx147065 */
1430516fc7f3Shx147065 if (plist->ael_argc > MAX_PREFERENCE_NUM) {
1431516fc7f3Shx147065 pae = plist->ael_head;
1432516fc7f3Shx147065 while (pae->ae_next != plist->ael_tail)
1433516fc7f3Shx147065 pae = pae->ae_next;
1434516fc7f3Shx147065 free(plist->ael_tail->ae_arg);
1435516fc7f3Shx147065 plist->ael_tail->ae_arg = NULL;
1436516fc7f3Shx147065 free(plist->ael_tail);
1437516fc7f3Shx147065 plist->ael_tail = pae;
1438516fc7f3Shx147065 plist->ael_tail->ae_next = NULL;
1439516fc7f3Shx147065 plist->ael_argc--;
1440516fc7f3Shx147065 }
1441516fc7f3Shx147065 PRTDBG(("set_prefer: %d Profiles in prefer list\n", plist->ael_argc));
1442516fc7f3Shx147065 return (B_TRUE);
1443516fc7f3Shx147065 }
1444516fc7f3Shx147065 /*
1445516fc7f3Shx147065 * add_to_history: Save the scanlist argv into history section
1446516fc7f3Shx147065 */
1447516fc7f3Shx147065 static void
add_to_history(config_file_t * p_config_file,int argc,char ** argv)1448516fc7f3Shx147065 add_to_history(config_file_t *p_config_file, int argc, char **argv)
1449516fc7f3Shx147065 {
1450516fc7f3Shx147065 int i = 0, j = 0, pos = 0;
1451516fc7f3Shx147065 aelist_t *plist = NULL;
1452516fc7f3Shx147065 section_t *p_section = NULL;
1453516fc7f3Shx147065 ae_t *pae = NULL;
1454516fc7f3Shx147065 ae_t *pae_m = NULL;
1455516fc7f3Shx147065 char item[256];
1456516fc7f3Shx147065 time_t cltime;
1457516fc7f3Shx147065
1458516fc7f3Shx147065 PRTDBG(("add_to_history(0x%x, %d, 0x%x)\n", p_config_file, argc, argv));
1459516fc7f3Shx147065 assert(p_config_file != NULL);
1460516fc7f3Shx147065
1461516fc7f3Shx147065 p_section = find_section(p_config_file, WIFI_HISTORY);
1462516fc7f3Shx147065
1463516fc7f3Shx147065 if (p_section == NULL) {
1464516fc7f3Shx147065 plist = new_ael(HISTORY);
1465516fc7f3Shx147065 new_section(p_config_file, plist, WIFI_HISTORY);
1466516fc7f3Shx147065 } else {
1467516fc7f3Shx147065 plist = p_section->list;
1468516fc7f3Shx147065 }
1469516fc7f3Shx147065
1470516fc7f3Shx147065 if (plist != NULL) {
1471516fc7f3Shx147065 for (i = 0; i < argc; i++) {
1472516fc7f3Shx147065 if (!strlen(argv[i]))
1473516fc7f3Shx147065 continue;
1474516fc7f3Shx147065 pos = 0;
1475516fc7f3Shx147065 pae = plist->ael_head;
1476516fc7f3Shx147065 pae_m = plist->ael_head;
1477516fc7f3Shx147065 /*
1478516fc7f3Shx147065 * add time stamp to the history record
1479516fc7f3Shx147065 */
1480516fc7f3Shx147065 cltime = time(&cltime);
1481516fc7f3Shx147065 (void) snprintf(item, sizeof (item), "%s%c%ld",
1482516fc7f3Shx147065 argv[i], ',', cltime);
1483516fc7f3Shx147065 while (pae != NULL) {
1484516fc7f3Shx147065 if (strncmp(item, pae->ae_arg,
1485516fc7f3Shx147065 strlen(argv[i])) == 0) {
1486516fc7f3Shx147065 free(pae->ae_arg);
1487516fc7f3Shx147065 pae->ae_arg = NULL;
1488516fc7f3Shx147065 if (!pos) {
1489516fc7f3Shx147065 plist->ael_head = pae->ae_next;
1490516fc7f3Shx147065 if (pae->ae_next == NULL)
1491516fc7f3Shx147065 plist->ael_tail = NULL;
1492516fc7f3Shx147065 } else {
1493516fc7f3Shx147065 for (j = 0; j < pos - 1; j++)
1494516fc7f3Shx147065 pae_m = pae_m->ae_next;
1495516fc7f3Shx147065 pae_m->ae_next = pae->ae_next;
1496516fc7f3Shx147065 if (pae->ae_next == NULL)
1497516fc7f3Shx147065 plist->ael_tail = pae_m;
1498516fc7f3Shx147065 }
1499516fc7f3Shx147065 free(pae);
1500516fc7f3Shx147065 plist->ael_argc--;
1501516fc7f3Shx147065 break;
1502516fc7f3Shx147065 }
1503516fc7f3Shx147065 pos++;
1504516fc7f3Shx147065 pae = pae->ae_next;
1505516fc7f3Shx147065 }
1506516fc7f3Shx147065 new_ae(plist, item);
1507516fc7f3Shx147065 }
1508516fc7f3Shx147065
1509516fc7f3Shx147065 if (plist->ael_argc > MAX_HISTORY_NUM) {
1510516fc7f3Shx147065 for (i = 0; i < plist->ael_argc - MAX_HISTORY_NUM;
1511516fc7f3Shx147065 i++) {
1512516fc7f3Shx147065 pae = plist->ael_head;
1513516fc7f3Shx147065 free(pae->ae_arg);
1514516fc7f3Shx147065 plist->ael_head = pae->ae_next;
1515516fc7f3Shx147065 free(pae);
1516516fc7f3Shx147065 }
1517516fc7f3Shx147065 plist->ael_argc = MAX_HISTORY_NUM;
1518516fc7f3Shx147065 }
1519516fc7f3Shx147065 }
1520516fc7f3Shx147065 }
1521516fc7f3Shx147065
1522516fc7f3Shx147065 static void
do_print_usage()1523516fc7f3Shx147065 do_print_usage()
1524516fc7f3Shx147065 {
1525516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1526516fc7f3Shx147065 " autoconf [wait={n|forever}]\n"), gExecName);
1527516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1528516fc7f3Shx147065 " connect profile [wait={n|forever}]\n"), gExecName);
1529516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1530516fc7f3Shx147065 " connect essid [wait={n|forever}]\n"), gExecName);
1531516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1532516fc7f3Shx147065 " disconnect\n"), gExecName);
1533516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1534516fc7f3Shx147065 " getparam [parameter [...]]\n"), gExecName);
1535516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1536516fc7f3Shx147065 " setparam [parameter=value [...]]\n"), gExecName);
1537516fc7f3Shx147065 (void) fprintf(stderr, gettext(
1538516fc7f3Shx147065 "\tparameters:\n"
1539516fc7f3Shx147065 "\t\tbssid\t\t - read only: 6 byte mac address of "
1540516fc7f3Shx147065 "base station\n"
1541516fc7f3Shx147065 "\t\tessid\t\t - name of the network, a string of up "
1542516fc7f3Shx147065 "to 32 chars\n"
1543516fc7f3Shx147065 "\t\tbsstype\t\t - bss(ap, infrastructure), ibss(ad-hoc)"
1544516fc7f3Shx147065 " or auto\n"
1545516fc7f3Shx147065 "\t\tcreateibss\t - flag to identify whether a ibss is to be\n"
1546516fc7f3Shx147065 "\t\t\t\t created when the network to connect is\n"
1547516fc7f3Shx147065 "\t\t\t\t not available, yes or no\n"
1548516fc7f3Shx147065 "\t\tchannel\t\t - channel(used only when creating an ibss)\n"
1549516fc7f3Shx147065 "\t\t\t\t valid value:\n"
1550516fc7f3Shx147065 "\t\t\t\t\t 802.11a: 0-99\n"
1551516fc7f3Shx147065 "\t\t\t\t\t 802.11b: 1-14\n"
1552516fc7f3Shx147065 "\t\t\t\t\t 802.11g: 1-14\n"
1553516fc7f3Shx147065 "\t\trates\t\t - set of rates, seperated by ',' valid rates:\n"
1554516fc7f3Shx147065 "\t\t\t\t 1,2,5.5,6,9,11,12,18,22,24,33,36,48 and 54\n"
1555516fc7f3Shx147065 "\t\tpowermode\t - off, mps or fast\n"
1556516fc7f3Shx147065 "\t\tauthmode\t - opensystem or shared_key\n"
1557516fc7f3Shx147065 "\t\tencryption\t - none or wep\n"
1558516fc7f3Shx147065 "\t\twepkey|1-4\t - write only:\n"
1559516fc7f3Shx147065 "\t\t\t\t 5 chars or 10 hex digits for 40bit wepkey;\n"
1560516fc7f3Shx147065 "\t\t\t\t 13 chars or 26 hex digits for 128bit wepkey\n"
1561516fc7f3Shx147065 "\t\twepkeyindex\t - an integer within the range 1-4\n"
1562516fc7f3Shx147065 "\t\tsignal\t\t - read only: signal strength from 0 to 15\n"
1563516fc7f3Shx147065 "\t\tradio\t\t - on or off\n"));
1564516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1565516fc7f3Shx147065 " restoredef\n"), gExecName);
1566516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1567516fc7f3Shx147065 " scan\n"), gExecName);
1568516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1569516fc7f3Shx147065 " showstatus\n"), gExecName);
1570516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1571516fc7f3Shx147065 " setwepkey 1|2|3|4\n"), gExecName);
1572516fc7f3Shx147065
1573516fc7f3Shx147065 (void) fprintf(stderr, "\n");
1574516fc7f3Shx147065
1575516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1576516fc7f3Shx147065 " createprofile profile parameter=value [...]\n"), gExecName);
1577516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1578516fc7f3Shx147065 " deleteprofile profile1 [profile2 [...]]\n"), gExecName);
1579516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1580516fc7f3Shx147065 " showprofile profile1 [profile2 [...]]\n"), gExecName);
1581516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1582516fc7f3Shx147065 " setprofilewepkey profile 1|2|3|4\n"), gExecName);
1583516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1584516fc7f3Shx147065 " getprofileparam profile [parameter [...]]\n"), gExecName);
1585516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1586516fc7f3Shx147065 " setprofileparam profile [parameter=value [...]]\n"), gExecName);
1587516fc7f3Shx147065
1588516fc7f3Shx147065 (void) fprintf(stderr, "\n");
1589516fc7f3Shx147065
1590516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1591516fc7f3Shx147065 " history\n"), gExecName);
1592516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1593516fc7f3Shx147065 " listprefer\n"), gExecName);
1594516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1595516fc7f3Shx147065 " removeprefer profile\n"), gExecName);
1596516fc7f3Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1597516fc7f3Shx147065 " setprefer profile [n]\n"), gExecName);
1598516fc7f3Shx147065 }
1599516fc7f3Shx147065
1600516fc7f3Shx147065 /*
1601516fc7f3Shx147065 * do_print_support_params: Query interface which cmd is supported
1602516fc7f3Shx147065 */
1603516fc7f3Shx147065 static boolean_t
do_print_support_params(int fd)1604516fc7f3Shx147065 do_print_support_params(int fd)
1605516fc7f3Shx147065 {
1606516fc7f3Shx147065 int i = 0, n = 0;
1607516fc7f3Shx147065
1608516fc7f3Shx147065 PRTDBG(("do_print_support_params(\"%d\")\n", fd));
1609516fc7f3Shx147065 assert(fd != -1);
1610516fc7f3Shx147065
1611516fc7f3Shx147065 (void) printf(gettext("\t parameter\tproperty\n"));
1612516fc7f3Shx147065 for (i = 0; i < N_GS_FUNC; i++) {
1613516fc7f3Shx147065 gbuf->wldp_result = WL_LACK_FEATURE;
1614516fc7f3Shx147065 if ((do_gs_func[i].p_do_get_func != NULL) &&
1615516fc7f3Shx147065 (do_gs_func[i].p_do_get_func(fd) != B_TRUE)) {
1616516fc7f3Shx147065 continue;
1617516fc7f3Shx147065 }
1618516fc7f3Shx147065 if (gbuf->wldp_result == WL_SUCCESS) {
1619516fc7f3Shx147065 (void) printf("\t%11s", do_gs_func[i].cmd);
1620516fc7f3Shx147065 if (do_gs_func[i].rw == RO)
1621516fc7f3Shx147065 (void) printf(gettext("\tread only\n"));
1622516fc7f3Shx147065 else
1623516fc7f3Shx147065 (void) printf(gettext("\tread/write\n"));
1624516fc7f3Shx147065 n++;
1625516fc7f3Shx147065 }
1626516fc7f3Shx147065 }
1627516fc7f3Shx147065
1628516fc7f3Shx147065 return (n ? B_TRUE : B_FALSE);
1629516fc7f3Shx147065 }
1630516fc7f3Shx147065
1631516fc7f3Shx147065 /*
1632516fc7f3Shx147065 * check_authority: Check if command is permitted.
1633516fc7f3Shx147065 */
1634516fc7f3Shx147065 static boolean_t
check_authority(wifi_auth_t type)1635516fc7f3Shx147065 check_authority(wifi_auth_t type)
1636516fc7f3Shx147065 {
1637516fc7f3Shx147065 struct passwd *pw = NULL;
1638516fc7f3Shx147065
1639516fc7f3Shx147065 PRTDBG(("check_authority()\n"));
1640516fc7f3Shx147065
1641516fc7f3Shx147065 pw = getpwuid(getuid());
1642516fc7f3Shx147065 if (pw == NULL)
1643516fc7f3Shx147065 return (B_FALSE);
1644516fc7f3Shx147065 if (chkauthattr(p_auth_string[type], pw->pw_name) == 0) {
1645516fc7f3Shx147065 if (type == AUTH_WEP)
1646516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
1647516fc7f3Shx147065 "privilege '%s' is required for setting "
1648516fc7f3Shx147065 "wepkey.\n"), gExecName, WIFI_WEP_AUTH);
1649516fc7f3Shx147065 else
1650516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
1651516fc7f3Shx147065 "privilege '%s' is required.\n"),
1652516fc7f3Shx147065 gExecName, WIFI_CONFIG_AUTH);
1653516fc7f3Shx147065 return (B_FALSE);
1654516fc7f3Shx147065 } else {
1655516fc7f3Shx147065 return (B_TRUE);
1656516fc7f3Shx147065 }
1657516fc7f3Shx147065 }
1658516fc7f3Shx147065
1659516fc7f3Shx147065 /*
1660516fc7f3Shx147065 * construct the 'history' and 'scan' output format
1661516fc7f3Shx147065 * memory allocated. need to free after the function is invoked.
1662516fc7f3Shx147065 */
1663516fc7f3Shx147065 static char *
construct_format(uint32_t nt)1664516fc7f3Shx147065 construct_format(uint32_t nt)
1665516fc7f3Shx147065 {
1666516fc7f3Shx147065 char *format;
1667516fc7f3Shx147065 int len = 0, i;
1668516fc7f3Shx147065
1669516fc7f3Shx147065 #define FORMAT_LEN 256
1670516fc7f3Shx147065 assert((nt >= 1) && (nt <= 4));
1671516fc7f3Shx147065 format = safe_malloc(FORMAT_LEN);
1672516fc7f3Shx147065
1673516fc7f3Shx147065 for (i = 0; i < nt; i++)
1674516fc7f3Shx147065 len += snprintf(format + len, FORMAT_LEN - len, "\t");
1675516fc7f3Shx147065 if ((len <= 0) || (len > FORMAT_LEN - 1)) {
1676516fc7f3Shx147065 return ("\t\t\t\t");
1677516fc7f3Shx147065 }
1678516fc7f3Shx147065 return (format);
1679516fc7f3Shx147065 }
1680516fc7f3Shx147065
1681516fc7f3Shx147065 /*
1682516fc7f3Shx147065 * find the essid of the named profile.
1683516fc7f3Shx147065 * gp_config_file is golable, so the return is gloable too.
1684516fc7f3Shx147065 */
1685516fc7f3Shx147065 static const char *
essid_of_profile(const char * profile)1686516fc7f3Shx147065 essid_of_profile(const char *profile)
1687516fc7f3Shx147065 {
1688516fc7f3Shx147065 section_t *p_section = NULL;
1689516fc7f3Shx147065 aelist_t *plist = NULL;
1690516fc7f3Shx147065 ae_t *pae = NULL;
1691516fc7f3Shx147065 char *pbuf;
1692516fc7f3Shx147065
1693516fc7f3Shx147065 PRTDBG(("essid_of_profile: profile = %s\n", profile));
1694516fc7f3Shx147065 pbuf = append_pa(profile);
1695516fc7f3Shx147065 p_section = find_section(gp_config_file, pbuf);
1696516fc7f3Shx147065 free(pbuf);
1697516fc7f3Shx147065
1698516fc7f3Shx147065 if (p_section == NULL) {
1699516fc7f3Shx147065 return (NULL);
1700516fc7f3Shx147065 } else {
1701516fc7f3Shx147065 plist = p_section->list;
1702516fc7f3Shx147065 }
1703516fc7f3Shx147065 pae = plist->ael_head;
1704516fc7f3Shx147065 while (pae != NULL) {
1705516fc7f3Shx147065 if (strncmp(pae->ae_arg, "essid=", strlen("essid=")) == 0) {
1706516fc7f3Shx147065 PRTDBG(("essid_of_profile: essid = %s\n",
1707516fc7f3Shx147065 pae->ae_arg));
1708516fc7f3Shx147065 return (get_value(pae->ae_arg));
1709516fc7f3Shx147065 }
1710516fc7f3Shx147065 pae = pae->ae_next;
1711516fc7f3Shx147065 }
1712516fc7f3Shx147065 return (NULL);
1713516fc7f3Shx147065 }
1714516fc7f3Shx147065
1715516fc7f3Shx147065 /*
1716516fc7f3Shx147065 * If we don't know which profile is our favorate in 'autoconf',
1717516fc7f3Shx147065 * we select the wifi network based on the following heuristic
1718516fc7f3Shx147065 * 1. the network without wep.
1719516fc7f3Shx147065 * 2. the network with the strongst signal.
1720516fc7f3Shx147065 * 3. the network with the faster speed(not implemented since signal affects
1721516fc7f3Shx147065 * the speed in some degree).
1722516fc7f3Shx147065 */
1723516fc7f3Shx147065 static void
heuristic_load(int fd,uint32_t ess_num,wl_ess_conf_t ** p_ess_conf)1724516fc7f3Shx147065 heuristic_load(int fd, uint32_t ess_num, wl_ess_conf_t **p_ess_conf)
1725516fc7f3Shx147065 {
1726516fc7f3Shx147065 int i = 0;
1727516fc7f3Shx147065 char *flag = NULL;
1728516fc7f3Shx147065 int have_nowep_wlan = 0;
1729516fc7f3Shx147065 wl_rssi_t maxsignal = 0;
1730516fc7f3Shx147065 char essid[34];
1731516fc7f3Shx147065 int timeout = LOADPROFILE_TIMEOUT;
1732516fc7f3Shx147065
1733516fc7f3Shx147065 PRTDBG(("heuristic_load: enter\n"));
1734516fc7f3Shx147065 (void) call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0);
1735516fc7f3Shx147065 flag = calloc(sizeof (char), ess_num);
1736516fc7f3Shx147065 for (i = 0; i < ess_num; i++) { /* extract none-wep network */
1737516fc7f3Shx147065 if (p_ess_conf[i]->wl_ess_conf_wepenabled == B_FALSE) {
1738516fc7f3Shx147065 flag[i] = 1;
1739516fc7f3Shx147065 have_nowep_wlan = 1;
1740516fc7f3Shx147065 }
1741516fc7f3Shx147065 }
1742516fc7f3Shx147065 /*
1743516fc7f3Shx147065 * if all the wlans are weped, we select the one with strongest signal
1744516fc7f3Shx147065 * in all of them, otherwise we just select in the none weped ones.
1745516fc7f3Shx147065 */
1746516fc7f3Shx147065 if (!have_nowep_wlan)
1747516fc7f3Shx147065 (void) memset(flag, 1, ess_num);
1748516fc7f3Shx147065 for (i = 0; i < ess_num; i++) { /* extract the strongest signal ones */
1749516fc7f3Shx147065 if (flag[i] == 1) {
1750516fc7f3Shx147065 if (p_ess_conf[i]->wl_ess_conf_sl > maxsignal) {
1751516fc7f3Shx147065 maxsignal = p_ess_conf[i]->wl_ess_conf_sl;
1752516fc7f3Shx147065 (void) memset(flag, 0, i);
1753516fc7f3Shx147065 } else if (p_ess_conf[i]->wl_ess_conf_sl == maxsignal)
1754516fc7f3Shx147065 continue;
1755516fc7f3Shx147065 else
1756516fc7f3Shx147065 flag[i] = 0;
1757516fc7f3Shx147065 }
1758516fc7f3Shx147065 }
1759516fc7f3Shx147065 for (i = 0; i < ess_num; i++) {
1760516fc7f3Shx147065 if (flag[i] == 1)
1761516fc7f3Shx147065 break;
1762516fc7f3Shx147065 }
1763516fc7f3Shx147065 free(flag);
1764516fc7f3Shx147065 PRTDBG(("heuristic_load: %s is selected\n",
1765516fc7f3Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid));
1766516fc7f3Shx147065 /* select one in all the networks which meet the preceding stardands */
1767516fc7f3Shx147065 if (i == ess_num)
1768516fc7f3Shx147065 (void) do_set_essid(fd, "");
1769516fc7f3Shx147065 else
1770516fc7f3Shx147065 (void) do_set_essid(fd,
1771516fc7f3Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid);
1772516fc7f3Shx147065
1773516fc7f3Shx147065 if ((ess_num == 0) || (do_get_essid(fd) == B_FALSE)) {
1774516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: autoconf:"
1775516fc7f3Shx147065 " failed to connect to any essid\n"),
1776516fc7f3Shx147065 gExecName);
1777516fc7f3Shx147065 exit(WIFI_MINOR_ERR);
1778516fc7f3Shx147065 }
1779516fc7f3Shx147065 (void) strlcpy(essid, ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid,
1780516fc7f3Shx147065 sizeof (essid));
1781516fc7f3Shx147065 (void) printf(gettext("%s: autoconf: essid '%s' is selected%s\n"),
1782516fc7f3Shx147065 gExecName, essid,
1783516fc7f3Shx147065 have_nowep_wlan ? "" : ": this is a WEPed "
1784516fc7f3Shx147065 "access point");
1785516fc7f3Shx147065
1786516fc7f3Shx147065 if (!have_nowep_wlan)
1787516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
1788516fc7f3Shx147065
1789516fc7f3Shx147065 while (timeout > 0) {
1790516fc7f3Shx147065 if ((do_get_linkstatus(fd) == B_TRUE) &&
1791516fc7f3Shx147065 (*(wl_linkstatus_t *)(gbuf->wldp_buf) == WL_CONNECTED)) {
1792516fc7f3Shx147065 (void) printf(gettext("%s: connecting to "
1793516fc7f3Shx147065 "essid '%s'\n"), gExecName, essid);
1794516fc7f3Shx147065 return;
1795516fc7f3Shx147065 }
1796516fc7f3Shx147065 (void) sleep(1);
1797516fc7f3Shx147065 timeout--;
1798516fc7f3Shx147065 }
1799516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to connect to "
1800516fc7f3Shx147065 "essid '%s'\n"), gExecName, essid);
1801516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
1802516fc7f3Shx147065 }
1803516fc7f3Shx147065
1804516fc7f3Shx147065 /*
1805516fc7f3Shx147065 * Called in autoconf and startconf to find which 'profile' is selected.
1806516fc7f3Shx147065 * The process is: check profile names in the prefer list item by item,
1807516fc7f3Shx147065 * if the essid of the profile is in the scan list, then it is the wanted.
1808516fc7f3Shx147065 * readonly: 1 for startconf
1809516fc7f3Shx147065 * 0 for autoconf
1810516fc7f3Shx147065 * for autoconf, the scan result will be recorded in the history list.
1811516fc7f3Shx147065 */
1812516fc7f3Shx147065 static char *
select_profile(int fd,int readonly,int timeout)1813516fc7f3Shx147065 select_profile(int fd, int readonly, int timeout)
1814516fc7f3Shx147065 {
1815516fc7f3Shx147065 uint32_t ess_num = 0;
1816516fc7f3Shx147065 int nprefer = 1;
1817516fc7f3Shx147065 char **ess_argv;
1818516fc7f3Shx147065 char **hisess_argv;
1819516fc7f3Shx147065 wl_ess_conf_t **p_ess_conf;
1820516fc7f3Shx147065 section_t *p_section = NULL;
1821516fc7f3Shx147065 aelist_t *plist = NULL;
1822516fc7f3Shx147065 ae_t *pae = NULL;
1823516fc7f3Shx147065 int i;
1824516fc7f3Shx147065 const char *parg;
1825516fc7f3Shx147065 char *selected = NULL;
1826516fc7f3Shx147065 boolean_t flag = B_FALSE;
1827516fc7f3Shx147065
1828516fc7f3Shx147065 if ((call_ioctl(fd, WLAN_COMMAND, WL_SCAN, 0) == B_FALSE) ||
1829516fc7f3Shx147065 (do_get_wlanlist(fd) == B_FALSE)) {
1830516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
1831516fc7f3Shx147065 "autoconf : failed to scan\n"), gExecName);
1832516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
1833516fc7f3Shx147065 }
1834516fc7f3Shx147065 ess_num = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num;
1835516fc7f3Shx147065 ess_argv = safe_calloc(sizeof (char *), ess_num);
1836516fc7f3Shx147065 hisess_argv = safe_calloc(sizeof (char *), ess_num);
1837516fc7f3Shx147065 p_ess_conf = safe_calloc(sizeof (wl_ess_list_t *), ess_num);
1838516fc7f3Shx147065 for (i = 0; i < ess_num; i++) {
1839516fc7f3Shx147065 p_ess_conf[i] = ((wl_ess_list_t *)gbuf->wldp_buf)
1840516fc7f3Shx147065 ->wl_ess_list_ess + i;
1841516fc7f3Shx147065 ess_argv[i] = safe_malloc(MAX_SCANBUF_LEN);
1842516fc7f3Shx147065 if (readonly == 0) {
1843516fc7f3Shx147065 hisess_argv[i] = safe_malloc(MAX_SCANBUF_LEN);
1844516fc7f3Shx147065 (void) snprintf(hisess_argv[i], MAX_SCANBUF_LEN,
1845516fc7f3Shx147065 "%s%c%02x:%02x:%02x:%02x:%02x:%02x%c%s",
1846516fc7f3Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid,
1847516fc7f3Shx147065 ',',
1848516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[0]),
1849516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[1]),
1850516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[2]),
1851516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[3]),
1852516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[4]),
1853516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[5]), ',',
1854516fc7f3Shx147065 (p_ess_conf[i]->wl_ess_conf_wepenabled == B_TRUE
1855516fc7f3Shx147065 ? "wep":"none"));
1856516fc7f3Shx147065 }
1857516fc7f3Shx147065 (void) snprintf(ess_argv[i], MAX_SCANBUF_LEN, "%s",
1858516fc7f3Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid);
1859516fc7f3Shx147065 }
1860516fc7f3Shx147065 if (readonly == 0) {
1861516fc7f3Shx147065 add_to_history(gp_config_file, ess_num, hisess_argv);
1862516fc7f3Shx147065 for (i = 0; i < ess_num; i++) {
1863516fc7f3Shx147065 free(hisess_argv[i]);
1864516fc7f3Shx147065 }
1865516fc7f3Shx147065 free(hisess_argv);
1866516fc7f3Shx147065 }
1867516fc7f3Shx147065
1868516fc7f3Shx147065 p_section = find_section(gp_config_file, WIFI_PREFER);
1869516fc7f3Shx147065 if (p_section == NULL) {
1870516fc7f3Shx147065 if (ess_num > 0) {
1871516fc7f3Shx147065 heuristic_load(fd, ess_num, p_ess_conf);
1872516fc7f3Shx147065 exit(WIFI_EXIT_DEF);
1873516fc7f3Shx147065 }
1874516fc7f3Shx147065 goto done;
1875516fc7f3Shx147065 }
1876516fc7f3Shx147065 plist = p_section->list;
1877516fc7f3Shx147065 assert(plist != NULL);
1878516fc7f3Shx147065 if (plist != NULL) {
1879516fc7f3Shx147065 nprefer = plist->ael_argc;
1880516fc7f3Shx147065 if (nprefer == 0) {
1881516fc7f3Shx147065 if (ess_num > 0) {
1882516fc7f3Shx147065 heuristic_load(fd, ess_num, p_ess_conf);
1883516fc7f3Shx147065 exit(WIFI_EXIT_DEF);
1884516fc7f3Shx147065 }
1885516fc7f3Shx147065 goto done;
1886516fc7f3Shx147065 }
1887516fc7f3Shx147065 }
1888516fc7f3Shx147065 pae = plist->ael_head;
1889516fc7f3Shx147065 while ((pae != NULL) && (flag != B_TRUE)) {
1890516fc7f3Shx147065 parg = essid_of_profile(pae->ae_arg);
1891516fc7f3Shx147065 if (parg != NULL) {
1892516fc7f3Shx147065 for (i = 0; i < ess_num; i++) {
1893516fc7f3Shx147065 if (strcmp(parg, ess_argv[i]) == 0) {
1894516fc7f3Shx147065 selected = pae->ae_arg;
1895516fc7f3Shx147065 flag = B_TRUE;
1896516fc7f3Shx147065 break;
1897516fc7f3Shx147065 }
1898516fc7f3Shx147065 }
1899516fc7f3Shx147065 }
1900516fc7f3Shx147065 pae = pae->ae_next;
1901516fc7f3Shx147065 }
1902516fc7f3Shx147065 done:
1903516fc7f3Shx147065 if ((selected == NULL) && (timeout == 0)) {
1904516fc7f3Shx147065 heuristic_load(fd, ess_num, p_ess_conf);
1905516fc7f3Shx147065 }
1906516fc7f3Shx147065 for (i = 0; i < ess_num; i++) {
1907516fc7f3Shx147065 free(ess_argv[i]);
1908516fc7f3Shx147065 }
1909516fc7f3Shx147065 free(ess_argv);
1910516fc7f3Shx147065 free(p_ess_conf);
1911516fc7f3Shx147065 return (selected);
1912516fc7f3Shx147065 }
1913516fc7f3Shx147065
1914516fc7f3Shx147065 static boolean_t
is_waittime_valid(char * pbuf)1915516fc7f3Shx147065 is_waittime_valid(char *pbuf)
1916516fc7f3Shx147065 {
1917516fc7f3Shx147065 int i;
1918516fc7f3Shx147065
1919516fc7f3Shx147065 i = atoi(pbuf);
1920516fc7f3Shx147065 if (i == -1)
1921516fc7f3Shx147065 return (B_TRUE);
1922516fc7f3Shx147065 for (i = 0; i < strlen(pbuf); i++) {
1923516fc7f3Shx147065 if (isdigit(pbuf[i]) == 0) {
1924516fc7f3Shx147065 return (B_FALSE);
1925516fc7f3Shx147065 }
1926516fc7f3Shx147065 }
1927516fc7f3Shx147065 return (B_TRUE);
1928516fc7f3Shx147065 }
1929516fc7f3Shx147065 /*
1930516fc7f3Shx147065 * do_autoconf: First scan the wlanlist, and select one essid from scan result
1931516fc7f3Shx147065 * by the order in {preferrence} list. If no match, then heuristic_load;
1932516fc7f3Shx147065 */
1933516fc7f3Shx147065 /*ARGSUSED*/
1934516fc7f3Shx147065 static boolean_t
do_autoconf(int fd,int argc,char ** argv)1935516fc7f3Shx147065 do_autoconf(int fd, int argc, char **argv)
1936516fc7f3Shx147065 {
1937516fc7f3Shx147065 const char *selected = NULL;
1938516fc7f3Shx147065 int timeout = LOADPROFILE_TIMEOUT, forever = 0, len = 0;
1939516fc7f3Shx147065 char *pequal, *param;
1940516fc7f3Shx147065 char **ld_argv = NULL;
1941516fc7f3Shx147065 boolean_t ret = B_TRUE;
1942516fc7f3Shx147065
1943516fc7f3Shx147065 PRTDBG(("do_autoconf(%d, 0x%x)\n", argc, argv));
1944516fc7f3Shx147065 assert(fd > 0);
1945516fc7f3Shx147065 if (argc > 0) {
1946516fc7f3Shx147065 param = safe_strdup(argv[0]);
1947516fc7f3Shx147065 pequal = strchr(param, '=');
1948516fc7f3Shx147065 if (pequal != NULL) {
1949516fc7f3Shx147065 *pequal++ = '\0';
1950516fc7f3Shx147065 } else {
1951516fc7f3Shx147065 do_print_usage();
1952516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
1953516fc7f3Shx147065 }
1954516fc7f3Shx147065 if (strcmp(param, "wait") != 0) {
1955516fc7f3Shx147065 do_print_usage();
1956516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
1957516fc7f3Shx147065 } else {
1958516fc7f3Shx147065 if (strcmp(pequal, "forever") == 0) {
1959516fc7f3Shx147065 forever = 1;
1960516fc7f3Shx147065 } else {
1961516fc7f3Shx147065 if (is_waittime_valid(pequal) == B_FALSE) {
1962516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
1963516fc7f3Shx147065 "invalid value %s for 'wait'\n"),
1964516fc7f3Shx147065 gExecName, pequal);
1965516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
1966516fc7f3Shx147065 }
1967516fc7f3Shx147065 if (sscanf(pequal, "%d", &timeout) != 1) {
1968516fc7f3Shx147065 do_print_usage();
1969516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
1970516fc7f3Shx147065 }
1971516fc7f3Shx147065 if (timeout == -1) {
1972516fc7f3Shx147065 forever = 1;
1973516fc7f3Shx147065 }
1974516fc7f3Shx147065 }
1975516fc7f3Shx147065 }
1976516fc7f3Shx147065 free(param);
1977516fc7f3Shx147065 if (argc > 1) {
1978516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing "
1979516fc7f3Shx147065 "useless tokens after '%s'\n"),
1980516fc7f3Shx147065 gExecName, argv[0]);
1981516fc7f3Shx147065 }
1982516fc7f3Shx147065 }
1983516fc7f3Shx147065
1984516fc7f3Shx147065 while ((forever == 1) || (timeout > 0)) {
1985516fc7f3Shx147065 timeout--;
1986516fc7f3Shx147065 selected = select_profile(fd, 0, max(timeout, forever));
1987516fc7f3Shx147065 if (selected != NULL)
1988516fc7f3Shx147065 break;
1989516fc7f3Shx147065 (void) sleep(1);
1990516fc7f3Shx147065 }
1991516fc7f3Shx147065 if (selected == NULL) {
1992516fc7f3Shx147065 return (B_TRUE);
1993516fc7f3Shx147065 }
1994516fc7f3Shx147065 (void) printf(gettext("%s: autoconf: profile [%s]"
1995516fc7f3Shx147065 " is selected\n"), gExecName, selected);
1996516fc7f3Shx147065 ld_argv = safe_calloc(sizeof (char *), argc+1);
1997516fc7f3Shx147065 ld_argv[0] = safe_strdup(selected);
1998516fc7f3Shx147065 if (argc > 0) {
1999516fc7f3Shx147065 len = max(strlen(argv[0]), strlen("wait=forever"));
2000516fc7f3Shx147065 ld_argv[1] = safe_malloc(len);
2001516fc7f3Shx147065 safe_snprintf(ld_argv[1], len + 1, forever == 1 ?
2002516fc7f3Shx147065 "wait=forever" : "wait=%d", timeout);
2003516fc7f3Shx147065 }
2004516fc7f3Shx147065 ret = do_loadpf(fd, argc+1, ld_argv);
2005516fc7f3Shx147065 free(ld_argv[0]);
2006516fc7f3Shx147065 if (argc > 0) {
2007516fc7f3Shx147065 free(ld_argv[1]);
2008516fc7f3Shx147065 }
2009516fc7f3Shx147065 free(ld_argv);
2010516fc7f3Shx147065 return (ret);
2011516fc7f3Shx147065 }
2012516fc7f3Shx147065
2013516fc7f3Shx147065 /*
2014516fc7f3Shx147065 * do_startconf: almost the same as the do_autoconf, except that doesn't
2015516fc7f3Shx147065 * write file.
2016516fc7f3Shx147065 */
2017516fc7f3Shx147065 /*ARGSUSED*/
2018516fc7f3Shx147065 static boolean_t
do_startconf(int fd,int argc,char ** argv)2019516fc7f3Shx147065 do_startconf(int fd, int argc, char **argv)
2020516fc7f3Shx147065 {
2021516fc7f3Shx147065 int i = 0, ael_num = 0;
2022516fc7f3Shx147065 section_t *p_section = NULL;
2023516fc7f3Shx147065 section_t *p_wep_section = NULL;
2024516fc7f3Shx147065 aelist_t *plist = NULL;
2025516fc7f3Shx147065 const char *selected = NULL;
2026516fc7f3Shx147065 ae_t *pae = NULL;
2027516fc7f3Shx147065 char *pbuf = NULL;
2028516fc7f3Shx147065 char **argvnew = NULL;
2029516fc7f3Shx147065
2030516fc7f3Shx147065 PRTDBG(("do_startconf(%d, 0x%x)\n", argc, argv));
2031516fc7f3Shx147065 assert(fd > 0);
2032516fc7f3Shx147065
2033516fc7f3Shx147065 selected = select_profile(fd, 1, 0);
2034516fc7f3Shx147065 if (selected == NULL) {
2035516fc7f3Shx147065 return (B_TRUE);
2036516fc7f3Shx147065 }
2037516fc7f3Shx147065
2038516fc7f3Shx147065 (void) call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0);
2039516fc7f3Shx147065
2040516fc7f3Shx147065 pbuf = append_pa(selected);
2041516fc7f3Shx147065 p_wep_section = find_section(gp_wepkey_file, pbuf);
2042516fc7f3Shx147065 p_section = find_section(gp_config_file, pbuf);
2043516fc7f3Shx147065 free(pbuf);
2044516fc7f3Shx147065
2045516fc7f3Shx147065 if (p_wep_section != NULL) {
2046516fc7f3Shx147065 plist = p_wep_section->list;
2047516fc7f3Shx147065 pae = plist->ael_head;
2048516fc7f3Shx147065 while (pae != NULL) {
2049516fc7f3Shx147065 if (pae->ae_arg != NULL)
2050516fc7f3Shx147065 (void) do_set_wepkey(fd, pae->ae_arg);
2051516fc7f3Shx147065 pae = pae->ae_next;
2052516fc7f3Shx147065 }
2053516fc7f3Shx147065 }
2054516fc7f3Shx147065
2055516fc7f3Shx147065 if (p_section != NULL) {
2056516fc7f3Shx147065 plist = p_section->list;
2057516fc7f3Shx147065 if (plist->ael_argc == 0) {
2058516fc7f3Shx147065 return (B_TRUE);
2059516fc7f3Shx147065 }
2060516fc7f3Shx147065 argvnew = aeltoargv(plist, &ael_num);
2061516fc7f3Shx147065 (void) do_set(fd, ael_num, argvnew);
2062516fc7f3Shx147065
2063516fc7f3Shx147065 for (i = 0; i < ael_num; i++)
2064516fc7f3Shx147065 free(argvnew[i]);
2065516fc7f3Shx147065 free(argvnew);
2066516fc7f3Shx147065 }
2067516fc7f3Shx147065 return (B_TRUE);
2068516fc7f3Shx147065 }
2069516fc7f3Shx147065
2070516fc7f3Shx147065 static char *
find_active_profile(int fd)2071516fc7f3Shx147065 find_active_profile(int fd)
2072516fc7f3Shx147065 {
2073516fc7f3Shx147065 section_t *p_section = NULL, *activep_section = NULL;
2074516fc7f3Shx147065 aelist_t *plist = NULL;
2075516fc7f3Shx147065 ae_t *pae = NULL;
2076516fc7f3Shx147065 const char *pessid = NULL, *pbssid = NULL;
2077516fc7f3Shx147065 char essid[34], bssid[32];
2078516fc7f3Shx147065 const char *activeprofile = NULL;
2079516fc7f3Shx147065
2080516fc7f3Shx147065 PRTDBG(("find_active_profile: %d\n", fd));
2081516fc7f3Shx147065 if (do_get_essid(fd) == B_FALSE) {
2082516fc7f3Shx147065 return (NULL);
2083516fc7f3Shx147065 }
2084516fc7f3Shx147065 (void) strlcpy(essid, ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid,
2085516fc7f3Shx147065 sizeof (essid));
2086516fc7f3Shx147065 if (do_get_bssid(fd) == B_FALSE) {
2087516fc7f3Shx147065 return (NULL);
2088516fc7f3Shx147065 }
2089516fc7f3Shx147065 safe_snprintf(bssid, sizeof (bssid), "%02x:%02x:%02x:%02x:%02x:%02x",
2090516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[0],
2091516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[1],
2092516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[2],
2093516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[3],
2094516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[4],
2095516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[5]);
2096516fc7f3Shx147065 activep_section = find_section(gp_config_file, WIFI_ACTIVEP);
2097516fc7f3Shx147065 if (activep_section == NULL)
2098516fc7f3Shx147065 return (NULL);
2099516fc7f3Shx147065 activeprofile = get_value(activep_section->list->
2100516fc7f3Shx147065 ael_head->ae_arg);
2101516fc7f3Shx147065 if (activeprofile == NULL)
2102516fc7f3Shx147065 return (NULL);
2103516fc7f3Shx147065 p_section = gp_config_file->section_head;
2104516fc7f3Shx147065 while (p_section != NULL) {
2105516fc7f3Shx147065 if (((plist = p_section->list) != NULL) &&
2106516fc7f3Shx147065 (plist->type == PROFILE) &&
2107516fc7f3Shx147065 (strcmp(p_section->section_id, activeprofile) == 0)) {
2108516fc7f3Shx147065 pae = plist->ael_head;
2109516fc7f3Shx147065 while (pae != NULL) {
2110516fc7f3Shx147065 if (strncmp(pae->ae_arg, "essid=",
2111516fc7f3Shx147065 strlen("essid=")) == 0) {
2112516fc7f3Shx147065 pessid = get_value(pae->ae_arg);
2113516fc7f3Shx147065 }
2114516fc7f3Shx147065 if (strncmp(pae->ae_arg, "bssid=",
2115516fc7f3Shx147065 strlen("bssid=")) == 0) {
2116516fc7f3Shx147065 pbssid = get_value(pae->ae_arg);
2117516fc7f3Shx147065 }
2118516fc7f3Shx147065 pae = pae->ae_next;
2119516fc7f3Shx147065 }
2120516fc7f3Shx147065 if (pessid && pbssid &&
2121516fc7f3Shx147065 (strcmp(essid, pessid) == 0) &&
2122516fc7f3Shx147065 (strcmp(bssid, pbssid) == 0)) {
2123516fc7f3Shx147065 return (p_section->section_id);
2124516fc7f3Shx147065 }
2125516fc7f3Shx147065 }
2126516fc7f3Shx147065 p_section = p_section->section_next;
2127516fc7f3Shx147065 }
2128516fc7f3Shx147065 return (NULL);
2129516fc7f3Shx147065 }
2130516fc7f3Shx147065
2131516fc7f3Shx147065 static void
record_active_profile(char * pname,int action)2132516fc7f3Shx147065 record_active_profile(char *pname, int action)
2133516fc7f3Shx147065 {
2134516fc7f3Shx147065 section_t *p_section = NULL;
2135516fc7f3Shx147065 aelist_t *plist = NULL;
2136516fc7f3Shx147065 char pbuf[256];
2137516fc7f3Shx147065
2138516fc7f3Shx147065 p_section = find_section(gp_config_file, WIFI_ACTIVEP);
2139516fc7f3Shx147065 if (p_section == NULL) {
2140516fc7f3Shx147065 plist = new_ael(ACTIVEP);
2141516fc7f3Shx147065 new_section(gp_config_file, plist, WIFI_ACTIVEP);
2142516fc7f3Shx147065 } else {
2143516fc7f3Shx147065 plist = p_section->list;
2144516fc7f3Shx147065 }
2145516fc7f3Shx147065
2146516fc7f3Shx147065 if (action == RECORD_ADD) {
2147516fc7f3Shx147065 assert(pname != NULL);
2148516fc7f3Shx147065 safe_snprintf(pbuf, sizeof (pbuf), "activep=%s", pname);
2149516fc7f3Shx147065 update_aelist(plist, pbuf);
2150516fc7f3Shx147065 } else if (action == RECORD_DEL) {
2151516fc7f3Shx147065 assert(pname == NULL);
2152516fc7f3Shx147065 update_aelist(plist, "activep= ");
2153516fc7f3Shx147065 }
2154516fc7f3Shx147065 }
2155516fc7f3Shx147065
2156516fc7f3Shx147065 /*
2157516fc7f3Shx147065 * do_loadpf: load a profile, set related parameters both in wifi
2158516fc7f3Shx147065 * and in wifiwepkey, if network name is not exist in the
2159516fc7f3Shx147065 * configration files, then we clean all parameters and set essid only
2160516fc7f3Shx147065 */
2161516fc7f3Shx147065 static boolean_t
do_loadpf(int fd,int argc,char ** argv)2162516fc7f3Shx147065 do_loadpf(int fd, int argc, char ** argv)
2163516fc7f3Shx147065 {
2164516fc7f3Shx147065 int i = 0, ael_num = 0;
2165516fc7f3Shx147065 int timeout = LOADPROFILE_TIMEOUT, forever = 0;
2166516fc7f3Shx147065 section_t *p_section = NULL;
2167516fc7f3Shx147065 section_t *p_wep_section = NULL;
2168516fc7f3Shx147065 aelist_t *plist = NULL;
2169516fc7f3Shx147065 ae_t *pae = NULL;
2170516fc7f3Shx147065 char *pbuf = NULL;
2171516fc7f3Shx147065 char **argvnew = NULL;
2172516fc7f3Shx147065 char *connect;
2173516fc7f3Shx147065 char *pequal, *param;
2174516fc7f3Shx147065
2175516fc7f3Shx147065 PRTDBG(("do_loadpf(%d, %x)\n", argc, argv));
2176516fc7f3Shx147065 assert(fd > 0);
2177516fc7f3Shx147065 if (argc == 0) {
2178516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: connect: "
2179516fc7f3Shx147065 "profile name missing\n"), gExecName);
2180516fc7f3Shx147065 return (B_FALSE);
2181516fc7f3Shx147065 }
2182516fc7f3Shx147065 if (argc > 1) {
2183516fc7f3Shx147065 param = safe_strdup(argv[1]);
2184516fc7f3Shx147065 pequal = strchr(param, '=');
2185516fc7f3Shx147065 if (pequal != NULL) {
2186516fc7f3Shx147065 *pequal++ = '\0';
2187516fc7f3Shx147065 } else {
2188516fc7f3Shx147065 do_print_usage();
2189516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
2190516fc7f3Shx147065 }
2191516fc7f3Shx147065 if (strcmp(param, "wait") != 0) {
2192516fc7f3Shx147065 do_print_usage();
2193516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
2194516fc7f3Shx147065 } else {
2195516fc7f3Shx147065 if (strcmp(pequal, "forever") == 0) {
2196516fc7f3Shx147065 forever = 1;
2197516fc7f3Shx147065 } else {
2198516fc7f3Shx147065 if (is_waittime_valid(pequal) == B_FALSE) {
2199516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
2200516fc7f3Shx147065 "invalid value %s for 'wait'\n"),
2201516fc7f3Shx147065 gExecName, pequal);
2202516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
2203516fc7f3Shx147065 }
2204516fc7f3Shx147065 if (sscanf(pequal, "%d", &timeout) != 1) {
2205516fc7f3Shx147065 do_print_usage();
2206516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
2207516fc7f3Shx147065 }
2208516fc7f3Shx147065 if (timeout == -1) {
2209516fc7f3Shx147065 forever = 1;
2210516fc7f3Shx147065 }
2211516fc7f3Shx147065 }
2212516fc7f3Shx147065 }
2213516fc7f3Shx147065 free(param);
2214516fc7f3Shx147065 if (argc > 2) {
2215516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing "
2216516fc7f3Shx147065 "useless tokens after '%s'\n"),
2217516fc7f3Shx147065 gExecName, argv[1]);
2218516fc7f3Shx147065 }
2219516fc7f3Shx147065 }
2220516fc7f3Shx147065 (void) call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0);
2221516fc7f3Shx147065
2222516fc7f3Shx147065 pbuf = append_pa(argv[0]);
2223516fc7f3Shx147065 p_wep_section = find_section(gp_wepkey_file, pbuf);
2224516fc7f3Shx147065 p_section = find_section(gp_config_file, pbuf);
2225516fc7f3Shx147065
2226516fc7f3Shx147065 if (p_wep_section != NULL) {
2227516fc7f3Shx147065 (void) set_prefer(gp_config_file, argv[0], 1);
2228516fc7f3Shx147065 plist = p_wep_section->list;
2229516fc7f3Shx147065 pae = plist->ael_head;
2230516fc7f3Shx147065 while (pae != NULL) {
2231516fc7f3Shx147065 if (pae->ae_arg != NULL) {
2232516fc7f3Shx147065 (void) do_set_wepkey(fd, pae->ae_arg);
2233516fc7f3Shx147065 }
2234516fc7f3Shx147065 pae = pae->ae_next;
2235516fc7f3Shx147065 }
2236516fc7f3Shx147065 }
2237516fc7f3Shx147065
2238516fc7f3Shx147065 if (p_section != NULL) {
2239516fc7f3Shx147065 connect = "profile";
2240516fc7f3Shx147065
2241516fc7f3Shx147065 (void) set_prefer(gp_config_file, argv[0], 1);
2242516fc7f3Shx147065 plist = p_section->list;
2243516fc7f3Shx147065 if (plist->ael_argc == 0) {
2244516fc7f3Shx147065 free(pbuf);
2245516fc7f3Shx147065 return (B_TRUE);
2246516fc7f3Shx147065 }
2247516fc7f3Shx147065 argvnew = aeltoargv(plist, &ael_num);
2248516fc7f3Shx147065 /*
2249516fc7f3Shx147065 * if there is no 'essid' item in argvnew, the profile
2250516fc7f3Shx147065 * name(argv[0]) is treated as essid.
2251516fc7f3Shx147065 */
2252516fc7f3Shx147065 for (i = 0; i < ael_num; i++) {
2253516fc7f3Shx147065 if (strncmp(argvnew[i], "essid=", strlen("essid="))
2254516fc7f3Shx147065 == 0)
2255516fc7f3Shx147065 break;
2256516fc7f3Shx147065 }
2257516fc7f3Shx147065 if (i == ael_num)
2258516fc7f3Shx147065 (void) do_set_essid(fd, argv[0]);
2259516fc7f3Shx147065
2260516fc7f3Shx147065 (void) do_set(fd, ael_num, argvnew);
2261516fc7f3Shx147065
2262516fc7f3Shx147065 for (i = 0; i < ael_num; i++)
2263516fc7f3Shx147065 free(argvnew[i]);
2264516fc7f3Shx147065 free(argvnew);
2265516fc7f3Shx147065
2266516fc7f3Shx147065 /*
2267516fc7f3Shx147065 * set flag in {active_profile} so that showprofile knows
2268516fc7f3Shx147065 * which profile is active when more than one profiles are
2269516fc7f3Shx147065 * created for the same WLAN.
2270516fc7f3Shx147065 */
2271516fc7f3Shx147065 record_active_profile(pbuf, RECORD_ADD);
2272516fc7f3Shx147065 } else {
2273516fc7f3Shx147065 (void) do_set_essid(fd, argv[0]);
2274516fc7f3Shx147065 connect = "essid";
2275516fc7f3Shx147065 }
2276516fc7f3Shx147065
2277516fc7f3Shx147065 while ((forever == 1) || (timeout > 0)) {
2278516fc7f3Shx147065 if ((do_get_linkstatus(fd) == B_TRUE) &&
2279516fc7f3Shx147065 (*(wl_linkstatus_t *)(gbuf->wldp_buf) == WL_CONNECTED)) {
2280516fc7f3Shx147065 section_t *p_section = NULL;
2281516fc7f3Shx147065 aelist_t *plist = NULL;
2282516fc7f3Shx147065 char bssid[32];
2283516fc7f3Shx147065 /* record bssid in the profile */
2284516fc7f3Shx147065 if (do_get_bssid(fd) == B_FALSE) {
2285516fc7f3Shx147065 free(pbuf);
2286516fc7f3Shx147065 return (B_TRUE);
2287516fc7f3Shx147065 }
2288516fc7f3Shx147065 safe_snprintf(bssid, sizeof (bssid),
2289516fc7f3Shx147065 "bssid=%02x:%02x:%02x:%02x:%02x:%02x",
2290516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[0],
2291516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[1],
2292516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[2],
2293516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[3],
2294516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[4],
2295516fc7f3Shx147065 ((uint8_t *)gbuf->wldp_buf)[5]);
2296516fc7f3Shx147065
2297516fc7f3Shx147065 p_section = find_section(gp_config_file, pbuf);
2298516fc7f3Shx147065 if (p_section != NULL) {
2299516fc7f3Shx147065 plist = p_section->list;
2300516fc7f3Shx147065 update_aelist(plist, bssid);
2301516fc7f3Shx147065 }
2302516fc7f3Shx147065 free(pbuf);
2303516fc7f3Shx147065 (void) printf(gettext("%s: connecting to "
2304516fc7f3Shx147065 "%s '%s'\n"), gExecName, connect, argv[0]);
2305516fc7f3Shx147065 return (B_TRUE);
2306516fc7f3Shx147065 }
2307516fc7f3Shx147065 (void) sleep(1);
2308516fc7f3Shx147065 timeout--;
2309516fc7f3Shx147065 PRTDBG(("connect counting:......%d\n", timeout));
2310516fc7f3Shx147065 }
2311516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to connect to "
2312516fc7f3Shx147065 "%s '%s'\n"), gExecName, connect, argv[0]);
2313516fc7f3Shx147065 free(pbuf);
2314516fc7f3Shx147065 return (B_FALSE);
2315516fc7f3Shx147065 }
2316516fc7f3Shx147065
2317516fc7f3Shx147065 /*
2318516fc7f3Shx147065 * if wepkey is set in the profile, display wepkey|n=*****
2319516fc7f3Shx147065 * when showprofile and getprofilewepkey.
2320516fc7f3Shx147065 * if wepkeyn is NULL, all the wepkeys will be display,
2321516fc7f3Shx147065 * otherwise, just display the matching one.
2322516fc7f3Shx147065 */
2323516fc7f3Shx147065 static void
print_wepkey_info(const char * id,const char * wepkeyn)2324516fc7f3Shx147065 print_wepkey_info(const char *id, const char *wepkeyn)
2325516fc7f3Shx147065 {
2326516fc7f3Shx147065 char *pequal, *param;
2327516fc7f3Shx147065 section_t *p_section = NULL;
2328516fc7f3Shx147065 aelist_t *plist = NULL;
2329516fc7f3Shx147065 ae_t *pae = NULL;
2330516fc7f3Shx147065
2331516fc7f3Shx147065 p_section = find_section(gp_wepkey_file, id);
2332516fc7f3Shx147065 if (p_section != NULL) {
2333516fc7f3Shx147065 plist = p_section->list;
2334516fc7f3Shx147065 pae = plist->ael_head;
2335516fc7f3Shx147065 while (pae != NULL) {
2336516fc7f3Shx147065 if (pae->ae_arg != NULL) {
2337516fc7f3Shx147065 param = safe_strdup(pae->ae_arg);
2338516fc7f3Shx147065 pequal = strchr(param, '=');
2339516fc7f3Shx147065 if (pequal == NULL)
2340516fc7f3Shx147065 return;
2341516fc7f3Shx147065 *pequal = '\0';
2342516fc7f3Shx147065 if (wepkeyn != NULL) {
2343516fc7f3Shx147065 if (strcmp(wepkeyn, param) == 0)
2344516fc7f3Shx147065 (void) printf("\t%s=*****\n",
2345516fc7f3Shx147065 param);
2346516fc7f3Shx147065 free(param);
2347516fc7f3Shx147065 return;
2348516fc7f3Shx147065 } else {
2349516fc7f3Shx147065 (void) printf("\t%s=*****\n", param);
2350516fc7f3Shx147065 free(param);
2351516fc7f3Shx147065 }
2352516fc7f3Shx147065 }
2353516fc7f3Shx147065 pae = pae->ae_next;
2354516fc7f3Shx147065 }
2355516fc7f3Shx147065 }
2356516fc7f3Shx147065 }
2357516fc7f3Shx147065
2358516fc7f3Shx147065 /*
2359516fc7f3Shx147065 * do_printpf: print each parameters of the profile, if no network name
2360516fc7f3Shx147065 * assigned, then print all profile saved in configration file.
2361516fc7f3Shx147065 */
2362516fc7f3Shx147065 /*ARGSUSED*/
2363516fc7f3Shx147065 static boolean_t
do_printpf(int fd,int argc,char ** argv)2364516fc7f3Shx147065 do_printpf(int fd, int argc, char ** argv)
2365516fc7f3Shx147065 {
2366516fc7f3Shx147065 section_t *p_section = NULL;
2367516fc7f3Shx147065 aelist_t *plist = NULL;
2368516fc7f3Shx147065 ae_t *pae = NULL;
2369516fc7f3Shx147065 char *pbuf = NULL;
2370516fc7f3Shx147065 int i;
2371516fc7f3Shx147065
2372516fc7f3Shx147065 PRTDBG(("do_printpf(%d, %x)\n", argc, argv));
2373516fc7f3Shx147065
2374516fc7f3Shx147065 /*
2375516fc7f3Shx147065 * if no profile name is inputted, all the profiles will be displayed.
2376516fc7f3Shx147065 */
2377516fc7f3Shx147065 if (argc == 0) {
2378516fc7f3Shx147065 p_section = gp_config_file->section_head;
2379516fc7f3Shx147065 while (p_section != NULL) {
2380516fc7f3Shx147065 plist = p_section->list;
2381516fc7f3Shx147065 if (plist->type == PROFILE) {
2382516fc7f3Shx147065 (void) printf("%s\n", p_section->section_id);
2383516fc7f3Shx147065 pae = plist->ael_head;
2384516fc7f3Shx147065 while (pae != NULL) {
2385516fc7f3Shx147065 if (pae->ae_arg != NULL) {
2386516fc7f3Shx147065 (void) printf("\t%s\n",
2387516fc7f3Shx147065 pae->ae_arg);
2388516fc7f3Shx147065 }
2389516fc7f3Shx147065 pae = pae->ae_next;
2390516fc7f3Shx147065 }
2391516fc7f3Shx147065 /*
2392516fc7f3Shx147065 * identify whether wepkey is set
2393516fc7f3Shx147065 * in the profile
2394516fc7f3Shx147065 */
2395516fc7f3Shx147065 print_wepkey_info(p_section->section_id, NULL);
2396516fc7f3Shx147065 }
2397516fc7f3Shx147065 p_section = p_section->section_next;
2398516fc7f3Shx147065 }
2399516fc7f3Shx147065 return (B_TRUE);
2400516fc7f3Shx147065 }
2401516fc7f3Shx147065
2402516fc7f3Shx147065 for (i = 0; i < argc; i++) {
2403516fc7f3Shx147065 pbuf = append_pa(argv[i]);
2404516fc7f3Shx147065 p_section = find_section(gp_config_file, pbuf);
2405516fc7f3Shx147065 free(pbuf);
2406516fc7f3Shx147065 if (p_section != NULL) {
2407516fc7f3Shx147065 (void) printf("%s\n", p_section->section_id);
2408516fc7f3Shx147065 plist = p_section->list;
2409516fc7f3Shx147065 if (plist != NULL) {
2410516fc7f3Shx147065 pae = plist->ael_head;
2411516fc7f3Shx147065 while (pae != NULL) {
2412516fc7f3Shx147065 if (pae->ae_arg != NULL) {
2413516fc7f3Shx147065 (void) printf("\t%s\n",
2414516fc7f3Shx147065 pae->ae_arg);
2415516fc7f3Shx147065 }
2416516fc7f3Shx147065 pae = pae->ae_next;
2417516fc7f3Shx147065 }
2418516fc7f3Shx147065 /*
2419516fc7f3Shx147065 * identify whether wepkey is set
2420516fc7f3Shx147065 * in the profile
2421516fc7f3Shx147065 */
2422516fc7f3Shx147065 print_wepkey_info(p_section->section_id, NULL);
2423516fc7f3Shx147065 }
2424516fc7f3Shx147065 } else {
2425516fc7f3Shx147065 (void) fprintf(stderr,
2426516fc7f3Shx147065 gettext("%s: showprofile : "
2427516fc7f3Shx147065 "no such profile: '%s'\n"),
2428516fc7f3Shx147065 gExecName, argv[i]);
2429516fc7f3Shx147065 return (B_FALSE);
2430516fc7f3Shx147065 }
2431516fc7f3Shx147065 }
2432516fc7f3Shx147065 return (B_TRUE);
2433516fc7f3Shx147065 }
2434516fc7f3Shx147065 /*
2435516fc7f3Shx147065 * find_ae: Find an ae by its contents, return its pointer.
2436516fc7f3Shx147065 */
2437516fc7f3Shx147065 static ae_t *
find_ae(aelist_t * plist,const char * arg)2438516fc7f3Shx147065 find_ae(aelist_t *plist, const char *arg)
2439516fc7f3Shx147065 {
2440516fc7f3Shx147065 char *param = NULL;
2441516fc7f3Shx147065 char *pnext = NULL;
2442516fc7f3Shx147065 ae_t *pae = NULL;
2443516fc7f3Shx147065
2444516fc7f3Shx147065 if ((arg == NULL) || (plist == NULL)) {
2445516fc7f3Shx147065 PRTDBG(("find_ae: arg= NULL or plist=NULL\n"));
2446516fc7f3Shx147065 return (NULL);
2447516fc7f3Shx147065 }
2448516fc7f3Shx147065 PRTDBG(("find_ae(0x%x, \"%s\")\n", plist, arg));
2449516fc7f3Shx147065 param = safe_strdup(arg);
2450516fc7f3Shx147065 pnext = strchr(param, '=');
2451516fc7f3Shx147065 if (pnext != NULL) {
2452516fc7f3Shx147065 *pnext = '\0';
2453516fc7f3Shx147065 } else {
2454516fc7f3Shx147065 PRTDBG(("find_ae: param = \"%s\"\n", param));
2455516fc7f3Shx147065 free(param);
2456516fc7f3Shx147065 return (NULL);
2457516fc7f3Shx147065 }
2458516fc7f3Shx147065
2459516fc7f3Shx147065 pae = plist->ael_head;
2460516fc7f3Shx147065 while (pae != NULL) {
2461516fc7f3Shx147065 if ((pae->ae_arg != NULL) &&
2462516fc7f3Shx147065 (strncmp(pae->ae_arg, param, strlen(param)) == 0)) {
2463516fc7f3Shx147065 PRTDBG(("find_ae: param = \"%s\"\n", param));
2464516fc7f3Shx147065 free(param);
2465516fc7f3Shx147065 return (pae);
2466516fc7f3Shx147065 }
2467516fc7f3Shx147065 pae = pae->ae_next;
2468516fc7f3Shx147065 }
2469516fc7f3Shx147065 free(param);
2470516fc7f3Shx147065 return (NULL);
2471516fc7f3Shx147065 }
2472516fc7f3Shx147065
2473516fc7f3Shx147065 /*
2474516fc7f3Shx147065 * update_aelist: Update an aelist by arg, for example:
2475516fc7f3Shx147065 * there are an item with content"essid=ap7-2",
2476516fc7f3Shx147065 * update_aelist(0x..., "essid=myssid2") will update it as "essid=myssid2"
2477516fc7f3Shx147065 */
2478516fc7f3Shx147065 static void
update_aelist(aelist_t * plist,const char * arg)2479516fc7f3Shx147065 update_aelist(aelist_t *plist, const char *arg)
2480516fc7f3Shx147065 {
2481516fc7f3Shx147065 ae_t *pae = NULL;
2482516fc7f3Shx147065
2483516fc7f3Shx147065 assert((arg != NULL)&&(plist != NULL));
2484516fc7f3Shx147065 PRTDBG(("update_aelist(0x%x, \"%s\")\n", plist, arg));
2485516fc7f3Shx147065 pae = find_ae(plist, arg);
2486516fc7f3Shx147065 if (pae == NULL) {
2487516fc7f3Shx147065 new_ae(plist, arg);
2488516fc7f3Shx147065 } else {
2489516fc7f3Shx147065 free(pae->ae_arg);
2490516fc7f3Shx147065 pae->ae_arg = safe_strdup(arg);
2491516fc7f3Shx147065 }
2492516fc7f3Shx147065 }
2493516fc7f3Shx147065
2494516fc7f3Shx147065 /*
2495516fc7f3Shx147065 * do_deletepf: delete a profile in configration files.
2496516fc7f3Shx147065 */
2497516fc7f3Shx147065 /*ARGSUSED*/
2498516fc7f3Shx147065 static boolean_t
do_deletepf(int fd,int argc,char ** argv)2499516fc7f3Shx147065 do_deletepf(int fd, int argc, char **argv)
2500516fc7f3Shx147065 {
2501516fc7f3Shx147065 int i = 0;
2502516fc7f3Shx147065 char *section_id;
2503516fc7f3Shx147065 char *prefer;
2504516fc7f3Shx147065 section_t *p_section = NULL, *p_sectionbak = NULL;
2505516fc7f3Shx147065 aelist_t *plist = NULL;
2506516fc7f3Shx147065
2507516fc7f3Shx147065 PRTDBG(("do_deletepf(%d, \"%s\")\n", argc, argv));
2508516fc7f3Shx147065 if (argc <= 0) {
2509516fc7f3Shx147065 do_print_usage();
2510516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
2511516fc7f3Shx147065 }
2512516fc7f3Shx147065
2513516fc7f3Shx147065 /*
2514516fc7f3Shx147065 * if a "all" is inputted, all the profiles will be deleted.
2515516fc7f3Shx147065 */
2516516fc7f3Shx147065 if (strcasecmp(argv[0], "all") == 0) {
2517516fc7f3Shx147065 p_section = gp_config_file->section_head;
2518516fc7f3Shx147065 while ((p_section != NULL) &&
2519516fc7f3Shx147065 ((plist = p_section->list) != NULL)) {
2520516fc7f3Shx147065 if (plist->type == PROFILE) {
2521516fc7f3Shx147065 p_sectionbak = p_section->section_next;
2522516fc7f3Shx147065 section_id = safe_strdup(p_section->section_id);
2523516fc7f3Shx147065 (void) del_section(gp_config_file, section_id);
2524516fc7f3Shx147065 (void) del_section(gp_wepkey_file, section_id);
2525516fc7f3Shx147065 /*
2526516fc7f3Shx147065 * remove the '[]' of the [section_id]
2527516fc7f3Shx147065 */
2528516fc7f3Shx147065 prefer = section_id + 1;
2529516fc7f3Shx147065 *(prefer + strlen(section_id) - 2) = '\0';
2530516fc7f3Shx147065 (void) del_prefer(gp_config_file, prefer,
2531516fc7f3Shx147065 B_FALSE);
2532516fc7f3Shx147065 free(section_id);
2533516fc7f3Shx147065 p_section = p_sectionbak;
2534516fc7f3Shx147065 continue;
2535516fc7f3Shx147065 }
2536516fc7f3Shx147065 p_section = p_section->section_next;
2537516fc7f3Shx147065 }
2538516fc7f3Shx147065 return (B_TRUE);
2539516fc7f3Shx147065 }
2540516fc7f3Shx147065 if (gp_config_file != NULL) {
2541516fc7f3Shx147065 for (i = 0; i < argc; i++) {
2542516fc7f3Shx147065 section_id = append_pa(argv[i]);
2543516fc7f3Shx147065 if (del_section(gp_config_file, section_id)
2544516fc7f3Shx147065 == B_FALSE) {
2545516fc7f3Shx147065 if (del_section(gp_wepkey_file, section_id)
2546516fc7f3Shx147065 == B_TRUE) {
2547516fc7f3Shx147065 (void) del_prefer(gp_config_file,
2548516fc7f3Shx147065 argv[i], B_FALSE);
2549516fc7f3Shx147065 free(section_id);
2550516fc7f3Shx147065 return (B_TRUE);
2551516fc7f3Shx147065 } else {
2552516fc7f3Shx147065 (void) fprintf(stderr,
2553516fc7f3Shx147065 gettext("%s: deleteprofile"
2554516fc7f3Shx147065 ": no such profile: '%s'\n"),
2555516fc7f3Shx147065 gExecName, argv[i]);
2556516fc7f3Shx147065 free(section_id);
2557516fc7f3Shx147065 return (B_FALSE);
2558516fc7f3Shx147065 }
2559516fc7f3Shx147065 }
2560516fc7f3Shx147065 (void) del_prefer(gp_config_file, argv[i], B_FALSE);
2561516fc7f3Shx147065 (void) del_section(gp_wepkey_file, section_id);
2562516fc7f3Shx147065 free(section_id);
2563516fc7f3Shx147065 }
2564516fc7f3Shx147065 }
2565516fc7f3Shx147065 return (B_TRUE);
2566516fc7f3Shx147065 }
2567516fc7f3Shx147065
2568516fc7f3Shx147065 /*
2569516fc7f3Shx147065 * do_history: Print the list in {history} section.
2570516fc7f3Shx147065 */
2571516fc7f3Shx147065 /*ARGSUSED*/
2572516fc7f3Shx147065 static boolean_t
do_history(int fd,int argc,char ** argv)2573516fc7f3Shx147065 do_history(int fd, int argc, char **argv)
2574516fc7f3Shx147065 {
2575516fc7f3Shx147065 section_t *p_section = NULL;
2576516fc7f3Shx147065 aelist_t *plist = NULL;
2577516fc7f3Shx147065 ae_t *pae = NULL;
2578516fc7f3Shx147065 char *param, *param_bak, *pcomma;
2579516fc7f3Shx147065 uint32_t maxessidlen = 0, ulen;
2580516fc7f3Shx147065 char format[256], *ntstr;
2581516fc7f3Shx147065 uint32_t nt = 0, cnt = 0;
2582516fc7f3Shx147065 int len;
2583516fc7f3Shx147065 time_t cltime;
2584516fc7f3Shx147065
2585516fc7f3Shx147065 PRTDBG(("do_history(%d, 0x%x)\n", argc, argv));
2586516fc7f3Shx147065 if (argc > 0) {
2587516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
2588516fc7f3Shx147065 "after 'history'\n"), gExecName);
2589516fc7f3Shx147065 }
2590516fc7f3Shx147065 p_section = find_section(gp_config_file, WIFI_HISTORY);
2591516fc7f3Shx147065 if (p_section == NULL) {
2592516fc7f3Shx147065 PRTDBG(("no history section\n"));
2593516fc7f3Shx147065 return (B_FALSE);
2594516fc7f3Shx147065 }
2595516fc7f3Shx147065 plist = p_section->list;
2596516fc7f3Shx147065
2597516fc7f3Shx147065 /*
2598516fc7f3Shx147065 * If history section is empty, directly return.
2599516fc7f3Shx147065 */
2600516fc7f3Shx147065 if (plist == NULL)
2601516fc7f3Shx147065 return (B_TRUE);
2602516fc7f3Shx147065 /*
2603516fc7f3Shx147065 * construct the output format in terms of the
2604516fc7f3Shx147065 * maxmium essid length
2605516fc7f3Shx147065 */
2606516fc7f3Shx147065 pae = NULL;
2607516fc7f3Shx147065 pae = plist->ael_head;
2608516fc7f3Shx147065 while (pae != NULL) {
2609516fc7f3Shx147065 if (pae->ae_arg != NULL) {
2610516fc7f3Shx147065 param = safe_strdup(pae->ae_arg);
2611516fc7f3Shx147065 pcomma = strchr(param, ',');
2612516fc7f3Shx147065 if (pcomma == NULL) {
2613516fc7f3Shx147065 (void) fprintf(stderr,
2614516fc7f3Shx147065 gettext("%s: history : "
2615516fc7f3Shx147065 "data format error\n"),
2616516fc7f3Shx147065 gExecName);
2617516fc7f3Shx147065 free(param);
2618516fc7f3Shx147065 return (B_FALSE);
2619516fc7f3Shx147065 }
2620516fc7f3Shx147065 *pcomma = '\0';
2621516fc7f3Shx147065 ulen = strlen(param);
2622516fc7f3Shx147065 maxessidlen = (maxessidlen > ulen
2623516fc7f3Shx147065 ? maxessidlen:ulen);
2624516fc7f3Shx147065 free(param);
2625516fc7f3Shx147065 }
2626516fc7f3Shx147065 pae = pae->ae_next;
2627516fc7f3Shx147065 }
2628516fc7f3Shx147065 if ((nt = (maxessidlen / 8 + 1)) > 4)
2629516fc7f3Shx147065 nt = 4;
2630516fc7f3Shx147065 len = snprintf(format, sizeof (format), gettext("essid"));
2631516fc7f3Shx147065 ntstr = construct_format(nt);
2632516fc7f3Shx147065 assert((ntstr != NULL) && (strlen(ntstr) <= 4));
2633516fc7f3Shx147065 len += snprintf(format + len, sizeof (format) - len, "%s", ntstr);
2634516fc7f3Shx147065 len += snprintf(format + len, sizeof (format) - len,
2635516fc7f3Shx147065 gettext("bssid\t\t encryption\tlast seen\n"));
2636516fc7f3Shx147065
2637516fc7f3Shx147065 if ((len <= 0) || (len > sizeof (format) - 1)) {
2638516fc7f3Shx147065 (void) printf(gettext("essid\t\t\t\tbssid\t\t encryption"
2639516fc7f3Shx147065 "\tlast seen\n"));
2640516fc7f3Shx147065 } else {
2641516fc7f3Shx147065 (void) printf("%s", format);
2642516fc7f3Shx147065 }
2643516fc7f3Shx147065 /*
2644516fc7f3Shx147065 * output the contents of the history section.
2645516fc7f3Shx147065 */
2646516fc7f3Shx147065 pae = plist->ael_head;
2647516fc7f3Shx147065 while (pae != NULL) {
2648516fc7f3Shx147065 if (pae->ae_arg != NULL) {
2649516fc7f3Shx147065 param = safe_strdup(pae->ae_arg);
2650516fc7f3Shx147065 param_bak = param;
2651516fc7f3Shx147065 if ((pcomma = strchr(param, ',')) != NULL) {
2652516fc7f3Shx147065 *pcomma = '\0';
2653516fc7f3Shx147065 cnt = nt - (min((strlen(param)/8 + 1), 4) - 1);
2654516fc7f3Shx147065 ntstr = construct_format(cnt);
2655516fc7f3Shx147065 assert(ntstr != NULL);
2656516fc7f3Shx147065 /* display essid */
2657516fc7f3Shx147065 (void) printf("%s%s", param, ntstr);
2658516fc7f3Shx147065 free(ntstr);
2659516fc7f3Shx147065 }
2660516fc7f3Shx147065 param = pcomma + 1;
2661516fc7f3Shx147065 if ((pcomma = strchr(param, ',')) != NULL) {
2662516fc7f3Shx147065 *pcomma = '\0';
2663516fc7f3Shx147065 /* display bssid */
2664516fc7f3Shx147065 (void) printf("%s ", param);
2665516fc7f3Shx147065 }
2666516fc7f3Shx147065 param = pcomma + 1;
2667516fc7f3Shx147065 if ((pcomma = strchr(param, ',')) != NULL) {
2668516fc7f3Shx147065 *pcomma = '\0';
2669516fc7f3Shx147065 /* display wep */
2670516fc7f3Shx147065 (void) printf("%s\t\t", param);
2671516fc7f3Shx147065 }
2672516fc7f3Shx147065 param = pcomma + 1;
2673516fc7f3Shx147065 /* display time stamp */
2674516fc7f3Shx147065 cltime = (time_t)atol(param);
2675516fc7f3Shx147065 (void) printf("%s", ctime(&cltime));
2676516fc7f3Shx147065 free(param_bak);
2677516fc7f3Shx147065 }
2678516fc7f3Shx147065 pae = pae->ae_next;
2679516fc7f3Shx147065 }
2680516fc7f3Shx147065
2681516fc7f3Shx147065 return (B_TRUE);
2682516fc7f3Shx147065 }
2683516fc7f3Shx147065
2684516fc7f3Shx147065 /*
2685516fc7f3Shx147065 * do_lsprefer: Print the list in {preferrence} section
2686516fc7f3Shx147065 */
2687516fc7f3Shx147065 /*ARGSUSED*/
2688516fc7f3Shx147065 static boolean_t
do_lsprefer(int fd,int argc,char ** argv)2689516fc7f3Shx147065 do_lsprefer(int fd, int argc, char **argv)
2690516fc7f3Shx147065 {
2691516fc7f3Shx147065 int i = 0;
2692516fc7f3Shx147065 section_t *p_section = NULL;
2693516fc7f3Shx147065 aelist_t *plist = NULL;
2694516fc7f3Shx147065 ae_t *pae = NULL;
2695516fc7f3Shx147065 char *pbuf;
2696516fc7f3Shx147065
2697516fc7f3Shx147065 PRTDBG(("do_lsprefer(%d, 0x%x)\n", argc, argv));
2698516fc7f3Shx147065 if (argc > 0) {
2699516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
2700516fc7f3Shx147065 "after 'listprefer'\n"), gExecName);
2701516fc7f3Shx147065 }
2702516fc7f3Shx147065 p_section = find_section(gp_config_file, WIFI_PREFER);
2703516fc7f3Shx147065 if (p_section != NULL) {
2704516fc7f3Shx147065 plist = p_section->list;
2705516fc7f3Shx147065 if (plist != NULL) {
2706516fc7f3Shx147065 pae = NULL;
2707516fc7f3Shx147065 pae = plist->ael_head;
2708516fc7f3Shx147065 while (pae != NULL) {
2709516fc7f3Shx147065 if (pae->ae_arg != NULL) {
2710516fc7f3Shx147065 pbuf = append_pa(pae->ae_arg);
2711516fc7f3Shx147065 (void) printf("%d\t%s\n", ++i, pbuf);
2712516fc7f3Shx147065 }
2713516fc7f3Shx147065 pae = pae->ae_next;
2714516fc7f3Shx147065 }
2715516fc7f3Shx147065 }
2716516fc7f3Shx147065 return (B_TRUE);
2717516fc7f3Shx147065 } else {
2718516fc7f3Shx147065 PRTDBG(("no preference section\n"));
2719516fc7f3Shx147065 return (B_FALSE);
2720516fc7f3Shx147065 }
2721516fc7f3Shx147065 }
2722516fc7f3Shx147065
2723516fc7f3Shx147065 /*
2724516fc7f3Shx147065 * do_rmprefer: Remove an item in {preferrence} list
2725516fc7f3Shx147065 */
2726516fc7f3Shx147065 /*ARGSUSED*/
2727516fc7f3Shx147065 static boolean_t
do_rmprefer(int fd,int argc,char ** argv)2728516fc7f3Shx147065 do_rmprefer(int fd, int argc, char **argv)
2729516fc7f3Shx147065 {
2730516fc7f3Shx147065 int i = 0;
2731516fc7f3Shx147065 section_t *p_section = NULL;
2732516fc7f3Shx147065 aelist_t *plist = NULL;
2733516fc7f3Shx147065 ae_t *pae = NULL;
2734516fc7f3Shx147065
2735516fc7f3Shx147065 PRTDBG(("do_rmprefer(%d, 0x%x)\n", argc, argv));
2736516fc7f3Shx147065 if (argc <= 0) {
2737516fc7f3Shx147065 do_print_usage();
2738516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
2739516fc7f3Shx147065 }
2740516fc7f3Shx147065
2741516fc7f3Shx147065 /*
2742516fc7f3Shx147065 * if a "all" is inputted, all the items in the preference
2743516fc7f3Shx147065 * list will be deleted.
2744516fc7f3Shx147065 */
2745516fc7f3Shx147065 if (strcasecmp(argv[0], "all") == 0) {
2746516fc7f3Shx147065 p_section = find_section(gp_config_file, WIFI_PREFER);
2747516fc7f3Shx147065 if (p_section != NULL)
2748516fc7f3Shx147065 plist = p_section->list;
2749516fc7f3Shx147065
2750516fc7f3Shx147065 if ((p_section == NULL) || (plist == NULL))
2751516fc7f3Shx147065 return (B_FALSE);
2752516fc7f3Shx147065 pae = plist->ael_head;
2753516fc7f3Shx147065 while (pae != NULL) {
2754516fc7f3Shx147065 free(pae);
2755516fc7f3Shx147065 pae = pae->ae_next;
2756516fc7f3Shx147065 }
2757516fc7f3Shx147065 plist->ael_head = plist->ael_tail = NULL;
2758516fc7f3Shx147065 plist->ael_argc = 0;
2759516fc7f3Shx147065 } else if (gp_config_file != NULL) {
2760516fc7f3Shx147065 for (i = 0; i < argc; i++) {
2761516fc7f3Shx147065 if (del_prefer(gp_config_file, argv[i], B_TRUE)
2762516fc7f3Shx147065 == B_FALSE) {
2763516fc7f3Shx147065 return (B_FALSE);
2764516fc7f3Shx147065 }
2765516fc7f3Shx147065 }
2766516fc7f3Shx147065 }
2767516fc7f3Shx147065 return (B_TRUE);
2768516fc7f3Shx147065 }
2769516fc7f3Shx147065
2770516fc7f3Shx147065 static boolean_t
is_prefer_rank_valid(const char * pbuf)2771516fc7f3Shx147065 is_prefer_rank_valid(const char *pbuf)
2772516fc7f3Shx147065 {
2773516fc7f3Shx147065 int i;
2774516fc7f3Shx147065 boolean_t ret = B_FALSE;
2775516fc7f3Shx147065
2776516fc7f3Shx147065 for (i = 0; i < strlen(pbuf); i++) {
2777516fc7f3Shx147065 if (isdigit(pbuf[i]) == 0) {
2778516fc7f3Shx147065 ret = B_FALSE;
2779516fc7f3Shx147065 goto exit0;
2780516fc7f3Shx147065 }
2781516fc7f3Shx147065 }
2782516fc7f3Shx147065 i = atoi(pbuf);
2783516fc7f3Shx147065 if ((i >= 1) && (i <= MAX_PREFERENCE_NUM))
2784516fc7f3Shx147065 ret = B_TRUE;
2785516fc7f3Shx147065 exit0:
2786516fc7f3Shx147065 return (ret);
2787516fc7f3Shx147065 }
2788516fc7f3Shx147065
2789516fc7f3Shx147065 /*
2790516fc7f3Shx147065 * do_setprefer: Set network preferrence
2791516fc7f3Shx147065 */
2792516fc7f3Shx147065 /*ARGSUSED*/
2793516fc7f3Shx147065 static boolean_t
do_setprefer(int fd,int argc,char ** argv)2794516fc7f3Shx147065 do_setprefer(int fd, int argc, char **argv)
2795516fc7f3Shx147065 {
2796516fc7f3Shx147065 int rank = 0;
2797516fc7f3Shx147065
2798516fc7f3Shx147065 PRTDBG(("do_setprefer(%d, 0x%x)\n", argc, argv));
2799516fc7f3Shx147065 if (argc <= 0) {
2800516fc7f3Shx147065 do_print_usage();
2801516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
2802516fc7f3Shx147065 }
2803516fc7f3Shx147065 if (argc == 1) {
2804516fc7f3Shx147065 rank = 1;
2805516fc7f3Shx147065 } else {
2806516fc7f3Shx147065 if (is_prefer_rank_valid(argv[1]) == B_FALSE) {
2807516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: preference rank "
2808516fc7f3Shx147065 "should be an integer within 1-10\n"), gExecName);
2809516fc7f3Shx147065 return (B_FALSE);
2810516fc7f3Shx147065 }
2811516fc7f3Shx147065 rank = atoi(argv[1]);
2812516fc7f3Shx147065 }
2813516fc7f3Shx147065 return (set_prefer(gp_config_file, argv[0], rank));
2814516fc7f3Shx147065 }
2815516fc7f3Shx147065
2816516fc7f3Shx147065 static boolean_t
is_wepkeyindex_valid(const char * pbuf)2817516fc7f3Shx147065 is_wepkeyindex_valid(const char *pbuf)
2818516fc7f3Shx147065 {
2819516fc7f3Shx147065 int i;
2820516fc7f3Shx147065 boolean_t ret = B_FALSE;
2821516fc7f3Shx147065
2822516fc7f3Shx147065 for (i = 0; i < strlen(pbuf); i++) {
2823516fc7f3Shx147065 if (isdigit(pbuf[i]) == 0) {
2824516fc7f3Shx147065 ret = B_FALSE;
2825516fc7f3Shx147065 goto exit0;
2826516fc7f3Shx147065 }
2827516fc7f3Shx147065 }
2828516fc7f3Shx147065 i = atoi(pbuf);
2829516fc7f3Shx147065 if ((i >= 1) && (i <= MAX_NWEPKEYS))
2830516fc7f3Shx147065 ret = B_TRUE;
2831516fc7f3Shx147065 exit0:
2832516fc7f3Shx147065 return (ret);
2833516fc7f3Shx147065 }
2834516fc7f3Shx147065
2835516fc7f3Shx147065 static boolean_t
is_channel_valid(const char * pbuf)2836516fc7f3Shx147065 is_channel_valid(const char *pbuf)
2837516fc7f3Shx147065 {
2838516fc7f3Shx147065 int i;
2839516fc7f3Shx147065 boolean_t ret = B_FALSE;
2840516fc7f3Shx147065
2841516fc7f3Shx147065 for (i = 0; i < strlen(pbuf); i++) {
2842516fc7f3Shx147065 if (isdigit(pbuf[i]) == 0) {
2843516fc7f3Shx147065 ret = B_FALSE;
2844516fc7f3Shx147065 goto exit0;
2845516fc7f3Shx147065 }
2846516fc7f3Shx147065 }
2847516fc7f3Shx147065 i = atoi(pbuf);
2848516fc7f3Shx147065 if ((i >= 0) && (i <= MAX_CHANNEL_NUM))
2849516fc7f3Shx147065 ret = B_TRUE;
2850516fc7f3Shx147065 exit0:
2851516fc7f3Shx147065 return (ret);
2852516fc7f3Shx147065 }
2853516fc7f3Shx147065
2854516fc7f3Shx147065 static boolean_t
is_wepkey_valid(const char * pbuf,uint32_t length)2855516fc7f3Shx147065 is_wepkey_valid(const char *pbuf, uint32_t length)
2856516fc7f3Shx147065 {
2857516fc7f3Shx147065 int i;
2858516fc7f3Shx147065 boolean_t ret = B_FALSE;
2859516fc7f3Shx147065
2860516fc7f3Shx147065 switch (length) {
2861516fc7f3Shx147065 case 10:
2862516fc7f3Shx147065 case 26:
2863516fc7f3Shx147065 for (i = 0; i < length; i++) {
2864516fc7f3Shx147065 if (isxdigit(pbuf[i]) == 0) {
2865516fc7f3Shx147065 ret = B_FALSE;
2866516fc7f3Shx147065 goto exit0;
2867516fc7f3Shx147065 }
2868516fc7f3Shx147065 }
2869516fc7f3Shx147065 ret = B_TRUE;
2870516fc7f3Shx147065 break;
2871516fc7f3Shx147065 case 5:
2872516fc7f3Shx147065 case 13:
2873516fc7f3Shx147065 ret = B_TRUE;
2874516fc7f3Shx147065 break;
2875516fc7f3Shx147065 default:
2876516fc7f3Shx147065 ret = B_FALSE;
2877516fc7f3Shx147065 break;
2878516fc7f3Shx147065 }
2879516fc7f3Shx147065 exit0:
2880516fc7f3Shx147065 if (ret == B_FALSE) {
2881516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
2882516fc7f3Shx147065 "wepkey should be:\n"
2883516fc7f3Shx147065 "\t 40bits: 5 char or 10 hex digits.\n"
2884516fc7f3Shx147065 "\t 128bits: 13 char or 26 hex digits.\n"),
2885516fc7f3Shx147065 gExecName);
2886516fc7f3Shx147065 }
2887516fc7f3Shx147065 return (ret);
2888516fc7f3Shx147065 }
2889516fc7f3Shx147065
2890516fc7f3Shx147065 /*
2891516fc7f3Shx147065 * get_valid_wepkey: get an valid wepkey from stdin
2892516fc7f3Shx147065 */
2893516fc7f3Shx147065 static char *
get_valid_wepkey()2894516fc7f3Shx147065 get_valid_wepkey()
2895516fc7f3Shx147065 {
2896516fc7f3Shx147065 int i = 0;
2897516fc7f3Shx147065 char *buf = NULL;
2898516fc7f3Shx147065 uint8_t length = 0;
2899516fc7f3Shx147065 struct termios stored_settings;
2900516fc7f3Shx147065 struct termios new_settings;
2901516fc7f3Shx147065
2902516fc7f3Shx147065 PRTDBG(("get_valid_wepkey()\n"));
2903516fc7f3Shx147065 buf = safe_calloc(sizeof (char), MAX_KEY_LENGTH + 2);
2904516fc7f3Shx147065 /*
2905516fc7f3Shx147065 * Because we need to get single char from terminal, so we need to
2906516fc7f3Shx147065 * disable canonical mode and set buffer size to 1 tyte. And because
2907516fc7f3Shx147065 * wepkey should not be see by others, so we disable echo too.
2908516fc7f3Shx147065 */
2909516fc7f3Shx147065 (void) fflush(stdin);
2910516fc7f3Shx147065 (void) tcgetattr(0, &stored_settings);
2911516fc7f3Shx147065 new_settings = stored_settings;
2912516fc7f3Shx147065 new_settings.c_lflag &= (~ICANON);
2913516fc7f3Shx147065 new_settings.c_lflag &= (~ECHO);
2914516fc7f3Shx147065 new_settings.c_cc[VTIME] = 0;
2915516fc7f3Shx147065 new_settings.c_cc[VMIN] = 1;
2916516fc7f3Shx147065 /* Set new terminal attributes */
2917516fc7f3Shx147065 (void) tcsetattr(0, TCSANOW, &new_settings);
2918516fc7f3Shx147065 while (((buf[i++] = getchar()) != '\n') && (i < MAX_KEY_LENGTH + 1)) {
2919516fc7f3Shx147065 (void) putchar('*');
2920516fc7f3Shx147065 }
2921516fc7f3Shx147065 (void) putchar('\n');
2922516fc7f3Shx147065 /* Restore terminal attributes */
2923516fc7f3Shx147065 (void) tcsetattr(0, TCSANOW, &stored_settings);
2924516fc7f3Shx147065 (void) fflush(stdin);
2925516fc7f3Shx147065
2926516fc7f3Shx147065 if (buf[--i] != '\n') {
2927516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: wepkey length "
2928516fc7f3Shx147065 "exceeds 26 hex digits\n"), gExecName);
2929516fc7f3Shx147065 free(buf);
2930516fc7f3Shx147065 return (NULL);
2931516fc7f3Shx147065 }
2932516fc7f3Shx147065 /* Replace last char '\n' with '\0' */
2933516fc7f3Shx147065 buf[i] = '\0';
2934516fc7f3Shx147065 length = (uint8_t)i;
2935516fc7f3Shx147065 return ((is_wepkey_valid(buf, length) == B_TRUE)?
2936516fc7f3Shx147065 buf : NULL);
2937516fc7f3Shx147065 }
2938516fc7f3Shx147065
2939516fc7f3Shx147065 /*
2940516fc7f3Shx147065 * do_set_wepkey: Set parameters in wepkey, and call ioctl
2941516fc7f3Shx147065 */
2942516fc7f3Shx147065 static boolean_t
do_set_wepkey(int fd,const char * pbuf)2943516fc7f3Shx147065 do_set_wepkey(int fd, const char *pbuf)
2944516fc7f3Shx147065 {
2945516fc7f3Shx147065 int id = 0;
2946516fc7f3Shx147065 char i = 0;
2947516fc7f3Shx147065 uint8_t len = 0;
2948516fc7f3Shx147065 uint8_t length;
2949516fc7f3Shx147065 const char *wepkey = NULL;
2950516fc7f3Shx147065 char key[MAX_KEY_LENGTH] = {0};
2951516fc7f3Shx147065 unsigned int keytmp;
2952516fc7f3Shx147065 wl_wep_key_tab_t wepkey_tab;
2953516fc7f3Shx147065
2954516fc7f3Shx147065 PRTDBG(("do_set_wepkey(%d, \"%s\")\n", fd, pbuf));
2955516fc7f3Shx147065 if (!check_authority(AUTH_WEP)) {
2956516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
2957516fc7f3Shx147065 }
2958516fc7f3Shx147065 id = pbuf[strlen("wepkeyn") - 1] - '0';
2959516fc7f3Shx147065 wepkey = get_value(pbuf);
2960516fc7f3Shx147065 length = strlen(wepkey);
2961516fc7f3Shx147065 switch (length) {
2962516fc7f3Shx147065 case 10:
2963516fc7f3Shx147065 case 26:
2964516fc7f3Shx147065 for (i = 0; i < length / 2; i++) {
2965516fc7f3Shx147065 (void) sscanf(wepkey + i * 2, "%2x", &keytmp);
2966516fc7f3Shx147065 key[i] = (char)keytmp;
2967516fc7f3Shx147065 }
2968516fc7f3Shx147065 len = length / 2;
2969516fc7f3Shx147065 break;
2970516fc7f3Shx147065 case 5:
2971516fc7f3Shx147065 case 13:
2972516fc7f3Shx147065 (void) strlcpy(key, wepkey, MAX_KEY_LENGTH);
2973516fc7f3Shx147065 len = length;
2974516fc7f3Shx147065 break;
2975516fc7f3Shx147065 default:
2976516fc7f3Shx147065 PRTDBG(("do_set_wepkey: error pbuf size\n"));
2977516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
2978516fc7f3Shx147065 "wepkey should be:\n"
2979516fc7f3Shx147065 "\t 40bits: 5 char or 10 hex digits.\n"
2980516fc7f3Shx147065 "\t 128bits: 13 char or 26 hex digits.\n"),
2981516fc7f3Shx147065 gExecName);
2982516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
2983516fc7f3Shx147065 }
2984516fc7f3Shx147065
2985516fc7f3Shx147065 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab));
2986516fc7f3Shx147065 for (i = 0; i < MAX_NWEPKEYS; i++) {
2987516fc7f3Shx147065 wepkey_tab[i].wl_wep_operation = WL_NUL;
2988516fc7f3Shx147065 }
2989516fc7f3Shx147065
2990516fc7f3Shx147065 if (id > 0 && id <= MAX_NWEPKEYS) {
2991516fc7f3Shx147065 wepkey_tab[id-1].wl_wep_operation = WL_ADD;
2992516fc7f3Shx147065 wepkey_tab[id-1].wl_wep_length = len;
2993516fc7f3Shx147065 (void) memcpy(wepkey_tab[id-1].wl_wep_key, key, len);
2994516fc7f3Shx147065 } else {
2995516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: wepkeyindex "
2996516fc7f3Shx147065 "should be an integer within the range 1-4\n"), gExecName);
2997516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
2998516fc7f3Shx147065 }
2999516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &wepkey_tab, sizeof (wl_wep_key_tab_t));
3000516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_WEP_KEY_TAB,
3001516fc7f3Shx147065 sizeof (wl_wep_key_tab_t)));
3002516fc7f3Shx147065 }
3003516fc7f3Shx147065
3004516fc7f3Shx147065 /*
3005516fc7f3Shx147065 * get the committed wepkey. the return form is like wepkey1=*****;
3006516fc7f3Shx147065 */
3007516fc7f3Shx147065 /*ARGSUSED*/
3008516fc7f3Shx147065 static char *
get_commit_key(int fd,int argc,char ** argv)3009516fc7f3Shx147065 get_commit_key(int fd, int argc, char **argv)
3010516fc7f3Shx147065 {
3011516fc7f3Shx147065 int key;
3012516fc7f3Shx147065 int len;
3013516fc7f3Shx147065 char *wepkey = NULL;
3014516fc7f3Shx147065 char *wepkey_confirm = NULL;
3015516fc7f3Shx147065 char *pbuf = NULL;
3016516fc7f3Shx147065
3017516fc7f3Shx147065 key = atoi(argv[0]);
3018516fc7f3Shx147065 if (key <= 0 || key > MAX_NWEPKEYS) {
3019516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: wepkeyindex "
3020516fc7f3Shx147065 "should be an integer within the range 1-4\n"), gExecName);
3021516fc7f3Shx147065 goto exit0;
3022516fc7f3Shx147065 }
3023516fc7f3Shx147065 (void) printf(gettext("input wepkey%d:"), key);
3024516fc7f3Shx147065 wepkey = get_valid_wepkey();
3025516fc7f3Shx147065 if (wepkey == NULL) {
3026516fc7f3Shx147065 goto exit0;
3027516fc7f3Shx147065 }
3028516fc7f3Shx147065 (void) printf(gettext("confirm wepkey%d:"), key);
3029516fc7f3Shx147065 wepkey_confirm = get_valid_wepkey();
3030516fc7f3Shx147065 if (wepkey_confirm == NULL) {
3031516fc7f3Shx147065 free(wepkey);
3032516fc7f3Shx147065 goto exit0;
3033516fc7f3Shx147065 }
3034516fc7f3Shx147065 if (strcmp(wepkey, wepkey_confirm) != 0) {
3035516fc7f3Shx147065 free(wepkey);
3036516fc7f3Shx147065 free(wepkey_confirm);
3037516fc7f3Shx147065 (void) fprintf(stderr,
3038516fc7f3Shx147065 gettext("%s: wepkey: "
3039516fc7f3Shx147065 "two inputs are not identical\n"), gExecName);
3040516fc7f3Shx147065 goto exit0;
3041516fc7f3Shx147065 }
3042516fc7f3Shx147065 free(wepkey_confirm); /* wepkey_confirm is no longer used */
3043516fc7f3Shx147065
3044516fc7f3Shx147065 len = MAX_KEY_LENGTH + strlen("wepkey1=\n") + 1;
3045516fc7f3Shx147065 pbuf = safe_malloc(len);
3046516fc7f3Shx147065 safe_snprintf(pbuf, len, "%s%d=%s", "wepkey", key, wepkey);
3047516fc7f3Shx147065
3048516fc7f3Shx147065 free(wepkey); /* wepkey is no longer used */
3049516fc7f3Shx147065 return (pbuf);
3050516fc7f3Shx147065 exit0:
3051516fc7f3Shx147065 return (NULL);
3052516fc7f3Shx147065 }
3053516fc7f3Shx147065
3054516fc7f3Shx147065 /*
3055516fc7f3Shx147065 * do_wepkey: Get input from user, call do_set_wepkey
3056516fc7f3Shx147065 */
3057516fc7f3Shx147065 /*ARGSUSED*/
3058516fc7f3Shx147065 static boolean_t
do_wepkey(int fd,int argc,char ** argv)3059516fc7f3Shx147065 do_wepkey(int fd, int argc, char **argv)
3060516fc7f3Shx147065 {
3061516fc7f3Shx147065 char *pbuf;
3062516fc7f3Shx147065
3063516fc7f3Shx147065 PRTDBG(("do_wepkey(%d, 0x%x)\n", argc, argv));
3064516fc7f3Shx147065 assert(fd > 0);
3065516fc7f3Shx147065 if (argc <= 0) {
3066516fc7f3Shx147065 do_print_usage();
3067516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
3068516fc7f3Shx147065 }
3069516fc7f3Shx147065 if (argc > 1) {
3070516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3071516fc7f3Shx147065 "after 'setwepkey'\n"), gExecName);
3072516fc7f3Shx147065 }
3073516fc7f3Shx147065 pbuf = get_commit_key(fd, argc, argv);
3074516fc7f3Shx147065 if ((pbuf != NULL) && (do_set_wepkey(fd, pbuf) == B_TRUE)) {
3075516fc7f3Shx147065 free(pbuf);
3076516fc7f3Shx147065 return (B_TRUE);
3077516fc7f3Shx147065 }
3078516fc7f3Shx147065 free(pbuf);
3079516fc7f3Shx147065 return (B_FALSE);
3080516fc7f3Shx147065 }
3081516fc7f3Shx147065
3082516fc7f3Shx147065 /*ARGSUSED*/
3083516fc7f3Shx147065 static boolean_t
do_setprofwepkey(int fd,int argc,char ** argv)3084516fc7f3Shx147065 do_setprofwepkey(int fd, int argc, char **argv)
3085516fc7f3Shx147065 {
3086516fc7f3Shx147065 char *pbuf;
3087516fc7f3Shx147065 char *section_id = NULL;
3088516fc7f3Shx147065 section_t *p_section = NULL;
3089516fc7f3Shx147065 aelist_t *plist = NULL;
3090516fc7f3Shx147065
3091516fc7f3Shx147065 PRTDBG(("do_setprofwepkey(%d, 0x%x)\n", argc, argv));
3092516fc7f3Shx147065 if (argc < 2) {
3093516fc7f3Shx147065 do_print_usage();
3094516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
3095516fc7f3Shx147065 }
3096516fc7f3Shx147065 if (argc > 2) {
3097516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3098516fc7f3Shx147065 "after 'setprofwepkey'\n"), gExecName);
3099516fc7f3Shx147065 }
3100516fc7f3Shx147065
3101516fc7f3Shx147065 section_id = append_pa(argv[0]);
3102516fc7f3Shx147065 p_section = find_section(gp_wepkey_file, section_id);
3103516fc7f3Shx147065 free(section_id);
3104516fc7f3Shx147065 if (p_section == NULL) {
3105516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
3106516fc7f3Shx147065 "no such profile: '%s'\n"),
3107516fc7f3Shx147065 gExecName, argv[0]);
3108516fc7f3Shx147065 return (B_FALSE);
3109516fc7f3Shx147065 }
3110516fc7f3Shx147065
3111516fc7f3Shx147065 argc--;
3112516fc7f3Shx147065 argv++;
3113516fc7f3Shx147065 pbuf = get_commit_key(fd, argc, argv);
3114516fc7f3Shx147065 if (pbuf == NULL)
3115516fc7f3Shx147065 return (B_FALSE);
3116516fc7f3Shx147065 plist = p_section->list;
3117516fc7f3Shx147065 update_aelist(plist, pbuf);
3118516fc7f3Shx147065
3119516fc7f3Shx147065 return (B_TRUE);
3120516fc7f3Shx147065 }
3121516fc7f3Shx147065
3122516fc7f3Shx147065 /*
3123516fc7f3Shx147065 * do_wlanlist: Scan for wlanlist
3124516fc7f3Shx147065 */
3125516fc7f3Shx147065 /*ARGSUSED*/
3126516fc7f3Shx147065 static boolean_t
do_wlanlist(int fd,int argc,char ** argv)3127516fc7f3Shx147065 do_wlanlist(int fd, int argc, char **argv)
3128516fc7f3Shx147065 {
3129516fc7f3Shx147065 PRTDBG(("do_wlanlist(%d, 0x%x)\n", argc, argv));
3130516fc7f3Shx147065 assert(fd > 0);
3131516fc7f3Shx147065 if (argc > 0) {
3132516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3133516fc7f3Shx147065 "after 'scan'\n"), gExecName);
3134516fc7f3Shx147065 }
3135516fc7f3Shx147065 if (call_ioctl(fd, WLAN_COMMAND, WL_SCAN, 0) == B_FALSE) {
3136516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to scan\n"),
3137516fc7f3Shx147065 gExecName);
3138516fc7f3Shx147065 return (B_FALSE);
3139516fc7f3Shx147065 }
3140516fc7f3Shx147065 if (do_get_wlanlist(fd) == B_TRUE) {
3141516fc7f3Shx147065 print_gbuf(WLANLIST);
3142516fc7f3Shx147065 }
3143516fc7f3Shx147065 return (B_TRUE);
3144516fc7f3Shx147065 }
3145516fc7f3Shx147065
3146516fc7f3Shx147065 /*
3147516fc7f3Shx147065 * do_showstatus: show the basic status of the interface, including
3148516fc7f3Shx147065 * linkstauts, essid, encryption and signal strength.
3149516fc7f3Shx147065 */
3150516fc7f3Shx147065 /*ARGSUSED*/
3151516fc7f3Shx147065 static boolean_t
do_showstatus(int fd,int argc,char ** argv)3152516fc7f3Shx147065 do_showstatus(int fd, int argc, char **argv)
3153516fc7f3Shx147065 {
3154516fc7f3Shx147065 wl_rssi_t signal;
3155516fc7f3Shx147065 char *active_profile = NULL;
3156516fc7f3Shx147065
3157516fc7f3Shx147065 PRTDBG(("do_showstatus(%d, 0x%x)\n", argc, argv));
3158516fc7f3Shx147065 assert(fd > 0);
3159516fc7f3Shx147065
3160516fc7f3Shx147065 if (argc > 0) {
3161516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3162516fc7f3Shx147065 "after 'showstatus'\n"), gExecName);
3163516fc7f3Shx147065 }
3164516fc7f3Shx147065 if (do_get_linkstatus(fd) == B_TRUE) {
3165516fc7f3Shx147065 print_gbuf(LINKSTATUS);
3166516fc7f3Shx147065 if (*(wl_linkstatus_t *)(gbuf->wldp_buf) == WL_NOTCONNECTED) {
3167516fc7f3Shx147065 return (B_TRUE);
3168516fc7f3Shx147065 }
3169516fc7f3Shx147065 }
3170516fc7f3Shx147065 active_profile = find_active_profile(fd);
3171516fc7f3Shx147065 (void) printf("\tactive profile: %s\n",
3172516fc7f3Shx147065 active_profile ? active_profile : "none");
3173516fc7f3Shx147065 if (do_get_essid(fd) == B_TRUE) {
3174516fc7f3Shx147065 print_gbuf(ESSID);
3175516fc7f3Shx147065 }
3176516fc7f3Shx147065 if (do_get_bssid(fd) == B_TRUE) {
3177516fc7f3Shx147065 print_gbuf(BSSID);
3178516fc7f3Shx147065 }
3179516fc7f3Shx147065 if (do_get_encryption(fd) == B_TRUE) {
3180516fc7f3Shx147065 print_gbuf(ENCRYPTION);
3181516fc7f3Shx147065 }
3182516fc7f3Shx147065 if (do_get_signal(fd) == B_TRUE) {
3183516fc7f3Shx147065 signal = *(wl_rssi_t *)(gbuf->wldp_buf);
3184516fc7f3Shx147065 if (signal < 4) {
3185516fc7f3Shx147065 (void) printf("\tsignal strength: weak(%d)\n",
3186516fc7f3Shx147065 signal);
3187516fc7f3Shx147065 } else if ((signal >= 4) && (signal <= 11)) {
3188516fc7f3Shx147065 (void) printf("\tsignal strength: medium(%d)\n",
3189516fc7f3Shx147065 signal);
3190516fc7f3Shx147065 } else {
3191516fc7f3Shx147065 (void) printf("\tsignal strength: strong(%d)\n",
3192516fc7f3Shx147065 signal);
3193516fc7f3Shx147065 }
3194516fc7f3Shx147065 }
3195516fc7f3Shx147065
3196516fc7f3Shx147065 return (B_TRUE);
3197516fc7f3Shx147065 }
3198516fc7f3Shx147065
3199516fc7f3Shx147065
3200516fc7f3Shx147065 /*
3201516fc7f3Shx147065 * do_restoredef: Ask driver for loading default parameters
3202516fc7f3Shx147065 */
3203516fc7f3Shx147065 /*ARGSUSED*/
3204516fc7f3Shx147065 static boolean_t
do_restoredef(int fd,int argc,char ** argv)3205516fc7f3Shx147065 do_restoredef(int fd, int argc, char **argv)
3206516fc7f3Shx147065 {
3207516fc7f3Shx147065 PRTDBG(("do_restoredef(%d, 0x%x)\n", argc, argv));
3208516fc7f3Shx147065 assert(fd > 0);
3209516fc7f3Shx147065
3210516fc7f3Shx147065 if (argc > 0) {
3211516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3212516fc7f3Shx147065 "after 'restoredef'\n"), gExecName);
3213516fc7f3Shx147065 }
3214516fc7f3Shx147065 record_active_profile(NULL, RECORD_DEL);
3215516fc7f3Shx147065 if (call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0) == B_FALSE) {
3216516fc7f3Shx147065 return (B_FALSE);
3217516fc7f3Shx147065 } else {
3218516fc7f3Shx147065 return (B_TRUE);
3219516fc7f3Shx147065 }
3220516fc7f3Shx147065 }
3221516fc7f3Shx147065
3222516fc7f3Shx147065 /*
3223516fc7f3Shx147065 * do_disconnect: disconnect from the current connectted network
3224516fc7f3Shx147065 */
3225516fc7f3Shx147065 /*ARGSUSED*/
3226516fc7f3Shx147065 static boolean_t
do_disconnect(int fd,int argc,char ** argv)3227516fc7f3Shx147065 do_disconnect(int fd, int argc, char **argv)
3228516fc7f3Shx147065 {
3229516fc7f3Shx147065 PRTDBG(("do_disconnect(%d, 0x%x)\n", argc, argv));
3230516fc7f3Shx147065 assert(fd > 0);
3231516fc7f3Shx147065
3232516fc7f3Shx147065 if (argc > 0) {
3233516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3234516fc7f3Shx147065 "after 'disconnect'\n"), gExecName);
3235516fc7f3Shx147065 }
3236516fc7f3Shx147065 record_active_profile(NULL, RECORD_DEL);
3237516fc7f3Shx147065 if (call_ioctl(fd, WLAN_COMMAND, WL_DISASSOCIATE, 0) == B_FALSE) {
3238516fc7f3Shx147065 return (B_FALSE);
3239516fc7f3Shx147065 } else {
3240516fc7f3Shx147065 return (B_TRUE);
3241516fc7f3Shx147065 }
3242516fc7f3Shx147065 }
3243516fc7f3Shx147065
3244516fc7f3Shx147065 static boolean_t
do_set_essid(int fd,const char * arg)3245516fc7f3Shx147065 do_set_essid(int fd, const char *arg)
3246516fc7f3Shx147065 {
3247516fc7f3Shx147065 wl_essid_t essid;
3248516fc7f3Shx147065
3249516fc7f3Shx147065 PRTDBG(("do_set_essid(%d, \"%s\")\n", fd, arg));
3250516fc7f3Shx147065
3251516fc7f3Shx147065 /*
3252516fc7f3Shx147065 * a trick here: clean the active_profile flag
3253516fc7f3Shx147065 * in section{active_profile}
3254516fc7f3Shx147065 */
3255516fc7f3Shx147065 record_active_profile(NULL, RECORD_DEL);
3256516fc7f3Shx147065
3257516fc7f3Shx147065 (void) memset(&essid, 0x0, sizeof (essid));
3258516fc7f3Shx147065
3259516fc7f3Shx147065 if (arg == NULL || strcmp(arg, "") == 0) {
3260516fc7f3Shx147065 essid.wl_essid_length = 0;
3261516fc7f3Shx147065 essid.wl_essid_essid[0] = '\0';
3262516fc7f3Shx147065 } else {
3263516fc7f3Shx147065 essid.wl_essid_length = strlen(arg);
3264*0d2f4bc9Sff224033 if (essid.wl_essid_length > MAX_ESSID_LENGTH - 1) {
3265516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
3266516fc7f3Shx147065 "essid exceeds 32 bytes\n"), gExecName);
3267516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3268516fc7f3Shx147065 }
3269516fc7f3Shx147065 (void) strcpy(essid.wl_essid_essid, arg);
3270516fc7f3Shx147065 }
3271516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &essid, sizeof (wl_essid_t));
3272516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_ESSID, sizeof (wl_essid_t)));
3273516fc7f3Shx147065 }
3274516fc7f3Shx147065
3275516fc7f3Shx147065 static boolean_t
do_set_bsstype(int fd,const char * arg)3276516fc7f3Shx147065 do_set_bsstype(int fd, const char *arg)
3277516fc7f3Shx147065 {
3278516fc7f3Shx147065 wl_bss_type_t bsstype;
3279516fc7f3Shx147065
3280516fc7f3Shx147065 assert(arg != NULL);
3281516fc7f3Shx147065
3282516fc7f3Shx147065 PRTDBG(("do_set_bsstype(%d, \"%s\")\n", fd, arg));
3283516fc7f3Shx147065
3284516fc7f3Shx147065 (void) memset(&bsstype, 0xff, sizeof (bsstype));
3285516fc7f3Shx147065
3286516fc7f3Shx147065 if ((strcasecmp(arg, "BSS") == 0) ||
3287516fc7f3Shx147065 (strcasecmp(arg, "AP") == 0) ||
3288516fc7f3Shx147065 (strcasecmp(arg, "INFRASTRUCTURE") == 0)) {
3289516fc7f3Shx147065 bsstype = WL_BSS_BSS;
3290516fc7f3Shx147065 } else if ((strcasecmp(arg, "IBSS") == 0) ||
3291516fc7f3Shx147065 (strcasecmp(arg, "AD-HOC") == 0)) {
3292516fc7f3Shx147065 bsstype = WL_BSS_IBSS;
3293516fc7f3Shx147065 } else if (strcasecmp(arg, "AUTO") == 0) {
3294516fc7f3Shx147065 bsstype = WL_BSS_ANY;
3295516fc7f3Shx147065 } else {
3296516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: bsstype: "
3297516fc7f3Shx147065 "bss(ap,infrastructure) ibss(ad-hoc) or auto\n"),
3298516fc7f3Shx147065 gExecName);
3299516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3300516fc7f3Shx147065 }
3301516fc7f3Shx147065
3302516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &bsstype, sizeof (wl_bss_type_t));
3303516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_BSS_TYPE,
3304516fc7f3Shx147065 sizeof (wl_bss_type_t)));
3305516fc7f3Shx147065 }
3306516fc7f3Shx147065
3307516fc7f3Shx147065 static boolean_t
do_set_createibss(int fd,const char * arg)3308516fc7f3Shx147065 do_set_createibss(int fd, const char *arg)
3309516fc7f3Shx147065 {
3310516fc7f3Shx147065 wl_create_ibss_t create_ibss;
3311516fc7f3Shx147065
3312516fc7f3Shx147065 assert(arg != NULL);
3313516fc7f3Shx147065
3314516fc7f3Shx147065 PRTDBG(("do_set_createibss(%d, \"%s\")\n", fd, arg));
3315516fc7f3Shx147065
3316516fc7f3Shx147065 (void) memset(&create_ibss, 0x0, sizeof (create_ibss));
3317516fc7f3Shx147065
3318516fc7f3Shx147065 if (strcasecmp(arg, "YES") == 0) {
3319516fc7f3Shx147065 create_ibss = B_TRUE;
3320516fc7f3Shx147065 } else if (strcasecmp(arg, "NO") == 0) {
3321516fc7f3Shx147065 create_ibss = B_FALSE;
3322516fc7f3Shx147065 } else {
3323516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
3324516fc7f3Shx147065 "createibss: yes or no\n"), gExecName);
3325516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3326516fc7f3Shx147065 }
3327516fc7f3Shx147065
3328516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &create_ibss,
3329516fc7f3Shx147065 sizeof (wl_create_ibss_t));
3330516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_CREATE_IBSS,
3331516fc7f3Shx147065 sizeof (wl_create_ibss_t)));
3332516fc7f3Shx147065 }
3333516fc7f3Shx147065
3334516fc7f3Shx147065 static boolean_t
do_set_channel(int fd,const char * arg)3335516fc7f3Shx147065 do_set_channel(int fd, const char *arg)
3336516fc7f3Shx147065 {
3337516fc7f3Shx147065 wl_phy_conf_t phy_conf;
3338516fc7f3Shx147065
3339516fc7f3Shx147065 assert(arg != NULL);
3340516fc7f3Shx147065 PRTDBG(("do_set_channel(%d, \"%s\")\n", fd, arg));
3341516fc7f3Shx147065
3342516fc7f3Shx147065 (void) memset(&phy_conf, 0xff, sizeof (phy_conf));
3343516fc7f3Shx147065
3344516fc7f3Shx147065 if (is_channel_valid(arg) == B_FALSE) {
3345516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: channel No. "
3346516fc7f3Shx147065 "should be:\n"
3347516fc7f3Shx147065 "\t802.11a: 0-99\n"
3348516fc7f3Shx147065 "\t802.11b: 1-14\n"
3349516fc7f3Shx147065 "\t802.11g: 1-14\n"), gExecName);
3350516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3351516fc7f3Shx147065 }
3352516fc7f3Shx147065 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = atoi(arg);
3353516fc7f3Shx147065 PRTDBG(("channel=%d\n", phy_conf.wl_phy_dsss_conf.wl_dsss_channel));
3354516fc7f3Shx147065
3355516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &phy_conf, sizeof (wl_phy_conf_t));
3356516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_PHY_CONFIG,
3357516fc7f3Shx147065 sizeof (wl_phy_conf_t)));
3358516fc7f3Shx147065 }
3359516fc7f3Shx147065 /*
3360516fc7f3Shx147065 * is_rates_support: Querying driver about supported rates.
3361516fc7f3Shx147065 */
3362516fc7f3Shx147065 static boolean_t
is_rates_support(int fd,int num,uint8_t * rates)3363516fc7f3Shx147065 is_rates_support(int fd, int num, uint8_t *rates)
3364516fc7f3Shx147065 {
3365516fc7f3Shx147065 int rates_num = 0;
3366516fc7f3Shx147065 int i = 0, j = 0;
3367516fc7f3Shx147065 uint8_t value = 0;
3368516fc7f3Shx147065
3369516fc7f3Shx147065 assert((rates != NULL)&&(num != 0));
3370516fc7f3Shx147065 PRTDBG(("is_rates_support(%d, %d, 0x%x)\n", fd, num, rates));
3371516fc7f3Shx147065
3372516fc7f3Shx147065 if (call_ioctl(fd, WLAN_GET_PARAM, WL_SUPPORTED_RATES, 0)
3373516fc7f3Shx147065 == B_TRUE) {
3374516fc7f3Shx147065 rates_num = ((wl_rates_t *)(gbuf->wldp_buf))->wl_rates_num;
3375516fc7f3Shx147065
3376516fc7f3Shx147065 for (i = 0; i < num; i++) {
3377516fc7f3Shx147065 PRTDBG(("rates[%d] = %d\n", i, rates[i]));
3378516fc7f3Shx147065 for (j = 0; j < rates_num; j++) {
3379516fc7f3Shx147065 value = ((wl_rates_t *)gbuf->wldp_buf)
3380516fc7f3Shx147065 ->wl_rates_rates[j];
3381516fc7f3Shx147065 PRTDBG(("supported rates[%d]=%d\n", j, value));
3382516fc7f3Shx147065 if (value == rates[i]) {
3383516fc7f3Shx147065 break;
3384516fc7f3Shx147065 }
3385516fc7f3Shx147065 }
3386516fc7f3Shx147065 if (j == rates_num) {
3387516fc7f3Shx147065 if (rates[i] == 11) {
3388516fc7f3Shx147065 (void) fprintf(stderr,
3389516fc7f3Shx147065 gettext("%s: "
3390516fc7f3Shx147065 "rate 5.5M is not supported\n"),
3391516fc7f3Shx147065 gExecName);
3392516fc7f3Shx147065 } else {
3393516fc7f3Shx147065 (void) fprintf(stderr,
3394516fc7f3Shx147065 gettext("%s: "
3395516fc7f3Shx147065 "rate %dM is not supported\n"),
3396516fc7f3Shx147065 gExecName, rates[i]/2);
3397516fc7f3Shx147065 }
3398516fc7f3Shx147065 return (B_FALSE);
3399516fc7f3Shx147065 }
3400516fc7f3Shx147065 }
3401516fc7f3Shx147065 return (B_TRUE);
3402516fc7f3Shx147065 }
3403516fc7f3Shx147065 return (B_FALSE);
3404516fc7f3Shx147065 }
3405516fc7f3Shx147065
3406516fc7f3Shx147065 /*
3407516fc7f3Shx147065 *
3408516fc7f3Shx147065 */
3409516fc7f3Shx147065 static uint8_t
rates_convert(const char * rates)3410516fc7f3Shx147065 rates_convert(const char *rates)
3411516fc7f3Shx147065 {
3412516fc7f3Shx147065 int i;
3413516fc7f3Shx147065 uint8_t ret;
3414516fc7f3Shx147065
3415516fc7f3Shx147065 for (i = 0; i < WIFI_RATES_NUM; i++) {
3416516fc7f3Shx147065 if (strcmp(rates, wifi_rates_s[i].rates_s) == 0) {
3417516fc7f3Shx147065 ret = wifi_rates_s[i].rates_i;
3418516fc7f3Shx147065 break;
3419516fc7f3Shx147065 }
3420516fc7f3Shx147065 }
3421516fc7f3Shx147065 if (i == WIFI_RATES_NUM) {
3422516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
3423516fc7f3Shx147065 "invalid rates '%s'\n"), gExecName, rates);
3424516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3425516fc7f3Shx147065 }
3426516fc7f3Shx147065 return (ret);
3427516fc7f3Shx147065 }
3428516fc7f3Shx147065
3429516fc7f3Shx147065 /*
3430516fc7f3Shx147065 * get_rates: convert string value arg into uint8_t array,
3431516fc7f3Shx147065 * array length will be save into *len[i].
3432516fc7f3Shx147065 * for example:
3433516fc7f3Shx147065 * arg = "1,2,5.5,11"
3434516fc7f3Shx147065 * then after call, rates[] = {2,4,11,22} will be returned.
3435516fc7f3Shx147065 * and *len will equal to 4
3436516fc7f3Shx147065 */
3437516fc7f3Shx147065 static uint8_t *
get_rates(const char * arg,uint32_t * len)3438516fc7f3Shx147065 get_rates(const char *arg, uint32_t *len)
3439516fc7f3Shx147065 {
3440516fc7f3Shx147065 int i = 1, j = 0;
3441516fc7f3Shx147065 uint8_t *rates = NULL;
3442516fc7f3Shx147065 char *pnext = NULL;
3443516fc7f3Shx147065 char *token;
3444516fc7f3Shx147065 char *pstart;
3445516fc7f3Shx147065 char *pstart_bak;
3446516fc7f3Shx147065
3447516fc7f3Shx147065 assert(arg != NULL);
3448516fc7f3Shx147065
3449516fc7f3Shx147065 if (strlen(arg) == 0) {
3450516fc7f3Shx147065 PRTDBG(("get_rates: empty rates string\n"));
3451516fc7f3Shx147065 return (NULL);
3452516fc7f3Shx147065 }
3453516fc7f3Shx147065 PRTDBG(("get_rates(\"%s\", 0x%x)\n", arg, len));
3454516fc7f3Shx147065 pstart = safe_strdup(arg);
3455516fc7f3Shx147065 pstart_bak = pstart;
3456516fc7f3Shx147065 while ((pnext = strchr(pstart, ',')) != NULL) {
3457516fc7f3Shx147065 pstart = pnext + 1;
3458516fc7f3Shx147065 i++;
3459516fc7f3Shx147065 }
3460516fc7f3Shx147065 *len = i;
3461516fc7f3Shx147065 rates = safe_calloc(sizeof (uint8_t), i);
3462516fc7f3Shx147065
3463516fc7f3Shx147065 pstart = pstart_bak;
3464516fc7f3Shx147065 if ((token = strtok(pstart, ",")) != NULL) {
3465516fc7f3Shx147065 PRTDBG(("rates[0]: %s\n", token));
3466516fc7f3Shx147065 rates[0] = rates_convert(token);
3467516fc7f3Shx147065 i = 1;
3468516fc7f3Shx147065 while ((token = strtok(NULL, ",")) != NULL) {
3469516fc7f3Shx147065 PRTDBG(("rates[%d]: %s\n", i, token));
3470516fc7f3Shx147065 rates[i++] = rates_convert(token);
3471516fc7f3Shx147065 }
3472516fc7f3Shx147065 }
3473516fc7f3Shx147065 free(pstart_bak);
3474516fc7f3Shx147065 for (i = 0; i < *len; i++) {
3475516fc7f3Shx147065 for (j = 0; j < i; j++)
3476516fc7f3Shx147065 if (rates[j] == rates[i]) {
3477516fc7f3Shx147065 (void) fprintf(stderr,
3478516fc7f3Shx147065 gettext("%s: rates duplicated\n"),
3479516fc7f3Shx147065 gExecName);
3480516fc7f3Shx147065 free(rates);
3481516fc7f3Shx147065 return (NULL);
3482516fc7f3Shx147065 }
3483516fc7f3Shx147065 }
3484516fc7f3Shx147065
3485516fc7f3Shx147065 return (rates);
3486516fc7f3Shx147065 }
3487516fc7f3Shx147065
3488516fc7f3Shx147065 static boolean_t
do_set_rates(int fd,const char * arg)3489516fc7f3Shx147065 do_set_rates(int fd, const char *arg)
3490516fc7f3Shx147065 {
3491516fc7f3Shx147065 int i = 0;
3492516fc7f3Shx147065 uint32_t num = 0;
3493516fc7f3Shx147065 uint8_t *rates;
3494516fc7f3Shx147065
3495516fc7f3Shx147065 assert(arg != NULL);
3496516fc7f3Shx147065
3497516fc7f3Shx147065 PRTDBG(("do_set_rates(%d, \"%s\")\n", fd, arg));
3498516fc7f3Shx147065
3499516fc7f3Shx147065 rates = get_rates(arg, &num);
3500516fc7f3Shx147065 if ((rates == NULL) ||
3501516fc7f3Shx147065 is_rates_support(fd, num, rates) == B_FALSE) {
3502516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3503516fc7f3Shx147065 }
3504516fc7f3Shx147065
3505516fc7f3Shx147065 ((wl_rates_t *)(gbuf->wldp_buf))->wl_rates_num = num;
3506516fc7f3Shx147065 for (i = 0; i < num; i++) {
3507516fc7f3Shx147065 ((wl_rates_t *)gbuf->wldp_buf)->wl_rates_rates[i]
3508516fc7f3Shx147065 = rates[i];
3509516fc7f3Shx147065 }
3510516fc7f3Shx147065 free(rates);
3511516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_DESIRED_RATES,
3512516fc7f3Shx147065 offsetof(wl_rates_t, wl_rates_rates) +
3513516fc7f3Shx147065 num*sizeof (char)));
3514516fc7f3Shx147065 }
3515516fc7f3Shx147065
3516516fc7f3Shx147065 static boolean_t
do_set_powermode(int fd,const char * arg)3517516fc7f3Shx147065 do_set_powermode(int fd, const char *arg)
3518516fc7f3Shx147065 {
3519516fc7f3Shx147065 wl_ps_mode_t ps_mode;
3520516fc7f3Shx147065
3521516fc7f3Shx147065 assert(arg != NULL);
3522516fc7f3Shx147065
3523516fc7f3Shx147065 PRTDBG(("do_set_powermode(%d, \"%s\")\n", fd, arg));
3524516fc7f3Shx147065
3525516fc7f3Shx147065 (void) memset(&ps_mode, 0xff, sizeof (ps_mode));
3526516fc7f3Shx147065
3527516fc7f3Shx147065 if ((strcasecmp(arg, "OFF") == 0) ||
3528516fc7f3Shx147065 (strcasecmp(arg, "MPS") == 0) ||
3529516fc7f3Shx147065 (strcasecmp(arg, "FAST") == 0)) {
3530516fc7f3Shx147065 switch (arg[0]) {
3531516fc7f3Shx147065 case 'O':
3532516fc7f3Shx147065 case 'o':
3533516fc7f3Shx147065 ps_mode.wl_ps_mode = WL_PM_AM;
3534516fc7f3Shx147065 break;
3535516fc7f3Shx147065 case 'M':
3536516fc7f3Shx147065 case 'm':
3537516fc7f3Shx147065 ps_mode.wl_ps_mode = WL_PM_MPS;
3538516fc7f3Shx147065 break;
3539516fc7f3Shx147065 case 'F':
3540516fc7f3Shx147065 case 'f':
3541516fc7f3Shx147065 ps_mode.wl_ps_mode = WL_PM_FAST;
3542516fc7f3Shx147065 break;
3543516fc7f3Shx147065 default:
3544516fc7f3Shx147065 break;
3545516fc7f3Shx147065 }
3546516fc7f3Shx147065 } else {
3547516fc7f3Shx147065 (void) fprintf(stderr,
3548516fc7f3Shx147065 gettext("%s: powermode: off mps or fast\n"), gExecName);
3549516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3550516fc7f3Shx147065 }
3551516fc7f3Shx147065
3552516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &ps_mode, sizeof (wl_ps_mode_t));
3553516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_POWER_MODE,
3554516fc7f3Shx147065 sizeof (wl_ps_mode_t)));
3555516fc7f3Shx147065 }
3556516fc7f3Shx147065
3557516fc7f3Shx147065 static boolean_t
do_set_authmode(int fd,const char * arg)3558516fc7f3Shx147065 do_set_authmode(int fd, const char *arg)
3559516fc7f3Shx147065 {
3560516fc7f3Shx147065 wl_authmode_t auth_mode;
3561516fc7f3Shx147065
3562516fc7f3Shx147065 assert(arg != NULL);
3563516fc7f3Shx147065 PRTDBG(("do_set_authmode(%d, \"%s\")\n", fd, arg));
3564516fc7f3Shx147065
3565516fc7f3Shx147065 (void) memset(&auth_mode, 0xff, sizeof (auth_mode));
3566516fc7f3Shx147065 /* Mark */
3567516fc7f3Shx147065 if (strcasecmp(arg, "OPENSYSTEM") == 0) {
3568516fc7f3Shx147065 auth_mode = WL_OPENSYSTEM;
3569516fc7f3Shx147065 } else if (strcasecmp(arg, "SHARED_KEY") == 0) {
3570516fc7f3Shx147065 auth_mode = WL_SHAREDKEY;
3571516fc7f3Shx147065 } else {
3572516fc7f3Shx147065 (void) fprintf(stderr,
3573516fc7f3Shx147065 gettext("%s: authmode: "
3574516fc7f3Shx147065 "opensystem or shared_key\n"), gExecName);
3575516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3576516fc7f3Shx147065 }
3577516fc7f3Shx147065
3578516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &auth_mode, sizeof (wl_authmode_t));
3579516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_AUTH_MODE,
3580516fc7f3Shx147065 sizeof (wl_authmode_t)));
3581516fc7f3Shx147065 }
3582516fc7f3Shx147065
3583516fc7f3Shx147065 static boolean_t
do_set_encryption(int fd,const char * arg)3584516fc7f3Shx147065 do_set_encryption(int fd, const char *arg)
3585516fc7f3Shx147065 {
3586516fc7f3Shx147065 wl_encryption_t encryption;
3587516fc7f3Shx147065
3588516fc7f3Shx147065 assert(arg != NULL);
3589516fc7f3Shx147065 PRTDBG(("do_set_encryption(%d, \"%s\")\n", fd, arg));
3590516fc7f3Shx147065
3591516fc7f3Shx147065 (void) memset(&encryption, 0xff, sizeof (encryption));
3592516fc7f3Shx147065
3593516fc7f3Shx147065 if (strcasecmp(arg, "NONE") == 0) {
3594516fc7f3Shx147065 encryption = WL_NOENCRYPTION;
3595516fc7f3Shx147065 } else if (strcasecmp(arg, "WEP") == 0) {
3596516fc7f3Shx147065 encryption = WL_ENC_WEP;
3597516fc7f3Shx147065 } else {
3598516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: encryption: "
3599516fc7f3Shx147065 "none or wep\n"), gExecName);
3600516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3601516fc7f3Shx147065 }
3602516fc7f3Shx147065
3603516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &encryption, sizeof (wl_encryption_t));
3604516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_ENCRYPTION,
3605516fc7f3Shx147065 sizeof (wl_encryption_t)));
3606516fc7f3Shx147065 }
3607516fc7f3Shx147065
3608516fc7f3Shx147065 static boolean_t
do_set_wepkeyid(int fd,const char * arg)3609516fc7f3Shx147065 do_set_wepkeyid(int fd, const char *arg)
3610516fc7f3Shx147065 {
3611516fc7f3Shx147065 wl_wep_key_id_t wep_key_id;
3612516fc7f3Shx147065
3613516fc7f3Shx147065 assert(arg != NULL);
3614516fc7f3Shx147065 PRTDBG(("do_set_wepkeyid(%d, \"%s\")\n", fd, arg));
3615516fc7f3Shx147065
3616516fc7f3Shx147065 (void) memset(&wep_key_id, 0xff, sizeof (wep_key_id));
3617516fc7f3Shx147065 if (is_wepkeyindex_valid(arg) == B_FALSE) {
3618516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: wepkeyindex "
3619516fc7f3Shx147065 "should be an integer within the range 1-4\n"), gExecName);
3620516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3621516fc7f3Shx147065 }
3622516fc7f3Shx147065 wep_key_id = atoi(arg) - 1;
3623516fc7f3Shx147065
3624516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &wep_key_id, sizeof (wl_wep_key_id_t));
3625516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_WEP_KEY_ID,
3626516fc7f3Shx147065 sizeof (wl_wep_key_id_t)));
3627516fc7f3Shx147065 }
3628516fc7f3Shx147065
3629516fc7f3Shx147065 static boolean_t
do_set_radioon(int fd,const char * arg)3630516fc7f3Shx147065 do_set_radioon(int fd, const char *arg)
3631516fc7f3Shx147065 {
3632516fc7f3Shx147065 wl_radio_t radio;
3633516fc7f3Shx147065
3634516fc7f3Shx147065 assert(arg != NULL);
3635516fc7f3Shx147065 PRTDBG(("do_set_radioon(%d, \"%s\")\n", fd, arg));
3636516fc7f3Shx147065
3637516fc7f3Shx147065 (void) memset(&radio, 0xff, sizeof (radio));
3638516fc7f3Shx147065
3639516fc7f3Shx147065 if (strcasecmp(arg, "ON") == 0) {
3640516fc7f3Shx147065 radio = B_TRUE;
3641516fc7f3Shx147065 } else if (strcasecmp(arg, "OFF") == 0) {
3642516fc7f3Shx147065 radio = B_FALSE;
3643516fc7f3Shx147065 } else {
3644516fc7f3Shx147065 (void) fprintf(stderr,
3645516fc7f3Shx147065 gettext("%s: radio : on or off\n"), gExecName);
3646516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
3647516fc7f3Shx147065 }
3648516fc7f3Shx147065
3649516fc7f3Shx147065 (void) memmove(gbuf->wldp_buf, &radio, sizeof (wl_radio_t));
3650516fc7f3Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_RADIO, sizeof (wl_radio_t)));
3651516fc7f3Shx147065 }
3652516fc7f3Shx147065 /*
3653516fc7f3Shx147065 * print_gbuf: After each ioctl system call, gbuf will contain result, gbuf
3654516fc7f3Shx147065 * contents's format varies from each kind of ioctl system call.
3655516fc7f3Shx147065 */
3656516fc7f3Shx147065 static void
print_gbuf(config_item_t index)3657516fc7f3Shx147065 print_gbuf(config_item_t index)
3658516fc7f3Shx147065 {
3659516fc7f3Shx147065 int i = 0, j = 0;
3660516fc7f3Shx147065 uint32_t ess_num;
3661516fc7f3Shx147065 char **ess_argv;
3662516fc7f3Shx147065 uint32_t rates_num;
3663516fc7f3Shx147065 uint32_t subtype;
3664516fc7f3Shx147065 wl_bss_type_t bsstype;
3665516fc7f3Shx147065 wl_create_ibss_t createibss;
3666516fc7f3Shx147065 wl_ps_mode_t *ps_mode;
3667516fc7f3Shx147065 wl_authmode_t authmode;
3668516fc7f3Shx147065 wl_encryption_t encryption;
3669516fc7f3Shx147065 wl_wep_key_id_t wepkeyid;
3670516fc7f3Shx147065 wl_rssi_t signal;
3671516fc7f3Shx147065 wl_radio_t radioon;
3672516fc7f3Shx147065 wl_ess_conf_t **p_ess_conf;
3673516fc7f3Shx147065 wl_linkstatus_t linkstatus;
3674516fc7f3Shx147065 char format[256], *ntstr;
3675516fc7f3Shx147065 uint32_t maxessidlen = 0, nt = 0, cnt = 0;
3676516fc7f3Shx147065 int len;
3677516fc7f3Shx147065 uint8_t bssid[6];
3678516fc7f3Shx147065
3679516fc7f3Shx147065 PRTDBG(("print_gbuf(%d)\n", index));
3680516fc7f3Shx147065 assert(gbuf->wldp_length < MAX_BUF_LEN);
3681516fc7f3Shx147065
3682516fc7f3Shx147065 switch (index) {
3683516fc7f3Shx147065 case BSSID:
3684516fc7f3Shx147065 (void) printf("\tbssid: ");
3685516fc7f3Shx147065 (void) memset(bssid, 0, sizeof (bssid));
3686516fc7f3Shx147065 if (memcmp((uint8_t *)gbuf->wldp_buf, bssid, sizeof (bssid))
3687516fc7f3Shx147065 == 0) {
3688516fc7f3Shx147065 (void) printf("none\n");
3689516fc7f3Shx147065 break;
3690516fc7f3Shx147065 }
3691516fc7f3Shx147065 (void) memset(bssid, 0xff, sizeof (bssid));
3692516fc7f3Shx147065 if (memcmp((uint8_t *)gbuf->wldp_buf, bssid, sizeof (bssid))
3693516fc7f3Shx147065 == 0) {
3694516fc7f3Shx147065 (void) printf("none\n");
3695516fc7f3Shx147065 break;
3696516fc7f3Shx147065 }
3697516fc7f3Shx147065 for (i = 0; i < 5; i++)
3698516fc7f3Shx147065 (void) printf("%02x:", ((uint8_t *)gbuf->wldp_buf)[i]);
3699516fc7f3Shx147065 (void) printf("%02x\n", ((uint8_t *)gbuf->wldp_buf)[i]);
3700516fc7f3Shx147065 break;
3701516fc7f3Shx147065 case ESSID:
3702516fc7f3Shx147065 (void) printf("\tessid: %s\n", ((wl_essid_t *)(gbuf->wldp_buf))
3703516fc7f3Shx147065 ->wl_essid_essid);
3704516fc7f3Shx147065 break;
3705516fc7f3Shx147065 case BSSTYPE:
3706516fc7f3Shx147065 bsstype = *(wl_bss_type_t *)(gbuf->wldp_buf);
3707516fc7f3Shx147065 switch (bsstype) {
3708516fc7f3Shx147065 case WL_BSS_BSS:
3709516fc7f3Shx147065 (void) printf("\tbsstype: bss(ap, infrastructure)\n");
3710516fc7f3Shx147065 break;
3711516fc7f3Shx147065 case WL_BSS_IBSS:
3712516fc7f3Shx147065 (void) printf("\tbsstype: ibss(ad-hoc)\n");
3713516fc7f3Shx147065 break;
3714516fc7f3Shx147065 case WL_BSS_ANY:
3715516fc7f3Shx147065 (void) printf("\tbsstype: auto\n");
3716516fc7f3Shx147065 break;
3717516fc7f3Shx147065 default:
3718516fc7f3Shx147065 (void) fprintf(stderr,
3719516fc7f3Shx147065 gettext("%s: "
3720516fc7f3Shx147065 "invalid bsstype value\n"), gExecName);
3721516fc7f3Shx147065 }
3722516fc7f3Shx147065 break;
3723516fc7f3Shx147065 case CREATEIBSS:
3724516fc7f3Shx147065 createibss = *(wl_create_ibss_t *)(gbuf->wldp_buf);
3725516fc7f3Shx147065 switch (createibss) {
3726516fc7f3Shx147065 case B_TRUE:
3727516fc7f3Shx147065 (void) printf("\tcreateibss: yes\n");
3728516fc7f3Shx147065 break;
3729516fc7f3Shx147065 case B_FALSE:
3730516fc7f3Shx147065 (void) printf("\tcreateibss: no\n");
3731516fc7f3Shx147065 break;
3732516fc7f3Shx147065 default:
3733516fc7f3Shx147065 (void) fprintf(stderr,
3734516fc7f3Shx147065 gettext("%s: "
3735516fc7f3Shx147065 "invalid createibss value\n"), gExecName);
3736516fc7f3Shx147065 }
3737516fc7f3Shx147065 break;
3738516fc7f3Shx147065 case CHANNEL:
3739516fc7f3Shx147065 subtype = ((wl_fhss_t *)(gbuf->wldp_buf))->wl_fhss_subtype;
3740516fc7f3Shx147065 switch (subtype) {
3741516fc7f3Shx147065 case WL_FHSS:
3742516fc7f3Shx147065 case WL_DSSS:
3743516fc7f3Shx147065 case WL_IRBASE:
3744516fc7f3Shx147065 case WL_HRDS:
3745516fc7f3Shx147065 case WL_ERP:
3746516fc7f3Shx147065 (void) printf("\tchannel: %d\n", ((wl_fhss_t *)
3747516fc7f3Shx147065 (gbuf->wldp_buf))->wl_fhss_channel);
3748516fc7f3Shx147065 break;
3749516fc7f3Shx147065 case WL_OFDM:
3750516fc7f3Shx147065 (void) printf("\tchannel: %d\n", ((wl_ofdm_t *)
3751516fc7f3Shx147065 (gbuf->wldp_buf))
3752516fc7f3Shx147065 ->wl_ofdm_frequency);
3753516fc7f3Shx147065 break;
3754516fc7f3Shx147065 default:
3755516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
3756516fc7f3Shx147065 "invalid subtype\n"), gExecName);
3757516fc7f3Shx147065 break;
3758516fc7f3Shx147065 }
3759516fc7f3Shx147065 break;
3760516fc7f3Shx147065 case RATES:
3761516fc7f3Shx147065 rates_num = ((wl_rates_t *)(gbuf->wldp_buf))->wl_rates_num;
3762516fc7f3Shx147065 (void) printf("\trates: ");
3763516fc7f3Shx147065 for (i = 0; i < rates_num; i++) {
3764516fc7f3Shx147065 char rate;
3765516fc7f3Shx147065 rate = ((wl_rates_t *)gbuf->wldp_buf)
3766516fc7f3Shx147065 ->wl_rates_rates[i];
3767516fc7f3Shx147065 if (rate == WL_RATE_5_5M)
3768516fc7f3Shx147065 (void) printf("5.5");
3769516fc7f3Shx147065 else
3770516fc7f3Shx147065 (void) printf("%d", (uint8_t)(rate / 2));
3771516fc7f3Shx147065
3772516fc7f3Shx147065 if (i == (rates_num - 1))
3773516fc7f3Shx147065 (void) printf("\n");
3774516fc7f3Shx147065 else
3775516fc7f3Shx147065 (void) printf(",");
3776516fc7f3Shx147065 }
3777516fc7f3Shx147065 break;
3778516fc7f3Shx147065 case POWERMODE:
3779516fc7f3Shx147065 ps_mode = (wl_ps_mode_t *)(gbuf->wldp_buf);
3780516fc7f3Shx147065 switch (ps_mode->wl_ps_mode) {
3781516fc7f3Shx147065 case WL_PM_AM:
3782516fc7f3Shx147065 (void) printf("\tpowermode: off\n");
3783516fc7f3Shx147065 break;
3784516fc7f3Shx147065 case WL_PM_MPS:
3785516fc7f3Shx147065 (void) printf("\tpowermode: mps\n");
3786516fc7f3Shx147065 break;
3787516fc7f3Shx147065 case WL_PM_FAST:
3788516fc7f3Shx147065 (void) printf("\tpowermode: fast\n");
3789516fc7f3Shx147065 break;
3790516fc7f3Shx147065 default:
3791516fc7f3Shx147065 (void) fprintf(stderr,
3792516fc7f3Shx147065 gettext("%s: "
3793516fc7f3Shx147065 "invalid powermode value\n"), gExecName);
3794516fc7f3Shx147065 break;
3795516fc7f3Shx147065 }
3796516fc7f3Shx147065 break;
3797516fc7f3Shx147065 case AUTHMODE:
3798516fc7f3Shx147065 authmode = *(wl_authmode_t *)(gbuf->wldp_buf);
3799516fc7f3Shx147065 switch (authmode) {
3800516fc7f3Shx147065 case WL_OPENSYSTEM:
3801516fc7f3Shx147065 (void) printf("\tauthmode: opensystem\n");
3802516fc7f3Shx147065 break;
3803516fc7f3Shx147065 case WL_SHAREDKEY:
3804516fc7f3Shx147065 (void) printf("\tauthmode: shared_key\n");
3805516fc7f3Shx147065 break;
3806516fc7f3Shx147065 default:
3807516fc7f3Shx147065 (void) fprintf(stderr,
3808516fc7f3Shx147065 gettext("%s: "
3809516fc7f3Shx147065 "invalid authmode value\n"), gExecName);
3810516fc7f3Shx147065 break;
3811516fc7f3Shx147065 }
3812516fc7f3Shx147065 break;
3813516fc7f3Shx147065 case ENCRYPTION:
3814516fc7f3Shx147065 encryption = *(wl_encryption_t *)(gbuf->wldp_buf);
3815516fc7f3Shx147065 switch (encryption) {
3816516fc7f3Shx147065 case WL_NOENCRYPTION:
3817516fc7f3Shx147065 (void) printf("\tencryption: none\n");
3818516fc7f3Shx147065 break;
3819516fc7f3Shx147065 case WL_ENC_WEP:
3820516fc7f3Shx147065 (void) printf("\tencryption: wep\n");
3821516fc7f3Shx147065 break;
3822516fc7f3Shx147065 default:
3823516fc7f3Shx147065 (void) fprintf(stderr,
3824516fc7f3Shx147065 gettext("%s: "
3825516fc7f3Shx147065 "invalid encryption value\n"), gExecName);
3826516fc7f3Shx147065 break;
3827516fc7f3Shx147065 }
3828516fc7f3Shx147065 break;
3829516fc7f3Shx147065 case WEPKEYID:
3830516fc7f3Shx147065 wepkeyid = *(wl_wep_key_id_t *)(gbuf->wldp_buf);
3831516fc7f3Shx147065 (void) printf("\twepkeyindex: %d\n", wepkeyid + 1);
3832516fc7f3Shx147065 break;
3833516fc7f3Shx147065 case SIGNAL:
3834516fc7f3Shx147065 signal = *(wl_rssi_t *)(gbuf->wldp_buf);
3835516fc7f3Shx147065 (void) printf("\tsignal: %d\n", signal);
3836516fc7f3Shx147065 break;
3837516fc7f3Shx147065 case RADIOON:
3838516fc7f3Shx147065 radioon = *(wl_radio_t *)(gbuf->wldp_buf);
3839516fc7f3Shx147065 switch (radioon) {
3840516fc7f3Shx147065 case B_TRUE:
3841516fc7f3Shx147065 (void) printf("\tradio: on\n");
3842516fc7f3Shx147065 break;
3843516fc7f3Shx147065 case B_FALSE:
3844516fc7f3Shx147065 (void) printf("\tradio: off\n");
3845516fc7f3Shx147065 break;
3846516fc7f3Shx147065 default: /* Mark */
3847516fc7f3Shx147065 (void) fprintf(stderr,
3848516fc7f3Shx147065 gettext("%s: "
3849516fc7f3Shx147065 "invalid radioon value\n"), gExecName);
3850516fc7f3Shx147065 }
3851516fc7f3Shx147065 break;
3852516fc7f3Shx147065 case LINKSTATUS:
3853516fc7f3Shx147065 linkstatus = *(wl_linkstatus_t *)(gbuf->wldp_buf);
3854516fc7f3Shx147065 switch (linkstatus) {
3855516fc7f3Shx147065 case WL_CONNECTED:
3856516fc7f3Shx147065 (void) printf("\tlinkstatus: connected\n");
3857516fc7f3Shx147065 break;
3858516fc7f3Shx147065 case WL_NOTCONNECTED:
3859516fc7f3Shx147065 (void) printf("\tlinkstatus: not connected\n");
3860516fc7f3Shx147065 break;
3861516fc7f3Shx147065 default: /* Mark */
3862516fc7f3Shx147065 (void) fprintf(stderr,
3863516fc7f3Shx147065 gettext("%s: "
3864516fc7f3Shx147065 "invalid linkstatus value\n"), gExecName);
3865516fc7f3Shx147065 }
3866516fc7f3Shx147065 break;
3867516fc7f3Shx147065 case WLANLIST:
3868516fc7f3Shx147065 ess_num = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num;
3869516fc7f3Shx147065 ess_argv = safe_calloc(sizeof (char *), ess_num);
3870516fc7f3Shx147065 p_ess_conf = safe_calloc(sizeof (wl_ess_conf_t *), ess_num);
3871516fc7f3Shx147065 for (i = 0; i < ess_num; i++) {
3872516fc7f3Shx147065 p_ess_conf[i] = ((wl_ess_list_t *)gbuf->wldp_buf)
3873516fc7f3Shx147065 ->wl_ess_list_ess + i;
3874516fc7f3Shx147065 maxessidlen = (maxessidlen >
3875516fc7f3Shx147065 strlen(p_ess_conf[i]
3876516fc7f3Shx147065 ->wl_ess_conf_essid.wl_essid_essid) ?
3877516fc7f3Shx147065 maxessidlen :
3878516fc7f3Shx147065 strlen(p_ess_conf[i]
3879516fc7f3Shx147065 ->wl_ess_conf_essid.wl_essid_essid));
3880516fc7f3Shx147065 }
3881516fc7f3Shx147065 /*
3882516fc7f3Shx147065 * construct the output format.
3883516fc7f3Shx147065 */
3884516fc7f3Shx147065 if ((nt = (maxessidlen / 8 + 1)) > 4)
3885516fc7f3Shx147065 nt = 4;
3886516fc7f3Shx147065 len = snprintf(format, sizeof (format), gettext("essid"));
3887516fc7f3Shx147065 ntstr = construct_format(nt);
3888516fc7f3Shx147065 assert(ntstr != NULL);
3889516fc7f3Shx147065 len += snprintf(format + len, sizeof (format) - len, "%s",
3890516fc7f3Shx147065 ntstr);
3891516fc7f3Shx147065 len += snprintf(format + len, sizeof (format) - len,
3892516fc7f3Shx147065 gettext("bssid\t\t type\t\tencryption\tsignallevel\n"));
3893516fc7f3Shx147065
3894516fc7f3Shx147065 if ((len <= 0) || (len > sizeof (format) - 1)) {
3895516fc7f3Shx147065 (void) printf("essid\t\t\t\tbssid\t\t type\t\t"
3896516fc7f3Shx147065 "encryption\tsignallevel\n");
3897516fc7f3Shx147065 } else {
3898516fc7f3Shx147065 (void) printf("%s", format);
3899516fc7f3Shx147065 }
3900516fc7f3Shx147065
3901516fc7f3Shx147065 for (i = 0; i < ess_num; i++) {
3902516fc7f3Shx147065 ess_argv[i] = safe_malloc(MAX_SCANBUF_LEN);
3903516fc7f3Shx147065 safe_snprintf(ess_argv[i], MAX_SCANBUF_LEN,
3904516fc7f3Shx147065 "%s%c%02x:%02x:%02x:%02x:%02x:%02x%c%s",
3905516fc7f3Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid,
3906516fc7f3Shx147065 ',',
3907516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[0]),
3908516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[1]),
3909516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[2]),
3910516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[3]),
3911516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[4]),
3912516fc7f3Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[5]), ',',
3913516fc7f3Shx147065 (p_ess_conf[i]->wl_ess_conf_wepenabled ==
3914516fc7f3Shx147065 B_TRUE ? "wep":"none"));
3915516fc7f3Shx147065 len = strlen(p_ess_conf[i]->wl_ess_conf_essid.
3916516fc7f3Shx147065 wl_essid_essid);
3917516fc7f3Shx147065 cnt = nt - (min(len /8 + 1, 4) - 1);
3918516fc7f3Shx147065 ntstr = construct_format(cnt);
3919516fc7f3Shx147065 assert(ntstr != NULL);
3920516fc7f3Shx147065 (void) printf("%s%s", p_ess_conf[i]->wl_ess_conf_essid.
3921516fc7f3Shx147065 wl_essid_essid, ntstr);
3922516fc7f3Shx147065 free(ntstr);
3923516fc7f3Shx147065 for (j = 0; j < 5; j++) {
3924516fc7f3Shx147065 (void) printf("%02x:", (uint8_t)(p_ess_conf[i]
3925516fc7f3Shx147065 ->wl_ess_conf_bssid[j]));
3926516fc7f3Shx147065 }
3927516fc7f3Shx147065 (void) printf("%02x ", (uint8_t)(p_ess_conf[i]
3928516fc7f3Shx147065 ->wl_ess_conf_bssid[j]));
3929516fc7f3Shx147065
3930516fc7f3Shx147065 if (p_ess_conf[i]->wl_ess_conf_bsstype ==
3931516fc7f3Shx147065 WL_BSS_BSS)
3932516fc7f3Shx147065 (void) printf("access point");
3933516fc7f3Shx147065 else
3934516fc7f3Shx147065 (void) printf("ad-hoc");
3935516fc7f3Shx147065 if (p_ess_conf[i]->wl_ess_conf_wepenabled ==
3936516fc7f3Shx147065 WL_ENC_WEP)
3937516fc7f3Shx147065 (void) printf("\twep\t");
3938516fc7f3Shx147065 else
3939516fc7f3Shx147065 (void) printf("\tnone\t");
3940516fc7f3Shx147065 (void) printf("\t%d\n", p_ess_conf[i]->wl_ess_conf_sl);
3941516fc7f3Shx147065 }
3942516fc7f3Shx147065 add_to_history(gp_config_file, ess_num, ess_argv);
3943516fc7f3Shx147065 free(p_ess_conf);
3944516fc7f3Shx147065 for (i = 0; i < ess_num; i++) {
3945516fc7f3Shx147065 free(ess_argv[i]);
3946516fc7f3Shx147065 }
3947516fc7f3Shx147065 free(ess_argv);
3948516fc7f3Shx147065 break;
3949516fc7f3Shx147065 default:
3950516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
3951516fc7f3Shx147065 "invalid parameter type\n"), gExecName);
3952516fc7f3Shx147065 break;
3953516fc7f3Shx147065 }
3954516fc7f3Shx147065 }
3955516fc7f3Shx147065 /*
3956516fc7f3Shx147065 * do_get_xxx: will send ioctl to driver, then the driver will fill gbuf
3957516fc7f3Shx147065 * with related value. gbuf has a format of wldp_t structure.
3958516fc7f3Shx147065 */
3959516fc7f3Shx147065 static boolean_t
do_get_bssid(int fd)3960516fc7f3Shx147065 do_get_bssid(int fd)
3961516fc7f3Shx147065 {
3962516fc7f3Shx147065 PRTDBG(("do_get_bssid(%d)\n", fd));
3963516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_BSSID, 0));
3964516fc7f3Shx147065 }
3965516fc7f3Shx147065
3966516fc7f3Shx147065 static boolean_t
do_get_essid(int fd)3967516fc7f3Shx147065 do_get_essid(int fd)
3968516fc7f3Shx147065 {
3969516fc7f3Shx147065 PRTDBG(("do_get_essid(%d)\n", fd));
3970516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_ESSID, 0));
3971516fc7f3Shx147065 }
3972516fc7f3Shx147065
3973516fc7f3Shx147065 static boolean_t
do_get_bsstype(int fd)3974516fc7f3Shx147065 do_get_bsstype(int fd)
3975516fc7f3Shx147065 {
3976516fc7f3Shx147065 PRTDBG(("do_get_bsstype(%d)\n", fd));
3977516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_BSS_TYPE, 0));
3978516fc7f3Shx147065 }
3979516fc7f3Shx147065
3980516fc7f3Shx147065 static boolean_t
do_get_createibss(int fd)3981516fc7f3Shx147065 do_get_createibss(int fd)
3982516fc7f3Shx147065 {
3983516fc7f3Shx147065 PRTDBG(("do_get_createibss(%d)\n", fd));
3984516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_CREATE_IBSS, 0));
3985516fc7f3Shx147065 }
3986516fc7f3Shx147065
3987516fc7f3Shx147065 static boolean_t
do_get_channel(int fd)3988516fc7f3Shx147065 do_get_channel(int fd)
3989516fc7f3Shx147065 {
3990516fc7f3Shx147065 PRTDBG(("do_get_channel(%d)\n", fd));
3991516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_PHY_CONFIG, 0));
3992516fc7f3Shx147065 }
3993516fc7f3Shx147065
3994516fc7f3Shx147065 static boolean_t
do_get_wlanlist(int fd)3995516fc7f3Shx147065 do_get_wlanlist(int fd)
3996516fc7f3Shx147065 {
3997516fc7f3Shx147065 PRTDBG(("do_get_wlanlist(%d)\n", fd));
3998516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_ESS_LIST, 0));
3999516fc7f3Shx147065 }
4000516fc7f3Shx147065
4001516fc7f3Shx147065 static boolean_t
do_get_linkstatus(int fd)4002516fc7f3Shx147065 do_get_linkstatus(int fd)
4003516fc7f3Shx147065 {
4004516fc7f3Shx147065 PRTDBG(("do_get_linkstauts(%d)\n", fd));
4005516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_LINKSTATUS, 0));
4006516fc7f3Shx147065 }
4007516fc7f3Shx147065
4008516fc7f3Shx147065 static boolean_t
do_get_rates(int fd)4009516fc7f3Shx147065 do_get_rates(int fd)
4010516fc7f3Shx147065 {
4011516fc7f3Shx147065 PRTDBG(("do_get_rates(%d)\n", fd));
4012516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_DESIRED_RATES, 0));
4013516fc7f3Shx147065 }
4014516fc7f3Shx147065
4015516fc7f3Shx147065 static boolean_t
do_get_powermode(int fd)4016516fc7f3Shx147065 do_get_powermode(int fd)
4017516fc7f3Shx147065 {
4018516fc7f3Shx147065 PRTDBG(("do_get_powermode(%d)\n", fd));
4019516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_POWER_MODE, 0));
4020516fc7f3Shx147065 }
4021516fc7f3Shx147065
4022516fc7f3Shx147065 static boolean_t
do_get_authmode(int fd)4023516fc7f3Shx147065 do_get_authmode(int fd)
4024516fc7f3Shx147065 {
4025516fc7f3Shx147065 PRTDBG(("do_get_authmode(%d)\n", fd));
4026516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_AUTH_MODE, 0));
4027516fc7f3Shx147065 }
4028516fc7f3Shx147065
4029516fc7f3Shx147065 static boolean_t
do_get_encryption(int fd)4030516fc7f3Shx147065 do_get_encryption(int fd)
4031516fc7f3Shx147065 {
4032516fc7f3Shx147065 PRTDBG(("do_get_encryption(%d)\n", fd));
4033516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_ENCRYPTION, 0));
4034516fc7f3Shx147065 }
4035516fc7f3Shx147065
4036516fc7f3Shx147065 static boolean_t
do_get_wepkeyid(int fd)4037516fc7f3Shx147065 do_get_wepkeyid(int fd)
4038516fc7f3Shx147065 {
4039516fc7f3Shx147065 PRTDBG(("do_get_wepkeyid(%d)\n", fd));
4040516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_WEP_KEY_ID, 0));
4041516fc7f3Shx147065 }
4042516fc7f3Shx147065 static boolean_t
do_get_signal(int fd)4043516fc7f3Shx147065 do_get_signal(int fd)
4044516fc7f3Shx147065 {
4045516fc7f3Shx147065 PRTDBG(("do_get_signal(%d)\n", fd));
4046516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_RSSI, 0));
4047516fc7f3Shx147065 }
4048516fc7f3Shx147065
4049516fc7f3Shx147065 static boolean_t
do_get_radioon(int fd)4050516fc7f3Shx147065 do_get_radioon(int fd)
4051516fc7f3Shx147065 {
4052516fc7f3Shx147065 PRTDBG(("do_get_radioon(%d)\n", fd));
4053516fc7f3Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_RADIO, 0));
4054516fc7f3Shx147065 }
4055516fc7f3Shx147065
4056516fc7f3Shx147065 /*
4057516fc7f3Shx147065 * param has two kinds of forms:
4058516fc7f3Shx147065 * 'wepkeyn=*****' (when equalflag == B_TRUE),
4059516fc7f3Shx147065 * 'wepkeyn' (when equalflag == B_FALSE)
4060516fc7f3Shx147065 */
4061516fc7f3Shx147065 static boolean_t
param_is_wepkey(char * param,boolean_t equalflag)4062516fc7f3Shx147065 param_is_wepkey(char *param, boolean_t equalflag)
4063516fc7f3Shx147065 {
4064516fc7f3Shx147065 if ((equalflag == B_FALSE) &&
4065516fc7f3Shx147065 (strcmp(param, "wepkey1") == 0) ||
4066516fc7f3Shx147065 (strcmp(param, "wepkey2") == 0) ||
4067516fc7f3Shx147065 (strcmp(param, "wepkey3") == 0) ||
4068516fc7f3Shx147065 (strcmp(param, "wepkey4") == 0))
4069516fc7f3Shx147065 return (B_TRUE);
4070516fc7f3Shx147065 else if ((equalflag == B_TRUE) &&
4071516fc7f3Shx147065 (strncmp(param, "wepkey1=", strlen("wepkey1="))) == 0 ||
4072516fc7f3Shx147065 (strncmp(param, "wepkey2=", strlen("wepkey2="))) == 0 ||
4073516fc7f3Shx147065 (strncmp(param, "wepkey3=", strlen("wepkey3="))) == 0 ||
4074516fc7f3Shx147065 (strncmp(param, "wepkey4=", strlen("wepkey4="))) == 0)
4075516fc7f3Shx147065 return (B_TRUE);
4076516fc7f3Shx147065 else
4077516fc7f3Shx147065 return (B_FALSE);
4078516fc7f3Shx147065 }
4079516fc7f3Shx147065
4080516fc7f3Shx147065 /*
4081516fc7f3Shx147065 * update/add items in the profile
4082516fc7f3Shx147065 */
4083516fc7f3Shx147065 static boolean_t
items_in_profile(aelist_t * cplist,aelist_t * wplist,int argc,char ** argv)4084516fc7f3Shx147065 items_in_profile(aelist_t *cplist, aelist_t *wplist, int argc, char **argv)
4085516fc7f3Shx147065 {
4086516fc7f3Shx147065 int i = 0, j = 0;
4087516fc7f3Shx147065 char *param;
4088516fc7f3Shx147065 char *pequal;
4089516fc7f3Shx147065 const char *wepkey;
4090516fc7f3Shx147065
4091516fc7f3Shx147065 for (i = 0; i < argc; i++) {
4092516fc7f3Shx147065 if (param_is_wepkey(argv[i], B_TRUE) == B_TRUE) {
4093516fc7f3Shx147065 wepkey = get_value(argv[i]);
4094516fc7f3Shx147065 if (value_is_valid(WEPKEY, wepkey) == B_FALSE) {
4095516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4096516fc7f3Shx147065 "invalid value '%s' for parameter "
4097516fc7f3Shx147065 "'wepkey'\n"), gExecName, wepkey);
4098516fc7f3Shx147065 return (B_FALSE);
4099516fc7f3Shx147065 }
4100516fc7f3Shx147065 update_aelist(wplist, argv[i]);
4101516fc7f3Shx147065 continue;
4102516fc7f3Shx147065 }
4103516fc7f3Shx147065 param = safe_strdup(argv[i]);
4104516fc7f3Shx147065 pequal = strchr(param, '=');
4105516fc7f3Shx147065 if (pequal == NULL) {
4106516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4107516fc7f3Shx147065 "invalid argument '%s', use "
4108516fc7f3Shx147065 "parameter=value'\n"),
4109516fc7f3Shx147065 gExecName, argv[i]);
4110516fc7f3Shx147065 free(param);
4111516fc7f3Shx147065 return (B_FALSE);
4112516fc7f3Shx147065 }
4113516fc7f3Shx147065
4114516fc7f3Shx147065 *pequal++ = '\0';
4115516fc7f3Shx147065 for (j = 0; j < N_GS_FUNC; j++) {
4116516fc7f3Shx147065 if (strcmp(param, do_gs_func[j].cmd) == 0) {
4117516fc7f3Shx147065 break;
4118516fc7f3Shx147065 }
4119516fc7f3Shx147065 }
4120516fc7f3Shx147065 if (j == N_GS_FUNC) {
4121516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4122516fc7f3Shx147065 "unrecognized parameter '%s'\n"),
4123516fc7f3Shx147065 gExecName, param);
4124516fc7f3Shx147065 free(param);
4125516fc7f3Shx147065 return (B_FALSE);
4126516fc7f3Shx147065 }
4127516fc7f3Shx147065 if (value_is_valid(do_gs_func[j].index, pequal) ==
4128516fc7f3Shx147065 B_FALSE) {
4129516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4130516fc7f3Shx147065 "invalid value '%s' for parameter '%s'\n"),
4131516fc7f3Shx147065 gExecName, pequal, param);
4132516fc7f3Shx147065 return (B_FALSE);
4133516fc7f3Shx147065 }
4134516fc7f3Shx147065 free(param);
4135516fc7f3Shx147065 update_aelist(cplist, argv[i]);
4136516fc7f3Shx147065 }
4137516fc7f3Shx147065 return (B_TRUE);
4138516fc7f3Shx147065 }
4139516fc7f3Shx147065
4140516fc7f3Shx147065 /*
4141516fc7f3Shx147065 * do_createprofile: Called when create a profile off-line.
4142516fc7f3Shx147065 */
4143516fc7f3Shx147065 /*ARGSUSED*/
4144516fc7f3Shx147065 static boolean_t
do_createprofile(int fd,int argc,char ** argv)4145516fc7f3Shx147065 do_createprofile(int fd, int argc, char **argv)
4146516fc7f3Shx147065 {
4147516fc7f3Shx147065 int i = 0;
4148516fc7f3Shx147065 char *pbuf = NULL;
4149516fc7f3Shx147065 char *pfbuf = NULL;
4150516fc7f3Shx147065 const char *profilename;
4151516fc7f3Shx147065 aelist_t *plist_config = NULL, *plist_wepkey = NULL;
4152516fc7f3Shx147065
4153516fc7f3Shx147065 PRTDBG(("do_createprofile(%d, 0x%x)\n", argc, argv));
4154516fc7f3Shx147065 if (argc <= 0) {
4155516fc7f3Shx147065 do_print_usage();
4156516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
4157516fc7f3Shx147065 }
4158516fc7f3Shx147065 /*
4159516fc7f3Shx147065 * When creating a profile, if the profile name is not specified,
4160516fc7f3Shx147065 * the essid is selected as the profile name. the paramters are
4161516fc7f3Shx147065 * saved into the section.
4162516fc7f3Shx147065 */
4163516fc7f3Shx147065 if (strchr(argv[0], '=') == NULL) {
4164516fc7f3Shx147065 pfbuf = safe_strdup(argv[0]);
4165516fc7f3Shx147065 argc--;
4166516fc7f3Shx147065 argv++;
4167516fc7f3Shx147065 }
4168516fc7f3Shx147065 for (i = 0; i < argc; i++) {
4169516fc7f3Shx147065 if (strncmp(argv[i], "essid=", strlen("essid=")) == 0) {
4170516fc7f3Shx147065 break;
4171516fc7f3Shx147065 }
4172516fc7f3Shx147065 }
4173516fc7f3Shx147065 if (i == argc) {
4174516fc7f3Shx147065 (void) fprintf(stderr,
4175516fc7f3Shx147065 gettext("%s: "
4176516fc7f3Shx147065 "essid required when creating profile\n"),
4177516fc7f3Shx147065 gExecName);
4178516fc7f3Shx147065 goto exit0;
4179516fc7f3Shx147065 }
4180516fc7f3Shx147065 profilename = (pfbuf ? pfbuf : get_value(argv[i]));
4181516fc7f3Shx147065 if (strlen(profilename) == 0) {
4182516fc7f3Shx147065 (void) fprintf(stderr,
4183516fc7f3Shx147065 gettext("%s: "
4184516fc7f3Shx147065 "non-empty essid required\n"),
4185516fc7f3Shx147065 gExecName);
4186516fc7f3Shx147065 goto exit0;
4187516fc7f3Shx147065 }
4188516fc7f3Shx147065 /*
4189516fc7f3Shx147065 * 'all', '{preference}', '{history}', '{active_profile}'
4190516fc7f3Shx147065 * and any string with '[' as start and ']' as end should
4191516fc7f3Shx147065 * not be a profile name
4192516fc7f3Shx147065 */
4193516fc7f3Shx147065 if ((strcasecmp(profilename, "all") == 0) ||
4194516fc7f3Shx147065 (strcmp(profilename, WIFI_HISTORY) == 0) ||
4195516fc7f3Shx147065 (strcmp(profilename, WIFI_PREFER) == 0) ||
4196516fc7f3Shx147065 (strcmp(profilename, WIFI_ACTIVEP) == 0) ||
4197516fc7f3Shx147065 ((profilename[0] == '[') &&
4198516fc7f3Shx147065 (profilename[strlen(profilename) - 1] == ']'))) {
4199516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4200516fc7f3Shx147065 "'%s' is an invalid profile name\n"),
4201516fc7f3Shx147065 gExecName, profilename);
4202516fc7f3Shx147065 goto exit0;
4203516fc7f3Shx147065 }
4204516fc7f3Shx147065 pbuf = append_pa(profilename);
4205516fc7f3Shx147065
4206516fc7f3Shx147065 PRTDBG(("do_createprofile: profile_name = %s\n", pbuf));
4207516fc7f3Shx147065 if ((find_section(gp_config_file, pbuf) != NULL) ||
4208516fc7f3Shx147065 find_section(gp_wepkey_file, pbuf) != NULL) {
4209516fc7f3Shx147065 (void) fprintf(stderr,
4210516fc7f3Shx147065 gettext("%s: "
4211516fc7f3Shx147065 "profile '%s' already exists\n"),
4212516fc7f3Shx147065 gExecName, profilename);
4213516fc7f3Shx147065 goto exit1;
4214516fc7f3Shx147065 }
4215516fc7f3Shx147065 /*
4216516fc7f3Shx147065 * Save each parameters in the profile.
4217516fc7f3Shx147065 */
4218516fc7f3Shx147065 plist_config = new_ael(PROFILE);
4219516fc7f3Shx147065 new_section(gp_config_file, plist_config, pbuf);
4220516fc7f3Shx147065 plist_wepkey = new_ael(PROFILE);
4221516fc7f3Shx147065 new_section(gp_wepkey_file, plist_wepkey, pbuf);
4222516fc7f3Shx147065 free(pfbuf);
4223516fc7f3Shx147065 free(pbuf);
4224516fc7f3Shx147065 return (items_in_profile(plist_config, plist_wepkey,
4225516fc7f3Shx147065 argc, argv));
4226516fc7f3Shx147065 exit1:
4227516fc7f3Shx147065 free(pbuf);
4228516fc7f3Shx147065 exit0:
4229516fc7f3Shx147065 free(pfbuf);
4230516fc7f3Shx147065 return (B_FALSE);
4231516fc7f3Shx147065 }
4232516fc7f3Shx147065
4233516fc7f3Shx147065 /*ARGSUSED*/
4234516fc7f3Shx147065 static boolean_t
do_setprofparam(int fd,int argc,char ** argv)4235516fc7f3Shx147065 do_setprofparam(int fd, int argc, char **argv)
4236516fc7f3Shx147065 {
4237516fc7f3Shx147065 char *pbuf = NULL;
4238516fc7f3Shx147065 section_t *psection_config = NULL, *psection_wep = NULL;
4239516fc7f3Shx147065 aelist_t *plist_config = NULL, *plist_wepkey = NULL;
4240516fc7f3Shx147065
4241516fc7f3Shx147065 PRTDBG(("do_setprofparam(%d, 0x%x)\n", argc, argv));
4242516fc7f3Shx147065 if (argc < 1) {
4243516fc7f3Shx147065 do_print_usage();
4244516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
4245516fc7f3Shx147065 }
4246516fc7f3Shx147065 pbuf = append_pa(argv[0]);
4247516fc7f3Shx147065
4248516fc7f3Shx147065 psection_config = find_section(gp_config_file, pbuf);
4249516fc7f3Shx147065 psection_wep = find_section(gp_wepkey_file, pbuf);
4250516fc7f3Shx147065 if ((psection_config == NULL) || (psection_wep == NULL)) {
4251516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4252516fc7f3Shx147065 "profile '%s' doesn't exist\n"),
4253516fc7f3Shx147065 gExecName, argv[0]);
4254516fc7f3Shx147065 free(pbuf);
4255516fc7f3Shx147065 return (B_FALSE);
4256516fc7f3Shx147065 }
4257516fc7f3Shx147065 free(pbuf);
4258516fc7f3Shx147065 /*
4259516fc7f3Shx147065 * modify each parameters in the profile.
4260516fc7f3Shx147065 */
4261516fc7f3Shx147065 plist_config = psection_config->list;
4262516fc7f3Shx147065 plist_wepkey = psection_wep->list;
4263516fc7f3Shx147065 argc--;
4264516fc7f3Shx147065 argv++;
4265516fc7f3Shx147065 return (items_in_profile(plist_config, plist_wepkey,
4266516fc7f3Shx147065 argc, argv));
4267516fc7f3Shx147065 }
4268516fc7f3Shx147065
4269516fc7f3Shx147065 /*ARGSUSED*/
4270516fc7f3Shx147065 static boolean_t
do_getprofparam(int fd,int argc,char ** argv)4271516fc7f3Shx147065 do_getprofparam(int fd, int argc, char **argv)
4272516fc7f3Shx147065 {
4273516fc7f3Shx147065 int i = 0, j = 0;
4274516fc7f3Shx147065 int flag;
4275516fc7f3Shx147065 boolean_t ret = B_TRUE;
4276516fc7f3Shx147065 section_t *p_section = NULL;
4277516fc7f3Shx147065 aelist_t *plist = NULL;
4278516fc7f3Shx147065 ae_t *pae = NULL;
4279516fc7f3Shx147065 char *pbuf = NULL;
4280516fc7f3Shx147065
4281516fc7f3Shx147065 PRTDBG(("do_getprofparam(%d, 0x%x)\n", argc, argv));
4282516fc7f3Shx147065 if (argc < 1) {
4283516fc7f3Shx147065 do_print_usage();
4284516fc7f3Shx147065 exit(WIFI_IMPROPER_USE);
4285516fc7f3Shx147065 }
4286516fc7f3Shx147065 pbuf = append_pa(argv[0]);
4287516fc7f3Shx147065 p_section = find_section(gp_config_file, pbuf);
4288516fc7f3Shx147065 if (p_section == NULL) {
4289516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4290516fc7f3Shx147065 "profile '%s' doesn't exist\n"),
4291516fc7f3Shx147065 gExecName, argv[0]);
4292516fc7f3Shx147065 ret = B_FALSE;
4293516fc7f3Shx147065 goto exit0;
4294516fc7f3Shx147065 }
4295516fc7f3Shx147065 argc--;
4296516fc7f3Shx147065 argv++;
4297516fc7f3Shx147065
4298516fc7f3Shx147065 plist = p_section->list;
4299516fc7f3Shx147065 assert(plist != NULL);
4300516fc7f3Shx147065 /*
4301516fc7f3Shx147065 * If no specific parameter typed, we print out all parameters
4302516fc7f3Shx147065 */
4303516fc7f3Shx147065 if (argc == 0) {
4304516fc7f3Shx147065 pae = plist->ael_head;
4305516fc7f3Shx147065 while (pae != NULL) {
4306516fc7f3Shx147065 if (pae->ae_arg != NULL) {
4307516fc7f3Shx147065 (void) printf("\t%s\n", pae->ae_arg);
4308516fc7f3Shx147065 }
4309516fc7f3Shx147065 pae = pae->ae_next;
4310516fc7f3Shx147065 }
4311516fc7f3Shx147065 print_wepkey_info(p_section->section_id, NULL);
4312516fc7f3Shx147065 ret = B_TRUE;
4313516fc7f3Shx147065 goto exit0;
4314516fc7f3Shx147065 }
4315516fc7f3Shx147065
4316516fc7f3Shx147065 /*
4317516fc7f3Shx147065 * Match function with do_gs_func[] table, and print its result
4318516fc7f3Shx147065 */
4319516fc7f3Shx147065 for (i = 0; i < argc; i++) {
4320516fc7f3Shx147065 flag = 0;
4321516fc7f3Shx147065 for (j = 0; j < N_GS_FUNC; j++) {
4322516fc7f3Shx147065 if (strcmp(argv[i], do_gs_func[j].cmd) == 0) {
4323516fc7f3Shx147065 break;
4324516fc7f3Shx147065 }
4325516fc7f3Shx147065 if (param_is_wepkey(argv[i], B_FALSE) == B_TRUE) {
4326516fc7f3Shx147065 j = WEPKEY;
4327516fc7f3Shx147065 print_wepkey_info(p_section->section_id,
4328516fc7f3Shx147065 argv[i]);
4329516fc7f3Shx147065 flag++;
4330516fc7f3Shx147065 break;
4331516fc7f3Shx147065 }
4332516fc7f3Shx147065 }
4333516fc7f3Shx147065 if (j == N_GS_FUNC) {
4334516fc7f3Shx147065 (void) fprintf(stderr,
4335516fc7f3Shx147065 gettext("wificonifg: unrecognized parameter: "
4336516fc7f3Shx147065 "%s\n"), argv[i]);
4337516fc7f3Shx147065 ret = B_FALSE;
4338516fc7f3Shx147065 goto exit0;
4339516fc7f3Shx147065 }
4340516fc7f3Shx147065
4341516fc7f3Shx147065 pae = plist->ael_head;
4342516fc7f3Shx147065 while ((pae != NULL) && (!flag)) {
4343516fc7f3Shx147065 if ((pae->ae_arg != NULL) &&
4344516fc7f3Shx147065 (strncmp(pae->ae_arg, argv[i],
4345516fc7f3Shx147065 strlen(argv[i])) == 0)) {
4346516fc7f3Shx147065 (void) printf("\t%s\n", pae->ae_arg);
4347516fc7f3Shx147065 flag++;
4348516fc7f3Shx147065 }
4349516fc7f3Shx147065 pae = pae->ae_next;
4350516fc7f3Shx147065 }
4351516fc7f3Shx147065 if (!flag) {
4352516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4353516fc7f3Shx147065 "parameter '%s' has not been set in profile %s\n"),
4354516fc7f3Shx147065 gExecName, argv[i], pbuf);
4355516fc7f3Shx147065 ret = B_FALSE;
4356516fc7f3Shx147065 goto exit0;
4357516fc7f3Shx147065 }
4358516fc7f3Shx147065 }
4359516fc7f3Shx147065 exit0:
4360516fc7f3Shx147065 free(pbuf);
4361516fc7f3Shx147065 return (ret);
4362516fc7f3Shx147065 }
4363516fc7f3Shx147065
4364516fc7f3Shx147065 /*
4365516fc7f3Shx147065 * Verify whether the value in the parameter=value pair is valid or not.
4366516fc7f3Shx147065 * For the channel, since we donot know what kind of wifi card(a,b,or g)
4367516fc7f3Shx147065 * is in the system, so we just leave to verify the validity of the value
4368516fc7f3Shx147065 * when the value is set to the card.
4369516fc7f3Shx147065 * The same goes for the rates.
4370516fc7f3Shx147065 */
4371516fc7f3Shx147065 static boolean_t
value_is_valid(config_item_t item,const char * value)4372516fc7f3Shx147065 value_is_valid(config_item_t item, const char *value)
4373516fc7f3Shx147065 {
4374516fc7f3Shx147065 uint32_t num = 0;
4375516fc7f3Shx147065 uint8_t *rates;
4376516fc7f3Shx147065 boolean_t ret;
4377516fc7f3Shx147065
4378516fc7f3Shx147065 assert(value != NULL);
4379516fc7f3Shx147065 switch (item) {
4380516fc7f3Shx147065 case ESSID:
4381516fc7f3Shx147065 if (strlen(value) > 32)
4382516fc7f3Shx147065 ret = B_FALSE;
4383516fc7f3Shx147065 else
4384516fc7f3Shx147065 ret = B_TRUE;
4385516fc7f3Shx147065 break;
4386516fc7f3Shx147065 case BSSTYPE:
4387516fc7f3Shx147065 if ((strcasecmp(value, "bss") == 0) ||
4388516fc7f3Shx147065 (strcasecmp(value, "ap") == 0) ||
4389516fc7f3Shx147065 (strcasecmp(value, "infrastructure") == 0) ||
4390516fc7f3Shx147065 (strcasecmp(value, "ibss") == 0) ||
4391516fc7f3Shx147065 (strcasecmp(value, "ad-hoc") == 0) ||
4392516fc7f3Shx147065 (strcasecmp(value, "auto") == 0))
4393516fc7f3Shx147065 ret = B_TRUE;
4394516fc7f3Shx147065 else
4395516fc7f3Shx147065 ret = B_FALSE;
4396516fc7f3Shx147065 break;
4397516fc7f3Shx147065 case CREATEIBSS:
4398516fc7f3Shx147065 if ((strcasecmp(value, "yes") == 0) ||
4399516fc7f3Shx147065 (strcasecmp(value, "no") == 0))
4400516fc7f3Shx147065 ret = B_TRUE;
4401516fc7f3Shx147065 else
4402516fc7f3Shx147065 ret = B_FALSE;
4403516fc7f3Shx147065 break;
4404516fc7f3Shx147065 case AUTHMODE:
4405516fc7f3Shx147065 if ((strcasecmp(value, "opensystem") == 0) ||
4406516fc7f3Shx147065 (strcasecmp(value, "shared_key") == 0))
4407516fc7f3Shx147065 ret = B_TRUE;
4408516fc7f3Shx147065 else
4409516fc7f3Shx147065 ret = B_FALSE;
4410516fc7f3Shx147065 break;
4411516fc7f3Shx147065 case POWERMODE:
4412516fc7f3Shx147065 if ((strcasecmp(value, "off") == 0) ||
4413516fc7f3Shx147065 (strcasecmp(value, "mps") == 0) ||
4414516fc7f3Shx147065 (strcasecmp(value, "fast") == 0))
4415516fc7f3Shx147065 ret = B_TRUE;
4416516fc7f3Shx147065 else
4417516fc7f3Shx147065 ret = B_FALSE;
4418516fc7f3Shx147065 break;
4419516fc7f3Shx147065 case ENCRYPTION:
4420516fc7f3Shx147065 if ((strcasecmp(value, "wep") == 0) ||
4421516fc7f3Shx147065 (strcasecmp(value, "none") == 0))
4422516fc7f3Shx147065 ret = B_TRUE;
4423516fc7f3Shx147065 else
4424516fc7f3Shx147065 ret = B_FALSE;
4425516fc7f3Shx147065 break;
4426516fc7f3Shx147065 case RADIOON:
4427516fc7f3Shx147065 if ((strcasecmp(value, "on") == 0) ||
4428516fc7f3Shx147065 (strcasecmp(value, "off") == 0))
4429516fc7f3Shx147065 ret = B_TRUE;
4430516fc7f3Shx147065 else
4431516fc7f3Shx147065 ret = B_FALSE;
4432516fc7f3Shx147065 break;
4433516fc7f3Shx147065 case WEPKEYID:
4434516fc7f3Shx147065 ret = is_wepkeyindex_valid(value);
4435516fc7f3Shx147065 break;
4436516fc7f3Shx147065 case WEPKEY:
4437516fc7f3Shx147065 ret = is_wepkey_valid(value, strlen(value));
4438516fc7f3Shx147065 break;
4439516fc7f3Shx147065 case CHANNEL:
4440516fc7f3Shx147065 ret = is_channel_valid(value);
4441516fc7f3Shx147065 break;
4442516fc7f3Shx147065 case RATES:
4443516fc7f3Shx147065 rates = get_rates(value, &num);
4444516fc7f3Shx147065 if (rates == NULL) {
4445516fc7f3Shx147065 ret = B_FALSE;
4446516fc7f3Shx147065 } else {
4447516fc7f3Shx147065 free(rates);
4448516fc7f3Shx147065 ret = B_TRUE;
4449516fc7f3Shx147065 }
4450516fc7f3Shx147065 break;
4451516fc7f3Shx147065 default:
4452516fc7f3Shx147065 ret = B_FALSE;
4453516fc7f3Shx147065 break;
4454516fc7f3Shx147065 }
4455516fc7f3Shx147065
4456516fc7f3Shx147065 return (ret);
4457516fc7f3Shx147065 }
4458516fc7f3Shx147065
4459516fc7f3Shx147065 /*
4460516fc7f3Shx147065 * do_set: Called when set a parameter, the format should be
4461516fc7f3Shx147065 * parameter=value.
4462516fc7f3Shx147065 */
4463516fc7f3Shx147065 static boolean_t
do_set(int fd,int argc,char ** argv)4464516fc7f3Shx147065 do_set(int fd, int argc, char **argv)
4465516fc7f3Shx147065 {
4466516fc7f3Shx147065 int i = 0, j = 0;
4467516fc7f3Shx147065 char *param;
4468516fc7f3Shx147065 char *pequal;
4469516fc7f3Shx147065 char *value;
4470516fc7f3Shx147065 boolean_t ret;
4471516fc7f3Shx147065
4472516fc7f3Shx147065 PRTDBG(("do_set(%d, 0x%x)\n", argc, argv));
4473516fc7f3Shx147065 assert(fd > 0);
4474516fc7f3Shx147065 if (argc <= 0) {
4475516fc7f3Shx147065 (void) do_print_support_params(fd);
4476516fc7f3Shx147065 ret = B_FALSE;
4477516fc7f3Shx147065 goto exit0;
4478516fc7f3Shx147065 }
4479516fc7f3Shx147065 /*
4480516fc7f3Shx147065 * Set each parameters, if one failed, others behind it will
4481516fc7f3Shx147065 * not be set
4482516fc7f3Shx147065 */
4483516fc7f3Shx147065 for (i = 0; i < argc; i++) {
4484516fc7f3Shx147065 /*
4485516fc7f3Shx147065 * Separate param and its value, if the user types "param=",
4486516fc7f3Shx147065 * then value will be set to "";if the user types "param",
4487516fc7f3Shx147065 * it is an error.
4488516fc7f3Shx147065 */
4489516fc7f3Shx147065 param = safe_strdup(argv[i]);
4490516fc7f3Shx147065 pequal = strchr(param, '=');
4491516fc7f3Shx147065 value = NULL;
4492516fc7f3Shx147065 if (pequal != NULL) {
4493516fc7f3Shx147065 *pequal = '\0';
4494516fc7f3Shx147065 value = pequal + 1;
4495516fc7f3Shx147065 } else {
4496516fc7f3Shx147065 (void) fprintf(stderr,
4497516fc7f3Shx147065 gettext("%s: invalid setparam argument "
4498516fc7f3Shx147065 "'%s', use 'parameter=value'\n"),
4499516fc7f3Shx147065 gExecName, argv[i]);
4500516fc7f3Shx147065 free(param);
4501516fc7f3Shx147065 ret = B_FALSE;
4502516fc7f3Shx147065 goto exit0;
4503516fc7f3Shx147065 }
4504516fc7f3Shx147065 PRTDBG(("do_set: param = \"%s\", value = \"%s\"\n",
4505516fc7f3Shx147065 param, value));
4506516fc7f3Shx147065 for (j = 0; j < N_GS_FUNC; j++) {
4507516fc7f3Shx147065 /*
4508516fc7f3Shx147065 * Match each parameters with do_gs_func table,
4509516fc7f3Shx147065 */
4510516fc7f3Shx147065 if (strcmp(param, do_gs_func[j].cmd) == 0)
4511516fc7f3Shx147065 break;
4512516fc7f3Shx147065 if (param_is_wepkey(param, B_FALSE) == B_TRUE) {
4513516fc7f3Shx147065 value = argv[i];
4514516fc7f3Shx147065 j = WEPKEY;
4515516fc7f3Shx147065 break;
4516516fc7f3Shx147065 }
4517516fc7f3Shx147065 }
4518516fc7f3Shx147065 if (j == N_GS_FUNC) {
4519516fc7f3Shx147065 (void) fprintf(stderr,
4520516fc7f3Shx147065 gettext("%s: unrecognized parameter: "
4521516fc7f3Shx147065 "%s\n"), gExecName, param);
4522516fc7f3Shx147065 free(param);
4523516fc7f3Shx147065 ret = B_FALSE;
4524516fc7f3Shx147065 goto exit0;
4525516fc7f3Shx147065 }
4526516fc7f3Shx147065
4527516fc7f3Shx147065 if (do_gs_func[j].p_do_set_func == NULL) {
4528516fc7f3Shx147065 (void) fprintf(stderr,
4529516fc7f3Shx147065 gettext("%s: parameter '%s' is read-only\n"),
4530516fc7f3Shx147065 gExecName, do_gs_func[j].cmd);
4531516fc7f3Shx147065 free(param);
4532516fc7f3Shx147065 ret = B_FALSE;
4533516fc7f3Shx147065 goto exit0;
4534516fc7f3Shx147065 }
4535516fc7f3Shx147065 if (do_gs_func[j].p_do_set_func(fd, value)
4536516fc7f3Shx147065 == B_TRUE) {
4537516fc7f3Shx147065 ret = B_TRUE;
4538516fc7f3Shx147065 } else {
4539516fc7f3Shx147065 if (gbuf->wldp_result != WL_SUCCESS) {
4540516fc7f3Shx147065 (void) fprintf(stderr,
4541516fc7f3Shx147065 gettext("%s: "
4542516fc7f3Shx147065 "failed to set '%s' for "),
4543516fc7f3Shx147065 gExecName, param);
4544516fc7f3Shx147065 print_error(gbuf->wldp_result);
4545516fc7f3Shx147065 }
4546516fc7f3Shx147065 free(param);
4547516fc7f3Shx147065 ret = B_FALSE;
4548516fc7f3Shx147065 goto exit0;
4549516fc7f3Shx147065 }
4550516fc7f3Shx147065 free(param);
4551516fc7f3Shx147065 }
4552516fc7f3Shx147065 exit0:
4553516fc7f3Shx147065 return (ret);
4554516fc7f3Shx147065 }
4555516fc7f3Shx147065
4556516fc7f3Shx147065 static boolean_t
do_get(int fd,int argc,char ** argv)4557516fc7f3Shx147065 do_get(int fd, int argc, char **argv)
4558516fc7f3Shx147065 {
4559516fc7f3Shx147065 int i = 0, j = 0, n = 0;
4560516fc7f3Shx147065 boolean_t ret = B_TRUE;
4561516fc7f3Shx147065
4562516fc7f3Shx147065 PRTDBG(("do_get(%d, 0x%x)\n", argc, argv));
4563516fc7f3Shx147065 assert(fd > 0);
4564516fc7f3Shx147065 /*
4565516fc7f3Shx147065 * If no specific parameter typed, we print out all parameters
4566516fc7f3Shx147065 */
4567516fc7f3Shx147065 if (argc <= 0) {
4568516fc7f3Shx147065 for (i = 0; i < N_GS_FUNC; i++) {
4569516fc7f3Shx147065 if ((do_gs_func[i].p_do_get_func != NULL) &&
4570516fc7f3Shx147065 (do_gs_func[i].p_do_get_func(fd)
4571516fc7f3Shx147065 == B_TRUE)) {
4572516fc7f3Shx147065 print_gbuf(do_gs_func[i].index);
4573516fc7f3Shx147065 n++;
4574516fc7f3Shx147065 }
4575516fc7f3Shx147065 }
4576516fc7f3Shx147065 ret = n ? B_TRUE:B_FALSE;
4577516fc7f3Shx147065 goto exit0;
4578516fc7f3Shx147065 }
4579516fc7f3Shx147065 /*
4580516fc7f3Shx147065 * Match function with do_gs_func[] table, and print its result
4581516fc7f3Shx147065 */
4582516fc7f3Shx147065 for (i = 0; i < argc; i++) {
4583516fc7f3Shx147065 for (j = 0; j < N_GS_FUNC; j++) {
4584516fc7f3Shx147065 if (strcmp(argv[i], do_gs_func[j].cmd) == 0) {
4585516fc7f3Shx147065 break;
4586516fc7f3Shx147065 }
4587516fc7f3Shx147065 if (param_is_wepkey(argv[i], B_FALSE) == B_TRUE) {
4588516fc7f3Shx147065 j = WEPKEY;
4589516fc7f3Shx147065 break;
4590516fc7f3Shx147065 }
4591516fc7f3Shx147065 }
4592516fc7f3Shx147065 if (j == N_GS_FUNC) {
4593516fc7f3Shx147065 (void) fprintf(stderr,
4594516fc7f3Shx147065 gettext("wificonifg: unrecognized parameter: "
4595516fc7f3Shx147065 "%s\n"), argv[i]);
4596516fc7f3Shx147065 ret = B_FALSE;
4597516fc7f3Shx147065 goto exit0;
4598516fc7f3Shx147065 }
4599516fc7f3Shx147065 if (do_gs_func[j].p_do_get_func == NULL) {
4600516fc7f3Shx147065 (void) fprintf(stderr,
4601516fc7f3Shx147065 gettext("%s: parameter '%s' is write-only\n"),
4602516fc7f3Shx147065 gExecName, do_gs_func[j].cmd);
4603516fc7f3Shx147065 ret = B_FALSE;
4604516fc7f3Shx147065 goto exit0;
4605516fc7f3Shx147065 }
4606516fc7f3Shx147065 if (do_gs_func[j].p_do_get_func(fd) == B_TRUE) {
4607516fc7f3Shx147065 print_gbuf(do_gs_func[j].index);
4608516fc7f3Shx147065 ret = B_TRUE;
4609516fc7f3Shx147065 } else {
4610516fc7f3Shx147065 (void) fprintf(stderr,
4611516fc7f3Shx147065 gettext("%s: "
4612516fc7f3Shx147065 "failed to read parameter '%s' : "),
4613516fc7f3Shx147065 gExecName, argv[i]);
4614516fc7f3Shx147065 print_error(gbuf->wldp_result);
4615516fc7f3Shx147065 ret = B_FALSE;
4616516fc7f3Shx147065 }
4617516fc7f3Shx147065 }
4618516fc7f3Shx147065 exit0:
4619516fc7f3Shx147065 return (ret);
4620516fc7f3Shx147065 }
4621516fc7f3Shx147065
4622516fc7f3Shx147065 /*
4623516fc7f3Shx147065 * Only one wificonfig is running at one time.
4624516fc7f3Shx147065 * The following wificonfig which tries to be run will return error,
4625516fc7f3Shx147065 * and the pid of the process will own the filelock will be printed out.
4626516fc7f3Shx147065 */
4627516fc7f3Shx147065 static pid_t
enter_wifi_lock(int * fd)4628516fc7f3Shx147065 enter_wifi_lock(int *fd)
4629516fc7f3Shx147065 {
4630516fc7f3Shx147065 int fd0 = -1;
4631516fc7f3Shx147065 struct flock lock;
4632516fc7f3Shx147065
4633516fc7f3Shx147065 fd0 = open(WIFI_LOCKF, O_CREAT|O_WRONLY, 0600);
4634516fc7f3Shx147065 if (fd0 < 0) {
4635516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to open lockfile"
4636516fc7f3Shx147065 " '"WIFI_LOCKF"': %s\n"), gExecName, strerror(errno));
4637516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
4638516fc7f3Shx147065 }
4639516fc7f3Shx147065
4640516fc7f3Shx147065 *fd = fd0;
4641516fc7f3Shx147065 lock.l_type = F_WRLCK;
4642516fc7f3Shx147065 lock.l_whence = SEEK_SET;
4643516fc7f3Shx147065 lock.l_start = 0;
4644516fc7f3Shx147065 lock.l_len = 0;
4645516fc7f3Shx147065
4646516fc7f3Shx147065 if ((fcntl(fd0, F_SETLK, &lock) == -1) &&
4647516fc7f3Shx147065 (errno == EAGAIN || errno == EDEADLK)) {
4648516fc7f3Shx147065 if (fcntl(fd0, F_GETLK, &lock) == -1) {
4649516fc7f3Shx147065 (void) fprintf(stderr,
4650516fc7f3Shx147065 gettext("%s: enter_filelock"));
4651516fc7f3Shx147065 exit(WIFI_FATAL_ERR);
4652516fc7f3Shx147065 }
4653516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s:"
4654516fc7f3Shx147065 "enter_filelock:filelock is owned "
4655516fc7f3Shx147065 "by 'process %d'\n"), gExecName, lock.l_pid);
4656516fc7f3Shx147065 return (lock.l_pid);
4657516fc7f3Shx147065 }
4658516fc7f3Shx147065
4659516fc7f3Shx147065 return (getpid());
4660516fc7f3Shx147065 }
4661516fc7f3Shx147065
4662516fc7f3Shx147065 static void
exit_wifi_lock(int fd)4663516fc7f3Shx147065 exit_wifi_lock(int fd)
4664516fc7f3Shx147065 {
4665516fc7f3Shx147065 struct flock lock;
4666516fc7f3Shx147065
4667516fc7f3Shx147065 lock.l_type = F_UNLCK;
4668516fc7f3Shx147065 lock.l_whence = SEEK_SET;
4669516fc7f3Shx147065 lock.l_start = 0;
4670516fc7f3Shx147065 lock.l_len = 0;
4671516fc7f3Shx147065 if (fcntl(fd, F_SETLK, &lock) == -1) {
4672516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: failed to"
4673516fc7f3Shx147065 " exit_filelock: %s\n"),
4674516fc7f3Shx147065 gExecName, strerror(errno));
4675516fc7f3Shx147065 }
4676516fc7f3Shx147065 (void) close(fd);
4677516fc7f3Shx147065 }
4678516fc7f3Shx147065
4679516fc7f3Shx147065 int
main(int argc,char ** argv)4680516fc7f3Shx147065 main(int argc, char **argv)
4681516fc7f3Shx147065 {
4682516fc7f3Shx147065 int i, ret;
4683516fc7f3Shx147065 int fddev = -1;
4684516fc7f3Shx147065 int c, iflag = 0, rflag = 0, fileonly = 0, readonly = 0;
4685516fc7f3Shx147065 int fd;
4686516fc7f3Shx147065 char *iname = NULL;
4687516fc7f3Shx147065 char *path = NULL;
4688516fc7f3Shx147065 extern char *optarg;
4689516fc7f3Shx147065 extern int optind;
4690516fc7f3Shx147065 char interface[LIFNAMSIZ];
4691516fc7f3Shx147065 char file_wifi[MAX_CONFIG_FILE_LENGTH];
4692516fc7f3Shx147065 char file_wifiwepkey[MAX_CONFIG_FILE_LENGTH];
4693516fc7f3Shx147065 priv_set_t *ppriv;
4694516fc7f3Shx147065 wifi_auth_t autht;
4695516fc7f3Shx147065
4696516fc7f3Shx147065 PRTDBG(("main(%d, 0x%x)\n", argc, argv));
4697516fc7f3Shx147065 PRTDBG(("uid=%d\n", getuid()));
4698516fc7f3Shx147065 PRTDBG(("euid=%d\n", geteuid()));
4699516fc7f3Shx147065
4700516fc7f3Shx147065 #ifdef DEBUG
4701516fc7f3Shx147065 if (wifi_debug == 1) { /* for debuf purpose only */
4702516fc7f3Shx147065 (void) printf("Press RETURN to continue...\n");
4703516fc7f3Shx147065 (void) getchar();
4704516fc7f3Shx147065 }
4705516fc7f3Shx147065 #endif
4706516fc7f3Shx147065 ret = WIFI_EXIT_DEF;
4707516fc7f3Shx147065
4708516fc7f3Shx147065 (void) setlocale(LC_ALL, "");
4709516fc7f3Shx147065 (void) textdomain(TEXT_DOMAIN);
4710516fc7f3Shx147065
4711516fc7f3Shx147065 gExecName = argv[0];
4712516fc7f3Shx147065
4713516fc7f3Shx147065 gbuf = safe_malloc(MAX_BUF_LEN);
4714516fc7f3Shx147065
4715516fc7f3Shx147065 if ((ppriv = priv_str_to_set("basic", ",", NULL)) == NULL) {
4716516fc7f3Shx147065 PRTDBG(("main: priviledge init error\n"));
4717516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4718516fc7f3Shx147065 "set priviledge to 'basic' error\n"),
4719516fc7f3Shx147065 gExecName);
4720516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4721516fc7f3Shx147065 goto exit0;
4722516fc7f3Shx147065 }
4723516fc7f3Shx147065 (void) priv_addset(ppriv, PRIV_NET_RAWACCESS);
4724516fc7f3Shx147065 (void) priv_addset(ppriv, PRIV_SYS_NET_CONFIG);
4725516fc7f3Shx147065 if (setppriv(PRIV_SET, PRIV_PERMITTED, ppriv) == -1) {
4726516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4727516fc7f3Shx147065 "set permitted priviledge: %s\n"),
4728516fc7f3Shx147065 gExecName, strerror(errno));
4729516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4730516fc7f3Shx147065 goto exit0;
4731516fc7f3Shx147065 }
4732516fc7f3Shx147065 if (setppriv(PRIV_SET, PRIV_LIMIT, ppriv) == -1) {
4733516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4734516fc7f3Shx147065 "set limit priviledge: %s\n"),
4735516fc7f3Shx147065 gExecName, strerror(errno));
4736516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4737516fc7f3Shx147065 goto exit0;
4738516fc7f3Shx147065 }
4739516fc7f3Shx147065 if (setppriv(PRIV_SET, PRIV_INHERITABLE, ppriv) == -1) {
4740516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4741516fc7f3Shx147065 "set inherit priviledge: %s\n"),
4742516fc7f3Shx147065 gExecName, strerror(errno));
4743516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4744516fc7f3Shx147065 goto exit0;
4745516fc7f3Shx147065 }
4746516fc7f3Shx147065 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, ppriv) == -1) {
4747516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4748516fc7f3Shx147065 "set effective priviledge: %s\n"),
4749516fc7f3Shx147065 gExecName, strerror(errno));
4750516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4751516fc7f3Shx147065 goto exit0;
4752516fc7f3Shx147065 }
4753516fc7f3Shx147065 priv_freeset(ppriv);
4754516fc7f3Shx147065
4755516fc7f3Shx147065 for (i = 0; i < argc; i++) {
4756516fc7f3Shx147065 PRTDBG(("%d\t\t\"%s\"\n", i, argv[i]));
4757516fc7f3Shx147065 }
4758516fc7f3Shx147065
4759516fc7f3Shx147065 while ((c = getopt(argc, argv, "i:R:")) != EOF) {
4760516fc7f3Shx147065 switch (c) {
4761516fc7f3Shx147065 case 'i':
4762516fc7f3Shx147065 if (iflag) {
4763516fc7f3Shx147065 do_print_usage();
4764516fc7f3Shx147065 ret = WIFI_IMPROPER_USE;
4765516fc7f3Shx147065 goto exit0;
4766516fc7f3Shx147065 }
4767516fc7f3Shx147065 iflag = 1;
4768516fc7f3Shx147065 iname = optarg;
4769516fc7f3Shx147065 break;
4770516fc7f3Shx147065 case 'R':
4771516fc7f3Shx147065 if (rflag) {
4772516fc7f3Shx147065 do_print_usage();
4773516fc7f3Shx147065 ret = WIFI_IMPROPER_USE;
4774516fc7f3Shx147065 goto exit0;
4775516fc7f3Shx147065 }
4776516fc7f3Shx147065 rflag = 1;
4777516fc7f3Shx147065 path = optarg;
4778516fc7f3Shx147065 break;
4779516fc7f3Shx147065 case '?':
4780516fc7f3Shx147065 default:
4781516fc7f3Shx147065 do_print_usage();
4782516fc7f3Shx147065 ret = WIFI_IMPROPER_USE;
4783516fc7f3Shx147065 goto exit0;
4784516fc7f3Shx147065 }
4785516fc7f3Shx147065 }
4786516fc7f3Shx147065 argc -= optind;
4787516fc7f3Shx147065 argv += optind;
4788516fc7f3Shx147065
4789516fc7f3Shx147065 if (argc <= 0) {
4790516fc7f3Shx147065 if (iname) {
4791516fc7f3Shx147065 if ((fddev = open_dev(iname)) == -1) {
4792516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4793516fc7f3Shx147065 goto exit0;
4794516fc7f3Shx147065 }
4795516fc7f3Shx147065 if (do_print_support_params(fddev) ==
4796516fc7f3Shx147065 B_TRUE)
4797516fc7f3Shx147065 ret = WIFI_EXIT_DEF;
4798516fc7f3Shx147065 else
4799516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4800516fc7f3Shx147065 goto exit1;
4801516fc7f3Shx147065 } else {
4802516fc7f3Shx147065 do_print_usage();
4803516fc7f3Shx147065 ret = WIFI_IMPROPER_USE;
4804516fc7f3Shx147065 goto exit0;
4805516fc7f3Shx147065 }
4806516fc7f3Shx147065 }
4807516fc7f3Shx147065
4808516fc7f3Shx147065 for (i = 0; i < N_FUNC; i++) {
4809516fc7f3Shx147065 if (strcmp(argv[0], do_func[i].cmd) == 0) {
4810516fc7f3Shx147065 autht = ((strcmp(argv[0], "setwepkey") == 0) ||
4811516fc7f3Shx147065 (strcmp(argv[0], "setprofwepkey") == 0)) ?
4812516fc7f3Shx147065 AUTH_WEP:AUTH_OTHER;
4813516fc7f3Shx147065 if (do_func[i].b_auth &&
4814516fc7f3Shx147065 !check_authority(autht)) {
4815516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4816516fc7f3Shx147065 goto exit0;
4817516fc7f3Shx147065 }
4818516fc7f3Shx147065 if (do_func[i].b_fileonly)
4819516fc7f3Shx147065 fileonly++;
4820516fc7f3Shx147065 if (do_func[i].b_readonly)
4821516fc7f3Shx147065 readonly++;
4822516fc7f3Shx147065 break;
4823516fc7f3Shx147065 }
4824516fc7f3Shx147065 }
4825516fc7f3Shx147065 if (i == N_FUNC) {
4826516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: unrecognized "
4827516fc7f3Shx147065 "subcommand: %s\n"), gExecName, argv[0]);
4828516fc7f3Shx147065 do_print_usage();
4829516fc7f3Shx147065 ret = WIFI_IMPROPER_USE;
4830516fc7f3Shx147065 goto exit0;
4831516fc7f3Shx147065 }
4832516fc7f3Shx147065 if ((fileonly) && (iname)) {
4833516fc7f3Shx147065 do_print_usage();
4834516fc7f3Shx147065 ret = WIFI_IMPROPER_USE;
4835516fc7f3Shx147065 goto exit0;
4836516fc7f3Shx147065 }
4837516fc7f3Shx147065 if ((!fileonly) && (!iname)) {
4838516fc7f3Shx147065 if (search_interface(interface) != B_TRUE) {
4839516fc7f3Shx147065 (void) fprintf(stderr, gettext("%s: "
4840516fc7f3Shx147065 "failed to find the default wifi interface;"
4841516fc7f3Shx147065 " -i option should be used to specify the "
4842516fc7f3Shx147065 "wifi interface\n"), gExecName);
4843516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4844516fc7f3Shx147065 goto exit0;
4845516fc7f3Shx147065 }
4846516fc7f3Shx147065 iname = interface;
4847516fc7f3Shx147065 }
4848516fc7f3Shx147065 if (iname) {
4849516fc7f3Shx147065 if ((fddev = open_dev(iname)) == -1) {
4850516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4851516fc7f3Shx147065 goto exit0;
4852516fc7f3Shx147065 }
4853516fc7f3Shx147065 }
4854516fc7f3Shx147065 if (rflag) {
4855516fc7f3Shx147065 safe_snprintf(file_wifi, sizeof (file_wifi),
4856516fc7f3Shx147065 "%s%s", path, p_file_wifi);
4857516fc7f3Shx147065 safe_snprintf(file_wifiwepkey, sizeof (file_wifiwepkey),
4858516fc7f3Shx147065 "%s%s", path, p_file_wifiwepkey);
4859516fc7f3Shx147065 } else {
4860516fc7f3Shx147065 safe_snprintf(file_wifi, sizeof (file_wifi),
4861516fc7f3Shx147065 "%s", p_file_wifi);
4862516fc7f3Shx147065 safe_snprintf(file_wifiwepkey, sizeof (file_wifiwepkey),
4863516fc7f3Shx147065 "%s", p_file_wifiwepkey);
4864516fc7f3Shx147065 }
4865516fc7f3Shx147065 /*
4866516fc7f3Shx147065 * There is an occasion when more than one wificonfig processes
4867516fc7f3Shx147065 * which attempt to write the <wifi> and <wifiwepkey> files are
4868516fc7f3Shx147065 * running. We must be able to avoid this.
4869516fc7f3Shx147065 * We use file lock here to implement this.
4870516fc7f3Shx147065 */
4871516fc7f3Shx147065 if ((!readonly) && (enter_wifi_lock(&fd) != getpid())) {
4872516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4873516fc7f3Shx147065 goto exit1;
4874516fc7f3Shx147065 }
4875516fc7f3Shx147065 gp_config_file = parse_file(file_wifi);
4876516fc7f3Shx147065 if (gp_config_file == NULL) {
4877516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4878516fc7f3Shx147065 goto exit2;
4879516fc7f3Shx147065 }
4880516fc7f3Shx147065
4881516fc7f3Shx147065 gp_wepkey_file = parse_file(file_wifiwepkey);
4882516fc7f3Shx147065 if (gp_wepkey_file == NULL) {
4883516fc7f3Shx147065 destroy_config(gp_config_file);
4884516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4885516fc7f3Shx147065 goto exit2;
4886516fc7f3Shx147065 }
4887516fc7f3Shx147065 if (do_func[i].p_do_func(fddev, argc-1, argv+1)
4888516fc7f3Shx147065 == B_TRUE) {
4889516fc7f3Shx147065 /*
4890516fc7f3Shx147065 * can not write file when startconfing
4891516fc7f3Shx147065 * during boot
4892516fc7f3Shx147065 */
4893516fc7f3Shx147065 if (do_func[i].b_readonly)
4894516fc7f3Shx147065 ret = WIFI_EXIT_DEF;
4895516fc7f3Shx147065 else if ((fprint_config_file(gp_config_file,
4896516fc7f3Shx147065 file_wifi) != B_TRUE) ||
4897516fc7f3Shx147065 (fprint_config_file(gp_wepkey_file,
4898516fc7f3Shx147065 file_wifiwepkey) != B_TRUE))
4899516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4900516fc7f3Shx147065 else
4901516fc7f3Shx147065 ret = WIFI_EXIT_DEF;
4902516fc7f3Shx147065 } else {
4903516fc7f3Shx147065 PRTDBG(("Command %s failed\n", argv[0]));
4904516fc7f3Shx147065 ret = WIFI_FATAL_ERR;
4905516fc7f3Shx147065 }
4906516fc7f3Shx147065 destroy_config(gp_wepkey_file);
4907516fc7f3Shx147065 destroy_config(gp_config_file);
4908516fc7f3Shx147065 exit2:
4909516fc7f3Shx147065 if (!readonly)
4910516fc7f3Shx147065 exit_wifi_lock(fd);
4911516fc7f3Shx147065 exit1:
4912516fc7f3Shx147065 if (iname)
4913516fc7f3Shx147065 (void) close(fddev);
4914516fc7f3Shx147065 exit0:
4915516fc7f3Shx147065 free(gbuf);
4916516fc7f3Shx147065 return (ret);
4917516fc7f3Shx147065 }
4918516fc7f3Shx147065
4919516fc7f3Shx147065 #ifdef DEBUG
4920516fc7f3Shx147065 static void
wifi_dbgprintf(char * fmt,...)4921516fc7f3Shx147065 wifi_dbgprintf(char *fmt, ...)
4922516fc7f3Shx147065 {
4923516fc7f3Shx147065 va_list ap;
4924516fc7f3Shx147065 va_start(ap, fmt);
4925516fc7f3Shx147065 (void) vfprintf(stdout, fmt, ap);
4926516fc7f3Shx147065 va_end(ap);
4927516fc7f3Shx147065 }
4928516fc7f3Shx147065 #endif
4929