blob: 5397f544ad696831b2bd5ecd63afe704038e04f9 [file] [log] [blame]
/** @file mlanevent.c
*
* @brief Program to receive events from the driver/firmware of the uAP
* driver.
*
* Copyright (C) 2008-2017, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
* (the "License"). You may use, redistribute and/or modify this File in
* accordance with the terms and conditions of the License, a copy of which
* is available along with the File in the gpl.txt file or by writing to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
*
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
* this warranty disclaimer.
*
*/
/****************************************************************************
Change log:
03/18/08: Initial creation
****************************************************************************/
/****************************************************************************
Header files
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <getopt.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/if.h>
#include "mlanevent.h"
#ifdef WIFI_DIRECT_SUPPORT
#include <arpa/inet.h>
#endif
/****************************************************************************
Definitions
****************************************************************************/
/** Enable or disable debug outputs */
#define DEBUG 0
/****************************************************************************
Global variables
****************************************************************************/
/** Termination flag */
int terminate_flag = 0;
/****************************************************************************
Local functions
****************************************************************************/
/**
* @brief Signal handler
*
* @param sig Received signal number
* @return N/A
*/
void
sig_handler(int sig)
{
printf("Stopping application.\n");
#if DEBUG
printf("Process ID of process killed = %d\n", getpid());
#endif
terminate_flag = 1;
}
/**
* @brief Dump hex data
*
* @param p A pointer to data buffer
* @param len The len of data buffer
* @param delim Deliminator character
* @return Hex integer
*/
static void
hexdump(void *p, t_s32 len, char delim)
{
t_s32 i;
t_u8 *s = p;
for (i = 0; i < len; i++) {
if (i != len - 1)
printf("%02x%c", *s++, delim);
else
printf("%02x\n", *s);
if ((i + 1) % 16 == 0)
printf("\n");
}
}
/**
* @brief Hex to number
*
* @param c Hex value
* @return Integer value or -1
*/
int
hex2num(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
/**
* @brief Check hex string
*
* @param hex A pointer to hex string
* @return 0 or MLAN_EVENT_FAILURE
*/
int
ishexstring(void *hex)
{
int i, a;
char *p = hex;
int len = strlen(p);
if (!strncasecmp("0x", p, 2)) {
p += 2;
len -= 2;
}
for (i = 0; i < len; i++) {
a = hex2num(*p);
if (a < 0)
return MLAN_EVENT_FAILURE;
p++;
}
return 0;
}
/**
* @brief Convert char to hex integer
*
* @param chr Char
* @return Hex integer
*/
unsigned char
hexc2bin(char chr)
{
if (chr >= '0' && chr <= '9')
chr -= '0';
else if (chr >= 'A' && chr <= 'F')
chr -= ('A' - 10);
else if (chr >= 'a' && chr <= 'f')
chr -= ('a' - 10);
return chr;
}
/**
* @brief Convert string to hex integer
*
* @param s A pointer string buffer
* @return Hex integer
*/
unsigned int
a2hex(char *s)
{
unsigned int val = 0;
if (!strncasecmp("0x", s, 2)) {
s += 2;
}
while (*s && isxdigit(*s)) {
val = (val << 4) + hexc2bin(*s++);
}
return val;
}
/**
* @brief Prints a MAC address in colon separated form from raw data
*
* @param raw A pointer to the hex data buffer
* @return N/A
*/
void
print_mac(t_u8 *raw)
{
printf("%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)raw[0],
(unsigned int)raw[1], (unsigned int)raw[2], (unsigned int)raw[3],
(unsigned int)raw[4], (unsigned int)raw[5]);
return;
}
/**
* @brief Print usage information
*
* @return N/A
*/
void
print_usage(void)
{
printf("\n");
printf("Usage : mlanevent.exe [-v] [-h]\n");
printf(" -v : Print version information\n");
printf(" -h : Print help information\n");
printf(" -i : Specify device number from 0 to %d\n",
MAX_NO_OF_DEVICES - 1);
printf(" 0xff for all devices\n");
printf("\n");
}
/**
* @brief Parse and print STA deauthentication event data
*
* @param buffer Pointer to received event buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_event_sta_deauth(t_u8 *buffer, t_u16 size)
{
eventbuf_sta_deauth *event_body = NULL;
if (size < sizeof(eventbuf_sta_deauth)) {
printf("ERR:Event buffer too small!\n");
return;
}
event_body = (eventbuf_sta_deauth *)buffer;
event_body->reason_code = uap_le16_to_cpu(event_body->reason_code);
printf("EVENT: STA_DEAUTH\n");
printf("Deauthenticated STA MAC: ");
print_mac(event_body->sta_mac_address);
printf("\nReason: ");
switch (event_body->reason_code) {
case 1:
printf("Client station leaving the network\n");
break;
case 2:
printf("Client station aged out\n");
break;
case 3:
printf("Client station deauthenticated by user's request\n");
break;
case 4:
printf("Client station authentication failure\n");
break;
case 5:
printf("Client station association failure\n");
break;
case 6:
printf("Client mac address is blocked by ACL filter\n");
break;
case 7:
printf("Client station table is full\n");
break;
case 8:
printf("Client 4-way handshake timeout\n");
break;
case 9:
printf("Client group key handshake timeout\n");
break;
default:
printf("Unspecified\n");
break;
}
return;
}
/**
* @brief Parse and print WEP ICV error event data
*
* @param buffer Pointer to received event buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_event_wep_icv_error(t_u8 *buffer, t_u16 size)
{
int i = 0;
eventbuf_wep_icv_error *event_body = NULL;
if (size < sizeof(eventbuf_wep_icv_error)) {
printf("ERR:Event buffer too small!\n");
return;
}
event_body = (eventbuf_wep_icv_error *)buffer;
event_body->reason_code = uap_le16_to_cpu(event_body->reason_code);
printf("EVENT: WEP_ICV_ERROR\n");
printf("Deauthenticated STA MAC: ");
print_mac(event_body->sta_mac_address);
printf("WEP key index = %d\n", event_body->wep_key_index);
printf("WEP key length = %d\n", event_body->wep_key_length);
printf("WEP key : \n");
for (i = 0; i < event_body->wep_key_length; i++) {
printf("%02x ", event_body->wep_key[i]);
}
printf("\n");
return;
}
/**
* @brief Prints mgmt frame
*
* @param mgmt_tlv A pointer to mgmt_tlv
* @param tlv_len Length of tlv payload
* @return N/A
*/
void
print_mgmt_frame(MrvlIETypes_MgmtFrameSet_t *mgmt_tlv, int tlv_len)
{
IEEEtypes_AssocRqst_t *assoc_req = NULL;
IEEEtypes_ReAssocRqst_t *reassoc_req = NULL;
IEEEtypes_AssocRsp_t *assoc_resp = NULL;
t_u16 frm_ctl = 0;
printf("\nMgmt Frame:\n");
memcpy(&frm_ctl, &mgmt_tlv->frame_control, sizeof(t_u16));
printf("FrameControl: 0x%x\n", frm_ctl);
if (mgmt_tlv->frame_control.type != 0) {
printf("Frame type=%d subtype=%d:\n",
mgmt_tlv->frame_control.type,
mgmt_tlv->frame_control.sub_type);
hexdump(mgmt_tlv->frame_contents, tlv_len - sizeof(t_u16), ' ');
return;
}
switch (mgmt_tlv->frame_control.sub_type) {
case SUBTYPE_ASSOC_REQUEST:
printf("Assoc Request:\n");
assoc_req = (IEEEtypes_AssocRqst_t *)mgmt_tlv->frame_contents;
printf("CapInfo: 0x%x ListenInterval: 0x%x \n",
uap_le16_to_cpu(assoc_req->cap_info),
uap_le16_to_cpu(assoc_req->listen_interval));
printf("AssocReqIE:\n");
hexdump(assoc_req->ie_buffer,
tlv_len - sizeof(IEEEtypes_AssocRqst_t)
- sizeof(IEEEtypes_FrameCtl_t), ' ');
break;
case SUBTYPE_REASSOC_REQUEST:
printf("ReAssoc Request:\n");
reassoc_req =
(IEEEtypes_ReAssocRqst_t *)mgmt_tlv->frame_contents;
printf("CapInfo: 0x%x ListenInterval: 0x%x \n",
uap_le16_to_cpu(reassoc_req->cap_info),
uap_le16_to_cpu(reassoc_req->listen_interval));
printf("Current AP address: ");
print_mac(reassoc_req->current_ap_addr);
printf("\nReAssocReqIE:\n");
hexdump(reassoc_req->ie_buffer,
tlv_len - sizeof(IEEEtypes_ReAssocRqst_t)
- sizeof(IEEEtypes_FrameCtl_t), ' ');
break;
case SUBTYPE_ASSOC_RESPONSE:
case SUBTYPE_REASSOC_RESPONSE:
if (mgmt_tlv->frame_control.sub_type == SUBTYPE_ASSOC_RESPONSE)
printf("Assoc Response:\n");
else
printf("ReAssoc Response:\n");
assoc_resp = (IEEEtypes_AssocRsp_t *)mgmt_tlv->frame_contents;
printf("CapInfo: 0x%x StatusCode: %d AID: 0x%x \n",
uap_le16_to_cpu(assoc_resp->cap_info),
(int)(uap_le16_to_cpu(assoc_resp->status_code)),
uap_le16_to_cpu(assoc_resp->aid) & 0x3fff);
break;
default:
printf("Frame subtype = %d:\n",
mgmt_tlv->frame_control.sub_type);
hexdump(mgmt_tlv->frame_contents, tlv_len - sizeof(t_u16), ' ');
break;
}
return;
}
/**
* @brief Parse and print RSN connect event data
*
* @param buffer Pointer to received buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_event_rsn_connect(t_u8 *buffer, t_u16 size)
{
int tlv_buf_left = size;
t_u16 tlv_type, tlv_len;
tlvbuf_header *tlv = NULL;
eventbuf_rsn_connect *event_body = NULL;
if (size < sizeof(eventbuf_rsn_connect)) {
printf("ERR:Event buffer too small!\n");
return;
}
event_body = (eventbuf_rsn_connect *)buffer;
printf("EVENT: RSN_CONNECT\n");
printf("Station MAC: ");
print_mac(event_body->sta_mac_address);
printf("\n");
tlv_buf_left = size - sizeof(eventbuf_rsn_connect);
if (tlv_buf_left < (int)sizeof(tlvbuf_header))
return;
tlv = (tlvbuf_header *)(buffer + sizeof(eventbuf_rsn_connect));
while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
tlv_type = uap_le16_to_cpu(tlv->type);
tlv_len = uap_le16_to_cpu(tlv->len);
if ((sizeof(tlvbuf_header) + tlv_len) >
(unsigned int)tlv_buf_left) {
printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len,
tlv_buf_left);
break;
}
switch (tlv_type) {
case IEEE_WPA_IE:
printf("WPA IE:\n");
hexdump((t_u8 *)tlv + sizeof(tlvbuf_header), tlv_len,
' ');
break;
case IEEE_RSN_IE:
printf("RSN IE:\n");
hexdump((t_u8 *)tlv + sizeof(tlvbuf_header), tlv_len,
' ');
break;
default:
printf("unknown tlv: %d\n", tlv_type);
break;
}
tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len +
sizeof(tlvbuf_header));
}
return;
}
/**
* @brief Parse and print STA associate event data
*
* @param buffer Pointer to received buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_event_sta_assoc(t_u8 *buffer, t_u16 size)
{
int tlv_buf_left = size;
t_u16 tlv_type, tlv_len;
tlvbuf_header *tlv = NULL;
MrvlIEtypes_WapiInfoSet_t *wapi_tlv = NULL;
MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = NULL;
eventbuf_sta_assoc *event_body = NULL;
if (size < sizeof(eventbuf_sta_assoc)) {
printf("ERR:Event buffer too small!\n");
return;
}
event_body = (eventbuf_sta_assoc *)buffer;
printf("EVENT: STA_ASSOCIATE\n");
printf("Associated STA MAC: ");
print_mac(event_body->sta_mac_address);
printf("\n");
tlv_buf_left = size - sizeof(eventbuf_sta_assoc);
if (tlv_buf_left < (int)sizeof(tlvbuf_header))
return;
tlv = (tlvbuf_header *)(buffer + sizeof(eventbuf_sta_assoc));
while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
tlv_type = uap_le16_to_cpu(tlv->type);
tlv_len = uap_le16_to_cpu(tlv->len);
if ((sizeof(tlvbuf_header) + tlv_len) >
(unsigned int)tlv_buf_left) {
printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len,
tlv_buf_left);
break;
}
switch (tlv_type) {
case MRVL_WAPI_INFO_TLV_ID:
wapi_tlv = (MrvlIEtypes_WapiInfoSet_t *)tlv;
printf("WAPI Multicast PN:\n");
hexdump(wapi_tlv->multicast_PN, tlv_len, ' ');
break;
case MRVL_MGMT_FRAME_TLV_ID:
mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv;
print_mgmt_frame(mgmt_tlv, tlv_len);
break;
default:
printf("unknown tlv: %d\n", tlv_type);
break;
}
tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len +
sizeof(tlvbuf_header));
}
return;
}
/**
* @brief Parse and print BSS start event data
*
* @param buffer Pointer to received buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_event_bss_start(t_u8 *buffer, t_u16 size)
{
eventbuf_bss_start *event_body = NULL;
int tlv_buf_left = size;
t_u16 tlv_type, tlv_len;
tlvbuf_header *tlv = NULL;
tlvbuf_channel_config *channel_tlv = NULL;
if (size < sizeof(eventbuf_bss_start)) {
printf("ERR:Event buffer too small!\n");
return;
}
event_body = (eventbuf_bss_start *)buffer;
printf("EVENT: BSS_START ");
printf("BSS MAC: ");
print_mac(event_body->ap_mac_address);
printf("\n");
tlv_buf_left = size - sizeof(eventbuf_bss_start);
if (tlv_buf_left < (int)sizeof(tlvbuf_header))
return;
tlv = (tlvbuf_header *)(buffer + sizeof(eventbuf_bss_start));
while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
tlv_type = uap_le16_to_cpu(tlv->type);
tlv_len = uap_le16_to_cpu(tlv->len);
if ((sizeof(tlvbuf_header) + tlv_len) >
(unsigned int)tlv_buf_left) {
printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len,
tlv_buf_left);
break;
}
switch (tlv_type) {
case MRVL_CHANNELCONFIG_TLV_ID:
channel_tlv = (tlvbuf_channel_config *)tlv;
printf("Channel = %d\n", channel_tlv->chan_number);
printf("Band = %s\n",
(channel_tlv->bandcfg.chanBand ==
BAND_5GHZ) ? "5GHz" : "2.4GHz");
printf("Channel Select Mode = %s\n",
(channel_tlv->bandcfg.scanMode ==
SCAN_MODE_ACS) ? "ACS" : "Manual");
if (channel_tlv->bandcfg.chan2Offset == SEC_CHAN_NONE)
printf("no secondary channel\n");
else if (channel_tlv->bandcfg.chan2Offset ==
SEC_CHAN_ABOVE)
printf("secondary channel is above primary channel\n");
else if (channel_tlv->bandcfg.chan2Offset ==
SEC_CHAN_BELOW)
printf("secondary channel is below primary channel\n");
break;
default:
#if DEBUG
printf("unknown tlv: %d\n", tlv_type);
#endif
break;
}
tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len +
sizeof(tlvbuf_header));
}
return;
}
#ifdef WIFI_DIRECT_SUPPORT
/**
* @brief Print WIFI_WPS IE elements from event payload
*
* @param buffer Pointer to received buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_wifi_wps_ie_elements(t_u8 *buffer, t_u16 size)
{
t_u8 *ptr = buffer;
t_u8 *array_ptr;
int i;
t_u16 wps_len = 0, wps_type = 0;
t_u16 ie_len_wps = size;
while (ie_len_wps > sizeof(tlvbuf_wps_ie)) {
memcpy(&wps_type, ptr, sizeof(t_u16));
memcpy(&wps_len, ptr + 2, sizeof(t_u16));
endian_convert_tlv_wps_header_in(wps_type, wps_len);
switch (wps_type) {
case SC_Version:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
printf("\t WPS Version = 0x%2x\n",
*(wps_tlv->data));
}
break;
case SC_Simple_Config_State:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
printf("\t WPS setupstate = 0x%x\n",
*(wps_tlv->data));
}
break;
case SC_Request_Type:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
printf("\t WPS RequestType = 0x%x\n",
*(wps_tlv->data));
}
break;
case SC_Response_Type:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
printf("\t WPS ResponseType = 0x%x\n",
*(wps_tlv->data));
}
break;
case SC_Config_Methods:
{
t_u16 wps_config_methods = 0;
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
memcpy(&wps_config_methods, wps_tlv->data,
sizeof(t_u16));
wps_config_methods = ntohs(wps_config_methods);
printf("\t WPS SpecConfigMethods = 0x%x\n",
wps_config_methods);
}
break;
case SC_UUID_E:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
array_ptr = wps_tlv->data;
printf("\t WPS UUID = ");
for (i = 0; i < wps_len; i++)
printf("0x%02X ", *array_ptr++);
printf("\n");
}
break;
case SC_Primary_Device_Type:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
array_ptr = wps_tlv->data;
printf("\t WPS Primary Device Type = ");
for (i = 0; i < wps_len; i++)
printf("0x%02X ", *array_ptr++);
printf("\n");
}
break;
case SC_RF_Band:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
printf("\t WPS RF Band = 0x%x\n",
*(wps_tlv->data));
}
break;
case SC_Association_State:
{
t_u16 wps_association_state = 0;
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
memcpy(&wps_association_state, wps_tlv->data,
sizeof(t_u16));
wps_association_state =
ntohs(wps_association_state);
printf("\t WPS Association State = 0x%x\n",
wps_association_state);
}
break;
case SC_Configuration_Error:
{
t_u16 wps_configuration_error = 0;
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
memcpy(&wps_configuration_error, wps_tlv->data,
sizeof(t_u16));
wps_configuration_error =
ntohs(wps_configuration_error);
printf("\t WPS Configuration Error = 0x%x\n",
wps_configuration_error);
}
break;
case SC_Device_Password_ID:
{
t_u16 wps_device_password_id = 0;
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
memcpy(&wps_device_password_id, wps_tlv->data,
sizeof(t_u16));
wps_device_password_id =
ntohs(wps_device_password_id);
printf("\t WPS Device Password ID = 0x%x\n",
wps_device_password_id);
}
break;
case SC_Device_Name:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
array_ptr = wps_tlv->data;
printf("\t WPS Device Name = ");
for (i = 0; i < wps_len; i++)
printf("%c", *array_ptr++);
printf("\n");
}
break;
case SC_Manufacturer:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
array_ptr = wps_tlv->data;
printf("\t WPS Manufacturer = ");
for (i = 0; i < wps_len; i++)
printf("%c", *array_ptr++);
printf("\n");
}
break;
case SC_Model_Name:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
array_ptr = wps_tlv->data;
printf("\t WPS Model Name = ");
for (i = 0; i < wps_len; i++)
printf("%c", *array_ptr++);
printf("\n");
}
break;
case SC_Model_Number:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
array_ptr = wps_tlv->data;
printf("\t WPS Model Number = ");
for (i = 0; i < wps_len; i++)
printf("%c", *array_ptr++);
printf("\n");
}
break;
case SC_Serial_Number:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
array_ptr = wps_tlv->data;
printf("\t WPS Serial Number = ");
for (i = 0; i < wps_len; i++)
printf("%c", *array_ptr++);
printf("\n");
}
break;
case SC_Vendor_Extension:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
array_ptr = wps_tlv->data;
printf("\t WPS 2.0 Vendor Extension = ");
for (i = 0; i < wps_len; i++)
printf("%x", *array_ptr++);
printf("\n");
}
break;
case SC_Selected_Registrar:
{
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
printf("\t Selected Registrar = %d\n",
*(wps_tlv->data));
}
break;
case SC_SelectedRegistrarConfigMethods:
{
t_u16 sr_config_methods = 0;
tlvbuf_wps_ie *wps_tlv = (tlvbuf_wps_ie *)ptr;
memcpy(&sr_config_methods, wps_tlv->data,
sizeof(t_u16));
sr_config_methods = ntohs(sr_config_methods);
printf("\t Selected Registrar Configuration Methods = 0x%x\n", sr_config_methods);
}
break;
default:
printf("unknown ie=0x%x, len=%d\n", wps_type, wps_len);
break;
}
ptr += wps_len + sizeof(tlvbuf_wps_ie);
/* Take care of error condition */
if (wps_len + sizeof(tlvbuf_wps_ie) <= ie_len_wps)
ie_len_wps -= wps_len + sizeof(tlvbuf_wps_ie);
else
ie_len_wps = 0;
}
}
/**
* @brief Print WIFIDIRECT IE elements from event payload
*
* @param buffer Pointer to received buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_wifidirect_ie_elements(t_u8 *buffer, t_u16 size)
{
t_u8 *ptr = buffer;
t_u8 *array_ptr, *orig_ptr = NULL;
int i;
static t_u16 len = 0;
static t_u16 saved_len = 0;
static t_u16 pending_len = 0;
static t_u8 type = 0;
static t_u8 next_byte = WIFIDIRECT_OVERLAP_TYPE;
static t_u8 saved_data[WIFI_IE_MAX_PAYLOAD] = { 0 };
t_u16 temp;
t_u16 left_len = size;
while (left_len > 0) {
if (next_byte == WIFIDIRECT_OVERLAP_TYPE) {
type = *ptr;
next_byte = WIFIDIRECT_OVERLAP_LEN;
left_len--;
ptr++;
}
if (left_len >= sizeof(len) &&
next_byte == WIFIDIRECT_OVERLAP_LEN) {
memcpy(&len, ptr, sizeof(t_u16));
len = uap_le16_to_cpu(len);
next_byte = WIFIDIRECT_OVERLAP_DATA;
left_len -= sizeof(t_u16);
ptr += sizeof(t_u16);
/* case when Type, Len in one frame and data in next */
if (left_len == 0) {
memcpy(saved_data,
ptr - WIFIDIRECT_IE_HEADER_LEN,
WIFIDIRECT_IE_HEADER_LEN);
saved_len = WIFIDIRECT_IE_HEADER_LEN;
pending_len = len;
}
}
if (left_len > 0 && next_byte == WIFIDIRECT_OVERLAP_DATA) {
/* copy next data */
if (pending_len > 0 &&
(left_len <= (WIFI_IE_MAX_PAYLOAD - saved_len))) {
memcpy(saved_data + saved_len, ptr,
pending_len);
orig_ptr = ptr;
ptr = saved_data;
} else {
ptr -= WIFIDIRECT_IE_HEADER_LEN;
}
if (!pending_len && !orig_ptr && left_len < len) {
/* save along with type and len */
memcpy(saved_data,
ptr - WIFIDIRECT_IE_HEADER_LEN,
left_len + WIFIDIRECT_IE_HEADER_LEN);
saved_len = left_len + WIFIDIRECT_IE_HEADER_LEN;
pending_len = len - left_len;
break;
}
switch (type) {
case TLV_TYPE_WIFIDIRECT_DEVICE_ID:
{
tlvbuf_wifidirect_device_id
*wifidirect_tlv =
(tlvbuf_wifidirect_device_id *)
ptr;
printf("\t Device ID - ");
print_mac(wifidirect_tlv->
dev_mac_address);
printf("\n");
}
break;
case TLV_TYPE_WIFIDIRECT_CAPABILITY:
{
tlvbuf_wifidirect_capability
*wifidirect_tlv =
(tlvbuf_wifidirect_capability *)
ptr;
printf("\t Device capability = %d\n",
(int)wifidirect_tlv->
dev_capability);
printf("\t Group capability = %d\n",
(int)wifidirect_tlv->
group_capability);
}
break;
case TLV_TYPE_WIFIDIRECT_GROUPOWNER_INTENT:
{
tlvbuf_wifidirect_group_owner_intent
*wifidirect_tlv =
(tlvbuf_wifidirect_group_owner_intent
*)ptr;
printf("\t Group owner intent = %d\n",
(int)wifidirect_tlv->dev_intent);
}
break;
case TLV_TYPE_WIFIDIRECT_MANAGEABILITY:
{
tlvbuf_wifidirect_manageability
*wifidirect_tlv =
(tlvbuf_wifidirect_manageability
*)ptr;
printf("\t Manageability = %d\n",
(int)wifidirect_tlv->
manageability);
}
break;
case TLV_TYPE_WIFIDIRECT_INVITATION_FLAG:
{
tlvbuf_wifidirect_invitation_flag
*wifidirect_tlv =
(tlvbuf_wifidirect_invitation_flag
*)ptr;
printf("\t Invitation Flag = %d\n",
(int)wifidirect_tlv->
invitation_flag &
INVITATION_FLAG_MASK);
}
break;
case TLV_TYPE_WIFIDIRECT_CHANNEL_LIST:
{
tlvbuf_wifidirect_channel_list
*wifidirect_tlv =
(tlvbuf_wifidirect_channel_list
*)ptr;
chan_entry *temp_ptr;
printf("\t Country String %c%c",
wifidirect_tlv->
country_string[0],
wifidirect_tlv->
country_string[1]);
if (isalpha
(wifidirect_tlv->country_string[2]))
printf("%c",
wifidirect_tlv->
country_string[2]);
printf("\n");
temp_ptr =
(chan_entry *)wifidirect_tlv->
wifidirect_chan_entry_list;
temp = uap_le16_to_cpu(wifidirect_tlv->
length) -
(sizeof
(tlvbuf_wifidirect_channel_list)
- WIFIDIRECT_IE_HEADER_LEN);
while (temp) {
printf("\t Regulatory_class = %d\n", (int)(temp_ptr->regulatory_class));
printf("\t No of channels = %d\n", (int)temp_ptr->num_of_channels);
printf("\t Channel list = ");
for (i = 0;
i <
temp_ptr->num_of_channels;
i++) {
printf("%d ",
*(temp_ptr->
chan_list +
i));
}
printf("\n");
temp -= sizeof(chan_entry) +
temp_ptr->
num_of_channels;
temp_ptr =
(chan_entry *)((t_u8 *)
temp_ptr
+
sizeof
(chan_entry)
+
temp_ptr->
num_of_channels);
}
printf("\n");
}
break;
case TLV_TYPE_WIFIDIRECT_NOTICE_OF_ABSENCE:
{
tlvbuf_wifidirect_notice_of_absence
*wifidirect_tlv =
(tlvbuf_wifidirect_notice_of_absence
*)ptr;
noa_descriptor *temp_ptr;
printf("\t Instance of Notice of absence timing %d\n", (int)wifidirect_tlv->noa_index);
printf("\t CTWindow and Opportunistic power save parameters %d\n", (int)wifidirect_tlv->ctwindow_opp_ps);
temp_ptr =
(noa_descriptor *)
wifidirect_tlv->
wifidirect_noa_descriptor_list;
temp = uap_le16_to_cpu(wifidirect_tlv->
length) -
(sizeof
(tlvbuf_wifidirect_notice_of_absence)
- WIFIDIRECT_IE_HEADER_LEN);
while (temp) {
printf("\t Count or Type = %d\n", (int)temp_ptr->count_type);
printf("\t Duration = %dms\n",
uap_le32_to_cpu
(temp_ptr->duration));
printf("\t Interval = %dms\n",
uap_le32_to_cpu
(temp_ptr->interval));
printf("\t Start Time = %d\n",
uap_le32_to_cpu
(temp_ptr->start_time));
printf("\n");
temp_ptr +=
sizeof(noa_descriptor);
temp -= sizeof(noa_descriptor);
}
}
break;
case TLV_TYPE_WIFIDIRECT_DEVICE_INFO:
{
tlvbuf_wifidirect_device_info
*wifidirect_tlv =
(tlvbuf_wifidirect_device_info
*)ptr;
printf("\t Device address - ");
print_mac(wifidirect_tlv->dev_address);
printf("\n");
printf("\t Config methods - 0x%02X\n",
ntohs(wifidirect_tlv->
config_methods));
printf("\t Primay device type = %02d-%02X%02X%02X%02X-%02d\n", (int)ntohs(wifidirect_tlv->primary_category), (int)wifidirect_tlv->primary_oui[0], (int)wifidirect_tlv->primary_oui[1], (int)wifidirect_tlv->primary_oui[2], (int)wifidirect_tlv->primary_oui[3], (int)ntohs(wifidirect_tlv->primary_subcategory));
printf("\t Secondary Device Count = %d\n", (int)wifidirect_tlv->secondary_dev_count);
array_ptr =
wifidirect_tlv->
secondary_dev_info;
for (i = 0;
i <
wifidirect_tlv->
secondary_dev_count; i++) {
memcpy(&temp, array_ptr,
sizeof(t_u16));
printf("\t Secondary device type = %02d-", ntohs(temp));
array_ptr += sizeof(temp);
printf("%02X%02X%02X%02X",
array_ptr[0],
array_ptr[1],
array_ptr[2],
array_ptr[3]);
array_ptr += 4;
memcpy(&temp, array_ptr,
sizeof(t_u16));
printf("-%02d\n", ntohs(temp));
array_ptr += sizeof(temp);
}
/* display device name */
array_ptr =
wifidirect_tlv->device_name +
wifidirect_tlv->
secondary_dev_count *
WPS_DEVICE_TYPE_LEN;
if (*(t_u16 *)
(((t_u8 *)(&wifidirect_tlv->
device_name_len)) +
wifidirect_tlv->
secondary_dev_count *
WPS_DEVICE_TYPE_LEN))
printf("\t Device Name = ");
memcpy(&temp,
(((t_u8 *)(&wifidirect_tlv->
device_name_len)) +
wifidirect_tlv->
secondary_dev_count *
WPS_DEVICE_TYPE_LEN),
sizeof(t_u16));
temp = ntohs(temp);
for (i = 0; i < temp; i++)
printf("%c", *array_ptr++);
printf("\n");
}
break;
case TLV_TYPE_WIFIDIRECT_GROUP_INFO:
{
tlvbuf_wifidirect_group_info
*wifidirect_tlv =
(tlvbuf_wifidirect_group_info *)
ptr;
t_u8 wifidirect_client_dev_length;
wifidirect_client_dev_info *temp_ptr;
temp_ptr =
(wifidirect_client_dev_info *)
wifidirect_tlv->
wifidirect_client_dev_list;
if (temp_ptr == NULL)
break;
wifidirect_client_dev_length =
temp_ptr->dev_length;
temp = uap_le16_to_cpu(wifidirect_tlv->
length) -
wifidirect_client_dev_length;
while (temp) {
printf("\t Group WifiDirect Client Device address - ");
print_mac(temp_ptr->
wifidirect_dev_address);
printf("\n");
printf("\t Group WifiDirect Client Interface address - ");
print_mac(temp_ptr->
wifidirect_intf_address);
printf("\n");
printf("\t Group WifiDirect Client Device capability = %d\n", (int)temp_ptr->wifidirect_dev_capability);
printf("\t Group WifiDirect Client Config methods - 0x%02X\n", ntohs(temp_ptr->config_methods));
printf("\t Group WifiDirect Client Primay device type = %02d-%02X%02X%02X%02X-%02d\n", (int)ntohs(temp_ptr->primary_category), (int)temp_ptr->primary_oui[0], (int)temp_ptr->primary_oui[1], (int)temp_ptr->primary_oui[2], (int)temp_ptr->primary_oui[3], (int)ntohs(temp_ptr->primary_subcategory));
printf("\t Group WifiDirect Client Secondary Device Count = %d\n", (int)temp_ptr->wifidirect_secondary_dev_count);
array_ptr =
temp_ptr->
wifidirect_secondary_dev_info;
for (i = 0;
i <
temp_ptr->
wifidirect_secondary_dev_count;
i++) {
memcpy(&temp, array_ptr,
sizeof(t_u16));
printf("\t Group WifiDirect Client Secondary device type = %02d-", ntohs(temp));
array_ptr +=
sizeof(temp);
printf("%02X%02X%02X%02X", array_ptr[0], array_ptr[1], array_ptr[2], array_ptr[3]);
array_ptr += 4;
memcpy(&temp, array_ptr,
sizeof(t_u16));
printf("-%02d\n",
ntohs(temp));
array_ptr +=
sizeof(temp);
}
/* display device name */
array_ptr =
temp_ptr->
wifidirect_device_name +
temp_ptr->
wifidirect_secondary_dev_count
* WPS_DEVICE_TYPE_LEN;
printf("\t Group WifiDirect Device Name = ");
memcpy(&temp,
(((t_u8 *)(&temp_ptr->
wifidirect_device_name_len))
+
temp_ptr->
wifidirect_secondary_dev_count
* WPS_DEVICE_TYPE_LEN),
sizeof(t_u16));
temp = ntohs(temp);
for (i = 0; i < temp; i++)
printf("%c",
*array_ptr++);
printf("\n");
temp_ptr +=
wifidirect_client_dev_length;
temp -= wifidirect_client_dev_length;
if (temp_ptr)
wifidirect_client_dev_length
=
temp_ptr->
dev_length;
}
printf("\n");
}
break;
case TLV_TYPE_WIFIDIRECT_GROUP_ID:
{
tlvbuf_wifidirect_group_id
*wifidirect_tlv =
(tlvbuf_wifidirect_group_id *)
ptr;
printf("\t Group address - ");
print_mac(wifidirect_tlv->
group_address);
printf("\n");
printf("\t Group ssid = ");
for (i = 0;
(unsigned int)i <
uap_le16_to_cpu(wifidirect_tlv->
length)
-
(sizeof(tlvbuf_wifidirect_group_id)
- WIFIDIRECT_IE_HEADER_LEN); i++)
printf("%c",
wifidirect_tlv->
group_ssid[i]);
printf("\n");
}
break;
case TLV_TYPE_WIFIDIRECT_GROUP_BSS_ID:
{
tlvbuf_wifidirect_group_bss_id
*wifidirect_tlv =
(tlvbuf_wifidirect_group_bss_id
*)ptr;
printf("\t Group BSS Id - ");
print_mac(wifidirect_tlv->group_bssid);
printf("\n");
}
break;
case TLV_TYPE_WIFIDIRECT_INTERFACE:
{
tlvbuf_wifidirect_interface
*wifidirect_tlv =
(tlvbuf_wifidirect_interface *)
ptr;
printf("\t Interface Id - ");
print_mac(wifidirect_tlv->interface_id);
printf("\t Interface count = %d",
(int)wifidirect_tlv->
interface_count);
for (i = 0;
i <
wifidirect_tlv->interface_count;
i++) {
printf("\n\t Interface address [%d]", i + 1);
print_mac(&wifidirect_tlv->
interface_idlist[i *
ETH_ALEN]);
}
printf("\n");
}
break;
case TLV_TYPE_WIFIDIRECT_CHANNEL:
{
tlvbuf_wifidirect_channel
*wifidirect_tlv =
(tlvbuf_wifidirect_channel *)
ptr;
printf("\t Listen Channel Country String %c%c", wifidirect_tlv->country_string[0], wifidirect_tlv->country_string[1]);
if (isalpha
(wifidirect_tlv->country_string[2]))
printf("%c",
wifidirect_tlv->
country_string[2]);
printf("\n");
printf("\t Listen Channel regulatory class = %d\n", (int)wifidirect_tlv->regulatory_class);
printf("\t Listen Channel number = %d\n", (int)wifidirect_tlv->channel_number);
}
break;
case TLV_TYPE_WIFIDIRECT_OPCHANNEL:
{
tlvbuf_wifidirect_channel
*wifidirect_tlv =
(tlvbuf_wifidirect_channel *)
ptr;
printf("\t Operating Channel Country String %c%c", wifidirect_tlv->country_string[0], wifidirect_tlv->country_string[1]);
if (isalpha
(wifidirect_tlv->country_string[2]))
printf("%c",
wifidirect_tlv->
country_string[2]);
printf("\n");
printf("\t Operating Channel regulatory class = %d\n", (int)wifidirect_tlv->regulatory_class);
printf("\t Operating Channel number = %d\n", (int)wifidirect_tlv->channel_number);
}
break;
case TLV_TYPE_WIFIDIRECT_CONFIG_TIMEOUT:
{
tlvbuf_wifidirect_config_timeout
*wifidirect_tlv =
(tlvbuf_wifidirect_config_timeout
*)ptr;
printf("\t GO configuration timeout = %d msec\n", (int)wifidirect_tlv->group_config_timeout * 10);
printf("\t Client configuration timeout = %d msec\n", (int)wifidirect_tlv->device_config_timeout * 10);
}
break;
case TLV_TYPE_WIFIDIRECT_EXTENDED_LISTEN_TIME:
{
tlvbuf_wifidirect_ext_listen_time
*wifidirect_tlv =
(tlvbuf_wifidirect_ext_listen_time
*)ptr;
printf("\t Availability Period = %d msec\n", (int)wifidirect_tlv->availability_period);
printf("\t Availability Interval = %d msec\n", (int)wifidirect_tlv->availability_interval);
}
break;
case TLV_TYPE_WIFIDIRECT_INTENDED_ADDRESS:
{
tlvbuf_wifidirect_intended_addr
*wifidirect_tlv =
(tlvbuf_wifidirect_intended_addr
*)ptr;
printf("\t Intended Interface Address - ");
print_mac(wifidirect_tlv->
group_address);
printf("\n");
}
break;
case TLV_TYPE_WIFIDIRECT_STATUS:
{
tlvbuf_wifidirect_status *wifidirect_tlv
=
(tlvbuf_wifidirect_status *)ptr;
printf("\t Status = %d\n",
wifidirect_tlv->status_code);
}
break;
default:
printf("unknown ie=0x%x, len=%d\n", type, len);
break;
}
next_byte = WIFIDIRECT_OVERLAP_TYPE;
if (orig_ptr)
ptr = orig_ptr + pending_len;
}
ptr += len + WIFIDIRECT_IE_HEADER_LEN;
left_len -= len;
}
printf("\n");
return;
}
/**
* @brief Parse and print WIFIDIRECT generic event data
*
* @param buffer Pointer to received buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_event_wifidirect_generic(t_u8 *buffer, t_u16 size)
{
const t_u8 wifi_oui[3] = { 0x50, 0x6F, 0x9A };
const t_u8 wps_oui[3] = { 0x00, 0x50, 0xF2 };
apeventbuf_wifidirect_generic *wifidirect_event;
wifidirect_ie_header *wifidirect_wps_header;
t_u16 wifidirect_wps_len = 0, type, sub_type;
printf("EVENT: WIFIDIRECT \n");
wifidirect_event = (apeventbuf_wifidirect_generic *)(buffer);
printf("Event length = %d\n",
uap_le16_to_cpu(wifidirect_event->event_length));
printf("Event Type = ");
type = uap_le16_to_cpu(wifidirect_event->event_type);
switch (type) {
case 0:
printf("Negotiation Request\n");
break;
case 1:
printf("Negotiation Response\n");
break;
case 2:
printf("Negotiation Result\n");
break;
case 3:
printf("Invitation Request\n");
break;
case 4:
printf("Invitation Response\n");
break;
case 5:
printf("Discoverability Request\n");
break;
case 6:
printf("Discoverability Response\n");
break;
case 7:
printf("Provision Discovery Request\n");
break;
case 8:
printf("Provision Discovery Response\n");
break;
case 9:
printf("GO Negotiation response Tx Event\n");
break;
case 10:
printf("GO Negotiation confirm Tx Event\n");
break;
case 14:
printf("Peer Detected event\n");
break;
case 15:
printf("Client associated event\n");
break;
case 16:
printf("FW debug event: %s\n",
wifidirect_event->entire_ie_list);
return;
default:
printf("Unknown\n");
break;
}
sub_type = uap_le16_to_cpu(wifidirect_event->event_sub_type);
if (type == 2) {
switch (sub_type) {
case 0:
printf("Event SubType = No Role\n");
break;
case 1:
printf("Event SubType = Group Owner Role\n");
break;
case 2:
printf("Event SubType = Client Role\n");
break;
default:
printf("Event SubType = %d\n", sub_type);
break;
}
} else if (type == 3 || type == 4) {
switch (sub_type & 0x03) { /* lower 2 bits */
case 0:
printf("Event SubType = No Role\n");
break;
case 1:
printf("Event SubType = Group Owner Role\n");
break;
case 2:
printf("Event SubType = Client Role\n");
break;
}
switch ((sub_type & 0x1C) >> 2) { /* next 3 bits */
case 0:
printf("Packet processing state = None\n");
break;
case 1:
printf("Packet processing state = Processing\n");
break;
case 2:
printf("Packet processing state = Insufficient information, Dropped\n");
break;
case 3:
printf("Packet processing state = Success\n");
break;
case 4:
printf("Packet processing state = Fail\n");
break;
default:
printf("Event SubType = %d\n", sub_type);
break;
}
} else if (type == 7 || type == 8) {
switch (sub_type) {
case 0:
printf("Event SubType = No Config Method\n");
break;
case 8:
printf("Event SubType = Config Method Display\n");
break;
case 0x80:
printf("Event SubType = Config Method Push Button\n");
break;
case 0x100:
printf("Event SubType = Config Method Keypad\n");
break;
default:
printf("Event SubType = %d\n", sub_type);
break;
}
}
printf("Peer Mac Address - ");
print_mac(wifidirect_event->peer_mac_addr);
printf("\n");
/* Print rest of IE elements */
wifidirect_wps_header =
(wifidirect_ie_header *)(wifidirect_event->entire_ie_list);
wifidirect_wps_len = uap_le16_to_cpu(wifidirect_event->event_length)
- sizeof(apeventbuf_wifidirect_generic);
while (wifidirect_wps_len >= sizeof(wifidirect_ie_header)) {
if (!memcmp
(wifidirect_wps_header->oui, wifi_oui, sizeof(wifi_oui)) ||
!(memcmp
(wifidirect_wps_header->oui, wps_oui, sizeof(wps_oui)))) {
switch (wifidirect_wps_header->oui_type) {
case WIFIDIRECT_OUI_TYPE:
print_wifidirect_ie_elements
(wifidirect_wps_header->ie_list,
wifidirect_wps_header->ie_length -
sizeof(wifidirect_wps_header->oui)
-
sizeof(wifidirect_wps_header->
oui_type));
printf("\n");
break;
case WIFI_WPS_OUI_TYPE:
print_wifi_wps_ie_elements
(wifidirect_wps_header->ie_list,
wifidirect_wps_header->ie_length -
sizeof(wifidirect_wps_header->oui)
-
sizeof(wifidirect_wps_header->
oui_type));
printf("\n");
break;
}
}
wifidirect_wps_len -=
wifidirect_wps_header->ie_length + IE_HEADER_LEN;
wifidirect_wps_header =
(wifidirect_ie_header *)(((t_u8 *)wifidirect_wps_header)
+
wifidirect_wps_header->
ie_length + IE_HEADER_LEN);
}
}
/**
* @brief Parse and print WIFIDIRECT service discovery event data
*
* @param buffer Pointer to received buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_event_wifidirect_service_discovery(t_u8 *buffer, t_u16 size)
{
unsigned int i;
t_u16 event_len = 0;
t_u16 dns_len = 0, dns_type;
t_u8 action = 0; /* req = 0, resp = 1 */
apeventbuf_wifidirect_discovery_request *wifidirect_disc_req;
apeventbuf_wifidirect_discovery_response *wifidirect_disc_resp;
printf("EVENT: WIFIDIRECT SERVICE DISCOVERY\n");
memcpy(&event_len, buffer, sizeof(t_u16));
event_len = uap_le16_to_cpu(event_len);
printf("Event length = %d\n", event_len);
printf("Service Discovery packet:\n");
/* check request /response Byte at offset 2+6+2 */
action = *(buffer + sizeof(t_u16) + ETH_ALEN + sizeof(t_u8));
if (action == WIFIDIRECT_DISCOVERY_REQUEST_ACTION) {
wifidirect_disc_req =
(apeventbuf_wifidirect_discovery_request *)(buffer +
sizeof
(t_u16));
printf("\t Peer Mac Address - ");
print_mac(wifidirect_disc_req->peer_mac_addr);
printf("\n\t Category = %d\n", wifidirect_disc_req->category);
printf("\t Action = %d\n", wifidirect_disc_req->action);
printf("\t Dialog taken = %d\n",
wifidirect_disc_req->dialog_taken);
printf("\t Advertize protocol IE - 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", wifidirect_disc_req->advertize_protocol_ie[0], wifidirect_disc_req->advertize_protocol_ie[1], wifidirect_disc_req->advertize_protocol_ie[2], wifidirect_disc_req->advertize_protocol_ie[3]);
printf("\t Request query length = %d\n",
uap_le16_to_cpu(wifidirect_disc_req->query_len));
printf("\t Information Id - 0x%02x, 0x%02x\n",
wifidirect_disc_req->info_id[0],
wifidirect_disc_req->info_id[1]);
printf("\t Request length = %d\n",
uap_le16_to_cpu(wifidirect_disc_req->request_len));
printf("\t OUI - 0x%02x, 0x%02x, 0x%02x\n",
wifidirect_disc_req->oui[0], wifidirect_disc_req->oui[1],
wifidirect_disc_req->oui[2]);
printf("\t OUI sub type = %d\n",
wifidirect_disc_req->oui_sub_type);
printf("\t Service update Indicator = %d\n",
uap_le16_to_cpu(wifidirect_disc_req->
service_update_indicator));
printf("\t Vendor length = %d\n",
uap_le16_to_cpu(wifidirect_disc_req->vendor_len));
printf("\t Service protocol = %d\n",
wifidirect_disc_req->service_protocol);
printf("\t Service transaction Id = %d\n",
wifidirect_disc_req->service_transaction_id);
printf("\t Query Data = ");
if (wifidirect_disc_req->service_protocol == 1) {
printf(" * Bonjour * \n");
printf("\t\t DNS = ");
dns_len =
uap_le16_to_cpu(wifidirect_disc_req->
vendor_len) -
WIFIDIRECT_DISCOVERY_BONJOUR_FIXED_LEN;
for (i = 0; i < dns_len; i++)
printf("%02x ",
(int)*(wifidirect_disc_req->disc_query.u.
bonjour.dns + i));
memcpy(&dns_type,
(&wifidirect_disc_req->disc_query.u.bonjour.
dns_type + dns_len), sizeof(dns_type));
dns_type = uap_le16_to_cpu(dns_type);
printf("\n\t\t DNS Type = %d\n", dns_type);
printf("\t\t Version = %d\n",
*(&wifidirect_disc_req->disc_query.u.bonjour.
version + dns_len));
} else if (wifidirect_disc_req->service_protocol == 2) {
printf(" * uPnP * \n");
printf("\t\t Version = %d\n",
wifidirect_disc_req->disc_query.u.upnp.version);
dns_len =
uap_le16_to_cpu(wifidirect_disc_req->
vendor_len) -
WIFIDIRECT_DISCOVERY_UPNP_FIXED_LEN;
printf("\t\t Value = ");
for (i = 0; i < dns_len; i++)
printf("%02x ",
(int)*(wifidirect_disc_req->disc_query.u.
upnp.value + i));
}
printf("\n");
} else if (action == WIFIDIRECT_DISCOVERY_RESPONSE_ACTION) {
wifidirect_disc_resp =
(apeventbuf_wifidirect_discovery_response *)(buffer +
sizeof
(t_u16));
printf("\t Peer Mac Address - ");
print_mac(wifidirect_disc_resp->peer_mac_addr);
printf("\n\t Category = %d\n", wifidirect_disc_resp->category);
printf("\t Action = %d\n", wifidirect_disc_resp->action);
printf("\t Dialog taken = %d\n",
wifidirect_disc_resp->dialog_taken);
printf("\t Status code = %d\n",
wifidirect_disc_resp->status_code);
printf("\t GAS reply - 0x%02x\n",
uap_le16_to_cpu(wifidirect_disc_resp->gas_reply));
printf("\t Advertize protocol IE - 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", wifidirect_disc_resp->advertize_protocol_ie[0], wifidirect_disc_resp->advertize_protocol_ie[1], wifidirect_disc_resp->advertize_protocol_ie[2], wifidirect_disc_resp->advertize_protocol_ie[3]);
printf("\t Response query length = %d\n",
uap_le16_to_cpu(wifidirect_disc_resp->query_len));
printf("\t Information Id - 0x%02x, 0x%02x\n",
wifidirect_disc_resp->info_id[0],
wifidirect_disc_resp->info_id[1]);
printf("\t Response length = %d\n",
uap_le16_to_cpu(wifidirect_disc_resp->response_len));
printf("\t OUI - 0x%02x, 0x%02x, 0x%02x\n",
wifidirect_disc_resp->oui[0],
wifidirect_disc_resp->oui[1],
wifidirect_disc_resp->oui[2]);
printf("\t OUI sub type = %d\n",
wifidirect_disc_resp->oui_sub_type);
printf("\t Service update Indicator = %d\n",
uap_le16_to_cpu(wifidirect_disc_resp->
service_update_indicator));
printf("\t Vendor length = %d\n",
uap_le16_to_cpu(wifidirect_disc_resp->vendor_len));
printf("\t Service protocol = %d\n",
wifidirect_disc_resp->service_protocol);
printf("\t Service transaction Id = %d\n",
wifidirect_disc_resp->service_transaction_id);
printf("\t Status Code = %d\n",
wifidirect_disc_resp->disc_status_code);
printf("\t Response Data = ");
if (wifidirect_disc_resp->service_protocol == 1) {
printf(" * Bonjour * \n");
/*
printf("\t\t DNS = ");
dns_len = uap_le16_to_cpu(wifidirect_disc_resp->vendor_len) -
(WIFIDIRECT_DISCOVERY_BONJOUR_FIXED_LEN + 1);
for( i=0; i < dns_len; i++)
printf("%c",*(wifidirect_disc_resp->disc_resp.u.bonjour.dns + i));
memcpy(&dns_type, (&wifidirect_disc_req->disc_query.u.bonjour.dns_type
+ dns_len), sizeof(dns_type));
dns_type = uap_le16_to_cpu(dns_type);
printf("\n\t\t DNS Type = %d\n", dns_type);
printf("\t\t Version = %d\n", *(&wifidirect_disc_resp->disc_resp.u.bonjour.version
+ dns_len));
*/
} else if (wifidirect_disc_resp->service_protocol == 2) {
printf(" * uPnP * \n");
printf("\t\t Version = %d\n",
wifidirect_disc_resp->disc_resp.u.upnp.version);
dns_len =
uap_le16_to_cpu(wifidirect_disc_resp->
vendor_len) -
WIFIDIRECT_DISCOVERY_UPNP_FIXED_LEN;
printf("\t\t Value = ");
for (i = 0; i < dns_len; i++)
printf("%02x ",
(int)*(wifidirect_disc_resp->disc_resp.u.
upnp.value + i));
}
printf("\n");
}
}
#endif
/**
* @brief Parse and print TDLS generic event data
*
* @param buffer Pointer to received buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_event_tdls_generic(t_u8 *buffer, t_u16 size)
{
eventbuf_tdls_generic *tdls_event;
eventbuf_tdls_debug *tdls_debug;
eventbuf_tdls_packet *tdls_pkt;
printf("EVENT: TDLS\n");
tdls_event = (eventbuf_tdls_generic *)(buffer);
printf("Event Type = ");
switch (uap_le16_to_cpu(tdls_event->event_type)) {
case TDLS_EVENT_TYPE_SETUP_FAILURE:
printf("TDLS setup failure\n");
break;
case TDLS_EVENT_TYPE_SETUP_REQ_RCVD:
printf("TDLS setup request received from peer\n");
break;
case TDLS_EVENT_TYPE_LINK_TORN_DOWN:
printf("TDLS link torn down\n");
break;
case TDLS_EVENT_TYPE_LINK_ESTABLISHED:
printf("TDLS link established\n");
break;
case TDLS_EVENT_TYPE_DEBUG:
tdls_debug = (eventbuf_tdls_debug *)(buffer);
printf("TDLS debug event, ");
printf("TSF = %lld\n", uap_le64_to_cpu(tdls_debug->tsf));
printf("String = ");
printf((char *)(tdls_debug->string),
uap_le32_to_cpu(tdls_debug->first_arg),
uap_le32_to_cpu(tdls_debug->second_arg),
uap_le32_to_cpu(tdls_debug->third_arg));
printf("\n");
return;
case TDLS_EVENT_TYPE_PACKET:
tdls_pkt = (eventbuf_tdls_packet *)(buffer);
printf("TDLS packet len=%d\n", tdls_pkt->length);
hexdump((t_u8 *)tdls_pkt->data, tdls_pkt->length, ' ');
return;
case TDLS_EVENT_TYPE_CHAN_SWITCH_RESULT:
if (tdls_event->u.switch_result.status) {
printf("TDLS Channel Switch Failed! current channel=%d Reasoncode %d\n", tdls_event->u.switch_result.current_channel, tdls_event->u.switch_result.reason);
} else {
printf("TDLS Channel Switch Successful. current channel=%d\n", tdls_event->u.switch_result.current_channel);
}
break;
case TDLS_EVENT_TYPE_START_CHAN_SWITCH:
printf("TDLS Start channel switch...\n");
break;
case TDLS_EVENT_TYPE_CHAN_SWITCH_STOPPED:
printf("TDLS Channel Switch stopped! reason=%d\n",
tdls_event->u.cs_stop_reason);
break;
default:
printf("Unknown\n");
break;
}
printf("Peer Mac Address - ");
print_mac(tdls_event->peer_mac_addr);
printf("\n");
if (uap_le16_to_cpu(tdls_event->event_type) ==
TDLS_EVENT_TYPE_SETUP_FAILURE) {
switch (uap_le16_to_cpu(tdls_event->u.reason_code)) {
case 1:
printf("Reason Code = Internal error\n");
break;
case 7:
printf("Reason Code = Timeout waiting for response\n");
break;
case 8:
printf("Reason Code = Non-zero setup response status\n");
break;
default:
printf("Reason Code = %d\n",
uap_le16_to_cpu(tdls_event->u.reason_code));
break;
}
} else if (uap_le16_to_cpu(tdls_event->event_type) ==
TDLS_EVENT_TYPE_LINK_TORN_DOWN) {
switch (uap_le16_to_cpu(tdls_event->u.reason_code)) {
case 3:
printf("Reason Code = Peer station is leaving BSS\n");
break;
case 25:
printf("Reason Code = Peer station is unreachable on direct link\n");
break;
case 26:
printf("Reason Code = Unspecified\n");
break;
case 211:
printf("Reason Code = Setup received from TDLS peer\n");
break;
case 212:
printf("Reason Code = Clearing TDLS connections due to deauth/disassoc\n");
break;
default:
printf("Reason Code = %d\n",
uap_le16_to_cpu(tdls_event->u.reason_code));
break;
}
} else if (uap_le16_to_cpu(tdls_event->event_type) ==
TDLS_EVENT_TYPE_LINK_ESTABLISHED) {
int ie_len = uap_le16_to_cpu(tdls_event->u.ie_length);
if (ie_len) {
printf("Peer IE len=%d\n", ie_len);
hexdump((t_u8 *)tdls_event->ie_ptr, ie_len, ' ');
}
}
}
/**
* @brief Prints station reject state
*
* @param state Fail state
* @return N/A
*/
void
print_reject_state(t_u8 state)
{
switch (state) {
case REJECT_STATE_FAIL_EAPOL_2:
printf("Reject state: FAIL_EAPOL_2\n");
break;
case REJECT_STATE_FAIL_EAPOL_4:
printf("Reject state: FAIL_EAPOL_4:\n");
break;
case REJECT_STATE_FAIL_EAPOL_GROUP_2:
printf("Reject state: FAIL_EAPOL_GROUP_2\n");
break;
default:
printf("ERR: unknown reject state %d\n", state);
break;
}
return;
}
/**
* @brief Prints station reject reason
*
* @param reason Reason code
* @return N/A
*/
void
print_reject_reason(t_u16 reason)
{
switch (reason) {
case IEEEtypes_REASON_INVALID_IE:
printf("Reject reason: Invalid IE\n");
break;
case IEEEtypes_REASON_MIC_FAILURE:
printf("Reject reason: Mic Failure\n");
break;
default:
printf("Reject reason: %d\n", reason);
break;
}
return;
}
/**
* @brief Prints EAPOL state
*
* @param state Eapol state
* @return N/A
*/
void
print_eapol_state(t_u8 state)
{
switch (state) {
case EAPOL_START:
printf("Eapol state: EAPOL_START\n");
break;
case EAPOL_WAIT_PWK2:
printf("Eapol state: EAPOL_WAIT_PWK2\n");
break;
case EAPOL_WAIT_PWK4:
printf("Eapol state: EAPOL_WAIT_PWK4\n");
break;
case EAPOL_WAIT_GTK2:
printf("Eapol state: EAPOL_WAIT_GTK2\n");
break;
case EAPOL_END:
printf("Eapol state: EAPOL_END\n");
break;
default:
printf("ERR: unknow eapol state%d\n", state);
break;
}
return;
}
/**
* @brief Parse and print debug event data
*
* @param buffer Pointer to received buffer
* @param size Length of the received event data
* @return N/A
*/
void
print_event_debug(t_u8 *buffer, t_u16 size)
{
eventbuf_debug *event_body = NULL;
if (size < sizeof(eventbuf_debug)) {
printf("ERR:Event buffer too small!\n");
return;
}
event_body = (eventbuf_debug *)buffer;
printf("Debug Event Type: %s\n",
(event_body->debug_type == 0) ? "EVENT" : "INFO");
printf("%s log:\n",
(uap_le32_to_cpu(event_body->debug_id_major) ==
DEBUG_ID_MAJ_AUTHENTICATOR) ? "Authenticator" : "Assoc_agent");
if (uap_le32_to_cpu(event_body->debug_id_major) ==
DEBUG_ID_MAJ_AUTHENTICATOR) {
switch (uap_le32_to_cpu(event_body->debug_id_minor)) {
case DEBUG_MAJ_AUTH_MIN_PWK1:
printf("EAPOL Key message 1 (PWK):\n");
hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
sizeof(eapol_keymsg_debug_t), ' ');
break;
case DEBUG_MAJ_AUTH_MIN_PWK2:
printf("EAPOL Key message 2 (PWK):\n");
hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
sizeof(eapol_keymsg_debug_t), ' ');
break;
case DEBUG_MAJ_AUTH_MIN_PWK3:
printf("EAPOL Key message 3 (PWK):\n");
hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
sizeof(eapol_keymsg_debug_t), ' ');
break;
case DEBUG_MAJ_AUTH_MIN_PWK4:
printf("EAPOL Key message 4: (PWK)\n");
hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
sizeof(eapol_keymsg_debug_t), ' ');
break;
case DEBUG_MAJ_AUTH_MIN_GWK1:
printf("EAPOL Key message 1: (GWK)\n");
hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
sizeof(eapol_keymsg_debug_t), ' ');
break;
case DEBUG_MAJ_AUTH_MIN_GWK2:
printf("EAPOL Key message 2: (GWK)\n");
hexdump((t_u8 *)&event_body->info.eapol_pwkmsg,
sizeof(eapol_keymsg_debug_t), ' ');
break;
case DEBUG_MAJ_AUTH_MIN_STA_REJ:
printf("Reject STA MAC: ");
print_mac(event_body->info.sta_reject.sta_mac_addr);
printf("\n");
print_reject_state(event_body->info.sta_reject.
reject_state);
print_reject_reason(uap_le16_to_cpu
(event_body->info.sta_reject.
reject_reason));
break;
case DEBUG_MAJ_AUTH_MIN_EAPOL_TR:
printf("STA MAC: ");
print_mac(event_body->info.eapol_state.sta_mac_addr);
printf("\n");
print_eapol_state(event_body->info.eapol_state.
eapol_state);
break;
default:
printf("ERR: unknow debug_id_minor: %d\n",
(int)uap_le32_to_cpu(event_body->
debug_id_minor));
hexdump(buffer, size, ' ');
return;
}
} else if (uap_le32_to_cpu(event_body->debug_id_major) ==
DEBUG_ID_MAJ_ASSOC_AGENT) {
switch (uap_le32_to_cpu(event_body->debug_id_minor)) {
case DEBUG_ID_MAJ_ASSOC_MIN_WPA_IE:
printf("STA MAC: ");
print_mac(event_body->info.wpaie.sta_mac_addr);
printf("\n");
printf("wpa ie:\n");
hexdump(event_body->info.wpaie.wpa_ie, MAX_WPA_IE_LEN,
' ');
break;
case DEBUG_ID_MAJ_ASSOC_MIN_STA_REJ:
printf("Reject STA MAC: ");
print_mac(event_body->info.sta_reject.sta_mac_addr);
printf("\n");
print_reject_state(event_body->info.sta_reject.
reject_state);
print_reject_reason(uap_le16_to_cpu
(event_body->info.sta_reject.
reject_reason));
break;
default:
printf("ERR: unknow debug_id_minor: %d\n",
(int)uap_le32_to_cpu(event_body->
debug_id_minor));
hexdump(buffer, size, ' ');
return;
}
}
return;
}
/**
* @brief Parse and print received nlist event information
*
* @param buffer Pointer to the data buffer
* @param size Length of the received event
* @return N/A
*/
void
print_event_11k_nlist_report(t_u8 *buffer, t_u16 size)
{
int tlv_buf_left = 0;
tlvbuf_header *tlv;
nlist_entry_tlv *nlist;
int entry_num = 0;
t_u16 tlv_type, tlv_len;
if (size < 2) {
printf("No neighbor AP list found: %d\n", size);
return;
}
tlv_buf_left = *(t_u16 *)buffer;
tlv_buf_left = uap_le16_to_cpu(tlv_buf_left);
if (tlv_buf_left < (int)sizeof(tlvbuf_header))
return;
printf("neighbor AP list tlv len: %d\n", tlv_buf_left);
tlv = (tlvbuf_header *)(buffer + 2);
while (tlv_buf_left >= (int)sizeof(tlvbuf_header)) {
tlv_type = uap_le16_to_cpu(tlv->type);
tlv_len = uap_le16_to_cpu(tlv->len);
if ((sizeof(tlvbuf_header) + tlv_len) >
(unsigned int)tlv_buf_left) {
printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len,
tlv_buf_left);
break;
}
switch (tlv_type) {
case MRVL_NEIGHBOR_REPORT_TLV_ID:
nlist = (nlist_entry_tlv *) tlv;
printf("Neighbor entry %d:\n", entry_num);
printf("BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
nlist->bssid[0], nlist->bssid[1],
nlist->bssid[2], nlist->bssid[3],
nlist->bssid[4], nlist->bssid[5]);
printf("BSSID Info: %02x:%02x:%02x:%02x \n",
nlist->bssid_info[0], nlist->bssid_info[1],
nlist->bssid_info[2], nlist->bssid_info[3]);
printf("reg class: %d, chan: %d, phy: %d \n",
nlist->reg_class, nlist->chan, nlist->phy_type);
if (tlv_len > sizeof(nlist_entry_tlv)) {
printf("sub IE:\n");
hexdump((t_u8 *)tlv + sizeof(nlist_entry_tlv),
tlv_len - sizeof(nlist_entry_tlv) +
sizeof(tlvbuf_header), ' ');
}
entry_num++;
break;
default:
#if DEBUG
printf("unknown tlv: %d\n", tlv_type);
#endif
break;
}
tlv_buf_left -= (sizeof(tlvbuf_header) + tlv_len);
tlv = (tlvbuf_header *)((t_u8 *)tlv + tlv_len +
sizeof(tlvbuf_header));
}
return;
}
/**
* @brief Parse and print received event information
*
* @param event Pointer to received event
* @param size Length of the received event
* @return N/A
*/
void
print_event(event_header *event, t_u16 size)
{
t_u32 event_id = event->event_id;
switch (event_id) {
case MICRO_AP_EV_ID_STA_DEAUTH:
print_event_sta_deauth(event->event_data, size - EVENT_ID_LEN);
break;
case MICRO_AP_EV_ID_STA_ASSOC:
print_event_sta_assoc(event->event_data, size - EVENT_ID_LEN);
break;
case MICRO_AP_EV_ID_BSS_START:
print_event_bss_start(event->event_data, size - EVENT_ID_LEN);
break;
case MICRO_AP_EV_ID_DEBUG:
print_event_debug(event->event_data, size - EVENT_ID_LEN);
break;
case MICRO_AP_EV_BSS_IDLE:
printf("EVENT: BSS_IDLE\n");
break;
case MICRO_AP_EV_BSS_ACTIVE:
printf("EVENT: BSS_ACTIVE\n");
break;
case MICRO_AP_EV_RSN_CONNECT:
print_event_rsn_connect(event->event_data, size - EVENT_ID_LEN);
break;
#ifdef WIFI_DIRECT_SUPPORT
case EVENT_WIFIDIRECT_GENERIC:
print_event_wifidirect_generic(event->event_data,
size - EVENT_ID_LEN);
break;
case EVENT_WIFIDIRECT_SERVICE_DISCOVERY:
print_event_wifidirect_service_discovery(event->event_data,
size - EVENT_ID_LEN);
break;
#endif
case EVENT_TDLS_GENERIC:
print_event_tdls_generic(event->event_data,
size - EVENT_ID_LEN);
break;
case UAP_EVENT_ID_DRV_HS_ACTIVATED:
printf("EVENT: uAP HS_ACTIVATED\n");
break;
case UAP_EVENT_ID_DRV_HS_DEACTIVATED:
printf("EVENT: uAP HS_DEACTIVATED\n");
break;
case UAP_EVENT_ID_HS_WAKEUP:
printf("EVENT: uAP HS_WAKEUP\n");
break;
case UAP_EVENT_HOST_SLEEP_AWAKE:
break;
case UAP_EVENT_ID_DRV_MGMT_FRAME:
printf("EVENT: Mgmt frame from FW\n");
hexdump((void *)event, size, ' ');
break;
case MICRO_AP_EV_WMM_STATUS_CHANGE:
printf("EVENT: WMM_STATUS_CHANGE\n");
break;
case EVENT_RADAR_DETECTED:
printf("EVENT: RADAR_DETECTED\n");
break;
case EVENT_CHANNEL_REPORT_RDY:
printf("EVENT: CHANNEL_REPORT_READY\n");
hexdump((void *)event, size, ' ');
break;
case EVENT_WEP_ICV_ERROR:
print_event_wep_icv_error(event->event_data,
size - EVENT_ID_LEN);
break;
case EVENT_ID_DRV_SCAN_REPORT:
printf("Scan request completed.\n");
break;
case EVENT_NLIST_REPORT:
printf("EVENT: 11k neighbor AP list report\n");
print_event_11k_nlist_report(event->event_data,
size - EVENT_ID_LEN);
break;
default:
/* Handle string based events */
#define CUS_EVT_PORT_RELEASE "EVENT=PORT_RELEASE"
if (!strncmp
((char *)event, CUS_EVT_PORT_RELEASE,
strlen(CUS_EVT_PORT_RELEASE))) {
printf("EVENT: PORT_RELEASE.\n");
break;
}
#define CUS_EVT_TDLS_CONNECTED "EVENT=TDLS_CONNECTED"
if (!strncmp
((char *)event, CUS_EVT_TDLS_CONNECTED,
strlen(CUS_EVT_TDLS_CONNECTED))) {
printf("EVENT: TDLS_CONNECTED\n");
print_mac((t_u8 *)event +
strlen(CUS_EVT_TDLS_CONNECTED));
printf("\n");
break;
}
#define CUS_EVT_TDLS_TEARDOWN "EVENT=TDLS_TEARDOWN"
if (!strncmp
((char *)event, CUS_EVT_TDLS_TEARDOWN,
strlen(CUS_EVT_TDLS_TEARDOWN))) {
printf("EVENT: TDLS_TEARDOWN\n");
print_mac((t_u8 *)event +
strlen(CUS_EVT_TDLS_TEARDOWN));
printf("\n");
break;
}
#define CUS_EVT_STA_CONNECTED "EVENT=STA_CONNECTED"
if (!strncmp
((char *)event, CUS_EVT_STA_CONNECTED,
strlen(CUS_EVT_STA_CONNECTED))) {
printf("EVENT: STA_CONNECTED\n");
print_mac((t_u8 *)event +
strlen(CUS_EVT_STA_CONNECTED) + 1);
printf("\n");
break;
}
#define CUS_EVT_STA_DISCONNECTED "EVENT=STA_DISCONNECTED"
if (!strncmp
((char *)event, CUS_EVT_STA_DISCONNECTED,
strlen(CUS_EVT_STA_DISCONNECTED))) {
printf("EVENT: STA_DISCONNECTED\n");
break;
}
#define CUS_EVT_AP_CONNECTED "EVENT=AP_CONNECTED"
if (!strncmp
((char *)event, CUS_EVT_AP_CONNECTED,
strlen(CUS_EVT_AP_CONNECTED))) {
printf("EVENT: AP_CONNECTED\n");
print_mac((t_u8 *)event + strlen(CUS_EVT_AP_CONNECTED));
printf("\n");
break;
}
#define CUS_EVT_ADHOC_LINK_SENSED "EVENT=ADHOC_LINK_SENSED"
if (!strncmp
((char *)event, CUS_EVT_ADHOC_LINK_SENSED,
strlen(CUS_EVT_ADHOC_LINK_SENSED))) {
printf("EVENT: ADHOC_LINK_SENSED\n");
break;
}
#define CUS_EVT_ADHOC_LINK_LOST "EVENT=ADHOC_LINK_LOST"
if (!strncmp
((char *)event, CUS_EVT_ADHOC_LINK_LOST,
strlen(CUS_EVT_ADHOC_LINK_LOST))) {
printf("EVENT: ADHOC_LINK_LOST\n");
break;
}
#define CUS_EVT_OBSS_SCAN_PARAM "EVENT=OBSS_SCAN_PARAM"
if (!strncmp
((char *)event, CUS_EVT_OBSS_SCAN_PARAM,
strlen(CUS_EVT_OBSS_SCAN_PARAM))) {
printf("EVENT: OBSS_SCAN_PARAM\n");
break;
}
#define CUS_EVT_BW_CHANGED "EVENT=BW_CHANGED"
if (!strncmp
((char *)event, CUS_EVT_BW_CHANGED,
strlen(CUS_EVT_BW_CHANGED))) {
printf("EVENT: BW_CHANGED\n");
break;
}
#define CUS_EVT_MLME_MIC_ERR_UNI "MLME-MICHAELMICFAILURE.indication unicast"
if (!strncmp
((char *)event, CUS_EVT_MLME_MIC_ERR_UNI,
strlen(CUS_EVT_MLME_MIC_ERR_UNI))) {
printf("EVENT: MLME-MICHAELMICFAILURE.indication unicast\n");
break;
}
#define CUS_EVT_MLME_MIC_ERR_MUL "MLME-MICHAELMICFAILURE.indication multicast"
if (!strncmp
((char *)event, CUS_EVT_MLME_MIC_ERR_MUL,
strlen(CUS_EVT_MLME_MIC_ERR_MUL))) {
printf("EVENT: MLME-MICHAELMICFAILURE.indication multicast\n");
break;
}
#define CUS_EVT_BEACON_RSSI_LOW "EVENT=BEACON_RSSI_LOW"
if (!strncmp
((char *)event, CUS_EVT_BEACON_RSSI_LOW,
strlen(CUS_EVT_BEACON_RSSI_LOW))) {
printf("EVENT: BEACON_RSSI_LOW\n");
break;
}
#define CUS_EVT_BEACON_RSSI_HIGH "EVENT=BEACON_RSSI_HIGH"
if (!strncmp
((char *)event, CUS_EVT_BEACON_RSSI_HIGH,
strlen(CUS_EVT_BEACON_RSSI_HIGH))) {
printf("EVENT: BEACON_RSSI_HIGH\n");
break;
}
#define CUS_EVT_BEACON_SNR_LOW "EVENT=BEACON_SNR_LOW"
if (!strncmp
((char *)event, CUS_EVT_BEACON_SNR_LOW,
strlen(CUS_EVT_BEACON_SNR_LOW))) {
printf("EVENT: BEACON_SNR_LOW\n");
break;
}
#define CUS_EVT_BEACON_SNR_HIGH "EVENT=BEACON_SNR_HIGH"
if (!strncmp
((char *)event, CUS_EVT_BEACON_SNR_HIGH,
strlen(CUS_EVT_BEACON_SNR_HIGH))) {
printf("EVENT: BEACON_SNR_HIGH\n");
break;
}
#define CUS_EVT_MAX_FAIL "EVENT=MAX_FAIL"
if (!strncmp
((char *)event, CUS_EVT_MAX_FAIL,
strlen(CUS_EVT_MAX_FAIL))) {
printf("EVENT: MAX_FAIL\n");
break;
}
#define CUS_EVT_DATA_RSSI_LOW "EVENT=DATA_RSSI_LOW"
if (!strncmp
((char *)event, CUS_EVT_DATA_RSSI_LOW,
strlen(CUS_EVT_DATA_RSSI_LOW))) {
printf("EVENT: DATA_RSSI_LOW\n");
break;
}
#define CUS_EVT_DATA_SNR_LOW "EVENT=DATA_SNR_LOW"
if (!strncmp
((char *)event, CUS_EVT_DATA_SNR_LOW,
strlen(CUS_EVT_DATA_SNR_LOW))) {
printf("EVENT: DATA_SNR_LOW\n");
break;
}
#define CUS_EVT_DATA_RSSI_HIGH "EVENT=DATA_RSSI_HIGH"
if (!strncmp
((char *)event, CUS_EVT_DATA_RSSI_HIGH,
strlen(CUS_EVT_DATA_RSSI_HIGH))) {
printf("EVENT: DATA_RSSI_HIGH\n");
break;
}
#define CUS_EVT_DATA_SNR_HIGH "EVENT=DATA_SNR_HIGH"
if (!strncmp
((char *)event, CUS_EVT_DATA_SNR_HIGH,
strlen(CUS_EVT_DATA_SNR_HIGH))) {
printf("EVENT: DATA_SNR_HIGH\n");
break;
}
#define CUS_EVT_LINK_QUALITY "EVENT=LINK_QUALITY"
if (!strncmp
((char *)event, CUS_EVT_LINK_QUALITY,
strlen(CUS_EVT_LINK_QUALITY))) {
printf("EVENT: LINK_QUALITY\n");
break;
}
#define CUS_EVT_WEP_ICV_ERR "EVENT=WEP_ICV_ERR"
if (!strncmp
((char *)event, CUS_EVT_WEP_ICV_ERR,
strlen(CUS_EVT_WEP_ICV_ERR))) {
printf("EVENT: WEP_ICV_ERR\n");
break;
}
#define CUS_EVT_CHANNEL_SWITCH_ANN "EVENT=CHANNEL_SWITCH_ANN"
if (!strncmp
((char *)event, CUS_EVT_CHANNEL_SWITCH_ANN,
strlen(CUS_EVT_CHANNEL_SWITCH_ANN))) {
printf("EVENT: CHANNEL_SWITCH_ANN\n");
break;
}
#define CUS_EVT_HS_WAKEUP "HS_WAKEUP"
if (!strncmp
((char *)event, CUS_EVT_HS_WAKEUP,
strlen(CUS_EVT_HS_WAKEUP))) {
printf("EVENT: HS_WAKEUP\n");
break;
}
#define CUS_EVT_HS_ACTIVATED "HS_ACTIVATED"
if (!strncmp
((char *)event, CUS_EVT_HS_ACTIVATED,
strlen(CUS_EVT_HS_ACTIVATED))) {
printf("EVENT: HS_ACTIVATED\n");
break;
}
#define CUS_EVT_HS_DEACTIVATED "HS_DEACTIVATED"
if (!strncmp
((char *)event, CUS_EVT_HS_DEACTIVATED,
strlen(CUS_EVT_HS_DEACTIVATED))) {
printf("EVENT: HS_DEACTIVATED\n");
break;
}
/** Custom indication message sent to the application layer for WMM changes */
#define WMM_CONFIG_CHANGE_INDICATION "WMM_CONFIG_CHANGE.indication"
if (!strncmp
((char *)event, WMM_CONFIG_CHANGE_INDICATION,
strlen(WMM_CONFIG_CHANGE_INDICATION))) {
printf("EVENT: STA_DISCONNECTED\n");
break;
}
#define CUS_EVT_DRIVER_HANG "EVENT=DRIVER_HANG"
if (!strncmp
((char *)event, CUS_EVT_DRIVER_HANG,
strlen(CUS_EVT_DRIVER_HANG))) {
printf("EVENT: DRIVER_HANG\n");
break;
}
printf("ERR:Undefined event type (0x%X). Dumping event buffer:\n", (unsigned int)event_id);
hexdump((void *)event, size, ' ');
break;
}
return;
}
/**
* @brief Read event data from netlink socket
*
* @param sk_fd Netlink socket handler
* @param buffer Pointer to the data buffer
* @param nlh Pointer to netlink message header
* @param msg Pointer to message header
* @return Number of bytes read or MLAN_EVENT_FAILURE
*/
int
read_event_netlink_socket(int sk_fd, unsigned char *buffer,
struct nlmsghdr *nlh, struct msghdr *msg)
{
int count = -1;
count = recvmsg(sk_fd, msg, 0);
#if DEBUG
printf("DBG:Waiting for message from NETLINK.\n");
#endif
if (count < 0) {
printf("ERR:NETLINK read failed!\n");
terminate_flag++;
return MLAN_EVENT_FAILURE;
}
#if DEBUG
printf("DBG:Received message payload (%d)\n", count);
#endif
if (count > NLMSG_SPACE(NL_MAX_PAYLOAD)) {
printf("ERR:Buffer overflow!\n");
return MLAN_EVENT_FAILURE;
}
memset(buffer, 0, NL_MAX_PAYLOAD);
memcpy(buffer, NLMSG_DATA(nlh), count - NLMSG_HDRLEN);
#if DEBUG
hexdump(buffer, count - NLMSG_HDRLEN, ' ');
#endif
return count - NLMSG_HDRLEN;
}
/**
* @brief Configure and read event data from netlink socket
*
* @param sk_fd Array of netlink sockets
* @param no_of_sk Number of netlink sockets opened
* @param recv_buf Pointer to the array of evt_buf structures
* @param timeout Socket listen timeout value
* @param nlh Pointer to netlink message header
* @param msg Pointer to message header
* @return Number of bytes read or MLAN_EVENT_FAILURE
*/
int
read_event(int *sk_fd, int no_of_sk, evt_buf *recv_buf, int timeout,
struct nlmsghdr *nlh, struct msghdr *msg)
{
struct timeval tv;
fd_set rfds;
int i = 0, max_sk_fd = sk_fd[0];
int ret = MLAN_EVENT_FAILURE;
/* Setup read fds */
FD_ZERO(&rfds);
for (i = 0; i < no_of_sk; i++) {
if (sk_fd[i] > max_sk_fd)
max_sk_fd = sk_fd[i];
if (sk_fd[i] > 0)
FD_SET(sk_fd[i], &rfds);
}
/* Initialize timeout value */
if (timeout != 0)
tv.tv_sec = timeout;
else
tv.tv_sec = UAP_RECV_WAIT_DEFAULT;
tv.tv_usec = 0;
/* Wait for reply */
ret = select(max_sk_fd + 1, &rfds, NULL, NULL, &tv);
if (ret == -1) {
/* Error */
terminate_flag++;
return MLAN_EVENT_FAILURE;
} else if (!ret) {
/* Timeout. Try again */
return MLAN_EVENT_FAILURE;
}
for (i = 0; i < no_of_sk; i++) {
if (sk_fd[i] > 0) {
if (FD_ISSET(sk_fd[i], &rfds)) {
/* Success */
recv_buf[i].flag = 1;
recv_buf[i].length =
read_event_netlink_socket(sk_fd[i],
recv_buf[i].
buffer, nlh,
msg);
ret += recv_buf[i].length;
}
}
}
return ret;
}
/* Command line options */
static const struct option long_opts[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0}
};
/**
* @brief Determine the netlink number
*
* @param i socket number
*
* @return Netlink number to use
*/
static int
get_netlink_num(int i)
{
FILE *fp;
int netlink_num = NETLINK_MARVELL;
char str[64];
char *srch = "netlink_num";
char filename[64];
if (i == 0) {
strcpy(filename, "/proc/mwlan/config");
} else if (i > 0) {
sprintf(filename, "/proc/mwlan/config%d", i);
}
/* Try to open /proc/mwlan/config$ */
fp = fopen(filename, "r");
if (fp) {
while (!feof(fp)) {
fgets(str, sizeof(str), fp);
if (strncmp(str, srch, strlen(srch)) == 0) {
netlink_num = atoi(str + strlen(srch) + 1);
break;
}
}
fclose(fp);
} else {
return -1;
}
printf("Netlink number = %d\n", netlink_num);
return netlink_num;
}
/****************************************************************************
Global functions
****************************************************************************/
/**
* @brief The main function
*
* @param argc Number of arguments
* @param argv Pointer to the arguments
* @return 0 or 1
*/
int
main(int argc, char *argv[])
{
int opt;
int nl_sk[MAX_NO_OF_DEVICES];
struct nlmsghdr *nlh = NULL;
struct sockaddr_nl src_addr, dest_addr;
struct msghdr msg;
struct iovec iov;
evt_buf evt_recv_buf[MAX_NO_OF_DEVICES];
struct timeval current_time;
struct tm *timeinfo;
int num_events = 0;
event_header *event = NULL;
int ret = MLAN_EVENT_FAILURE;
int netlink_num[MAX_NO_OF_DEVICES];
char if_name[IFNAMSIZ + 1];
t_u32 event_id = 0;
int i = 0, no_of_sk = 0, dev_index = -1;
/* Check command line options */
while ((opt = getopt_long(argc, argv, "hvti:", long_opts, NULL)) > 0) {
switch (opt) {
case 'h':
print_usage();
return 0;
case 'v':
printf("mlanevent version : %s\n", MLAN_EVENT_VERSION);
return 0;
break;
case 'i':
if ((IS_HEX_OR_DIGIT(argv[2]) == MLAN_EVENT_FAILURE) ||
(A2HEXDECIMAL(argv[2]) < 0)
|| ((A2HEXDECIMAL(argv[2]) >= MAX_NO_OF_DEVICES) &&
(A2HEXDECIMAL(argv[2]) != 0xff))) {
print_usage();
return 1;
} else {
dev_index = A2HEXDECIMAL(argv[2]);
argc -= optind;
argv += optind;
}
break;
default:
print_usage();
return 1;
}
}
if (optind < argc) {
fputs("Too many arguments.\n", stderr);
print_usage();
return 1;
}
if ((dev_index >= 0) && (dev_index < MAX_NO_OF_DEVICES)) {
no_of_sk = 1;
} else {
/* Currently, we support maximum 4 devices */
/* TODO: determine no_of_sk at run time */
no_of_sk = MAX_NO_OF_DEVICES;
}
for (i = 0; i < no_of_sk; i++) {
/* Initialise */
nl_sk[i] = -1;
if (no_of_sk == 1) {
netlink_num[i] = get_netlink_num(dev_index);
if (netlink_num[i] < 0) {
printf("ERR:Could not get netlink socket. Invalid device number.\n");
ret = MLAN_EVENT_FAILURE;
goto done;
}
} else {
netlink_num[i] = get_netlink_num(i);
}
if (netlink_num[i] >= 0) {
/* Open netlink socket */
nl_sk[i] = socket(PF_NETLINK, SOCK_RAW, netlink_num[i]);
if (nl_sk[i] < 0) {
printf("ERR:Could not open netlink socket.\n");
ret = MLAN_EVENT_FAILURE;
goto done;
}
/* Set source address */
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* Our PID */
src_addr.nl_groups = NL_MULTICAST_GROUP;
/* Bind socket with source address */
if (bind
(nl_sk[i], (struct sockaddr *)&src_addr,
sizeof(src_addr)) < 0) {
printf("ERR:Could not bind socket!\n");
ret = MLAN_EVENT_FAILURE;
goto done;
}
/* Set destination address */
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* Kernel */
dest_addr.nl_groups = NL_MULTICAST_GROUP;
/* Initialize netlink header */
nlh = (struct nlmsghdr *)
malloc(NLMSG_SPACE(NL_MAX_PAYLOAD));
if (!nlh) {
printf("ERR: Could not alloc buffer\n");
ret = MLAN_EVENT_FAILURE;
goto done;
}
memset(nlh, 0, NLMSG_SPACE(NL_MAX_PAYLOAD));
/* Initialize I/O vector */
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(NL_MAX_PAYLOAD);
/* Initialize message header */
memset(&msg, 0, sizeof(struct msghdr));
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
memset(&evt_recv_buf[i], 0, sizeof(evt_buf));
}
}
gettimeofday(&current_time, NULL);
printf("\n");
printf("**********************************************\n");
if ((timeinfo = localtime(&(current_time.tv_sec))))
printf("mlanevent start time : %s", asctime(timeinfo));
printf(" %u usecs\n",
(unsigned int)current_time.tv_usec);
printf("**********************************************\n");
signal(SIGTERM, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGALRM, sig_handler);
while (1) {
if (terminate_flag) {
printf("Stopping!\n");
break;
}
ret = read_event(nl_sk, no_of_sk, evt_recv_buf, 0, nlh, &msg);
/* No result. Loop again */
if (ret == MLAN_EVENT_FAILURE) {
continue;
}
if (ret == 0) {
/* Zero bytes received */
printf("ERR:Received zero bytes!\n");
continue;
}
for (i = 0; i < no_of_sk; i++) {
if (evt_recv_buf[i].flag == 1) {
num_events++;
gettimeofday(&current_time, NULL);
printf("\n");
printf("============================================\n");
printf("Received event");
if ((timeinfo =
localtime(&(current_time.tv_sec))))
printf(": %s", asctime(timeinfo));
printf(" %u usecs\n",
(unsigned int)current_time.tv_usec);
printf("============================================\n");
memcpy(&event_id, evt_recv_buf[i].buffer,
sizeof(event_id));
if (((event_id & 0xFF000000) == 0x80000000) ||
((event_id & 0xFF000000) == 0)) {
event = (event_header
*)(evt_recv_buf[i].buffer);
} else {
memset(if_name, 0, IFNAMSIZ + 1);
memcpy(if_name, evt_recv_buf[i].buffer,
IFNAMSIZ);
printf("EVENT for interface %s\n",
if_name);
event = (event_header
*)((t_u8 *)(evt_recv_buf[i].
buffer) +
IFNAMSIZ);
ret -= IFNAMSIZ;
evt_recv_buf[i].length -= IFNAMSIZ;
}
#if DEBUG
printf("DBG:Received buffer =\n");
hexdump(evt_recv_buf[i].buffer,
evt_recv_buf[i].length + IFNAMSIZ, ' ');
#endif
print_event(event, evt_recv_buf[i].length);
/* Reset event flag after reading */
evt_recv_buf[i].flag = 0;
}
}
fflush(stdout);
}
gettimeofday(&current_time, NULL);
printf("\n");
printf("*********************************************\n");
if ((timeinfo = localtime(&(current_time.tv_sec))))
printf("mlanevent end time : %s", asctime(timeinfo));
printf(" %u usecs\n",
(unsigned int)current_time.tv_usec);
printf("Total events : %u\n", num_events);
printf("*********************************************\n");
done:
for (i = 0; i < no_of_sk; i++) {
if (nl_sk[i] > 0)
close(nl_sk[i]);
}
if (nlh)
free(nlh);
return 0;
}