3a32ed12b6
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1015 lines
27 KiB
C
1015 lines
27 KiB
C
/*
|
|
*************************************************************************
|
|
* Ralink Tech Inc.
|
|
* 5F., No.36, Taiyuan St., Jhubei City,
|
|
* Hsinchu County 302,
|
|
* Taiwan, R.O.C.
|
|
*
|
|
* (c) Copyright 2002-2007, Ralink Technology, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
* *
|
|
*************************************************************************
|
|
*/
|
|
|
|
#include "rt_config.h"
|
|
|
|
ULONG RTDebugLevel = RT_DEBUG_ERROR;
|
|
|
|
BUILD_TIMER_FUNCTION(MlmePeriodicExec);
|
|
BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
|
|
BUILD_TIMER_FUNCTION(APSDPeriodicExec);
|
|
BUILD_TIMER_FUNCTION(AsicRfTuningExec);
|
|
#ifdef RT2870
|
|
BUILD_TIMER_FUNCTION(BeaconUpdateExec);
|
|
#endif // RT2870 //
|
|
|
|
BUILD_TIMER_FUNCTION(BeaconTimeout);
|
|
BUILD_TIMER_FUNCTION(ScanTimeout);
|
|
BUILD_TIMER_FUNCTION(AuthTimeout);
|
|
BUILD_TIMER_FUNCTION(AssocTimeout);
|
|
BUILD_TIMER_FUNCTION(ReassocTimeout);
|
|
BUILD_TIMER_FUNCTION(DisassocTimeout);
|
|
BUILD_TIMER_FUNCTION(LinkDownExec);
|
|
BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec);
|
|
BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc);
|
|
#ifdef RT2860
|
|
BUILD_TIMER_FUNCTION(PsPollWakeExec);
|
|
BUILD_TIMER_FUNCTION(RadioOnExec);
|
|
#endif
|
|
|
|
// for wireless system event message
|
|
char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
|
|
// system status event
|
|
"had associated successfully", /* IW_ASSOC_EVENT_FLAG */
|
|
"had disassociated", /* IW_DISASSOC_EVENT_FLAG */
|
|
"had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */
|
|
"had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */
|
|
"occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */
|
|
"occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
|
|
"occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */
|
|
"occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */
|
|
"occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */
|
|
"occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */
|
|
"Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
|
|
"Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
|
|
"RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
|
|
"set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
|
|
"set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
|
|
"connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */
|
|
"disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */
|
|
"scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */
|
|
"scan terminate!! Busy!! Enqueue fail!!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
|
|
};
|
|
|
|
// for wireless IDS_spoof_attack event message
|
|
char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
|
|
"detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */
|
|
"detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
|
|
"detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
|
|
"detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
|
|
"detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */
|
|
"detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */
|
|
"detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */
|
|
"detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */
|
|
"detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
|
|
"detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */
|
|
};
|
|
|
|
// for wireless IDS_flooding_attack event message
|
|
char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
|
|
"detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */
|
|
"detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
|
|
"detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
|
|
"detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
|
|
"detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */
|
|
"detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */
|
|
"detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
|
|
};
|
|
|
|
/* timeout -- ms */
|
|
VOID RTMP_SetPeriodicTimer(
|
|
IN NDIS_MINIPORT_TIMER *pTimer,
|
|
IN unsigned long timeout)
|
|
{
|
|
timeout = ((timeout*HZ) / 1000);
|
|
pTimer->expires = jiffies + timeout;
|
|
add_timer(pTimer);
|
|
}
|
|
|
|
/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
|
|
VOID RTMP_OS_Init_Timer(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN NDIS_MINIPORT_TIMER *pTimer,
|
|
IN TIMER_FUNCTION function,
|
|
IN PVOID data)
|
|
{
|
|
init_timer(pTimer);
|
|
pTimer->data = (unsigned long)data;
|
|
pTimer->function = function;
|
|
}
|
|
|
|
|
|
VOID RTMP_OS_Add_Timer(
|
|
IN NDIS_MINIPORT_TIMER *pTimer,
|
|
IN unsigned long timeout)
|
|
{
|
|
if (timer_pending(pTimer))
|
|
return;
|
|
|
|
timeout = ((timeout*HZ) / 1000);
|
|
pTimer->expires = jiffies + timeout;
|
|
add_timer(pTimer);
|
|
}
|
|
|
|
VOID RTMP_OS_Mod_Timer(
|
|
IN NDIS_MINIPORT_TIMER *pTimer,
|
|
IN unsigned long timeout)
|
|
{
|
|
timeout = ((timeout*HZ) / 1000);
|
|
mod_timer(pTimer, jiffies + timeout);
|
|
}
|
|
|
|
VOID RTMP_OS_Del_Timer(
|
|
IN NDIS_MINIPORT_TIMER *pTimer,
|
|
OUT BOOLEAN *pCancelled)
|
|
{
|
|
if (timer_pending(pTimer))
|
|
{
|
|
*pCancelled = del_timer_sync(pTimer);
|
|
}
|
|
else
|
|
{
|
|
*pCancelled = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
VOID RTMP_OS_Release_Packet(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PQUEUE_ENTRY pEntry)
|
|
{
|
|
//RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry);
|
|
}
|
|
|
|
// Unify all delay routine by using udelay
|
|
VOID RTMPusecDelay(
|
|
IN ULONG usec)
|
|
{
|
|
ULONG i;
|
|
|
|
for (i = 0; i < (usec / 50); i++)
|
|
udelay(50);
|
|
|
|
if (usec % 50)
|
|
udelay(usec % 50);
|
|
}
|
|
|
|
void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
|
|
{
|
|
time->u.LowPart = jiffies;
|
|
}
|
|
|
|
// pAd MUST allow to be NULL
|
|
NDIS_STATUS os_alloc_mem(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT PUCHAR *mem,
|
|
IN ULONG size)
|
|
{
|
|
*mem = (PUCHAR) kmalloc(size, GFP_ATOMIC);
|
|
if (*mem)
|
|
return (NDIS_STATUS_SUCCESS);
|
|
else
|
|
return (NDIS_STATUS_FAILURE);
|
|
}
|
|
|
|
// pAd MUST allow to be NULL
|
|
NDIS_STATUS os_free_mem(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR mem)
|
|
{
|
|
|
|
ASSERT(mem);
|
|
kfree(mem);
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN ULONG Length)
|
|
{
|
|
struct sk_buff *pkt;
|
|
|
|
pkt = dev_alloc_skb(Length);
|
|
|
|
if (pkt == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length));
|
|
}
|
|
|
|
if (pkt)
|
|
{
|
|
RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
|
|
}
|
|
|
|
return (PNDIS_PACKET) pkt;
|
|
}
|
|
|
|
|
|
PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Cached,
|
|
OUT PVOID *VirtualAddress)
|
|
{
|
|
struct sk_buff *pkt;
|
|
|
|
pkt = dev_alloc_skb(Length);
|
|
|
|
if (pkt == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length));
|
|
}
|
|
|
|
if (pkt)
|
|
{
|
|
RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
|
|
*VirtualAddress = (PVOID) pkt->data;
|
|
}
|
|
else
|
|
{
|
|
*VirtualAddress = (PVOID) NULL;
|
|
}
|
|
|
|
return (PNDIS_PACKET) pkt;
|
|
}
|
|
|
|
|
|
VOID build_tx_packet(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNDIS_PACKET pPacket,
|
|
IN PUCHAR pFrame,
|
|
IN ULONG FrameLen)
|
|
{
|
|
|
|
struct sk_buff *pTxPkt;
|
|
|
|
ASSERT(pPacket);
|
|
pTxPkt = RTPKT_TO_OSPKT(pPacket);
|
|
|
|
NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
|
|
}
|
|
|
|
VOID RTMPFreeAdapter(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
POS_COOKIE os_cookie;
|
|
int index;
|
|
|
|
os_cookie=(POS_COOKIE)pAd->OS_Cookie;
|
|
|
|
kfree(pAd->BeaconBuf);
|
|
|
|
|
|
NdisFreeSpinLock(&pAd->MgmtRingLock);
|
|
#ifdef RT2860
|
|
NdisFreeSpinLock(&pAd->RxRingLock);
|
|
#endif
|
|
for (index =0 ; index < NUM_OF_TX_RING; index++)
|
|
{
|
|
NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
|
|
NdisFreeSpinLock(&pAd->DeQueueLock[index]);
|
|
pAd->DeQueueRunning[index] = FALSE;
|
|
}
|
|
|
|
NdisFreeSpinLock(&pAd->irq_lock);
|
|
|
|
vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa);
|
|
kfree(os_cookie);
|
|
}
|
|
|
|
BOOLEAN OS_Need_Clone_Packet(void)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
|
|
must have only one NDIS BUFFER
|
|
return - byte copied. 0 means can't create NDIS PACKET
|
|
NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket
|
|
|
|
Arguments:
|
|
pAd Pointer to our adapter
|
|
pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
|
|
*pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet.
|
|
|
|
Return Value:
|
|
NDIS_STATUS_SUCCESS
|
|
NDIS_STATUS_FAILURE
|
|
|
|
Note:
|
|
|
|
========================================================================
|
|
*/
|
|
NDIS_STATUS RTMPCloneNdisPacket(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN BOOLEAN pInsAMSDUHdr,
|
|
IN PNDIS_PACKET pInPacket,
|
|
OUT PNDIS_PACKET *ppOutPacket)
|
|
{
|
|
|
|
struct sk_buff *pkt;
|
|
|
|
ASSERT(pInPacket);
|
|
ASSERT(ppOutPacket);
|
|
|
|
// 1. Allocate a packet
|
|
pkt = dev_alloc_skb(2048);
|
|
|
|
if (pkt == NULL)
|
|
{
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
|
|
NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket));
|
|
*ppOutPacket = OSPKT_TO_RTPKT(pkt);
|
|
|
|
|
|
RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
|
|
|
|
printk("###Clone###\n");
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
// the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket()
|
|
NDIS_STATUS RTMPAllocateNdisPacket(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT PNDIS_PACKET *ppPacket,
|
|
IN PUCHAR pHeader,
|
|
IN UINT HeaderLen,
|
|
IN PUCHAR pData,
|
|
IN UINT DataLen)
|
|
{
|
|
PNDIS_PACKET pPacket;
|
|
ASSERT(pData);
|
|
ASSERT(DataLen);
|
|
|
|
// 1. Allocate a packet
|
|
pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + TXPADDING_SIZE);
|
|
if (pPacket == NULL)
|
|
{
|
|
*ppPacket = NULL;
|
|
#ifdef DEBUG
|
|
printk("RTMPAllocateNdisPacket Fail\n\n");
|
|
#endif
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
// 2. clone the frame content
|
|
if (HeaderLen > 0)
|
|
NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
|
|
if (DataLen > 0)
|
|
NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen);
|
|
|
|
// 3. update length of packet
|
|
skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen);
|
|
|
|
RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
|
|
// printk("%s : pPacket = %p, len = %d\n", __func__, pPacket, GET_OS_PKT_LEN(pPacket));
|
|
*ppPacket = pPacket;
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
Description:
|
|
This routine frees a miniport internally allocated NDIS_PACKET and its
|
|
corresponding NDIS_BUFFER and allocated memory.
|
|
========================================================================
|
|
*/
|
|
VOID RTMPFreeNdisPacket(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNDIS_PACKET pPacket)
|
|
{
|
|
dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
|
|
}
|
|
|
|
|
|
// IRQL = DISPATCH_LEVEL
|
|
// NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same
|
|
// scatter gather buffer
|
|
NDIS_STATUS Sniff2BytesFromNdisBuffer(
|
|
IN PNDIS_BUFFER pFirstBuffer,
|
|
IN UCHAR DesiredOffset,
|
|
OUT PUCHAR pByte0,
|
|
OUT PUCHAR pByte1)
|
|
{
|
|
*pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset);
|
|
*pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1);
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
void RTMP_QueryPacketInfo(
|
|
IN PNDIS_PACKET pPacket,
|
|
OUT PACKET_INFO *pPacketInfo,
|
|
OUT PUCHAR *pSrcBufVA,
|
|
OUT UINT *pSrcBufLen)
|
|
{
|
|
pPacketInfo->BufferCount = 1;
|
|
pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket);
|
|
pPacketInfo->PhysicalBufferCount = 1;
|
|
pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
|
|
|
|
*pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
|
|
*pSrcBufLen = GET_OS_PKT_LEN(pPacket);
|
|
}
|
|
|
|
void RTMP_QueryNextPacketInfo(
|
|
IN PNDIS_PACKET *ppPacket,
|
|
OUT PACKET_INFO *pPacketInfo,
|
|
OUT PUCHAR *pSrcBufVA,
|
|
OUT UINT *pSrcBufLen)
|
|
{
|
|
PNDIS_PACKET pPacket = NULL;
|
|
|
|
if (*ppPacket)
|
|
pPacket = GET_OS_PKT_NEXT(*ppPacket);
|
|
|
|
if (pPacket)
|
|
{
|
|
pPacketInfo->BufferCount = 1;
|
|
pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket);
|
|
pPacketInfo->PhysicalBufferCount = 1;
|
|
pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
|
|
|
|
*pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
|
|
*pSrcBufLen = GET_OS_PKT_LEN(pPacket);
|
|
*ppPacket = GET_OS_PKT_NEXT(pPacket);
|
|
}
|
|
else
|
|
{
|
|
pPacketInfo->BufferCount = 0;
|
|
pPacketInfo->pFirstBuffer = NULL;
|
|
pPacketInfo->PhysicalBufferCount = 0;
|
|
pPacketInfo->TotalPacketLength = 0;
|
|
|
|
*pSrcBufVA = NULL;
|
|
*pSrcBufLen = 0;
|
|
*ppPacket = NULL;
|
|
}
|
|
}
|
|
|
|
// not yet support MBSS
|
|
PNET_DEV get_netdev_from_bssid(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
PNET_DEV dev_p = NULL;
|
|
|
|
dev_p = pAd->net_dev;
|
|
|
|
ASSERT(dev_p);
|
|
return dev_p; /* return one of MBSS */
|
|
}
|
|
|
|
PNDIS_PACKET DuplicatePacket(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNDIS_PACKET pPacket,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
struct sk_buff *skb;
|
|
PNDIS_PACKET pRetPacket = NULL;
|
|
USHORT DataSize;
|
|
UCHAR *pData;
|
|
|
|
DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
|
|
pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
|
|
|
|
|
|
skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
|
|
if (skb)
|
|
{
|
|
skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
|
|
pRetPacket = OSPKT_TO_RTPKT(skb);
|
|
}
|
|
|
|
return pRetPacket;
|
|
|
|
}
|
|
|
|
PNDIS_PACKET duplicate_pkt(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pHeader802_3,
|
|
IN UINT HdrLen,
|
|
IN PUCHAR pData,
|
|
IN ULONG DataSize,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
struct sk_buff *skb;
|
|
PNDIS_PACKET pPacket = NULL;
|
|
|
|
|
|
if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL)
|
|
{
|
|
skb_reserve(skb, 2);
|
|
NdisMoveMemory(skb->tail, pHeader802_3, HdrLen);
|
|
skb_put(skb, HdrLen);
|
|
NdisMoveMemory(skb->tail, pData, DataSize);
|
|
skb_put(skb, DataSize);
|
|
skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
|
|
pPacket = OSPKT_TO_RTPKT(skb);
|
|
}
|
|
|
|
return pPacket;
|
|
}
|
|
|
|
|
|
#define TKIP_TX_MIC_SIZE 8
|
|
PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNDIS_PACKET pPacket)
|
|
{
|
|
struct sk_buff *skb, *newskb;
|
|
|
|
|
|
skb = RTPKT_TO_OSPKT(pPacket);
|
|
if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE)
|
|
{
|
|
// alloc a new skb and copy the packet
|
|
newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC);
|
|
dev_kfree_skb_any(skb);
|
|
if (newskb == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
|
|
return NULL;
|
|
}
|
|
skb = newskb;
|
|
}
|
|
|
|
return OSPKT_TO_RTPKT(skb);
|
|
}
|
|
|
|
|
|
|
|
|
|
PNDIS_PACKET ClonePacket(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNDIS_PACKET pPacket,
|
|
IN PUCHAR pData,
|
|
IN ULONG DataSize)
|
|
{
|
|
struct sk_buff *pRxPkt;
|
|
struct sk_buff *pClonedPkt;
|
|
|
|
ASSERT(pPacket);
|
|
pRxPkt = RTPKT_TO_OSPKT(pPacket);
|
|
|
|
// clone the packet
|
|
pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
|
|
|
|
if (pClonedPkt)
|
|
{
|
|
// set the correct dataptr and data len
|
|
pClonedPkt->dev = pRxPkt->dev;
|
|
pClonedPkt->data = pData;
|
|
pClonedPkt->len = DataSize;
|
|
pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
|
|
ASSERT(DataSize < 1530);
|
|
}
|
|
return pClonedPkt;
|
|
}
|
|
|
|
//
|
|
// change OS packet DataPtr and DataLen
|
|
//
|
|
void update_os_packet_info(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN RX_BLK *pRxBlk,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
struct sk_buff *pOSPkt;
|
|
|
|
ASSERT(pRxBlk->pRxPacket);
|
|
pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
|
|
|
|
pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
|
|
pOSPkt->data = pRxBlk->pData;
|
|
pOSPkt->len = pRxBlk->DataSize;
|
|
pOSPkt->tail = pOSPkt->data + pOSPkt->len;
|
|
}
|
|
|
|
|
|
void wlan_802_11_to_802_3_packet(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN RX_BLK *pRxBlk,
|
|
IN PUCHAR pHeader802_3,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
struct sk_buff *pOSPkt;
|
|
|
|
ASSERT(pRxBlk->pRxPacket);
|
|
ASSERT(pHeader802_3);
|
|
|
|
pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
|
|
|
|
pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
|
|
pOSPkt->data = pRxBlk->pData;
|
|
pOSPkt->len = pRxBlk->DataSize;
|
|
pOSPkt->tail = pOSPkt->data + pOSPkt->len;
|
|
|
|
//
|
|
// copy 802.3 header
|
|
//
|
|
//
|
|
|
|
NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3);
|
|
}
|
|
|
|
void announce_802_3_packet(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNDIS_PACKET pPacket)
|
|
{
|
|
|
|
struct sk_buff *pRxPkt;
|
|
|
|
ASSERT(pPacket);
|
|
|
|
pRxPkt = RTPKT_TO_OSPKT(pPacket);
|
|
|
|
/* Push up the protocol stack */
|
|
#ifdef IKANOS_VX_1X0
|
|
IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len);
|
|
#else
|
|
pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
|
|
|
|
netif_rx(pRxPkt);
|
|
#endif // IKANOS_VX_1X0 //
|
|
}
|
|
|
|
|
|
PRTMP_SCATTER_GATHER_LIST
|
|
rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg)
|
|
{
|
|
sg->NumberOfElements = 1;
|
|
sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket);
|
|
sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
|
|
return (sg);
|
|
}
|
|
|
|
void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
|
|
{
|
|
unsigned char *pt;
|
|
int x;
|
|
|
|
if (RTDebugLevel < RT_DEBUG_TRACE)
|
|
return;
|
|
|
|
pt = pSrcBufVA;
|
|
printk("%s: %p, len = %d\n",str, pSrcBufVA, SrcBufLen);
|
|
for (x=0; x<SrcBufLen; x++)
|
|
{
|
|
if (x % 16 == 0)
|
|
printk("0x%04x : ", x);
|
|
printk("%02x ", ((unsigned char)pt[x]));
|
|
if (x%16 == 15) printk("\n");
|
|
}
|
|
printk("\n");
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
Send log message through wireless event
|
|
|
|
Support standard iw_event with IWEVCUSTOM. It is used below.
|
|
|
|
iwreq_data.data.flags is used to store event_flag that is defined by user.
|
|
iwreq_data.data.length is the length of the event log.
|
|
|
|
The format of the event log is composed of the entry's MAC address and
|
|
the desired log message (refer to pWirelessEventText).
|
|
|
|
ex: 11:22:33:44:55:66 has associated successfully
|
|
|
|
p.s. The requirement of Wireless Extension is v15 or newer.
|
|
|
|
========================================================================
|
|
*/
|
|
VOID RTMPSendWirelessEvent(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN USHORT Event_flag,
|
|
IN PUCHAR pAddr,
|
|
IN UCHAR BssIdx,
|
|
IN CHAR Rssi)
|
|
{
|
|
#if WIRELESS_EXT >= 15
|
|
|
|
union iwreq_data wrqu;
|
|
PUCHAR pBuf = NULL, pBufPtr = NULL;
|
|
USHORT event, type, BufLen;
|
|
UCHAR event_table_len = 0;
|
|
|
|
type = Event_flag & 0xFF00;
|
|
event = Event_flag & 0x00FF;
|
|
|
|
switch (type)
|
|
{
|
|
case IW_SYS_EVENT_FLAG_START:
|
|
event_table_len = IW_SYS_EVENT_TYPE_NUM;
|
|
break;
|
|
|
|
case IW_SPOOF_EVENT_FLAG_START:
|
|
event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
|
|
break;
|
|
|
|
case IW_FLOOD_EVENT_FLAG_START:
|
|
event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
|
|
break;
|
|
}
|
|
|
|
if (event_table_len == 0)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __func__, type));
|
|
return;
|
|
}
|
|
|
|
if (event >= event_table_len)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __func__, event));
|
|
return;
|
|
}
|
|
|
|
//Allocate memory and copy the msg.
|
|
if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL)
|
|
{
|
|
//Prepare the payload
|
|
memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
|
|
|
|
pBufPtr = pBuf;
|
|
|
|
if (pAddr)
|
|
pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr));
|
|
else if (BssIdx < MAX_MBSSID_NUM)
|
|
pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx);
|
|
else
|
|
pBufPtr += sprintf(pBufPtr, "(RT2860) ");
|
|
|
|
if (type == IW_SYS_EVENT_FLAG_START)
|
|
pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]);
|
|
else if (type == IW_SPOOF_EVENT_FLAG_START)
|
|
pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi);
|
|
else if (type == IW_FLOOD_EVENT_FLAG_START)
|
|
pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]);
|
|
else
|
|
pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
|
|
|
|
pBufPtr[pBufPtr - pBuf] = '\0';
|
|
BufLen = pBufPtr - pBuf;
|
|
|
|
memset(&wrqu, 0, sizeof(wrqu));
|
|
wrqu.data.flags = Event_flag;
|
|
wrqu.data.length = BufLen;
|
|
|
|
//send wireless event
|
|
wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, pBuf);
|
|
|
|
//DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf));
|
|
|
|
kfree(pBuf);
|
|
}
|
|
else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __func__));
|
|
#else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __func__));
|
|
#endif /* WIRELESS_EXT >= 15 */
|
|
}
|
|
|
|
void send_monitor_packets(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN RX_BLK *pRxBlk)
|
|
{
|
|
struct sk_buff *pOSPkt;
|
|
wlan_ng_prism2_header *ph;
|
|
int rate_index = 0;
|
|
USHORT header_len = 0;
|
|
UCHAR temp_header[40] = {0};
|
|
|
|
u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96, 108, 109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38
|
|
54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 0,1,2,3,4,5,6,7,8,9,10,
|
|
11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80};
|
|
|
|
|
|
ASSERT(pRxBlk->pRxPacket);
|
|
if (pRxBlk->DataSize < 10)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __func__, pRxBlk->DataSize));
|
|
goto err_free_sk_buff;
|
|
}
|
|
|
|
if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE)
|
|
{
|
|
#ifndef RT30xx
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%zu)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header)));
|
|
#endif
|
|
#ifdef RT30xx
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header)));
|
|
#endif
|
|
goto err_free_sk_buff;
|
|
}
|
|
|
|
pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
|
|
pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
|
|
if (pRxBlk->pHeader->FC.Type == BTYPE_DATA)
|
|
{
|
|
pRxBlk->DataSize -= LENGTH_802_11;
|
|
if ((pRxBlk->pHeader->FC.ToDs == 1) &&
|
|
(pRxBlk->pHeader->FC.FrDs == 1))
|
|
header_len = LENGTH_802_11_WITH_ADDR4;
|
|
else
|
|
header_len = LENGTH_802_11;
|
|
|
|
// QOS
|
|
if (pRxBlk->pHeader->FC.SubType & 0x08)
|
|
{
|
|
header_len += 2;
|
|
// Data skip QOS contorl field
|
|
pRxBlk->DataSize -=2;
|
|
}
|
|
|
|
// Order bit: A-Ralink or HTC+
|
|
if (pRxBlk->pHeader->FC.Order)
|
|
{
|
|
header_len += 4;
|
|
// Data skip HTC contorl field
|
|
pRxBlk->DataSize -= 4;
|
|
}
|
|
|
|
// Copy Header
|
|
if (header_len <= 40)
|
|
NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
|
|
|
|
// skip HW padding
|
|
if (pRxBlk->RxD.L2PAD)
|
|
pRxBlk->pData += (header_len + 2);
|
|
else
|
|
pRxBlk->pData += header_len;
|
|
} //end if
|
|
|
|
|
|
if (pRxBlk->DataSize < pOSPkt->len) {
|
|
skb_trim(pOSPkt,pRxBlk->DataSize);
|
|
} else {
|
|
skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len));
|
|
} //end if
|
|
|
|
if ((pRxBlk->pData - pOSPkt->data) > 0) {
|
|
skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data));
|
|
skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data));
|
|
} //end if
|
|
|
|
if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) {
|
|
if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) {
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __func__));
|
|
goto err_free_sk_buff;
|
|
} //end if
|
|
} //end if
|
|
|
|
if (header_len > 0)
|
|
NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len);
|
|
|
|
ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header));
|
|
NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header));
|
|
|
|
ph->msgcode = DIDmsg_lnxind_wlansniffrm;
|
|
ph->msglen = sizeof(wlan_ng_prism2_header);
|
|
strcpy(ph->devname, pAd->net_dev->name);
|
|
|
|
ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
|
|
ph->hosttime.status = 0;
|
|
ph->hosttime.len = 4;
|
|
ph->hosttime.data = jiffies;
|
|
|
|
ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
|
|
ph->mactime.status = 0;
|
|
ph->mactime.len = 0;
|
|
ph->mactime.data = 0;
|
|
|
|
ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
|
|
ph->istx.status = 0;
|
|
ph->istx.len = 0;
|
|
ph->istx.data = 0;
|
|
|
|
ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
|
|
ph->channel.status = 0;
|
|
ph->channel.len = 4;
|
|
|
|
ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel;
|
|
|
|
ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
|
|
ph->rssi.status = 0;
|
|
ph->rssi.len = 4;
|
|
ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));;
|
|
|
|
ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
|
|
ph->signal.status = 0;
|
|
ph->signal.len = 4;
|
|
ph->signal.data = 0; //rssi + noise;
|
|
|
|
ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
|
|
ph->noise.status = 0;
|
|
ph->noise.len = 4;
|
|
ph->noise.data = 0;
|
|
|
|
if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX)
|
|
{
|
|
rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS);
|
|
}
|
|
else
|
|
if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
|
|
rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4;
|
|
else
|
|
rate_index = (UCHAR)(pRxBlk->pRxWI->MCS);
|
|
if (rate_index < 0)
|
|
rate_index = 0;
|
|
if (rate_index > 255)
|
|
rate_index = 255;
|
|
|
|
ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
|
|
ph->rate.status = 0;
|
|
ph->rate.len = 4;
|
|
ph->rate.data = ralinkrate[rate_index];
|
|
|
|
ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
|
|
ph->frmlen.status = 0;
|
|
ph->frmlen.len = 4;
|
|
ph->frmlen.data = (u_int32_t)pRxBlk->DataSize;
|
|
|
|
|
|
pOSPkt->pkt_type = PACKET_OTHERHOST;
|
|
pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
|
|
pOSPkt->ip_summed = CHECKSUM_NONE;
|
|
netif_rx(pOSPkt);
|
|
|
|
return;
|
|
|
|
err_free_sk_buff:
|
|
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
|
|
return;
|
|
|
|
}
|
|
|
|
void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify)
|
|
{
|
|
daemonize(pThreadName /*"%s",pAd->net_dev->name*/);
|
|
|
|
allow_signal(SIGTERM);
|
|
allow_signal(SIGKILL);
|
|
current->flags |= PF_NOFREEZE;
|
|
|
|
/* signal that we've started the thread */
|
|
complete(pNotify);
|
|
}
|
|
|
|
void RTMP_IndicateMediaState(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
if (pAd->CommonCfg.bWirelessEvent)
|
|
{
|
|
if (pAd->IndicateMediaState == NdisMediaStateConnected)
|
|
{
|
|
RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
|
|
}
|
|
else
|
|
{
|
|
RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
|
|
}
|
|
}
|
|
}
|
|
|