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