diff options
Diffstat (limited to 'package/broadcom-wl/src/wlc/wlc.c')
-rw-r--r-- | package/broadcom-wl/src/wlc/wlc.c | 1100 |
1 files changed, 0 insertions, 1100 deletions
diff --git a/package/broadcom-wl/src/wlc/wlc.c b/package/broadcom-wl/src/wlc/wlc.c deleted file mode 100644 index 5a51234..0000000 --- a/package/broadcom-wl/src/wlc/wlc.c +++ /dev/null @@ -1,1100 +0,0 @@ -/* - * wlc - Broadcom Wireless Driver Control Utility - * - * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <glob.h> -#include <ctype.h> - -#include <typedefs.h> -#include <wlutils.h> -#include <proto/802.11.h> - -#define VERSION "0.1" -#define BUFSIZE 8192 -#define PTABLE_MAGIC 0xbadc0ded -#define PTABLE_SLT1 1 -#define PTABLE_SLT2 2 -#define PTABLE_ACKW 3 -#define PTABLE_ADHM 4 -#define PTABLE_END 0xffffffff - -/* - * Copy each token in wordlist delimited by space into word - * Taken from Broadcom shutils.h - */ -#define foreach(word, wordlist, next) \ - for (next = &wordlist[strspn(wordlist, " ")], \ - strncpy(word, next, sizeof(word)), \ - word[strcspn(word, " ")] = '\0', \ - word[sizeof(word) - 1] = '\0', \ - next = strchr(next, ' '); \ - strlen(word); \ - next = next ? &next[strspn(next, " ")] : "", \ - strncpy(word, next, sizeof(word)), \ - word[strcspn(word, " ")] = '\0', \ - word[sizeof(word) - 1] = '\0', \ - next = strchr(next, ' ')) - -static char wlbuf[8192]; -static char interface[16] = "wl0"; -static unsigned long kmem_offset = 0; -static int vif = 0, debug = 1, fromstdin = 0; - -typedef enum { - NONE = 0x00, - - /* types */ - PARAM_TYPE = 0x00f, - INT = 0x001, - STRING = 0x002, - MAC = 0x003, - - /* options */ - PARAM_OPTIONS = 0x0f0, - NOARG = 0x010, - - /* modes */ - PARAM_MODE = 0xf00, - GET = 0x100, - SET = 0x200, -} wlc_param; - -struct wlc_call { - const char *name; - wlc_param param; - int (*handler)(wlc_param param, void *data, void *value); - union { - int num; - char *str; - void *ptr; - } data; - const char *desc; -}; - -/* can't use the system include because of the stupid broadcom header files */ -extern struct ether_addr *ether_aton(const char *asc); -static inline int my_ether_ntoa(unsigned char *ea, char *buf) -{ - return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", - ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); -} - -static int wlc_ioctl(wlc_param param, void *data, void *value) -{ - unsigned int *var = ((unsigned int *) data); - unsigned int ioc = *var; - - if (param & NOARG) { - return wl_ioctl(interface, ioc, NULL, 0); - } - switch(param & PARAM_TYPE) { - case MAC: - return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, 6); - case INT: - return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, sizeof(int)); - case STRING: - return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, BUFSIZE); - } - return 0; -} - -static int wlc_iovar(wlc_param param, void *data, void *value) -{ - int *val = (int *) value; - char *iov = *((char **) data); - int ret = 0; - - if (param & SET) { - switch(param & PARAM_TYPE) { - case INT: - ret = wl_iovar_setint(interface, iov, *val); - break; - case MAC: - ret = wl_iovar_set(interface, iov, value, 6); - break; - } - } - if (param & GET) { - switch(param & PARAM_TYPE) { - case INT: - ret = wl_iovar_getint(interface, iov, val); - break; - case MAC: - ret = wl_iovar_get(interface, iov, value, 6); - break; - } - } - - return ret; -} - -static int wlc_bssiovar(wlc_param param, void *data, void *value) -{ - int *val = (int *) value; - char *iov = *((char **) data); - int ret = 0; - - if (param & SET) { - switch(param & PARAM_TYPE) { - case INT: - ret = wl_bssiovar_setint(interface, iov, vif, *val); - } - } - if (param & GET) { - switch(param & PARAM_TYPE) { - case INT: - ret = wl_bssiovar_getint(interface, iov, vif, val); - } - } - - return ret; -} - -static int wlc_vif_enabled(wlc_param param, void *data, void *value) -{ - int *val = (int *) value; - int buf[3]; - int ret = 0; - - sprintf((char *) buf, "bss"); - buf[1] = vif; - if (param & SET) { - buf[2] = (*val ? 1 : 0); - ret = wl_ioctl(interface, WLC_SET_VAR, buf, sizeof(buf)); - } else if (param & GET) { - ret = wl_ioctl(interface, WLC_GET_VAR, buf, sizeof(buf)); - *val = buf[0]; - } - - return ret; -} - -static int wlc_ssid(wlc_param param, void *data, void *value) -{ - int ret = -1, ret2 = -1; - char *dest = (char *) value; - wlc_ssid_t ssid; - - if ((param & PARAM_MODE) == GET) { - ret = wl_bssiovar_get(interface, "ssid", vif, &ssid, sizeof(ssid)); - - if (ret) - /* if we can't get the ssid through the bssiovar, try WLC_GET_SSID */ - ret = wl_ioctl(interface, WLC_GET_SSID, &ssid, sizeof(ssid)); - - if (!ret) { - memcpy(dest, ssid.SSID, ssid.SSID_len); - dest[ssid.SSID_len] = 0; - } - } else if ((param & PARAM_MODE) == SET) { - strncpy(ssid.SSID, value, 32); - ssid.SSID_len = strlen(value); - - if (ssid.SSID_len > 32) - ssid.SSID_len = 32; - - if (vif == 0) { - /* for the main interface, also try the WLC_SET_SSID call */ - ret2 = wl_ioctl(interface, WLC_SET_SSID, &ssid, sizeof(ssid)); - } - - ret = wl_bssiovar_set(interface, "ssid", vif, &ssid, sizeof(ssid)); - ret = (!ret2 ? 0 : ret); - } - - return ret; -} - -static int wlc_int(wlc_param param, void *data, void *value) -{ - int *var = *((int **) data); - int *val = (int *) value; - - if ((param & PARAM_MODE) == SET) { - *var = *val; - } else if ((param & PARAM_MODE) == GET) { - *val = *var; - } - - return 0; -} - -static int wlc_flag(wlc_param param, void *data, void *value) -{ - int *var = *((int **) data); - - *var = 1; - - return 0; -} - -static int wlc_string(wlc_param param, void *data, void *value) -{ - char *var = *((char **) data); - - if ((param & PARAM_MODE) == GET) { - strcpy(value, var); - } - - return 0; -} - -static int wlc_afterburner(wlc_param param, void *data, void *value) -{ - int *val = (int *) value; - int ret = 0; - - if ((param & PARAM_MODE) == GET) { - ret = wl_iovar_getint(interface, "afterburner", val); - } else { - wl_iovar_setint(interface, "wlfeatureflag", (*val ? 3 : 0)); - ret = wl_iovar_setint(interface, "afterburner", (*val ? 1 : 0)); - wl_iovar_setint(interface, "afterburner_override", *val); - } - - return ret; -} - -static int wlc_maclist(wlc_param param, void *data, void *value) -{ - unsigned int *var = ((unsigned int *) data); - unsigned int ioc = *var; - int limit = (sizeof(wlbuf) - 4) / sizeof(struct ether_addr); - struct maclist *list = (struct maclist *) wlbuf; - char *str = (char *) value; - char astr[30], *p; - struct ether_addr *addr; - int isset = 0; - int ret; - - if ((param & PARAM_MODE) == GET) { - list->count = limit; - ret = wl_ioctl(interface, (ioc >> 16) & 0xffff, wlbuf, sizeof(wlbuf)); - - if (!ret) - while (list->count) { - str += sprintf(str, "%s", ((((char *) value) == str) ? "" : " ")); - str += my_ether_ntoa((unsigned char *) &list->ea[list->count-- - 1], str); - } - - return ret; - } else { - while (*str && isspace(*str)) - *str++; - - if (*str == '+') { - str++; - - list->count = limit; - if (wl_ioctl(interface, (ioc >> 16) & 0xffff, wlbuf, sizeof(wlbuf)) == 0) - isset = 1; - - while (*str && isspace(*str)) - str++; - } - - if (!isset) - memset(wlbuf, 0, sizeof(wlbuf)); - - foreach(astr, str, p) { - if (list->count >= limit) - break; - - if ((addr = ether_aton(astr)) != NULL) - memcpy(&list->ea[list->count++], addr, sizeof(struct ether_addr)); - } - - return wl_ioctl(interface, ioc & 0xffff, wlbuf, sizeof(wlbuf)); - } -} - -static int wlc_radio(wlc_param param, void *data, void *value) -{ - int *val = (int *) value; - int ret; - - if ((param & PARAM_MODE) == GET) { - ret = wl_ioctl(interface, WLC_GET_RADIO, val, sizeof(int)); - *val = ((*val & 1) ? 0 : 1); - } else { - *val = (1 << 16) | (*val ? 0 : 1); - ret = wl_ioctl(interface, WLC_SET_RADIO, val, sizeof(int)); - } - - return ret; -} - -static int wlc_wsec_key(wlc_param param, void *null, void *value) -{ - wl_wsec_key_t wsec_key; - unsigned char *index = value; - unsigned char *key; - unsigned char *data; - unsigned char hex[3]; - - if ((param & PARAM_MODE) != SET) - return 0; - - memset(&wsec_key, 0, sizeof(wsec_key)); - if (index[0] == '=') { - wsec_key.flags = WL_PRIMARY_KEY; - index++; - } - - if ((index[0] < '1') || (index[0] > '4') || (index[1] != ',')) - return -1; - - key = index + 2; - if (strncmp(key, "d:", 2) == 0) { /* delete key */ - } else if (strncmp(key, "s:", 2) == 0) { /* ascii key */ - key += 2; - wsec_key.len = strlen(key); - - if ((wsec_key.len != 5) && (wsec_key.len != 13)) - return -1; - - strcpy(wsec_key.data, key); - } else { /* hex key */ - wsec_key.len = strlen(key); - if ((wsec_key.len != 10) && (wsec_key.len != 26)) - return -1; - - wsec_key.len /= 2; - data = wsec_key.data; - hex[2] = 0; - do { - hex[0] = *(key++); - hex[1] = *(key++); - *(data++) = (unsigned char) strtoul(hex, NULL, 16); - } while (*key != 0); - } - - return wl_bssiovar_set(interface, "wsec_key", vif, &wsec_key, sizeof(wsec_key)); -} - -static inline int cw2ecw(int cw) -{ - int i; - for (cw++, i = 0; cw; i++) cw >>=1; - return i - 1; -} - -static int wlc_wme_ac(wlc_param param, void *data, void *value) -{ - char *type = *((char **) data); - char *settings = (char *) value; - char cmd[100], *p, *val; - edcf_acparam_t params[AC_COUNT]; - int ret; - int intval; - int cur = -1; - char *buf = wlbuf; - - if ((param & PARAM_MODE) != SET) - return -1; - - memset(params, 0, sizeof(params)); - ret = wl_iovar_get(interface, type, params, sizeof(params)); - memset(buf, 0, BUFSIZE); - strcpy(buf, type); - buf += strlen(buf) + 1; - - foreach(cmd, settings, p) { - val = strchr(cmd, '='); - if (val == NULL) { - if (strcmp(cmd, "be") == 0) - cur = AC_BE; - else if (strcmp(cmd, "bk") == 0) - cur = AC_BK; - else if (strcmp(cmd, "vi") == 0) - cur = AC_VI; - else if (strcmp(cmd, "vo") == 0) - cur = AC_VO; - else - return -1; - - /* just in case */ - params[cur].ACI = (params[cur].ACI & (0x3 << 5)) | (cur << 5); - } else { - *(val++) = 0; - - intval = strtoul(val, NULL, 10); - if (strcmp(cmd, "cwmin") == 0) - params[cur].ECW = (params[cur].ECW & ~(0xf)) | cw2ecw(intval); - else if (strcmp(cmd, "ecwmin") == 0) - params[cur].ECW = (params[cur].ECW & ~(0xf)) | (intval & 0xf); - else if (strcmp(cmd, "cwmax") == 0) - params[cur].ECW = (params[cur].ECW & ~(0xf << 4)) | (cw2ecw(intval) << 4); - else if (strcmp(cmd, "ecwmax") == 0) - params[cur].ECW = (params[cur].ECW & ~(0xf << 4)) | ((intval & 0xf) << 4); - else if (strcmp(cmd, "aifsn") == 0) - params[cur].ACI = (params[cur].ACI & ~(0xf)) | (intval & 0xf); - else if (strcmp(cmd, "txop") == 0) - params[cur].TXOP = intval >> 5; - else if (strcmp(cmd, "force") == 0) - params[cur].ACI = (params[cur].ACI & ~(1 << 4)) | ((intval) ? (1 << 4) : 0); - else return -1; - - memcpy(buf, ¶ms[cur], sizeof(edcf_acparam_t)); - wl_ioctl(interface, WLC_SET_VAR, wlbuf, BUFSIZE); - } - } - return ret; -} - -static int wlc_ifname(wlc_param param, void *data, void *value) -{ - char *val = (char *) value; - int ret = 0; - - if (param & SET) { - if (strlen(val) < 16) - strcpy(interface, val); - else ret = -1; - } - if (param & GET) { - strcpy(val, interface); - } - - return ret; -} - -static int wlc_wdsmac(wlc_param param, void *data, void *value) -{ - unsigned char mac[6]; - int ret = 0; - - ret = wl_ioctl(interface, WLC_WDS_GET_REMOTE_HWADDR, &mac, 6); - if (ret == 0) - my_ether_ntoa(mac, value); - - return ret; -} - -static int wlc_pmk(wlc_param param, void *data, void *value) -{ - int ret = -1; - char *str = (char *) value; - wsec_pmk_t pmk; - - /* driver doesn't support GET */ - - if ((param & PARAM_MODE) == SET) { - strncpy(pmk.key, value, WSEC_MAX_PSK_LEN); - pmk.key_len = strlen(value); - - if (pmk.key_len > WSEC_MAX_PSK_LEN) - pmk.key_len = WSEC_MAX_PSK_LEN; - - pmk.flags = WSEC_PASSPHRASE; - - ret = wl_ioctl(interface, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk)); - } - - return ret; -} - -static const struct wlc_call wlc_calls[] = { - { - .name = "version", - .param = STRING|NOARG, - .handler = wlc_string, - .data.str = VERSION, - .desc = "Version of this program" - }, - { - .name = "debug", - .param = INT, - .handler = wlc_int, - .data.ptr = &debug, - .desc = "wlc debug level" - }, - { - .name = "stdin", - .param = NOARG, - .handler = wlc_flag, - .data.ptr = &fromstdin, - .desc = "Accept input from stdin" - }, - { - .name = "ifname", - .param = STRING, - .handler = wlc_ifname, - .desc = "interface to send commands to" - }, - { - .name = "up", - .param = NOARG, - .handler = wlc_ioctl, - .data.num = WLC_UP, - .desc = "Bring the interface up" - }, - { - .name = "down", - .param = NOARG, - .handler = wlc_ioctl, - .data.num = WLC_DOWN, - .desc = "Bring the interface down" - }, - { - .name = "radio", - .param = INT, - .handler = wlc_radio, - .desc = "Radio enabled flag" - }, - { - .name = "ap", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_AP << 16) | WLC_SET_AP), - .desc = "Access Point mode" - }, - { - .name = "mssid", - .param = INT, - .handler = wlc_iovar, - .data.str = "mbss", - .desc = "Multi-ssid mode" - }, - { - .name = "apsta", - .param = INT, - .handler = wlc_iovar, - .data.str = "apsta", - .desc = "AP+STA mode" - }, - { - .name = "infra", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_INFRA << 16) | WLC_SET_INFRA), - .desc = "Infrastructure mode" - }, - { - .name = "wet", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_WET << 16) | WLC_SET_WET), - .desc = "Wireless repeater mode", - }, - { - .name = "statimeout", - .param = INT, - .handler = wlc_iovar, - .data.str = "sta_retry_time", - .desc = "STA connection timeout" - }, - { - .name = "country", - .param = STRING, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_COUNTRY << 16) | WLC_SET_COUNTRY), - .desc = "Country code" - }, - { - .name = "channel", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_CHANNEL << 16) | WLC_SET_CHANNEL), - .desc = "Channel", - }, - { - .name = "vlan_mode", - .param = INT, - .handler = wlc_bssiovar, - .data.str = "vlan_mode", - .desc = "Parse 802.1Q tags", - }, - { - .name = "vif", - .param = INT, - .handler = wlc_int, - .data.ptr = &vif, - .desc = "Current vif index" - }, - { - .name = "enabled", - .param = INT, - .handler = wlc_vif_enabled, - .desc = "vif enabled flag" - }, - { - .name = "ssid", - .param = STRING, - .handler = wlc_ssid, - .desc = "Interface ESSID" - }, - { - .name = "closed", - .param = INT, - .handler = wlc_bssiovar, - .data.str = "closednet", - .desc = "Hidden ESSID flag" - }, - { - .name = "wsec", - .param = INT, - .handler = wlc_bssiovar, - .data.str = "wsec", - .desc = "Security mode flags" - }, - { - .name = "wepkey", - .param = STRING, - .handler = wlc_wsec_key, - .desc = "Set/Remove WEP keys" - }, - { - .name = "wepauth", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_AUTH << 16) | WLC_SET_AUTH), - .desc = "WEP authentication type. 0 = OpenSystem, 1 = SharedKey" - }, - { - .name = "wsec_restrict", - .param = INT, - .handler = wlc_bssiovar, - .data.str = "wsec_restrict", - .desc = "Drop unencrypted traffic" - }, - { - .name = "eap_restrict", - .param = INT, - .handler = wlc_bssiovar, - .data.str = "eap_restrict", - .desc = "Only allow 802.1X traffic until 802.1X authorized" - }, - { - .name = "wpa_auth", - .param = INT, - .handler = wlc_bssiovar, - .data.str = "wpa_auth", - .desc = "WPA authentication modes" - }, - { - .name = "ap_isolate", - .param = INT, - .handler = wlc_bssiovar, - .data.str = "ap_isolate", - .desc = "Isolate connected clients" - }, - { - .name = "supplicant", - .param = INT, - .handler = wlc_iovar, - .data.str = "sup_wpa", - .desc = "Built-in WPA supplicant" - }, - { - .name = "passphrase", - .param = STRING, - .handler = wlc_pmk, - .desc = "Passphrase for built-in WPA supplicant", - }, - { - .name = "maxassoc", - .param = INT, - .handler = wlc_iovar, - .data.str = "maxassoc", - .desc = "Max. number of associated clients", - }, - { - .name = "wme", - .param = INT, - .handler = wlc_iovar, - .data.str = "wme", - .desc = "WME enabled" - }, - { - .name = "wme_ac_ap", - .param = STRING, - .handler = wlc_wme_ac, - .data.str = "wme_ac_ap", - .desc = "Set WME AC options for AP mode", - }, - { - .name = "wme_ac_sta", - .param = STRING, - .handler = wlc_wme_ac, - .data.str = "wme_ac_sta", - .desc = "Set WME AC options for STA mode", - }, - { - .name = "wme_noack", - .param = INT, - .handler = wlc_iovar, - .data.str = "wme_noack", - .desc = "WME ACK disable request", - }, - { - .name = "802.11d", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_REGULATORY << 16) | WLC_SET_REGULATORY), - .desc = "Enable/disable 802.11d regulatory management", - }, - { - .name = "802.11h", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_SPECT_MANAGMENT << 16) | WLC_SET_SPECT_MANAGMENT), - .desc = "Enable/disable 802.11h spectrum management", - }, - { - .name = "fragthresh", - .param = INT, - .handler = wlc_iovar, - .data.str = "fragthresh", - .desc = "Fragmentation threshold", - }, - { - .name = "rtsthresh", - .param = INT, - .handler = wlc_iovar, - .data.str = "rtsthresh", - .desc = "RTS threshold" - }, - { - .name = "slottime", - .param = INT, - .handler = wlc_iovar, - .data.str = "acktiming", - .desc = "Slot time" - }, - { - .name = "rxant", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_ANTDIV << 16) | WLC_SET_ANTDIV), - .desc = "Rx antenna selection" - }, - { - .name = "txant", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_TXANT << 16) | WLC_SET_TXANT), - .desc = "Tx antenna selection" - }, - { - .name = "dtim", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_DTIMPRD << 16) | WLC_SET_DTIMPRD), - .desc = "DTIM period", - }, - { - .name = "bcn", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_BCNPRD << 16) | WLC_SET_BCNPRD), - .desc = "Beacon interval" - }, - { - .name = "frameburst", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_FAKEFRAG << 16) | WLC_SET_FAKEFRAG), - .desc = "Framebursting" - }, - { - .name = "monitor", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_MONITOR << 16) | WLC_SET_MONITOR), - .desc = "Monitor mode" - }, - { - .name = "passive", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_PASSIVE << 16) | WLC_SET_PASSIVE), - .desc = "Passive mode" - }, - { - .name = "macfilter", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_MACMODE << 16) | WLC_SET_MACMODE), - .desc = "MAC filter mode (0:disabled, 1:deny, 2:allow)" - }, - { - .name = "maclist", - .param = STRING, - .data.num = ((WLC_GET_MACLIST << 16) | WLC_SET_MACLIST), - .handler = wlc_maclist, - .desc = "MAC filter list" - }, - { - .name = "autowds", - .param = INT, - .handler = wlc_ioctl, - .data.num = ((WLC_GET_LAZYWDS << 16) | WLC_SET_LAZYWDS), - .desc = "Automatic WDS" - }, - { - .name = "wds", - .param = STRING, - .data.num = ((WLC_GET_WDSLIST << 16) | WLC_SET_WDSLIST), - .handler = wlc_maclist, - .desc = "WDS connection list" - }, - { - .name = "wdstimeout", - .param = INT, - .handler = wlc_iovar, - .data.str = "wdstimeout", - .desc = "WDS link detection timeout" - }, - { - .name = "wdsmac", - .param = STRING|NOARG, - .handler = wlc_wdsmac, - .desc = "MAC of the remote WDS endpoint (only with wds0.* interfaces)" - }, - { - .name = "afterburner", - .param = INT, - .handler = wlc_afterburner, - .desc = "Broadcom Afterburner" - }, - { - .name = "join_once", - .param = INT, - .handler = wlc_iovar, - .data.str = "IBSS_join_once", - .desc = "Prevent unwanted IBSS merges" - }, - { - .name = "bssid", - .param = MAC, - .handler = wlc_iovar, - .data.str = "cur_etheraddr", - .desc = "BSSID" - }, - { - .name = "default_bssid", - .param = MAC, - .handler = wlc_iovar, - .data.str = "perm_etheraddr", - .desc = "Default BSSID (read-only)" - }, - { - .name = "allow_mode", - .param = INT, - .data.num = ((WLC_GET_ALLOW_MODE << 16) | WLC_SET_ALLOW_MODE), - .handler = wlc_ioctl, - .desc = "STA/IBSS assoc mode" - }, - { - .name = "des_bssid", - .param = MAC, - .data.num = ((WLC_GET_DESIRED_BSSID << 16) | WLC_SET_DESIRED_BSSID), - .handler = wlc_ioctl, - .desc = "Desired BSSID" - }, - { - .name = "assoclist", - .param = STRING, - .data.num = (WLC_GET_ASSOCLIST << 16), - .handler = wlc_maclist, - .desc = "MACs of associated stations" - }, - { - .name = "gmode", - .param = INT, - .data.num = ((WLC_GET_GMODE << 16) | WLC_SET_GMODE), - .handler = wlc_ioctl, - .desc = "G Mode" - }, -}; -#define wlc_calls_size (sizeof(wlc_calls) / sizeof(struct wlc_call)) - -static void usage(char *cmd) -{ - int i; - fprintf(stderr, "Usage: %s <command> [<argument> ...]\n" - "\n" - "Available commands:\n", cmd); - for (i = 0; i < wlc_calls_size; i++) { - fprintf(stderr, "\t%-16s\t%s\n", wlc_calls[i].name ?: "", wlc_calls[i].desc ?: ""); - } - fprintf(stderr, "\n"); - exit(1); -} - -static int do_command(const struct wlc_call *cmd, char *arg) -{ - static char buf[BUFSIZE]; - int set; - int ret = 0; - char *format, *end; - int intval; - void *ptr = (void *) buf; - - if (debug >= 10) { - fprintf(stderr, "do_command %-16s\t'%s'\n", cmd->name, arg); - } - - if ((arg == NULL) && ((cmd->param & PARAM_TYPE) != NONE)) { - set = 0; - ret = cmd->handler(cmd->param | GET, (void *) &cmd->data, (void *) buf); - if (ret == 0) { - switch(cmd->param & PARAM_TYPE) { - case INT: - intval = *((int *) buf); - - if (intval > 65535) - format = "0x%08x\n"; - else if (intval > 255) - format = "0x%04x\n"; - else - format = "%d\n"; - - fprintf(stdout, format, intval); - break; - case STRING: - fprintf(stdout, "%s\n", buf); - break; - case MAC: - my_ether_ntoa(buf, buf + 6); - fprintf(stdout, "%s\n", buf + 6); - break; - } - } - } else { /* SET */ - set = 1; - switch(cmd->param & PARAM_TYPE) { - case INT: - intval = strtoul(arg, &end, 10); - if (end && !(*end)) { - memcpy(buf, &intval, sizeof(intval)); - } else { - fprintf(stderr, "%s: Invalid argument\n", cmd->name); - return -1; - } - break; - case STRING: - strncpy(buf, arg, BUFSIZE); - buf[BUFSIZE - 1] = 0; - break; - case MAC: - ptr = ether_aton(arg); - if (!ptr) { - fprintf(stderr, "%s: Invalid mac address '%s'\n", cmd->name, arg); - return -1; - } - break; - } - - ret = cmd->handler(cmd->param | SET, (void *) &cmd->data, ptr); - } - - if ((debug > 0) && (ret != 0)) - fprintf(stderr, "Command '%s %s' failed: %d\n", (set == 1 ? "set" : "get"), cmd->name, ret); - - return ret; -} - -static struct wlc_call *find_cmd(char *name) -{ - int found = 0, i = 0; - - while (!found && (i < wlc_calls_size)) { - if (strcmp(name, wlc_calls[i].name) == 0) - found = 1; - else - i++; - } - - return (struct wlc_call *) (found ? &wlc_calls[i] : NULL); -} - -int main(int argc, char **argv) -{ - static char buf[BUFSIZE]; - char *s, *s2; - char *cmd = argv[0]; - struct wlc_call *call; - int ret = 0; - - if (argc < 2) - usage(argv[0]); - - for(interface[2] = '0'; (interface[2] < '3') && (wl_probe(interface) != 0); interface[2]++); - if (interface[2] == '3') { - fprintf(stderr, "No Broadcom wl interface found!\n"); - return -1; - } - - argv++; - argc--; - while ((argc > 0) && (argv[0] != NULL)) { - if ((call = find_cmd(argv[0])) == NULL) { - fprintf(stderr, "Invalid command: %s\n\n", argv[0]); - usage(cmd); - } - if ((argc > 1) && (!(call->param & NOARG))) { - ret = do_command(call, argv[1]); - argv += 2; - argc -= 2; - } else { - ret = do_command(call, NULL); - argv++; - argc--; - } - } - - while (fromstdin && !feof(stdin)) { - *buf = 0; - fgets(buf, BUFSIZE - 1, stdin); - - if (*buf == 0) - continue; - - if ((s = strchr(buf, '\r')) != NULL) - *s = 0; - if ((s = strchr(buf, '\n')) != NULL) - *s = 0; - - s = buf; - while (isspace(*s)) - s++; - - if (!*s) - continue; - - if ((s2 = strchr(buf, ' ')) != NULL) - *(s2++) = 0; - - while (s2 && isspace(*s2)) - s2++; - - if ((call = find_cmd(buf)) == NULL) { - fprintf(stderr, "Invalid command: %s\n", buf); - ret = -1; - } else - ret = do_command(call, ((call->param & NOARG) ? NULL : s2)); - } - - return ret; -} |