⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 am930mac.c

📁 Linux Wireless LAN Project 的目标是开发一个完整的
💻 C
📖 第 1 页 / 共 4 页
字号:
	DBFENTER;	if ( mac->hw != NULL )	{		am930hw_ISR( mac->hw );	}	DBFEXIT;}/*----------------------------------------------------------------*	am930mac_mk_capinfo**	Uses the MIB and the current MAC state variables to construct*	a cap_info halfword.  The value returned is in HOST order!**	Arguments:*		none**	returns: *		The capinfo halfword in HOST order!----------------------------------------------------------------*/UINT16  am930mac_mk_capinfo(am930mac_t *mac){	UINT16	capinfo = 0;	if ( mac->mode == AM930_MACMODE_ESS_STA ||		 mac->mode == AM930_MACMODE_ESS_AP )	{		capinfo |= WLAN_SET_MGMT_CAP_INFO_ESS(1);	}	else if ( mac->mode == AM930_MACMODE_IBSS_STA )	{		capinfo |= WLAN_SET_MGMT_CAP_INFO_IBSS(1);	}	if ( mac->exclude_unencrypted )	{		capinfo |= WLAN_SET_MGMT_CAP_INFO_PRIVACY(1);	}	return capinfo;}/*----------------------------------------------------------------*	am930mac_ontxcomplete**	Callback from hw when tx is signaled complete.**	returns: nothing----------------------------------------------------------------*/void am930mac_ontxcomplete( am930mac_t *mac, UINT32 txresult ){	UINT32		txdone = 1;	wlan_pb_t	*pb = NULL;	am930q_t	*q;	int			i = 0;	DBFENTER;	do 	{		WLAN_LOG_DEBUG3( 3,"nextq=%x llcq.len=%d macq.len=%d\n", 			mac->nextq, am930q_length(mac->llcq), am930q_length(mac->macq));		q = NULL;		if ( am930q_length(mac->llcq) > 0 && am930q_length(mac->macq) > 0 )		{			q = mac->nextq & 0x01 ? mac->llcq : mac->macq;		}		else if ( am930q_length(mac->llcq) > 0 )		{			q = mac->llcq;		}		else if ( am930q_length(mac->macq) > 0 )		{			q = mac->macq;		}		if ( q != NULL )		{			pb = (wlan_pb_t*)am930q_dequeue(q);			if ( pb != NULL )			{				txdone = am930hw_txdata( mac->hw, pb, mac->mgr->curr_rate);				am930shim_pbfree(pb);				pb = NULL;			}			else			{				txdone = 1;			}		}		mac->nextq ^= 1;	} while( q != NULL && txdone == 0 && i++ < 4);#if (WLAN_OS == WLAN_LINUX_KERNEL)	if ( txresult != 0xffffffff )	{		am930shim_ontxcomplete( mac->llc, txresult);	}#elif (WLAN_OS == WLAN_LWOS)	am930shim_ontxcomplete( mac->llc, txresult);#else		#error "No WLAN_OS match!"#endif	DBFEXIT;	return;}/*----------------------------------------------------------------*	am930mac_rxdata**	Private helper for the rxframe method.**	returns: nothing----------------------------------------------------------------*/void am930mac_rxdata( am930mac_t *mac, wlan_pb_t *pb, am930rxstats_t *stats){	wlan_pb_t *pb2;	/* a clone */	DBFENTER;	if ( mac->mode != AM930_MACMODE_ESS_AP )	{		am930shim_rxframe( mac->llc, pb);	}	else	{		int 					isme;		int						isgroup;		wlan_stable_item_t		*sta = NULL;		isme = (memcmp(pb->p80211_hdr->a3.a3, mac->hw->addr, WLAN_ADDR_LEN) == 0);		isgroup = (pb->p80211_hdr->a3.a3[0] & 0x01);		/* Determine if we need two copies of the frame */		if ( !isgroup )		{			/* It's a directed frame, we only need one copy.  That */			/*  one copy will be sent either out the the WM, or up */			/*  to the higher layers                               */			/* TODO: We're making some assumptions about the hdr format here. */			/*		 Needs review.	*/			sta = am930mgr_stable_lookup( mac->mgr, pb->p80211_hdr->a3.a3);			if ( sta != NULL )			{				if (!(sta->sta.info & WLAN_STA_INFO_AUTH) )				{					am930mgr_class2err(mac->mgr, pb->p80211_hdr->a3.a2);					am930shim_pbfree(pb);					kfree_s( stats, sizeof(am930rxstats_t));					return;				}			}			if ( sta != NULL )			{				if ( !(sta->sta.info & WLAN_STA_INFO_ASSOC) )				{					am930mgr_class3err(mac->mgr, pb->p80211_hdr->a3.a2);					am930shim_pbfree(pb);					kfree_s( stats, sizeof(am930rxstats_t));					return;				}			}			pb2 = pb;		}		else		{			/* It's a multi/broadcast frame, we need two copies. One  */			/* for retransmission on the WM, one to hand up to higher */			/* layers                                                 */			/* clone the pb */			pb2 = am930shim_pballoc();			if ( pb2 != NULL )			{				am930shim_pballoc_p80211(pb2, pb->p80211buflen);				if ( pb2->p80211hostbuf != NULL )				{					memcpy(pb2->p80211hostbuf, pb->p80211hostbuf, pb->p80211buflen);					pb2->p80211frmlen = pb->p80211frmlen - WLAN_CRC_LEN;					pb2->p80211_payloadlen = pb->p80211_payloadlen;					pb2->wep_iscrypt = pb->wep_iscrypt;					pb2->wep_iv = pb->wep_iv;					pb2->wep_icv = pb->wep_icv;				}				else /* alloc failure, drop the frame */				{					am930shim_pbfree(pb2);					am930shim_pbfree(pb);					kfree_s( stats, sizeof(am930rxstats_t));					return;				}			}			else /* alloc failure, drop the frame */			{				am930shim_pbfree(pb);				kfree_s( stats, sizeof(am930rxstats_t));				return;			}		}		/* If the frame needs to go back out on the WM, do it */		if ( isgroup || sta != NULL )		{			UINT8	a[WLAN_ADDR_LEN];			UINT16	fc;			/* switch the addresses around and send it out */			memcpy( a, pb2->p80211_hdr->a3.a1, WLAN_BSSID_LEN); 	/* save bssid */			memcpy( pb2->p80211_hdr->a3.a1, pb2->p80211_hdr->a3.a3, WLAN_ADDR_LEN);	/* DA to a1 */			memcpy( pb2->p80211_hdr->a3.a3, pb2->p80211_hdr->a3.a2, WLAN_ADDR_LEN); /* SA to a3 */			memcpy( pb2->p80211_hdr->a3.a2, a, WLAN_BSSID_LEN);	/* bssid to a2 */				fc = ieee2host16(pb2->p80211_hdr->a3.fc);			fc &= ~(WLAN_SET_FC_TODS(1) |					WLAN_SET_FC_RETRY(1) |					WLAN_SET_FC_PWRMGT(1) );			fc |=  WLAN_SET_FC_FROMDS(1);			pb2->p80211_hdr->a3.fc = host2ieee16(fc);					pb2->p80211_hdr->a3.dur = host2ieee16(0);			/* check to see if we need to encrypt */			if ( 			((pb2->p80211_hdr->a3.a1[0] & 0x01) && mac->exclude_unencrypted))			{					am930mac_wep_encrypt(mac, pb2);			}			else if ( sta != NULL )			{				if ( ( sta->sta.info & WLAN_STA_INFO_WEPON) || 					mac->exclude_unencrypted)				{						am930mac_wep_encrypt(mac, pb2);				}			}			/* enqueue the frame for delivery */			if ( am930mac_txmac( mac, pb2) > 1 ) /* if not queued */			{				am930shim_pbfree(pb2);			}		}		/* If the frame needs to go up to higher layers, do that.  In the */		/*  case of multi/broadcast frames, both will be done.            */		if( isme || isgroup || sta == NULL )		{			am930shim_rxframe( mac->llc, pb);		}	}	kfree_s( stats, sizeof(am930rxstats_t));	DBFEXIT;	return;}/*----------------------------------------------------------------*	am930mac_rxenqueue**	Enqueue a received frame for later processing.**	returns: nothing----------------------------------------------------------------*/void am930mac_rxenqueue( am930mac_t *mac, wlan_pb_t *pb, am930rxstats_t *stats){	am930mac_rxitem_t	*item;	DBFENTER;	item = kmalloc(sizeof(am930mac_rxitem_t), GFP_ATOMIC);	if ( item != NULL )	{		item->f = pb;		item->s = stats;		if ( am930q_enqueue( mac->rxq, item) >= 2 )		{			/* drop the frame */			am930shim_pbfree( pb );			am930shim_free(stats, sizeof(am930rxstats_t));			kfree_s(item, sizeof(am930mac_rxitem_t));		}		else		{			#if (WLAN_OS == WLAN_LWOS )				am930lw_readerkick();			#endif		}	}	else	{		/* drop the frame */		am930shim_pbfree( pb );		am930shim_free(stats, sizeof(am930rxstats_t));	}		DBFEXIT;	return;}/*----------------------------------------------------------------*	am930mac_rxframe**	Public method called when a frame has been received at a*   lower layer and needs to be handled by this layer.**	returns: nothing----------------------------------------------------------------*/void am930mac_rxframe( am930mac_t *mac){	UINT32				ftype;	wlan_pb_t			*pb;	am930rxstats_t		*stats;	am930mac_rxitem_t	*item;	DBFENTER;	while (((item) = am930q_dequeue(mac->rxq)) != NULL)	{		pb = item->f;		stats = item->s;		kfree_s( item, sizeof(*item));				ftype = WLAN_GET_FC_FTYPE(ieee2host16(pb->p80211_hdr->a3.fc));		if ( ftype != WLAN_FTYPE_MGMT && ftype != WLAN_FTYPE_DATA )		{			/* we've got a frame we shouldn't...drop it */			WLAN_LOG_WARNING0("Ctl or unknown frame type received, dropped\n"); 			kfree_s( stats, sizeof(am930rxstats_t));			am930shim_pbfree(pb);		}		/* first, give the frag filter a chance */		pb = am930mac_defrag(mac, pb);		if ( pb == NULL )		{			/* the frame was absorbed by a fragment pool, do no more */			kfree_s( stats, sizeof(am930rxstats_t));		}		else		{			/* OK, we still have the frame, give the crypto a chance */			pb = am930mac_wep_decrypt(mac, pb);			if ( pb == NULL )			{				/* the frame failed decryption somehow, do no more */				kfree_s( stats, sizeof(am930rxstats_t));			}			else			{				switch( ftype )				{					case WLAN_FTYPE_MGMT:						am930mac_rxmgmt( mac, pb, stats);						break;					case WLAN_FTYPE_DATA:						am930mac_rxdata( mac, pb, stats);						break;				}			}		}	}	DBFEXIT;	return;}/*----------------------------------------------------------------*	am930mac_defragfinish**	Takes a fragment pool, validates it and assembles the MSDU*	into a new pb buffer.  If the fragments are encrypted, each*	fragment is decrypted as it's being added to the assembly.**	When defragmentation is complete, we discard the pb's for*	the fragments and mark the fragpool as free.**	Arguments:*		mac		- the receiver*		hash	- index of the fragpool to assemble*	*	returns: *	<a new pb>	- if the fragpool was succesfully reassembled*		NULL	- The fragpool was missing fragments, or the decryption*					of a fragment failed.----------------------------------------------------------------*/wlan_pb_t *am930mac_defragfinish( am930mac_t *mac, UINT8 hash ){	wlan_pb_t	*pb = NULL;	UINT32		nfrag = 0;	UINT32		iscrypt = 0;	UINT32  	seenall = 0;	UINT32  	offset = 0;	UINT32  	isbad = 0;	UINT32		i;	UINT32		len = WLAN_HDR_A3_LEN + WLAN_CRC_LEN;					/* calcs elsewhere assume CRC is present, so we need it */	DBFENTER;	/* add a lot to the lifetime counter to prevent removal */	mac->defragpool[hash].lifetime += 100000UL;	/* validate the fragment pool */	for (i=0; i < WLAN_FRAGS_MAX && !seenall; i++)	{		pb = mac->defragpool[hash].pb[i]; 		if ( pb == NULL )		{			/* Missing fragments. It's bad */			seenall = 1;			isbad = 1;			WLAN_LOG_DEBUG0(1, "defragfinish, missing frags, dropped .\n");		}		else		{			if ( i == 0 && WLAN_GET_FC_ISWEP(ieee2host16(pb->p80211_hdr->a3.fc)) )			{				/* If the first frag is crypt, they must all be */				iscrypt = 1;			}			if ( WLAN_GET_FC_ISWEP(ieee2host16(pb->p80211_hdr->a3.fc)) && !iscrypt )			{				/* mix of crypt and non-crypt. It's bad */				seenall = 1;				isbad = 1;				WLAN_LOG_DEBUG0(1, "defragfinish, not all crypt, dropped .\n");			}			if ( WLAN_GET_FC_MOREFRAG(ieee2host16(pb->p80211_hdr->a3.fc)) == 0 )			{				/* Ok, this is the last one. As long as isbad is clear */				/*  we're on our way */				seenall = 1;			}			nfrag++;			len += pb->p80211_payloadlen;		}	}	if ( !isbad )	{		/* validation was successful, decrypt and defrag */		#if (WLAN_OS == WLAN_LINUX_KERNEL)			pb = am930llc_pballoc();		#elif (WLAN_OS == WLAN_LWOS)			pb = am930lw_pballoc();		#else			#error "No WLAN_OS match!"		#endif		if ( pb == NULL )		{			WLAN_LOG_DEBUG0(2,"pballoc failed.\n");		}		else		{			#if (WLAN_OS == WLAN_LINUX_KERNEL)				am930llc_pballoc_p80211(pb, len);			#elif (WLAN_OS == WLAN_LWOS)				am930lw_pballoc_p80211(pb, len);			#else				#error "No WLAN_OS match!"			#endif

⌨️ 快捷键说明

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