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

📄 am930llc.c

📁 Linux Wireless LAN Project 的目标是开发一个完整的
💻 C
📖 第 1 页 / 共 3 页
字号:
			pb->p80211_payload = pb->ethbuf + sizeof(wlan_ethhdr_t);			pb->p80211_payloadlen = pb->ethbuflen - sizeof(wlan_ethhdr_t);		}	}	return 0;}/*----------------------------------------------------------------*	am930llc_p80211_to_ether*	Uses the contents of a received 802.11 frame and the etherconv *	setting to build an ether frame.**	This function extracts the src and dest address from the 802.11*	frame to use in the construction of the eth frame.**	This function _will_ set the ethfree member.  If a caller wants*	to allow some other component (a higher layer?) take responsiblity*	for freeing the ethhostbuf, the caller should set ethfree to NULL.**	Assume the following are already set:*		pb->p80211free*		pb->p80211hostbuf*		pb->p80211buf*		pb->p80211buflen*		pb->p80211_hdr*		pb->p80211_payload*		pb->p80211_payloadlen*	returns: zero on success, non-zero on failure----------------------------------------------------------------*/int am930llc_pb_p80211_to_ether( am930llc_t *llc, wlan_pb_t *pb){	UINT8			*daddr = NULL;	UINT8			*saddr = NULL;	wlan_ethhdr_t	*ethhdr;	UINT			llclen;		/* 802 LLC+data length */	UINT			dixlen;		/* DIX data length */	UINT			buflen;		/* full frame length, including PAD */	UINT16			fc;	/* setup some vars for convenience */	fc = ieee2host16(pb->p80211_hdr->a3.fc);	if ( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0) )	{		daddr = pb->p80211_hdr->a3.a1;		saddr = pb->p80211_hdr->a3.a2;	}	else if( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 1) ) 	{		daddr = pb->p80211_hdr->a3.a1;		saddr = pb->p80211_hdr->a3.a3;	}	else if( (WLAN_GET_FC_TODS(fc) == 1) && (WLAN_GET_FC_FROMDS(fc) == 0) ) 	{		daddr = pb->p80211_hdr->a3.a3;		saddr = pb->p80211_hdr->a3.a2;	}	else	{		WLAN_LOG_ERROR0("HDR_A4 detected! A4 currently not supported.\n");		/* set some bogus pointers so at least we won't crash */		daddr = pb->p80211_hdr->a3.a1;		saddr = pb->p80211_hdr->a3.a2;	}	ethhdr = (wlan_ethhdr_t*)(pb->p80211_payload);	pb->p80211_llc = (wlan_llc_t*)(((UINT8*)pb->p80211_hdr) + sizeof(p80211_hdr_a3_t));	pb->p80211_snap = (wlan_snap_t*)(((UINT8*)pb->p80211_llc) + sizeof(wlan_llc_t));	/* Test for the various encodings */	if ( memcmp( daddr, ethhdr->daddr, WLAN_ETHADDR_LEN) == 0 && 		memcmp(  saddr, ethhdr->saddr, WLAN_ETHADDR_LEN) == 0 )	{		/* ENCAP */		/* Test for an overlength frame */		if ( pb->p80211frmlen > WLAN_HDR_A3_LEN+WLAN_CRC_LEN+WLAN_MAX_ETHFRM_LEN)		{			/* A bogus length ethfrm has been encap'd. */			/* Is someone trying an oflow attack? */			return 1;		}		/* allocate space and setup host buffer */		buflen = llclen = pb->p80211frmlen - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;		pb->ethhostbuf = dev_alloc_skb(buflen + 2); /* +2 is attempt to align IP header */		if ( pb->ethhostbuf == NULL ) return 1;		pb->ethfree = am930llc_pbfreeskb;		skb_reserve( pb->ethhostbuf, 2);		skb_put( ((struct sk_buff*)pb->ethhostbuf), buflen);	/* make room */		pb->ethbuf = ((struct sk_buff*)pb->ethhostbuf)->data;		pb->ethbuflen = buflen;		/* setup the pointers */		pb->eth_hdr = (wlan_ethhdr_t*)pb->ethbuf;		pb->eth_llc = (wlan_llc_t*)(pb->ethbuf + sizeof(wlan_ethhdr_t));		pb->eth_snap = (wlan_snap_t*)			(pb->ethbuf + sizeof(wlan_ethhdr_t) + sizeof(wlan_llc_t));		pb->eth_payload = pb->ethbuf + sizeof(wlan_ethhdr_t);		pb->eth_payloadlen = buflen - sizeof(wlan_ethhdr_t);		/* now copy the data from the 80211 frame */		memcpy( pb->ethbuf, pb->p80211_payload, buflen);	/* copy the data */	}	else if (	pb->p80211_llc->dsap == 0xaa &&				pb->p80211_llc->ssap == 0xaa &&				pb->p80211_llc->ctl == 0x03 &&				memcmp( pb->p80211_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) == 0 &&				llc->ethconv == WLAN_ETHCONV_8021h && 				am930llc_stt_findproto(llc, pb->p80211_snap->type) )	{		/* it's a SNAP + RFC1042 frame && protocol is in STT */		/* build 802.3 + RFC1042 */				/* Test for an overlength frame */		if ( pb->p80211_payloadlen > WLAN_MAX_ETHFRM_LEN - WLAN_ETHHDR_LEN )		{			/* A bogus length ethfrm has been sent. */			/* Is someone trying an oflow attack? */			return 1;		}		llclen = pb->p80211_payloadlen;		buflen = wlan_max( llclen + sizeof(wlan_ethhdr_t), WLAN_MIN_ETHFRM_LEN);		pb->ethhostbuf = dev_alloc_skb(buflen + 2); /* +2 is attempt to align IP header */		if ( pb->ethhostbuf == NULL ) return 1;		skb_reserve( (struct sk_buff*)pb->ethhostbuf, 2);				skb_put( (struct sk_buff*)pb->ethhostbuf, buflen);	/* make room */		pb->ethbuf = ((struct sk_buff*)pb->ethhostbuf)->data;		pb->ethbuflen = buflen;/*		memset( pb->ethbuf, 0, buflen);	*/		/* zero for possible PAD */		/* set up the pointers */		pb->eth_hdr = (wlan_ethhdr_t*)pb->ethbuf;		pb->eth_llc = (wlan_llc_t*)(pb->ethbuf + sizeof(wlan_ethhdr_t));		pb->eth_snap = (wlan_snap_t*)			(pb->ethbuf + sizeof(wlan_ethhdr_t) + sizeof(wlan_llc_t));		pb->eth_payload = pb->ethbuf + sizeof(wlan_ethhdr_t);		pb->eth_payloadlen = llclen;		/* set up the 802.3 header */			pb->eth_hdr->type = htons(pb->eth_payloadlen);		memcpy( pb->eth_hdr->daddr, daddr, WLAN_ETHADDR_LEN);		memcpy( pb->eth_hdr->saddr, saddr, WLAN_ETHADDR_LEN);		/* now copy the data from the 80211 frame */		memcpy( pb->eth_payload, pb->p80211_payload, pb->p80211_payloadlen);	}	else if (	pb->p80211_llc->dsap == 0xaa &&				pb->p80211_llc->ssap == 0xaa &&				pb->p80211_llc->ctl == 0x03 )	{		/* it's an 802.1h frame || (an RFC1042 && protocol is not in STT) */		/* build a DIXII + RFC894 */		dixlen = pb->p80211_payloadlen - sizeof(wlan_llc_t) - sizeof(wlan_snap_t);		/* Test for an overlength frame */		if ( dixlen + WLAN_ETHHDR_LEN > WLAN_MAX_ETHFRM_LEN)		{			/* A bogus length ethfrm has been sent. */			/* Is someone trying an oflow attack? */			return 1;		}		dixlen = pb->p80211_payloadlen - sizeof(wlan_llc_t) - sizeof(wlan_snap_t);		buflen = wlan_max( dixlen + sizeof(wlan_ethhdr_t), WLAN_MIN_ETHFRM_LEN);		pb->ethhostbuf = dev_alloc_skb(buflen + 2); /* +2 is attempt to align IP header */		if ( pb->ethhostbuf == NULL ) return 1;		skb_reserve( (struct sk_buff*)pb->ethhostbuf, 2);				skb_put( (struct sk_buff*)pb->ethhostbuf, buflen);	/* make room */		pb->ethbuf = ((struct sk_buff*)pb->ethhostbuf)->data;		pb->ethbuflen = buflen;/*		memset( pb->ethbuf, 0, buflen);	*/		/* zero for possible PAD */		/* set up the pointers */		pb->eth_hdr = (wlan_ethhdr_t*)pb->ethbuf;		pb->eth_llc = NULL;		pb->eth_snap = NULL;		pb->eth_payload = pb->ethbuf + sizeof(wlan_ethhdr_t);		pb->eth_payloadlen = dixlen;		/* make sure the llc and snap ptrs are set */		pb->p80211_llc = (wlan_llc_t*)pb->p80211_payload;		pb->p80211_snap = (wlan_snap_t*)			(pb->p80211_payload + sizeof(wlan_llc_t));		/* set up the DIXII header */			pb->eth_hdr->type = pb->p80211_snap->type;		memcpy( pb->eth_hdr->daddr, daddr, WLAN_ETHADDR_LEN);		memcpy( pb->eth_hdr->saddr, saddr, WLAN_ETHADDR_LEN);		/* now copy the data from the 80211 frame */		memcpy( pb->eth_payload, 				pb->p80211_payload + sizeof(wlan_llc_t) + sizeof(wlan_snap_t), 				dixlen);	}	else	{		/* any NON-ENCAP */		/* it's a generic 80211+LLC or IPX 'Raw 802.3' */		/*  build an 802.3 frame */		/* allocate space and setup hostbuf */		/* Test for an overlength frame */		if ( pb->p80211_payloadlen + WLAN_ETHHDR_LEN > WLAN_MAX_ETHFRM_LEN)		{			/* A bogus length ethfrm has been sent. */			/* Is someone trying an oflow attack? */			return 1;		}		llclen = pb->p80211_payloadlen;		buflen = wlan_max( llclen + sizeof(wlan_ethhdr_t), WLAN_MIN_ETHFRM_LEN);		pb->ethhostbuf = dev_alloc_skb(buflen + 2); /* +2 is attempt to align IP header */		if ( pb->ethhostbuf == NULL ) return 1;		skb_reserve( (struct sk_buff*)pb->ethhostbuf, 2);				skb_put( (struct sk_buff*)pb->ethhostbuf, buflen);	/* make room */		pb->ethbuf = ((struct sk_buff*)pb->ethhostbuf)->data;		pb->ethbuflen = buflen;/*		memset( pb->ethbuf, 0, buflen);	*/		/* zero for possible PAD */		/* set up the pointers */		pb->eth_hdr = (wlan_ethhdr_t*)pb->ethbuf;		pb->eth_llc = (wlan_llc_t*)(pb->ethbuf + sizeof(wlan_ethhdr_t));		pb->eth_snap = (wlan_snap_t*)			(pb->ethbuf + sizeof(wlan_ethhdr_t) + sizeof(wlan_llc_t));		pb->eth_payload = pb->ethbuf + sizeof(wlan_ethhdr_t);		pb->eth_payloadlen = llclen;		/* set up the 802.3 header */			pb->eth_hdr->type = htons(pb->eth_payloadlen);		memcpy( pb->eth_hdr->daddr, daddr, WLAN_ETHADDR_LEN);		memcpy( pb->eth_hdr->saddr, saddr, WLAN_ETHADDR_LEN);		/* now copy the data from the 80211 frame */		memcpy( pb->eth_payload, pb->p80211_payload, pb->p80211_payloadlen);	}	return 0;}/*----------------------------------------------------------------*	am930llc_pbfreeskb*	Free method for wlan_pb's that have skbs in them.  Called*	via ptr from am930llc_pbfree.**	returns: nothing----------------------------------------------------------------*/void am930llc_pbfreeskb( void *buf, int size ){#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0))	dev_kfree_skb( (struct sk_buff*)buf, FREE_WRITE);#else	dev_kfree_skb( (struct sk_buff*)buf );#endif}/*----------------------------------------------------------------*	am930llc_pbkfree_s*	Free method for wlan_pb's that have linux kmalloc'd *	buffer's in them.  Called via ptr from am930llc_pbfree.**	returns: nothing----------------------------------------------------------------*/void am930llc_pbkfree_s( void *buf, int size){	kfree_s( buf, size);}/*----------------------------------------------------------------*	am930llc_pballoc*	Allocates and zeros a wlan_pb structure.  Largely here for*	symmetry with the pbfree routine.**	returns: A valid wlan_pb ptr on success,*			NULL otherwise.----------------------------------------------------------------*/wlan_pb_t* am930llc_pballoc(void){	wlan_pb_t	*pb;	pb = kmalloc( sizeof(wlan_pb_t), GFP_ATOMIC);	if ( pb != NULL )	{		memset(pb, 0, sizeof(wlan_pb_t));	}	return pb;}/*----------------------------------------------------------------*	am930llc_pballoc_p80211*	Allocates a buffer for an 80211 frame and sets the ptrs in a *	given pb.  Primarily used by the receive path (see hw).  Handled*	here so that the allocation used and the free method are set*	in one place (helps with portability?).**	returns: nothing*			caller should check pb->p80211hostbuf for NULL----------------------------------------------------------------*/void am930llc_pballoc_p80211(wlan_pb_t *pb, UINT len){	pb->p80211hostbuf = kmalloc( len, GFP_ATOMIC);	if ( pb->p80211hostbuf != NULL )	{		pb->p80211free = am930llc_pbkfree_s;		pb->p80211buf = (UINT8*)pb->p80211hostbuf;		pb->p80211buflen = len;		pb->p80211frmlen = len;		/* initially assume frm is same as buf */		pb->p80211_hdr = (p80211_hdr_t*)pb->p80211buf;		pb->p80211_payload = pb->p80211buf + WLAN_HDR_A3_LEN;		pb->p80211_payloadlen = pb->p80211buflen - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;	}	return;}/*----------------------------------------------------------------*	am930llc_pbfree*	Frees the ethhostbuf and the p80211hostbuf elements of a wlan_pb*	if there is a free method for each.  Then frees the wlan_pb itself.**	returns: nothing----------------------------------------------------------------*/void am930llc_pbfree(wlan_pb_t* pb){	if ( pb->ethhostbuf != NULL && pb->ethfree != NULL)	{		(*(pb->ethfree))(pb->ethhostbuf, pb->ethbuflen);	}	if ( pb->p80211hostbuf != NULL && pb->p80211free != NULL)	{		(*(pb->p80211free))(pb->p80211hostbuf, pb->p80211buflen);	}	kfree_s(pb, sizeof(wlan_pb_t));}/*----------------------------------------------------------------*	am930llc_rxframe*	Event method called from mac when a frame has been received.**	returns: zero----------------------------------------------------------------*/void am930llc_rxframe( am930llc_t *llc, wlan_pb_t *pb){	struct sk_buff	*skb;	DBFENTER;	llc->dev->interrupt = 1;	if ( llc->dev->start )	{		if ( am930llc_pb_p80211_to_ether(llc, pb) == 0 )		{			llc->dev->last_rx = jiffies;			/* take ownership of skb from pb */			skb = (struct sk_buff*)pb->ethhostbuf;			pb->ethhostbuf = NULL;			pb->ethfree = NULL;			skb->dev = llc->dev;			WLAN_HEX_DUMP(3,"llcethrx:", skb->data, skb->len);			skb->protocol = eth_type_trans( skb, llc->dev);			V2P(llc->dev->priv)->stats.rx_packets++;			netif_rx(skb);		}	}	llc->dev->interrupt = 0;	am930llc_pbfree(pb);	DBFEXIT;	return;}/*----------------------------------------------------------------*	am930llc_rxframe_err**	returns: zero----------------------------------------------------------------*/void am930llc_rxframe_err( am930llc_t *llc){	DBFENTER;	V2P(llc->dev->priv)->stats.rx_errors++;	DBFEXIT;	return;}/*----------------------------------------------------------------*	am930llc_sendtosniffer*	*	If a sniffer is registered, this function fills in the *	sniffer msg header and uses a netlink unicast delivery to send*	the frame up to the sniffer.*	*	Note: the caller is relinquishes ownership of the skb passed to*			this function.*	Arguments:*		skb		ptr to an skb allocated by the caller and filled with*				a wlan_sniffer_t + an 802.11 frame.**	returns: nothing----------------------------------------------------------------*/void am930llc_sendtosniffer(am930llc_t *llc, struct sk_buff *skb){	if ( llc->nlsk == NULL || llc->snifferpid == 0)	{		/* This really shouldn't happen */		WLAN_LOG_WARNING0("sendtosniffer called when no nl sk or registered sniffern");		kfree_skb(skb);	}	else	{		netlink_unicast( llc->nlsk, skb, llc->snifferpid, 1);	}	return;}/*----------------------------------------------------------------*	am930llc_stt_findproto*	Searches the 802.1h Selective Translation Table for a given *	protocol.**	returns: 1 - if the table is empty or a match is found.*			 0 - if the table is non-empty and a match is not found.----------------------------------------------------------------*/int am930llc_stt_findproto(am930llc_t *llc, UINT16 proto){	/* Always return found for now.  This is the behavior used by the */	/*  Zoom Win95 driver when 802.1h mode is selected */	/* TODO: If necessary, add an actual search */	return 1;}/*----------------------------------------------------------------*	am930llc_stt_addproto*	Adds a protocol number to the 802.1h Selective Translation Table.**	returns: 0 - on success*			 non-zero - if the table is full, or a memory allocation fails.----------------------------------------------------------------*/int am930llc_stt_addproto(am930llc_t *llc, UINT16 proto){	return 0;}/*----------------------------------------------------------------*	am930llc_devset_multicast_list*	set_multicast_list method for the linux net device. **	returns: nothing----------------------------------------------------------------*/#define HW_MAX_ADDRS 4void am930llc_devset_multicast_list(device_t *dev){	DBFENTER;	/* First handle our promisc state on its own */	/* We can handle it here by itself since the card supports ALLMULTI */	if ( dev->flags & IFF_PROMISC )	{		/* Enable Promiscuous Mode */		UINT8 one = 1;		am930mgr_mibsetitem(V2P(dev->priv)->llc->mgr, 			MAC_PROMISC_EN, &one, sizeof(one));		WLAN_LOG_DEBUG0(2, "am930 promisc enabled\n");	}	else	{		UINT8 zero = 0;		am930mgr_mibsetitem(V2P(dev->priv)->llc->mgr, 			MAC_PROMISC_EN, &zero, sizeof(zero));		WLAN_LOG_DEBUG0(2, "am930 promisc disabled\n");	}	/* Now handle the multicast state */	if ( dev->flags & IFF_ALLMULTI || (dev->mc_count > HW_MAX_ADDRS) )	{		/* Enable the hw "rcv all multicast" mode, either because of 		   the IFF_ALLMULTI switch or because we have more multicast		   hw addresses than the hw filter can hold (1.0 fw has four).		*/		printk(KERN_DEBUG "IFF_ALLMULTI currently unsupported.\n");	}	else if ( dev->mc_count )	{		/* Load the contents of the mc_list from the dev structure into		   the filter list in the hardware (effectively reset it from		   scratch).		*/		printk(KERN_DEBUG "Multicast filters currently unsupported.\n");	}	else	{		/* Disable allmulti, and clear the multicast filter list */	}	DBFEXIT;	return;}/*----------------------------------------------------------------*	am930llc_ontxcomplete**	returns: zero----------------------------------------------------------------*/void am930llc_ontxcomplete( am930llc_t *llc, UINT32 txresult){	DBFENTER;	if ( txresult != 0 && txresult != 0xffffffffUL) /* tx failure */	{		V2P(llc->dev->priv)->stats.tx_errors++;	}	else	{		V2P(llc->dev->priv)->stats.tx_packets++;	}	llc->dev->tbusy = 0;	mark_bh(NET_BH);	DBFEXIT;	return;}

⌨️ 快捷键说明

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