blob: 11f501619fd06278df4bc7917fcab05241f02aa5 [file] [log] [blame]
/*
* wl ap command module
*
* Broadcom Proprietary and Confidential. Copyright (C) 2017,
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
* the contents of this file may not be disclosed to third parties, copied
* or duplicated in any form, in whole or in part, without the prior
* written permission of Broadcom.
*
*
* <<Broadcom-WL-IPTag/Proprietary:>>
*
* $Id: wluc_ap.c 458728 2014-02-27 18:15:25Z $
*/
#ifdef WIN32
#include <windows.h>
#endif
#include <wlioctl.h>
#if defined(DONGLEBUILD)
#include <typedefs.h>
#include <osl.h>
#endif
/* Because IL_BIGENDIAN was removed there are few warnings that need
* to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
* Hence these warnings were not seen earlier.
* For now ignore the following warnings
*/
#ifdef WIN32
#pragma warning(push)
#pragma warning(disable : 4244)
#pragma warning(disable : 4761)
#endif
#include <bcmutils.h>
#include <bcmendian.h>
#include "wlu_common.h"
#include "wlu.h"
static cmd_func_t wl_maclist_1;
static cmd_func_t wl_management_info;
static cmd_func_t wl_bsscfg_enable;
static cmd_func_t wl_radar;
static cmd_t wl_ap_cmds[] = {
{ "ap", wl_int, WLC_GET_AP, WLC_SET_AP,
"Set AP mode: 0 (STA) or 1 (AP)" },
{ "tkip_countermeasures", wl_int, -1, WLC_TKIP_COUNTERMEASURES,
"Enable or disable TKIP countermeasures (TKIP-enabled AP only)\n"
"\t0 - disable\n"
"\t1 - enable" },
{ "shortslot_restrict", wl_int, WLC_GET_SHORTSLOT_RESTRICT, WLC_SET_SHORTSLOT_RESTRICT,
"Get/Set AP Restriction on associations for 11g Short Slot Timing capable STAs.\n"
"\t0 - Do not restrict association based on ShortSlot capability\n"
"\t1 - Restrict association to STAs with ShortSlot capability" },
{ "ignore_bcns", wl_int, WLC_GET_IGNORE_BCNS, WLC_SET_IGNORE_BCNS,
"AP only (G mode): Check for beacons without NONERP element"
"(0=Examine beacons, 1=Ignore beacons)" },
{ "scb_timeout", wl_int, WLC_GET_SCB_TIMEOUT, WLC_SET_SCB_TIMEOUT,
"AP only: inactivity timeout value for authenticated stas" },
{ "assoclist", wl_maclist, WLC_GET_ASSOCLIST, -1,
"AP only: Get the list of associated MAC addresses."},
{ "radar", wl_radar, WLC_GET_RADAR, WLC_SET_RADAR,
"Enable/Disable radar. One-shot Radar simulation with optional sub-band"},
{ "authe_sta_list", wl_maclist_1, WLC_GET_VAR, -1,
"Get authenticated sta mac address list"},
{ "autho_sta_list", wl_maclist_1, WLC_GET_VAR, -1,
"Get authorized sta mac address list"},
{ "beacon_info", wl_management_info, WLC_GET_VAR, -1,
"Returns the 802.11 management frame beacon information\n"
"Usage: wl beacon_info [-f file] [-r]\n"
"\t-f Write beacon data to file\n"
"\t-r Raw hex dump of beacon data" },
{ "probe_resp_info", wl_management_info, WLC_GET_VAR, -1,
"Returns the 802.11 management frame probe response information\n"
"Usage: wl probe_resp_info [-f file] [-r]\n"
"\t-f Write probe response data to file\n"
"\t-r Raw hex dump of probe response data" },
{ "bss", wl_bsscfg_enable, WLC_GET_VAR, WLC_SET_VAR,
"set/get BSS enabled status: up/down"},
{ "closednet", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
"set/get BSS closed network attribute"},
{ "ap_isolate", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
"set/get AP isolation"},
{ "mode_reqd", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
"Set/Get operational capabilities required for STA to associate to the BSS "
"supported by the interface.\n"
"\tUsage: wl [-i ifname] mode_reqd [value]\n"
"\t wl mode_reqd [-C bss_idx ] [value]\n"
"\t\t <ifname> is the name of the interface corresponding to the BSS.\n"
"\t\t\t If the <ifname> is not given, the primary BSS is assumed.\n"
"\t\t <bss_idx> is the the BSS configuration index.\n"
"\t\t\t If the <bss_idx> is not given, configuraion #0 is assumed\n"
"\t\t <value> is the numeric values in the range [0..3]\n"
"\t\t 0 - no requirements on joining devices.\n"
"\t\t 1 - devices must advertise ERP (11g) capabilities to be allowed to associate\n"
"\t\t\t to a 2.4 GHz BSS.\n"
"\t\t 2 - devices must advertise HT (11n) capabilities to be allowed to associate\n"
"\t\t\t to a BSS.\n"
"\t\t 3 - devices must advertise VHT (11ac) capabilities to be allowed to associate\n"
"\t\t\t to a BSS.\n"
"\tThe command returns an error if the BSS interface is up.\n"
"\tThis configuration can only be changed while the BSS interface is down.\n"
"\tNote that support for HT implies support for ERP,\n"
"\tand support for VHT implies support for HT."},
{ NULL, NULL, 0, 0, NULL }
};
static char *buf;
/* module initialization */
void
wluc_ap_module_init(void)
{
/* get the global buf */
buf = wl_get_buf();
/* register ap commands */
wl_module_cmds_register(wl_ap_cmds);
}
/*
* Get Radar Enable/Disable status
* Set one-shot radar simulation with optional subband
*/
int
wl_radar(void *wl, cmd_t *cmd, char **argv)
{
int ret;
int val;
char *endptr = NULL;
UNUSED_PARAMETER(cmd);
if (!*++argv) {
if ((ret = wlu_get(wl, WLC_GET_RADAR, &val, sizeof(int))) < 0) {
return ret;
}
val = dtoh32(val);
wl_printint(val);
} else {
struct {
int val;
uint sub;
} radar;
radar.val = strtol(*argv, &endptr, 0);
if (*endptr != '\0') {
/* not all the value string was parsed by strtol */
return BCME_USAGE_ERROR;
}
radar.val = htod32(radar.val);
radar.sub = 0;
if (!*++argv) {
ret = wlu_set(wl, WLC_SET_RADAR, &radar.val, sizeof(radar.val));
} else {
radar.sub = strtol(*argv, &endptr, 0);
if (*endptr != '\0') {
/* not all the value string was parsed by strtol */
return BCME_USAGE_ERROR;
}
radar.sub = htod32(radar.sub);
ret = wlu_set(wl, WLC_SET_RADAR, &radar, sizeof(radar));
}
}
return ret;
}
static int
wl_bsscfg_enable(void *wl, cmd_t *cmd, char **argv)
{
char *endptr;
const char *val_name = "bss";
int bsscfg_idx = 0;
int val;
int consumed;
int ret;
UNUSED_PARAMETER(cmd);
/* skip the command name */
argv++;
/* parse a bsscfg_idx option if present */
if ((ret = wl_cfg_option(argv, val_name, &bsscfg_idx, &consumed)) != 0)
return ret;
argv += consumed;
if (consumed == 0) { /* Use the -i parameter if that was present */
bsscfg_idx = -1;
}
if (!*argv) {
bsscfg_idx = htod32(bsscfg_idx);
ret = wlu_iovar_getbuf(wl, val_name, &bsscfg_idx, sizeof(bsscfg_idx),
buf, WLC_IOCTL_MAXLEN);
if (ret < 0)
return ret;
val = *(int*)buf;
val = dtoh32(val);
if (val)
printf("up\n");
else
printf("down\n");
return 0;
} else {
struct {
int cfg;
int val;
} bss_setbuf;
if (!stricmp(*argv, "move"))
val = WLC_AP_IOV_OP_MOVE;
else if (!stricmp(*argv, "ap"))
val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
else if (!stricmp(*argv, "sta"))
val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
else if (!stricmp(*argv, "up"))
val = WLC_AP_IOV_OP_ENABLE;
else if (!stricmp(*argv, "down"))
val = WLC_AP_IOV_OP_DISABLE;
else if (!stricmp(*argv, "del"))
val = WLC_AP_IOV_OP_DELETE;
else {
val = strtol(*argv, &endptr, 0);
if (*endptr != '\0') {
/* not all the value string was parsed by strtol */
return BCME_USAGE_ERROR;
}
}
bss_setbuf.cfg = htod32(bsscfg_idx);
bss_setbuf.val = htod32(val);
return wlu_iovar_set(wl, val_name, &bss_setbuf, sizeof(bss_setbuf));
}
}
static void dump_management_fields(uint8 *data, int len)
{
int i, tag_len;
uint8 tag;
char temp[64];
uint8 *p;
while (len > 0) {
/* Get the tag */
tag = *data;
data++; len--;
/* Get the tag length */
tag_len = (int) *data;
data++; len--;
printf("Tag:%d Len:%d - ", tag, tag_len);
switch (tag) {
case DOT11_MNG_SSID_ID:
for (i = 0; i < tag_len; i++) {
temp[i] = data[i];
}
if (i < 64) {
temp[i] = '\0';
}
printf("SSID: '%s'\n", temp);
break;
case DOT11_MNG_FH_PARMS_ID:
printf("FH Parameter Set\n");
break;
case DOT11_MNG_DS_PARMS_ID:
printf("DS Parameter Set\n");
break;
case DOT11_MNG_CF_PARMS_ID:
printf("CF Parameter Set\n");
break;
case DOT11_MNG_RATES_ID:
printf("Supported Rates\n");
break;
case DOT11_MNG_TIM_ID:
printf("Traffic Indication Map (TIM)\n");
break;
case DOT11_MNG_IBSS_PARMS_ID:
printf("IBSS Parameter Set\n");
break;
case DOT11_MNG_COUNTRY_ID:
p = data;
printf("Country '%c%c%c'\n",
data[0], data[1], data[2]);
p += DOT11_MNG_COUNTRY_ID_LEN;
while (((data+tag_len) - p) >= DOT11_MNG_COUNTRY_ID_LEN) {
printf("Start Channel: %d, Channels: %d, "
"Max TX Power: %d dBm\n",
p[0], p[1], p[2]);
p += DOT11_MNG_COUNTRY_ID_LEN;
}
break;
case DOT11_MNG_HOPPING_PARMS_ID:
printf("Hopping Pattern Parameters\n");
break;
case DOT11_MNG_HOPPING_TABLE_ID:
printf("Hopping Pattern Table\n");
break;
case DOT11_MNG_REQUEST_ID:
printf("Request\n");
break;
case DOT11_MNG_QBSS_LOAD_ID:
printf("QBSS Load\n");
break;
case DOT11_MNG_EDCA_PARAM_ID:
printf("EDCA Parameter\n");
break;
case DOT11_MNG_CHALLENGE_ID:
printf("Challenge text\n");
break;
case DOT11_MNG_PWR_CONSTRAINT_ID:
printf("Power Constraint\n");
break;
case DOT11_MNG_PWR_CAP_ID:
printf("Power Capability\n");
break;
case DOT11_MNG_TPC_REQUEST_ID:
printf("Transmit Power Control (TPC) Request\n");
break;
case DOT11_MNG_TPC_REPORT_ID:
printf("Transmit Power Control (TPC) Report\n");
break;
case DOT11_MNG_SUPP_CHANNELS_ID:
printf("Supported Channels\n");
break;
case DOT11_MNG_CHANNEL_SWITCH_ID:
printf("Channel Switch Announcement\n");
break;
case DOT11_MNG_MEASURE_REQUEST_ID:
printf("Measurement Request\n");
break;
case DOT11_MNG_MEASURE_REPORT_ID:
printf("Measurement Report\n");
break;
case DOT11_MNG_QUIET_ID:
printf("Quiet\n");
break;
case DOT11_MNG_IBSS_DFS_ID:
printf("IBSS DFS\n");
break;
case DOT11_MNG_ERP_ID:
printf("ERP Information\n");
break;
case DOT11_MNG_TS_DELAY_ID:
printf("TS Delay\n");
break;
case DOT11_MNG_HT_CAP:
printf("HT Capabilities\n");
break;
case DOT11_MNG_QOS_CAP_ID:
printf("QoS Capability\n");
break;
case DOT11_MNG_NONERP_ID:
printf("NON-ERP\n");
break;
case DOT11_MNG_RSN_ID:
printf("RSN\n");
break;
case DOT11_MNG_EXT_RATES_ID:
printf("Extended Supported Rates\n");
break;
case DOT11_MNG_AP_CHREP_ID:
printf("AP Channel Report\n");
break;
case DOT11_MNG_NEIGHBOR_REP_ID:
printf("Neighbor Report\n");
break;
case DOT11_MNG_MDIE_ID:
printf("Mobility Domain\n");
break;
case DOT11_MNG_FTIE_ID:
printf("Fast BSS Transition\n");
break;
case DOT11_MNG_FT_TI_ID:
printf("802.11R Timeout Interval\n");
break;
case DOT11_MNG_REGCLASS_ID:
printf("Regulatory Class\n");
break;
case DOT11_MNG_EXT_CSA_ID:
printf("Extended CSA\n");
break;
case DOT11_MNG_HT_ADD:
printf("HT Information\n");
break;
case DOT11_MNG_EXT_CHANNEL_OFFSET:
printf("Ext Channel\n");
break;
#ifdef BCMWAPI_WAI
case DOT11_MNG_WAPI_ID:
printf("WAPI\n");
break;
#endif
case DOT11_MNG_RRM_CAP_ID:
printf("Radio Measurement\n");
break;
case DOT11_MNG_HT_BSS_COEXINFO_ID:
printf("OBSS Coexistence INFO\n");
break;
case DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID:
printf("OBSS Intolerant Channel List\n");
break;
case DOT11_MNG_HT_OBSS_ID:
printf("OBSS HT Info\n");
break;
#ifdef DOT11_MNG_CHANNEL_USAGE
case DOT11_MNG_CHANNEL_USAGE:
printf("Channel Usage\n");
break;
#endif
case DOT11_MNG_LINK_IDENTIFIER_ID:
printf("TDLS Link Identifier\n");
break;
case DOT11_MNG_WAKEUP_SCHEDULE_ID:
printf("TDLS Wakeup Schedule\n");
break;
case DOT11_MNG_CHANNEL_SWITCH_TIMING_ID:
printf("TDLS Channel Switch Timing\n");
break;
case DOT11_MNG_PTI_CONTROL_ID:
printf("TDLS PTI Control\n");
break;
case DOT11_MNG_PU_BUFFER_STATUS_ID:
printf("TDLS PU Buffer Status\n");
break;
case DOT11_MNG_EXT_CAP_ID:
printf("Management Ext Capability\n");
break;
case DOT11_MNG_PROPR_ID:
printf("Proprietary\n");
break;
default:
if (tag_len <= len) {
printf("Unsupported tag\n");
} else {
/* Just dump the remaining data */
printf("Unsupported tag error/malformed\n");
tag_len = len;
}
break;
} /* switch */
wl_hexdump(data, tag_len);
data += tag_len;
len -= tag_len;
} /* while */
}
static void dump_management_info(uint8 *data, int len)
{
struct dot11_management_header hdr;
struct dot11_bcn_prb parms;
if (len <= (int) (sizeof(hdr)+sizeof(parms))) {
/* Management packet invalid */
return;
}
memcpy(&hdr, data, sizeof(hdr));
data += sizeof(hdr);
len -= sizeof(hdr);
memcpy(&parms, data, sizeof(parms));
data += sizeof(parms);
len -= sizeof(parms);
/* 802.11 MAC header */
printf("Frame Ctl: 0x%04x\n", ltoh16(hdr.fc));
printf("Duration : 0x%04x\n", ltoh16(hdr.durid));
printf("Dest addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
hdr.da.octet[0],
hdr.da.octet[1],
hdr.da.octet[2],
hdr.da.octet[3],
hdr.da.octet[4],
hdr.da.octet[5]);
printf("Src addr : %02x:%02x:%02x:%02x:%02x:%02x\n",
hdr.sa.octet[0],
hdr.sa.octet[1],
hdr.sa.octet[2],
hdr.sa.octet[3],
hdr.sa.octet[4],
hdr.sa.octet[5]);
printf("BSSID : %02x:%02x:%02x:%02x:%02x:%02x\n",
hdr.bssid.octet[0],
hdr.bssid.octet[1],
hdr.bssid.octet[2],
hdr.bssid.octet[3],
hdr.bssid.octet[4],
hdr.bssid.octet[5]);
printf("Seq ctl : 0x%04x\n", hdr.seq);
/* 802.11 management frame */
printf("Timestamp: 0x%08x%08x\n",
ltoh32(parms.timestamp[0]), ltoh32(parms.timestamp[1]));
printf("Beacon Interval: 0x%04x\n", ltoh16(parms.beacon_interval));
printf("Capabilities: 0x%04x\n", ltoh32(parms.capability));
dump_management_fields(data, len);
}
static int
wl_management_info(void *wl, cmd_t *cmd, char**argv)
{
int ret = 0;
int len;
uint8 *data;
FILE *fp = NULL;
char *fname = NULL;
int raw = 0;
/* Skip the command name */
argv++;
while (*argv) {
char *s = *argv;
if (!strcmp(s, "-f") && argv[1] != NULL) {
/* Write packet to a file */
fname = argv[1];
argv += 2;
} else if (!strcmp(s, "-r")) {
/* Do a hex dump to console */
raw = 1;
argv++;
} else
return BCME_USAGE_ERROR;
}
/* Get the beacon information */
strcpy(buf, cmd->name);
if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
return ret;
/*
* Dump out the beacon data. The first word (4 bytes) is the
* length of the management packet followed by the data itself.
*/
len = dtoh32(*(int *)buf);
if (len <= 0) {
/* Nothing to do */
return ret;
}
data = (uint8 *) (buf + sizeof(int));
printf("Data: %p Len: %d bytes\n", data, len);
if (fname != NULL) {
/* Write the packet to a file */
if ((fp = fopen(fname, "wb")) == NULL) {
fprintf(stderr, "Failed to open file %s\n",
fname);
ret = BCME_BADARG;
} else {
ret = fwrite(data, 1, len, fp);
if (ret != len) {
fprintf(stderr,
"Error write %d bytes to file %s, rc %d!\n",
len, fname, ret);
ret = -1;
}
}
} else if (raw) {
/* Hex dump */
wl_hexdump(data, len);
} else {
/* Print management (w/some decode) */
dump_management_info(data, len);
}
if (fp)
fclose(fp);
return ret;
}
static int
wl_maclist_1(void *wl, cmd_t *cmd, char **argv)
{
struct maclist *maclist;
struct ether_addr *ea;
uint i;
int ret;
strcpy(buf, argv[0]);
if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
return ret;
maclist = (struct maclist *)buf;
for (i = 0, ea = maclist->ea; i < dtoh32(maclist->count); i++, ea++)
printf("%s %s\n", cmd->name, wl_ether_etoa(ea));
return 0;
}