rtmp_apcli_pppoe.c

来自「Ralink RT61 SoftAP Driver source code. 」· C语言 代码 · 共 984 行 · 第 1/2 页

C
984
字号
/*
 ***************************************************************************
 * Ralink Tech Inc.
 * 4F, No. 2 Technology 5th Rd.
 * Science-based Industrial Park
 * Hsin-chu, Taiwan, R.O.C.
 *
 * (c) Copyright 2002-2006, Ralink Technology, Inc.
 *
 * All rights reserved.	Ralink's source	code is	an unpublished work	and	the
 * use of a	copyright notice does not imply	otherwise. This	source code
 * contains	confidential trade secret material of Ralink Tech. Any attemp
 * or participation	in deciphering,	decoding, reverse engineering or in	any
 * way altering	the	source code	is stricitly prohibited, unless	the	prior
 * written consent of Ralink Technology, Inc. is obtained.
 ***************************************************************************

	Module Name:
	rtmp_apcli_pppoe.c

	Abstract:
	apcli convert engine subroutine for PPPoE protocol.Due to the difference of
	characteristic of PPPoE discovery stage and session stage, we seperate that
	as two parts and used different stretegy to handle it.

	Revision History:
	Who			When			What
	--------	----------		----------------------------------------------
	Shiang      June/19/06      Init version
*/

#ifdef APCLI_SUPPORT

#include "rtmp_apcli.h"

NDIS_STATUS APCLI_PPPoE_Dis_init(VOID);
NDIS_STATUS APCLI_PPPoE_Dis_exit(VOID);
PUCHAR APCLI_PPPoE_Dis_rx(PRTMP_ADAPTER pAd, struct sk_buff *pSkb, PUCHAR pLayerHdr);
PUCHAR APCLI_PPPoE_Dis_tx(PRTMP_ADAPTER pAd, struct sk_buff *pSkb, PUCHAR pLayerHdr);

NDIS_STATUS APCLI_PPPoE_Ses_init(VOID);
NDIS_STATUS APCLI_PPPoE_Ses_exit(VOID);
PUCHAR APCLI_PPPoE_Ses_rx(PRTMP_ADAPTER pAd, struct sk_buff *pSkb, PUCHAR pLayerHdr);
PUCHAR APCLI_PPPoE_Ses_tx(PRTMP_ADAPTER pAd, struct sk_buff *pSkb, PUCHAR pLayerHdr);


/*
                  1                 2               3             4
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  VER  | TYPE  |      CODE     |          SESSION_ID           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            LENGTH             |           payload             ~
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

	VER = 0x1, TYPE =0x1
	
PPPoE Discovery Stage(Ethernet protocol type = 0x8863):
	PADI:
		DESTINATION_ADDR = 0xffffffff
		CODE = 0x09, SESSION_ID = 0x0000
		LENGTH = payload length

	PADO:
		DESTINATION_ADDR = Unicast Ethernet address of sender
		CODE = 0x07, SESSION_ID = 0x0000
		LENGTH = payload length
		NEcessary TAGS: AC-NAME(0x0102), Sevice-Name(0x0101), and other service names.

		Note: if the PPPoE server cannot serve the PADI it MUST NOT respond with a PADO

	
	PADR:
		DESTINATION_ADDR = unicast Ethernet address 
		CODE = 0x19, SESSION_ID = 0x0000
		LENGTH = payload length
		Necessary TAGS: Service-Name(0x0101)
		Optional TAGS: ....

	PADS:
		If success:
			DESTINATION_ADDR = unicast Ethernet address 
			CODE = 0x65, SESSION_ID = unique value for this pppoe session.(16 bits)
			LENGHT - payload length
			Necessary TAGS: Service-Name(0x0101)

		if failed:
			SESSION_ID = 0x0000
			Necessary TAGS: Service-Name-Error(0x0201).

	PADT:
		DESTINATION_ADDR = unicast Ethernet address
		CODE = 0xa7, SESSION_ID = previous assigned 16 bits session ID.
		Necessary TAGS: NO.

PPPoE Session Stage(Ethernet protocol type = 0x8864):
	PPP data:
		DESTINATION_ADDR = unicast Ethernet address
		CODE = 0x00, 
	LCP:
		DESTINATION_ADDR = unicast Ethernet address
		CODE = 0x00, 

*/

#define PPPOE_CODE_PADI			0x09
#define PPPOE_CODE_PADO			0x07
#define PPPOE_CODE_PADR			0x19
#define PPPOE_CODE_PADS			0x65
#define PPPOE_CODE_PADT			0xa7
#define PPPOE_TAG_ID_HOST_UNIQ	0x0103
#define PPPOE_TAG_ID_AC_COOKIE	0x0104

#define APCLI_MAX_HOST_UNIQ_LEN 16
#define PPPoE_SES_ENTRY_AGEOUT_TIME 3000

/* Data structure used for PPPoE discovery stage */
#define PPPOE_DIS_UID_LEN		6
typedef struct _UidMacMappingEntry
{
	UCHAR isServer;
	UCHAR uIDAddByUs;				 // If the host-uniq or AC-cookie is add by our driver, set it as 1, else set as 0.
	UCHAR uIDStr[PPPOE_DIS_UID_LEN]; // String used for identify who sent this pppoe packet in discovery stage.
	UCHAR macAddr[MAC_ADDR_LEN];	 // Mac address associated to this uid string.
	UINT lastTime;
	struct _UidMacMappingEntry *pNext;	//Pointer to next entry in link-list of Uid hash table.
}UidMacMappingEntry, *PUidMacMappingEntry;

typedef struct _UidMacMappingTable
{
	BOOLEAN valid;
	UidMacMappingEntry *uidHash[MAX_SUPPORT_APCLI_STA];
}UidMacMappingTable;

// "Host-Uniq <-> Mac Address" Mapping table used for PPPoE Discovery stage
static UidMacMappingTable UidMacTable=
{
	.valid = FALSE,
};

/* Data struct used for PPPoE session stage */
typedef struct _SesMacMappingEntry
{
	UINT16	sessionID;	// In network order
	UCHAR	outMacAddr[MAC_ADDR_LEN];
	UCHAR	inMacAddr[MAC_ADDR_LEN];
	UINT 	lastTime;
	struct	_SesMacMappingEntry *pNext;	
}SesMacMappingEntry, *PSesMacMappingEntry;

typedef struct _SesMacMappingTable
{
	BOOLEAN valid;
	SesMacMappingEntry *sesHash[MAX_SUPPORT_APCLI_STA];
}SesMacMappingTable;

static SesMacMappingTable SesMacTable =
{
	.valid = FALSE,
};

// Declaration of protocol handler for PPPoE Discovery stage
struct _UWRProtoEntry apCliPPPoEDisHandler =
{
	.init = APCLI_PPPoE_Dis_init,
	.tx = APCLI_PPPoE_Dis_tx,
	.rx = APCLI_PPPoE_Dis_rx,
	.exit = APCLI_PPPoE_Dis_exit,
};

// Declaration of protocol handler for PPPoE Session stage
struct _UWRProtoEntry apCliPPPoESesHandler =
{
	.init = APCLI_PPPoE_Ses_init,
	.tx = APCLI_PPPoE_Ses_tx,
	.rx = APCLI_PPPoE_Ses_rx,
	.exit =APCLI_PPPoE_Ses_exit,
};

NDIS_STATUS dumpSesMacTb(UINT hashIdx)
{
	SesMacMappingEntry *pHead;

	if (!SesMacTable.valid)
	{
		printk("SesMacTable not init yet, so cannot do dump!\n");
		return FALSE;
	}
	
	pHead = SesMacTable.sesHash[hashIdx];
	printk("%s(): Now dump SesMac Table with index=%d!\n", __FUNCTION__, hashIdx);
	while(pHead)
	{
		printk("-sesID=%d,inMac=%02x:%02x:%02x:%02x:%02x:%02x,outMac=%02x:%02x:%02x:%02x:%02x:%02x,jiffies=0x%x, pNext=%p\n",
		pHead->sessionID, pHead->inMacAddr[0], pHead->inMacAddr[1], pHead->inMacAddr[2], pHead->inMacAddr[3], pHead->inMacAddr[4],
		pHead->inMacAddr[5], pHead->inMacAddr[0], pHead->inMacAddr[1], pHead->inMacAddr[2], pHead->inMacAddr[3], pHead->inMacAddr[4],
		pHead->inMacAddr[5],pHead->lastTime, pHead->pNext);
		pHead = pHead->pNext;
	}

	printk("----EndOfDump!\n");

	return TRUE;

}


NDIS_STATUS dumpUidMacTb(UINT hashIdx)
{
	UidMacMappingEntry *pHead;
	int i;
	
	if (!UidMacTable.valid)
	{
		printk("UidMacTable not init yet, so cannot do dump!\n");
		return FALSE;
	}
	
	pHead = UidMacTable.uidHash[hashIdx];
	printk("%s(): Now dump UidMac Table with index=%d!\n", __FUNCTION__, hashIdx);
	while(pHead)
	{
		printk("---isSrv=%d, uIDAddbyUs=%d, Mac=%02x:%02x:%02x:%02x:%02x:%02x, jiffies=0x%x, pNext=%p\n", 
				pHead->isServer, pHead->uIDAddByUs, pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2],
				pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5], pHead->lastTime, pHead->pNext);
		printk("---uIDStr=");
		for(i=0; i< PPPOE_DIS_UID_LEN; i++)
			printk("%02x", pHead->uIDStr[i]);
		printk("\n");
		pHead = pHead->pNext;
	}
	printk("----EndOfDump!\n");
	
	return TRUE;
}

NDIS_STATUS UidMacTable_RemoveAll(VOID)
{
	UidMacMappingEntry *pEntry;
	INT             i;

	if (!UidMacTable.valid)
		return TRUE;

	for (i=0; i<IPMAC_TB_HASH_ENTRY_NUM; i++)
	{
		while((pEntry = UidMacTable.uidHash[i]) != NULL)
		{
			UidMacTable.uidHash[i] = pEntry->pNext;
#ifdef KMALLOC_BATCH
			UWRNodeEntryFree((PUCHAR)pEntry);
#else
			kfree(pEntry);
#endif
		}
	}

	UidMacTable.valid = FALSE;

	return TRUE;
}


NDIS_STATUS SesMacTable_RemoveAll(VOID)
{
	SesMacMappingEntry *pEntry;
	INT             i;

	if (!SesMacTable.valid)
		return TRUE;

	for (i=0; i<IPMAC_TB_HASH_ENTRY_NUM; i++)
	{
		while((pEntry = SesMacTable.sesHash[i]) != NULL)
		{
			SesMacTable.sesHash[i] = pEntry->pNext;
#ifdef KMALLOC_BATCH
			UWRNodeEntryFree((PUCHAR)pEntry);
#else
			kfree(pEntry);
#endif
		}
	}

	SesMacTable.valid = FALSE;
	
	return TRUE;

}


PUidMacMappingEntry UidMacTableUpdate(
	IN PRTMP_ADAPTER	pAd,
	IN PUCHAR			pInMac,
	IN PUCHAR			pOutMac,
	IN PUCHAR			pTagInfo,
	IN UINT16			tagLen,
	IN UINT16			isServer)
{
	UINT 				hashIdx, i=0, uIDAddByUs = 0;
	UidMacMappingEntry	*pEntry = NULL, *pPrev = NULL, *pNewEntry =NULL;
	UCHAR 				hashVal = 0;
	PUCHAR				pUIDStr= NULL;

	if (!UidMacTable.valid)
		return NULL;

	if (pTagInfo && tagLen >0)
	{
		pUIDStr = pTagInfo;
		uIDAddByUs = 0;
		tagLen = (tagLen > PPPOE_DIS_UID_LEN ? PPPOE_DIS_UID_LEN : tagLen);
	}
	else
	{
		// We assume the station just have one role,i.e., just a PPPoE server or just a PPPoE client.
		// For a packet send by server, we use the destination MAC as our uIDStr
		// For a packet send by client, we use the source MAC as our uIDStr.
		pUIDStr = isServer ? pOutMac: pInMac;
		tagLen = MAC_ADDR_LEN;
		uIDAddByUs = 1;
	}

	for (i=0; i<tagLen; i++)
		hashVal ^= (pUIDStr[i] & 0xff);
	hashIdx = hashVal % MAX_SUPPORT_APCLI_STA;
	
	//First, check if the hashIdx exists
	if (hashIdx < MAX_SUPPORT_APCLI_STA)
	{
		pEntry = pPrev = UidMacTable.uidHash[hashIdx];
		while(pEntry)
		{
			// Find the existed UidMac Mapping entry
			if (NdisEqualMemory(pUIDStr, pEntry->uIDStr, tagLen) && IS_EQUAL_MAC(pEntry->macAddr, pInMac))
    			{
#if 0
				printk("%s(): Got the Mac(%02x:%02x:%02x:%02x:%02x:%02x) with tagInfo:\n",
						__FUNCTION__, pEntry->macAddr[0],pEntry->macAddr[1],pEntry->macAddr[2],
						pEntry->macAddr[3],pEntry->macAddr[4],pEntry->macAddr[5]); 
				for(i=0; i< tagLen; i++)
					printk("%02x ", pUIDStr[i] & 0xff);
				printk("\n");
#endif
				// Update info of this entry
				pEntry->isServer = isServer;
				pEntry->uIDAddByUs = uIDAddByUs;
				pEntry->lastTime = jiffies;
				return pEntry;
			}
			else
        		{	// handle the age-out situation
	        		if ((jiffies - pEntry->lastTime) > IPMAC_TB_ENTRY_AGEOUT_TIME)
				{
					// Remove the aged entry from the uidHash
					if (pEntry == UidMacTable.uidHash[hashIdx])
					{
						UidMacTable.uidHash[hashIdx]= pEntry->pNext;
						pPrev = UidMacTable.uidHash[hashIdx];
	        			}
					else 
					{	
						pPrev->pNext = pEntry->pNext;
					}

					//After remove this entry from macHash list and uidHash list, now free it!
#ifdef KMALLOC_BATCH
					UWRNodeEntryFree((PUCHAR)pEntry);
#else
					kfree(pEntry);
#endif
					pEntry = (pPrev == NULL ? NULL: pPrev->pNext);
	        		} 
				else
				{
					pPrev = pEntry;
					pEntry = pEntry->pNext;
				}
			}
		}
	}

	// Allocate a new UidMacMapping entry and insert into the double-hash
#ifdef KMALLOC_BATCH
	pNewEntry = (UidMacMappingEntry *)UWRNodeEntryAlloc();
#else
	pNewEntry = (UidMacMappingEntry *)kmalloc(sizeof(UidMacMappingEntry), MEM_ALLOC_FLAG);
#endif
	if (pNewEntry)
	{	
		memset(pNewEntry, 0, sizeof(UidMacMappingEntry));
		
		pNewEntry->isServer = isServer;
		pNewEntry->uIDAddByUs = uIDAddByUs;
		memcpy(pNewEntry->macAddr, pInMac, MAC_ADDR_LEN);
		memcpy(pNewEntry->uIDStr, pUIDStr, tagLen);
		pNewEntry->pNext = NULL;
		pNewEntry->lastTime = jiffies;
		
		// Update mac-side hash link list
		if (UidMacTable.uidHash[hashIdx] == NULL)
		{	// Hash list is empty, directly assign it.
			UidMacTable.uidHash[hashIdx] = pNewEntry;
		}
		else 
		{
			// Ok, we insert the new entry into the root of uidHash[hashIdx]
			pNewEntry->pNext = UidMacTable.uidHash[hashIdx];
			UidMacTable.uidHash[hashIdx] = pNewEntry;
		}
		//dumpUidMacTb(hashIdx); //for debug
			
		return pNewEntry;
	}
	
	return NULL;
}


PUidMacMappingEntry UidMacTableLookUp(
	IN PRTMP_ADAPTER	pAd,
	IN PUCHAR			pTagInfo,
	IN UINT16			tagLen)
{
    UINT 				hashIdx;
	UINT16				len;
	UCHAR				hashValue = 0;
    UidMacMappingEntry	*pEntry = NULL;

	if (!UidMacTable.valid)
		return NULL;

	// Use hash to find out the location of that entry and get the Mac address.
	len = tagLen;
	while(len)
		hashValue ^= pTagInfo[--len];
	hashIdx = hashValue % MAX_SUPPORT_APCLI_STA;

	pEntry = UidMacTable.uidHash[hashIdx];
	while(pEntry)
	{
		if (NdisEqualMemory(pEntry->uIDStr, pTagInfo, tagLen))
		{
/*			printk("%s(): dstMac=%02x:%02x:%02x:%02x:%02x:%02x for mapped dstIP(%d.%d.%d.%d)\n", 
					__FUNCTION__, pEntry->macAddr[0],pEntry->macAddr[1],pEntry->macAddr[2],
					pEntry->macAddr[3],pEntry->macAddr[4],pEntry->macAddr[5],
					(ipAddr>>24) & 0xff, (ipAddr>>16) & 0xff, (ipAddr>>8) & 0xff, ipAddr & 0xff); 
*/			
			//Update the lastTime to prevent the aging before pDA processed!
			pEntry->lastTime = jiffies; 
			
			return pEntry;
        }
        else
			pEntry = pEntry->pNext;
	}
	
	// We didn't find any matched Mac address.
	return NULL;
	
}


PUCHAR getInMacByOutMacFromSesMacTb(
	IN PUCHAR outMac,
	IN UINT16 sesID)
{
	UINT16 				hashIdx;
	SesMacMappingEntry *pEntry = NULL;

	if (!SesMacTable.valid)
		return NULL;
	
	// Use hash to find out the location of that entry and get the Mac address.
	hashIdx = sesID % MAX_SUPPORT_APCLI_STA;

	pEntry = SesMacTable.sesHash[hashIdx];
	while(pEntry)
	{
		if ((pEntry->sessionID == sesID) &&  IS_EQUAL_MAC(pEntry->outMacAddr, outMac))
		{
			DBGPRINT(RT_DEBUG_TRACE,"%s(): find it! dstMac=%02x:%02x:%02x:%02x:%02x:%02x\n", 
				__FUNCTION__, pEntry->inMacAddr[0],pEntry->inMacAddr[1],pEntry->inMacAddr[2],
				pEntry->inMacAddr[3],pEntry->inMacAddr[4],pEntry->inMacAddr[5]);

			//Update the lastTime to prevent the aging before pDA processed!
			pEntry->lastTime = jiffies; 

			return pEntry->inMacAddr;
		} 
		else
		{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?