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