/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <ctype.h>
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <stropts.h>
#include <assert.h>
#include <termios.h>
#include <time.h>
#include <string.h>
#include <strings.h>
#include <auth_attr.h>
#include <auth_list.h>
#include <libdevinfo.h>
#include <secdb.h>
#include <priv.h>
#include <pwd.h>
#include <umem.h>
#include <locale.h>
#include <libintl.h>
#include <dirent.h>
#include <inet/wifi_ioctl.h>
/*
* Debug information
*/
#ifdef DEBUG
int wifi_debug = 0;
void wifi_dbgprintf(char *fmt, ...);
#else /* DEBUG */
#endif /* DEBUG */
#define RECORD_ADD 0
/*
* Wificonfig exit status
*/
#define WIFI_EXIT_DEF 0
typedef enum {
} list_type_t;
typedef enum {
LINKSTATUS = 0,
typedef struct ae {
char *ae_arg;
}ae_t;
typedef struct aelist {
int ael_argc;
}aelist_t;
typedef struct section {
char *section_id;
/*
* config_file_t is an abstract of configration file,
* wifi/wifiwepkey.<interface>
*/
typedef struct config_file {
int section_argc;
typedef enum {
AUTH_WEP = 0,
} wifi_auth_t;
static char *p_auth_string[] = {
};
/*
* gbuf: is a global buf, which is used to communicate between the user and
* the driver
*/
static void print_error(uint32_t);
static void *safe_malloc(size_t);
static char *safe_strdup(const char *s1);
static void safe_snprintf(char *s, size_t n,
const char *format, ...);
static config_file_t *new_config_file();
const char *section_id);
const char *file_name);
const char *section_id);
static char *find_active_profile(int);
static const char *essid_of_profile(const char *profile);
int rank);
static char *get_commit_key(int, int, char **);
static void do_print_usage();
typedef struct cmd_ops {
} cmd_ops_t;
{
"autoconf",
},
{
"startconf",
},
{
"connect",
},
{
"disconnect",
},
{
"showprofile",
},
{
"deleteprofile",
},
{
"history",
},
{
"listprefer",
},
{
"removeprefer",
},
{
"setprefer",
},
{
"setwepkey",
},
{
"restoredef",
},
{
"getparam",
},
{
"setparam",
},
{
"createprofile",
},
{
"scan",
},
{
"showstatus",
},
{
"setprofileparam",
},
{
"getprofileparam",
},
{
"setprofilewepkey",
}
};
typedef struct gs_ops {
} gs_ops_t;
};
/*
* valid rate value
*/
typedef struct wifi_rates_tab {
char *rates_s;
/*
* the rates value is in increments of 500kb/s.
* according to the 802.11 a/b/g specs(IEEE):
* 802.11b(IEEE Std 802.11b-1999) page35, rates should be:
* X02, X04, X0b, X16
* 802.11a(IEEE Std 802.11a-1999) page47, rates should be:
* 6,9,12,18,24,36,48,54 Mb/s
* 802.11g(IEEE Std 802.11g-2003) page44, rates should be:
* 1,2,5.5,11,6,9,12,18,22,24,33,36,48,54 Mb/s
*/
{"1", WL_RATE_1M, 0, 0, 0},
{"2", WL_RATE_2M, 0, 0, 0},
{"5.5", WL_RATE_5_5M, 0, 0, 0},
{"6", WL_RATE_6M, 0, 0, 0},
{"9", WL_RATE_9M, 0, 0, 0},
{"11", WL_RATE_11M, 0, 0, 0},
{"12", WL_RATE_12M, 0, 0, 0},
{"18", WL_RATE_18M, 0, 0, 0},
{"22", WL_RATE_22M, 0, 0, 0},
{"24", WL_RATE_24M, 0, 0, 0},
{"33", WL_RATE_33M, 0, 0, 0},
{"36", WL_RATE_36M, 0, 0, 0},
{"48", WL_RATE_48M, 0, 0, 0},
{"54", WL_RATE_54M, 0, 0, 0}
};
/* print the error message on why set or get ioctl command failed. */
static void
{
char *buf;
switch (errorno) {
case WL_SUCCESS:
break;
case WL_NOTSUPPORTED:
case WL_LACK_FEATURE:
case WL_HW_ERROR:
case WL_ACCESS_DENIED:
break;
case WL_READONLY:
break;
case WL_WRITEONLY:
break;
case WL_NOAP:
break;
default:
break;
}
}
static void *
{
void *buf;
}
return (buf);
}
static void *
{
void *buf;
}
return (buf);
}
static char *
{
char *p;
if (p == NULL) {
}
return (p);
}
static void
{
int len;
gettext("%s: snprintf: %s\n"),
}
}
static void
{
int err;
}
}
/*
* new_ae: Add an element with content pointed by arg to the list *ael.
*/
static void
{
} else {
}
}
/*
* new_ael: Create a new aelist with list_type "type"
* and return the list pointer.
*/
static aelist_t *
{
return (plist);
}
/*
* new_config_file: Creates a new config_file_t struct which is counterpart of
* of the configration file, and return the pointer.
*/
static config_file_t *
{
p_config_file->section_argc = 0;
return (p_config_file);
}
/*
* new_section: Add a list pointed by "p_list", with identity "section_id" to
* the config_file_t struct pointed by "p_config_file"
*/
static void
const char *section_id)
{
section_id));
(section_id != NULL));
} else {
}
}
/*
* destroy_config:Destroy the config_file struct
*/
static void
{
}
}
}
}
/*
* parse_file: Parse each section of the configration file
* and construct the config_file_t structure.
* Example:
* A config file has contents below:
*
* {preferrence}
* essid=ap7-3
* essid=linksys
*
* {history}
* essid=ap7-3
* essid=ap7-2
*
* [ap7-3]
* essid=ap7-3
* wepkeyid=3
* channel=11
* rates=1,2
*
* [linksys]
* essid=linksys
* createibss=BSS
* authmode=OPENSYSTEM
* wepkeyid=1
*
* then its config_file_t structure will be:
*
* config_file_t
* |~~~~~~~~~~~~~~~~~~~~~~~~~~|
* | section_argc=5 |
* |~~~~~~~~~~~~T~~~~~~~~~~~~~|
* /| *head | *tail |\
* / ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \
* / \
* / \
* / \
* / \
* / \
* section_t V section_t V section_t
* |~~~~~~~~~~~~~~~|~~| |~~~~~~~~~~~~~~~|~~| |~~~~~~~~~~~~~~|~~|
* |"{preferrence}"| | | "{history}" | | | "[linksys]" | |
* |~~~~~~~~~~~~~~~| -+---->|~~~~~~~~~~~~~~~| -+->..->|~~~~~~~~~~~~~~| -+->NULL
* | *list | | | *list | | | *list | |
* ~~T~~~~~~~~~~~~~~~~~ ~~~T~~~~~~~~~~~~~~~~ ~~~T~~~~~~~~~~~~~~~
* | | |
* | | |
* V aelist_t V aelist_t V aelist_t
* |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| |~~~~~~~~~~~~~|
* | argc=2 | | argc=3 | | argc=4 |
* |~~~~~~~~~~~~~| |~~~~~~~~~~~~~| |~~~~~~~~~~~~~|
* |PREFFERRENCE | | HISTORY | | PROFILE |
* |~~~~~~T~~~~~~| |~~~~~~T~~~~~~| |~~~~~~T~~~~~~|
* |*head |*tail |\ |*head |*tail |\ |*head |*tail |
* ~~T~~~~~~~~~~~~ \ ~~T~~~~~~~~~~~~ \ /~~~~~~~~~~~~~~~\
* | \ V V / \
* | \ ... ... / \
* V ae_t V ae_t ae_t V ae_t V
* |~~~~~~~~~T~~| |~~~~~~~~~T~~| |~~~~~~~~~T~~| |~~~~~~~~~T~~|
* |"essid= | -+->|"essid= | -+->NULL |"essid= | -+->..->|"wepkeyid| -+->NULL
* | ap7-3" | | | linksys"| | | linksys"| | | =1" | |
* ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
*
*/
static config_file_t *
{
int fd = 0;
/*
* be opened with "r" attribute. If these two files do not exist,
* create them here.
*/
if (fd < 0) {
goto error1;
}
}
continue;
/* replace the old '\n' to '\0' */
if (prefer_list == NULL) {
} else {
"%s : duplicated %s section\n"),
goto error;
}
if (history_list == NULL) {
} else {
"%s : duplicated %s section\n"),
goto error;
}
if (activep_list == NULL) {
} else {
"%s : duplicated %s section\n"),
goto error;
}
buf_line);
} else {
switch (cur_list) {
case PREFERENCE:
if (prefer_list->ael_argc <=
break;
case HISTORY:
if (history_list->ael_argc <=
break;
case ACTIVEP:
break;
case PROFILE:
break;
default:
gettext("%s: %s: file format error\n"),
goto error;
}
}
}
return (p_config_file);
return (NULL);
}
/*
* construct an argument vector from an aelist
*/
static char **
{
int argc = 0;
/* skip bssid since it can not be set */
continue;
argc++;
break;
}
return (argv);
}
/*
* archived contents into a file
*/
static boolean_t
{
int fd = 0;
int len;
file_name));
if (fd < 0) {
return (B_FALSE);
}
PRTDBG(("fprint_config_file: section_id=%s\n",
p_section->section_id));
if (len < 0) {
"failed to update %s: %s\n"),
return (B_FALSE);
}
if (len < 0) {
gettext("%s: failed to "
"update %s: %s\n"),
return (B_FALSE);
}
}
}
}
}
/*
* /etc/inet/security/wifiwepkey should be retained.
* if those file do not exist, set default file mode.
*/
} else {
"file %s stat: %s\n"),
return (B_FALSE);
}
}
return (B_FALSE);
}
return (B_TRUE);
}
/*
* append_pa: Each section holds a section_id which identifies a section
* a profile uses its essid appending "[]" to denote its section_id.
* note: new memory is allocated, remember to free.
*/
static char *
{
int len;
return (pbuf);
}
/*
* find a section by section_id from p_config_file,
* return the section pointer.
*/
static section_t *
{
return (p_section);
}
return (NULL);
}
/*
* get_value: Get rid of "parameter=" from a "parameter=value", for example:
* when we read an line from file, we gets "essid=ap7-2", this function
* returns the pointer to string "ap7-2";
*/
static const char *
{
char *p;
if (p != NULL)
return (p + 1);
else
return (NULL);
}
/*
*/
static boolean_t
{
int fd;
PRTDBG(("search interface\n"));
/*
* Try to return the first found wifi interface.
* If no wifi interface is available, return B_FALSE
*/
return (B_FALSE);
}
continue;
continue;
if (fd == -1) {
continue;
} else {
PRTDBG(("interface %s is the first found interface\n",
return (B_TRUE);
}
}
PRTDBG(("failed to find available wireless interface\n"));
return (B_FALSE);
}
/*
* open_dev: Open the driver.
* if the 'devname' has format like 'ath0', we should add the path to that
*/
static int
{
int fd;
int len;
/*
* If the devname is got from the user input, we
* add '/dev/' to that relative devname. If it
* is got from the 'search interface', it is an
* absolute path.
*/
} else {
}
if (fd == -1) {
return (-1);
}
"not a stream device\n"),
return (-1);
}
return (fd);
}
/*
* call_ioctl: Fill strioctl structure and issue an ioctl system call
*/
static boolean_t
{
PRTDBG(("call_ioctl_gs(%d, 0x%x, 0x%x, 0x%x)\n",
switch (cmd) {
case WLAN_GET_PARAM:
break;
case WLAN_SET_PARAM:
break;
case WLAN_COMMAND:
break;
default:
"unsupported ioctl command\n"), gExecName);
return (B_FALSE);
}
return (B_FALSE);
}
if (cmd == WLAN_COMMAND) {
return (B_TRUE);
} else {
}
}
/*
* del_prefer: Delete an item from the {preferrence} list, the idea is
* simply free the ae_t element, and set ae_arg to NULL, then when archive
* the config_file_t struct to the file, it will be delete.
* The last flag is used to identify whether this function is invoked due to
* the 'removeprefer' subcommand or due to 'deleteprofile' subcommand.
*/
static boolean_t
{
int i = 0, position = 0;
int number;
return (B_FALSE);
if (!position) {
} else {
for (i = 0; i < position - 1; i++)
}
break;
}
position++;
}
"no such profile: '%s' in the preference list\n"),
return (B_FALSE);
}
return (B_TRUE);
}
/*
* del_section: Delete an section from p_config_file, the idea is
* simply free the aelist_t struct and set it to NULL, when archiving
* config_file_t struct to the file, we will find section list is NULL,
* and will not write it to file, so it will be deleted.
*/
static boolean_t
{
int i = 0, position = 0;
PRTDBG(("del_section: %d section(s) in config file\n",
return (B_FALSE);
}
}
if (!position) {
NULL;
} else {
for (i = 0; i < position - 1; i++) {
}
}
break;
}
position++;
}
}
return (B_TRUE);
}
/*
* set_prefer: Reorder the preferrence list.
*/
static boolean_t
{
int i = 0, position = 0;
"no such profile: '%s'\n"),
return (B_FALSE);
}
return (B_TRUE);
} else {
}
if (!position) {
} else {
for (i = 0; i < position - 1; i++)
}
break;
}
position++;
}
} else if (rank <= 1) {
} else {
}
}
/*
* If number of prefer list items is larger than the MAX_PREFERENCE_NUM
* delete those items whose No is larger than MAX_PREFERENCE_NUM.
*/
}
return (B_TRUE);
}
/*
* add_to_history: Save the scanlist argv into history section
*/
static void
{
int i = 0, j = 0, pos = 0;
} else {
}
for (i = 0; i < argc; i++) {
continue;
pos = 0;
/*
* add time stamp to the history record
*/
if (!pos) {
} else {
for (j = 0; j < pos - 1; j++)
}
break;
}
pos++;
}
}
i++) {
}
}
}
}
static void
{
" autoconf [wait={n|forever}]\n"), gExecName);
" connect profile [wait={n|forever}]\n"), gExecName);
" connect essid [wait={n|forever}]\n"), gExecName);
" disconnect\n"), gExecName);
" getparam [parameter [...]]\n"), gExecName);
" setparam [parameter=value [...]]\n"), gExecName);
"\tparameters:\n"
"\t\tbssid\t\t - read only: 6 byte mac address of "
"base station\n"
"\t\tessid\t\t - name of the network, a string of up "
"to 32 chars\n"
"\t\tbsstype\t\t - bss(ap, infrastructure), ibss(ad-hoc)"
" or auto\n"
"\t\tcreateibss\t - flag to identify whether a ibss is to be\n"
"\t\t\t\t created when the network to connect is\n"
"\t\t\t\t not available, yes or no\n"
"\t\tchannel\t\t - channel(used only when creating an ibss)\n"
"\t\t\t\t valid value:\n"
"\t\t\t\t\t 802.11a: 0-99\n"
"\t\t\t\t\t 802.11b: 1-14\n"
"\t\t\t\t\t 802.11g: 1-14\n"
"\t\trates\t\t - set of rates, seperated by ',' valid rates:\n"
"\t\t\t\t 1,2,5.5,6,9,11,12,18,22,24,33,36,48 and 54\n"
"\t\tpowermode\t - off, mps or fast\n"
"\t\tauthmode\t - opensystem or shared_key\n"
"\t\tencryption\t - none or wep\n"
"\t\twepkey|1-4\t - write only:\n"
"\t\t\t\t 5 chars or 10 hex digits for 40bit wepkey;\n"
"\t\t\t\t 13 chars or 26 hex digits for 128bit wepkey\n"
"\t\twepkeyindex\t - an integer within the range 1-4\n"
"\t\tsignal\t\t - read only: signal strength from 0 to 15\n"
"\t\tradio\t\t - on or off\n"));
" restoredef\n"), gExecName);
" scan\n"), gExecName);
" showstatus\n"), gExecName);
" setwepkey 1|2|3|4\n"), gExecName);
" createprofile profile parameter=value [...]\n"), gExecName);
" deleteprofile profile1 [profile2 [...]]\n"), gExecName);
" showprofile profile1 [profile2 [...]]\n"), gExecName);
" setprofilewepkey profile 1|2|3|4\n"), gExecName);
" getprofileparam profile [parameter [...]]\n"), gExecName);
" setprofileparam profile [parameter=value [...]]\n"), gExecName);
" history\n"), gExecName);
" listprefer\n"), gExecName);
" removeprefer profile\n"), gExecName);
" setprefer profile [n]\n"), gExecName);
}
/*
* do_print_support_params: Query interface which cmd is supported
*/
static boolean_t
{
int i = 0, n = 0;
for (i = 0; i < N_GS_FUNC; i++) {
continue;
}
else
n++;
}
}
}
/*
* check_authority: Check if command is permitted.
*/
static boolean_t
{
PRTDBG(("check_authority()\n"));
return (B_FALSE);
"privilege '%s' is required for setting "
else
"privilege '%s' is required.\n"),
return (B_FALSE);
} else {
return (B_TRUE);
}
}
/*
* construct the 'history' and 'scan' output format
* memory allocated. need to free after the function is invoked.
*/
static char *
{
char *format;
int len = 0, i;
for (i = 0; i < nt; i++)
return ("\t\t\t\t");
}
return (format);
}
/*
* find the essid of the named profile.
* gp_config_file is golable, so the return is gloable too.
*/
static const char *
{
char *pbuf;
return (NULL);
} else {
}
PRTDBG(("essid_of_profile: essid = %s\n",
}
}
return (NULL);
}
/*
* If we don't know which profile is our favorate in 'autoconf',
* we select the wifi network based on the following heuristic
* 1. the network without wep.
* 2. the network with the strongst signal.
* 3. the network with the faster speed(not implemented since signal affects
* the speed in some degree).
*/
static void
{
int i = 0;
int have_nowep_wlan = 0;
PRTDBG(("heuristic_load: enter\n"));
for (i = 0; i < ess_num; i++) { /* extract none-wep network */
flag[i] = 1;
have_nowep_wlan = 1;
}
}
/*
* if all the wlans are weped, we select the one with strongest signal
* in all of them, otherwise we just select in the none weped ones.
*/
if (!have_nowep_wlan)
for (i = 0; i < ess_num; i++) { /* extract the strongest signal ones */
if (flag[i] == 1) {
continue;
else
flag[i] = 0;
}
}
for (i = 0; i < ess_num; i++) {
if (flag[i] == 1)
break;
}
PRTDBG(("heuristic_load: %s is selected\n",
/* select one in all the networks which meet the preceding stardands */
if (i == ess_num)
else
(void) do_set_essid(fd,
" failed to connect to any essid\n"),
}
sizeof (essid));
"access point");
if (!have_nowep_wlan)
while (timeout > 0) {
return;
}
(void) sleep(1);
timeout--;
}
}
/*
* Called in autoconf and startconf to find which 'profile' is selected.
* The process is: check profile names in the prefer list item by item,
* if the essid of the profile is in the scan list, then it is the wanted.
* readonly: 1 for startconf
* 0 for autoconf
* for autoconf, the scan result will be recorded in the history list.
*/
static char *
{
char **ess_argv;
char **hisess_argv;
int i;
const char *parg;
"autoconf : failed to scan\n"), gExecName);
}
for (i = 0; i < ess_num; i++) {
->wl_ess_list_ess + i;
if (readonly == 0) {
"%s%c%02x:%02x:%02x:%02x:%02x:%02x%c%s",
',',
? "wep":"none"));
}
}
if (readonly == 0) {
for (i = 0; i < ess_num; i++) {
free(hisess_argv[i]);
}
}
if (ess_num > 0) {
}
goto done;
}
if (nprefer == 0) {
if (ess_num > 0) {
}
goto done;
}
}
for (i = 0; i < ess_num; i++) {
break;
}
}
}
}
done:
}
for (i = 0; i < ess_num; i++) {
}
return (selected);
}
static boolean_t
{
int i;
if (i == -1)
return (B_TRUE);
return (B_FALSE);
}
}
return (B_TRUE);
}
/*
* do_autoconf: First scan the wlanlist, and select one essid from scan result
* by the order in {preferrence} list. If no match, then heuristic_load;
*/
/*ARGSUSED*/
static boolean_t
{
if (argc > 0) {
*pequal++ = '\0';
} else {
}
} else {
forever = 1;
} else {
"invalid value %s for 'wait'\n"),
}
}
if (timeout == -1) {
forever = 1;
}
}
}
if (argc > 1) {
"useless tokens after '%s'\n"),
}
}
timeout--;
break;
(void) sleep(1);
}
return (B_TRUE);
}
if (argc > 0) {
}
if (argc > 0) {
}
return (ret);
}
/*
* do_startconf: almost the same as the do_autoconf, except that doesn't
* write file.
*/
/*ARGSUSED*/
static boolean_t
{
int i = 0, ael_num = 0;
return (B_TRUE);
}
if (p_wep_section != NULL) {
}
}
return (B_TRUE);
}
for (i = 0; i < ael_num; i++)
}
return (B_TRUE);
}
static char *
{
return (NULL);
}
sizeof (essid));
return (NULL);
}
if (activep_section == NULL)
return (NULL);
if (activeprofile == NULL)
return (NULL);
strlen("essid=")) == 0) {
}
strlen("bssid=")) == 0) {
}
}
return (p_section->section_id);
}
}
}
return (NULL);
}
static void
{
} else {
}
if (action == RECORD_ADD) {
} else if (action == RECORD_DEL) {
}
}
/*
* do_loadpf: load a profile, set related parameters both in wifi
* and in wifiwepkey, if network name is not exist in the
* configration files, then we clean all parameters and set essid only
*/
static boolean_t
{
int i = 0, ael_num = 0;
char *connect;
if (argc == 0) {
"profile name missing\n"), gExecName);
return (B_FALSE);
}
if (argc > 1) {
*pequal++ = '\0';
} else {
}
} else {
forever = 1;
} else {
"invalid value %s for 'wait'\n"),
}
}
if (timeout == -1) {
forever = 1;
}
}
}
if (argc > 2) {
"useless tokens after '%s'\n"),
}
}
if (p_wep_section != NULL) {
}
}
}
connect = "profile";
return (B_TRUE);
}
/*
* if there is no 'essid' item in argvnew, the profile
* name(argv[0]) is treated as essid.
*/
for (i = 0; i < ael_num; i++) {
== 0)
break;
}
if (i == ael_num)
for (i = 0; i < ael_num; i++)
/*
* set flag in {active_profile} so that showprofile knows
* which profile is active when more than one profiles are
* created for the same WLAN.
*/
} else {
connect = "essid";
}
/* record bssid in the profile */
return (B_TRUE);
}
"bssid=%02x:%02x:%02x:%02x:%02x:%02x",
}
return (B_TRUE);
}
(void) sleep(1);
timeout--;
}
return (B_FALSE);
}
/*
* if wepkey is set in the profile, display wepkey|n=*****
* when showprofile and getprofilewepkey.
* if wepkeyn is NULL, all the wepkeys will be display,
* otherwise, just display the matching one.
*/
static void
{
return;
*pequal = '\0';
(void) printf("\t%s=*****\n",
param);
return;
} else {
}
}
}
}
}
/*
* do_printpf: print each parameters of the profile, if no network name
* assigned, then print all profile saved in configration file.
*/
/*ARGSUSED*/
static boolean_t
{
int i;
/*
* if no profile name is inputted, all the profiles will be displayed.
*/
if (argc == 0) {
(void) printf("\t%s\n",
}
}
/*
* identify whether wepkey is set
* in the profile
*/
}
}
return (B_TRUE);
}
for (i = 0; i < argc; i++) {
(void) printf("\t%s\n",
}
}
/*
* identify whether wepkey is set
* in the profile
*/
}
} else {
gettext("%s: showprofile : "
"no such profile: '%s'\n"),
return (B_FALSE);
}
}
return (B_TRUE);
}
/*
* find_ae: Find an ae by its contents, return its pointer.
*/
static ae_t *
{
PRTDBG(("find_ae: arg= NULL or plist=NULL\n"));
return (NULL);
}
*pnext = '\0';
} else {
return (NULL);
}
return (pae);
}
}
return (NULL);
}
/*
* update_aelist: Update an aelist by arg, for example:
* there are an item with content"essid=ap7-2",
* update_aelist(0x..., "essid=myssid2") will update it as "essid=myssid2"
*/
static void
{
} else {
}
}
/*
* do_deletepf: delete a profile in configration files.
*/
/*ARGSUSED*/
static boolean_t
{
int i = 0;
char *section_id;
char *prefer;
if (argc <= 0) {
}
/*
* if a "all" is inputted, all the profiles will be deleted.
*/
/*
* remove the '[]' of the [section_id]
*/
B_FALSE);
continue;
}
}
return (B_TRUE);
}
if (gp_config_file != NULL) {
for (i = 0; i < argc; i++) {
== B_FALSE) {
== B_TRUE) {
(void) del_prefer(gp_config_file,
return (B_TRUE);
} else {
gettext("%s: deleteprofile"
": no such profile: '%s'\n"),
return (B_FALSE);
}
}
}
}
return (B_TRUE);
}
/*
* do_history: Print the list in {history} section.
*/
/*ARGSUSED*/
static boolean_t
{
int len;
if (argc > 0) {
"after 'history'\n"), gExecName);
}
PRTDBG(("no history section\n"));
return (B_FALSE);
}
/*
* If history section is empty, directly return.
*/
return (B_TRUE);
/*
* construct the output format in terms of the
* maxmium essid length
*/
gettext("%s: history : "
"data format error\n"),
return (B_FALSE);
}
*pcomma = '\0';
? maxessidlen:ulen);
}
}
nt = 4;
gettext("bssid\t\t encryption\tlast seen\n"));
"\tlast seen\n"));
} else {
}
/*
* output the contents of the history section.
*/
*pcomma = '\0';
/* display essid */
}
*pcomma = '\0';
/* display bssid */
}
*pcomma = '\0';
/* display wep */
}
/* display time stamp */
}
}
return (B_TRUE);
}
/*
* do_lsprefer: Print the list in {preferrence} section
*/
/*ARGSUSED*/
static boolean_t
{
int i = 0;
char *pbuf;
if (argc > 0) {
"after 'listprefer'\n"), gExecName);
}
}
}
}
return (B_TRUE);
} else {
PRTDBG(("no preference section\n"));
return (B_FALSE);
}
}
/*
* do_rmprefer: Remove an item in {preferrence} list
*/
/*ARGSUSED*/
static boolean_t
{
int i = 0;
if (argc <= 0) {
}
/*
* if a "all" is inputted, all the items in the preference
* list will be deleted.
*/
return (B_FALSE);
}
} else if (gp_config_file != NULL) {
for (i = 0; i < argc; i++) {
== B_FALSE) {
return (B_FALSE);
}
}
}
return (B_TRUE);
}
static boolean_t
{
int i;
goto exit0;
}
}
if ((i >= 1) && (i <= MAX_PREFERENCE_NUM))
return (ret);
}
/*
* do_setprefer: Set network preferrence
*/
/*ARGSUSED*/
static boolean_t
{
int rank = 0;
if (argc <= 0) {
}
if (argc == 1) {
rank = 1;
} else {
"should be an integer within 1-10\n"), gExecName);
return (B_FALSE);
}
}
}
static boolean_t
{
int i;
goto exit0;
}
}
if ((i >= 1) && (i <= MAX_NWEPKEYS))
return (ret);
}
static boolean_t
{
int i;
goto exit0;
}
}
if ((i >= 0) && (i <= MAX_CHANNEL_NUM))
return (ret);
}
static boolean_t
{
int i;
switch (length) {
case 10:
case 26:
for (i = 0; i < length; i++) {
goto exit0;
}
}
break;
case 5:
case 13:
break;
default:
break;
}
"wepkey should be:\n"
"\t 40bits: 5 char or 10 hex digits.\n"
"\t 128bits: 13 char or 26 hex digits.\n"),
}
return (ret);
}
/*
* get_valid_wepkey: get an valid wepkey from stdin
*/
static char *
{
int i = 0;
PRTDBG(("get_valid_wepkey()\n"));
/*
* Because we need to get single char from terminal, so we need to
* disable canonical mode and set buffer size to 1 tyte. And because
* wepkey should not be see by others, so we disable echo too.
*/
(void) tcgetattr(0, &stored_settings);
/* Set new terminal attributes */
(void) putchar('*');
}
(void) putchar('\n');
/* Restore terminal attributes */
if (buf[--i] != '\n') {
"exceeds 26 hex digits\n"), gExecName);
return (NULL);
}
/* Replace last char '\n' with '\0' */
buf[i] = '\0';
}
/*
* do_set_wepkey: Set parameters in wepkey, and call ioctl
*/
static boolean_t
{
int id = 0;
char i = 0;
unsigned int keytmp;
if (!check_authority(AUTH_WEP)) {
}
switch (length) {
case 10:
case 26:
for (i = 0; i < length / 2; i++) {
}
break;
case 5:
case 13:
break;
default:
PRTDBG(("do_set_wepkey: error pbuf size\n"));
"wepkey should be:\n"
"\t 40bits: 5 char or 10 hex digits.\n"
"\t 128bits: 13 char or 26 hex digits.\n"),
}
for (i = 0; i < MAX_NWEPKEYS; i++) {
}
} else {
"should be an integer within the range 1-4\n"), gExecName);
}
sizeof (wl_wep_key_tab_t)));
}
/*
* get the committed wepkey. the return form is like wepkey1=*****;
*/
/*ARGSUSED*/
static char *
{
int key;
int len;
"should be an integer within the range 1-4\n"), gExecName);
goto exit0;
}
wepkey = get_valid_wepkey();
goto exit0;
}
if (wepkey_confirm == NULL) {
goto exit0;
}
gettext("%s: wepkey: "
"two inputs are not identical\n"), gExecName);
goto exit0;
}
return (pbuf);
return (NULL);
}
/*
* do_wepkey: Get input from user, call do_set_wepkey
*/
/*ARGSUSED*/
static boolean_t
{
char *pbuf;
if (argc <= 0) {
}
if (argc > 1) {
"after 'setwepkey'\n"), gExecName);
}
return (B_TRUE);
}
return (B_FALSE);
}
/*ARGSUSED*/
static boolean_t
{
char *pbuf;
if (argc < 2) {
}
if (argc > 2) {
"after 'setprofwepkey'\n"), gExecName);
}
"no such profile: '%s'\n"),
return (B_FALSE);
}
argc--;
argv++;
return (B_FALSE);
return (B_TRUE);
}
/*
* do_wlanlist: Scan for wlanlist
*/
/*ARGSUSED*/
static boolean_t
{
if (argc > 0) {
"after 'scan'\n"), gExecName);
}
return (B_FALSE);
}
}
return (B_TRUE);
}
/*
* do_showstatus: show the basic status of the interface, including
* linkstauts, essid, encryption and signal strength.
*/
/*ARGSUSED*/
static boolean_t
{
if (argc > 0) {
"after 'showstatus'\n"), gExecName);
}
return (B_TRUE);
}
}
(void) printf("\tactive profile: %s\n",
}
}
}
if (signal < 4) {
(void) printf("\tsignal strength: weak(%d)\n",
signal);
(void) printf("\tsignal strength: medium(%d)\n",
signal);
} else {
(void) printf("\tsignal strength: strong(%d)\n",
signal);
}
}
return (B_TRUE);
}
/*
* do_restoredef: Ask driver for loading default parameters
*/
/*ARGSUSED*/
static boolean_t
{
if (argc > 0) {
"after 'restoredef'\n"), gExecName);
}
return (B_FALSE);
} else {
return (B_TRUE);
}
}
/*
* do_disconnect: disconnect from the current connectted network
*/
/*ARGSUSED*/
static boolean_t
{
if (argc > 0) {
"after 'disconnect'\n"), gExecName);
}
return (B_FALSE);
} else {
return (B_TRUE);
}
}
static boolean_t
{
/*
* a trick here: clean the active_profile flag
* in section{active_profile}
*/
essid.wl_essid_length = 0;
} else {
"essid exceeds 32 bytes\n"), gExecName);
}
}
}
static boolean_t
{
} else {
"bss(ap,infrastructure) ibss(ad-hoc) or auto\n"),
}
sizeof (wl_bss_type_t)));
}
static boolean_t
{
} else {
"createibss: yes or no\n"), gExecName);
}
sizeof (wl_create_ibss_t));
sizeof (wl_create_ibss_t)));
}
static boolean_t
{
"should be:\n"
"\t802.11a: 0-99\n"
"\t802.11b: 1-14\n"
"\t802.11g: 1-14\n"), gExecName);
}
sizeof (wl_phy_conf_t)));
}
/*
* is_rates_support: Querying driver about supported rates.
*/
static boolean_t
{
int rates_num = 0;
int i = 0, j = 0;
== B_TRUE) {
for (i = 0; i < num; i++) {
for (j = 0; j < rates_num; j++) {
->wl_rates_rates[j];
break;
}
}
if (j == rates_num) {
if (rates[i] == 11) {
gettext("%s: "
"rate 5.5M is not supported\n"),
} else {
gettext("%s: "
"rate %dM is not supported\n"),
}
return (B_FALSE);
}
}
return (B_TRUE);
}
return (B_FALSE);
}
/*
*
*/
static uint8_t
{
int i;
for (i = 0; i < WIFI_RATES_NUM; i++) {
break;
}
}
if (i == WIFI_RATES_NUM) {
}
return (ret);
}
/*
* get_rates: convert string value arg into uint8_t array,
* array length will be save into *len[i].
* for example:
* arg = "1,2,5.5,11"
* then after call, rates[] = {2,4,11,22} will be returned.
* and *len will equal to 4
*/
static uint8_t *
{
int i = 1, j = 0;
char *token;
char *pstart;
char *pstart_bak;
PRTDBG(("get_rates: empty rates string\n"));
return (NULL);
}
pstart_bak = pstart;
i++;
}
*len = i;
pstart = pstart_bak;
i = 1;
}
}
for (i = 0; i < *len; i++) {
for (j = 0; j < i; j++)
gettext("%s: rates duplicated\n"),
return (NULL);
}
}
return (rates);
}
static boolean_t
{
int i = 0;
}
for (i = 0; i < num; i++) {
= rates[i];
}
num*sizeof (char)));
}
static boolean_t
{
switch (arg[0]) {
case 'O':
case 'o':
break;
case 'M':
case 'm':
break;
case 'F':
case 'f':
break;
default:
break;
}
} else {
}
sizeof (wl_ps_mode_t)));
}
static boolean_t
{
/* Mark */
} else {
gettext("%s: authmode: "
"opensystem or shared_key\n"), gExecName);
}
sizeof (wl_authmode_t)));
}
static boolean_t
{
} else {
"none or wep\n"), gExecName);
}
sizeof (wl_encryption_t)));
}
static boolean_t
{
"should be an integer within the range 1-4\n"), gExecName);
}
sizeof (wl_wep_key_id_t)));
}
static boolean_t
{
} else {
}
}
/*
* print_gbuf: After each ioctl system call, gbuf will contain result, gbuf
* contents's format varies from each kind of ioctl system call.
*/
static void
{
int i = 0, j = 0;
char **ess_argv;
int len;
switch (index) {
case BSSID:
(void) printf("\tbssid: ");
== 0) {
(void) printf("none\n");
break;
}
== 0) {
(void) printf("none\n");
break;
}
for (i = 0; i < 5; i++)
break;
case ESSID:
->wl_essid_essid);
break;
case BSSTYPE:
switch (bsstype) {
case WL_BSS_BSS:
(void) printf("\tbsstype: bss(ap, infrastructure)\n");
break;
case WL_BSS_IBSS:
(void) printf("\tbsstype: ibss(ad-hoc)\n");
break;
case WL_BSS_ANY:
(void) printf("\tbsstype: auto\n");
break;
default:
gettext("%s: "
"invalid bsstype value\n"), gExecName);
}
break;
case CREATEIBSS:
switch (createibss) {
case B_TRUE:
(void) printf("\tcreateibss: yes\n");
break;
case B_FALSE:
(void) printf("\tcreateibss: no\n");
break;
default:
gettext("%s: "
"invalid createibss value\n"), gExecName);
}
break;
case CHANNEL:
switch (subtype) {
case WL_FHSS:
case WL_DSSS:
case WL_IRBASE:
case WL_HRDS:
case WL_ERP:
break;
case WL_OFDM:
break;
default:
"invalid subtype\n"), gExecName);
break;
}
break;
case RATES:
(void) printf("\trates: ");
for (i = 0; i < rates_num; i++) {
char rate;
->wl_rates_rates[i];
if (rate == WL_RATE_5_5M)
(void) printf("5.5");
else
if (i == (rates_num - 1))
(void) printf("\n");
else
(void) printf(",");
}
break;
case POWERMODE:
switch (ps_mode->wl_ps_mode) {
case WL_PM_AM:
(void) printf("\tpowermode: off\n");
break;
case WL_PM_MPS:
(void) printf("\tpowermode: mps\n");
break;
case WL_PM_FAST:
(void) printf("\tpowermode: fast\n");
break;
default:
gettext("%s: "
"invalid powermode value\n"), gExecName);
break;
}
break;
case AUTHMODE:
switch (authmode) {
case WL_OPENSYSTEM:
(void) printf("\tauthmode: opensystem\n");
break;
case WL_SHAREDKEY:
(void) printf("\tauthmode: shared_key\n");
break;
default:
gettext("%s: "
"invalid authmode value\n"), gExecName);
break;
}
break;
case ENCRYPTION:
switch (encryption) {
case WL_NOENCRYPTION:
(void) printf("\tencryption: none\n");
break;
case WL_ENC_WEP:
(void) printf("\tencryption: wep\n");
break;
default:
gettext("%s: "
"invalid encryption value\n"), gExecName);
break;
}
break;
case WEPKEYID:
break;
case SIGNAL:
break;
case RADIOON:
switch (radioon) {
case B_TRUE:
(void) printf("\tradio: on\n");
break;
case B_FALSE:
(void) printf("\tradio: off\n");
break;
default: /* Mark */
gettext("%s: "
"invalid radioon value\n"), gExecName);
}
break;
case LINKSTATUS:
switch (linkstatus) {
case WL_CONNECTED:
(void) printf("\tlinkstatus: connected\n");
break;
case WL_NOTCONNECTED:
(void) printf("\tlinkstatus: not connected\n");
break;
default: /* Mark */
gettext("%s: "
"invalid linkstatus value\n"), gExecName);
}
break;
case WLANLIST:
for (i = 0; i < ess_num; i++) {
->wl_ess_list_ess + i;
maxessidlen = (maxessidlen >
strlen(p_ess_conf[i]
strlen(p_ess_conf[i]
}
/*
* construct the output format.
*/
nt = 4;
ntstr);
gettext("bssid\t\t type\t\tencryption\tsignallevel\n"));
(void) printf("essid\t\t\t\tbssid\t\t type\t\t"
"encryption\tsignallevel\n");
} else {
}
for (i = 0; i < ess_num; i++) {
"%s%c%02x:%02x:%02x:%02x:%02x:%02x%c%s",
',',
(p_ess_conf[i]->wl_ess_conf_wepenabled ==
for (j = 0; j < 5; j++) {
->wl_ess_conf_bssid[j]));
}
->wl_ess_conf_bssid[j]));
if (p_ess_conf[i]->wl_ess_conf_bsstype ==
(void) printf("access point");
else
(void) printf("ad-hoc");
if (p_ess_conf[i]->wl_ess_conf_wepenabled ==
(void) printf("\twep\t");
else
(void) printf("\tnone\t");
}
for (i = 0; i < ess_num; i++) {
}
break;
default:
"invalid parameter type\n"), gExecName);
break;
}
}
/*
* do_get_xxx: will send ioctl to driver, then the driver will fill gbuf
* with related value. gbuf has a format of wldp_t structure.
*/
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
static boolean_t
{
}
/*
* param has two kinds of forms:
* 'wepkeyn=*****' (when equalflag == B_TRUE),
* 'wepkeyn' (when equalflag == B_FALSE)
*/
static boolean_t
{
return (B_TRUE);
return (B_TRUE);
else
return (B_FALSE);
}
/*
*/
static boolean_t
{
int i = 0, j = 0;
char *param;
char *pequal;
const char *wepkey;
for (i = 0; i < argc; i++) {
"invalid value '%s' for parameter "
return (B_FALSE);
}
continue;
}
"invalid argument '%s', use "
"parameter=value'\n"),
return (B_FALSE);
}
*pequal++ = '\0';
for (j = 0; j < N_GS_FUNC; j++) {
break;
}
}
if (j == N_GS_FUNC) {
"unrecognized parameter '%s'\n"),
return (B_FALSE);
}
B_FALSE) {
"invalid value '%s' for parameter '%s'\n"),
return (B_FALSE);
}
}
return (B_TRUE);
}
/*
* do_createprofile: Called when create a profile off-line.
*/
/*ARGSUSED*/
static boolean_t
{
int i = 0;
const char *profilename;
if (argc <= 0) {
}
/*
* When creating a profile, if the profile name is not specified,
* the essid is selected as the profile name. the paramters are
* saved into the section.
*/
argc--;
argv++;
}
for (i = 0; i < argc; i++) {
break;
}
}
if (i == argc) {
gettext("%s: "
"essid required when creating profile\n"),
goto exit0;
}
if (strlen(profilename) == 0) {
gettext("%s: "
"non-empty essid required\n"),
goto exit0;
}
/*
* 'all', '{preference}', '{history}', '{active_profile}'
* and any string with '[' as start and ']' as end should
* not be a profile name
*/
((profilename[0] == '[') &&
"'%s' is an invalid profile name\n"),
goto exit0;
}
gettext("%s: "
"profile '%s' already exists\n"),
goto exit1;
}
/*
* Save each parameters in the profile.
*/
return (B_FALSE);
}
/*ARGSUSED*/
static boolean_t
{
if (argc < 1) {
}
"profile '%s' doesn't exist\n"),
return (B_FALSE);
}
/*
* modify each parameters in the profile.
*/
argc--;
argv++;
}
/*ARGSUSED*/
static boolean_t
{
int i = 0, j = 0;
int flag;
if (argc < 1) {
}
"profile '%s' doesn't exist\n"),
goto exit0;
}
argc--;
argv++;
/*
* If no specific parameter typed, we print out all parameters
*/
if (argc == 0) {
}
}
goto exit0;
}
/*
* Match function with do_gs_func[] table, and print its result
*/
for (i = 0; i < argc; i++) {
flag = 0;
for (j = 0; j < N_GS_FUNC; j++) {
break;
}
j = WEPKEY;
argv[i]);
flag++;
break;
}
}
if (j == N_GS_FUNC) {
gettext("wificonifg: unrecognized parameter: "
"%s\n"), argv[i]);
goto exit0;
}
flag++;
}
}
if (!flag) {
"parameter '%s' has not been set in profile %s\n"),
goto exit0;
}
}
return (ret);
}
/*
* Verify whether the value in the parameter=value pair is valid or not.
* For the channel, since we donot know what kind of wifi card(a,b,or g)
* is in the system, so we just leave to verify the validity of the value
* when the value is set to the card.
* The same goes for the rates.
*/
static boolean_t
{
switch (item) {
case ESSID:
else
break;
case BSSTYPE:
else
break;
case CREATEIBSS:
else
break;
case AUTHMODE:
else
break;
case POWERMODE:
else
break;
case ENCRYPTION:
else
break;
case RADIOON:
else
break;
case WEPKEYID:
break;
case WEPKEY:
break;
case CHANNEL:
break;
case RATES:
} else {
}
break;
default:
break;
}
return (ret);
}
/*
* do_set: Called when set a parameter, the format should be
* parameter=value.
*/
static boolean_t
{
int i = 0, j = 0;
char *param;
char *pequal;
char *value;
if (argc <= 0) {
(void) do_print_support_params(fd);
goto exit0;
}
/*
* Set each parameters, if one failed, others behind it will
* not be set
*/
for (i = 0; i < argc; i++) {
/*
* Separate param and its value, if the user types "param=",
* then value will be set to "";if the user types "param",
* it is an error.
*/
*pequal = '\0';
} else {
gettext("%s: invalid setparam argument "
"'%s', use 'parameter=value'\n"),
goto exit0;
}
PRTDBG(("do_set: param = \"%s\", value = \"%s\"\n",
for (j = 0; j < N_GS_FUNC; j++) {
/*
* Match each parameters with do_gs_func table,
*/
break;
j = WEPKEY;
break;
}
}
if (j == N_GS_FUNC) {
gettext("%s: unrecognized parameter: "
goto exit0;
}
gettext("%s: parameter '%s' is read-only\n"),
goto exit0;
}
== B_TRUE) {
} else {
gettext("%s: "
"failed to set '%s' for "),
}
goto exit0;
}
}
return (ret);
}
static boolean_t
{
int i = 0, j = 0, n = 0;
/*
* If no specific parameter typed, we print out all parameters
*/
if (argc <= 0) {
for (i = 0; i < N_GS_FUNC; i++) {
== B_TRUE)) {
n++;
}
}
goto exit0;
}
/*
* Match function with do_gs_func[] table, and print its result
*/
for (i = 0; i < argc; i++) {
for (j = 0; j < N_GS_FUNC; j++) {
break;
}
j = WEPKEY;
break;
}
}
if (j == N_GS_FUNC) {
gettext("wificonifg: unrecognized parameter: "
"%s\n"), argv[i]);
goto exit0;
}
gettext("%s: parameter '%s' is write-only\n"),
goto exit0;
}
} else {
gettext("%s: "
"failed to read parameter '%s' : "),
}
}
return (ret);
}
/*
* Only one wificonfig is running at one time.
* The following wificonfig which tries to be run will return error,
* and the pid of the process will own the filelock will be printed out.
*/
static pid_t
{
if (fd0 < 0) {
}
gettext("%s: enter_filelock"));
}
"enter_filelock:filelock is owned "
}
return (getpid());
}
static void
{
" exit_filelock: %s\n"),
}
}
int
{
int i, ret;
int fd;
extern char *optarg;
extern int optind;
#ifdef DEBUG
(void) printf("Press RETURN to continue...\n");
(void) getchar();
}
#endif
ret = WIFI_EXIT_DEF;
(void) textdomain(TEXT_DOMAIN);
PRTDBG(("main: priviledge init error\n"));
"set priviledge to 'basic' error\n"),
goto exit0;
}
"set permitted priviledge: %s\n"),
goto exit0;
}
"set limit priviledge: %s\n"),
goto exit0;
}
"set inherit priviledge: %s\n"),
goto exit0;
}
"set effective priviledge: %s\n"),
goto exit0;
}
for (i = 0; i < argc; i++) {
}
switch (c) {
case 'i':
if (iflag) {
goto exit0;
}
iflag = 1;
break;
case 'R':
if (rflag) {
goto exit0;
}
rflag = 1;
break;
case '?':
default:
goto exit0;
}
}
if (argc <= 0) {
if (iname) {
goto exit0;
}
if (do_print_support_params(fddev) ==
ret = WIFI_EXIT_DEF;
else
goto exit1;
} else {
goto exit0;
}
}
for (i = 0; i < N_FUNC; i++) {
!check_authority(autht)) {
goto exit0;
}
if (do_func[i].b_fileonly)
fileonly++;
if (do_func[i].b_readonly)
readonly++;
break;
}
}
if (i == N_FUNC) {
goto exit0;
}
goto exit0;
}
"failed to find the default wifi interface;"
" -i option should be used to specify the "
"wifi interface\n"), gExecName);
goto exit0;
}
}
if (iname) {
goto exit0;
}
}
if (rflag) {
} else {
"%s", p_file_wifi);
"%s", p_file_wifiwepkey);
}
/*
* There is an occasion when more than one wificonfig processes
* which attempt to write the <wifi> and <wifiwepkey> files are
* running. We must be able to avoid this.
* We use file lock here to implement this.
*/
goto exit1;
}
if (gp_config_file == NULL) {
goto exit2;
}
if (gp_wepkey_file == NULL) {
goto exit2;
}
== B_TRUE) {
/*
* can not write file when startconfing
* during boot
*/
if (do_func[i].b_readonly)
ret = WIFI_EXIT_DEF;
else if ((fprint_config_file(gp_config_file,
file_wifiwepkey) != B_TRUE))
else
ret = WIFI_EXIT_DEF;
} else {
}
if (!readonly)
if (iname)
return (ret);
}
#ifdef DEBUG
static void
{
}
#endif