From c26bfff033443bf5b964e97d18f606b0b645c7de Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 20 Jul 2011 16:53:58 +0200 Subject: [PATCH 1/1] Imported Upstream version 1.4 --- Makefile | 50 +++ uapevent.c | 899 +++++++++++++++++++++++++++++++++++++++++++++++++++++ uapevent.h | 508 ++++++++++++++++++++++++++++++ 3 files changed, 1457 insertions(+) create mode 100755 Makefile create mode 100644 uapevent.c create mode 100644 uapevent.h diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..5817989 --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +# File : uapevent/Makefile +# +# Copyright (C) 2008, Marvell International Ltd. +# All Rights Reserved + +# Path to the top directory of the wlan distribution +PATH_TO_TOP = ../.. + +# Determine how we should copy things to the install directory +ABSPATH := $(filter /%, $(INSTALLDIR)) +RELPATH := $(filter-out /%, $(INSTALLDIR)) +INSTALLPATH := $(ABSPATH) +ifeq ($(strip $(INSTALLPATH)),) +INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH) +endif + +# Override CFLAGS for application sources, remove __ kernel namespace defines +CFLAGS := $(filter-out -D__%, $(EXTRA_CFLAGS)) + + +#CFLAGS += -DAP22 -fshort-enums +CFLAGS += -Wall +#ECHO = @ +LIBS = -lrt + +.PHONY: default tags all + +OBJECTS = uapevent.o +HEADERS = uapevent.h + +TARGET = uapevent + +build default: $(TARGET) + @cp -f $(TARGET) $(INSTALLPATH) + +all : tags default + +$(TARGET): $(OBJECTS) $(HEADERS) + $(ECHO)$(CC) $(LIBS) -o $@ $(OBJECTS) + +%.o: %.c $(HEADERS) + $(ECHO)$(CC) $(CFLAGS) -c -o $@ $< + +tags: + ctags -R -f tags.txt + +clean: + $(ECHO)$(RM) $(OBJECTS) $(TARGET) + $(ECHO)$(RM) tags.txt + diff --git a/uapevent.c b/uapevent.c new file mode 100644 index 0000000..b68b290 --- /dev/null +++ b/uapevent.c @@ -0,0 +1,899 @@ +/** @file uapevent.c + * + * @brief Program to receive events from the driver/firmware of the uAP + * driver. + * + * Copyright (C) 2008-2009, 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "uapevent.h" + +/**************************************************************************** + 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, s32 len, s8 delim) +{ + s32 i; + 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 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(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 : uapevent.exe [-v] [-h]\n"); + printf(" -v : Print version information\n"); + printf(" -h : Print help information\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(u8 * buffer, 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->ReasonCode = uap_le16_to_cpu(event_body->ReasonCode); + printf("EVENT: STA_DEAUTH\n"); + printf("Deauthenticated STA MAC: "); + print_mac(event_body->StaMacAddress); + printf("\nReason: "); + switch (event_body->ReasonCode) { + case 1: + printf("Unspecified reason.\n"); + break; + case 2: + printf("Previous authentication no longer valid.\n"); + break; + case 3: + printf("Deauthenticated because sending STA is leaving IBSS or ESS.\n"); + break; + case 4: + printf("Disassociated due to inactivity.\n"); + break; + case 5: + printf + ("Disassociated because AP is unable to handle all currently associated STAs.\n"); + break; + case 6: + printf("Class 2 frame received from nonauthenticated STA.\n"); + break; + case 7: + printf("Class 3 frame received from nonassociated STA.\n"); + break; + case 8: + printf("Disassociated because sending STA is leaving BSS.\n"); + break; + case 9: + printf + ("STA requesting (re)association is not authenticated with responding STA.\n"); + break; + case 10: + printf + ("Disassociated because the information in the Power Capability element is unacceptable.\n"); + break; + case 11: + printf + ("Disassociated because the information in the Supported Channels element is unacceptable.\n"); + break; + case 13: + printf("Invalid information element.\n"); + break; + case 14: + printf("Message integrity code (MIC) failure.\n"); + break; + case 15: + printf("4-Way Handshake timeout.\n"); + break; + case 16: + printf("Group Key Handshake timeout.\n"); + break; + case 17: + printf("Information element in 4-Way Handshake different from\n"); + printf(" (Re)Association Request/Probe Response/Beacon frame.\n"); + break; + case 18: + printf("Invalid group cipher.\n"); + break; + case 19: + printf("Invalid pairwise cipher.\n"); + break; + case 20: + printf("Invalid AKMP.\n"); + break; + case 21: + printf("Unsupported RSN information element version.\n"); + break; + case 22: + printf("Invalid RSN information element capabilities.\n"); + break; + case 23: + printf("IEEE 802.1X authentication failed.\n"); + break; + case 24: + printf("Cipher suite rejected because of the security policy.\n"); + break; + case 32: + printf("Disassociated for unspecified, QoS-related reason.\n"); + break; + case 33: + printf + ("Disassociated because QoS AP lacks sufficient bandwidth for this QoS STA.\n"); + break; + case 34: + printf + ("Disassociated because excessive number of frames need to be acknowledged\n"); + printf + (" but are not acknowledged due to AP transmissions and or poor channel conditions.\n"); + break; + case 35: + printf + ("Disassociated because STA is transmitting outside the limits of its TXOPs.\n"); + break; + case 36: + printf + ("Requested from peer STA as the STA is leaving the BSS or resetting.\n"); + break; + case 37: + printf + ("Requested from peer STA as it does not want to use the mechanism.\n"); + break; + case 38: + printf("Requested from peer STA as the STA received frames using"); + printf(" the mechanism for which a setup is required.\n"); + break; + case 39: + printf("Requested from peer STA due to timeout.\n"); + break; + case 45: + printf("Peer STA does not support the requested cipher suite.\n"); + break; + default: + printf("Reserved or Unspecified\n"); + break; + } + 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; + u16 frmctl = 0; + printf("\nMgmt Frame:\n"); + memcpy(&frmctl, &mgmt_tlv->FrameControl, sizeof(u16)); + printf("FrameControl: 0x%x\n", frmctl); + if (mgmt_tlv->FrameControl.Type != 0) { + printf("Frame type=%d subtype=%d:\n", mgmt_tlv->FrameControl.Type, + mgmt_tlv->FrameControl.Subtype); + hexdump(mgmt_tlv->FrameContents, tlv_len - sizeof(u16), ' '); + return; + } + switch (mgmt_tlv->FrameControl.Subtype) { + case SUBTYPE_ASSOC_REQUEST: + printf("Assoc Request:\n"); + assoc_req = (IEEEtypes_AssocRqst_t *) mgmt_tlv->FrameContents; + printf("CapInfo: 0x%x ListenInterval: 0x%x \n", + uap_le16_to_cpu(assoc_req->CapInfo), + uap_le16_to_cpu(assoc_req->ListenInterval)); + printf("AssocReqIE:\n"); + hexdump(assoc_req->IEBuffer, + 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->FrameContents; + printf("CapInfo: 0x%x ListenInterval: 0x%x \n", + uap_le16_to_cpu(reassoc_req->CapInfo), + uap_le16_to_cpu(reassoc_req->ListenInterval)); + printf("Current AP address: "); + print_mac(reassoc_req->CurrentApAddr); + printf("\nReAssocReqIE:\n"); + hexdump(reassoc_req->IEBuffer, + tlv_len - sizeof(IEEEtypes_ReAssocRqst_t) - + sizeof(IEEEtypes_FrameCtl_t), ' '); + break; + case SUBTYPE_ASSOC_RESPONSE: + case SUBTYPE_REASSOC_RESPONSE: + if (mgmt_tlv->FrameControl.Subtype == SUBTYPE_ASSOC_RESPONSE) + printf("Assoc Response:\n"); + else + printf("ReAssoc Response:\n"); + assoc_resp = (IEEEtypes_AssocRsp_t *) mgmt_tlv->FrameContents; + printf("CapInfo: 0x%x StatusCode: %d AID: 0x%x \n", + uap_le16_to_cpu(assoc_resp->CapInfo), + (int) (uap_le16_to_cpu(assoc_resp->StatusCode)), + uap_le16_to_cpu(assoc_resp->AId) & 0x3fff); + break; + default: + printf("Frame subtype = %d:\n", mgmt_tlv->FrameControl.Subtype); + hexdump(mgmt_tlv->FrameContents, tlv_len - sizeof(u16), ' '); + break; + } + 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(u8 * buffer, u16 size) +{ + int tlvBufLeft = size; + u16 tlvType, tlvLen; + 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->StaMacAddress); + printf("\n"); + tlvBufLeft = size - sizeof(EVENTBUF_STA_ASSOC); + if (tlvBufLeft < (int) sizeof(tlvbuf_header)) + return; + tlv = (tlvbuf_header *) (buffer + sizeof(EVENTBUF_STA_ASSOC)); + + while (tlvBufLeft >= (int) sizeof(tlvbuf_header)) { + tlvType = uap_le16_to_cpu(tlv->type); + tlvLen = uap_le16_to_cpu(tlv->len); + if ((sizeof(tlvbuf_header) + tlvLen) > tlvBufLeft) { + printf("wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlvLen, tlvBufLeft); + break; + } + switch (tlvType) { + case MRVL_WAPI_INFO_TLV_ID: + wapi_tlv = (MrvlIEtypes_WapiInfoSet_t *) tlv; + printf("WAPI Multicast PN:\n"); + hexdump(wapi_tlv->MulticastPN, tlvLen, ' '); + break; + case MRVL_MGMT_FRAME_TLV_ID: + mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *) tlv; + print_mgmt_frame(mgmt_tlv, tlvLen); + break; + default: + printf("unknown tlv: %d\n", tlvType); + break; + } + tlvBufLeft -= (sizeof(tlvbuf_header) + tlvLen); + tlv = (tlvbuf_header *) ((u8 *) tlv + tlvLen + 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(u8 * buffer, u16 size) +{ + EVENTBUF_BSS_START *event_body = 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->apMacAddress); + printf("\n"); + return; +} + +/** + * @brief Prints station reject state + * + * @param state fail state + * @return N/A + */ +void +print_reject_state(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(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(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(u8 * buffer, 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->debugtype == 0) ? "EVENT" : "INFO"); + printf("%s log:\n", + (uap_le32_to_cpu(event_body->debugIdMajor) == + DEBUG_ID_MAJ_AUTHENTICATOR) ? "Authenticator" : "Assoc_agent"); + if (uap_le32_to_cpu(event_body->debugIdMajor) == DEBUG_ID_MAJ_AUTHENTICATOR) { + switch (uap_le32_to_cpu(event_body->debugIdMinor)) { + case DEBUG_MAJ_AUTH_MIN_PWK1: + printf("EAPOL Key message 1 (PWK):\n"); + hexdump((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((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((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((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((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((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.staMacAddr); + 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.staMacAddr); + printf("\n"); + print_eapol_state(event_body->info.eapol_state.eapolState); + break; + default: + printf("ERR: unknow debugIdMinor: %d\n", + (int) uap_le32_to_cpu(event_body->debugIdMinor)); + hexdump(buffer, size, ' '); + return; + } + } else if (uap_le32_to_cpu(event_body->debugIdMajor) == + DEBUG_ID_MAJ_ASSOC_AGENT) { + switch (uap_le32_to_cpu(event_body->debugIdMinor)) { + case DEBUG_ID_MAJ_ASSOC_MIN_WPA_IE: + printf("STA MAC: "); + print_mac(event_body->info.wpaIe.staMacAddr); + 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.staMacAddr); + 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 debugIdMinor: %d\n", + (int) uap_le32_to_cpu(event_body->debugIdMinor)); + hexdump(buffer, size, ' '); + return; + } + } + 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(EVENTHEADER * event, u16 size) +{ + u32 event_id = event->EventId & EVENT_ID_MASK; + switch (event_id) { + case MICRO_AP_EV_ID_STA_DEAUTH: + print_event_sta_deauth(event->EventData, size - EVENT_ID_LEN); + break; + case MICRO_AP_EV_ID_STA_ASSOC: + print_event_sta_assoc(event->EventData, size - EVENT_ID_LEN); + break; + case MICRO_AP_EV_ID_BSS_START: + print_event_bss_start(event->EventData, size - EVENT_ID_LEN); + break; + case MICRO_AP_EV_ID_DEBUG: + print_event_debug(event->EventData, 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; + default: + printf("ERR:Undefined event type (%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 UAP_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 UAP_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 UAP_FAILURE; + } + bzero(buffer, 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 Netlink socket handler + * @param buffer Pointer to the data buffer + * @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 UAP_FAILURE + */ +int +read_event(int sk_fd, unsigned char *buffer, int timeout, struct nlmsghdr *nlh, + struct msghdr *msg) +{ + struct timeval tv; + fd_set rfds; + int ret = UAP_FAILURE; + + /* Setup read fds */ + FD_ZERO(&rfds); + FD_SET(sk_fd, &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(sk_fd + 1, &rfds, NULL, NULL, &tv); + if (ret == -1) { + /* Error */ + terminate_flag++; + return UAP_FAILURE; + } else if (!ret) { + /* Timeout. Try again */ + return UAP_FAILURE; + } + if (!FD_ISSET(sk_fd, &rfds)) { + /* Unexpected error. Try again */ + return UAP_FAILURE; + } + + /* Success */ + ret = read_event_netlink_socket(sk_fd, buffer, nlh, msg); + 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} +}; + +/**************************************************************************** + 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 = 0; + struct nlmsghdr *nlh = NULL; + struct sockaddr_nl src_addr, dest_addr; + struct msghdr msg; + struct iovec iov; + unsigned char *buffer = NULL; + struct timeval current_time; + struct tm *timeinfo; + int num_events = 0; + EVENTHEADER *event = NULL; + int ret = UAP_FAILURE; + + /* Check command line options */ + while ((opt = getopt_long(argc, argv, "hvt", long_opts, NULL)) > 0) { + switch (opt) { + case 'h': + print_usage(); + return 0; + case 'v': + printf("uapevent version : %s\n", UAP_VERSION); + return 0; + break; + default: + print_usage(); + return 1; + } + } + if (optind < argc) { + fputs("Too many arguments.\n", stderr); + print_usage(); + return 1; + } + + /* Open netlink socket */ + nl_sk = socket(PF_NETLINK, SOCK_RAW, NETLINK_MARVELL); + if (nl_sk < 0) { + printf("ERR:Could not open netlink socket.\n"); + ret = UAP_FAILURE; + goto done; + } + + /* Set source address */ + bzero((char *) &src_addr, 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, (struct sockaddr *) &src_addr, sizeof(src_addr)) < 0) { + printf("ERR:Could not bind socket!\n"); + ret = UAP_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 = UAP_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; + + /* Initialize receive buffer */ + buffer = malloc(NL_MAX_PAYLOAD); + if (!buffer) { + printf("ERR: Could not alloc buffer\n"); + ret = UAP_FAILURE; + goto done; + } + bzero(buffer, sizeof(buffer)); + + gettimeofday(¤t_time, NULL); + + printf("\n"); + printf("*********************************************\n"); + if ((timeinfo = localtime(&(current_time.tv_sec)))) + printf("uapevent 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, buffer, 0, nlh, &msg); + + /* No result. Loop again */ + if (ret == UAP_FAILURE) { + continue; + } + if (ret == 0) { + /* Zero bytes received */ + printf("ERR:Received zero bytes!\n"); + continue; + } + num_events++; + gettimeofday(¤t_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"); + event = (EVENTHEADER *) buffer; + event->EventId = uap_le32_to_cpu(event->EventId); +#if DEBUG + printf("DBG:Received buffer =\n"); + hexdump(buffer, ret, ' '); +#endif + print_event(event, ret); + fflush(stdout); + } + gettimeofday(¤t_time, NULL); + printf("\n"); + printf("********************************************\n"); + if ((timeinfo = localtime(&(current_time.tv_sec)))) + printf("uapevent 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: + if (buffer) + free(buffer); + if (nl_sk) + close(nl_sk); + if (nlh) + free(nlh); + return 0; +} diff --git a/uapevent.h b/uapevent.h new file mode 100644 index 0000000..bc84577 --- /dev/null +++ b/uapevent.h @@ -0,0 +1,508 @@ +/** @file uapevent.h + * + * @brief Header file for uapevent application + * + * Copyright (C) 2008-2009, 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 +************************************************************************/ + +#ifndef _UAP_H +#define _UAP_H + +#if (BYTE_ORDER == LITTLE_ENDIAN) +#undef BIG_ENDIAN +#endif + +/** 16 bits byte swap */ +#define swap_byte_16(x) \ + ((u16)((((u16)(x) & 0x00ffU) << 8) | \ + (((u16)(x) & 0xff00U) >> 8))) + +/** 32 bits byte swap */ +#define swap_byte_32(x) \ + ((u32)((((u32)(x) & 0x000000ffUL) << 24) | \ + (((u32)(x) & 0x0000ff00UL) << 8) | \ + (((u32)(x) & 0x00ff0000UL) >> 8) | \ + (((u32)(x) & 0xff000000UL) >> 24))) + +/** 64 bits byte swap */ +#define swap_byte_64(x) \ + ((u64)((u64)(((u64)(x) & 0x00000000000000ffULL) << 56) | \ + (u64)(((u64)(x) & 0x000000000000ff00ULL) << 40) | \ + (u64)(((u64)(x) & 0x0000000000ff0000ULL) << 24) | \ + (u64)(((u64)(x) & 0x00000000ff000000ULL) << 8) | \ + (u64)(((u64)(x) & 0x000000ff00000000ULL) >> 8) | \ + (u64)(((u64)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (u64)(((u64)(x) & 0x00ff000000000000ULL) >> 40) | \ + (u64)(((u64)(x) & 0xff00000000000000ULL) >> 56) )) + +#ifdef BIG_ENDIAN +/** Convert from 16 bit little endian format to CPU format */ +#define uap_le16_to_cpu(x) swap_byte_16(x) +/** Convert from 32 bit little endian format to CPU format */ +#define uap_le32_to_cpu(x) swap_byte_32(x) +/** Convert from 64 bit little endian format to CPU format */ +#define uap_le64_to_cpu(x) swap_byte_64(x) +/** Convert to 16 bit little endian format from CPU format */ +#define uap_cpu_to_le16(x) swap_byte_16(x) +/** Convert to 32 bit little endian format from CPU format */ +#define uap_cpu_to_le32(x) swap_byte_32(x) +/** Convert to 64 bit little endian format from CPU format */ +#define uap_cpu_to_le64(x) swap_byte_64(x) +#else /* BIG_ENDIAN */ +/** Do nothing */ +#define uap_le16_to_cpu(x) x +/** Do nothing */ +#define uap_le32_to_cpu(x) x +/** Do nothing */ +#define uap_le64_to_cpu(x) x +/** Do nothing */ +#define uap_cpu_to_le16(x) x +/** Do nothing */ +#define uap_cpu_to_le32(x) x +/** Do nothing */ +#define uap_cpu_to_le64(x) x +#endif /* BIG_ENDIAN */ + +/** uAP application version string */ +#define UAP_VERSION "uAP 1.4" + +/** Success */ +#define UAP_SUCCESS 1 +/** Failure */ +#define UAP_FAILURE -1 + +#ifdef __GNUC__ +/** Structure packing begins */ +#define PACK_START +/** Structure packeing end */ +#define PACK_END __attribute__ ((packed)) +#else +/** Structure packing begins */ +#define PACK_START __packed +/** Structure packeing end */ +#define PACK_END +#endif + +#ifndef ETH_ALEN +/** MAC address length */ +#define ETH_ALEN 6 +#endif + +/** Netlink protocol number */ +#define NETLINK_MARVELL (MAX_LINKS - 1) +/** Netlink maximum payload size */ +#define NL_MAX_PAYLOAD 1024 +/** Netlink multicast group number */ +#define NL_MULTICAST_GROUP 1 +/** Default wait time in seconds for events */ +#define UAP_RECV_WAIT_DEFAULT 10 + +/** Character, 1 byte */ +typedef char s8; +/** Unsigned character, 1 byte */ +typedef unsigned char u8; + +/** Short integer */ +typedef signed short s16; +/** Unsigned short integer */ +typedef unsigned short u16; + +/** Long integer */ +typedef signed long s32; +/** Unsigned long integer */ +typedef unsigned long u32; + +/** event ID mask */ +#define EVENT_ID_MASK 0x0fff + +/** Event header */ +typedef PACK_START struct _EVENTHEADER +{ + /** Event ID */ + u32 EventId; + /** Event data */ + u8 EventData[0]; +} PACK_END EVENTHEADER; + +/** Event ID length */ +#define EVENT_ID_LEN 4 + +/** Event ID: STA deauth */ +#define MICRO_AP_EV_ID_STA_DEAUTH 44 + +/** Event ID: STA associated */ +#define MICRO_AP_EV_ID_STA_ASSOC 45 + +/** Event ID: BSS started */ +#define MICRO_AP_EV_ID_BSS_START 46 + +/** Event ID: Debug event */ +#define MICRO_AP_EV_ID_DEBUG 54 + +/** Event ID: BSS idle event */ +#define MICRO_AP_EV_BSS_IDLE 67 + +/** Event ID: BSS active event */ +#define MICRO_AP_EV_BSS_ACTIVE 68 + +/** TLV buffer header*/ +typedef PACK_START struct _tlvbuf_header +{ + /** Header type */ + u16 type; + /** Header length */ + u16 len; +} PACK_END tlvbuf_header; + +/** TLV ID : WAPI Information */ +#define MRVL_WAPI_INFO_TLV_ID 0x0167 + +/** TLV ID : Management Frame */ +#define MRVL_MGMT_FRAME_TLV_ID 0x0168 +/** Assoc Request */ +#define SUBTYPE_ASSOC_REQUEST 0 +/** Assoc Response */ +#define SUBTYPE_ASSOC_RESPONSE 1 +/** ReAssoc Request */ +#define SUBTYPE_REASSOC_REQUEST 2 +/** ReAssoc Response */ +#define SUBTYPE_REASSOC_RESPONSE 3 + +/** Event body : STA deauth */ +typedef PACK_START struct _EVENTBUF_STA_DEAUTH +{ + /** Deauthentication reason */ + u16 ReasonCode; + /** MAC address of deauthenticated STA */ + u8 StaMacAddress[ETH_ALEN]; +} PACK_END EVENTBUF_STA_DEAUTH; + +/** Event body : STA associated */ +typedef PACK_START struct _EVENTBUF_STA_ASSOC +{ + /** Reserved */ + u8 Reserved[2]; + /** MAC address of associated STA */ + u8 StaMacAddress[ETH_ALEN]; + /** Assoc request/response buffer */ + u8 AssocPayload[0]; +} PACK_END EVENTBUF_STA_ASSOC; + +/** Event body : BSS started */ +typedef PACK_START struct _EVENTBUF_BSS_START +{ + /** Reserved */ + u8 Reserved[2]; + /** MAC address of BSS */ + u8 apMacAddress[ETH_ALEN]; +} PACK_END EVENTBUF_BSS_START; + +/** + * IEEE 802.11 MAC Message Data Structures + * + * Each IEEE 802.11 MAC message includes a MAC header, a frame body (which + * can be empty), and a frame check sequence field. This section gives the + * structures that used for the MAC message headers and frame bodies that + * can exist in the three types of MAC messages - 1) Control messages, + * 2) Data messages, and 3) Management messages. + */ +#ifdef BIG_ENDIAN +typedef PACK_START struct _IEEEtypes_FrameCtl_t +{ + /** Order */ + u8 Order:1; + /** Wep */ + u8 Wep:1; + /** MoreData */ + u8 MoreData:1; + /** PwrMgmt */ + u8 PwrMgmt:1; + /** Retry */ + u8 Retry:1; + /** MoreFrag */ + u8 MoreFrag:1; + /** FromDs */ + u8 FromDs:1; + /** ToDs */ + u8 ToDs:1; + /** Subtype */ + u8 Subtype:4; + /** Type */ + u8 Type:2; + /** Protocol Version */ + u8 ProtocolVersion:2; +} PACK_END IEEEtypes_FrameCtl_t; +#else +typedef PACK_START struct _IEEEtypes_FrameCtl_t +{ + /** Protocol Version */ + u8 ProtocolVersion:2; + /** Type */ + u8 Type:2; + /** Subtype */ + u8 Subtype:4; + /** ToDs */ + u8 ToDs:1; + /** FromDs */ + u8 FromDs:1; + /** MoreFrag */ + u8 MoreFrag:1; + /** Retry */ + u8 Retry:1; + /** PwrMgmt */ + u8 PwrMgmt:1; + /** MoreData */ + u8 MoreData:1; + /** Wep */ + u8 Wep:1; + /** Order */ + u8 Order:1; +} PACK_END IEEEtypes_FrameCtl_t; +#endif + +/** IEEEtypes_AssocRqst_t */ +typedef PACK_START struct _IEEEtypes_AssocRqst_t +{ + /** CapInfo */ + u16 CapInfo; + /** ListenInterval */ + u16 ListenInterval; + /** IE Buffer */ + u8 IEBuffer[0]; +} PACK_END IEEEtypes_AssocRqst_t; + +/** IEEEtypes_AssocRsp_t */ +typedef PACK_START struct _IEEEtypes_AssocRsp_t +{ + /** CapInfo */ + u16 CapInfo; + /** StatusCode */ + u16 StatusCode; + /** AID */ + u16 AId; +} PACK_END IEEEtypes_AssocRsp_t; + +/** IEEEtypes_ReAssocRqst_t */ +typedef PACK_START struct _IEEEtypes_ReAssocRqst_t +{ + /** CapInfo */ + u16 CapInfo; + /** ListenInterval */ + u16 ListenInterval; + /** Current APAddr */ + u8 CurrentApAddr[ETH_ALEN]; + /** IE Buffer */ + u8 IEBuffer[0]; +} PACK_END IEEEtypes_ReAssocRqst_t; + +/** MrvlIEtypes_WapiInfoSet_t */ +typedef PACK_START struct _MrvlIEtypes_WapiInfoSet_t +{ + /** Type */ + u16 Type; + /** Length */ + u16 Len; + /** Multicast PN */ + u8 MulticastPN[16]; +} PACK_END MrvlIEtypes_WapiInfoSet_t; + +/** MrvlIETypes_MgmtFrameSet_t */ +typedef PACK_START struct _MrvlIETypes_MgmtFrameSet_t +{ + /** Type */ + u16 Type; + /** Length */ + u16 Len; + /** Frame Control */ + IEEEtypes_FrameCtl_t FrameControl; + /** Frame Contents */ + u8 FrameContents[0]; +} PACK_END MrvlIETypes_MgmtFrameSet_t; + +/**Debug Type : Event */ +#define DEBUG_TYPE_EVENT 0 +/**Debug Type : Info */ +#define DEBUG_TYPE_INFO 1 + +/** Major debug id: Authenticator */ +#define DEBUG_ID_MAJ_AUTHENTICATOR 1 +/** Minor debug id: PWK1 */ +#define DEBUG_MAJ_AUTH_MIN_PWK1 0 +/** Minor debug id: PWK2 */ +#define DEBUG_MAJ_AUTH_MIN_PWK2 1 +/** Minor debug id: PWK3 */ +#define DEBUG_MAJ_AUTH_MIN_PWK3 2 +/** Minor debug id: PWK4 */ +#define DEBUG_MAJ_AUTH_MIN_PWK4 3 +/** Minor debug id: GWK1 */ +#define DEBUG_MAJ_AUTH_MIN_GWK1 4 +/** Minor debug id: GWK2 */ +#define DEBUG_MAJ_AUTH_MIN_GWK2 5 +/** Minor debug id: station reject */ +#define DEBUG_MAJ_AUTH_MIN_STA_REJ 6 +/** Minor debug id: EAPOL_TR */ +#define DEBUG_MAJ_AUTH_MIN_EAPOL_TR 7 + +/** Major debug id: Assoicate agent */ +#define DEBUG_ID_MAJ_ASSOC_AGENT 2 +/** Minor debug id: WPA IE*/ +#define DEBUG_ID_MAJ_ASSOC_MIN_WPA_IE 0 +/** Minor debug id: station reject */ +#define DEBUG_ID_MAJ_ASSOC_MIN_STA_REJ 1 + +/** ether_hdr */ +typedef PACK_START struct +{ + /** dest address */ + u8 da[ETH_ALEN]; + /** src address */ + u8 sa[ETH_ALEN]; + /** header type */ + u16 type; +} PACK_END ether_hdr_t; + +/** 8021x header */ +typedef PACK_START struct +{ + /** protocol version*/ + u8 protocol_ver; + /** packet type*/ + u8 pckt_type; + /** packet len */ + u8 pckt_body_len; +} PACK_END Hdr_8021x_t; + +/** nonce size */ +#define NONCE_SIZE 32 +/** max wpa ie len */ +#define MAX_WPA_IE_LEN 64 +/** EAPOL mic size */ +#define EAPOL_MIC_SIZE 16 + +/** EAPOL key message */ +typedef PACK_START struct +{ + /** Ether header */ + ether_hdr_t Ether_Hdr; + /** 8021x header */ + Hdr_8021x_t hdr_8021x; + /** desc_type */ + u8 desc_type; + /** key info */ + u16 k; + /** key length */ + u16 key_length; + /** replay count */ + u32 replay_cnt[2]; + /** key nonce */ + u8 key_nonce[NONCE_SIZE]; + /** key IV */ + u8 EAPOL_key_IV[16]; + /** key RSC */ + u8 key_RSC[8]; + /** key ID */ + u8 key_ID[8]; + /** key MIC */ + u8 key_MIC[EAPOL_MIC_SIZE]; + /** key len */ + u16 key_material_len; + /** key data */ + u8 key_data[MAX_WPA_IE_LEN]; +} PACK_END EAPOL_KeyMsg_Debug_t; + +/** failure after receive EAPOL MSG2 PMK */ +#define REJECT_STATE_FAIL_EAPOL_2 1 +/** failure after receive EAPOL MSG4 PMK*/ +#define REJECT_STATE_FAIL_EAPOL_4 2 +/** failure after receive EAPOL Group MSG2 GWK */ +#define REJECT_STATE_FAIL_EAPOL_GROUP_2 3 + +/** Fail reason: Invalid ie */ +#define IEEEtypes_REASON_INVALID_IE 13 +/** Fail reason: Mic failure */ +#define IEEEtypes_REASON_MIC_FAILURE 14 + +/** station reject */ +typedef PACK_START struct +{ + /** reject state */ + u8 reject_state; + /** reject reason */ + u16 reject_reason; + /** station mac address */ + u8 staMacAddr[ETH_ALEN]; +} PACK_END sta_reject_t; + +/** wpa_ie */ +typedef PACK_START struct +{ + /** station mac address */ + u8 staMacAddr[ETH_ALEN]; + /** wpa ie */ + u8 wpa_ie[MAX_WPA_IE_LEN]; +} PACK_END wpaIe_t; + +/** initial state of the state machine */ +#define EAPOL_START 1 +/** sent eapol msg1, wait for msg2 from the client */ +#define EAPOL_WAIT_PWK2 2 +/** sent eapol msg3, wait for msg4 from the client */ +#define EAPOL_WAIT_PWK4 3 +/** sent eapol group key msg1, wait for group msg2 from the client */ +#define EAPOL_WAIT_GTK2 4 +/** eapol handshake complete */ +#define EAPOL_END 5 + +/** eapol state */ +typedef PACK_START struct +{ + /** eapol state*/ + u8 eapolState; + /** station address*/ + u8 staMacAddr[ETH_ALEN]; +} PACK_END eapolState_t; + +/**debug Info */ +typedef PACK_START union +{ + /** eapol key message */ + EAPOL_KeyMsg_Debug_t eapol_pwkMsg; + /** station reject*/ + sta_reject_t sta_reject; + /** wpa ie */ + wpaIe_t wpaIe; + /** eapol state */ + eapolState_t eapol_state; +} PACK_END dInfo; + +/** Event body : Debug */ +typedef PACK_START struct _EVENTBUF_DEBUG +{ + /** debug type */ + u8 debugtype; + /** Major debug id */ + u32 debugIdMajor; + /** Minor debug id */ + u32 debugIdMinor; + /** debug Info */ + dInfo info; +} PACK_END EVENTBUF_DEBUG; +#endif /* _UAP_H */ -- 2.30.2