1995Shx147065 /*
2995Shx147065 * CDDL HEADER START
3995Shx147065 *
4995Shx147065 * The contents of this file are subject to the terms of the
5*6834Sff224033 * Common Development and Distribution License (the "License").
6*6834Sff224033 * You may not use this file except in compliance with the License.
7995Shx147065 *
8995Shx147065 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9995Shx147065 * or http://www.opensolaris.org/os/licensing.
10995Shx147065 * See the License for the specific language governing permissions
11995Shx147065 * and limitations under the License.
12995Shx147065 *
13995Shx147065 * When distributing Covered Code, include this CDDL HEADER in each
14995Shx147065 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15995Shx147065 * If applicable, add the following below this CDDL HEADER, with the
16995Shx147065 * fields enclosed by brackets "[]" replaced with your own identifying
17995Shx147065 * information: Portions Copyright [yyyy] [name of copyright owner]
18995Shx147065 *
19995Shx147065 * CDDL HEADER END
20995Shx147065 */
21995Shx147065 /*
22*6834Sff224033 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23995Shx147065 * Use is subject to license terms.
24995Shx147065 */
25995Shx147065
26995Shx147065 #pragma ident "%Z%%M% %I% %E% SMI"
27995Shx147065
28995Shx147065 #include <stdio.h>
29995Shx147065 #include <stdlib.h>
30995Shx147065 #include <stddef.h>
31995Shx147065 #include <errno.h>
32995Shx147065 #include <ctype.h>
33995Shx147065 #include <stdarg.h>
34995Shx147065 #include <fcntl.h>
35995Shx147065 #include <unistd.h>
36995Shx147065 #include <net/if.h>
37995Shx147065 #include <sys/types.h>
38995Shx147065 #include <sys/stat.h>
39995Shx147065 #include <sys/wait.h>
40995Shx147065 #include <sys/ipc.h>
41995Shx147065 #include <sys/ddi.h>
42995Shx147065 #include <stropts.h>
43995Shx147065 #include <assert.h>
44995Shx147065 #include <termios.h>
45995Shx147065 #include <time.h>
46995Shx147065 #include <string.h>
47995Shx147065 #include <strings.h>
48995Shx147065 #include <auth_attr.h>
49995Shx147065 #include <auth_list.h>
50995Shx147065 #include <libdevinfo.h>
51995Shx147065 #include <secdb.h>
52995Shx147065 #include <priv.h>
53995Shx147065 #include <pwd.h>
54995Shx147065 #include <umem.h>
55995Shx147065 #include <locale.h>
56995Shx147065 #include <libintl.h>
57995Shx147065 #include <dirent.h>
58995Shx147065 #include <inet/wifi_ioctl.h>
59995Shx147065
60995Shx147065 /*
61995Shx147065 * Debug information
62995Shx147065 */
63995Shx147065 #ifdef DEBUG
64995Shx147065 int wifi_debug = 0;
65995Shx147065 void wifi_dbgprintf(char *fmt, ...);
66995Shx147065 #define PRTDBG(msg) if (wifi_debug > 1) wifi_dbgprintf msg
67995Shx147065 #else /* DEBUG */
68995Shx147065 #define PRTDBG(msg)
69995Shx147065 #endif /* DEBUG */
70995Shx147065
71995Shx147065 #define MAX_HISTORY_NUM 10
72995Shx147065 #define MAX_PREFERENCE_NUM 10
73995Shx147065 #define MAX_SCANBUF_LEN 256
74995Shx147065 #define MAX_CONFIG_FILE_LENGTH 256
75995Shx147065 #define MAX_LOADPF_LENGTH 256
76995Shx147065 #define LOADPROFILE_TIMEOUT 10
77995Shx147065 #define RECORD_ADD 0
78995Shx147065 #define RECORD_DEL 1
79995Shx147065 /*
80995Shx147065 * Wificonfig exit status
81995Shx147065 */
82995Shx147065 #define WIFI_EXIT_DEF 0
83995Shx147065 #define WIFI_FATAL_ERR 1
84995Shx147065 #define WIFI_IMPROPER_USE 2
85995Shx147065 #define WIFI_MINOR_ERR 3
86995Shx147065
87995Shx147065 #define WIFI_LOCKF "/var/run/lockf_wifi"
88995Shx147065
89995Shx147065 typedef enum {
90995Shx147065 PREFERENCE,
91995Shx147065 HISTORY,
92995Shx147065 ACTIVEP,
93995Shx147065 PROFILE,
94995Shx147065 OTHER
95995Shx147065 } list_type_t;
96995Shx147065
97995Shx147065 #define WIFI_PREFER "{preference}"
98995Shx147065 #define WIFI_HISTORY "{history}"
99995Shx147065 #define WIFI_ACTIVEP "{active_profile}"
100995Shx147065
101995Shx147065 typedef enum {
102995Shx147065 LINKSTATUS = 0,
103995Shx147065 BSSID,
104995Shx147065 ESSID,
105995Shx147065 BSSTYPE,
106995Shx147065 CREATEIBSS,
107995Shx147065 CHANNEL,
108995Shx147065 RATES,
109995Shx147065 POWERMODE,
110995Shx147065 AUTHMODE,
111995Shx147065 ENCRYPTION,
112995Shx147065 WEPKEYID,
113995Shx147065 WEPKEY,
114995Shx147065 SIGNAL,
115995Shx147065 RADIOON,
116995Shx147065 WLANLIST,
117995Shx147065 CONFIG_ITEM_END /* 15 */
118995Shx147065 } config_item_t;
119995Shx147065 typedef struct ae {
120995Shx147065 struct ae *ae_next;
121995Shx147065 char *ae_arg;
122995Shx147065 }ae_t;
123995Shx147065 typedef struct aelist {
124995Shx147065 int ael_argc;
125995Shx147065 ae_t *ael_head, *ael_tail;
126995Shx147065 list_type_t type;
127995Shx147065 }aelist_t;
128995Shx147065 typedef struct section {
129995Shx147065 struct section *section_next;
130995Shx147065 aelist_t *list;
131995Shx147065 char *section_id;
132995Shx147065 }section_t;
133995Shx147065
134995Shx147065 /*
135995Shx147065 * config_file_t is an abstract of configration file,
136995Shx147065 * either/etc/inet/wifi/wifi.<interface> or /etc/inet/secret/
137995Shx147065 * wifi/wifiwepkey.<interface>
138995Shx147065 */
139995Shx147065 typedef struct config_file {
140995Shx147065 int section_argc;
141995Shx147065 section_t *section_head, *section_tail;
142995Shx147065 }config_file_t;
143995Shx147065
144995Shx147065 static config_file_t *gp_config_file = NULL;
145995Shx147065 static config_file_t *gp_wepkey_file = NULL;
146995Shx147065 static char *p_file_wifi = "/etc/inet/wifi";
147995Shx147065 static char *p_file_wifiwepkey = "/etc/inet/secret/wifiwepkey";
148995Shx147065
149995Shx147065 typedef enum {
150995Shx147065 AUTH_WEP = 0,
151995Shx147065 AUTH_OTHER = 1
152995Shx147065 } wifi_auth_t;
153995Shx147065
154995Shx147065 static char *p_auth_string[] = {
155995Shx147065 WIFI_WEP_AUTH,
156995Shx147065 WIFI_CONFIG_AUTH
157995Shx147065 };
158995Shx147065
159995Shx147065 /*
160995Shx147065 * gbuf: is a global buf, which is used to communicate between the user and
161995Shx147065 * the driver
162995Shx147065 */
163995Shx147065 static wldp_t *gbuf = NULL;
164995Shx147065 static char *gExecName = NULL;
165995Shx147065
166995Shx147065 static void print_error(uint32_t);
167995Shx147065 static void *safe_malloc(size_t);
168995Shx147065 static void *safe_calloc(size_t, size_t);
169995Shx147065 static char *safe_strdup(const char *s1);
170995Shx147065 static void safe_snprintf(char *s, size_t n,
171995Shx147065 const char *format, ...);
172995Shx147065 static void safe_fclose(FILE *stream);
173995Shx147065 static void new_ae(aelist_t *ael, const char *arg);
174995Shx147065 static aelist_t *new_ael(list_type_t type);
175995Shx147065 static config_file_t *new_config_file();
176995Shx147065 static void new_section(config_file_t *p_config_file, aelist_t *p_list,
177995Shx147065 const char *section_id);
178995Shx147065 static void destroy_config(config_file_t *p_config_file);
179995Shx147065 static config_file_t *parse_file(const char *pfile);
180995Shx147065 static char **aeltoargv(aelist_t *ael, int *ael_num);
181995Shx147065 static boolean_t fprint_config_file(config_file_t *p_config_file,
182995Shx147065 const char *file_name);
183995Shx147065 static char *append_pa(const char *arg);
184995Shx147065 static section_t *find_section(config_file_t *p_config_file,
185995Shx147065 const char *section_id);
186995Shx147065 static ae_t *find_ae(aelist_t *plist, const char *arg);
187995Shx147065 static void update_aelist(aelist_t *plist, const char *arg);
188995Shx147065 static const char *get_value(const char *arg);
189995Shx147065 static char *find_active_profile(int);
190995Shx147065 static const char *essid_of_profile(const char *profile);
191995Shx147065 static boolean_t search_interface(char *interface);
192995Shx147065 static int open_dev(char *devname);
193995Shx147065 static boolean_t call_ioctl(int, int, uint32_t, uint32_t);
194995Shx147065 static boolean_t del_prefer(config_file_t *p_config_file, const char *prefer,
195995Shx147065 boolean_t rflag);
196995Shx147065 static boolean_t del_section(config_file_t *p_config_file, char *section_id);
197995Shx147065 static boolean_t set_prefer(config_file_t *p_config_file, const char *prefer,
198995Shx147065 int rank);
199995Shx147065 static void add_to_history(config_file_t *p_config_file,
200995Shx147065 int argc, char **argv);
201995Shx147065 static boolean_t check_authority(wifi_auth_t type);
202995Shx147065 static void heuristic_load(int fd, uint32_t ess_num, wl_ess_conf_t **);
203995Shx147065 static char *select_profile(int fd, int readonly, int timeout);
204995Shx147065 static char *construct_format(uint32_t nt);
205995Shx147065 static void print_gbuf(config_item_t index);
206995Shx147065 static boolean_t items_in_profile(aelist_t *, aelist_t *, int, char **);
207995Shx147065 static char *get_commit_key(int, int, char **);
208995Shx147065 static void print_wepkey_info(const char *id, const char *wepkeyn);
209995Shx147065 static void do_print_usage();
210995Shx147065 static boolean_t do_print_support_params(int fd);
211995Shx147065 static boolean_t do_autoconf(int fd, int argc, char **argv);
212995Shx147065 static boolean_t do_startconf(int fd, int argc, char **argv);
213995Shx147065 static boolean_t do_loadpf(int fd, int argc, char **argv);
214995Shx147065 static boolean_t do_disconnect(int fd, int argc, char **argv);
215995Shx147065 static boolean_t do_printpf(int fd, int argc, char **argv);
216995Shx147065 static boolean_t do_restoredef(int fd, int argc, char **argv);
217995Shx147065 static boolean_t do_history(int fd, int argc, char **argv);
218995Shx147065 static boolean_t do_deletepf(int fd, int argc, char **argv);
219995Shx147065 static boolean_t do_wepkey(int fd, int argc, char **argv);
220995Shx147065 static boolean_t do_setprefer(int fd, int argc, char **arg);
221995Shx147065 static boolean_t do_rmprefer(int fd, int argc, char **argv);
222995Shx147065 static boolean_t do_lsprefer(int fd, int argc, char **argv);
223995Shx147065 static boolean_t do_wlanlist(int fd, int argc, char **argv);
224995Shx147065 static boolean_t do_showstatus(int fd, int argc, char **argv);
225995Shx147065 static boolean_t do_getprofparam(int fd, int argc, char **argv);
226995Shx147065 static boolean_t do_setprofparam(int fd, int argc, char **argv);
227995Shx147065 static boolean_t do_setprofwepkey(int fd, int argc, char **argv);
228995Shx147065 static boolean_t is_rates_support(int fd, int num, uint8_t *rates);
229995Shx147065 static boolean_t do_set_bsstype(int fd, const char *arg);
230995Shx147065 static boolean_t do_set_essid(int fd, const char *arg);
231995Shx147065 static boolean_t do_set_powermode(int fd, const char *arg);
232995Shx147065 static boolean_t do_set_rates(int fd, const char *arg);
233995Shx147065 static boolean_t do_set_channel(int fd, const char *arg);
234995Shx147065 static boolean_t do_set_createibss(int fd, const char *arg);
235995Shx147065 static boolean_t do_set_radioon(int fd, const char *arg);
236995Shx147065 static boolean_t do_set_wepkeyid(int fd, const char *arg);
237995Shx147065 static boolean_t do_set_encryption(int fd, const char *arg);
238995Shx147065 static boolean_t do_set_authmode(int fd, const char *arg);
239995Shx147065 static boolean_t do_set_wepkey(int fd, const char *pbuf);
240995Shx147065 static boolean_t do_get_createibss(int fd);
241995Shx147065 static boolean_t do_get_bsstype(int fd);
242995Shx147065 static boolean_t do_get_essid(int fd);
243995Shx147065 static boolean_t do_get_bssid(int fd);
244995Shx147065 static boolean_t do_get_radioon(int fd);
245995Shx147065 static boolean_t do_get_signal(int fd);
246995Shx147065 static boolean_t do_get_wepkeyid(int fd);
247995Shx147065 static boolean_t do_get_encryption(int fd);
248995Shx147065 static boolean_t do_get_authmode(int fd);
249995Shx147065 static boolean_t do_get_powermode(int fd);
250995Shx147065 static boolean_t do_get_rates(int fd);
251995Shx147065 static boolean_t do_get_wlanlist(int fd);
252995Shx147065 static boolean_t do_get_linkstatus(int fd);
253995Shx147065 static boolean_t do_get_channel(int fd);
254995Shx147065 static boolean_t do_get(int fd, int argc, char **argv);
255995Shx147065 static boolean_t do_set(int fd, int argc, char **argv);
256995Shx147065 static boolean_t do_createprofile(int fd, int argc, char **argv);
257995Shx147065 static boolean_t value_is_valid(config_item_t item, const char *value);
258995Shx147065
259995Shx147065 typedef struct cmd_ops {
260995Shx147065 char cmd[32];
261995Shx147065 boolean_t (*p_do_func)(int fd, int argc, char **argv);
262995Shx147065 boolean_t b_auth;
263995Shx147065 boolean_t b_fileonly; /* operation only on the config file */
264995Shx147065 boolean_t b_readonly; /* only read from the card or config file */
265995Shx147065 } cmd_ops_t;
266995Shx147065 static cmd_ops_t do_func[] = {
267995Shx147065 {
268995Shx147065 "autoconf",
269995Shx147065 do_autoconf,
270995Shx147065 B_TRUE,
271995Shx147065 B_FALSE,
272995Shx147065 B_FALSE
273995Shx147065 },
274995Shx147065 {
275995Shx147065 "startconf",
276995Shx147065 do_startconf,
277995Shx147065 B_TRUE,
278995Shx147065 B_FALSE,
279995Shx147065 B_TRUE
280995Shx147065 },
281995Shx147065 {
282995Shx147065 "connect",
283995Shx147065 do_loadpf,
284995Shx147065 B_TRUE,
285995Shx147065 B_FALSE,
286995Shx147065 B_FALSE
287995Shx147065 },
288995Shx147065 {
289995Shx147065 "disconnect",
290995Shx147065 do_disconnect,
291995Shx147065 B_TRUE,
292995Shx147065 B_FALSE,
293995Shx147065 B_FALSE
294995Shx147065 },
295995Shx147065 {
296995Shx147065 "showprofile",
297995Shx147065 do_printpf,
298995Shx147065 B_FALSE,
299995Shx147065 B_TRUE,
300995Shx147065 B_TRUE
301995Shx147065 },
302995Shx147065 {
303995Shx147065 "deleteprofile",
304995Shx147065 do_deletepf,
305995Shx147065 B_TRUE,
306995Shx147065 B_TRUE,
307995Shx147065 B_FALSE
308995Shx147065 },
309995Shx147065 {
310995Shx147065 "history",
311995Shx147065 do_history,
312995Shx147065 B_FALSE,
313995Shx147065 B_TRUE,
314995Shx147065 B_TRUE
315995Shx147065 },
316995Shx147065 {
317995Shx147065 "listprefer",
318995Shx147065 do_lsprefer,
319995Shx147065 B_FALSE,
320995Shx147065 B_TRUE,
321995Shx147065 B_TRUE
322995Shx147065 },
323995Shx147065 {
324995Shx147065 "removeprefer",
325995Shx147065 do_rmprefer,
326995Shx147065 B_TRUE,
327995Shx147065 B_TRUE,
328995Shx147065 B_FALSE
329995Shx147065 },
330995Shx147065 {
331995Shx147065 "setprefer",
332995Shx147065 do_setprefer,
333995Shx147065 B_TRUE,
334995Shx147065 B_TRUE,
335995Shx147065 B_FALSE
336995Shx147065 },
337995Shx147065 {
338995Shx147065 "setwepkey",
339995Shx147065 do_wepkey,
340995Shx147065 B_TRUE,
341995Shx147065 B_FALSE,
342995Shx147065 B_FALSE
343995Shx147065 },
344995Shx147065 {
345995Shx147065 "restoredef",
346995Shx147065 do_restoredef,
347995Shx147065 B_TRUE,
348995Shx147065 B_FALSE,
349995Shx147065 B_FALSE
350995Shx147065 },
351995Shx147065 {
352995Shx147065 "getparam",
353995Shx147065 do_get,
354995Shx147065 B_FALSE,
355995Shx147065 B_FALSE,
356995Shx147065 B_TRUE
357995Shx147065 },
358995Shx147065 {
359995Shx147065 "setparam",
360995Shx147065 do_set,
361995Shx147065 B_TRUE,
362995Shx147065 B_FALSE,
363995Shx147065 B_FALSE
364995Shx147065 },
365995Shx147065 {
366995Shx147065 "createprofile",
367995Shx147065 do_createprofile,
368995Shx147065 B_TRUE,
369995Shx147065 B_TRUE,
370995Shx147065 B_FALSE
371995Shx147065 },
372995Shx147065 {
373995Shx147065 "scan",
374995Shx147065 do_wlanlist,
375995Shx147065 B_FALSE,
376995Shx147065 B_FALSE,
377995Shx147065 B_FALSE
378995Shx147065 },
379995Shx147065 {
380995Shx147065 "showstatus",
381995Shx147065 do_showstatus,
382995Shx147065 B_FALSE,
383995Shx147065 B_FALSE,
384995Shx147065 B_TRUE
385995Shx147065 },
386995Shx147065 {
387995Shx147065 "setprofileparam",
388995Shx147065 do_setprofparam,
389995Shx147065 B_TRUE,
390995Shx147065 B_TRUE,
391995Shx147065 B_FALSE
392995Shx147065 },
393995Shx147065 {
394995Shx147065 "getprofileparam",
395995Shx147065 do_getprofparam,
396995Shx147065 B_FALSE,
397995Shx147065 B_TRUE,
398995Shx147065 B_TRUE
399995Shx147065 },
400995Shx147065 {
401995Shx147065 "setprofilewepkey",
402995Shx147065 do_setprofwepkey,
403995Shx147065 B_TRUE,
404995Shx147065 B_TRUE,
405995Shx147065 B_FALSE
406995Shx147065 }
407995Shx147065 };
408995Shx147065
409995Shx147065
410995Shx147065 typedef enum {RW, RO, WO} rw_property_t;
411995Shx147065 typedef struct gs_ops {
412995Shx147065 config_item_t index;
413995Shx147065 char cmd[32];
414995Shx147065 boolean_t (*p_do_get_func)(int fd);
415995Shx147065 boolean_t (*p_do_set_func)(int fd, const char *arg);
416995Shx147065 rw_property_t rw;
417995Shx147065 } gs_ops_t;
418995Shx147065 static gs_ops_t do_gs_func[] = {
419995Shx147065 {LINKSTATUS, "linkstatus", NULL, NULL, RO},
420995Shx147065 {BSSID, "bssid", do_get_bssid, NULL, RO},
421995Shx147065 {ESSID, "essid", do_get_essid, do_set_essid, RW},
422995Shx147065 {BSSTYPE, "bsstype", do_get_bsstype, do_set_bsstype, RW},
423995Shx147065 {CREATEIBSS, "createibss", do_get_createibss, do_set_createibss, RW},
424995Shx147065 {CHANNEL, "channel", do_get_channel, do_set_channel, RW},
425995Shx147065 {RATES, "rates", do_get_rates, do_set_rates, RW},
426995Shx147065 {POWERMODE, "powermode", do_get_powermode, do_set_powermode, RW},
427995Shx147065 {AUTHMODE, "authmode", do_get_authmode, do_set_authmode, RW},
428995Shx147065 {ENCRYPTION, "encryption", do_get_encryption, do_set_encryption, RW},
429995Shx147065 {WEPKEYID, "wepkeyindex", do_get_wepkeyid, do_set_wepkeyid, RW},
430995Shx147065 {WEPKEY, "wepkey|1-4", NULL, do_set_wepkey, WO},
431995Shx147065 {SIGNAL, "signal", do_get_signal, NULL, RO},
432995Shx147065 {RADIOON, "radio", do_get_radioon, do_set_radioon, RW},
433995Shx147065 };
434995Shx147065
435995Shx147065 #define N_FUNC sizeof (do_func) / sizeof (cmd_ops_t)
436995Shx147065 #define N_GS_FUNC sizeof (do_gs_func) / sizeof (gs_ops_t)
437995Shx147065
438995Shx147065 /*
439995Shx147065 * valid rate value
440995Shx147065 */
441995Shx147065 typedef struct wifi_rates_tab {
442995Shx147065 char *rates_s;
443995Shx147065 uint8_t rates_i;
444995Shx147065 uint8_t rates_reserve0;
445995Shx147065 uint8_t rates_reserve1;
446995Shx147065 uint8_t rates_reserve2;
447995Shx147065 } wifi_rates_tab_t;
448995Shx147065
449995Shx147065 /*
450995Shx147065 * the rates value is in increments of 500kb/s.
451995Shx147065 * according to the 802.11 a/b/g specs(IEEE):
452995Shx147065 * 802.11b(IEEE Std 802.11b-1999) page35, rates should be:
453995Shx147065 * X02, X04, X0b, X16
454995Shx147065 * 802.11a(IEEE Std 802.11a-1999) page47, rates should be:
455995Shx147065 * 6,9,12,18,24,36,48,54 Mb/s
456995Shx147065 * 802.11g(IEEE Std 802.11g-2003) page44, rates should be:
457995Shx147065 * 1,2,5.5,11,6,9,12,18,22,24,33,36,48,54 Mb/s
458995Shx147065 */
459995Shx147065 #define WIFI_RATES_NUM 14
460995Shx147065 static wifi_rates_tab_t wifi_rates_s[WIFI_RATES_NUM] = {
461995Shx147065 {"1", WL_RATE_1M, 0, 0, 0},
462995Shx147065 {"2", WL_RATE_2M, 0, 0, 0},
463995Shx147065 {"5.5", WL_RATE_5_5M, 0, 0, 0},
464995Shx147065 {"6", WL_RATE_6M, 0, 0, 0},
465995Shx147065 {"9", WL_RATE_9M, 0, 0, 0},
466995Shx147065 {"11", WL_RATE_11M, 0, 0, 0},
467995Shx147065 {"12", WL_RATE_12M, 0, 0, 0},
468995Shx147065 {"18", WL_RATE_18M, 0, 0, 0},
469995Shx147065 {"22", WL_RATE_22M, 0, 0, 0},
470995Shx147065 {"24", WL_RATE_24M, 0, 0, 0},
471995Shx147065 {"33", WL_RATE_33M, 0, 0, 0},
472995Shx147065 {"36", WL_RATE_36M, 0, 0, 0},
473995Shx147065 {"48", WL_RATE_48M, 0, 0, 0},
474995Shx147065 {"54", WL_RATE_54M, 0, 0, 0}
475995Shx147065 };
476995Shx147065 /* print the error message on why set or get ioctl command failed. */
477995Shx147065 static void
print_error(uint32_t errorno)478995Shx147065 print_error(uint32_t errorno)
479995Shx147065 {
480995Shx147065 char *buf;
481995Shx147065
482995Shx147065 switch (errorno) {
483995Shx147065 case WL_SUCCESS:
484995Shx147065 buf = gettext("command succeeded");
485995Shx147065 break;
486995Shx147065 case WL_NOTSUPPORTED:
487995Shx147065 case WL_LACK_FEATURE:
488995Shx147065 case WL_HW_ERROR:
489995Shx147065 case WL_ACCESS_DENIED:
490995Shx147065 buf = strerror(errorno);
491995Shx147065 break;
492995Shx147065 case WL_READONLY:
493995Shx147065 buf = gettext("parameter read-only");
494995Shx147065 break;
495995Shx147065 case WL_WRITEONLY:
496995Shx147065 buf = gettext("parameter write-only");
497995Shx147065 break;
498995Shx147065 case WL_NOAP:
499995Shx147065 buf = gettext("no access point available");
500995Shx147065 break;
501995Shx147065 default:
502995Shx147065 buf = gettext("unknown error");
503995Shx147065 break;
504995Shx147065 }
505995Shx147065 (void) fprintf(stderr, "%s\n", buf);
506995Shx147065 }
507995Shx147065
508995Shx147065 static void *
safe_malloc(size_t size)509995Shx147065 safe_malloc(size_t size)
510995Shx147065 {
511995Shx147065 void *buf;
512995Shx147065
513995Shx147065 buf = malloc(size);
514995Shx147065 if (buf == NULL) {
515995Shx147065 (void) fprintf(stderr, gettext("%s: malloc: %s\n"),
516995Shx147065 gExecName, strerror(errno));
517995Shx147065 exit(WIFI_FATAL_ERR);
518995Shx147065 }
519995Shx147065 return (buf);
520995Shx147065 }
521995Shx147065
522995Shx147065 static void *
safe_calloc(size_t nelem,size_t elsize)523995Shx147065 safe_calloc(size_t nelem, size_t elsize)
524995Shx147065 {
525995Shx147065 void *buf;
526995Shx147065
527995Shx147065 buf = calloc(nelem, elsize);
528995Shx147065 if (buf == NULL) {
529995Shx147065 (void) fprintf(stderr, gettext("%s: calloc: %s\n"),
530995Shx147065 gExecName, strerror(errno));
531995Shx147065 exit(WIFI_FATAL_ERR);
532995Shx147065 }
533995Shx147065 return (buf);
534995Shx147065 }
535995Shx147065
536995Shx147065 static char *
safe_strdup(const char * s1)537995Shx147065 safe_strdup(const char *s1)
538995Shx147065 {
539995Shx147065 char *p;
540995Shx147065
541995Shx147065 p = strdup(s1);
542995Shx147065 if (p == NULL) {
543995Shx147065 (void) fprintf(stderr, gettext("%s: strdup: %s\n"),
544995Shx147065 gExecName, strerror(errno));
545995Shx147065 exit(WIFI_FATAL_ERR);
546995Shx147065 }
547995Shx147065 return (p);
548995Shx147065 }
549995Shx147065
550995Shx147065 static void
safe_snprintf(char * s,size_t n,const char * format,...)551995Shx147065 safe_snprintf(char *s, size_t n, const char *format, ...)
552995Shx147065 {
553995Shx147065 int len;
554995Shx147065 va_list ap;
555995Shx147065 va_start(ap, format);
556995Shx147065
557995Shx147065 len = vsnprintf(s, n, format, ap);
558995Shx147065 if ((len <= 0) || (len > n - 1)) {
559995Shx147065 (void) fprintf(stderr,
560995Shx147065 gettext("%s: snprintf: %s\n"),
561995Shx147065 gExecName, strerror(errno));
562995Shx147065 exit(WIFI_FATAL_ERR);
563995Shx147065 }
564995Shx147065 va_end(ap);
565995Shx147065 }
566995Shx147065
567995Shx147065 static void
safe_fclose(FILE * stream)568995Shx147065 safe_fclose(FILE *stream)
569995Shx147065 {
570995Shx147065 int err;
571995Shx147065
572995Shx147065 err = fclose(stream);
573995Shx147065 if (err == EOF) {
574995Shx147065 (void) fprintf(stderr, gettext("%s: fclose: %s\n"),
575995Shx147065 gExecName, strerror(errno));
576995Shx147065 exit(WIFI_FATAL_ERR);
577995Shx147065 }
578995Shx147065 }
579995Shx147065 /*
580995Shx147065 * new_ae: Add an element with content pointed by arg to the list *ael.
581995Shx147065 */
582995Shx147065 static void
new_ae(aelist_t * ael,const char * arg)583995Shx147065 new_ae(aelist_t *ael, const char *arg)
584995Shx147065 {
585995Shx147065 ae_t *pae = NULL;
586995Shx147065
587995Shx147065 PRTDBG(("new_ae(0x%x, \"%s\")\n", ael, arg));
588995Shx147065 assert((ael != NULL) && (arg != NULL));
589995Shx147065
590995Shx147065 pae = safe_calloc(sizeof (*pae), 1);
591995Shx147065 pae->ae_arg = safe_strdup(arg);
592995Shx147065 pae->ae_next = NULL;
593995Shx147065
594995Shx147065 if (ael->ael_tail == NULL) {
595995Shx147065 ael->ael_head = pae;
596995Shx147065 } else {
597995Shx147065 ael->ael_tail->ae_next = pae;
598995Shx147065 }
599995Shx147065 ael->ael_tail = pae;
600995Shx147065 ael->ael_argc++;
601995Shx147065 }
602995Shx147065 /*
603995Shx147065 * new_ael: Create a new aelist with list_type "type"
604995Shx147065 * and return the list pointer.
605995Shx147065 */
606995Shx147065 static aelist_t *
new_ael(list_type_t type)607995Shx147065 new_ael(list_type_t type)
608995Shx147065 {
609995Shx147065 aelist_t *plist;
610995Shx147065
611995Shx147065 plist = safe_calloc(sizeof (*plist), 1);
612995Shx147065 plist->type = type;
613995Shx147065 plist->ael_argc = 0;
614995Shx147065 plist->ael_head = plist->ael_tail = NULL;
615995Shx147065
616995Shx147065 PRTDBG(("new_ael(%d) = 0x%x\n", type, plist));
617995Shx147065 return (plist);
618995Shx147065 }
619995Shx147065
620995Shx147065 /*
621995Shx147065 * new_config_file: Creates a new config_file_t struct which is counterpart of
622995Shx147065 * of the configration file, and return the pointer.
623995Shx147065 */
624995Shx147065 static config_file_t *
new_config_file()625995Shx147065 new_config_file()
626995Shx147065 {
627995Shx147065 config_file_t *p_config_file;
628995Shx147065
629995Shx147065 p_config_file = safe_calloc(sizeof (config_file_t), 1);
630995Shx147065 p_config_file->section_argc = 0;
631995Shx147065 p_config_file->section_head = p_config_file->section_tail = NULL;
632995Shx147065
633995Shx147065 PRTDBG(("new_config_file() = 0x%x\n", p_config_file));
634995Shx147065 return (p_config_file);
635995Shx147065 }
636995Shx147065
637995Shx147065 /*
638995Shx147065 * new_section: Add a list pointed by "p_list", with identity "section_id" to
639995Shx147065 * the config_file_t struct pointed by "p_config_file"
640995Shx147065 */
641995Shx147065 static void
new_section(config_file_t * p_config_file,aelist_t * p_list,const char * section_id)642995Shx147065 new_section(config_file_t *p_config_file, aelist_t *p_list,
643995Shx147065 const char *section_id)
644995Shx147065 {
645995Shx147065 section_t *p_section = NULL;
646995Shx147065
647995Shx147065 PRTDBG(("new_section(0x%x, 0x%x, \"%s\")\n", p_config_file, p_list,
648995Shx147065 section_id));
649995Shx147065 assert((p_config_file != NULL) && (p_list != NULL) &&
650995Shx147065 (section_id != NULL));
651995Shx147065
652995Shx147065 p_section = safe_calloc(sizeof (*p_section), 1);
653995Shx147065 p_section->list = p_list;
654995Shx147065 p_section->section_next = NULL;
655995Shx147065 p_section->section_id = safe_strdup(section_id);
656995Shx147065
657995Shx147065 if (p_config_file->section_tail == NULL) {
658995Shx147065 p_config_file->section_head = p_section;
659995Shx147065 } else {
660995Shx147065 p_config_file->section_tail->section_next = p_section;
661995Shx147065 }
662995Shx147065 p_config_file->section_tail = p_section;
663995Shx147065 p_config_file->section_argc++;
664995Shx147065 }
665995Shx147065
666995Shx147065 /*
667995Shx147065 * destroy_config:Destroy the config_file struct
668995Shx147065 */
669995Shx147065 static void
destroy_config(config_file_t * p_config_file)670995Shx147065 destroy_config(config_file_t *p_config_file)
671995Shx147065 {
672995Shx147065 section_t *p_section = NULL;
673995Shx147065 aelist_t *p_list = NULL;
674995Shx147065 ae_t *pae = NULL;
675995Shx147065
676995Shx147065 PRTDBG(("destory_config(0x%x)\n", p_config_file));
677995Shx147065 assert(p_config_file != NULL);
678995Shx147065
679995Shx147065 p_section = p_config_file->section_head;
680995Shx147065 while (p_section != NULL) {
681995Shx147065 p_list = p_section->list;
682995Shx147065 if (p_list != NULL) {
683995Shx147065 pae = p_list->ael_head;
684995Shx147065 while (pae != NULL) {
685995Shx147065 if (pae->ae_arg != NULL)
686995Shx147065 free(pae->ae_arg);
687995Shx147065 pae->ae_arg = NULL;
688995Shx147065 pae = pae->ae_next;
689995Shx147065 free(p_list->ael_head);
690995Shx147065 p_list->ael_head = pae;
691995Shx147065 }
692995Shx147065 free(p_list);
693995Shx147065 p_list = NULL;
694995Shx147065 }
695995Shx147065 if (p_section->section_id != NULL)
696995Shx147065 free(p_section->section_id);
697995Shx147065 p_section->section_id = NULL;
698995Shx147065 p_section = p_section->section_next;
699995Shx147065 free(p_config_file->section_head);
700995Shx147065 p_config_file->section_head = p_section;
701995Shx147065 }
702995Shx147065 free(p_config_file);
703995Shx147065 p_config_file = NULL;
704995Shx147065 }
705995Shx147065
706995Shx147065 /*
707995Shx147065 * parse_file: Parse each section of the configration file
708995Shx147065 * and construct the config_file_t structure.
709995Shx147065 * Example:
710995Shx147065 * A config file has contents below:
711995Shx147065 *
712995Shx147065 * {preferrence}
713995Shx147065 * essid=ap7-3
714995Shx147065 * essid=linksys
715995Shx147065 *
716995Shx147065 * {history}
717995Shx147065 * essid=ap7-3
718995Shx147065 * essid=ap7-2
719995Shx147065 *
720995Shx147065 * [ap7-3]
721995Shx147065 * essid=ap7-3
722995Shx147065 * wepkeyid=3
723995Shx147065 * channel=11
724995Shx147065 * rates=1,2
725995Shx147065 *
726995Shx147065 * [linksys]
727995Shx147065 * essid=linksys
728995Shx147065 * createibss=BSS
729995Shx147065 * authmode=OPENSYSTEM
730995Shx147065 * wepkeyid=1
731995Shx147065 *
732995Shx147065 * then its config_file_t structure will be:
733995Shx147065 *
734995Shx147065 * config_file_t
735995Shx147065 * |~~~~~~~~~~~~~~~~~~~~~~~~~~|
736995Shx147065 * | section_argc=5 |
737995Shx147065 * |~~~~~~~~~~~~T~~~~~~~~~~~~~|
738995Shx147065 * /| *head | *tail |\
739995Shx147065 * / ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \
740995Shx147065 * / \
741995Shx147065 * / \
742995Shx147065 * / \
743995Shx147065 * / \
744995Shx147065 * / \
745995Shx147065 * section_t V section_t V section_t
746995Shx147065 * |~~~~~~~~~~~~~~~|~~| |~~~~~~~~~~~~~~~|~~| |~~~~~~~~~~~~~~|~~|
747995Shx147065 * |"{preferrence}"| | | "{history}" | | | "[linksys]" | |
748995Shx147065 * |~~~~~~~~~~~~~~~| -+---->|~~~~~~~~~~~~~~~| -+->..->|~~~~~~~~~~~~~~| -+->NULL
749995Shx147065 * | *list | | | *list | | | *list | |
750995Shx147065 * ~~T~~~~~~~~~~~~~~~~~ ~~~T~~~~~~~~~~~~~~~~ ~~~T~~~~~~~~~~~~~~~
751995Shx147065 * | | |
752995Shx147065 * | | |
753995Shx147065 * V aelist_t V aelist_t V aelist_t
754995Shx147065 * |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| |~~~~~~~~~~~~~|
755995Shx147065 * | argc=2 | | argc=3 | | argc=4 |
756995Shx147065 * |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| |~~~~~~~~~~~~~|
757995Shx147065 * |PREFFERRENCE | | HISTORY | | PROFILE |
758995Shx147065 * |~~~~~~T~~~~~~| |~~~~~~T~~~~~~| |~~~~~~T~~~~~~|
759995Shx147065 * |*head |*tail |\ |*head |*tail |\ |*head |*tail |
760995Shx147065 * ~~T~~~~~~~~~~~~ \ ~~T~~~~~~~~~~~~ \ /~~~~~~~~~~~~~~~\
761995Shx147065 * | \ V V / \
762995Shx147065 * | \ ... ... / \
763995Shx147065 * V ae_t V ae_t ae_t V ae_t V
764995Shx147065 * |~~~~~~~~~T~~| |~~~~~~~~~T~~| |~~~~~~~~~T~~| |~~~~~~~~~T~~|
765995Shx147065 * |"essid= | -+->|"essid= | -+->NULL |"essid= | -+->..->|"wepkeyid| -+->NULL
766995Shx147065 * | ap7-3" | | | linksys"| | | linksys"| | | =1" | |
767995Shx147065 * ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
768995Shx147065 *
769995Shx147065 */
770995Shx147065
771995Shx147065 static config_file_t *
parse_file(const char * pfile)772995Shx147065 parse_file(const char *pfile)
773995Shx147065 {
774995Shx147065 FILE *file = NULL;
775995Shx147065 int fd = 0;
776995Shx147065 char buf_line[256];
777995Shx147065 config_file_t *p_config_file;
778995Shx147065 list_type_t cur_list = OTHER;
779995Shx147065 aelist_t *prefer_list = NULL;
780995Shx147065 aelist_t *history_list = NULL;
781995Shx147065 aelist_t *profile_list = NULL;
782995Shx147065 aelist_t *activep_list = NULL;
783995Shx147065
784995Shx147065 assert(pfile != NULL);
785995Shx147065 /*
786995Shx147065 * The files /etc/inet/wifi and /etc/inet/secret/wifiwepkey should
787995Shx147065 * be opened with "r" attribute. If these two files do not exist,
788995Shx147065 * create them here.
789995Shx147065 */
790995Shx147065 file = fopen(pfile, "r");
791995Shx147065
792995Shx147065 if (file == NULL) {
793995Shx147065 fd = open(pfile, O_CREAT|O_EXCL|O_RDWR, 0600);
794995Shx147065 if (fd < 0) {
795995Shx147065 (void) fprintf(stderr, gettext("%s: failed to open %s"
796995Shx147065 "\n"), gExecName, pfile);
797995Shx147065 goto error1;
798995Shx147065 }
799995Shx147065 file = fdopen(fd, "w");
800995Shx147065 (void) chmod(pfile, S_IRUSR);
801995Shx147065 }
802995Shx147065
803995Shx147065 p_config_file = new_config_file();
804995Shx147065
805995Shx147065 while (fgets(buf_line, sizeof (buf_line), file) != NULL) {
806995Shx147065 if ((buf_line[0] == '\n') || (buf_line[0] == ' '))
807995Shx147065 continue;
808995Shx147065 /* replace the old '\n' to '\0' */
809995Shx147065 buf_line[strlen(buf_line) - 1] = '\0';
810995Shx147065 if (strstr(buf_line, WIFI_PREFER) == buf_line) {
811995Shx147065 if (prefer_list == NULL) {
812995Shx147065 cur_list = PREFERENCE;
813995Shx147065 prefer_list = new_ael(PREFERENCE);
814995Shx147065 new_section(p_config_file, prefer_list,
815995Shx147065 WIFI_PREFER);
816995Shx147065 } else {
817995Shx147065 (void) fprintf(stderr, gettext("%s: "
818995Shx147065 "%s : duplicated %s section\n"),
819995Shx147065 gExecName, pfile, WIFI_PREFER);
820995Shx147065 goto error;
821995Shx147065 }
822995Shx147065 } else if (strstr(buf_line, WIFI_HISTORY) == buf_line) {
823995Shx147065 if (history_list == NULL) {
824995Shx147065 cur_list = HISTORY;
825995Shx147065 history_list = new_ael(HISTORY);
826995Shx147065 new_section(p_config_file, history_list,
827995Shx147065 WIFI_HISTORY);
828995Shx147065 } else {
829995Shx147065 (void) fprintf(stderr, gettext("%s: "
830995Shx147065 "%s : duplicated %s section\n"),
831995Shx147065 gExecName, pfile, WIFI_HISTORY);
832995Shx147065 goto error;
833995Shx147065 }
834995Shx147065 } else if (strstr(buf_line, WIFI_ACTIVEP) == buf_line) {
835995Shx147065 if (activep_list == NULL) {
836995Shx147065 cur_list = ACTIVEP;
837995Shx147065 activep_list = new_ael(ACTIVEP);
838995Shx147065 new_section(p_config_file, activep_list,
839995Shx147065 WIFI_ACTIVEP);
840995Shx147065 } else {
841995Shx147065 (void) fprintf(stderr, gettext("%s: "
842995Shx147065 "%s : duplicated %s section\n"),
843995Shx147065 gExecName, pfile, WIFI_ACTIVEP);
844995Shx147065 goto error;
845995Shx147065 }
846995Shx147065 } else if ((strchr(buf_line, '[') == buf_line) &&
847995Shx147065 (buf_line[strlen(buf_line) - 1] == ']')) {
848995Shx147065 cur_list = PROFILE;
849995Shx147065 profile_list = new_ael(PROFILE);
850995Shx147065 new_section(p_config_file, profile_list,
851995Shx147065 buf_line);
852995Shx147065 } else {
853995Shx147065 switch (cur_list) {
854995Shx147065 case PREFERENCE:
855995Shx147065 if (prefer_list->ael_argc <=
856995Shx147065 MAX_PREFERENCE_NUM)
857995Shx147065 new_ae(prefer_list, buf_line);
858995Shx147065 break;
859995Shx147065 case HISTORY:
860995Shx147065 if (history_list->ael_argc <=
861995Shx147065 MAX_HISTORY_NUM)
862995Shx147065 new_ae(history_list, buf_line);
863995Shx147065 break;
864995Shx147065 case ACTIVEP:
865995Shx147065 if ((activep_list->ael_argc <= 1) &&
866995Shx147065 (strpbrk(buf_line, "=") != NULL))
867995Shx147065 new_ae(activep_list, buf_line);
868995Shx147065 break;
869995Shx147065 case PROFILE:
870995Shx147065 if (strpbrk(buf_line, "=") != NULL)
871995Shx147065 new_ae(profile_list, buf_line);
872995Shx147065 break;
873995Shx147065 default:
874995Shx147065 (void) fprintf(stderr,
875995Shx147065 gettext("%s: %s: file format error\n"),
876995Shx147065 gExecName, pfile);
877995Shx147065 goto error;
878995Shx147065 }
879995Shx147065 }
880995Shx147065 }
881995Shx147065 PRTDBG(("parse_file(\"%s\")=0x%x\n", pfile, p_config_file));
882995Shx147065 (void) fclose(file);
883995Shx147065 return (p_config_file);
884995Shx147065 error:
885995Shx147065 destroy_config(p_config_file);
886995Shx147065 (void) fclose(file);
887995Shx147065 error1:
888995Shx147065 return (NULL);
889995Shx147065 }
890995Shx147065 /*
891995Shx147065 * construct an argument vector from an aelist
892995Shx147065 */
893995Shx147065 static char **
aeltoargv(aelist_t * ael,int * ael_num)894995Shx147065 aeltoargv(aelist_t *ael, int *ael_num)
895995Shx147065 {
896995Shx147065 ae_t *ae = NULL;
897995Shx147065 char **argv = NULL;
898995Shx147065 int argc = 0;
899995Shx147065
900995Shx147065 PRTDBG(("aeltoargv(%x)\n", ael));
901995Shx147065 assert(ael != NULL);
902995Shx147065
903995Shx147065 argv = safe_calloc(sizeof (*argv), ael->ael_argc);
904995Shx147065
905995Shx147065 for (argc = 0, ae = ael->ael_head; ae; ae = ae->ae_next) {
906995Shx147065 /* skip bssid since it can not be set */
907995Shx147065 if (strncmp(ae->ae_arg, "bssid=", strlen("bssid=")) == 0)
908995Shx147065 continue;
909995Shx147065 argv[argc] = safe_strdup(ae->ae_arg);
910995Shx147065 argc++;
911995Shx147065 if (ae == ael->ael_tail)
912995Shx147065 break;
913995Shx147065 }
914995Shx147065
915995Shx147065 PRTDBG(("aeltoargv(0x%x) = 0x%x\n\n", ael, argv));
916995Shx147065 *ael_num = argc;
917995Shx147065 return (argv);
918995Shx147065 }
919995Shx147065
920995Shx147065 /*
921995Shx147065 * archived contents into a file
922995Shx147065 */
923995Shx147065 static boolean_t
fprint_config_file(config_file_t * p_config_file,const char * file_name)924995Shx147065 fprint_config_file(config_file_t *p_config_file, const char *file_name)
925995Shx147065 {
926995Shx147065 FILE *file = NULL;
927995Shx147065 int fd = 0;
928995Shx147065 int len;
929995Shx147065 section_t *p_section = NULL;
930995Shx147065 aelist_t *p_list = NULL;
931995Shx147065 ae_t *pae = NULL;
932995Shx147065 char temp_file[256];
933995Shx147065 struct stat buf;
934995Shx147065
935995Shx147065 PRTDBG(("fprint_config_file(0x%x, \"%s\")\n", p_config_file,
936*6834Sff224033 file_name));
937995Shx147065 assert((p_config_file != NULL)&&(strcmp(file_name, "") != 0));
938995Shx147065
939995Shx147065 safe_snprintf(temp_file, sizeof (temp_file),
940995Shx147065 "%s.tmp", file_name);
941995Shx147065 fd = open(temp_file, O_CREAT|O_WRONLY|O_TRUNC, 0600);
942995Shx147065 if (fd < 0) {
943995Shx147065 (void) fprintf(stderr, gettext("%s: failed to open %s\n"),
944995Shx147065 gExecName, temp_file);
945995Shx147065 return (B_FALSE);
946995Shx147065 }
947995Shx147065 file = fdopen(fd, "w");
948995Shx147065
949995Shx147065 p_section = p_config_file->section_head;
950995Shx147065 while (p_section != NULL) {
951995Shx147065 p_list = p_section->list;
952995Shx147065 if (p_list != NULL) {
953995Shx147065 PRTDBG(("fprint_config_file: section_id=%s\n",
954995Shx147065 p_section->section_id));
955995Shx147065 len = fprintf(file, "\n%s\n", p_section->section_id);
956995Shx147065 if (len < 0) {
957995Shx147065 (void) fprintf(stderr, gettext("%s: "
958995Shx147065 "failed to update %s: %s\n"),
959995Shx147065 gExecName, file_name, strerror(errno));
960995Shx147065 safe_fclose(file);
961995Shx147065 return (B_FALSE);
962995Shx147065 }
963995Shx147065 pae = p_list->ael_head;
964995Shx147065 while (pae != NULL) {
965995Shx147065 if (pae->ae_arg != NULL) {
966995Shx147065 len = fprintf(file, "%s\n",
967995Shx147065 pae->ae_arg);
968995Shx147065 if (len < 0) {
969995Shx147065 (void) fprintf(stderr,
970995Shx147065 gettext("%s: failed to "
971995Shx147065 "update %s: %s\n"),
972995Shx147065 gExecName, file_name,
973995Shx147065 strerror(errno));
974995Shx147065 safe_fclose(file);
975995Shx147065 return (B_FALSE);
976995Shx147065 }
977995Shx147065 }
978995Shx147065 pae = pae->ae_next;
979995Shx147065 }
980995Shx147065 }
981995Shx147065 p_section = p_section->section_next;
982995Shx147065 }
983995Shx147065 safe_fclose(file);
984995Shx147065 /*
985995Shx147065 * The attribute of the file /etc/inet/wifi and
986995Shx147065 * /etc/inet/security/wifiwepkey should be retained.
987995Shx147065 * if those file do not exist, set default file mode.
988995Shx147065 */
989995Shx147065 if (stat(file_name, &buf) != 0) {
990995Shx147065 if (errno == ENOENT) {
991995Shx147065 buf.st_mode = 0600;
992995Shx147065 } else {
993995Shx147065 (void) fprintf(stderr, gettext("%s: failed to get "
994995Shx147065 "file %s stat: %s\n"),
995995Shx147065 gExecName, file_name, strerror(errno));
996995Shx147065 return (B_FALSE);
997995Shx147065 }
998995Shx147065 }
999995Shx147065 if (rename(temp_file, file_name) != 0) {
1000995Shx147065 (void) fprintf(stderr, gettext("%s: failed to update %s: %s"
1001995Shx147065 "\n"), gExecName, file_name, strerror(errno));
1002995Shx147065 return (B_FALSE);
1003995Shx147065 }
1004995Shx147065 (void) chmod(file_name, buf.st_mode);
1005995Shx147065 return (B_TRUE);
1006995Shx147065 }
1007995Shx147065 /*
1008995Shx147065 * append_pa: Each section holds a section_id which identifies a section
1009995Shx147065 * a profile uses its essid appending "[]" to denote its section_id.
1010995Shx147065 * note: new memory is allocated, remember to free.
1011995Shx147065 */
1012995Shx147065 static char *
append_pa(const char * arg)1013995Shx147065 append_pa(const char *arg)
1014995Shx147065 {
1015995Shx147065 char *pbuf = NULL;
1016995Shx147065 int len;
1017995Shx147065
1018995Shx147065 assert(arg != NULL);
1019995Shx147065
1020995Shx147065 len = strlen(arg) + 3;
1021995Shx147065 pbuf = safe_malloc(len);
1022995Shx147065 safe_snprintf(pbuf, len, "[%s]", arg);
1023995Shx147065 PRTDBG(("append_pa(\"%s\") = \"%s\"\n", arg, pbuf));
1024995Shx147065 return (pbuf);
1025995Shx147065 }
1026995Shx147065 /*
1027995Shx147065 * find a section by section_id from p_config_file,
1028995Shx147065 * return the section pointer.
1029995Shx147065 */
1030995Shx147065 static section_t *
find_section(config_file_t * p_config_file,const char * section_id)1031995Shx147065 find_section(config_file_t *p_config_file, const char *section_id)
1032995Shx147065 {
1033995Shx147065 section_t *p_section = NULL;
1034995Shx147065
1035995Shx147065 PRTDBG(("find_section(0x%x, \"%s\")\n", p_config_file, section_id));
1036995Shx147065 assert((section_id != NULL)&&(p_config_file != NULL));
1037995Shx147065
1038995Shx147065 p_section = p_config_file->section_head;
1039995Shx147065
1040995Shx147065 while (p_section != NULL) {
1041995Shx147065 if ((p_section->section_id != NULL) &&
1042995Shx147065 (strcmp(p_section->section_id, section_id) == 0))
1043995Shx147065 return (p_section);
1044995Shx147065 p_section = p_section->section_next;
1045995Shx147065 }
1046995Shx147065 return (NULL);
1047995Shx147065 }
1048995Shx147065
1049995Shx147065 /*
1050995Shx147065 * get_value: Get rid of "parameter=" from a "parameter=value", for example:
1051995Shx147065 * when we read an line from file, we gets "essid=ap7-2", this function
1052995Shx147065 * returns the pointer to string "ap7-2";
1053995Shx147065 */
1054995Shx147065
1055995Shx147065 static const char *
get_value(const char * arg)1056995Shx147065 get_value(const char *arg)
1057995Shx147065 {
1058995Shx147065 char *p;
1059995Shx147065 assert(arg != NULL);
1060995Shx147065
1061995Shx147065 p = strchr(arg, '=');
1062995Shx147065 PRTDBG(("get_value(\"%s\") = \"%s\"\n", arg, p + 1));
1063995Shx147065 if (p != NULL)
1064995Shx147065 return (p + 1);
1065995Shx147065 else
1066995Shx147065 return (NULL);
1067995Shx147065 }
1068995Shx147065
1069995Shx147065 /*
1070995Shx147065 * search /dev/wifi to see which interface is available
1071995Shx147065 */
1072995Shx147065 static boolean_t
search_interface(char * interface)1073995Shx147065 search_interface(char *interface)
1074995Shx147065 {
1075995Shx147065 DIR *dirp;
1076995Shx147065 struct dirent *dp;
1077995Shx147065 char buf[256];
1078995Shx147065 int fd;
1079995Shx147065
1080995Shx147065 PRTDBG(("search interface\n"));
1081995Shx147065 assert(interface != NULL);
1082995Shx147065
1083995Shx147065 /*
1084995Shx147065 * Try to return the first found wifi interface.
1085995Shx147065 * If no wifi interface is available, return B_FALSE
1086995Shx147065 */
1087995Shx147065
1088995Shx147065 if ((dirp = opendir("/dev/wifi")) == NULL) {
1089995Shx147065 PRTDBG(("failed to open '/dev/wifi'\n"));
1090995Shx147065 return (B_FALSE);
1091995Shx147065 }
1092995Shx147065 while ((dp = readdir(dirp)) != NULL) {
1093995Shx147065 if (strcmp(dp->d_name, ".") == 0 ||
1094995Shx147065 strcmp(dp->d_name, "..") == 0)
1095995Shx147065 continue;
1096995Shx147065 if (dp->d_name[strlen(dp->d_name) - 1] < '0' ||
1097995Shx147065 dp->d_name[strlen(dp->d_name) - 1] > '9')
1098995Shx147065 continue;
1099995Shx147065 safe_snprintf(buf, sizeof (buf), "%s%s",
1100995Shx147065 "/dev/wifi/", dp->d_name);
1101995Shx147065 fd = open(buf, O_RDWR);
1102995Shx147065 if (fd == -1) {
1103995Shx147065 PRTDBG(("interface %s doesn't exist\n", dp->d_name));
1104995Shx147065 continue;
1105995Shx147065 } else {
1106995Shx147065 PRTDBG(("interface %s is the first found interface\n",
1107995Shx147065 dp->d_name));
1108995Shx147065 (void) strlcpy(interface, buf, LIFNAMSIZ);
1109995Shx147065 (void) close(fd);
1110995Shx147065 (void) closedir(dirp);
1111995Shx147065 return (B_TRUE);
1112995Shx147065 }
1113995Shx147065 }
1114995Shx147065
1115995Shx147065 PRTDBG(("failed to find available wireless interface\n"));
1116995Shx147065 (void) closedir(dirp);
1117995Shx147065 return (B_FALSE);
1118995Shx147065
1119995Shx147065 }
1120995Shx147065 /*
1121995Shx147065 * open_dev: Open the driver.
1122995Shx147065 * if the 'devname' has format like 'ath0', we should add the path to that
1123995Shx147065 * device(/dev/ath0) and open it; if the 'devname' has format like
1124995Shx147065 * '/dev/wifi/ath0', we open it directly.
1125995Shx147065 */
1126995Shx147065 static int
open_dev(char * devname)1127995Shx147065 open_dev(char *devname)
1128995Shx147065 {
1129995Shx147065 int fd;
1130995Shx147065 int len;
1131995Shx147065 char *pbuf = NULL;
1132995Shx147065
1133995Shx147065 PRTDBG(("open_dev(\"%s\")\n", devname));
1134995Shx147065 assert(devname != NULL);
1135995Shx147065 /*
1136995Shx147065 * If the devname is got from the user input, we
1137995Shx147065 * add '/dev/' to that relative devname. If it
1138995Shx147065 * is got from the 'search interface', it is an
1139995Shx147065 * absolute path.
1140995Shx147065 */
1141995Shx147065 if (strncmp(devname, "/dev/wifi/", strlen("/dev/wifi/")) == 0) {
1142995Shx147065 pbuf = safe_strdup(devname);
1143995Shx147065 } else {
1144995Shx147065 len = strlen(devname) + strlen("/dev/") + 1;
1145995Shx147065 pbuf = safe_malloc(len);
1146995Shx147065 safe_snprintf(pbuf, len, "/dev/%s", devname);
1147995Shx147065 }
1148995Shx147065 fd = open(pbuf, O_RDWR);
1149995Shx147065 free(pbuf);
1150995Shx147065
1151995Shx147065 if (fd == -1) {
1152995Shx147065 (void) fprintf(stderr, gettext("%s: failed to open '%s': %s"
1153995Shx147065 "\n"), gExecName, devname, strerror(errno));
1154995Shx147065 return (-1);
1155995Shx147065 }
1156995Shx147065 if (!isastream(fd)) {
1157995Shx147065 (void) fprintf(stderr, gettext("%s: %s is "
1158995Shx147065 "not a stream device\n"),
1159995Shx147065 gExecName, devname);
1160995Shx147065 (void) close(fd);
1161995Shx147065 return (-1);
1162995Shx147065 }
1163995Shx147065 return (fd);
1164995Shx147065 }
1165995Shx147065 /*
1166995Shx147065 * call_ioctl: Fill strioctl structure and issue an ioctl system call
1167995Shx147065 */
1168995Shx147065 static boolean_t
call_ioctl(int fd,int cmd,uint32_t params,uint32_t buf_len)1169995Shx147065 call_ioctl(int fd, int cmd, uint32_t params, uint32_t buf_len)
1170995Shx147065 {
1171995Shx147065 struct strioctl stri;
1172995Shx147065
1173995Shx147065 PRTDBG(("call_ioctl_gs(%d, 0x%x, 0x%x, 0x%x)\n",
1174995Shx147065 fd, cmd, params, buf_len));
1175995Shx147065
1176995Shx147065 switch (cmd) {
1177995Shx147065 case WLAN_GET_PARAM:
1178995Shx147065 (void) memset(gbuf, 0, MAX_BUF_LEN);
1179995Shx147065 stri.ic_len = MAX_BUF_LEN;
1180995Shx147065 break;
1181995Shx147065 case WLAN_SET_PARAM:
1182995Shx147065 gbuf->wldp_length = buf_len + WIFI_BUF_OFFSET;
1183995Shx147065 stri.ic_len = gbuf->wldp_length;
1184995Shx147065 break;
1185995Shx147065 case WLAN_COMMAND:
1186995Shx147065 gbuf->wldp_length = sizeof (wldp_t);
1187995Shx147065 stri.ic_len = gbuf->wldp_length;
1188995Shx147065 break;
1189995Shx147065 default:
1190995Shx147065 (void) fprintf(stderr, gettext("%s: ioctl : "
1191995Shx147065 "unsupported ioctl command\n"), gExecName);
1192995Shx147065 return (B_FALSE);
1193995Shx147065 }
1194995Shx147065 gbuf->wldp_type = NET_802_11;
1195995Shx147065 gbuf->wldp_id = params;
1196995Shx147065
1197995Shx147065 stri.ic_cmd = cmd;
1198995Shx147065 stri.ic_timout = 0;
1199995Shx147065 stri.ic_dp = (char *)gbuf;
1200995Shx147065
1201995Shx147065 if (ioctl(fd, I_STR, &stri) == -1) {
1202995Shx147065 gbuf->wldp_result = 0xffff;
1203995Shx147065 return (B_FALSE);
1204995Shx147065 }
1205995Shx147065 if (cmd == WLAN_COMMAND) {
1206995Shx147065 return (B_TRUE);
1207995Shx147065 } else {
1208995Shx147065 return (gbuf->wldp_result != WL_SUCCESS ?
1209*6834Sff224033 B_FALSE:B_TRUE);
1210995Shx147065 }
1211995Shx147065 }
1212995Shx147065
1213995Shx147065 /*
1214995Shx147065 * del_prefer: Delete an item from the {preferrence} list, the idea is
1215995Shx147065 * simply free the ae_t element, and set ae_arg to NULL, then when archive
1216995Shx147065 * the config_file_t struct to the file, it will be delete.
1217995Shx147065 * The last flag is used to identify whether this function is invoked due to
1218995Shx147065 * the 'removeprefer' subcommand or due to 'deleteprofile' subcommand.
1219995Shx147065 */
1220995Shx147065 static boolean_t
del_prefer(config_file_t * p_config_file,const char * prefer,boolean_t rflag)1221995Shx147065 del_prefer(config_file_t *p_config_file, const char *prefer, boolean_t rflag)
1222995Shx147065 {
1223995Shx147065 section_t *p_section = NULL;
1224995Shx147065 aelist_t *plist = NULL;
1225995Shx147065 ae_t *pae = NULL;
1226995Shx147065 int i = 0, position = 0;
1227995Shx147065 int number;
1228995Shx147065 ae_t *prm_ae = NULL;
1229995Shx147065
1230995Shx147065 PRTDBG(("del_prefer(0x%x, \"%s\")\n", p_config_file, prefer));
1231995Shx147065 assert((prefer != NULL)&&(p_config_file != NULL));
1232995Shx147065
1233995Shx147065 p_section = find_section(p_config_file, WIFI_PREFER);
1234995Shx147065 if (p_section != NULL)
1235995Shx147065 plist = p_section->list;
1236995Shx147065
1237995Shx147065 if ((p_section == NULL) || (plist == NULL))
1238995Shx147065 return (B_FALSE);
1239995Shx147065
1240995Shx147065 number = plist->ael_argc;
1241995Shx147065 pae = plist->ael_head;
1242995Shx147065 prm_ae = plist->ael_head;
1243995Shx147065 while (pae != NULL) {
1244995Shx147065 if (strcmp(prefer, pae->ae_arg) == 0) {
1245995Shx147065 free(pae->ae_arg);
1246995Shx147065 pae->ae_arg = NULL; /* mark */
1247995Shx147065 if (!position) {
1248995Shx147065 plist->ael_head = pae->ae_next;
1249995Shx147065 if (pae->ae_next == NULL)
1250995Shx147065 plist->ael_tail = NULL;
1251995Shx147065 } else {
1252995Shx147065 for (i = 0; i < position - 1; i++)
1253995Shx147065 prm_ae = prm_ae->ae_next;
1254995Shx147065 prm_ae->ae_next = pae->ae_next;
1255995Shx147065 if (pae->ae_next == NULL)
1256995Shx147065 plist->ael_tail = prm_ae;
1257995Shx147065 }
1258995Shx147065 free(pae);
1259995Shx147065 pae = NULL;
1260995Shx147065 plist->ael_argc--;
1261995Shx147065 break;
1262995Shx147065 }
1263995Shx147065 position++;
1264995Shx147065 pae = pae->ae_next;
1265995Shx147065 }
1266995Shx147065 if ((number == plist->ael_argc) && (rflag == B_TRUE)) {
1267995Shx147065 (void) fprintf(stderr, gettext("%s: removeprefer : "
1268995Shx147065 "no such profile: '%s' in the preference list\n"),
1269995Shx147065 gExecName, prefer);
1270995Shx147065 return (B_FALSE);
1271995Shx147065 }
1272995Shx147065 return (B_TRUE);
1273995Shx147065 }
1274995Shx147065
1275995Shx147065 /*
1276995Shx147065 * del_section: Delete an section from p_config_file, the idea is
1277995Shx147065 * simply free the aelist_t struct and set it to NULL, when archiving
1278995Shx147065 * config_file_t struct to the file, we will find section list is NULL,
1279995Shx147065 * and will not write it to file, so it will be deleted.
1280995Shx147065 */
1281995Shx147065 static boolean_t
del_section(config_file_t * p_config_file,char * section_id)1282995Shx147065 del_section(config_file_t *p_config_file, char *section_id)
1283995Shx147065 {
1284995Shx147065 section_t *p_section = NULL;
1285995Shx147065 section_t *prm_section = NULL;
1286995Shx147065 aelist_t *plist = NULL;
1287995Shx147065 ae_t *pae = NULL;
1288995Shx147065 int i = 0, position = 0;
1289995Shx147065
1290995Shx147065 PRTDBG(("del_section(0x%x, \"%s\")\n", p_config_file, section_id));
1291995Shx147065 PRTDBG(("del_section: %d section(s) in config file\n",
1292995Shx147065 p_config_file->section_argc));
1293995Shx147065 assert((section_id != NULL)&&(p_config_file != NULL));
1294995Shx147065
1295995Shx147065 if (find_section(p_config_file, section_id) == NULL) {
1296995Shx147065 return (B_FALSE);
1297995Shx147065 }
1298995Shx147065 p_section = p_config_file->section_head;
1299995Shx147065 prm_section = p_config_file->section_head;
1300995Shx147065 while (p_section != NULL) {
1301995Shx147065 if (p_section->section_id != NULL) {
1302995Shx147065 if (strcmp(p_section->section_id, section_id) == 0) {
1303995Shx147065 plist = p_section->list;
1304995Shx147065 pae = plist->ael_head;
1305995Shx147065 while (pae != NULL) {
1306995Shx147065 free(pae->ae_arg);
1307995Shx147065 pae->ae_arg = NULL;
1308995Shx147065 pae = pae->ae_next;
1309995Shx147065 free(plist->ael_head);
1310995Shx147065 plist->ael_head = pae;
1311995Shx147065 }
1312995Shx147065 free(plist);
1313995Shx147065 p_section->list = NULL;
1314995Shx147065 free(p_section->section_id);
1315995Shx147065 p_section->section_id = NULL;
1316995Shx147065
1317995Shx147065 if (!position) {
1318995Shx147065 p_config_file->section_head =
1319995Shx147065 p_section->section_next;
1320995Shx147065 if (p_section->section_next == NULL)
1321995Shx147065 p_config_file->section_tail =
1322995Shx147065 NULL;
1323995Shx147065 } else {
1324995Shx147065 for (i = 0; i < position - 1; i++) {
1325995Shx147065 prm_section =
1326995Shx147065 prm_section->section_next;
1327995Shx147065 }
1328995Shx147065 prm_section->section_next =
1329995Shx147065 p_section->section_next;
1330995Shx147065 if (p_section->section_next == NULL)
1331995Shx147065 p_config_file->section_tail =
1332995Shx147065 prm_section;
1333995Shx147065 }
1334995Shx147065 free(p_section);
1335995Shx147065 p_config_file->section_argc--;
1336995Shx147065 break;
1337995Shx147065 }
1338995Shx147065 position++;
1339995Shx147065 }
1340995Shx147065 p_section = p_section->section_next;
1341995Shx147065 }
1342995Shx147065 return (B_TRUE);
1343995Shx147065 }
1344995Shx147065
1345995Shx147065 /*
1346995Shx147065 * set_prefer: Reorder the preferrence list.
1347995Shx147065 */
1348995Shx147065 static boolean_t
set_prefer(config_file_t * p_config_file,const char * prefer,int rank)1349995Shx147065 set_prefer(config_file_t *p_config_file, const char *prefer, int rank)
1350995Shx147065 {
1351995Shx147065 char *pbuf = NULL;
1352995Shx147065 aelist_t *plist = NULL;
1353995Shx147065 section_t *p_section = NULL;
1354995Shx147065 ae_t *pae = NULL;
1355995Shx147065 int i = 0, position = 0;
1356995Shx147065 ae_t *pae_move = NULL;
1357995Shx147065
1358995Shx147065 assert(prefer != NULL);
1359995Shx147065 PRTDBG(("set_prefer(0x%x, \"%s\", %d)\n", p_config_file, prefer, rank));
1360995Shx147065
1361995Shx147065 pbuf = append_pa(prefer);
1362995Shx147065 if (find_section(p_config_file, pbuf) == NULL) {
1363995Shx147065 (void) fprintf(stderr, gettext("%s: setprefer: "
1364995Shx147065 "no such profile: '%s'\n"),
1365995Shx147065 gExecName, prefer);
1366995Shx147065 free(pbuf);
1367995Shx147065 return (B_FALSE);
1368995Shx147065 }
1369995Shx147065 free(pbuf);
1370995Shx147065
1371995Shx147065 p_section = find_section(p_config_file, WIFI_PREFER);
1372995Shx147065
1373995Shx147065 if (p_section == NULL) {
1374995Shx147065 plist = new_ael(PREFERENCE);
1375995Shx147065 new_section(p_config_file, plist, WIFI_PREFER);
1376995Shx147065 new_ae(plist, prefer);
1377995Shx147065 return (B_TRUE);
1378995Shx147065 } else {
1379995Shx147065 plist = p_section->list;
1380995Shx147065 }
1381995Shx147065
1382995Shx147065 pae = plist->ael_head;
1383995Shx147065 pae_move = plist->ael_head;
1384995Shx147065 while (pae != NULL) {
1385995Shx147065 if (strcmp(prefer, pae->ae_arg) == 0) {
1386995Shx147065 free(pae->ae_arg);
1387995Shx147065 pae->ae_arg = NULL;
1388995Shx147065 if (!position) {
1389995Shx147065 plist->ael_head = pae->ae_next;
1390995Shx147065 if (pae->ae_next == NULL)
1391995Shx147065 plist->ael_tail = NULL;
1392995Shx147065 } else {
1393995Shx147065 for (i = 0; i < position - 1; i++)
1394995Shx147065 pae_move = pae_move->ae_next;
1395995Shx147065 pae_move->ae_next = pae->ae_next;
1396995Shx147065 if (pae->ae_next == NULL)
1397995Shx147065 plist->ael_tail = pae_move;
1398995Shx147065 }
1399995Shx147065 free(pae);
1400995Shx147065 plist->ael_argc--;
1401995Shx147065 break;
1402995Shx147065 }
1403995Shx147065 position++;
1404995Shx147065 pae = pae->ae_next;
1405995Shx147065 }
1406995Shx147065 PRTDBG(("set_prefer: %d Profiles in prefer list\n", plist->ael_argc));
1407995Shx147065 if (rank > plist->ael_argc) {
1408995Shx147065 new_ae(plist, prefer);
1409995Shx147065 } else if (rank <= 1) {
1410995Shx147065 pae = safe_calloc(sizeof (ae_t), 1);
1411995Shx147065 pae->ae_arg = safe_strdup(prefer);
1412995Shx147065 pae->ae_next = plist->ael_head;
1413995Shx147065 plist->ael_head = pae;
1414995Shx147065 plist->ael_argc++;
1415995Shx147065 } else {
1416995Shx147065 pae_move = plist->ael_head;
1417995Shx147065 for (i = 1; i < rank-1; i++) {
1418995Shx147065 pae_move = pae_move->ae_next;
1419995Shx147065 }
1420995Shx147065 pae = safe_calloc(sizeof (ae_t), 1);
1421995Shx147065 pae->ae_arg = safe_strdup(prefer);
1422995Shx147065 pae->ae_next = pae_move->ae_next;
1423995Shx147065 pae_move->ae_next = pae;
1424995Shx147065 plist->ael_argc++;
1425995Shx147065 }
1426995Shx147065 /*
1427995Shx147065 * If number of prefer list items is larger than the MAX_PREFERENCE_NUM
1428995Shx147065 * delete those items whose No is larger than MAX_PREFERENCE_NUM.
1429995Shx147065 */
1430995Shx147065 if (plist->ael_argc > MAX_PREFERENCE_NUM) {
1431995Shx147065 pae = plist->ael_head;
1432995Shx147065 while (pae->ae_next != plist->ael_tail)
1433995Shx147065 pae = pae->ae_next;
1434995Shx147065 free(plist->ael_tail->ae_arg);
1435995Shx147065 plist->ael_tail->ae_arg = NULL;
1436995Shx147065 free(plist->ael_tail);
1437995Shx147065 plist->ael_tail = pae;
1438995Shx147065 plist->ael_tail->ae_next = NULL;
1439995Shx147065 plist->ael_argc--;
1440995Shx147065 }
1441995Shx147065 PRTDBG(("set_prefer: %d Profiles in prefer list\n", plist->ael_argc));
1442995Shx147065 return (B_TRUE);
1443995Shx147065 }
1444995Shx147065 /*
1445995Shx147065 * add_to_history: Save the scanlist argv into history section
1446995Shx147065 */
1447995Shx147065 static void
add_to_history(config_file_t * p_config_file,int argc,char ** argv)1448995Shx147065 add_to_history(config_file_t *p_config_file, int argc, char **argv)
1449995Shx147065 {
1450995Shx147065 int i = 0, j = 0, pos = 0;
1451995Shx147065 aelist_t *plist = NULL;
1452995Shx147065 section_t *p_section = NULL;
1453995Shx147065 ae_t *pae = NULL;
1454995Shx147065 ae_t *pae_m = NULL;
1455995Shx147065 char item[256];
1456995Shx147065 time_t cltime;
1457995Shx147065
1458995Shx147065 PRTDBG(("add_to_history(0x%x, %d, 0x%x)\n", p_config_file, argc, argv));
1459995Shx147065 assert(p_config_file != NULL);
1460995Shx147065
1461995Shx147065 p_section = find_section(p_config_file, WIFI_HISTORY);
1462995Shx147065
1463995Shx147065 if (p_section == NULL) {
1464995Shx147065 plist = new_ael(HISTORY);
1465995Shx147065 new_section(p_config_file, plist, WIFI_HISTORY);
1466995Shx147065 } else {
1467995Shx147065 plist = p_section->list;
1468995Shx147065 }
1469995Shx147065
1470995Shx147065 if (plist != NULL) {
1471995Shx147065 for (i = 0; i < argc; i++) {
1472995Shx147065 if (!strlen(argv[i]))
1473995Shx147065 continue;
1474995Shx147065 pos = 0;
1475995Shx147065 pae = plist->ael_head;
1476995Shx147065 pae_m = plist->ael_head;
1477995Shx147065 /*
1478995Shx147065 * add time stamp to the history record
1479995Shx147065 */
1480995Shx147065 cltime = time(&cltime);
1481995Shx147065 (void) snprintf(item, sizeof (item), "%s%c%ld",
1482995Shx147065 argv[i], ',', cltime);
1483995Shx147065 while (pae != NULL) {
1484995Shx147065 if (strncmp(item, pae->ae_arg,
1485995Shx147065 strlen(argv[i])) == 0) {
1486995Shx147065 free(pae->ae_arg);
1487995Shx147065 pae->ae_arg = NULL;
1488995Shx147065 if (!pos) {
1489995Shx147065 plist->ael_head = pae->ae_next;
1490995Shx147065 if (pae->ae_next == NULL)
1491995Shx147065 plist->ael_tail = NULL;
1492995Shx147065 } else {
1493995Shx147065 for (j = 0; j < pos - 1; j++)
1494995Shx147065 pae_m = pae_m->ae_next;
1495995Shx147065 pae_m->ae_next = pae->ae_next;
1496995Shx147065 if (pae->ae_next == NULL)
1497995Shx147065 plist->ael_tail = pae_m;
1498995Shx147065 }
1499995Shx147065 free(pae);
1500995Shx147065 plist->ael_argc--;
1501995Shx147065 break;
1502995Shx147065 }
1503995Shx147065 pos++;
1504995Shx147065 pae = pae->ae_next;
1505995Shx147065 }
1506995Shx147065 new_ae(plist, item);
1507995Shx147065 }
1508995Shx147065
1509995Shx147065 if (plist->ael_argc > MAX_HISTORY_NUM) {
1510995Shx147065 for (i = 0; i < plist->ael_argc - MAX_HISTORY_NUM;
1511995Shx147065 i++) {
1512995Shx147065 pae = plist->ael_head;
1513995Shx147065 free(pae->ae_arg);
1514995Shx147065 plist->ael_head = pae->ae_next;
1515995Shx147065 free(pae);
1516995Shx147065 }
1517995Shx147065 plist->ael_argc = MAX_HISTORY_NUM;
1518995Shx147065 }
1519995Shx147065 }
1520995Shx147065 }
1521995Shx147065
1522995Shx147065 static void
do_print_usage()1523995Shx147065 do_print_usage()
1524995Shx147065 {
1525995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1526995Shx147065 " autoconf [wait={n|forever}]\n"), gExecName);
1527995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1528995Shx147065 " connect profile [wait={n|forever}]\n"), gExecName);
1529995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1530995Shx147065 " connect essid [wait={n|forever}]\n"), gExecName);
1531995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1532995Shx147065 " disconnect\n"), gExecName);
1533995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1534995Shx147065 " getparam [parameter [...]]\n"), gExecName);
1535995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1536995Shx147065 " setparam [parameter=value [...]]\n"), gExecName);
1537995Shx147065 (void) fprintf(stderr, gettext(
1538*6834Sff224033 "\tparameters:\n"
1539*6834Sff224033 "\t\tbssid\t\t - read only: 6 byte mac address of "
1540*6834Sff224033 "base station\n"
1541*6834Sff224033 "\t\tessid\t\t - name of the network, a string of up "
1542*6834Sff224033 "to 32 chars\n"
1543*6834Sff224033 "\t\tbsstype\t\t - bss(ap, infrastructure), ibss(ad-hoc)"
1544*6834Sff224033 " or auto\n"
1545*6834Sff224033 "\t\tcreateibss\t - flag to identify whether a ibss is to be\n"
1546*6834Sff224033 "\t\t\t\t created when the network to connect is\n"
1547*6834Sff224033 "\t\t\t\t not available, yes or no\n"
1548*6834Sff224033 "\t\tchannel\t\t - channel(used only when creating an ibss)\n"
1549*6834Sff224033 "\t\t\t\t valid value:\n"
1550*6834Sff224033 "\t\t\t\t\t 802.11a: 0-99\n"
1551*6834Sff224033 "\t\t\t\t\t 802.11b: 1-14\n"
1552*6834Sff224033 "\t\t\t\t\t 802.11g: 1-14\n"
1553*6834Sff224033 "\t\trates\t\t - set of rates, seperated by ',' valid rates:\n"
1554*6834Sff224033 "\t\t\t\t 1,2,5.5,6,9,11,12,18,22,24,33,36,48 and 54\n"
1555*6834Sff224033 "\t\tpowermode\t - off, mps or fast\n"
1556*6834Sff224033 "\t\tauthmode\t - opensystem or shared_key\n"
1557*6834Sff224033 "\t\tencryption\t - none or wep\n"
1558*6834Sff224033 "\t\twepkey|1-4\t - write only:\n"
1559*6834Sff224033 "\t\t\t\t 5 chars or 10 hex digits for 40bit wepkey;\n"
1560*6834Sff224033 "\t\t\t\t 13 chars or 26 hex digits for 128bit wepkey\n"
1561*6834Sff224033 "\t\twepkeyindex\t - an integer within the range 1-4\n"
1562*6834Sff224033 "\t\tsignal\t\t - read only: signal strength from 0 to 15\n"
1563*6834Sff224033 "\t\tradio\t\t - on or off\n"));
1564995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1565995Shx147065 " restoredef\n"), gExecName);
1566995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1567995Shx147065 " scan\n"), gExecName);
1568995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1569995Shx147065 " showstatus\n"), gExecName);
1570995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path][-i interface]"
1571995Shx147065 " setwepkey 1|2|3|4\n"), gExecName);
1572995Shx147065
1573995Shx147065 (void) fprintf(stderr, "\n");
1574995Shx147065
1575995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1576995Shx147065 " createprofile profile parameter=value [...]\n"), gExecName);
1577995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1578995Shx147065 " deleteprofile profile1 [profile2 [...]]\n"), gExecName);
1579995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1580995Shx147065 " showprofile profile1 [profile2 [...]]\n"), gExecName);
1581995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1582995Shx147065 " setprofilewepkey profile 1|2|3|4\n"), gExecName);
1583995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1584995Shx147065 " getprofileparam profile [parameter [...]]\n"), gExecName);
1585995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1586995Shx147065 " setprofileparam profile [parameter=value [...]]\n"), gExecName);
1587995Shx147065
1588995Shx147065 (void) fprintf(stderr, "\n");
1589995Shx147065
1590995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1591995Shx147065 " history\n"), gExecName);
1592995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1593995Shx147065 " listprefer\n"), gExecName);
1594995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1595995Shx147065 " removeprefer profile\n"), gExecName);
1596995Shx147065 (void) fprintf(stderr, gettext("\t%s [-R root_path]"
1597995Shx147065 " setprefer profile [n]\n"), gExecName);
1598995Shx147065 }
1599995Shx147065
1600995Shx147065 /*
1601995Shx147065 * do_print_support_params: Query interface which cmd is supported
1602995Shx147065 */
1603995Shx147065 static boolean_t
do_print_support_params(int fd)1604995Shx147065 do_print_support_params(int fd)
1605995Shx147065 {
1606995Shx147065 int i = 0, n = 0;
1607995Shx147065
1608995Shx147065 PRTDBG(("do_print_support_params(\"%d\")\n", fd));
1609995Shx147065 assert(fd != -1);
1610995Shx147065
1611995Shx147065 (void) printf(gettext("\t parameter\tproperty\n"));
1612995Shx147065 for (i = 0; i < N_GS_FUNC; i++) {
1613995Shx147065 gbuf->wldp_result = WL_LACK_FEATURE;
1614995Shx147065 if ((do_gs_func[i].p_do_get_func != NULL) &&
1615995Shx147065 (do_gs_func[i].p_do_get_func(fd) != B_TRUE)) {
1616995Shx147065 continue;
1617995Shx147065 }
1618995Shx147065 if (gbuf->wldp_result == WL_SUCCESS) {
1619995Shx147065 (void) printf("\t%11s", do_gs_func[i].cmd);
1620995Shx147065 if (do_gs_func[i].rw == RO)
1621995Shx147065 (void) printf(gettext("\tread only\n"));
1622995Shx147065 else
1623995Shx147065 (void) printf(gettext("\tread/write\n"));
1624995Shx147065 n++;
1625995Shx147065 }
1626995Shx147065 }
1627995Shx147065
1628995Shx147065 return (n ? B_TRUE : B_FALSE);
1629995Shx147065 }
1630995Shx147065
1631995Shx147065 /*
1632995Shx147065 * check_authority: Check if command is permitted.
1633995Shx147065 */
1634995Shx147065 static boolean_t
check_authority(wifi_auth_t type)1635995Shx147065 check_authority(wifi_auth_t type)
1636995Shx147065 {
1637995Shx147065 struct passwd *pw = NULL;
1638995Shx147065
1639995Shx147065 PRTDBG(("check_authority()\n"));
1640995Shx147065
1641995Shx147065 pw = getpwuid(getuid());
1642995Shx147065 if (pw == NULL)
1643995Shx147065 return (B_FALSE);
1644995Shx147065 if (chkauthattr(p_auth_string[type], pw->pw_name) == 0) {
1645995Shx147065 if (type == AUTH_WEP)
1646995Shx147065 (void) fprintf(stderr, gettext("%s: "
1647995Shx147065 "privilege '%s' is required for setting "
1648995Shx147065 "wepkey.\n"), gExecName, WIFI_WEP_AUTH);
1649995Shx147065 else
1650995Shx147065 (void) fprintf(stderr, gettext("%s: "
1651995Shx147065 "privilege '%s' is required.\n"),
1652995Shx147065 gExecName, WIFI_CONFIG_AUTH);
1653995Shx147065 return (B_FALSE);
1654995Shx147065 } else {
1655995Shx147065 return (B_TRUE);
1656995Shx147065 }
1657995Shx147065 }
1658995Shx147065
1659995Shx147065 /*
1660995Shx147065 * construct the 'history' and 'scan' output format
1661995Shx147065 * memory allocated. need to free after the function is invoked.
1662995Shx147065 */
1663995Shx147065 static char *
construct_format(uint32_t nt)1664995Shx147065 construct_format(uint32_t nt)
1665995Shx147065 {
1666995Shx147065 char *format;
1667995Shx147065 int len = 0, i;
1668995Shx147065
1669995Shx147065 #define FORMAT_LEN 256
1670995Shx147065 assert((nt >= 1) && (nt <= 4));
1671995Shx147065 format = safe_malloc(FORMAT_LEN);
1672995Shx147065
1673995Shx147065 for (i = 0; i < nt; i++)
1674995Shx147065 len += snprintf(format + len, FORMAT_LEN - len, "\t");
1675995Shx147065 if ((len <= 0) || (len > FORMAT_LEN - 1)) {
1676995Shx147065 return ("\t\t\t\t");
1677995Shx147065 }
1678995Shx147065 return (format);
1679995Shx147065 }
1680995Shx147065
1681995Shx147065 /*
1682995Shx147065 * find the essid of the named profile.
1683995Shx147065 * gp_config_file is golable, so the return is gloable too.
1684995Shx147065 */
1685995Shx147065 static const char *
essid_of_profile(const char * profile)1686995Shx147065 essid_of_profile(const char *profile)
1687995Shx147065 {
1688995Shx147065 section_t *p_section = NULL;
1689995Shx147065 aelist_t *plist = NULL;
1690995Shx147065 ae_t *pae = NULL;
1691995Shx147065 char *pbuf;
1692995Shx147065
1693995Shx147065 PRTDBG(("essid_of_profile: profile = %s\n", profile));
1694995Shx147065 pbuf = append_pa(profile);
1695995Shx147065 p_section = find_section(gp_config_file, pbuf);
1696995Shx147065 free(pbuf);
1697995Shx147065
1698995Shx147065 if (p_section == NULL) {
1699995Shx147065 return (NULL);
1700995Shx147065 } else {
1701995Shx147065 plist = p_section->list;
1702995Shx147065 }
1703995Shx147065 pae = plist->ael_head;
1704995Shx147065 while (pae != NULL) {
1705995Shx147065 if (strncmp(pae->ae_arg, "essid=", strlen("essid=")) == 0) {
1706995Shx147065 PRTDBG(("essid_of_profile: essid = %s\n",
1707995Shx147065 pae->ae_arg));
1708995Shx147065 return (get_value(pae->ae_arg));
1709995Shx147065 }
1710995Shx147065 pae = pae->ae_next;
1711995Shx147065 }
1712995Shx147065 return (NULL);
1713995Shx147065 }
1714995Shx147065
1715995Shx147065 /*
1716995Shx147065 * If we don't know which profile is our favorate in 'autoconf',
1717995Shx147065 * we select the wifi network based on the following heuristic
1718995Shx147065 * 1. the network without wep.
1719995Shx147065 * 2. the network with the strongst signal.
1720995Shx147065 * 3. the network with the faster speed(not implemented since signal affects
1721995Shx147065 * the speed in some degree).
1722995Shx147065 */
1723995Shx147065 static void
heuristic_load(int fd,uint32_t ess_num,wl_ess_conf_t ** p_ess_conf)1724995Shx147065 heuristic_load(int fd, uint32_t ess_num, wl_ess_conf_t **p_ess_conf)
1725995Shx147065 {
1726995Shx147065 int i = 0;
1727995Shx147065 char *flag = NULL;
1728995Shx147065 int have_nowep_wlan = 0;
1729995Shx147065 wl_rssi_t maxsignal = 0;
1730995Shx147065 char essid[34];
1731995Shx147065 int timeout = LOADPROFILE_TIMEOUT;
1732995Shx147065
1733995Shx147065 PRTDBG(("heuristic_load: enter\n"));
1734995Shx147065 (void) call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0);
1735995Shx147065 flag = calloc(sizeof (char), ess_num);
1736995Shx147065 for (i = 0; i < ess_num; i++) { /* extract none-wep network */
1737995Shx147065 if (p_ess_conf[i]->wl_ess_conf_wepenabled == B_FALSE) {
1738995Shx147065 flag[i] = 1;
1739995Shx147065 have_nowep_wlan = 1;
1740995Shx147065 }
1741995Shx147065 }
1742995Shx147065 /*
1743995Shx147065 * if all the wlans are weped, we select the one with strongest signal
1744995Shx147065 * in all of them, otherwise we just select in the none weped ones.
1745995Shx147065 */
1746995Shx147065 if (!have_nowep_wlan)
1747995Shx147065 (void) memset(flag, 1, ess_num);
1748995Shx147065 for (i = 0; i < ess_num; i++) { /* extract the strongest signal ones */
1749995Shx147065 if (flag[i] == 1) {
1750995Shx147065 if (p_ess_conf[i]->wl_ess_conf_sl > maxsignal) {
1751995Shx147065 maxsignal = p_ess_conf[i]->wl_ess_conf_sl;
1752995Shx147065 (void) memset(flag, 0, i);
1753995Shx147065 } else if (p_ess_conf[i]->wl_ess_conf_sl == maxsignal)
1754995Shx147065 continue;
1755995Shx147065 else
1756995Shx147065 flag[i] = 0;
1757995Shx147065 }
1758995Shx147065 }
1759995Shx147065 for (i = 0; i < ess_num; i++) {
1760995Shx147065 if (flag[i] == 1)
1761995Shx147065 break;
1762995Shx147065 }
1763995Shx147065 free(flag);
1764995Shx147065 PRTDBG(("heuristic_load: %s is selected\n",
1765995Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid));
1766995Shx147065 /* select one in all the networks which meet the preceding stardands */
1767995Shx147065 if (i == ess_num)
1768995Shx147065 (void) do_set_essid(fd, "");
1769995Shx147065 else
1770995Shx147065 (void) do_set_essid(fd,
1771995Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid);
1772995Shx147065
1773995Shx147065 if ((ess_num == 0) || (do_get_essid(fd) == B_FALSE)) {
1774995Shx147065 (void) fprintf(stderr, gettext("%s: autoconf:"
1775995Shx147065 " failed to connect to any essid\n"),
1776995Shx147065 gExecName);
1777995Shx147065 exit(WIFI_MINOR_ERR);
1778995Shx147065 }
1779995Shx147065 (void) strlcpy(essid, ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid,
1780995Shx147065 sizeof (essid));
1781995Shx147065 (void) printf(gettext("%s: autoconf: essid '%s' is selected%s\n"),
1782995Shx147065 gExecName, essid,
1783995Shx147065 have_nowep_wlan ? "" : ": this is a WEPed "
1784995Shx147065 "access point");
1785995Shx147065
1786995Shx147065 if (!have_nowep_wlan)
1787995Shx147065 exit(WIFI_FATAL_ERR);
1788995Shx147065
1789995Shx147065 while (timeout > 0) {
1790995Shx147065 if ((do_get_linkstatus(fd) == B_TRUE) &&
1791995Shx147065 (*(wl_linkstatus_t *)(gbuf->wldp_buf) == WL_CONNECTED)) {
1792995Shx147065 (void) printf(gettext("%s: connecting to "
1793995Shx147065 "essid '%s'\n"), gExecName, essid);
1794995Shx147065 return;
1795995Shx147065 }
1796995Shx147065 (void) sleep(1);
1797995Shx147065 timeout--;
1798995Shx147065 }
1799995Shx147065 (void) fprintf(stderr, gettext("%s: failed to connect to "
1800995Shx147065 "essid '%s'\n"), gExecName, essid);
1801995Shx147065 exit(WIFI_FATAL_ERR);
1802995Shx147065 }
1803995Shx147065
1804995Shx147065 /*
1805995Shx147065 * Called in autoconf and startconf to find which 'profile' is selected.
1806995Shx147065 * The process is: check profile names in the prefer list item by item,
1807995Shx147065 * if the essid of the profile is in the scan list, then it is the wanted.
1808995Shx147065 * readonly: 1 for startconf
1809995Shx147065 * 0 for autoconf
1810995Shx147065 * for autoconf, the scan result will be recorded in the history list.
1811995Shx147065 */
1812995Shx147065 static char *
select_profile(int fd,int readonly,int timeout)1813995Shx147065 select_profile(int fd, int readonly, int timeout)
1814995Shx147065 {
1815995Shx147065 uint32_t ess_num = 0;
1816995Shx147065 int nprefer = 1;
1817995Shx147065 char **ess_argv;
1818995Shx147065 char **hisess_argv;
1819995Shx147065 wl_ess_conf_t **p_ess_conf;
1820995Shx147065 section_t *p_section = NULL;
1821995Shx147065 aelist_t *plist = NULL;
1822995Shx147065 ae_t *pae = NULL;
1823995Shx147065 int i;
1824995Shx147065 const char *parg;
1825995Shx147065 char *selected = NULL;
1826995Shx147065 boolean_t flag = B_FALSE;
1827995Shx147065
1828995Shx147065 if ((call_ioctl(fd, WLAN_COMMAND, WL_SCAN, 0) == B_FALSE) ||
1829995Shx147065 (do_get_wlanlist(fd) == B_FALSE)) {
1830995Shx147065 (void) fprintf(stderr, gettext("%s: "
1831995Shx147065 "autoconf : failed to scan\n"), gExecName);
1832995Shx147065 exit(WIFI_FATAL_ERR);
1833995Shx147065 }
1834995Shx147065 ess_num = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num;
1835995Shx147065 ess_argv = safe_calloc(sizeof (char *), ess_num);
1836995Shx147065 hisess_argv = safe_calloc(sizeof (char *), ess_num);
1837995Shx147065 p_ess_conf = safe_calloc(sizeof (wl_ess_list_t *), ess_num);
1838995Shx147065 for (i = 0; i < ess_num; i++) {
1839995Shx147065 p_ess_conf[i] = ((wl_ess_list_t *)gbuf->wldp_buf)
1840995Shx147065 ->wl_ess_list_ess + i;
1841995Shx147065 ess_argv[i] = safe_malloc(MAX_SCANBUF_LEN);
1842995Shx147065 if (readonly == 0) {
1843995Shx147065 hisess_argv[i] = safe_malloc(MAX_SCANBUF_LEN);
1844995Shx147065 (void) snprintf(hisess_argv[i], MAX_SCANBUF_LEN,
1845995Shx147065 "%s%c%02x:%02x:%02x:%02x:%02x:%02x%c%s",
1846995Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid,
1847995Shx147065 ',',
1848995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[0]),
1849995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[1]),
1850995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[2]),
1851995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[3]),
1852995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[4]),
1853995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[5]), ',',
1854995Shx147065 (p_ess_conf[i]->wl_ess_conf_wepenabled == B_TRUE
1855995Shx147065 ? "wep":"none"));
1856995Shx147065 }
1857995Shx147065 (void) snprintf(ess_argv[i], MAX_SCANBUF_LEN, "%s",
1858995Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid);
1859995Shx147065 }
1860995Shx147065 if (readonly == 0) {
1861995Shx147065 add_to_history(gp_config_file, ess_num, hisess_argv);
1862995Shx147065 for (i = 0; i < ess_num; i++) {
1863995Shx147065 free(hisess_argv[i]);
1864995Shx147065 }
1865995Shx147065 free(hisess_argv);
1866995Shx147065 }
1867995Shx147065
1868995Shx147065 p_section = find_section(gp_config_file, WIFI_PREFER);
1869995Shx147065 if (p_section == NULL) {
1870995Shx147065 if (ess_num > 0) {
1871995Shx147065 heuristic_load(fd, ess_num, p_ess_conf);
1872995Shx147065 exit(WIFI_EXIT_DEF);
1873995Shx147065 }
1874995Shx147065 goto done;
1875995Shx147065 }
1876995Shx147065 plist = p_section->list;
1877995Shx147065 assert(plist != NULL);
1878995Shx147065 if (plist != NULL) {
1879995Shx147065 nprefer = plist->ael_argc;
1880995Shx147065 if (nprefer == 0) {
1881995Shx147065 if (ess_num > 0) {
1882995Shx147065 heuristic_load(fd, ess_num, p_ess_conf);
1883995Shx147065 exit(WIFI_EXIT_DEF);
1884995Shx147065 }
1885995Shx147065 goto done;
1886995Shx147065 }
1887995Shx147065 }
1888995Shx147065 pae = plist->ael_head;
1889995Shx147065 while ((pae != NULL) && (flag != B_TRUE)) {
1890995Shx147065 parg = essid_of_profile(pae->ae_arg);
1891995Shx147065 if (parg != NULL) {
1892995Shx147065 for (i = 0; i < ess_num; i++) {
1893995Shx147065 if (strcmp(parg, ess_argv[i]) == 0) {
1894995Shx147065 selected = pae->ae_arg;
1895995Shx147065 flag = B_TRUE;
1896995Shx147065 break;
1897995Shx147065 }
1898995Shx147065 }
1899995Shx147065 }
1900995Shx147065 pae = pae->ae_next;
1901995Shx147065 }
1902995Shx147065 done:
1903995Shx147065 if ((selected == NULL) && (timeout == 0)) {
1904995Shx147065 heuristic_load(fd, ess_num, p_ess_conf);
1905995Shx147065 }
1906995Shx147065 for (i = 0; i < ess_num; i++) {
1907995Shx147065 free(ess_argv[i]);
1908995Shx147065 }
1909995Shx147065 free(ess_argv);
1910995Shx147065 free(p_ess_conf);
1911995Shx147065 return (selected);
1912995Shx147065 }
1913995Shx147065
1914995Shx147065 static boolean_t
is_waittime_valid(char * pbuf)1915995Shx147065 is_waittime_valid(char *pbuf)
1916995Shx147065 {
1917995Shx147065 int i;
1918995Shx147065
1919995Shx147065 i = atoi(pbuf);
1920995Shx147065 if (i == -1)
1921995Shx147065 return (B_TRUE);
1922995Shx147065 for (i = 0; i < strlen(pbuf); i++) {
1923995Shx147065 if (isdigit(pbuf[i]) == 0) {
1924995Shx147065 return (B_FALSE);
1925995Shx147065 }
1926995Shx147065 }
1927995Shx147065 return (B_TRUE);
1928995Shx147065 }
1929995Shx147065 /*
1930995Shx147065 * do_autoconf: First scan the wlanlist, and select one essid from scan result
1931995Shx147065 * by the order in {preferrence} list. If no match, then heuristic_load;
1932995Shx147065 */
1933995Shx147065 /*ARGSUSED*/
1934995Shx147065 static boolean_t
do_autoconf(int fd,int argc,char ** argv)1935995Shx147065 do_autoconf(int fd, int argc, char **argv)
1936995Shx147065 {
1937995Shx147065 const char *selected = NULL;
1938995Shx147065 int timeout = LOADPROFILE_TIMEOUT, forever = 0, len = 0;
1939995Shx147065 char *pequal, *param;
1940995Shx147065 char **ld_argv = NULL;
1941995Shx147065 boolean_t ret = B_TRUE;
1942995Shx147065
1943995Shx147065 PRTDBG(("do_autoconf(%d, 0x%x)\n", argc, argv));
1944995Shx147065 assert(fd > 0);
1945995Shx147065 if (argc > 0) {
1946995Shx147065 param = safe_strdup(argv[0]);
1947995Shx147065 pequal = strchr(param, '=');
1948995Shx147065 if (pequal != NULL) {
1949995Shx147065 *pequal++ = '\0';
1950995Shx147065 } else {
1951995Shx147065 do_print_usage();
1952995Shx147065 exit(WIFI_IMPROPER_USE);
1953995Shx147065 }
1954995Shx147065 if (strcmp(param, "wait") != 0) {
1955995Shx147065 do_print_usage();
1956995Shx147065 exit(WIFI_IMPROPER_USE);
1957995Shx147065 } else {
1958995Shx147065 if (strcmp(pequal, "forever") == 0) {
1959995Shx147065 forever = 1;
1960995Shx147065 } else {
1961995Shx147065 if (is_waittime_valid(pequal) == B_FALSE) {
1962995Shx147065 (void) fprintf(stderr, gettext("%s: "
1963995Shx147065 "invalid value %s for 'wait'\n"),
1964995Shx147065 gExecName, pequal);
1965995Shx147065 exit(WIFI_FATAL_ERR);
1966995Shx147065 }
1967995Shx147065 if (sscanf(pequal, "%d", &timeout) != 1) {
1968995Shx147065 do_print_usage();
1969995Shx147065 exit(WIFI_IMPROPER_USE);
1970995Shx147065 }
1971995Shx147065 if (timeout == -1) {
1972995Shx147065 forever = 1;
1973995Shx147065 }
1974995Shx147065 }
1975995Shx147065 }
1976995Shx147065 free(param);
1977995Shx147065 if (argc > 1) {
1978995Shx147065 (void) fprintf(stderr, gettext("%s: trailing "
1979995Shx147065 "useless tokens after '%s'\n"),
1980995Shx147065 gExecName, argv[0]);
1981995Shx147065 }
1982995Shx147065 }
1983995Shx147065
1984995Shx147065 while ((forever == 1) || (timeout > 0)) {
1985995Shx147065 timeout--;
1986995Shx147065 selected = select_profile(fd, 0, max(timeout, forever));
1987995Shx147065 if (selected != NULL)
1988995Shx147065 break;
1989995Shx147065 (void) sleep(1);
1990995Shx147065 }
1991995Shx147065 if (selected == NULL) {
1992995Shx147065 return (B_TRUE);
1993995Shx147065 }
1994995Shx147065 (void) printf(gettext("%s: autoconf: profile [%s]"
1995995Shx147065 " is selected\n"), gExecName, selected);
1996995Shx147065 ld_argv = safe_calloc(sizeof (char *), argc+1);
1997995Shx147065 ld_argv[0] = safe_strdup(selected);
1998995Shx147065 if (argc > 0) {
1999995Shx147065 len = max(strlen(argv[0]), strlen("wait=forever"));
2000995Shx147065 ld_argv[1] = safe_malloc(len);
2001995Shx147065 safe_snprintf(ld_argv[1], len + 1, forever == 1 ?
2002995Shx147065 "wait=forever" : "wait=%d", timeout);
2003995Shx147065 }
2004995Shx147065 ret = do_loadpf(fd, argc+1, ld_argv);
2005995Shx147065 free(ld_argv[0]);
2006995Shx147065 if (argc > 0) {
2007995Shx147065 free(ld_argv[1]);
2008995Shx147065 }
2009995Shx147065 free(ld_argv);
2010995Shx147065 return (ret);
2011995Shx147065 }
2012995Shx147065
2013995Shx147065 /*
2014995Shx147065 * do_startconf: almost the same as the do_autoconf, except that doesn't
2015995Shx147065 * write file.
2016995Shx147065 */
2017995Shx147065 /*ARGSUSED*/
2018995Shx147065 static boolean_t
do_startconf(int fd,int argc,char ** argv)2019995Shx147065 do_startconf(int fd, int argc, char **argv)
2020995Shx147065 {
2021995Shx147065 int i = 0, ael_num = 0;
2022995Shx147065 section_t *p_section = NULL;
2023995Shx147065 section_t *p_wep_section = NULL;
2024995Shx147065 aelist_t *plist = NULL;
2025995Shx147065 const char *selected = NULL;
2026995Shx147065 ae_t *pae = NULL;
2027995Shx147065 char *pbuf = NULL;
2028995Shx147065 char **argvnew = NULL;
2029995Shx147065
2030995Shx147065 PRTDBG(("do_startconf(%d, 0x%x)\n", argc, argv));
2031995Shx147065 assert(fd > 0);
2032995Shx147065
2033995Shx147065 selected = select_profile(fd, 1, 0);
2034995Shx147065 if (selected == NULL) {
2035995Shx147065 return (B_TRUE);
2036995Shx147065 }
2037995Shx147065
2038995Shx147065 (void) call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0);
2039995Shx147065
2040995Shx147065 pbuf = append_pa(selected);
2041995Shx147065 p_wep_section = find_section(gp_wepkey_file, pbuf);
2042995Shx147065 p_section = find_section(gp_config_file, pbuf);
2043995Shx147065 free(pbuf);
2044995Shx147065
2045995Shx147065 if (p_wep_section != NULL) {
2046995Shx147065 plist = p_wep_section->list;
2047995Shx147065 pae = plist->ael_head;
2048995Shx147065 while (pae != NULL) {
2049995Shx147065 if (pae->ae_arg != NULL)
2050995Shx147065 (void) do_set_wepkey(fd, pae->ae_arg);
2051995Shx147065 pae = pae->ae_next;
2052995Shx147065 }
2053995Shx147065 }
2054995Shx147065
2055995Shx147065 if (p_section != NULL) {
2056995Shx147065 plist = p_section->list;
2057995Shx147065 if (plist->ael_argc == 0) {
2058995Shx147065 return (B_TRUE);
2059995Shx147065 }
2060995Shx147065 argvnew = aeltoargv(plist, &ael_num);
2061995Shx147065 (void) do_set(fd, ael_num, argvnew);
2062995Shx147065
2063995Shx147065 for (i = 0; i < ael_num; i++)
2064995Shx147065 free(argvnew[i]);
2065995Shx147065 free(argvnew);
2066995Shx147065 }
2067995Shx147065 return (B_TRUE);
2068995Shx147065 }
2069995Shx147065
2070995Shx147065 static char *
find_active_profile(int fd)2071995Shx147065 find_active_profile(int fd)
2072995Shx147065 {
2073995Shx147065 section_t *p_section = NULL, *activep_section = NULL;
2074995Shx147065 aelist_t *plist = NULL;
2075995Shx147065 ae_t *pae = NULL;
2076995Shx147065 const char *pessid = NULL, *pbssid = NULL;
2077995Shx147065 char essid[34], bssid[32];
2078995Shx147065 const char *activeprofile = NULL;
2079995Shx147065
2080995Shx147065 PRTDBG(("find_active_profile: %d\n", fd));
2081995Shx147065 if (do_get_essid(fd) == B_FALSE) {
2082995Shx147065 return (NULL);
2083995Shx147065 }
2084995Shx147065 (void) strlcpy(essid, ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid,
2085995Shx147065 sizeof (essid));
2086995Shx147065 if (do_get_bssid(fd) == B_FALSE) {
2087995Shx147065 return (NULL);
2088995Shx147065 }
2089995Shx147065 safe_snprintf(bssid, sizeof (bssid), "%02x:%02x:%02x:%02x:%02x:%02x",
2090995Shx147065 ((uint8_t *)gbuf->wldp_buf)[0],
2091995Shx147065 ((uint8_t *)gbuf->wldp_buf)[1],
2092995Shx147065 ((uint8_t *)gbuf->wldp_buf)[2],
2093995Shx147065 ((uint8_t *)gbuf->wldp_buf)[3],
2094995Shx147065 ((uint8_t *)gbuf->wldp_buf)[4],
2095995Shx147065 ((uint8_t *)gbuf->wldp_buf)[5]);
2096995Shx147065 activep_section = find_section(gp_config_file, WIFI_ACTIVEP);
2097995Shx147065 if (activep_section == NULL)
2098995Shx147065 return (NULL);
2099995Shx147065 activeprofile = get_value(activep_section->list->
2100995Shx147065 ael_head->ae_arg);
2101995Shx147065 if (activeprofile == NULL)
2102995Shx147065 return (NULL);
2103995Shx147065 p_section = gp_config_file->section_head;
2104995Shx147065 while (p_section != NULL) {
2105995Shx147065 if (((plist = p_section->list) != NULL) &&
2106995Shx147065 (plist->type == PROFILE) &&
2107995Shx147065 (strcmp(p_section->section_id, activeprofile) == 0)) {
2108995Shx147065 pae = plist->ael_head;
2109995Shx147065 while (pae != NULL) {
2110995Shx147065 if (strncmp(pae->ae_arg, "essid=",
2111995Shx147065 strlen("essid=")) == 0) {
2112995Shx147065 pessid = get_value(pae->ae_arg);
2113995Shx147065 }
2114995Shx147065 if (strncmp(pae->ae_arg, "bssid=",
2115995Shx147065 strlen("bssid=")) == 0) {
2116995Shx147065 pbssid = get_value(pae->ae_arg);
2117995Shx147065 }
2118995Shx147065 pae = pae->ae_next;
2119995Shx147065 }
2120995Shx147065 if (pessid && pbssid &&
2121995Shx147065 (strcmp(essid, pessid) == 0) &&
2122995Shx147065 (strcmp(bssid, pbssid) == 0)) {
2123995Shx147065 return (p_section->section_id);
2124995Shx147065 }
2125995Shx147065 }
2126995Shx147065 p_section = p_section->section_next;
2127995Shx147065 }
2128995Shx147065 return (NULL);
2129995Shx147065 }
2130995Shx147065
2131995Shx147065 static void
record_active_profile(char * pname,int action)2132995Shx147065 record_active_profile(char *pname, int action)
2133995Shx147065 {
2134995Shx147065 section_t *p_section = NULL;
2135995Shx147065 aelist_t *plist = NULL;
2136995Shx147065 char pbuf[256];
2137995Shx147065
2138995Shx147065 p_section = find_section(gp_config_file, WIFI_ACTIVEP);
2139995Shx147065 if (p_section == NULL) {
2140995Shx147065 plist = new_ael(ACTIVEP);
2141995Shx147065 new_section(gp_config_file, plist, WIFI_ACTIVEP);
2142995Shx147065 } else {
2143995Shx147065 plist = p_section->list;
2144995Shx147065 }
2145995Shx147065
2146995Shx147065 if (action == RECORD_ADD) {
2147995Shx147065 assert(pname != NULL);
2148995Shx147065 safe_snprintf(pbuf, sizeof (pbuf), "activep=%s", pname);
2149995Shx147065 update_aelist(plist, pbuf);
2150995Shx147065 } else if (action == RECORD_DEL) {
2151995Shx147065 assert(pname == NULL);
2152995Shx147065 update_aelist(plist, "activep= ");
2153995Shx147065 }
2154995Shx147065 }
2155995Shx147065
2156995Shx147065 /*
2157995Shx147065 * do_loadpf: load a profile, set related parameters both in wifi
2158995Shx147065 * and in wifiwepkey, if network name is not exist in the
2159995Shx147065 * configration files, then we clean all parameters and set essid only
2160995Shx147065 */
2161995Shx147065 static boolean_t
do_loadpf(int fd,int argc,char ** argv)2162995Shx147065 do_loadpf(int fd, int argc, char ** argv)
2163995Shx147065 {
2164995Shx147065 int i = 0, ael_num = 0;
2165995Shx147065 int timeout = LOADPROFILE_TIMEOUT, forever = 0;
2166995Shx147065 section_t *p_section = NULL;
2167995Shx147065 section_t *p_wep_section = NULL;
2168995Shx147065 aelist_t *plist = NULL;
2169995Shx147065 ae_t *pae = NULL;
2170995Shx147065 char *pbuf = NULL;
2171995Shx147065 char **argvnew = NULL;
2172995Shx147065 char *connect;
2173995Shx147065 char *pequal, *param;
2174995Shx147065
2175995Shx147065 PRTDBG(("do_loadpf(%d, %x)\n", argc, argv));
2176995Shx147065 assert(fd > 0);
2177995Shx147065 if (argc == 0) {
2178995Shx147065 (void) fprintf(stderr, gettext("%s: connect: "
2179995Shx147065 "profile name missing\n"), gExecName);
2180995Shx147065 return (B_FALSE);
2181995Shx147065 }
2182995Shx147065 if (argc > 1) {
2183995Shx147065 param = safe_strdup(argv[1]);
2184995Shx147065 pequal = strchr(param, '=');
2185995Shx147065 if (pequal != NULL) {
2186995Shx147065 *pequal++ = '\0';
2187995Shx147065 } else {
2188995Shx147065 do_print_usage();
2189995Shx147065 exit(WIFI_IMPROPER_USE);
2190995Shx147065 }
2191995Shx147065 if (strcmp(param, "wait") != 0) {
2192995Shx147065 do_print_usage();
2193995Shx147065 exit(WIFI_IMPROPER_USE);
2194995Shx147065 } else {
2195995Shx147065 if (strcmp(pequal, "forever") == 0) {
2196995Shx147065 forever = 1;
2197995Shx147065 } else {
2198995Shx147065 if (is_waittime_valid(pequal) == B_FALSE) {
2199995Shx147065 (void) fprintf(stderr, gettext("%s: "
2200995Shx147065 "invalid value %s for 'wait'\n"),
2201995Shx147065 gExecName, pequal);
2202995Shx147065 exit(WIFI_FATAL_ERR);
2203995Shx147065 }
2204995Shx147065 if (sscanf(pequal, "%d", &timeout) != 1) {
2205995Shx147065 do_print_usage();
2206995Shx147065 exit(WIFI_IMPROPER_USE);
2207995Shx147065 }
2208995Shx147065 if (timeout == -1) {
2209995Shx147065 forever = 1;
2210995Shx147065 }
2211995Shx147065 }
2212995Shx147065 }
2213995Shx147065 free(param);
2214995Shx147065 if (argc > 2) {
2215995Shx147065 (void) fprintf(stderr, gettext("%s: trailing "
2216995Shx147065 "useless tokens after '%s'\n"),
2217995Shx147065 gExecName, argv[1]);
2218995Shx147065 }
2219995Shx147065 }
2220995Shx147065 (void) call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0);
2221995Shx147065
2222995Shx147065 pbuf = append_pa(argv[0]);
2223995Shx147065 p_wep_section = find_section(gp_wepkey_file, pbuf);
2224995Shx147065 p_section = find_section(gp_config_file, pbuf);
2225995Shx147065
2226995Shx147065 if (p_wep_section != NULL) {
2227995Shx147065 (void) set_prefer(gp_config_file, argv[0], 1);
2228995Shx147065 plist = p_wep_section->list;
2229995Shx147065 pae = plist->ael_head;
2230995Shx147065 while (pae != NULL) {
2231995Shx147065 if (pae->ae_arg != NULL) {
2232995Shx147065 (void) do_set_wepkey(fd, pae->ae_arg);
2233995Shx147065 }
2234995Shx147065 pae = pae->ae_next;
2235995Shx147065 }
2236995Shx147065 }
2237995Shx147065
2238995Shx147065 if (p_section != NULL) {
2239995Shx147065 connect = "profile";
2240995Shx147065
2241995Shx147065 (void) set_prefer(gp_config_file, argv[0], 1);
2242995Shx147065 plist = p_section->list;
2243995Shx147065 if (plist->ael_argc == 0) {
2244995Shx147065 free(pbuf);
2245995Shx147065 return (B_TRUE);
2246995Shx147065 }
2247995Shx147065 argvnew = aeltoargv(plist, &ael_num);
2248995Shx147065 /*
2249995Shx147065 * if there is no 'essid' item in argvnew, the profile
2250995Shx147065 * name(argv[0]) is treated as essid.
2251995Shx147065 */
2252995Shx147065 for (i = 0; i < ael_num; i++) {
2253995Shx147065 if (strncmp(argvnew[i], "essid=", strlen("essid="))
2254995Shx147065 == 0)
2255995Shx147065 break;
2256995Shx147065 }
2257995Shx147065 if (i == ael_num)
2258995Shx147065 (void) do_set_essid(fd, argv[0]);
2259995Shx147065
2260995Shx147065 (void) do_set(fd, ael_num, argvnew);
2261995Shx147065
2262995Shx147065 for (i = 0; i < ael_num; i++)
2263995Shx147065 free(argvnew[i]);
2264995Shx147065 free(argvnew);
2265995Shx147065
2266995Shx147065 /*
2267995Shx147065 * set flag in {active_profile} so that showprofile knows
2268995Shx147065 * which profile is active when more than one profiles are
2269995Shx147065 * created for the same WLAN.
2270995Shx147065 */
2271995Shx147065 record_active_profile(pbuf, RECORD_ADD);
2272995Shx147065 } else {
2273995Shx147065 (void) do_set_essid(fd, argv[0]);
2274995Shx147065 connect = "essid";
2275995Shx147065 }
2276995Shx147065
2277995Shx147065 while ((forever == 1) || (timeout > 0)) {
2278995Shx147065 if ((do_get_linkstatus(fd) == B_TRUE) &&
2279995Shx147065 (*(wl_linkstatus_t *)(gbuf->wldp_buf) == WL_CONNECTED)) {
2280995Shx147065 section_t *p_section = NULL;
2281995Shx147065 aelist_t *plist = NULL;
2282995Shx147065 char bssid[32];
2283995Shx147065 /* record bssid in the profile */
2284995Shx147065 if (do_get_bssid(fd) == B_FALSE) {
2285995Shx147065 free(pbuf);
2286995Shx147065 return (B_TRUE);
2287995Shx147065 }
2288995Shx147065 safe_snprintf(bssid, sizeof (bssid),
2289995Shx147065 "bssid=%02x:%02x:%02x:%02x:%02x:%02x",
2290995Shx147065 ((uint8_t *)gbuf->wldp_buf)[0],
2291995Shx147065 ((uint8_t *)gbuf->wldp_buf)[1],
2292995Shx147065 ((uint8_t *)gbuf->wldp_buf)[2],
2293995Shx147065 ((uint8_t *)gbuf->wldp_buf)[3],
2294995Shx147065 ((uint8_t *)gbuf->wldp_buf)[4],
2295995Shx147065 ((uint8_t *)gbuf->wldp_buf)[5]);
2296995Shx147065
2297995Shx147065 p_section = find_section(gp_config_file, pbuf);
2298995Shx147065 if (p_section != NULL) {
2299995Shx147065 plist = p_section->list;
2300995Shx147065 update_aelist(plist, bssid);
2301995Shx147065 }
2302995Shx147065 free(pbuf);
2303995Shx147065 (void) printf(gettext("%s: connecting to "
2304995Shx147065 "%s '%s'\n"), gExecName, connect, argv[0]);
2305995Shx147065 return (B_TRUE);
2306995Shx147065 }
2307995Shx147065 (void) sleep(1);
2308995Shx147065 timeout--;
2309995Shx147065 PRTDBG(("connect counting:......%d\n", timeout));
2310995Shx147065 }
2311995Shx147065 (void) fprintf(stderr, gettext("%s: failed to connect to "
2312995Shx147065 "%s '%s'\n"), gExecName, connect, argv[0]);
2313995Shx147065 free(pbuf);
2314995Shx147065 return (B_FALSE);
2315995Shx147065 }
2316995Shx147065
2317995Shx147065 /*
2318995Shx147065 * if wepkey is set in the profile, display wepkey|n=*****
2319995Shx147065 * when showprofile and getprofilewepkey.
2320995Shx147065 * if wepkeyn is NULL, all the wepkeys will be display,
2321995Shx147065 * otherwise, just display the matching one.
2322995Shx147065 */
2323995Shx147065 static void
print_wepkey_info(const char * id,const char * wepkeyn)2324995Shx147065 print_wepkey_info(const char *id, const char *wepkeyn)
2325995Shx147065 {
2326995Shx147065 char *pequal, *param;
2327995Shx147065 section_t *p_section = NULL;
2328995Shx147065 aelist_t *plist = NULL;
2329995Shx147065 ae_t *pae = NULL;
2330995Shx147065
2331995Shx147065 p_section = find_section(gp_wepkey_file, id);
2332995Shx147065 if (p_section != NULL) {
2333995Shx147065 plist = p_section->list;
2334995Shx147065 pae = plist->ael_head;
2335995Shx147065 while (pae != NULL) {
2336995Shx147065 if (pae->ae_arg != NULL) {
2337995Shx147065 param = safe_strdup(pae->ae_arg);
2338995Shx147065 pequal = strchr(param, '=');
2339995Shx147065 if (pequal == NULL)
2340995Shx147065 return;
2341995Shx147065 *pequal = '\0';
2342995Shx147065 if (wepkeyn != NULL) {
2343995Shx147065 if (strcmp(wepkeyn, param) == 0)
2344995Shx147065 (void) printf("\t%s=*****\n",
2345995Shx147065 param);
2346995Shx147065 free(param);
2347995Shx147065 return;
2348995Shx147065 } else {
2349995Shx147065 (void) printf("\t%s=*****\n", param);
2350995Shx147065 free(param);
2351995Shx147065 }
2352995Shx147065 }
2353995Shx147065 pae = pae->ae_next;
2354995Shx147065 }
2355995Shx147065 }
2356995Shx147065 }
2357995Shx147065
2358995Shx147065 /*
2359995Shx147065 * do_printpf: print each parameters of the profile, if no network name
2360995Shx147065 * assigned, then print all profile saved in configration file.
2361995Shx147065 */
2362995Shx147065 /*ARGSUSED*/
2363995Shx147065 static boolean_t
do_printpf(int fd,int argc,char ** argv)2364995Shx147065 do_printpf(int fd, int argc, char ** argv)
2365995Shx147065 {
2366995Shx147065 section_t *p_section = NULL;
2367995Shx147065 aelist_t *plist = NULL;
2368995Shx147065 ae_t *pae = NULL;
2369995Shx147065 char *pbuf = NULL;
2370995Shx147065 int i;
2371995Shx147065
2372995Shx147065 PRTDBG(("do_printpf(%d, %x)\n", argc, argv));
2373995Shx147065
2374995Shx147065 /*
2375995Shx147065 * if no profile name is inputted, all the profiles will be displayed.
2376995Shx147065 */
2377995Shx147065 if (argc == 0) {
2378995Shx147065 p_section = gp_config_file->section_head;
2379995Shx147065 while (p_section != NULL) {
2380995Shx147065 plist = p_section->list;
2381995Shx147065 if (plist->type == PROFILE) {
2382995Shx147065 (void) printf("%s\n", p_section->section_id);
2383995Shx147065 pae = plist->ael_head;
2384995Shx147065 while (pae != NULL) {
2385995Shx147065 if (pae->ae_arg != NULL) {
2386995Shx147065 (void) printf("\t%s\n",
2387995Shx147065 pae->ae_arg);
2388995Shx147065 }
2389995Shx147065 pae = pae->ae_next;
2390995Shx147065 }
2391995Shx147065 /*
2392995Shx147065 * identify whether wepkey is set
2393995Shx147065 * in the profile
2394995Shx147065 */
2395995Shx147065 print_wepkey_info(p_section->section_id, NULL);
2396995Shx147065 }
2397995Shx147065 p_section = p_section->section_next;
2398995Shx147065 }
2399995Shx147065 return (B_TRUE);
2400995Shx147065 }
2401995Shx147065
2402995Shx147065 for (i = 0; i < argc; i++) {
2403995Shx147065 pbuf = append_pa(argv[i]);
2404995Shx147065 p_section = find_section(gp_config_file, pbuf);
2405995Shx147065 free(pbuf);
2406995Shx147065 if (p_section != NULL) {
2407995Shx147065 (void) printf("%s\n", p_section->section_id);
2408995Shx147065 plist = p_section->list;
2409995Shx147065 if (plist != NULL) {
2410995Shx147065 pae = plist->ael_head;
2411995Shx147065 while (pae != NULL) {
2412995Shx147065 if (pae->ae_arg != NULL) {
2413995Shx147065 (void) printf("\t%s\n",
2414995Shx147065 pae->ae_arg);
2415995Shx147065 }
2416995Shx147065 pae = pae->ae_next;
2417995Shx147065 }
2418995Shx147065 /*
2419995Shx147065 * identify whether wepkey is set
2420995Shx147065 * in the profile
2421995Shx147065 */
2422995Shx147065 print_wepkey_info(p_section->section_id, NULL);
2423995Shx147065 }
2424995Shx147065 } else {
2425995Shx147065 (void) fprintf(stderr,
2426*6834Sff224033 gettext("%s: showprofile : "
2427*6834Sff224033 "no such profile: '%s'\n"),
2428*6834Sff224033 gExecName, argv[i]);
2429995Shx147065 return (B_FALSE);
2430995Shx147065 }
2431995Shx147065 }
2432995Shx147065 return (B_TRUE);
2433995Shx147065 }
2434995Shx147065 /*
2435995Shx147065 * find_ae: Find an ae by its contents, return its pointer.
2436995Shx147065 */
2437995Shx147065 static ae_t *
find_ae(aelist_t * plist,const char * arg)2438995Shx147065 find_ae(aelist_t *plist, const char *arg)
2439995Shx147065 {
2440995Shx147065 char *param = NULL;
2441995Shx147065 char *pnext = NULL;
2442995Shx147065 ae_t *pae = NULL;
2443995Shx147065
2444995Shx147065 if ((arg == NULL) || (plist == NULL)) {
2445995Shx147065 PRTDBG(("find_ae: arg= NULL or plist=NULL\n"));
2446995Shx147065 return (NULL);
2447995Shx147065 }
2448995Shx147065 PRTDBG(("find_ae(0x%x, \"%s\")\n", plist, arg));
2449995Shx147065 param = safe_strdup(arg);
2450995Shx147065 pnext = strchr(param, '=');
2451995Shx147065 if (pnext != NULL) {
2452995Shx147065 *pnext = '\0';
2453995Shx147065 } else {
2454995Shx147065 PRTDBG(("find_ae: param = \"%s\"\n", param));
2455995Shx147065 free(param);
2456995Shx147065 return (NULL);
2457995Shx147065 }
2458995Shx147065
2459995Shx147065 pae = plist->ael_head;
2460995Shx147065 while (pae != NULL) {
2461995Shx147065 if ((pae->ae_arg != NULL) &&
2462995Shx147065 (strncmp(pae->ae_arg, param, strlen(param)) == 0)) {
2463995Shx147065 PRTDBG(("find_ae: param = \"%s\"\n", param));
2464995Shx147065 free(param);
2465995Shx147065 return (pae);
2466995Shx147065 }
2467995Shx147065 pae = pae->ae_next;
2468995Shx147065 }
2469995Shx147065 free(param);
2470995Shx147065 return (NULL);
2471995Shx147065 }
2472995Shx147065
2473995Shx147065 /*
2474995Shx147065 * update_aelist: Update an aelist by arg, for example:
2475995Shx147065 * there are an item with content"essid=ap7-2",
2476995Shx147065 * update_aelist(0x..., "essid=myssid2") will update it as "essid=myssid2"
2477995Shx147065 */
2478995Shx147065 static void
update_aelist(aelist_t * plist,const char * arg)2479995Shx147065 update_aelist(aelist_t *plist, const char *arg)
2480995Shx147065 {
2481995Shx147065 ae_t *pae = NULL;
2482995Shx147065
2483995Shx147065 assert((arg != NULL)&&(plist != NULL));
2484995Shx147065 PRTDBG(("update_aelist(0x%x, \"%s\")\n", plist, arg));
2485995Shx147065 pae = find_ae(plist, arg);
2486995Shx147065 if (pae == NULL) {
2487995Shx147065 new_ae(plist, arg);
2488995Shx147065 } else {
2489995Shx147065 free(pae->ae_arg);
2490995Shx147065 pae->ae_arg = safe_strdup(arg);
2491995Shx147065 }
2492995Shx147065 }
2493995Shx147065
2494995Shx147065 /*
2495995Shx147065 * do_deletepf: delete a profile in configration files.
2496995Shx147065 */
2497995Shx147065 /*ARGSUSED*/
2498995Shx147065 static boolean_t
do_deletepf(int fd,int argc,char ** argv)2499995Shx147065 do_deletepf(int fd, int argc, char **argv)
2500995Shx147065 {
2501995Shx147065 int i = 0;
2502995Shx147065 char *section_id;
2503995Shx147065 char *prefer;
2504995Shx147065 section_t *p_section = NULL, *p_sectionbak = NULL;
2505995Shx147065 aelist_t *plist = NULL;
2506995Shx147065
2507995Shx147065 PRTDBG(("do_deletepf(%d, \"%s\")\n", argc, argv));
2508995Shx147065 if (argc <= 0) {
2509995Shx147065 do_print_usage();
2510995Shx147065 exit(WIFI_IMPROPER_USE);
2511995Shx147065 }
2512995Shx147065
2513995Shx147065 /*
2514995Shx147065 * if a "all" is inputted, all the profiles will be deleted.
2515995Shx147065 */
2516995Shx147065 if (strcasecmp(argv[0], "all") == 0) {
2517995Shx147065 p_section = gp_config_file->section_head;
2518995Shx147065 while ((p_section != NULL) &&
2519995Shx147065 ((plist = p_section->list) != NULL)) {
2520995Shx147065 if (plist->type == PROFILE) {
2521995Shx147065 p_sectionbak = p_section->section_next;
2522995Shx147065 section_id = safe_strdup(p_section->section_id);
2523995Shx147065 (void) del_section(gp_config_file, section_id);
2524995Shx147065 (void) del_section(gp_wepkey_file, section_id);
2525995Shx147065 /*
2526995Shx147065 * remove the '[]' of the [section_id]
2527995Shx147065 */
2528995Shx147065 prefer = section_id + 1;
2529995Shx147065 *(prefer + strlen(section_id) - 2) = '\0';
2530995Shx147065 (void) del_prefer(gp_config_file, prefer,
2531995Shx147065 B_FALSE);
2532995Shx147065 free(section_id);
2533995Shx147065 p_section = p_sectionbak;
2534995Shx147065 continue;
2535995Shx147065 }
2536995Shx147065 p_section = p_section->section_next;
2537995Shx147065 }
2538995Shx147065 return (B_TRUE);
2539995Shx147065 }
2540995Shx147065 if (gp_config_file != NULL) {
2541995Shx147065 for (i = 0; i < argc; i++) {
2542995Shx147065 section_id = append_pa(argv[i]);
2543995Shx147065 if (del_section(gp_config_file, section_id)
2544995Shx147065 == B_FALSE) {
2545995Shx147065 if (del_section(gp_wepkey_file, section_id)
2546995Shx147065 == B_TRUE) {
2547995Shx147065 (void) del_prefer(gp_config_file,
2548995Shx147065 argv[i], B_FALSE);
2549995Shx147065 free(section_id);
2550995Shx147065 return (B_TRUE);
2551995Shx147065 } else {
2552995Shx147065 (void) fprintf(stderr,
2553995Shx147065 gettext("%s: deleteprofile"
2554995Shx147065 ": no such profile: '%s'\n"),
2555995Shx147065 gExecName, argv[i]);
2556995Shx147065 free(section_id);
2557995Shx147065 return (B_FALSE);
2558995Shx147065 }
2559995Shx147065 }
2560995Shx147065 (void) del_prefer(gp_config_file, argv[i], B_FALSE);
2561995Shx147065 (void) del_section(gp_wepkey_file, section_id);
2562995Shx147065 free(section_id);
2563995Shx147065 }
2564995Shx147065 }
2565995Shx147065 return (B_TRUE);
2566995Shx147065 }
2567995Shx147065
2568995Shx147065 /*
2569995Shx147065 * do_history: Print the list in {history} section.
2570995Shx147065 */
2571995Shx147065 /*ARGSUSED*/
2572995Shx147065 static boolean_t
do_history(int fd,int argc,char ** argv)2573995Shx147065 do_history(int fd, int argc, char **argv)
2574995Shx147065 {
2575995Shx147065 section_t *p_section = NULL;
2576995Shx147065 aelist_t *plist = NULL;
2577995Shx147065 ae_t *pae = NULL;
2578995Shx147065 char *param, *param_bak, *pcomma;
2579995Shx147065 uint32_t maxessidlen = 0, ulen;
2580995Shx147065 char format[256], *ntstr;
2581995Shx147065 uint32_t nt = 0, cnt = 0;
2582995Shx147065 int len;
2583995Shx147065 time_t cltime;
2584995Shx147065
2585995Shx147065 PRTDBG(("do_history(%d, 0x%x)\n", argc, argv));
2586995Shx147065 if (argc > 0) {
2587995Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
2588995Shx147065 "after 'history'\n"), gExecName);
2589995Shx147065 }
2590995Shx147065 p_section = find_section(gp_config_file, WIFI_HISTORY);
2591995Shx147065 if (p_section == NULL) {
2592995Shx147065 PRTDBG(("no history section\n"));
2593995Shx147065 return (B_FALSE);
2594995Shx147065 }
2595995Shx147065 plist = p_section->list;
2596995Shx147065
2597995Shx147065 /*
2598995Shx147065 * If history section is empty, directly return.
2599995Shx147065 */
2600995Shx147065 if (plist == NULL)
2601995Shx147065 return (B_TRUE);
2602995Shx147065 /*
2603995Shx147065 * construct the output format in terms of the
2604995Shx147065 * maxmium essid length
2605995Shx147065 */
2606995Shx147065 pae = NULL;
2607995Shx147065 pae = plist->ael_head;
2608995Shx147065 while (pae != NULL) {
2609995Shx147065 if (pae->ae_arg != NULL) {
2610995Shx147065 param = safe_strdup(pae->ae_arg);
2611995Shx147065 pcomma = strchr(param, ',');
2612995Shx147065 if (pcomma == NULL) {
2613995Shx147065 (void) fprintf(stderr,
2614995Shx147065 gettext("%s: history : "
2615995Shx147065 "data format error\n"),
2616995Shx147065 gExecName);
2617995Shx147065 free(param);
2618995Shx147065 return (B_FALSE);
2619995Shx147065 }
2620995Shx147065 *pcomma = '\0';
2621995Shx147065 ulen = strlen(param);
2622995Shx147065 maxessidlen = (maxessidlen > ulen
2623995Shx147065 ? maxessidlen:ulen);
2624995Shx147065 free(param);
2625995Shx147065 }
2626995Shx147065 pae = pae->ae_next;
2627995Shx147065 }
2628995Shx147065 if ((nt = (maxessidlen / 8 + 1)) > 4)
2629995Shx147065 nt = 4;
2630995Shx147065 len = snprintf(format, sizeof (format), gettext("essid"));
2631995Shx147065 ntstr = construct_format(nt);
2632995Shx147065 assert((ntstr != NULL) && (strlen(ntstr) <= 4));
2633995Shx147065 len += snprintf(format + len, sizeof (format) - len, "%s", ntstr);
2634995Shx147065 len += snprintf(format + len, sizeof (format) - len,
2635995Shx147065 gettext("bssid\t\t encryption\tlast seen\n"));
2636995Shx147065
2637995Shx147065 if ((len <= 0) || (len > sizeof (format) - 1)) {
2638995Shx147065 (void) printf(gettext("essid\t\t\t\tbssid\t\t encryption"
2639995Shx147065 "\tlast seen\n"));
2640995Shx147065 } else {
2641995Shx147065 (void) printf("%s", format);
2642995Shx147065 }
2643995Shx147065 /*
2644995Shx147065 * output the contents of the history section.
2645995Shx147065 */
2646995Shx147065 pae = plist->ael_head;
2647995Shx147065 while (pae != NULL) {
2648995Shx147065 if (pae->ae_arg != NULL) {
2649995Shx147065 param = safe_strdup(pae->ae_arg);
2650995Shx147065 param_bak = param;
2651995Shx147065 if ((pcomma = strchr(param, ',')) != NULL) {
2652995Shx147065 *pcomma = '\0';
2653995Shx147065 cnt = nt - (min((strlen(param)/8 + 1), 4) - 1);
2654995Shx147065 ntstr = construct_format(cnt);
2655995Shx147065 assert(ntstr != NULL);
2656995Shx147065 /* display essid */
2657995Shx147065 (void) printf("%s%s", param, ntstr);
2658995Shx147065 free(ntstr);
2659995Shx147065 }
2660995Shx147065 param = pcomma + 1;
2661995Shx147065 if ((pcomma = strchr(param, ',')) != NULL) {
2662995Shx147065 *pcomma = '\0';
2663995Shx147065 /* display bssid */
2664995Shx147065 (void) printf("%s ", param);
2665995Shx147065 }
2666995Shx147065 param = pcomma + 1;
2667995Shx147065 if ((pcomma = strchr(param, ',')) != NULL) {
2668995Shx147065 *pcomma = '\0';
2669995Shx147065 /* display wep */
2670995Shx147065 (void) printf("%s\t\t", param);
2671995Shx147065 }
2672995Shx147065 param = pcomma + 1;
2673995Shx147065 /* display time stamp */
2674995Shx147065 cltime = (time_t)atol(param);
2675995Shx147065 (void) printf("%s", ctime(&cltime));
2676995Shx147065 free(param_bak);
2677995Shx147065 }
2678995Shx147065 pae = pae->ae_next;
2679995Shx147065 }
2680995Shx147065
2681995Shx147065 return (B_TRUE);
2682995Shx147065 }
2683995Shx147065
2684995Shx147065 /*
2685995Shx147065 * do_lsprefer: Print the list in {preferrence} section
2686995Shx147065 */
2687995Shx147065 /*ARGSUSED*/
2688995Shx147065 static boolean_t
do_lsprefer(int fd,int argc,char ** argv)2689995Shx147065 do_lsprefer(int fd, int argc, char **argv)
2690995Shx147065 {
2691995Shx147065 int i = 0;
2692995Shx147065 section_t *p_section = NULL;
2693995Shx147065 aelist_t *plist = NULL;
2694995Shx147065 ae_t *pae = NULL;
2695995Shx147065 char *pbuf;
2696995Shx147065
2697995Shx147065 PRTDBG(("do_lsprefer(%d, 0x%x)\n", argc, argv));
2698995Shx147065 if (argc > 0) {
2699995Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
2700995Shx147065 "after 'listprefer'\n"), gExecName);
2701995Shx147065 }
2702995Shx147065 p_section = find_section(gp_config_file, WIFI_PREFER);
2703995Shx147065 if (p_section != NULL) {
2704995Shx147065 plist = p_section->list;
2705995Shx147065 if (plist != NULL) {
2706995Shx147065 pae = NULL;
2707995Shx147065 pae = plist->ael_head;
2708995Shx147065 while (pae != NULL) {
2709995Shx147065 if (pae->ae_arg != NULL) {
2710995Shx147065 pbuf = append_pa(pae->ae_arg);
2711995Shx147065 (void) printf("%d\t%s\n", ++i, pbuf);
2712995Shx147065 }
2713995Shx147065 pae = pae->ae_next;
2714995Shx147065 }
2715995Shx147065 }
2716995Shx147065 return (B_TRUE);
2717995Shx147065 } else {
2718995Shx147065 PRTDBG(("no preference section\n"));
2719995Shx147065 return (B_FALSE);
2720995Shx147065 }
2721995Shx147065 }
2722995Shx147065
2723995Shx147065 /*
2724995Shx147065 * do_rmprefer: Remove an item in {preferrence} list
2725995Shx147065 */
2726995Shx147065 /*ARGSUSED*/
2727995Shx147065 static boolean_t
do_rmprefer(int fd,int argc,char ** argv)2728995Shx147065 do_rmprefer(int fd, int argc, char **argv)
2729995Shx147065 {
2730995Shx147065 int i = 0;
2731995Shx147065 section_t *p_section = NULL;
2732995Shx147065 aelist_t *plist = NULL;
2733995Shx147065 ae_t *pae = NULL;
2734995Shx147065
2735995Shx147065 PRTDBG(("do_rmprefer(%d, 0x%x)\n", argc, argv));
2736995Shx147065 if (argc <= 0) {
2737995Shx147065 do_print_usage();
2738995Shx147065 exit(WIFI_IMPROPER_USE);
2739995Shx147065 }
2740995Shx147065
2741995Shx147065 /*
2742995Shx147065 * if a "all" is inputted, all the items in the preference
2743995Shx147065 * list will be deleted.
2744995Shx147065 */
2745995Shx147065 if (strcasecmp(argv[0], "all") == 0) {
2746995Shx147065 p_section = find_section(gp_config_file, WIFI_PREFER);
2747995Shx147065 if (p_section != NULL)
2748995Shx147065 plist = p_section->list;
2749995Shx147065
2750995Shx147065 if ((p_section == NULL) || (plist == NULL))
2751995Shx147065 return (B_FALSE);
2752995Shx147065 pae = plist->ael_head;
2753995Shx147065 while (pae != NULL) {
2754995Shx147065 free(pae);
2755995Shx147065 pae = pae->ae_next;
2756995Shx147065 }
2757995Shx147065 plist->ael_head = plist->ael_tail = NULL;
2758995Shx147065 plist->ael_argc = 0;
2759995Shx147065 } else if (gp_config_file != NULL) {
2760995Shx147065 for (i = 0; i < argc; i++) {
2761995Shx147065 if (del_prefer(gp_config_file, argv[i], B_TRUE)
2762995Shx147065 == B_FALSE) {
2763995Shx147065 return (B_FALSE);
2764995Shx147065 }
2765995Shx147065 }
2766995Shx147065 }
2767995Shx147065 return (B_TRUE);
2768995Shx147065 }
2769995Shx147065
2770995Shx147065 static boolean_t
is_prefer_rank_valid(const char * pbuf)2771995Shx147065 is_prefer_rank_valid(const char *pbuf)
2772995Shx147065 {
2773995Shx147065 int i;
2774995Shx147065 boolean_t ret = B_FALSE;
2775995Shx147065
2776995Shx147065 for (i = 0; i < strlen(pbuf); i++) {
2777995Shx147065 if (isdigit(pbuf[i]) == 0) {
2778995Shx147065 ret = B_FALSE;
2779995Shx147065 goto exit0;
2780995Shx147065 }
2781995Shx147065 }
2782995Shx147065 i = atoi(pbuf);
2783995Shx147065 if ((i >= 1) && (i <= MAX_PREFERENCE_NUM))
2784995Shx147065 ret = B_TRUE;
2785995Shx147065 exit0:
2786995Shx147065 return (ret);
2787995Shx147065 }
2788995Shx147065
2789995Shx147065 /*
2790995Shx147065 * do_setprefer: Set network preferrence
2791995Shx147065 */
2792995Shx147065 /*ARGSUSED*/
2793995Shx147065 static boolean_t
do_setprefer(int fd,int argc,char ** argv)2794995Shx147065 do_setprefer(int fd, int argc, char **argv)
2795995Shx147065 {
2796995Shx147065 int rank = 0;
2797995Shx147065
2798995Shx147065 PRTDBG(("do_setprefer(%d, 0x%x)\n", argc, argv));
2799995Shx147065 if (argc <= 0) {
2800995Shx147065 do_print_usage();
2801995Shx147065 exit(WIFI_IMPROPER_USE);
2802995Shx147065 }
2803995Shx147065 if (argc == 1) {
2804995Shx147065 rank = 1;
2805995Shx147065 } else {
2806995Shx147065 if (is_prefer_rank_valid(argv[1]) == B_FALSE) {
2807995Shx147065 (void) fprintf(stderr, gettext("%s: preference rank "
2808995Shx147065 "should be an integer within 1-10\n"), gExecName);
2809995Shx147065 return (B_FALSE);
2810995Shx147065 }
2811995Shx147065 rank = atoi(argv[1]);
2812995Shx147065 }
2813995Shx147065 return (set_prefer(gp_config_file, argv[0], rank));
2814995Shx147065 }
2815995Shx147065
2816995Shx147065 static boolean_t
is_wepkeyindex_valid(const char * pbuf)2817995Shx147065 is_wepkeyindex_valid(const char *pbuf)
2818995Shx147065 {
2819995Shx147065 int i;
2820995Shx147065 boolean_t ret = B_FALSE;
2821995Shx147065
2822995Shx147065 for (i = 0; i < strlen(pbuf); i++) {
2823995Shx147065 if (isdigit(pbuf[i]) == 0) {
2824995Shx147065 ret = B_FALSE;
2825995Shx147065 goto exit0;
2826995Shx147065 }
2827995Shx147065 }
2828995Shx147065 i = atoi(pbuf);
2829995Shx147065 if ((i >= 1) && (i <= MAX_NWEPKEYS))
2830995Shx147065 ret = B_TRUE;
2831995Shx147065 exit0:
2832995Shx147065 return (ret);
2833995Shx147065 }
2834995Shx147065
2835995Shx147065 static boolean_t
is_channel_valid(const char * pbuf)2836995Shx147065 is_channel_valid(const char *pbuf)
2837995Shx147065 {
2838995Shx147065 int i;
2839995Shx147065 boolean_t ret = B_FALSE;
2840995Shx147065
2841995Shx147065 for (i = 0; i < strlen(pbuf); i++) {
2842995Shx147065 if (isdigit(pbuf[i]) == 0) {
2843995Shx147065 ret = B_FALSE;
2844995Shx147065 goto exit0;
2845995Shx147065 }
2846995Shx147065 }
2847995Shx147065 i = atoi(pbuf);
2848995Shx147065 if ((i >= 0) && (i <= MAX_CHANNEL_NUM))
2849995Shx147065 ret = B_TRUE;
2850995Shx147065 exit0:
2851995Shx147065 return (ret);
2852995Shx147065 }
2853995Shx147065
2854995Shx147065 static boolean_t
is_wepkey_valid(const char * pbuf,uint32_t length)2855995Shx147065 is_wepkey_valid(const char *pbuf, uint32_t length)
2856995Shx147065 {
2857995Shx147065 int i;
2858995Shx147065 boolean_t ret = B_FALSE;
2859995Shx147065
2860995Shx147065 switch (length) {
2861995Shx147065 case 10:
2862995Shx147065 case 26:
2863995Shx147065 for (i = 0; i < length; i++) {
2864995Shx147065 if (isxdigit(pbuf[i]) == 0) {
2865995Shx147065 ret = B_FALSE;
2866995Shx147065 goto exit0;
2867995Shx147065 }
2868995Shx147065 }
2869995Shx147065 ret = B_TRUE;
2870995Shx147065 break;
2871995Shx147065 case 5:
2872995Shx147065 case 13:
2873995Shx147065 ret = B_TRUE;
2874995Shx147065 break;
2875995Shx147065 default:
2876995Shx147065 ret = B_FALSE;
2877995Shx147065 break;
2878995Shx147065 }
2879995Shx147065 exit0:
2880995Shx147065 if (ret == B_FALSE) {
2881995Shx147065 (void) fprintf(stderr, gettext("%s: "
2882995Shx147065 "wepkey should be:\n"
2883995Shx147065 "\t 40bits: 5 char or 10 hex digits.\n"
2884995Shx147065 "\t 128bits: 13 char or 26 hex digits.\n"),
2885995Shx147065 gExecName);
2886995Shx147065 }
2887995Shx147065 return (ret);
2888995Shx147065 }
2889995Shx147065
2890995Shx147065 /*
2891995Shx147065 * get_valid_wepkey: get an valid wepkey from stdin
2892995Shx147065 */
2893995Shx147065 static char *
get_valid_wepkey()2894995Shx147065 get_valid_wepkey()
2895995Shx147065 {
2896995Shx147065 int i = 0;
2897995Shx147065 char *buf = NULL;
2898995Shx147065 uint8_t length = 0;
2899995Shx147065 struct termios stored_settings;
2900995Shx147065 struct termios new_settings;
2901995Shx147065
2902995Shx147065 PRTDBG(("get_valid_wepkey()\n"));
2903995Shx147065 buf = safe_calloc(sizeof (char), MAX_KEY_LENGTH + 2);
2904995Shx147065 /*
2905995Shx147065 * Because we need to get single char from terminal, so we need to
2906995Shx147065 * disable canonical mode and set buffer size to 1 tyte. And because
2907995Shx147065 * wepkey should not be see by others, so we disable echo too.
2908995Shx147065 */
2909995Shx147065 (void) fflush(stdin);
2910995Shx147065 (void) tcgetattr(0, &stored_settings);
2911995Shx147065 new_settings = stored_settings;
2912995Shx147065 new_settings.c_lflag &= (~ICANON);
2913995Shx147065 new_settings.c_lflag &= (~ECHO);
2914995Shx147065 new_settings.c_cc[VTIME] = 0;
2915995Shx147065 new_settings.c_cc[VMIN] = 1;
2916995Shx147065 /* Set new terminal attributes */
2917995Shx147065 (void) tcsetattr(0, TCSANOW, &new_settings);
2918995Shx147065 while (((buf[i++] = getchar()) != '\n') && (i < MAX_KEY_LENGTH + 1)) {
2919995Shx147065 (void) putchar('*');
2920995Shx147065 }
2921995Shx147065 (void) putchar('\n');
2922995Shx147065 /* Restore terminal attributes */
2923995Shx147065 (void) tcsetattr(0, TCSANOW, &stored_settings);
2924995Shx147065 (void) fflush(stdin);
2925995Shx147065
2926995Shx147065 if (buf[--i] != '\n') {
2927995Shx147065 (void) fprintf(stderr, gettext("%s: wepkey length "
2928995Shx147065 "exceeds 26 hex digits\n"), gExecName);
2929995Shx147065 free(buf);
2930995Shx147065 return (NULL);
2931995Shx147065 }
2932995Shx147065 /* Replace last char '\n' with '\0' */
2933995Shx147065 buf[i] = '\0';
2934995Shx147065 length = (uint8_t)i;
2935995Shx147065 return ((is_wepkey_valid(buf, length) == B_TRUE)?
2936995Shx147065 buf : NULL);
2937995Shx147065 }
2938995Shx147065
2939995Shx147065 /*
2940995Shx147065 * do_set_wepkey: Set parameters in wepkey, and call ioctl
2941995Shx147065 */
2942995Shx147065 static boolean_t
do_set_wepkey(int fd,const char * pbuf)2943995Shx147065 do_set_wepkey(int fd, const char *pbuf)
2944995Shx147065 {
2945995Shx147065 int id = 0;
2946995Shx147065 char i = 0;
2947995Shx147065 uint8_t len = 0;
2948995Shx147065 uint8_t length;
2949995Shx147065 const char *wepkey = NULL;
2950995Shx147065 char key[MAX_KEY_LENGTH] = {0};
2951995Shx147065 unsigned int keytmp;
2952995Shx147065 wl_wep_key_tab_t wepkey_tab;
2953995Shx147065
2954995Shx147065 PRTDBG(("do_set_wepkey(%d, \"%s\")\n", fd, pbuf));
2955995Shx147065 if (!check_authority(AUTH_WEP)) {
2956995Shx147065 exit(WIFI_FATAL_ERR);
2957995Shx147065 }
2958995Shx147065 id = pbuf[strlen("wepkeyn") - 1] - '0';
2959995Shx147065 wepkey = get_value(pbuf);
2960995Shx147065 length = strlen(wepkey);
2961995Shx147065 switch (length) {
2962995Shx147065 case 10:
2963995Shx147065 case 26:
2964995Shx147065 for (i = 0; i < length / 2; i++) {
2965995Shx147065 (void) sscanf(wepkey + i * 2, "%2x", &keytmp);
2966995Shx147065 key[i] = (char)keytmp;
2967995Shx147065 }
2968995Shx147065 len = length / 2;
2969995Shx147065 break;
2970995Shx147065 case 5:
2971995Shx147065 case 13:
2972995Shx147065 (void) strlcpy(key, wepkey, MAX_KEY_LENGTH);
2973995Shx147065 len = length;
2974995Shx147065 break;
2975995Shx147065 default:
2976995Shx147065 PRTDBG(("do_set_wepkey: error pbuf size\n"));
2977995Shx147065 (void) fprintf(stderr, gettext("%s: "
2978995Shx147065 "wepkey should be:\n"
2979995Shx147065 "\t 40bits: 5 char or 10 hex digits.\n"
2980995Shx147065 "\t 128bits: 13 char or 26 hex digits.\n"),
2981995Shx147065 gExecName);
2982995Shx147065 exit(WIFI_FATAL_ERR);
2983995Shx147065 }
2984995Shx147065
2985995Shx147065 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab));
2986995Shx147065 for (i = 0; i < MAX_NWEPKEYS; i++) {
2987995Shx147065 wepkey_tab[i].wl_wep_operation = WL_NUL;
2988995Shx147065 }
2989995Shx147065
2990995Shx147065 if (id > 0 && id <= MAX_NWEPKEYS) {
2991995Shx147065 wepkey_tab[id-1].wl_wep_operation = WL_ADD;
2992995Shx147065 wepkey_tab[id-1].wl_wep_length = len;
2993995Shx147065 (void) memcpy(wepkey_tab[id-1].wl_wep_key, key, len);
2994995Shx147065 } else {
2995995Shx147065 (void) fprintf(stderr, gettext("%s: wepkeyindex "
2996995Shx147065 "should be an integer within the range 1-4\n"), gExecName);
2997995Shx147065 exit(WIFI_FATAL_ERR);
2998995Shx147065 }
2999995Shx147065 (void) memmove(gbuf->wldp_buf, &wepkey_tab, sizeof (wl_wep_key_tab_t));
3000995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_WEP_KEY_TAB,
3001995Shx147065 sizeof (wl_wep_key_tab_t)));
3002995Shx147065 }
3003995Shx147065
3004995Shx147065 /*
3005995Shx147065 * get the committed wepkey. the return form is like wepkey1=*****;
3006995Shx147065 */
3007995Shx147065 /*ARGSUSED*/
3008995Shx147065 static char *
get_commit_key(int fd,int argc,char ** argv)3009995Shx147065 get_commit_key(int fd, int argc, char **argv)
3010995Shx147065 {
3011995Shx147065 int key;
3012995Shx147065 int len;
3013995Shx147065 char *wepkey = NULL;
3014995Shx147065 char *wepkey_confirm = NULL;
3015995Shx147065 char *pbuf = NULL;
3016995Shx147065
3017995Shx147065 key = atoi(argv[0]);
3018995Shx147065 if (key <= 0 || key > MAX_NWEPKEYS) {
3019995Shx147065 (void) fprintf(stderr, gettext("%s: wepkeyindex "
3020995Shx147065 "should be an integer within the range 1-4\n"), gExecName);
3021995Shx147065 goto exit0;
3022995Shx147065 }
3023995Shx147065 (void) printf(gettext("input wepkey%d:"), key);
3024995Shx147065 wepkey = get_valid_wepkey();
3025995Shx147065 if (wepkey == NULL) {
3026995Shx147065 goto exit0;
3027995Shx147065 }
3028995Shx147065 (void) printf(gettext("confirm wepkey%d:"), key);
3029995Shx147065 wepkey_confirm = get_valid_wepkey();
3030995Shx147065 if (wepkey_confirm == NULL) {
3031995Shx147065 free(wepkey);
3032995Shx147065 goto exit0;
3033995Shx147065 }
3034995Shx147065 if (strcmp(wepkey, wepkey_confirm) != 0) {
3035995Shx147065 free(wepkey);
3036995Shx147065 free(wepkey_confirm);
3037995Shx147065 (void) fprintf(stderr,
3038995Shx147065 gettext("%s: wepkey: "
3039995Shx147065 "two inputs are not identical\n"), gExecName);
3040995Shx147065 goto exit0;
3041995Shx147065 }
3042995Shx147065 free(wepkey_confirm); /* wepkey_confirm is no longer used */
3043995Shx147065
3044995Shx147065 len = MAX_KEY_LENGTH + strlen("wepkey1=\n") + 1;
3045995Shx147065 pbuf = safe_malloc(len);
3046995Shx147065 safe_snprintf(pbuf, len, "%s%d=%s", "wepkey", key, wepkey);
3047995Shx147065
3048995Shx147065 free(wepkey); /* wepkey is no longer used */
3049995Shx147065 return (pbuf);
3050995Shx147065 exit0:
3051995Shx147065 return (NULL);
3052995Shx147065 }
3053995Shx147065
3054995Shx147065 /*
3055995Shx147065 * do_wepkey: Get input from user, call do_set_wepkey
3056995Shx147065 */
3057995Shx147065 /*ARGSUSED*/
3058995Shx147065 static boolean_t
do_wepkey(int fd,int argc,char ** argv)3059995Shx147065 do_wepkey(int fd, int argc, char **argv)
3060995Shx147065 {
3061995Shx147065 char *pbuf;
3062995Shx147065
3063995Shx147065 PRTDBG(("do_wepkey(%d, 0x%x)\n", argc, argv));
3064995Shx147065 assert(fd > 0);
3065995Shx147065 if (argc <= 0) {
3066995Shx147065 do_print_usage();
3067995Shx147065 exit(WIFI_IMPROPER_USE);
3068995Shx147065 }
3069995Shx147065 if (argc > 1) {
3070995Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3071995Shx147065 "after 'setwepkey'\n"), gExecName);
3072995Shx147065 }
3073995Shx147065 pbuf = get_commit_key(fd, argc, argv);
3074995Shx147065 if ((pbuf != NULL) && (do_set_wepkey(fd, pbuf) == B_TRUE)) {
3075995Shx147065 free(pbuf);
3076995Shx147065 return (B_TRUE);
3077995Shx147065 }
3078995Shx147065 free(pbuf);
3079995Shx147065 return (B_FALSE);
3080995Shx147065 }
3081995Shx147065
3082995Shx147065 /*ARGSUSED*/
3083995Shx147065 static boolean_t
do_setprofwepkey(int fd,int argc,char ** argv)3084995Shx147065 do_setprofwepkey(int fd, int argc, char **argv)
3085995Shx147065 {
3086995Shx147065 char *pbuf;
3087995Shx147065 char *section_id = NULL;
3088995Shx147065 section_t *p_section = NULL;
3089995Shx147065 aelist_t *plist = NULL;
3090995Shx147065
3091995Shx147065 PRTDBG(("do_setprofwepkey(%d, 0x%x)\n", argc, argv));
3092995Shx147065 if (argc < 2) {
3093995Shx147065 do_print_usage();
3094995Shx147065 exit(WIFI_IMPROPER_USE);
3095995Shx147065 }
3096995Shx147065 if (argc > 2) {
3097995Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3098995Shx147065 "after 'setprofwepkey'\n"), gExecName);
3099995Shx147065 }
3100995Shx147065
3101995Shx147065 section_id = append_pa(argv[0]);
3102995Shx147065 p_section = find_section(gp_wepkey_file, section_id);
3103995Shx147065 free(section_id);
3104995Shx147065 if (p_section == NULL) {
3105995Shx147065 (void) fprintf(stderr, gettext("%s: "
3106995Shx147065 "no such profile: '%s'\n"),
3107995Shx147065 gExecName, argv[0]);
3108995Shx147065 return (B_FALSE);
3109995Shx147065 }
3110995Shx147065
3111995Shx147065 argc--;
3112995Shx147065 argv++;
3113995Shx147065 pbuf = get_commit_key(fd, argc, argv);
3114995Shx147065 if (pbuf == NULL)
3115995Shx147065 return (B_FALSE);
3116995Shx147065 plist = p_section->list;
3117995Shx147065 update_aelist(plist, pbuf);
3118995Shx147065
3119995Shx147065 return (B_TRUE);
3120995Shx147065 }
3121995Shx147065
3122995Shx147065 /*
3123995Shx147065 * do_wlanlist: Scan for wlanlist
3124995Shx147065 */
3125995Shx147065 /*ARGSUSED*/
3126995Shx147065 static boolean_t
do_wlanlist(int fd,int argc,char ** argv)3127995Shx147065 do_wlanlist(int fd, int argc, char **argv)
3128995Shx147065 {
3129995Shx147065 PRTDBG(("do_wlanlist(%d, 0x%x)\n", argc, argv));
3130995Shx147065 assert(fd > 0);
3131995Shx147065 if (argc > 0) {
3132995Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3133995Shx147065 "after 'scan'\n"), gExecName);
3134995Shx147065 }
3135995Shx147065 if (call_ioctl(fd, WLAN_COMMAND, WL_SCAN, 0) == B_FALSE) {
3136995Shx147065 (void) fprintf(stderr, gettext("%s: failed to scan\n"),
3137995Shx147065 gExecName);
3138995Shx147065 return (B_FALSE);
3139995Shx147065 }
3140995Shx147065 if (do_get_wlanlist(fd) == B_TRUE) {
3141995Shx147065 print_gbuf(WLANLIST);
3142995Shx147065 }
3143995Shx147065 return (B_TRUE);
3144995Shx147065 }
3145995Shx147065
3146995Shx147065 /*
3147995Shx147065 * do_showstatus: show the basic status of the interface, including
3148995Shx147065 * linkstauts, essid, encryption and signal strength.
3149995Shx147065 */
3150995Shx147065 /*ARGSUSED*/
3151995Shx147065 static boolean_t
do_showstatus(int fd,int argc,char ** argv)3152995Shx147065 do_showstatus(int fd, int argc, char **argv)
3153995Shx147065 {
3154995Shx147065 wl_rssi_t signal;
3155995Shx147065 char *active_profile = NULL;
3156995Shx147065
3157995Shx147065 PRTDBG(("do_showstatus(%d, 0x%x)\n", argc, argv));
3158995Shx147065 assert(fd > 0);
3159995Shx147065
3160995Shx147065 if (argc > 0) {
3161995Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3162995Shx147065 "after 'showstatus'\n"), gExecName);
3163995Shx147065 }
3164995Shx147065 if (do_get_linkstatus(fd) == B_TRUE) {
3165995Shx147065 print_gbuf(LINKSTATUS);
3166995Shx147065 if (*(wl_linkstatus_t *)(gbuf->wldp_buf) == WL_NOTCONNECTED) {
3167995Shx147065 return (B_TRUE);
3168995Shx147065 }
3169995Shx147065 }
3170995Shx147065 active_profile = find_active_profile(fd);
3171995Shx147065 (void) printf("\tactive profile: %s\n",
3172995Shx147065 active_profile ? active_profile : "none");
3173995Shx147065 if (do_get_essid(fd) == B_TRUE) {
3174995Shx147065 print_gbuf(ESSID);
3175995Shx147065 }
3176995Shx147065 if (do_get_bssid(fd) == B_TRUE) {
3177995Shx147065 print_gbuf(BSSID);
3178995Shx147065 }
3179995Shx147065 if (do_get_encryption(fd) == B_TRUE) {
3180995Shx147065 print_gbuf(ENCRYPTION);
3181995Shx147065 }
3182995Shx147065 if (do_get_signal(fd) == B_TRUE) {
3183995Shx147065 signal = *(wl_rssi_t *)(gbuf->wldp_buf);
3184995Shx147065 if (signal < 4) {
3185995Shx147065 (void) printf("\tsignal strength: weak(%d)\n",
3186995Shx147065 signal);
3187995Shx147065 } else if ((signal >= 4) && (signal <= 11)) {
3188995Shx147065 (void) printf("\tsignal strength: medium(%d)\n",
3189995Shx147065 signal);
3190995Shx147065 } else {
3191995Shx147065 (void) printf("\tsignal strength: strong(%d)\n",
3192995Shx147065 signal);
3193995Shx147065 }
3194995Shx147065 }
3195995Shx147065
3196995Shx147065 return (B_TRUE);
3197995Shx147065 }
3198995Shx147065
3199995Shx147065
3200995Shx147065 /*
3201995Shx147065 * do_restoredef: Ask driver for loading default parameters
3202995Shx147065 */
3203995Shx147065 /*ARGSUSED*/
3204995Shx147065 static boolean_t
do_restoredef(int fd,int argc,char ** argv)3205995Shx147065 do_restoredef(int fd, int argc, char **argv)
3206995Shx147065 {
3207995Shx147065 PRTDBG(("do_restoredef(%d, 0x%x)\n", argc, argv));
3208995Shx147065 assert(fd > 0);
3209995Shx147065
3210995Shx147065 if (argc > 0) {
3211995Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3212995Shx147065 "after 'restoredef'\n"), gExecName);
3213995Shx147065 }
3214995Shx147065 record_active_profile(NULL, RECORD_DEL);
3215995Shx147065 if (call_ioctl(fd, WLAN_COMMAND, WL_LOAD_DEFAULTS, 0) == B_FALSE) {
3216995Shx147065 return (B_FALSE);
3217995Shx147065 } else {
3218995Shx147065 return (B_TRUE);
3219995Shx147065 }
3220995Shx147065 }
3221995Shx147065
3222995Shx147065 /*
3223995Shx147065 * do_disconnect: disconnect from the current connectted network
3224995Shx147065 */
3225995Shx147065 /*ARGSUSED*/
3226995Shx147065 static boolean_t
do_disconnect(int fd,int argc,char ** argv)3227995Shx147065 do_disconnect(int fd, int argc, char **argv)
3228995Shx147065 {
3229995Shx147065 PRTDBG(("do_disconnect(%d, 0x%x)\n", argc, argv));
3230995Shx147065 assert(fd > 0);
3231995Shx147065
3232995Shx147065 if (argc > 0) {
3233995Shx147065 (void) fprintf(stderr, gettext("%s: trailing useless tokens "
3234995Shx147065 "after 'disconnect'\n"), gExecName);
3235995Shx147065 }
3236995Shx147065 record_active_profile(NULL, RECORD_DEL);
3237995Shx147065 if (call_ioctl(fd, WLAN_COMMAND, WL_DISASSOCIATE, 0) == B_FALSE) {
3238995Shx147065 return (B_FALSE);
3239995Shx147065 } else {
3240995Shx147065 return (B_TRUE);
3241995Shx147065 }
3242995Shx147065 }
3243995Shx147065
3244995Shx147065 static boolean_t
do_set_essid(int fd,const char * arg)3245995Shx147065 do_set_essid(int fd, const char *arg)
3246995Shx147065 {
3247995Shx147065 wl_essid_t essid;
3248995Shx147065
3249995Shx147065 PRTDBG(("do_set_essid(%d, \"%s\")\n", fd, arg));
3250995Shx147065
3251995Shx147065 /*
3252995Shx147065 * a trick here: clean the active_profile flag
3253995Shx147065 * in section{active_profile}
3254995Shx147065 */
3255995Shx147065 record_active_profile(NULL, RECORD_DEL);
3256995Shx147065
3257995Shx147065 (void) memset(&essid, 0x0, sizeof (essid));
3258995Shx147065
3259995Shx147065 if (arg == NULL || strcmp(arg, "") == 0) {
3260995Shx147065 essid.wl_essid_length = 0;
3261995Shx147065 essid.wl_essid_essid[0] = '\0';
3262995Shx147065 } else {
3263995Shx147065 essid.wl_essid_length = strlen(arg);
3264*6834Sff224033 if (essid.wl_essid_length > MAX_ESSID_LENGTH - 1) {
3265995Shx147065 (void) fprintf(stderr, gettext("%s: "
3266995Shx147065 "essid exceeds 32 bytes\n"), gExecName);
3267995Shx147065 exit(WIFI_FATAL_ERR);
3268995Shx147065 }
3269995Shx147065 (void) strcpy(essid.wl_essid_essid, arg);
3270995Shx147065 }
3271995Shx147065 (void) memmove(gbuf->wldp_buf, &essid, sizeof (wl_essid_t));
3272995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_ESSID, sizeof (wl_essid_t)));
3273995Shx147065 }
3274995Shx147065
3275995Shx147065 static boolean_t
do_set_bsstype(int fd,const char * arg)3276995Shx147065 do_set_bsstype(int fd, const char *arg)
3277995Shx147065 {
3278995Shx147065 wl_bss_type_t bsstype;
3279995Shx147065
3280995Shx147065 assert(arg != NULL);
3281995Shx147065
3282995Shx147065 PRTDBG(("do_set_bsstype(%d, \"%s\")\n", fd, arg));
3283995Shx147065
3284995Shx147065 (void) memset(&bsstype, 0xff, sizeof (bsstype));
3285995Shx147065
3286995Shx147065 if ((strcasecmp(arg, "BSS") == 0) ||
3287995Shx147065 (strcasecmp(arg, "AP") == 0) ||
3288995Shx147065 (strcasecmp(arg, "INFRASTRUCTURE") == 0)) {
3289995Shx147065 bsstype = WL_BSS_BSS;
3290995Shx147065 } else if ((strcasecmp(arg, "IBSS") == 0) ||
3291995Shx147065 (strcasecmp(arg, "AD-HOC") == 0)) {
3292995Shx147065 bsstype = WL_BSS_IBSS;
3293995Shx147065 } else if (strcasecmp(arg, "AUTO") == 0) {
3294995Shx147065 bsstype = WL_BSS_ANY;
3295995Shx147065 } else {
3296995Shx147065 (void) fprintf(stderr, gettext("%s: bsstype: "
3297995Shx147065 "bss(ap,infrastructure) ibss(ad-hoc) or auto\n"),
3298995Shx147065 gExecName);
3299995Shx147065 exit(WIFI_FATAL_ERR);
3300995Shx147065 }
3301995Shx147065
3302995Shx147065 (void) memmove(gbuf->wldp_buf, &bsstype, sizeof (wl_bss_type_t));
3303995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_BSS_TYPE,
3304995Shx147065 sizeof (wl_bss_type_t)));
3305995Shx147065 }
3306995Shx147065
3307995Shx147065 static boolean_t
do_set_createibss(int fd,const char * arg)3308995Shx147065 do_set_createibss(int fd, const char *arg)
3309995Shx147065 {
3310995Shx147065 wl_create_ibss_t create_ibss;
3311995Shx147065
3312995Shx147065 assert(arg != NULL);
3313995Shx147065
3314995Shx147065 PRTDBG(("do_set_createibss(%d, \"%s\")\n", fd, arg));
3315995Shx147065
3316995Shx147065 (void) memset(&create_ibss, 0x0, sizeof (create_ibss));
3317995Shx147065
3318995Shx147065 if (strcasecmp(arg, "YES") == 0) {
3319995Shx147065 create_ibss = B_TRUE;
3320995Shx147065 } else if (strcasecmp(arg, "NO") == 0) {
3321995Shx147065 create_ibss = B_FALSE;
3322995Shx147065 } else {
3323995Shx147065 (void) fprintf(stderr, gettext("%s: "
3324995Shx147065 "createibss: yes or no\n"), gExecName);
3325995Shx147065 exit(WIFI_FATAL_ERR);
3326995Shx147065 }
3327995Shx147065
3328995Shx147065 (void) memmove(gbuf->wldp_buf, &create_ibss,
3329995Shx147065 sizeof (wl_create_ibss_t));
3330995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_CREATE_IBSS,
3331995Shx147065 sizeof (wl_create_ibss_t)));
3332995Shx147065 }
3333995Shx147065
3334995Shx147065 static boolean_t
do_set_channel(int fd,const char * arg)3335995Shx147065 do_set_channel(int fd, const char *arg)
3336995Shx147065 {
3337995Shx147065 wl_phy_conf_t phy_conf;
3338995Shx147065
3339995Shx147065 assert(arg != NULL);
3340995Shx147065 PRTDBG(("do_set_channel(%d, \"%s\")\n", fd, arg));
3341995Shx147065
3342995Shx147065 (void) memset(&phy_conf, 0xff, sizeof (phy_conf));
3343995Shx147065
3344995Shx147065 if (is_channel_valid(arg) == B_FALSE) {
3345995Shx147065 (void) fprintf(stderr, gettext("%s: channel No. "
3346995Shx147065 "should be:\n"
3347995Shx147065 "\t802.11a: 0-99\n"
3348995Shx147065 "\t802.11b: 1-14\n"
3349995Shx147065 "\t802.11g: 1-14\n"), gExecName);
3350995Shx147065 exit(WIFI_FATAL_ERR);
3351995Shx147065 }
3352995Shx147065 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = atoi(arg);
3353995Shx147065 PRTDBG(("channel=%d\n", phy_conf.wl_phy_dsss_conf.wl_dsss_channel));
3354995Shx147065
3355995Shx147065 (void) memmove(gbuf->wldp_buf, &phy_conf, sizeof (wl_phy_conf_t));
3356995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_PHY_CONFIG,
3357995Shx147065 sizeof (wl_phy_conf_t)));
3358995Shx147065 }
3359995Shx147065 /*
3360995Shx147065 * is_rates_support: Querying driver about supported rates.
3361995Shx147065 */
3362995Shx147065 static boolean_t
is_rates_support(int fd,int num,uint8_t * rates)3363995Shx147065 is_rates_support(int fd, int num, uint8_t *rates)
3364995Shx147065 {
3365995Shx147065 int rates_num = 0;
3366995Shx147065 int i = 0, j = 0;
3367995Shx147065 uint8_t value = 0;
3368995Shx147065
3369995Shx147065 assert((rates != NULL)&&(num != 0));
3370995Shx147065 PRTDBG(("is_rates_support(%d, %d, 0x%x)\n", fd, num, rates));
3371995Shx147065
3372995Shx147065 if (call_ioctl(fd, WLAN_GET_PARAM, WL_SUPPORTED_RATES, 0)
3373995Shx147065 == B_TRUE) {
3374995Shx147065 rates_num = ((wl_rates_t *)(gbuf->wldp_buf))->wl_rates_num;
3375995Shx147065
3376995Shx147065 for (i = 0; i < num; i++) {
3377995Shx147065 PRTDBG(("rates[%d] = %d\n", i, rates[i]));
3378995Shx147065 for (j = 0; j < rates_num; j++) {
3379995Shx147065 value = ((wl_rates_t *)gbuf->wldp_buf)
3380995Shx147065 ->wl_rates_rates[j];
3381995Shx147065 PRTDBG(("supported rates[%d]=%d\n", j, value));
3382995Shx147065 if (value == rates[i]) {
3383995Shx147065 break;
3384995Shx147065 }
3385995Shx147065 }
3386995Shx147065 if (j == rates_num) {
3387995Shx147065 if (rates[i] == 11) {
3388995Shx147065 (void) fprintf(stderr,
3389995Shx147065 gettext("%s: "
3390995Shx147065 "rate 5.5M is not supported\n"),
3391995Shx147065 gExecName);
3392995Shx147065 } else {
3393995Shx147065 (void) fprintf(stderr,
3394995Shx147065 gettext("%s: "
3395995Shx147065 "rate %dM is not supported\n"),
3396995Shx147065 gExecName, rates[i]/2);
3397995Shx147065 }
3398995Shx147065 return (B_FALSE);
3399995Shx147065 }
3400995Shx147065 }
3401995Shx147065 return (B_TRUE);
3402995Shx147065 }
3403995Shx147065 return (B_FALSE);
3404995Shx147065 }
3405995Shx147065
3406995Shx147065 /*
3407995Shx147065 *
3408995Shx147065 */
3409995Shx147065 static uint8_t
rates_convert(const char * rates)3410995Shx147065 rates_convert(const char *rates)
3411995Shx147065 {
3412995Shx147065 int i;
3413995Shx147065 uint8_t ret;
3414995Shx147065
3415995Shx147065 for (i = 0; i < WIFI_RATES_NUM; i++) {
3416995Shx147065 if (strcmp(rates, wifi_rates_s[i].rates_s) == 0) {
3417995Shx147065 ret = wifi_rates_s[i].rates_i;
3418995Shx147065 break;
3419995Shx147065 }
3420995Shx147065 }
3421995Shx147065 if (i == WIFI_RATES_NUM) {
3422995Shx147065 (void) fprintf(stderr, gettext("%s: "
3423995Shx147065 "invalid rates '%s'\n"), gExecName, rates);
3424995Shx147065 exit(WIFI_FATAL_ERR);
3425995Shx147065 }
3426995Shx147065 return (ret);
3427995Shx147065 }
3428995Shx147065
3429995Shx147065 /*
3430995Shx147065 * get_rates: convert string value arg into uint8_t array,
3431995Shx147065 * array length will be save into *len[i].
3432995Shx147065 * for example:
3433995Shx147065 * arg = "1,2,5.5,11"
3434995Shx147065 * then after call, rates[] = {2,4,11,22} will be returned.
3435995Shx147065 * and *len will equal to 4
3436995Shx147065 */
3437995Shx147065 static uint8_t *
get_rates(const char * arg,uint32_t * len)3438995Shx147065 get_rates(const char *arg, uint32_t *len)
3439995Shx147065 {
3440995Shx147065 int i = 1, j = 0;
3441995Shx147065 uint8_t *rates = NULL;
3442995Shx147065 char *pnext = NULL;
3443995Shx147065 char *token;
3444995Shx147065 char *pstart;
3445995Shx147065 char *pstart_bak;
3446995Shx147065
3447995Shx147065 assert(arg != NULL);
3448995Shx147065
3449995Shx147065 if (strlen(arg) == 0) {
3450995Shx147065 PRTDBG(("get_rates: empty rates string\n"));
3451995Shx147065 return (NULL);
3452995Shx147065 }
3453995Shx147065 PRTDBG(("get_rates(\"%s\", 0x%x)\n", arg, len));
3454995Shx147065 pstart = safe_strdup(arg);
3455995Shx147065 pstart_bak = pstart;
3456995Shx147065 while ((pnext = strchr(pstart, ',')) != NULL) {
3457995Shx147065 pstart = pnext + 1;
3458995Shx147065 i++;
3459995Shx147065 }
3460995Shx147065 *len = i;
3461995Shx147065 rates = safe_calloc(sizeof (uint8_t), i);
3462995Shx147065
3463995Shx147065 pstart = pstart_bak;
3464995Shx147065 if ((token = strtok(pstart, ",")) != NULL) {
3465995Shx147065 PRTDBG(("rates[0]: %s\n", token));
3466995Shx147065 rates[0] = rates_convert(token);
3467995Shx147065 i = 1;
3468995Shx147065 while ((token = strtok(NULL, ",")) != NULL) {
3469995Shx147065 PRTDBG(("rates[%d]: %s\n", i, token));
3470995Shx147065 rates[i++] = rates_convert(token);
3471995Shx147065 }
3472995Shx147065 }
3473995Shx147065 free(pstart_bak);
3474995Shx147065 for (i = 0; i < *len; i++) {
3475995Shx147065 for (j = 0; j < i; j++)
3476995Shx147065 if (rates[j] == rates[i]) {
3477995Shx147065 (void) fprintf(stderr,
3478995Shx147065 gettext("%s: rates duplicated\n"),
3479995Shx147065 gExecName);
3480995Shx147065 free(rates);
3481995Shx147065 return (NULL);
3482995Shx147065 }
3483995Shx147065 }
3484995Shx147065
3485995Shx147065 return (rates);
3486995Shx147065 }
3487995Shx147065
3488995Shx147065 static boolean_t
do_set_rates(int fd,const char * arg)3489995Shx147065 do_set_rates(int fd, const char *arg)
3490995Shx147065 {
3491995Shx147065 int i = 0;
3492995Shx147065 uint32_t num = 0;
3493995Shx147065 uint8_t *rates;
3494995Shx147065
3495995Shx147065 assert(arg != NULL);
3496995Shx147065
3497995Shx147065 PRTDBG(("do_set_rates(%d, \"%s\")\n", fd, arg));
3498995Shx147065
3499995Shx147065 rates = get_rates(arg, &num);
3500995Shx147065 if ((rates == NULL) ||
3501995Shx147065 is_rates_support(fd, num, rates) == B_FALSE) {
3502995Shx147065 exit(WIFI_FATAL_ERR);
3503995Shx147065 }
3504995Shx147065
3505995Shx147065 ((wl_rates_t *)(gbuf->wldp_buf))->wl_rates_num = num;
3506995Shx147065 for (i = 0; i < num; i++) {
3507995Shx147065 ((wl_rates_t *)gbuf->wldp_buf)->wl_rates_rates[i]
3508995Shx147065 = rates[i];
3509995Shx147065 }
3510995Shx147065 free(rates);
3511995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_DESIRED_RATES,
3512995Shx147065 offsetof(wl_rates_t, wl_rates_rates) +
3513995Shx147065 num*sizeof (char)));
3514995Shx147065 }
3515995Shx147065
3516995Shx147065 static boolean_t
do_set_powermode(int fd,const char * arg)3517995Shx147065 do_set_powermode(int fd, const char *arg)
3518995Shx147065 {
3519995Shx147065 wl_ps_mode_t ps_mode;
3520995Shx147065
3521995Shx147065 assert(arg != NULL);
3522995Shx147065
3523995Shx147065 PRTDBG(("do_set_powermode(%d, \"%s\")\n", fd, arg));
3524995Shx147065
3525995Shx147065 (void) memset(&ps_mode, 0xff, sizeof (ps_mode));
3526995Shx147065
3527995Shx147065 if ((strcasecmp(arg, "OFF") == 0) ||
3528995Shx147065 (strcasecmp(arg, "MPS") == 0) ||
3529995Shx147065 (strcasecmp(arg, "FAST") == 0)) {
3530995Shx147065 switch (arg[0]) {
3531995Shx147065 case 'O':
3532995Shx147065 case 'o':
3533995Shx147065 ps_mode.wl_ps_mode = WL_PM_AM;
3534995Shx147065 break;
3535995Shx147065 case 'M':
3536995Shx147065 case 'm':
3537995Shx147065 ps_mode.wl_ps_mode = WL_PM_MPS;
3538995Shx147065 break;
3539995Shx147065 case 'F':
3540995Shx147065 case 'f':
3541995Shx147065 ps_mode.wl_ps_mode = WL_PM_FAST;
3542995Shx147065 break;
3543995Shx147065 default:
3544995Shx147065 break;
3545995Shx147065 }
3546995Shx147065 } else {
3547995Shx147065 (void) fprintf(stderr,
3548995Shx147065 gettext("%s: powermode: off mps or fast\n"), gExecName);
3549995Shx147065 exit(WIFI_FATAL_ERR);
3550995Shx147065 }
3551995Shx147065
3552995Shx147065 (void) memmove(gbuf->wldp_buf, &ps_mode, sizeof (wl_ps_mode_t));
3553995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_POWER_MODE,
3554995Shx147065 sizeof (wl_ps_mode_t)));
3555995Shx147065 }
3556995Shx147065
3557995Shx147065 static boolean_t
do_set_authmode(int fd,const char * arg)3558995Shx147065 do_set_authmode(int fd, const char *arg)
3559995Shx147065 {
3560995Shx147065 wl_authmode_t auth_mode;
3561995Shx147065
3562995Shx147065 assert(arg != NULL);
3563995Shx147065 PRTDBG(("do_set_authmode(%d, \"%s\")\n", fd, arg));
3564995Shx147065
3565995Shx147065 (void) memset(&auth_mode, 0xff, sizeof (auth_mode));
3566995Shx147065 /* Mark */
3567995Shx147065 if (strcasecmp(arg, "OPENSYSTEM") == 0) {
3568995Shx147065 auth_mode = WL_OPENSYSTEM;
3569995Shx147065 } else if (strcasecmp(arg, "SHARED_KEY") == 0) {
3570995Shx147065 auth_mode = WL_SHAREDKEY;
3571995Shx147065 } else {
3572995Shx147065 (void) fprintf(stderr,
3573995Shx147065 gettext("%s: authmode: "
3574995Shx147065 "opensystem or shared_key\n"), gExecName);
3575995Shx147065 exit(WIFI_FATAL_ERR);
3576995Shx147065 }
3577995Shx147065
3578995Shx147065 (void) memmove(gbuf->wldp_buf, &auth_mode, sizeof (wl_authmode_t));
3579995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_AUTH_MODE,
3580995Shx147065 sizeof (wl_authmode_t)));
3581995Shx147065 }
3582995Shx147065
3583995Shx147065 static boolean_t
do_set_encryption(int fd,const char * arg)3584995Shx147065 do_set_encryption(int fd, const char *arg)
3585995Shx147065 {
3586995Shx147065 wl_encryption_t encryption;
3587995Shx147065
3588995Shx147065 assert(arg != NULL);
3589995Shx147065 PRTDBG(("do_set_encryption(%d, \"%s\")\n", fd, arg));
3590995Shx147065
3591995Shx147065 (void) memset(&encryption, 0xff, sizeof (encryption));
3592995Shx147065
3593995Shx147065 if (strcasecmp(arg, "NONE") == 0) {
3594995Shx147065 encryption = WL_NOENCRYPTION;
3595995Shx147065 } else if (strcasecmp(arg, "WEP") == 0) {
3596995Shx147065 encryption = WL_ENC_WEP;
3597995Shx147065 } else {
3598995Shx147065 (void) fprintf(stderr, gettext("%s: encryption: "
3599995Shx147065 "none or wep\n"), gExecName);
3600995Shx147065 exit(WIFI_FATAL_ERR);
3601995Shx147065 }
3602995Shx147065
3603995Shx147065 (void) memmove(gbuf->wldp_buf, &encryption, sizeof (wl_encryption_t));
3604995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_ENCRYPTION,
3605995Shx147065 sizeof (wl_encryption_t)));
3606995Shx147065 }
3607995Shx147065
3608995Shx147065 static boolean_t
do_set_wepkeyid(int fd,const char * arg)3609995Shx147065 do_set_wepkeyid(int fd, const char *arg)
3610995Shx147065 {
3611995Shx147065 wl_wep_key_id_t wep_key_id;
3612995Shx147065
3613995Shx147065 assert(arg != NULL);
3614995Shx147065 PRTDBG(("do_set_wepkeyid(%d, \"%s\")\n", fd, arg));
3615995Shx147065
3616995Shx147065 (void) memset(&wep_key_id, 0xff, sizeof (wep_key_id));
3617995Shx147065 if (is_wepkeyindex_valid(arg) == B_FALSE) {
3618995Shx147065 (void) fprintf(stderr, gettext("%s: wepkeyindex "
3619995Shx147065 "should be an integer within the range 1-4\n"), gExecName);
3620995Shx147065 exit(WIFI_FATAL_ERR);
3621995Shx147065 }
3622995Shx147065 wep_key_id = atoi(arg) - 1;
3623995Shx147065
3624995Shx147065 (void) memmove(gbuf->wldp_buf, &wep_key_id, sizeof (wl_wep_key_id_t));
3625995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_WEP_KEY_ID,
3626995Shx147065 sizeof (wl_wep_key_id_t)));
3627995Shx147065 }
3628995Shx147065
3629995Shx147065 static boolean_t
do_set_radioon(int fd,const char * arg)3630995Shx147065 do_set_radioon(int fd, const char *arg)
3631995Shx147065 {
3632995Shx147065 wl_radio_t radio;
3633995Shx147065
3634995Shx147065 assert(arg != NULL);
3635995Shx147065 PRTDBG(("do_set_radioon(%d, \"%s\")\n", fd, arg));
3636995Shx147065
3637995Shx147065 (void) memset(&radio, 0xff, sizeof (radio));
3638995Shx147065
3639995Shx147065 if (strcasecmp(arg, "ON") == 0) {
3640995Shx147065 radio = B_TRUE;
3641995Shx147065 } else if (strcasecmp(arg, "OFF") == 0) {
3642995Shx147065 radio = B_FALSE;
3643995Shx147065 } else {
3644995Shx147065 (void) fprintf(stderr,
3645995Shx147065 gettext("%s: radio : on or off\n"), gExecName);
3646995Shx147065 exit(WIFI_FATAL_ERR);
3647995Shx147065 }
3648995Shx147065
3649995Shx147065 (void) memmove(gbuf->wldp_buf, &radio, sizeof (wl_radio_t));
3650995Shx147065 return (call_ioctl(fd, WLAN_SET_PARAM, WL_RADIO, sizeof (wl_radio_t)));
3651995Shx147065 }
3652995Shx147065 /*
3653995Shx147065 * print_gbuf: After each ioctl system call, gbuf will contain result, gbuf
3654995Shx147065 * contents's format varies from each kind of ioctl system call.
3655995Shx147065 */
3656995Shx147065 static void
print_gbuf(config_item_t index)3657995Shx147065 print_gbuf(config_item_t index)
3658995Shx147065 {
3659995Shx147065 int i = 0, j = 0;
3660995Shx147065 uint32_t ess_num;
3661995Shx147065 char **ess_argv;
3662995Shx147065 uint32_t rates_num;
3663995Shx147065 uint32_t subtype;
3664995Shx147065 wl_bss_type_t bsstype;
3665995Shx147065 wl_create_ibss_t createibss;
3666995Shx147065 wl_ps_mode_t *ps_mode;
3667995Shx147065 wl_authmode_t authmode;
3668995Shx147065 wl_encryption_t encryption;
3669995Shx147065 wl_wep_key_id_t wepkeyid;
3670995Shx147065 wl_rssi_t signal;
3671995Shx147065 wl_radio_t radioon;
3672995Shx147065 wl_ess_conf_t **p_ess_conf;
3673995Shx147065 wl_linkstatus_t linkstatus;
3674995Shx147065 char format[256], *ntstr;
3675995Shx147065 uint32_t maxessidlen = 0, nt = 0, cnt = 0;
3676995Shx147065 int len;
3677995Shx147065 uint8_t bssid[6];
3678995Shx147065
3679995Shx147065 PRTDBG(("print_gbuf(%d)\n", index));
3680995Shx147065 assert(gbuf->wldp_length < MAX_BUF_LEN);
3681995Shx147065
3682995Shx147065 switch (index) {
3683995Shx147065 case BSSID:
3684995Shx147065 (void) printf("\tbssid: ");
3685995Shx147065 (void) memset(bssid, 0, sizeof (bssid));
3686995Shx147065 if (memcmp((uint8_t *)gbuf->wldp_buf, bssid, sizeof (bssid))
3687995Shx147065 == 0) {
3688995Shx147065 (void) printf("none\n");
3689995Shx147065 break;
3690995Shx147065 }
3691995Shx147065 (void) memset(bssid, 0xff, sizeof (bssid));
3692995Shx147065 if (memcmp((uint8_t *)gbuf->wldp_buf, bssid, sizeof (bssid))
3693995Shx147065 == 0) {
3694995Shx147065 (void) printf("none\n");
3695995Shx147065 break;
3696995Shx147065 }
3697995Shx147065 for (i = 0; i < 5; i++)
3698995Shx147065 (void) printf("%02x:", ((uint8_t *)gbuf->wldp_buf)[i]);
3699995Shx147065 (void) printf("%02x\n", ((uint8_t *)gbuf->wldp_buf)[i]);
3700995Shx147065 break;
3701995Shx147065 case ESSID:
3702995Shx147065 (void) printf("\tessid: %s\n", ((wl_essid_t *)(gbuf->wldp_buf))
3703995Shx147065 ->wl_essid_essid);
3704995Shx147065 break;
3705995Shx147065 case BSSTYPE:
3706995Shx147065 bsstype = *(wl_bss_type_t *)(gbuf->wldp_buf);
3707995Shx147065 switch (bsstype) {
3708995Shx147065 case WL_BSS_BSS:
3709995Shx147065 (void) printf("\tbsstype: bss(ap, infrastructure)\n");
3710995Shx147065 break;
3711995Shx147065 case WL_BSS_IBSS:
3712995Shx147065 (void) printf("\tbsstype: ibss(ad-hoc)\n");
3713995Shx147065 break;
3714995Shx147065 case WL_BSS_ANY:
3715995Shx147065 (void) printf("\tbsstype: auto\n");
3716995Shx147065 break;
3717995Shx147065 default:
3718995Shx147065 (void) fprintf(stderr,
3719995Shx147065 gettext("%s: "
3720995Shx147065 "invalid bsstype value\n"), gExecName);
3721995Shx147065 }
3722995Shx147065 break;
3723995Shx147065 case CREATEIBSS:
3724995Shx147065 createibss = *(wl_create_ibss_t *)(gbuf->wldp_buf);
3725995Shx147065 switch (createibss) {
3726995Shx147065 case B_TRUE:
3727995Shx147065 (void) printf("\tcreateibss: yes\n");
3728995Shx147065 break;
3729995Shx147065 case B_FALSE:
3730995Shx147065 (void) printf("\tcreateibss: no\n");
3731995Shx147065 break;
3732995Shx147065 default:
3733995Shx147065 (void) fprintf(stderr,
3734995Shx147065 gettext("%s: "
3735995Shx147065 "invalid createibss value\n"), gExecName);
3736995Shx147065 }
3737995Shx147065 break;
3738995Shx147065 case CHANNEL:
3739995Shx147065 subtype = ((wl_fhss_t *)(gbuf->wldp_buf))->wl_fhss_subtype;
3740995Shx147065 switch (subtype) {
3741995Shx147065 case WL_FHSS:
3742995Shx147065 case WL_DSSS:
3743995Shx147065 case WL_IRBASE:
3744995Shx147065 case WL_HRDS:
3745995Shx147065 case WL_ERP:
3746995Shx147065 (void) printf("\tchannel: %d\n", ((wl_fhss_t *)
3747995Shx147065 (gbuf->wldp_buf))->wl_fhss_channel);
3748995Shx147065 break;
3749995Shx147065 case WL_OFDM:
3750995Shx147065 (void) printf("\tchannel: %d\n", ((wl_ofdm_t *)
3751995Shx147065 (gbuf->wldp_buf))
3752995Shx147065 ->wl_ofdm_frequency);
3753995Shx147065 break;
3754995Shx147065 default:
3755995Shx147065 (void) fprintf(stderr, gettext("%s: "
3756995Shx147065 "invalid subtype\n"), gExecName);
3757995Shx147065 break;
3758995Shx147065 }
3759995Shx147065 break;
3760995Shx147065 case RATES:
3761995Shx147065 rates_num = ((wl_rates_t *)(gbuf->wldp_buf))->wl_rates_num;
3762995Shx147065 (void) printf("\trates: ");
3763995Shx147065 for (i = 0; i < rates_num; i++) {
3764995Shx147065 char rate;
3765995Shx147065 rate = ((wl_rates_t *)gbuf->wldp_buf)
3766995Shx147065 ->wl_rates_rates[i];
3767995Shx147065 if (rate == WL_RATE_5_5M)
3768995Shx147065 (void) printf("5.5");
3769995Shx147065 else
3770995Shx147065 (void) printf("%d", (uint8_t)(rate / 2));
3771995Shx147065
3772995Shx147065 if (i == (rates_num - 1))
3773995Shx147065 (void) printf("\n");
3774995Shx147065 else
3775995Shx147065 (void) printf(",");
3776995Shx147065 }
3777995Shx147065 break;
3778995Shx147065 case POWERMODE:
3779995Shx147065 ps_mode = (wl_ps_mode_t *)(gbuf->wldp_buf);
3780995Shx147065 switch (ps_mode->wl_ps_mode) {
3781995Shx147065 case WL_PM_AM:
3782995Shx147065 (void) printf("\tpowermode: off\n");
3783995Shx147065 break;
3784995Shx147065 case WL_PM_MPS:
3785995Shx147065 (void) printf("\tpowermode: mps\n");
3786995Shx147065 break;
3787995Shx147065 case WL_PM_FAST:
3788995Shx147065 (void) printf("\tpowermode: fast\n");
3789995Shx147065 break;
3790995Shx147065 default:
3791995Shx147065 (void) fprintf(stderr,
3792995Shx147065 gettext("%s: "
3793995Shx147065 "invalid powermode value\n"), gExecName);
3794995Shx147065 break;
3795995Shx147065 }
3796995Shx147065 break;
3797995Shx147065 case AUTHMODE:
3798995Shx147065 authmode = *(wl_authmode_t *)(gbuf->wldp_buf);
3799995Shx147065 switch (authmode) {
3800995Shx147065 case WL_OPENSYSTEM:
3801995Shx147065 (void) printf("\tauthmode: opensystem\n");
3802995Shx147065 break;
3803995Shx147065 case WL_SHAREDKEY:
3804995Shx147065 (void) printf("\tauthmode: shared_key\n");
3805995Shx147065 break;
3806995Shx147065 default:
3807995Shx147065 (void) fprintf(stderr,
3808995Shx147065 gettext("%s: "
3809995Shx147065 "invalid authmode value\n"), gExecName);
3810995Shx147065 break;
3811995Shx147065 }
3812995Shx147065 break;
3813995Shx147065 case ENCRYPTION:
3814995Shx147065 encryption = *(wl_encryption_t *)(gbuf->wldp_buf);
3815995Shx147065 switch (encryption) {
3816995Shx147065 case WL_NOENCRYPTION:
3817995Shx147065 (void) printf("\tencryption: none\n");
3818995Shx147065 break;
3819995Shx147065 case WL_ENC_WEP:
3820995Shx147065 (void) printf("\tencryption: wep\n");
3821995Shx147065 break;
3822995Shx147065 default:
3823995Shx147065 (void) fprintf(stderr,
3824995Shx147065 gettext("%s: "
3825995Shx147065 "invalid encryption value\n"), gExecName);
3826995Shx147065 break;
3827995Shx147065 }
3828995Shx147065 break;
3829995Shx147065 case WEPKEYID:
3830995Shx147065 wepkeyid = *(wl_wep_key_id_t *)(gbuf->wldp_buf);
3831995Shx147065 (void) printf("\twepkeyindex: %d\n", wepkeyid + 1);
3832995Shx147065 break;
3833995Shx147065 case SIGNAL:
3834995Shx147065 signal = *(wl_rssi_t *)(gbuf->wldp_buf);
3835995Shx147065 (void) printf("\tsignal: %d\n", signal);
3836995Shx147065 break;
3837995Shx147065 case RADIOON:
3838995Shx147065 radioon = *(wl_radio_t *)(gbuf->wldp_buf);
3839995Shx147065 switch (radioon) {
3840995Shx147065 case B_TRUE:
3841995Shx147065 (void) printf("\tradio: on\n");
3842995Shx147065 break;
3843995Shx147065 case B_FALSE:
3844995Shx147065 (void) printf("\tradio: off\n");
3845995Shx147065 break;
3846995Shx147065 default: /* Mark */
3847995Shx147065 (void) fprintf(stderr,
3848995Shx147065 gettext("%s: "
3849995Shx147065 "invalid radioon value\n"), gExecName);
3850995Shx147065 }
3851995Shx147065 break;
3852995Shx147065 case LINKSTATUS:
3853995Shx147065 linkstatus = *(wl_linkstatus_t *)(gbuf->wldp_buf);
3854995Shx147065 switch (linkstatus) {
3855995Shx147065 case WL_CONNECTED:
3856995Shx147065 (void) printf("\tlinkstatus: connected\n");
3857995Shx147065 break;
3858995Shx147065 case WL_NOTCONNECTED:
3859995Shx147065 (void) printf("\tlinkstatus: not connected\n");
3860995Shx147065 break;
3861995Shx147065 default: /* Mark */
3862995Shx147065 (void) fprintf(stderr,
3863995Shx147065 gettext("%s: "
3864995Shx147065 "invalid linkstatus value\n"), gExecName);
3865995Shx147065 }
3866995Shx147065 break;
3867995Shx147065 case WLANLIST:
3868995Shx147065 ess_num = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num;
3869995Shx147065 ess_argv = safe_calloc(sizeof (char *), ess_num);
3870995Shx147065 p_ess_conf = safe_calloc(sizeof (wl_ess_conf_t *), ess_num);
3871995Shx147065 for (i = 0; i < ess_num; i++) {
3872995Shx147065 p_ess_conf[i] = ((wl_ess_list_t *)gbuf->wldp_buf)
3873995Shx147065 ->wl_ess_list_ess + i;
3874995Shx147065 maxessidlen = (maxessidlen >
3875995Shx147065 strlen(p_ess_conf[i]
3876995Shx147065 ->wl_ess_conf_essid.wl_essid_essid) ?
3877995Shx147065 maxessidlen :
3878995Shx147065 strlen(p_ess_conf[i]
3879995Shx147065 ->wl_ess_conf_essid.wl_essid_essid));
3880995Shx147065 }
3881995Shx147065 /*
3882995Shx147065 * construct the output format.
3883995Shx147065 */
3884995Shx147065 if ((nt = (maxessidlen / 8 + 1)) > 4)
3885995Shx147065 nt = 4;
3886995Shx147065 len = snprintf(format, sizeof (format), gettext("essid"));
3887995Shx147065 ntstr = construct_format(nt);
3888995Shx147065 assert(ntstr != NULL);
3889995Shx147065 len += snprintf(format + len, sizeof (format) - len, "%s",
3890995Shx147065 ntstr);
3891995Shx147065 len += snprintf(format + len, sizeof (format) - len,
3892995Shx147065 gettext("bssid\t\t type\t\tencryption\tsignallevel\n"));
3893995Shx147065
3894995Shx147065 if ((len <= 0) || (len > sizeof (format) - 1)) {
3895995Shx147065 (void) printf("essid\t\t\t\tbssid\t\t type\t\t"
3896995Shx147065 "encryption\tsignallevel\n");
3897995Shx147065 } else {
3898995Shx147065 (void) printf("%s", format);
3899995Shx147065 }
3900995Shx147065
3901995Shx147065 for (i = 0; i < ess_num; i++) {
3902995Shx147065 ess_argv[i] = safe_malloc(MAX_SCANBUF_LEN);
3903995Shx147065 safe_snprintf(ess_argv[i], MAX_SCANBUF_LEN,
3904995Shx147065 "%s%c%02x:%02x:%02x:%02x:%02x:%02x%c%s",
3905995Shx147065 p_ess_conf[i]->wl_ess_conf_essid.wl_essid_essid,
3906995Shx147065 ',',
3907995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[0]),
3908995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[1]),
3909995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[2]),
3910995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[3]),
3911995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[4]),
3912995Shx147065 (uint8_t)(p_ess_conf[i]->wl_ess_conf_bssid[5]), ',',
3913995Shx147065 (p_ess_conf[i]->wl_ess_conf_wepenabled ==
3914995Shx147065 B_TRUE ? "wep":"none"));
3915995Shx147065 len = strlen(p_ess_conf[i]->wl_ess_conf_essid.
3916995Shx147065 wl_essid_essid);
3917995Shx147065 cnt = nt - (min(len /8 + 1, 4) - 1);
3918995Shx147065 ntstr = construct_format(cnt);
3919995Shx147065 assert(ntstr != NULL);
3920995Shx147065 (void) printf("%s%s", p_ess_conf[i]->wl_ess_conf_essid.
3921995Shx147065 wl_essid_essid, ntstr);
3922995Shx147065 free(ntstr);
3923995Shx147065 for (j = 0; j < 5; j++) {
3924995Shx147065 (void) printf("%02x:", (uint8_t)(p_ess_conf[i]
3925995Shx147065 ->wl_ess_conf_bssid[j]));
3926995Shx147065 }
3927995Shx147065 (void) printf("%02x ", (uint8_t)(p_ess_conf[i]
3928995Shx147065 ->wl_ess_conf_bssid[j]));
3929995Shx147065
3930995Shx147065 if (p_ess_conf[i]->wl_ess_conf_bsstype ==
3931995Shx147065 WL_BSS_BSS)
3932995Shx147065 (void) printf("access point");
3933995Shx147065 else
3934995Shx147065 (void) printf("ad-hoc");
3935995Shx147065 if (p_ess_conf[i]->wl_ess_conf_wepenabled ==
3936995Shx147065 WL_ENC_WEP)
3937995Shx147065 (void) printf("\twep\t");
3938995Shx147065 else
3939995Shx147065 (void) printf("\tnone\t");
3940995Shx147065 (void) printf("\t%d\n", p_ess_conf[i]->wl_ess_conf_sl);
3941995Shx147065 }
3942995Shx147065 add_to_history(gp_config_file, ess_num, ess_argv);
3943995Shx147065 free(p_ess_conf);
3944995Shx147065 for (i = 0; i < ess_num; i++) {
3945995Shx147065 free(ess_argv[i]);
3946995Shx147065 }
3947995Shx147065 free(ess_argv);
3948995Shx147065 break;
3949995Shx147065 default:
3950995Shx147065 (void) fprintf(stderr, gettext("%s: "
3951995Shx147065 "invalid parameter type\n"), gExecName);
3952995Shx147065 break;
3953995Shx147065 }
3954995Shx147065 }
3955995Shx147065 /*
3956995Shx147065 * do_get_xxx: will send ioctl to driver, then the driver will fill gbuf
3957995Shx147065 * with related value. gbuf has a format of wldp_t structure.
3958995Shx147065 */
3959995Shx147065 static boolean_t
do_get_bssid(int fd)3960995Shx147065 do_get_bssid(int fd)
3961995Shx147065 {
3962995Shx147065 PRTDBG(("do_get_bssid(%d)\n", fd));
3963995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_BSSID, 0));
3964995Shx147065 }
3965995Shx147065
3966995Shx147065 static boolean_t
do_get_essid(int fd)3967995Shx147065 do_get_essid(int fd)
3968995Shx147065 {
3969995Shx147065 PRTDBG(("do_get_essid(%d)\n", fd));
3970995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_ESSID, 0));
3971995Shx147065 }
3972995Shx147065
3973995Shx147065 static boolean_t
do_get_bsstype(int fd)3974995Shx147065 do_get_bsstype(int fd)
3975995Shx147065 {
3976995Shx147065 PRTDBG(("do_get_bsstype(%d)\n", fd));
3977995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_BSS_TYPE, 0));
3978995Shx147065 }
3979995Shx147065
3980995Shx147065 static boolean_t
do_get_createibss(int fd)3981995Shx147065 do_get_createibss(int fd)
3982995Shx147065 {
3983995Shx147065 PRTDBG(("do_get_createibss(%d)\n", fd));
3984995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_CREATE_IBSS, 0));
3985995Shx147065 }
3986995Shx147065
3987995Shx147065 static boolean_t
do_get_channel(int fd)3988995Shx147065 do_get_channel(int fd)
3989995Shx147065 {
3990995Shx147065 PRTDBG(("do_get_channel(%d)\n", fd));
3991995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_PHY_CONFIG, 0));
3992995Shx147065 }
3993995Shx147065
3994995Shx147065 static boolean_t
do_get_wlanlist(int fd)3995995Shx147065 do_get_wlanlist(int fd)
3996995Shx147065 {
3997995Shx147065 PRTDBG(("do_get_wlanlist(%d)\n", fd));
3998995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_ESS_LIST, 0));
3999995Shx147065 }
4000995Shx147065
4001995Shx147065 static boolean_t
do_get_linkstatus(int fd)4002995Shx147065 do_get_linkstatus(int fd)
4003995Shx147065 {
4004995Shx147065 PRTDBG(("do_get_linkstauts(%d)\n", fd));
4005995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_LINKSTATUS, 0));
4006995Shx147065 }
4007995Shx147065
4008995Shx147065 static boolean_t
do_get_rates(int fd)4009995Shx147065 do_get_rates(int fd)
4010995Shx147065 {
4011995Shx147065 PRTDBG(("do_get_rates(%d)\n", fd));
4012995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_DESIRED_RATES, 0));
4013995Shx147065 }
4014995Shx147065
4015995Shx147065 static boolean_t
do_get_powermode(int fd)4016995Shx147065 do_get_powermode(int fd)
4017995Shx147065 {
4018995Shx147065 PRTDBG(("do_get_powermode(%d)\n", fd));
4019995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_POWER_MODE, 0));
4020995Shx147065 }
4021995Shx147065
4022995Shx147065 static boolean_t
do_get_authmode(int fd)4023995Shx147065 do_get_authmode(int fd)
4024995Shx147065 {
4025995Shx147065 PRTDBG(("do_get_authmode(%d)\n", fd));
4026995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_AUTH_MODE, 0));
4027995Shx147065 }
4028995Shx147065
4029995Shx147065 static boolean_t
do_get_encryption(int fd)4030995Shx147065 do_get_encryption(int fd)
4031995Shx147065 {
4032995Shx147065 PRTDBG(("do_get_encryption(%d)\n", fd));
4033995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_ENCRYPTION, 0));
4034995Shx147065 }
4035995Shx147065
4036995Shx147065 static boolean_t
do_get_wepkeyid(int fd)4037995Shx147065 do_get_wepkeyid(int fd)
4038995Shx147065 {
4039995Shx147065 PRTDBG(("do_get_wepkeyid(%d)\n", fd));
4040995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_WEP_KEY_ID, 0));
4041995Shx147065 }
4042995Shx147065 static boolean_t
do_get_signal(int fd)4043995Shx147065 do_get_signal(int fd)
4044995Shx147065 {
4045995Shx147065 PRTDBG(("do_get_signal(%d)\n", fd));
4046995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_RSSI, 0));
4047995Shx147065 }
4048995Shx147065
4049995Shx147065 static boolean_t
do_get_radioon(int fd)4050995Shx147065 do_get_radioon(int fd)
4051995Shx147065 {
4052995Shx147065 PRTDBG(("do_get_radioon(%d)\n", fd));
4053995Shx147065 return (call_ioctl(fd, WLAN_GET_PARAM, WL_RADIO, 0));
4054995Shx147065 }
4055995Shx147065
4056995Shx147065 /*
4057995Shx147065 * param has two kinds of forms:
4058995Shx147065 * 'wepkeyn=*****' (when equalflag == B_TRUE),
4059995Shx147065 * 'wepkeyn' (when equalflag == B_FALSE)
4060995Shx147065 */
4061995Shx147065 static boolean_t
param_is_wepkey(char * param,boolean_t equalflag)4062995Shx147065 param_is_wepkey(char *param, boolean_t equalflag)
4063995Shx147065 {
4064995Shx147065 if ((equalflag == B_FALSE) &&
4065995Shx147065 (strcmp(param, "wepkey1") == 0) ||
4066995Shx147065 (strcmp(param, "wepkey2") == 0) ||
4067995Shx147065 (strcmp(param, "wepkey3") == 0) ||
4068995Shx147065 (strcmp(param, "wepkey4") == 0))
4069995Shx147065 return (B_TRUE);
4070995Shx147065 else if ((equalflag == B_TRUE) &&
4071995Shx147065 (strncmp(param, "wepkey1=", strlen("wepkey1="))) == 0 ||
4072995Shx147065 (strncmp(param, "wepkey2=", strlen("wepkey2="))) == 0 ||
4073995Shx147065 (strncmp(param, "wepkey3=", strlen("wepkey3="))) == 0 ||
4074995Shx147065 (strncmp(param, "wepkey4=", strlen("wepkey4="))) == 0)
4075995Shx147065 return (B_TRUE);
4076995Shx147065 else
4077995Shx147065 return (B_FALSE);
4078995Shx147065 }
4079995Shx147065
4080995Shx147065 /*
4081995Shx147065 * update/add items in the profile
4082995Shx147065 */
4083995Shx147065 static boolean_t
items_in_profile(aelist_t * cplist,aelist_t * wplist,int argc,char ** argv)4084995Shx147065 items_in_profile(aelist_t *cplist, aelist_t *wplist, int argc, char **argv)
4085995Shx147065 {
4086995Shx147065 int i = 0, j = 0;
4087995Shx147065 char *param;
4088995Shx147065 char *pequal;
4089995Shx147065 const char *wepkey;
4090995Shx147065
4091995Shx147065 for (i = 0; i < argc; i++) {
4092995Shx147065 if (param_is_wepkey(argv[i], B_TRUE) == B_TRUE) {
4093995Shx147065 wepkey = get_value(argv[i]);
4094995Shx147065 if (value_is_valid(WEPKEY, wepkey) == B_FALSE) {
4095995Shx147065 (void) fprintf(stderr, gettext("%s: "
4096995Shx147065 "invalid value '%s' for parameter "
4097995Shx147065 "'wepkey'\n"), gExecName, wepkey);
4098995Shx147065 return (B_FALSE);
4099995Shx147065 }
4100995Shx147065 update_aelist(wplist, argv[i]);
4101995Shx147065 continue;
4102995Shx147065 }
4103995Shx147065 param = safe_strdup(argv[i]);
4104995Shx147065 pequal = strchr(param, '=');
4105995Shx147065 if (pequal == NULL) {
4106995Shx147065 (void) fprintf(stderr, gettext("%s: "
4107995Shx147065 "invalid argument '%s', use "
4108995Shx147065 "parameter=value'\n"),
4109995Shx147065 gExecName, argv[i]);
4110995Shx147065 free(param);
4111995Shx147065 return (B_FALSE);
4112995Shx147065 }
4113995Shx147065
4114995Shx147065 *pequal++ = '\0';
4115995Shx147065 for (j = 0; j < N_GS_FUNC; j++) {
4116995Shx147065 if (strcmp(param, do_gs_func[j].cmd) == 0) {
4117995Shx147065 break;
4118995Shx147065 }
4119995Shx147065 }
4120995Shx147065 if (j == N_GS_FUNC) {
4121995Shx147065 (void) fprintf(stderr, gettext("%s: "
4122995Shx147065 "unrecognized parameter '%s'\n"),
4123995Shx147065 gExecName, param);
4124995Shx147065 free(param);
4125995Shx147065 return (B_FALSE);
4126995Shx147065 }
4127995Shx147065 if (value_is_valid(do_gs_func[j].index, pequal) ==
4128995Shx147065 B_FALSE) {
4129995Shx147065 (void) fprintf(stderr, gettext("%s: "
4130995Shx147065 "invalid value '%s' for parameter '%s'\n"),
4131995Shx147065 gExecName, pequal, param);
4132995Shx147065 return (B_FALSE);
4133995Shx147065 }
4134995Shx147065 free(param);
4135995Shx147065 update_aelist(cplist, argv[i]);
4136995Shx147065 }
4137995Shx147065 return (B_TRUE);
4138995Shx147065 }
4139995Shx147065
4140995Shx147065 /*
4141995Shx147065 * do_createprofile: Called when create a profile off-line.
4142995Shx147065 */
4143995Shx147065 /*ARGSUSED*/
4144995Shx147065 static boolean_t
do_createprofile(int fd,int argc,char ** argv)4145995Shx147065 do_createprofile(int fd, int argc, char **argv)
4146995Shx147065 {
4147995Shx147065 int i = 0;
4148995Shx147065 char *pbuf = NULL;
4149995Shx147065 char *pfbuf = NULL;
4150995Shx147065 const char *profilename;
4151995Shx147065 aelist_t *plist_config = NULL, *plist_wepkey = NULL;
4152995Shx147065
4153995Shx147065 PRTDBG(("do_createprofile(%d, 0x%x)\n", argc, argv));
4154995Shx147065 if (argc <= 0) {
4155995Shx147065 do_print_usage();
4156995Shx147065 exit(WIFI_IMPROPER_USE);
4157995Shx147065 }
4158995Shx147065 /*
4159995Shx147065 * When creating a profile, if the profile name is not specified,
4160995Shx147065 * the essid is selected as the profile name. the paramters are
4161995Shx147065 * saved into the section.
4162995Shx147065 */
4163995Shx147065 if (strchr(argv[0], '=') == NULL) {
4164995Shx147065 pfbuf = safe_strdup(argv[0]);
4165995Shx147065 argc--;
4166995Shx147065 argv++;
4167995Shx147065 }
4168995Shx147065 for (i = 0; i < argc; i++) {
4169995Shx147065 if (strncmp(argv[i], "essid=", strlen("essid=")) == 0) {
4170995Shx147065 break;
4171995Shx147065 }
4172995Shx147065 }
4173995Shx147065 if (i == argc) {
4174995Shx147065 (void) fprintf(stderr,
4175995Shx147065 gettext("%s: "
4176995Shx147065 "essid required when creating profile\n"),
4177995Shx147065 gExecName);
4178995Shx147065 goto exit0;
4179995Shx147065 }
4180995Shx147065 profilename = (pfbuf ? pfbuf : get_value(argv[i]));
4181995Shx147065 if (strlen(profilename) == 0) {
4182995Shx147065 (void) fprintf(stderr,
4183995Shx147065 gettext("%s: "
4184995Shx147065 "non-empty essid required\n"),
4185995Shx147065 gExecName);
4186995Shx147065 goto exit0;
4187995Shx147065 }
4188995Shx147065 /*
4189995Shx147065 * 'all', '{preference}', '{history}', '{active_profile}'
4190995Shx147065 * and any string with '[' as start and ']' as end should
4191995Shx147065 * not be a profile name
4192995Shx147065 */
4193995Shx147065 if ((strcasecmp(profilename, "all") == 0) ||
4194995Shx147065 (strcmp(profilename, WIFI_HISTORY) == 0) ||
4195995Shx147065 (strcmp(profilename, WIFI_PREFER) == 0) ||
4196995Shx147065 (strcmp(profilename, WIFI_ACTIVEP) == 0) ||
4197995Shx147065 ((profilename[0] == '[') &&
4198995Shx147065 (profilename[strlen(profilename) - 1] == ']'))) {
4199995Shx147065 (void) fprintf(stderr, gettext("%s: "
4200995Shx147065 "'%s' is an invalid profile name\n"),
4201995Shx147065 gExecName, profilename);
4202995Shx147065 goto exit0;
4203995Shx147065 }
4204995Shx147065 pbuf = append_pa(profilename);
4205995Shx147065
4206995Shx147065 PRTDBG(("do_createprofile: profile_name = %s\n", pbuf));
4207995Shx147065 if ((find_section(gp_config_file, pbuf) != NULL) ||
4208995Shx147065 find_section(gp_wepkey_file, pbuf) != NULL) {
4209995Shx147065 (void) fprintf(stderr,
4210995Shx147065 gettext("%s: "
4211995Shx147065 "profile '%s' already exists\n"),
4212995Shx147065 gExecName, profilename);
4213995Shx147065 goto exit1;
4214995Shx147065 }
4215995Shx147065 /*
4216995Shx147065 * Save each parameters in the profile.
4217995Shx147065 */
4218995Shx147065 plist_config = new_ael(PROFILE);
4219995Shx147065 new_section(gp_config_file, plist_config, pbuf);
4220995Shx147065 plist_wepkey = new_ael(PROFILE);
4221995Shx147065 new_section(gp_wepkey_file, plist_wepkey, pbuf);
4222995Shx147065 free(pfbuf);
4223995Shx147065 free(pbuf);
4224995Shx147065 return (items_in_profile(plist_config, plist_wepkey,
4225995Shx147065 argc, argv));
4226995Shx147065 exit1:
4227995Shx147065 free(pbuf);
4228995Shx147065 exit0:
4229995Shx147065 free(pfbuf);
4230995Shx147065 return (B_FALSE);
4231995Shx147065 }
4232995Shx147065
4233995Shx147065 /*ARGSUSED*/
4234995Shx147065 static boolean_t
do_setprofparam(int fd,int argc,char ** argv)4235995Shx147065 do_setprofparam(int fd, int argc, char **argv)
4236995Shx147065 {
4237995Shx147065 char *pbuf = NULL;
4238995Shx147065 section_t *psection_config = NULL, *psection_wep = NULL;
4239995Shx147065 aelist_t *plist_config = NULL, *plist_wepkey = NULL;
4240995Shx147065
4241995Shx147065 PRTDBG(("do_setprofparam(%d, 0x%x)\n", argc, argv));
4242995Shx147065 if (argc < 1) {
4243995Shx147065 do_print_usage();
4244995Shx147065 exit(WIFI_IMPROPER_USE);
4245995Shx147065 }
4246995Shx147065 pbuf = append_pa(argv[0]);
4247995Shx147065
4248995Shx147065 psection_config = find_section(gp_config_file, pbuf);
4249995Shx147065 psection_wep = find_section(gp_wepkey_file, pbuf);
4250995Shx147065 if ((psection_config == NULL) || (psection_wep == NULL)) {
4251995Shx147065 (void) fprintf(stderr, gettext("%s: "
4252995Shx147065 "profile '%s' doesn't exist\n"),
4253995Shx147065 gExecName, argv[0]);
4254995Shx147065 free(pbuf);
4255995Shx147065 return (B_FALSE);
4256995Shx147065 }
4257995Shx147065 free(pbuf);
4258995Shx147065 /*
4259995Shx147065 * modify each parameters in the profile.
4260995Shx147065 */
4261995Shx147065 plist_config = psection_config->list;
4262995Shx147065 plist_wepkey = psection_wep->list;
4263995Shx147065 argc--;
4264995Shx147065 argv++;
4265995Shx147065 return (items_in_profile(plist_config, plist_wepkey,
4266995Shx147065 argc, argv));
4267995Shx147065 }
4268995Shx147065
4269995Shx147065 /*ARGSUSED*/
4270995Shx147065 static boolean_t
do_getprofparam(int fd,int argc,char ** argv)4271995Shx147065 do_getprofparam(int fd, int argc, char **argv)
4272995Shx147065 {
4273995Shx147065 int i = 0, j = 0;
4274995Shx147065 int flag;
4275995Shx147065 boolean_t ret = B_TRUE;
4276995Shx147065 section_t *p_section = NULL;
4277995Shx147065 aelist_t *plist = NULL;
4278995Shx147065 ae_t *pae = NULL;
4279995Shx147065 char *pbuf = NULL;
4280995Shx147065
4281995Shx147065 PRTDBG(("do_getprofparam(%d, 0x%x)\n", argc, argv));
4282995Shx147065 if (argc < 1) {
4283995Shx147065 do_print_usage();
4284995Shx147065 exit(WIFI_IMPROPER_USE);
4285995Shx147065 }
4286995Shx147065 pbuf = append_pa(argv[0]);
4287995Shx147065 p_section = find_section(gp_config_file, pbuf);
4288995Shx147065 if (p_section == NULL) {
4289995Shx147065 (void) fprintf(stderr, gettext("%s: "
4290995Shx147065 "profile '%s' doesn't exist\n"),
4291995Shx147065 gExecName, argv[0]);
4292995Shx147065 ret = B_FALSE;
4293995Shx147065 goto exit0;
4294995Shx147065 }
4295995Shx147065 argc--;
4296995Shx147065 argv++;
4297995Shx147065
4298995Shx147065 plist = p_section->list;
4299995Shx147065 assert(plist != NULL);
4300995Shx147065 /*
4301995Shx147065 * If no specific parameter typed, we print out all parameters
4302995Shx147065 */
4303995Shx147065 if (argc == 0) {
4304995Shx147065 pae = plist->ael_head;
4305995Shx147065 while (pae != NULL) {
4306995Shx147065 if (pae->ae_arg != NULL) {
4307995Shx147065 (void) printf("\t%s\n", pae->ae_arg);
4308995Shx147065 }
4309995Shx147065 pae = pae->ae_next;
4310995Shx147065 }
4311995Shx147065 print_wepkey_info(p_section->section_id, NULL);
4312995Shx147065 ret = B_TRUE;
4313995Shx147065 goto exit0;
4314995Shx147065 }
4315995Shx147065
4316995Shx147065 /*
4317995Shx147065 * Match function with do_gs_func[] table, and print its result
4318995Shx147065 */
4319995Shx147065 for (i = 0; i < argc; i++) {
4320995Shx147065 flag = 0;
4321995Shx147065 for (j = 0; j < N_GS_FUNC; j++) {
4322995Shx147065 if (strcmp(argv[i], do_gs_func[j].cmd) == 0) {
4323995Shx147065 break;
4324995Shx147065 }
4325995Shx147065 if (param_is_wepkey(argv[i], B_FALSE) == B_TRUE) {
4326995Shx147065 j = WEPKEY;
4327995Shx147065 print_wepkey_info(p_section->section_id,
4328995Shx147065 argv[i]);
4329995Shx147065 flag++;
4330995Shx147065 break;
4331995Shx147065 }
4332995Shx147065 }
4333995Shx147065 if (j == N_GS_FUNC) {
4334995Shx147065 (void) fprintf(stderr,
4335995Shx147065 gettext("wificonifg: unrecognized parameter: "
4336995Shx147065 "%s\n"), argv[i]);
4337995Shx147065 ret = B_FALSE;
4338995Shx147065 goto exit0;
4339995Shx147065 }
4340995Shx147065
4341995Shx147065 pae = plist->ael_head;
4342995Shx147065 while ((pae != NULL) && (!flag)) {
4343995Shx147065 if ((pae->ae_arg != NULL) &&
4344995Shx147065 (strncmp(pae->ae_arg, argv[i],
4345995Shx147065 strlen(argv[i])) == 0)) {
4346995Shx147065 (void) printf("\t%s\n", pae->ae_arg);
4347995Shx147065 flag++;
4348995Shx147065 }
4349995Shx147065 pae = pae->ae_next;
4350995Shx147065 }
4351995Shx147065 if (!flag) {
4352995Shx147065 (void) fprintf(stderr, gettext("%s: "
4353995Shx147065 "parameter '%s' has not been set in profile %s\n"),
4354995Shx147065 gExecName, argv[i], pbuf);
4355995Shx147065 ret = B_FALSE;
4356995Shx147065 goto exit0;
4357995Shx147065 }
4358995Shx147065 }
4359995Shx147065 exit0:
4360995Shx147065 free(pbuf);
4361995Shx147065 return (ret);
4362995Shx147065 }
4363995Shx147065
4364995Shx147065 /*
4365995Shx147065 * Verify whether the value in the parameter=value pair is valid or not.
4366995Shx147065 * For the channel, since we donot know what kind of wifi card(a,b,or g)
4367995Shx147065 * is in the system, so we just leave to verify the validity of the value
4368995Shx147065 * when the value is set to the card.
4369995Shx147065 * The same goes for the rates.
4370995Shx147065 */
4371995Shx147065 static boolean_t
value_is_valid(config_item_t item,const char * value)4372995Shx147065 value_is_valid(config_item_t item, const char *value)
4373995Shx147065 {
4374995Shx147065 uint32_t num = 0;
4375995Shx147065 uint8_t *rates;
4376995Shx147065 boolean_t ret;
4377995Shx147065
4378995Shx147065 assert(value != NULL);
4379995Shx147065 switch (item) {
4380995Shx147065 case ESSID:
4381995Shx147065 if (strlen(value) > 32)
4382995Shx147065 ret = B_FALSE;
4383995Shx147065 else
4384995Shx147065 ret = B_TRUE;
4385995Shx147065 break;
4386995Shx147065 case BSSTYPE:
4387995Shx147065 if ((strcasecmp(value, "bss") == 0) ||
4388995Shx147065 (strcasecmp(value, "ap") == 0) ||
4389995Shx147065 (strcasecmp(value, "infrastructure") == 0) ||
4390995Shx147065 (strcasecmp(value, "ibss") == 0) ||
4391995Shx147065 (strcasecmp(value, "ad-hoc") == 0) ||
4392995Shx147065 (strcasecmp(value, "auto") == 0))
4393995Shx147065 ret = B_TRUE;
4394995Shx147065 else
4395995Shx147065 ret = B_FALSE;
4396995Shx147065 break;
4397995Shx147065 case CREATEIBSS:
4398995Shx147065 if ((strcasecmp(value, "yes") == 0) ||
4399995Shx147065 (strcasecmp(value, "no") == 0))
4400995Shx147065 ret = B_TRUE;
4401995Shx147065 else
4402995Shx147065 ret = B_FALSE;
4403995Shx147065 break;
4404995Shx147065 case AUTHMODE:
4405995Shx147065 if ((strcasecmp(value, "opensystem") == 0) ||
4406995Shx147065 (strcasecmp(value, "shared_key") == 0))
4407995Shx147065 ret = B_TRUE;
4408995Shx147065 else
4409995Shx147065 ret = B_FALSE;
4410995Shx147065 break;
4411995Shx147065 case POWERMODE:
4412995Shx147065 if ((strcasecmp(value, "off") == 0) ||
4413995Shx147065 (strcasecmp(value, "mps") == 0) ||
4414995Shx147065 (strcasecmp(value, "fast") == 0))
4415995Shx147065 ret = B_TRUE;
4416995Shx147065 else
4417995Shx147065 ret = B_FALSE;
4418995Shx147065 break;
4419995Shx147065 case ENCRYPTION:
4420995Shx147065 if ((strcasecmp(value, "wep") == 0) ||
4421995Shx147065 (strcasecmp(value, "none") == 0))
4422995Shx147065 ret = B_TRUE;
4423995Shx147065 else
4424995Shx147065 ret = B_FALSE;
4425995Shx147065 break;
4426995Shx147065 case RADIOON:
4427995Shx147065 if ((strcasecmp(value, "on") == 0) ||
4428995Shx147065 (strcasecmp(value, "off") == 0))
4429995Shx147065 ret = B_TRUE;
4430995Shx147065 else
4431995Shx147065 ret = B_FALSE;
4432995Shx147065 break;
4433995Shx147065 case WEPKEYID:
4434995Shx147065 ret = is_wepkeyindex_valid(value);
4435995Shx147065 break;
4436995Shx147065 case WEPKEY:
4437995Shx147065 ret = is_wepkey_valid(value, strlen(value));
4438995Shx147065 break;
4439995Shx147065 case CHANNEL:
4440995Shx147065 ret = is_channel_valid(value);
4441995Shx147065 break;
4442995Shx147065 case RATES:
4443995Shx147065 rates = get_rates(value, &num);
4444995Shx147065 if (rates == NULL) {
4445995Shx147065 ret = B_FALSE;
4446995Shx147065 } else {
4447995Shx147065 free(rates);
4448995Shx147065 ret = B_TRUE;
4449995Shx147065 }
4450995Shx147065 break;
4451995Shx147065 default:
4452995Shx147065 ret = B_FALSE;
4453995Shx147065 break;
4454995Shx147065 }
4455995Shx147065
4456995Shx147065 return (ret);
4457995Shx147065 }
4458995Shx147065
4459995Shx147065 /*
4460995Shx147065 * do_set: Called when set a parameter, the format should be
4461995Shx147065 * parameter=value.
4462995Shx147065 */
4463995Shx147065 static boolean_t
do_set(int fd,int argc,char ** argv)4464995Shx147065 do_set(int fd, int argc, char **argv)
4465995Shx147065 {
4466995Shx147065 int i = 0, j = 0;
4467995Shx147065 char *param;
4468995Shx147065 char *pequal;
4469995Shx147065 char *value;
4470995Shx147065 boolean_t ret;
4471995Shx147065
4472995Shx147065 PRTDBG(("do_set(%d, 0x%x)\n", argc, argv));
4473995Shx147065 assert(fd > 0);
4474995Shx147065 if (argc <= 0) {
4475995Shx147065 (void) do_print_support_params(fd);
4476995Shx147065 ret = B_FALSE;
4477995Shx147065 goto exit0;
4478995Shx147065 }
4479995Shx147065 /*
4480995Shx147065 * Set each parameters, if one failed, others behind it will
4481995Shx147065 * not be set
4482995Shx147065 */
4483995Shx147065 for (i = 0; i < argc; i++) {
4484995Shx147065 /*
4485995Shx147065 * Separate param and its value, if the user types "param=",
4486995Shx147065 * then value will be set to "";if the user types "param",
4487995Shx147065 * it is an error.
4488995Shx147065 */
4489995Shx147065 param = safe_strdup(argv[i]);
4490995Shx147065 pequal = strchr(param, '=');
4491995Shx147065 value = NULL;
4492995Shx147065 if (pequal != NULL) {
4493995Shx147065 *pequal = '\0';
4494995Shx147065 value = pequal + 1;
4495995Shx147065 } else {
4496995Shx147065 (void) fprintf(stderr,
4497995Shx147065 gettext("%s: invalid setparam argument "
4498995Shx147065 "'%s', use 'parameter=value'\n"),
4499995Shx147065 gExecName, argv[i]);
4500995Shx147065 free(param);
4501995Shx147065 ret = B_FALSE;
4502995Shx147065 goto exit0;
4503995Shx147065 }
4504995Shx147065 PRTDBG(("do_set: param = \"%s\", value = \"%s\"\n",
4505995Shx147065 param, value));
4506995Shx147065 for (j = 0; j < N_GS_FUNC; j++) {
4507995Shx147065 /*
4508995Shx147065 * Match each parameters with do_gs_func table,
4509995Shx147065 */
4510995Shx147065 if (strcmp(param, do_gs_func[j].cmd) == 0)
4511995Shx147065 break;
4512995Shx147065 if (param_is_wepkey(param, B_FALSE) == B_TRUE) {
4513995Shx147065 value = argv[i];
4514995Shx147065 j = WEPKEY;
4515995Shx147065 break;
4516995Shx147065 }
4517995Shx147065 }
4518995Shx147065 if (j == N_GS_FUNC) {
4519995Shx147065 (void) fprintf(stderr,
4520995Shx147065 gettext("%s: unrecognized parameter: "
4521995Shx147065 "%s\n"), gExecName, param);
4522995Shx147065 free(param);
4523995Shx147065 ret = B_FALSE;
4524995Shx147065 goto exit0;
4525995Shx147065 }
4526995Shx147065
4527995Shx147065 if (do_gs_func[j].p_do_set_func == NULL) {
4528995Shx147065 (void) fprintf(stderr,
4529995Shx147065 gettext("%s: parameter '%s' is read-only\n"),
4530995Shx147065 gExecName, do_gs_func[j].cmd);
4531995Shx147065 free(param);
4532995Shx147065 ret = B_FALSE;
4533995Shx147065 goto exit0;
4534995Shx147065 }
4535995Shx147065 if (do_gs_func[j].p_do_set_func(fd, value)
4536*6834Sff224033 == B_TRUE) {
4537995Shx147065 ret = B_TRUE;
4538995Shx147065 } else {
4539995Shx147065 if (gbuf->wldp_result != WL_SUCCESS) {
4540995Shx147065 (void) fprintf(stderr,
4541995Shx147065 gettext("%s: "
4542995Shx147065 "failed to set '%s' for "),
4543995Shx147065 gExecName, param);
4544995Shx147065 print_error(gbuf->wldp_result);
4545995Shx147065 }
4546995Shx147065 free(param);
4547995Shx147065 ret = B_FALSE;
4548995Shx147065 goto exit0;
4549995Shx147065 }
4550995Shx147065 free(param);
4551995Shx147065 }
4552995Shx147065 exit0:
4553995Shx147065 return (ret);
4554995Shx147065 }
4555995Shx147065
4556995Shx147065 static boolean_t
do_get(int fd,int argc,char ** argv)4557995Shx147065 do_get(int fd, int argc, char **argv)
4558995Shx147065 {
4559995Shx147065 int i = 0, j = 0, n = 0;
4560995Shx147065 boolean_t ret = B_TRUE;
4561995Shx147065
4562995Shx147065 PRTDBG(("do_get(%d, 0x%x)\n", argc, argv));
4563995Shx147065 assert(fd > 0);
4564995Shx147065 /*
4565995Shx147065 * If no specific parameter typed, we print out all parameters
4566995Shx147065 */
4567995Shx147065 if (argc <= 0) {
4568995Shx147065 for (i = 0; i < N_GS_FUNC; i++) {
4569995Shx147065 if ((do_gs_func[i].p_do_get_func != NULL) &&
4570995Shx147065 (do_gs_func[i].p_do_get_func(fd)
4571995Shx147065 == B_TRUE)) {
4572995Shx147065 print_gbuf(do_gs_func[i].index);
4573995Shx147065 n++;
4574995Shx147065 }
4575995Shx147065 }
4576995Shx147065 ret = n ? B_TRUE:B_FALSE;
4577995Shx147065 goto exit0;
4578995Shx147065 }
4579995Shx147065 /*
4580995Shx147065 * Match function with do_gs_func[] table, and print its result
4581995Shx147065 */
4582995Shx147065 for (i = 0; i < argc; i++) {
4583995Shx147065 for (j = 0; j < N_GS_FUNC; j++) {
4584995Shx147065 if (strcmp(argv[i], do_gs_func[j].cmd) == 0) {
4585995Shx147065 break;
4586995Shx147065 }
4587995Shx147065 if (param_is_wepkey(argv[i], B_FALSE) == B_TRUE) {
4588995Shx147065 j = WEPKEY;
4589995Shx147065 break;
4590995Shx147065 }
4591995Shx147065 }
4592995Shx147065 if (j == N_GS_FUNC) {
4593995Shx147065 (void) fprintf(stderr,
4594995Shx147065 gettext("wificonifg: unrecognized parameter: "
4595995Shx147065 "%s\n"), argv[i]);
4596995Shx147065 ret = B_FALSE;
4597995Shx147065 goto exit0;
4598995Shx147065 }
4599995Shx147065 if (do_gs_func[j].p_do_get_func == NULL) {
4600995Shx147065 (void) fprintf(stderr,
4601995Shx147065 gettext("%s: parameter '%s' is write-only\n"),
4602995Shx147065 gExecName, do_gs_func[j].cmd);
4603995Shx147065 ret = B_FALSE;
4604995Shx147065 goto exit0;
4605995Shx147065 }
4606995Shx147065 if (do_gs_func[j].p_do_get_func(fd) == B_TRUE) {
4607995Shx147065 print_gbuf(do_gs_func[j].index);
4608995Shx147065 ret = B_TRUE;
4609995Shx147065 } else {
4610995Shx147065 (void) fprintf(stderr,
4611995Shx147065 gettext("%s: "
4612995Shx147065 "failed to read parameter '%s' : "),
4613995Shx147065 gExecName, argv[i]);
4614995Shx147065 print_error(gbuf->wldp_result);
4615995Shx147065 ret = B_FALSE;
4616995Shx147065 }
4617995Shx147065 }
4618995Shx147065 exit0:
4619995Shx147065 return (ret);
4620995Shx147065 }
4621995Shx147065
4622995Shx147065 /*
4623995Shx147065 * Only one wificonfig is running at one time.
4624995Shx147065 * The following wificonfig which tries to be run will return error,
4625995Shx147065 * and the pid of the process will own the filelock will be printed out.
4626995Shx147065 */
4627995Shx147065 static pid_t
enter_wifi_lock(int * fd)4628995Shx147065 enter_wifi_lock(int *fd)
4629995Shx147065 {
4630995Shx147065 int fd0 = -1;
4631995Shx147065 struct flock lock;
4632995Shx147065
4633995Shx147065 fd0 = open(WIFI_LOCKF, O_CREAT|O_WRONLY, 0600);
4634995Shx147065 if (fd0 < 0) {
4635995Shx147065 (void) fprintf(stderr, gettext("%s: failed to open lockfile"
4636995Shx147065 " '"WIFI_LOCKF"': %s\n"), gExecName, strerror(errno));
4637995Shx147065 exit(WIFI_FATAL_ERR);
4638995Shx147065 }
4639995Shx147065
4640995Shx147065 *fd = fd0;
4641995Shx147065 lock.l_type = F_WRLCK;
4642995Shx147065 lock.l_whence = SEEK_SET;
4643995Shx147065 lock.l_start = 0;
4644995Shx147065 lock.l_len = 0;
4645995Shx147065
4646995Shx147065 if ((fcntl(fd0, F_SETLK, &lock) == -1) &&
4647995Shx147065 (errno == EAGAIN || errno == EDEADLK)) {
4648995Shx147065 if (fcntl(fd0, F_GETLK, &lock) == -1) {
4649995Shx147065 (void) fprintf(stderr,
4650995Shx147065 gettext("%s: enter_filelock"));
4651995Shx147065 exit(WIFI_FATAL_ERR);
4652995Shx147065 }
4653995Shx147065 (void) fprintf(stderr, gettext("%s:"
4654995Shx147065 "enter_filelock:filelock is owned "
4655995Shx147065 "by 'process %d'\n"), gExecName, lock.l_pid);
4656995Shx147065 return (lock.l_pid);
4657995Shx147065 }
4658995Shx147065
4659995Shx147065 return (getpid());
4660995Shx147065 }
4661995Shx147065
4662995Shx147065 static void
exit_wifi_lock(int fd)4663995Shx147065 exit_wifi_lock(int fd)
4664995Shx147065 {
4665995Shx147065 struct flock lock;
4666995Shx147065
4667995Shx147065 lock.l_type = F_UNLCK;
4668995Shx147065 lock.l_whence = SEEK_SET;
4669995Shx147065 lock.l_start = 0;
4670995Shx147065 lock.l_len = 0;
4671995Shx147065 if (fcntl(fd, F_SETLK, &lock) == -1) {
4672995Shx147065 (void) fprintf(stderr, gettext("%s: failed to"
4673995Shx147065 " exit_filelock: %s\n"),
4674995Shx147065 gExecName, strerror(errno));
4675995Shx147065 }
4676995Shx147065 (void) close(fd);
4677995Shx147065 }
4678995Shx147065
4679995Shx147065 int
main(int argc,char ** argv)4680995Shx147065 main(int argc, char **argv)
4681995Shx147065 {
4682995Shx147065 int i, ret;
4683995Shx147065 int fddev = -1;
4684995Shx147065 int c, iflag = 0, rflag = 0, fileonly = 0, readonly = 0;
4685995Shx147065 int fd;
4686995Shx147065 char *iname = NULL;
4687995Shx147065 char *path = NULL;
4688995Shx147065 extern char *optarg;
4689995Shx147065 extern int optind;
4690995Shx147065 char interface[LIFNAMSIZ];
4691995Shx147065 char file_wifi[MAX_CONFIG_FILE_LENGTH];
4692995Shx147065 char file_wifiwepkey[MAX_CONFIG_FILE_LENGTH];
4693995Shx147065 priv_set_t *ppriv;
4694995Shx147065 wifi_auth_t autht;
4695995Shx147065
4696995Shx147065 PRTDBG(("main(%d, 0x%x)\n", argc, argv));
4697995Shx147065 PRTDBG(("uid=%d\n", getuid()));
4698995Shx147065 PRTDBG(("euid=%d\n", geteuid()));
4699995Shx147065
4700995Shx147065 #ifdef DEBUG
4701995Shx147065 if (wifi_debug == 1) { /* for debuf purpose only */
4702995Shx147065 (void) printf("Press RETURN to continue...\n");
4703995Shx147065 (void) getchar();
4704995Shx147065 }
4705995Shx147065 #endif
4706995Shx147065 ret = WIFI_EXIT_DEF;
4707995Shx147065
4708995Shx147065 (void) setlocale(LC_ALL, "");
4709995Shx147065 (void) textdomain(TEXT_DOMAIN);
4710995Shx147065
4711995Shx147065 gExecName = argv[0];
4712995Shx147065
4713995Shx147065 gbuf = safe_malloc(MAX_BUF_LEN);
4714995Shx147065
4715995Shx147065 if ((ppriv = priv_str_to_set("basic", ",", NULL)) == NULL) {
4716995Shx147065 PRTDBG(("main: priviledge init error\n"));
4717995Shx147065 (void) fprintf(stderr, gettext("%s: "
4718995Shx147065 "set priviledge to 'basic' error\n"),
4719995Shx147065 gExecName);
4720995Shx147065 ret = WIFI_FATAL_ERR;
4721995Shx147065 goto exit0;
4722995Shx147065 }
4723995Shx147065 (void) priv_addset(ppriv, PRIV_NET_RAWACCESS);
4724995Shx147065 (void) priv_addset(ppriv, PRIV_SYS_NET_CONFIG);
4725995Shx147065 if (setppriv(PRIV_SET, PRIV_PERMITTED, ppriv) == -1) {
4726995Shx147065 (void) fprintf(stderr, gettext("%s: "
4727995Shx147065 "set permitted priviledge: %s\n"),
4728995Shx147065 gExecName, strerror(errno));
4729995Shx147065 ret = WIFI_FATAL_ERR;
4730995Shx147065 goto exit0;
4731995Shx147065 }
4732995Shx147065 if (setppriv(PRIV_SET, PRIV_LIMIT, ppriv) == -1) {
4733995Shx147065 (void) fprintf(stderr, gettext("%s: "
4734995Shx147065 "set limit priviledge: %s\n"),
4735995Shx147065 gExecName, strerror(errno));
4736995Shx147065 ret = WIFI_FATAL_ERR;
4737995Shx147065 goto exit0;
4738995Shx147065 }
4739995Shx147065 if (setppriv(PRIV_SET, PRIV_INHERITABLE, ppriv) == -1) {
4740995Shx147065 (void) fprintf(stderr, gettext("%s: "
4741995Shx147065 "set inherit priviledge: %s\n"),
4742995Shx147065 gExecName, strerror(errno));
4743995Shx147065 ret = WIFI_FATAL_ERR;
4744995Shx147065 goto exit0;
4745995Shx147065 }
4746995Shx147065 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, ppriv) == -1) {
4747995Shx147065 (void) fprintf(stderr, gettext("%s: "
4748995Shx147065 "set effective priviledge: %s\n"),
4749995Shx147065 gExecName, strerror(errno));
4750995Shx147065 ret = WIFI_FATAL_ERR;
4751995Shx147065 goto exit0;
4752995Shx147065 }
4753995Shx147065 priv_freeset(ppriv);
4754995Shx147065
4755995Shx147065 for (i = 0; i < argc; i++) {
4756995Shx147065 PRTDBG(("%d\t\t\"%s\"\n", i, argv[i]));
4757995Shx147065 }
4758995Shx147065
4759995Shx147065 while ((c = getopt(argc, argv, "i:R:")) != EOF) {
4760995Shx147065 switch (c) {
4761995Shx147065 case 'i':
4762995Shx147065 if (iflag) {
4763995Shx147065 do_print_usage();
4764995Shx147065 ret = WIFI_IMPROPER_USE;
4765995Shx147065 goto exit0;
4766995Shx147065 }
4767995Shx147065 iflag = 1;
4768995Shx147065 iname = optarg;
4769995Shx147065 break;
4770995Shx147065 case 'R':
4771995Shx147065 if (rflag) {
4772995Shx147065 do_print_usage();
4773995Shx147065 ret = WIFI_IMPROPER_USE;
4774995Shx147065 goto exit0;
4775995Shx147065 }
4776995Shx147065 rflag = 1;
4777995Shx147065 path = optarg;
4778995Shx147065 break;
4779995Shx147065 case '?':
4780995Shx147065 default:
4781995Shx147065 do_print_usage();
4782995Shx147065 ret = WIFI_IMPROPER_USE;
4783995Shx147065 goto exit0;
4784995Shx147065 }
4785995Shx147065 }
4786995Shx147065 argc -= optind;
4787995Shx147065 argv += optind;
4788995Shx147065
4789995Shx147065 if (argc <= 0) {
4790995Shx147065 if (iname) {
4791995Shx147065 if ((fddev = open_dev(iname)) == -1) {
4792995Shx147065 ret = WIFI_FATAL_ERR;
4793995Shx147065 goto exit0;
4794995Shx147065 }
4795995Shx147065 if (do_print_support_params(fddev) ==
4796995Shx147065 B_TRUE)
4797995Shx147065 ret = WIFI_EXIT_DEF;
4798995Shx147065 else
4799995Shx147065 ret = WIFI_FATAL_ERR;
4800995Shx147065 goto exit1;
4801995Shx147065 } else {
4802995Shx147065 do_print_usage();
4803995Shx147065 ret = WIFI_IMPROPER_USE;
4804995Shx147065 goto exit0;
4805995Shx147065 }
4806995Shx147065 }
4807995Shx147065
4808995Shx147065 for (i = 0; i < N_FUNC; i++) {
4809995Shx147065 if (strcmp(argv[0], do_func[i].cmd) == 0) {
4810995Shx147065 autht = ((strcmp(argv[0], "setwepkey") == 0) ||
4811995Shx147065 (strcmp(argv[0], "setprofwepkey") == 0)) ?
4812995Shx147065 AUTH_WEP:AUTH_OTHER;
4813995Shx147065 if (do_func[i].b_auth &&
4814995Shx147065 !check_authority(autht)) {
4815995Shx147065 ret = WIFI_FATAL_ERR;
4816995Shx147065 goto exit0;
4817995Shx147065 }
4818995Shx147065 if (do_func[i].b_fileonly)
4819995Shx147065 fileonly++;
4820995Shx147065 if (do_func[i].b_readonly)
4821995Shx147065 readonly++;
4822995Shx147065 break;
4823995Shx147065 }
4824995Shx147065 }
4825995Shx147065 if (i == N_FUNC) {
4826995Shx147065 (void) fprintf(stderr, gettext("%s: unrecognized "
4827995Shx147065 "subcommand: %s\n"), gExecName, argv[0]);
4828995Shx147065 do_print_usage();
4829995Shx147065 ret = WIFI_IMPROPER_USE;
4830995Shx147065 goto exit0;
4831995Shx147065 }
4832995Shx147065 if ((fileonly) && (iname)) {
4833995Shx147065 do_print_usage();
4834995Shx147065 ret = WIFI_IMPROPER_USE;
4835995Shx147065 goto exit0;
4836995Shx147065 }
4837995Shx147065 if ((!fileonly) && (!iname)) {
4838995Shx147065 if (search_interface(interface) != B_TRUE) {
4839995Shx147065 (void) fprintf(stderr, gettext("%s: "
4840995Shx147065 "failed to find the default wifi interface;"
4841995Shx147065 " -i option should be used to specify the "
4842995Shx147065 "wifi interface\n"), gExecName);
4843995Shx147065 ret = WIFI_FATAL_ERR;
4844995Shx147065 goto exit0;
4845995Shx147065 }
4846995Shx147065 iname = interface;
4847995Shx147065 }
4848995Shx147065 if (iname) {
4849995Shx147065 if ((fddev = open_dev(iname)) == -1) {
4850995Shx147065 ret = WIFI_FATAL_ERR;
4851995Shx147065 goto exit0;
4852995Shx147065 }
4853995Shx147065 }
4854995Shx147065 if (rflag) {
4855995Shx147065 safe_snprintf(file_wifi, sizeof (file_wifi),
4856995Shx147065 "%s%s", path, p_file_wifi);
4857995Shx147065 safe_snprintf(file_wifiwepkey, sizeof (file_wifiwepkey),
4858995Shx147065 "%s%s", path, p_file_wifiwepkey);
4859995Shx147065 } else {
4860995Shx147065 safe_snprintf(file_wifi, sizeof (file_wifi),
4861995Shx147065 "%s", p_file_wifi);
4862995Shx147065 safe_snprintf(file_wifiwepkey, sizeof (file_wifiwepkey),
4863995Shx147065 "%s", p_file_wifiwepkey);
4864995Shx147065 }
4865995Shx147065 /*
4866995Shx147065 * There is an occasion when more than one wificonfig processes
4867995Shx147065 * which attempt to write the <wifi> and <wifiwepkey> files are
4868995Shx147065 * running. We must be able to avoid this.
4869995Shx147065 * We use file lock here to implement this.
4870995Shx147065 */
4871995Shx147065 if ((!readonly) && (enter_wifi_lock(&fd) != getpid())) {
4872995Shx147065 ret = WIFI_FATAL_ERR;
4873995Shx147065 goto exit1;
4874995Shx147065 }
4875995Shx147065 gp_config_file = parse_file(file_wifi);
4876995Shx147065 if (gp_config_file == NULL) {
4877995Shx147065 ret = WIFI_FATAL_ERR;
4878995Shx147065 goto exit2;
4879995Shx147065 }
4880995Shx147065
4881995Shx147065 gp_wepkey_file = parse_file(file_wifiwepkey);
4882995Shx147065 if (gp_wepkey_file == NULL) {
4883995Shx147065 destroy_config(gp_config_file);
4884995Shx147065 ret = WIFI_FATAL_ERR;
4885995Shx147065 goto exit2;
4886995Shx147065 }
4887995Shx147065 if (do_func[i].p_do_func(fddev, argc-1, argv+1)
4888995Shx147065 == B_TRUE) {
4889995Shx147065 /*
4890995Shx147065 * can not write file when startconfing
4891995Shx147065 * during boot
4892995Shx147065 */
4893995Shx147065 if (do_func[i].b_readonly)
4894995Shx147065 ret = WIFI_EXIT_DEF;
4895995Shx147065 else if ((fprint_config_file(gp_config_file,
4896995Shx147065 file_wifi) != B_TRUE) ||
4897995Shx147065 (fprint_config_file(gp_wepkey_file,
4898995Shx147065 file_wifiwepkey) != B_TRUE))
4899995Shx147065 ret = WIFI_FATAL_ERR;
4900995Shx147065 else
4901995Shx147065 ret = WIFI_EXIT_DEF;
4902995Shx147065 } else {
4903995Shx147065 PRTDBG(("Command %s failed\n", argv[0]));
4904995Shx147065 ret = WIFI_FATAL_ERR;
4905995Shx147065 }
4906995Shx147065 destroy_config(gp_wepkey_file);
4907995Shx147065 destroy_config(gp_config_file);
4908995Shx147065 exit2:
4909995Shx147065 if (!readonly)
4910995Shx147065 exit_wifi_lock(fd);
4911995Shx147065 exit1:
4912995Shx147065 if (iname)
4913995Shx147065 (void) close(fddev);
4914995Shx147065 exit0:
4915995Shx147065 free(gbuf);
4916995Shx147065 return (ret);
4917995Shx147065 }
4918995Shx147065
4919995Shx147065 #ifdef DEBUG
4920995Shx147065 static void
wifi_dbgprintf(char * fmt,...)4921995Shx147065 wifi_dbgprintf(char *fmt, ...)
4922995Shx147065 {
4923995Shx147065 va_list ap;
4924995Shx147065 va_start(ap, fmt);
4925995Shx147065 (void) vfprintf(stdout, fmt, ap);
4926995Shx147065 va_end(ap);
4927995Shx147065 }
4928995Shx147065 #endif
4929