aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/rt3070/sta/auth.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2009-02-25 16:14:55 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-03 14:54:24 -0700
commite642f09951f7cbb69983781b07bb9cd881546ac4 (patch)
treec783967792f17f0abfab38c9a893fb9565b8bae2 /drivers/staging/rt3070/sta/auth.c
parent21a6a6e9f81fb26fbcecbb1304018d34dcd1794f (diff)
Staging: add rt3070 wireless driver
This is the Ralink RT3070 driver from the company that does horrible things like reading a config file from /etc. However, the driver that is currently under development from the wireless development community is not working at all yet, so distros and users are using this version instead (quite common hardware on a lot of netbook machines). So here is this driver, for now, until the wireless developers get a "clean" version into the main tree, or until this version is cleaned up sufficiently to move out of the staging tree. Ported to the Linux build system, fixed lots of build issues, forward ported to the current kernel version, and other minor cleanups were all done by me. Cc: Linux wireless <linux-wireless@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/rt3070/sta/auth.c')
-rw-r--r--drivers/staging/rt3070/sta/auth.c475
1 files changed, 475 insertions, 0 deletions
diff --git a/drivers/staging/rt3070/sta/auth.c b/drivers/staging/rt3070/sta/auth.c
new file mode 100644
index 00000000000..032b5df058b
--- /dev/null
+++ b/drivers/staging/rt3070/sta/auth.c
@@ -0,0 +1,475 @@
+/*
+ *************************************************************************
+ * 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ auth.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John 2004-9-3 porting from RT2500
+*/
+#include "../rt_config.h"
+
+/*
+ ==========================================================================
+ Description:
+ authenticate state machine init, including state transition and timer init
+ Parameters:
+ Sm - pointer to the auth state machine
+ Note:
+ The state machine looks like this
+
+ AUTH_REQ_IDLE AUTH_WAIT_SEQ2 AUTH_WAIT_SEQ4
+ MT2_MLME_AUTH_REQ mlme_auth_req_action invalid_state_when_auth invalid_state_when_auth
+ MT2_PEER_AUTH_EVEN drop peer_auth_even_at_seq2_action peer_auth_even_at_seq4_action
+ MT2_AUTH_TIMEOUT Drop auth_timeout_action auth_timeout_action
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+
+void AuthStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *Sm,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_REQ_IDLE, AUTH_MACHINE_BASE);
+
+ // the first column
+ StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)MlmeAuthReqAction);
+
+ // the second column
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq2Action);
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
+
+ // the third column
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq4Action);
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
+
+ RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE);
+}
+
+/*
+ ==========================================================================
+ Description:
+ function to be executed at timer thread when auth timer expires
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AuthTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+ DBGPRINT(RT_DEBUG_TRACE,("AUTH - AuthTimeout\n"));
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ // send a de-auth to reset AP's state machine (Patch AP-Dir635)
+ if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2)
+ Cls2errAction(pAd, pAd->MlmeAux.Bssid);
+
+
+ MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL);
+ RT28XX_MLME_HANDLER(pAd);
+}
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeAuthReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Addr[6];
+ USHORT Alg, Seq, Status;
+ ULONG Timeout;
+ HEADER_802_11 AuthHdr;
+ BOOLEAN TimerCancelled;
+ NDIS_STATUS NStatus;
+ PUCHAR pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+
+ // Block all authentication request durning WPA block period
+ if (pAd->StaCfg.bBlockAssoc == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Block Auth request durning WPA block period!\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_STATE_MACHINE_REJECT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+ else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg))
+ {
+ // reset timer
+ RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
+ COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr);
+ pAd->MlmeAux.Alg = Alg;
+ Seq = 1;
+ Status = MLME_SUCCESS;
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", Alg));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg));
+ MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11),&AuthHdr,
+ 2, &Alg,
+ 2, &Seq,
+ 2, &Status,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ RTMPSetTimer(&pAd->MlmeAux.AuthTimer, Timeout);
+ pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2;
+ }
+ else
+ {
+ DBGPRINT_ERR(("AUTH - MlmeAuthReqAction() sanity check failed\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_INVALID_FORMAT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerAuthRspAtSeq2Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Addr2[MAC_ADDR_LEN];
+ USHORT Seq, Status, RemoteStatus, Alg;
+ UCHAR ChlgText[CIPHER_TEXT_LEN];
+ UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8];
+ UCHAR Element[2];
+ HEADER_802_11 AuthHdr;
+ BOOLEAN TimerCancelled;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ USHORT Status2;
+
+ if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
+ {
+ if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status));
+ RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
+
+ if (Status == MLME_SUCCESS)
+ {
+ // Authentication Mode "LEAP" has allow for CCX 1.X
+ if ((pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen)
+#ifdef LEAP_SUPPORT
+ || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+ )
+ {
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+#ifdef LEAP_SUPPORT
+ pAd->Mlme.LeapMachine.CurrState = LEAP_IDLE;
+#endif // LEAP_SUPPORT //
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+ else
+ {
+ // 2. shared key, need to be challenged
+ Seq++;
+ RemoteStatus = MLME_SUCCESS;
+
+ // Get an unused nonpaged memory
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status2 = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2);
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n"));
+ MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid);
+ AuthHdr.FC.Wep = 1;
+ // Encrypt challenge text & auth information
+ RTMPInitWepEngine(
+ pAd,
+ pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
+ pAd->StaCfg.DefaultKeyId,
+ pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen,
+ CyperChlgText);
+
+ Alg = cpu2le16(*(USHORT *)&Alg);
+ Seq = cpu2le16(*(USHORT *)&Seq);
+ RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus);
+
+ RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2);
+ RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2);
+ RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2);
+ Element[0] = 16;
+ Element[1] = 128;
+ RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2);
+ RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128);
+ RTMPSetICV(pAd, CyperChlgText + 140);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &AuthHdr,
+ CIPHER_TEXT_LEN + 16, CyperChlgText,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT);
+ pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4;
+ }
+ }
+ else
+ {
+#ifdef LEAP_SUPPORT
+ if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+ {
+ //Invalid Authentication possible rogue AP
+ //Add this Ap to Rogue AP.
+ RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_INVALID_AUTH);
+ }
+#endif // LEAP_SUPPORT //
+ pAd->StaCfg.AuthFailReason = Status;
+ COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n"));
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerAuthRspAtSeq4Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Addr2[MAC_ADDR_LEN];
+ USHORT Alg, Seq, Status;
+ CHAR ChlgText[CIPHER_TEXT_LEN];
+ BOOLEAN TimerCancelled;
+
+ if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
+ {
+ if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n"));
+ RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
+
+ if (Status != MLME_SUCCESS)
+ {
+ pAd->StaCfg.AuthFailReason = Status;
+ COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
+ }
+
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n"));
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeDeauthReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MLME_DEAUTH_REQ_STRUCT *pInfo;
+ HEADER_802_11 DeauthHdr;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ USHORT Status;
+
+ pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg;
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
+ return;
+ }
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason));
+ MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11),&DeauthHdr,
+ 2, &pInfo->Reason,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ pAd->StaCfg.DeauthReason = pInfo->Reason;
+ COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr);
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_SUCCESS;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
+
+ // send wireless event - for deauthentication
+ if (pAd->CommonCfg.bWirelessEvent)
+ RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AuthTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_REJ_TIMEOUT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID InvalidStateWhenAuth(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_STATE_MACHINE_REJECT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Some STA/AP
+ Note:
+ This action should never trigger AUTH state transition, therefore we
+ separate it from AUTH state machine, and make it as a standalone service
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID Cls2errAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr)
+{
+ HEADER_802_11 DeauthHdr;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ USHORT Reason = REASON_CLS2ERR;
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n"));
+ MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11),&DeauthHdr,
+ 2, &Reason,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ pAd->StaCfg.DeauthReason = Reason;
+ COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr);
+}
+
+