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