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

📄 aironet4500_core.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        if (rx_buff->pkt_len < 22 ) rx_buff->pkt_len = 22;        //	if (!rx_buff->skb)		rx_buff->skb =  dev_alloc_skb(rx_buff->pkt_len + 12 +2);			if (rx_buff->skb == NULL) {		printk(KERN_CRIT "couldnt alloc rx_buff->skb in rx event \n");		priv->stats.rx_dropped++;		return -1;	}	rx_buff->type |= p80211copy_path_skb;		rx_buff->skb->dev = dev;//	skb_reserve(rx_buff->skb, rx_buff->pkt_len + 12 );	rx_buff->u.rx.payload = skb_put(rx_buff->skb, rx_buff->pkt_len + 12 ) ;	rx_buff->u.rx.payload  = ((char *)rx_buff->u.rx.payload ) +12;	AWC_ENTRY_EXIT_DEBUG("exit\n");	return 0;};intawc_802_11_find_copy_path(struct net_device * dev, struct awc_fid * rx_buff){//        struct awc_private * priv = (struct awc_private * )dev->priv;//        u8 is_802_3 = 0;//	int i = 0;	rx_buff->type =0;	return awc_802_11_copy_path_skb(dev,rx_buff);};/* 	called from INTERRUPT context,	must deliver the packet to where it was meant by 		awc_802_11_find_copy_path		SHOULD be efficient and	queue the packet if operations take longer*/ int parse_not_8023;       voidawc_802_11_router_rx(struct net_device * dev,struct awc_fid * rx_buff){        struct awc_private * priv = (struct awc_private * )dev->priv;	struct sk_buff * skb = rx_buff->skb;	u8 * payload = rx_buff->u.rx.payload;//	u8 * p802_3_macs_place = payload -12;	u16    pkt_len = rx_buff->pkt_len;		struct ieee_802_11_802_1H_header * bridge = NULL;	struct ieee_802_11_snap_header * snap = NULL;	struct ieee_802_11_802_1H_header * bridge_tmp;	struct ieee_802_11_snap_header * snap_tmp;	u16	ptr = 0;	u16	len;	AWC_ENTRY_EXIT_DEBUG("awc_802_11_router_rx");//	if (rx_buff->type & p80211_8023)		rx_buff->mac = rx_buff->u.rx.ieee_802_3.dst_mac;//	else	//		rx_buff->mac = rx_buff->u.rx.ieee_802_11.mac1;		if ( rx_buff->u.rx.ieee_802_11.frame_control == 0x8 )			memcpy(priv->bssid,rx_buff->u.rx.ieee_802_11.mac3,6);		while ((ptr < pkt_len - 1 ) && payload && parse_not_8023){		bridge_tmp 	= (struct ieee_802_11_802_1H_header*) &payload[ptr];		snap_tmp 	= (struct ieee_802_11_snap_header*) &payload[ptr];		len		= ntohs( *((u16*)&payload[ptr]) );				if (  len < 0x5DC)	{ // not a protocol						if ( len != pkt_len-2 - ptr){				printk(KERN_ERR "%s bad encapsulation lenght %x at pkt offset %x \n",dev->name,len,ptr);				goto bad_packet;			}			DEBUG(1,"parisng packet of size %x\n",len);			ptr +=2;			continue;		}					DEBUG(1,"parisng packet of proto %x\n",len);				if (snap_tmp->dsap == 0xaa &&  snap_tmp->ssap == 0xaa &&		    pkt_len - ptr > sizeof(struct ieee_802_11_snap_header) ){						DEBUG(0x200,"%s SNAP ",dev->name);			if (snap_tmp->ctrl != 0x03){				printk(KERN_ERR "%s unknown snap ctrl %x \n",dev->name,snap_tmp->ctrl);				goto bad_packet;			};			if (snap_tmp->oui[0] == 0 && // LLC RFC1042			    snap_tmp->oui[1] == 0 &&			    snap_tmp->oui[2] == 0 ){			    	snap = 	snap_tmp;			    	ptr +=	sizeof(struct ieee_802_11_snap_header);			    	DEBUG(0x200,"%s LLC RFC1042 \n",dev->name);			    	continue;			}			if (snap_tmp->oui[0] == 0 && // LLC 802.1H			    snap_tmp->oui[1] == 0 &&			    snap_tmp->oui[2] == 0x78){			    	snap = snap_tmp;			    	DEBUG(0x200,"%s LLC 802.1H \n",dev->name);			    	ptr +=	sizeof(struct ieee_802_11_snap_header);			    	continue;  			};			if (snap_tmp->oui[0] == 0x00 && // 802.1H itself			    snap_tmp->oui[1] == 0x40 &&			    snap_tmp->oui[2] == 0x96){			    	ptr +=	sizeof(struct ieee_802_11_802_1H_header);			    	if (ptr >= pkt_len){			    		goto bad_packet;			    		DEBUG(1,"%s invalid packet len in 802.1H SNAP OUI check \n",dev->name);			    	}			    	DEBUG(0x200,"%s OUI 004096  \n",dev->name);			    	DEBUG(0x200," 802.1H uknown1 %x  ",ntohs(bridge_tmp->unknown1));			    	DEBUG(0x200," 802.1H uknw type %x  \n",0xf000 & ntohs(bridge_tmp->unknown2));			    	DEBUG(0x200," 802.1H payloadsize %x  \n",0x0fff & ntohs(bridge_tmp->unknown2));			    				    	//goto bad_packet; // TODO			    				    	bridge = bridge_tmp;			    	if (bridge_tmp->unknown1 == 0x0000 &&			    	     ((ntohs(bridge_tmp->unknown2) & 0xf000) == 0x1000 ) ){			    	     rx_buff->type |= p80211_8021H;			    	     rx_buff->mac   = &payload[ptr];			    	     DEBUG(0x200," 802.1H DATA packet of size %x\n",0xf000 & ntohs(bridge_tmp->unknown2) );			    	     memcpy(priv->p2p,rx_buff->u.rx.ieee_802_11.mac2, 6);			    	     ptr +=12;			    	     continue;			    	};			    	DEBUG(0x200,"%s droping unknown  004096 packet \n ",dev->name);			    	goto bad_packet;			    				 			}			goto bad_packet;		}		if ( len > 0x5DC){ 			// packet without linklevel header for us					if (  len == 0x8000 ||  len == 0x8006){							DEBUG(0x200,"Non IP packet %x \n",ntohs(len));						};			goto good_packet;				};				goto good_packet;	}	   good_packet:	if (ptr > pkt_len)	goto bad_packet;	if ( rx_buff->mac != (payload + ptr -12) )		memcpy( payload +ptr -12, rx_buff->mac , 12);			if (!payload || !skb || !rx_buff->skb || !rx_buff->u.rx.payload)		return ;	//skb->ip_summed = CHECKSUM_NONE;	skb->data = payload + ptr -12;	skb->len += ptr ;		rx_buff->skb->protocol = eth_type_trans(rx_buff->skb,dev);	DEBUG(0x200,"eth_type_trans decided: %x\n",rx_buff->skb->protocol);	rx_buff->skb = NULL;	rx_buff->u.rx.payload = NULL;	priv->stats.rx_packets++;	priv->stats.rx_bytes++;		netif_rx(skb);	AWC_ENTRY_EXIT_DEBUG("exit\n");	return ;   bad_packet:   	DEBUG(0x200,"%s packet dropped in packet hdr parse \n ",dev->name);	if (rx_buff->skb && (rx_buff->type & p80211copy_path_skb)){		dev_kfree_skb_irq(rx_buff->skb);				rx_buff->skb = NULL;		rx_buff->u.rx.payload = NULL;	};	AWC_ENTRY_EXIT_DEBUG("exit\n");	};voidawc_802_11_failed_rx_copy(struct net_device * dev,struct awc_fid * rx_buff){	struct awc_private * priv = (struct awc_private * )dev->priv;	AWC_ENTRY_EXIT_DEBUG("awc_802_11_failed_rx_copy");	if (rx_buff->skb)                dev_kfree_skb_irq(rx_buff->skb);        rx_buff->skb = NULL;        rx_buff->u.rx.payload = NULL;	priv->stats.rx_errors++;	AWC_ENTRY_EXIT_DEBUG("exit\n");};/*	called from kernel->driver tx routine	must decide where and how to post the packet 	must post the packet to wherever it decides	either copy to card or enqueue to destination queue*/intawc_802_11_tx_find_path_and_post(struct net_device * dev,				 struct sk_buff * skb){	struct awc_private * priv = (struct awc_private * )dev->priv;	int i;	int len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* check min length*/	struct awc_fid * fid = NULL;//	u16 saved_fid ;	u16 p2p_direct =priv->p2p_found;	struct iphdr * ip_hdr;	//buffer = skb->data;	AWC_ENTRY_EXIT_DEBUG("awc_802_11_tx_find_path_and_post");		// netif_stop_queue(dev);	DOWN(&priv->tx_buff_semaphore);	if (len  > dev->mtu + 16 ) {		printk(KERN_ERR "%s packet size too large %d \n",dev->name, len);		goto final;	}	if (len + AWC_TX_HEAD_SIZE < AWC_TX_ALLOC_SMALL_SIZE  )		fid = awc_fid_queue_pop_head(&priv->tx_small_ready);	if (!fid)		fid = awc_fid_queue_pop_head(&priv->tx_large_ready);				if (!fid) {		DEBUG(32,"%s buffs in use \n",dev->name);		goto no_space;	}		/*	if (fid->u.tx.fid_size < len + AWC_TX_HEAD_SIZE){		awc_fid_queue_push_tail(&priv->tx_small_ready, fid);		fid = awc_fid_queue_pop_head(&priv->tx_large_ready);	}*/	if (!fid) {	       DEBUG(32,"%s buffs in use \n",dev->name);	       goto no_space;	}		if (fid->u.tx.fid_size < len + AWC_TX_HEAD_SIZE - 14){			printk(KERN_ERR "found too small tx fid size %d, pktlen %d \n",fid->u.tx.fid_size, len);	}	memset(&fid->u.tx.radio_tx,		0,sizeof(struct aironet4500_radio_tx_header));	memset(&fid->u.tx.ieee_802_11,	0,sizeof(struct ieee_802_11_header));	memset(&fid->u.tx.ieee_802_3,	0,sizeof(struct ieee_802_3_header));	fid->u.tx.payload =NULL;	fid->u.tx.gap_length =0;	fid->busy = 1;			priv->tx_buffs_in_use++;	DEBUG(32,"found large buff %x \n",fid->u.tx.fid);/*	fid->type |= p80211_llc_snap;	fid->snap.dsap = 0xaa; 	fid->snap.ssap = 0xaa; 	fid->snap.ctrl = 0x03;		fid->snap.oui[0] = 0x0;	fid->snap.oui[1] = 0x0;	fid->snap.oui[2] = 0x0;*/	fid->skb = skb;	if (priv->p2p_uc && !priv->p2p_found){ // we go without encapsulation to neighbour;			for (i=0; i < 6; i++)			if (priv->p2p[i] != skb->data[i]){				p2p_direct = 1;				break;			}		};	if (priv->force_tx_rate == 2 || priv->force_tx_rate == 4 || 		priv->force_tx_rate== 11 || priv->force_tx_rate == 22){			fid->u.tx.radio_tx.tx_bit_rate  = priv->force_tx_rate;	} else if (priv->force_tx_rate != 0 ) {		printk(KERN_ERR "wrong force_tx_rate=%d changed to default \n",	priv->force_tx_rate);		priv->force_tx_rate = 0;	};	fid->u.tx.radio_tx.TX_Control = 		aironet4500_tx_control_tx_ok_event_enable |		aironet4500_tx_control_tx_fail_event_enable |		aironet4500_tx_control_no_release;	if (len < priv->force_rts_on_shorter){		fid->u.tx.radio_tx.TX_Control |=			aironet4500_tx_control_use_rts;	};	ip_hdr = (struct iphdr * ) ((( char * ) skb->data) + 14);	if (ip_hdr && skb->data[12] == 0x80 ){		if (ip_hdr->tos & IPTOS_RELIABILITY && priv->ip_tos_reliability_rts)			fid->u.tx.radio_tx.TX_Control |=			    aironet4500_tx_control_use_rts;		if (ip_hdr->tos & IPTOS_THROUGHPUT && priv->ip_tos_troughput_no_retries)			fid->u.tx.radio_tx.TX_Control |=			    aironet4500_tx_control_no_retries;	};	if (priv->p802_11_send ||  memcmp(dev->dev_addr, skb->data +6, 6)  ){		fid->u.tx.radio_tx.TX_Control |=			aironet4500_tx_control_header_type_802_11;			DEBUG(0x200,"%s bridging, forcing 802_11 send \n ",dev->name);	}	if (!priv->p2p_uc || p2p_direct) {		if ((fid->u.tx.radio_tx.TX_Control &		                 aironet4500_tx_control_header_type_802_11 )){			// including 802.3 header into 802.11 packet			fid->u.tx.radio_tx.PayloadLength 	= len -12;			fid->u.tx.ieee_802_3.payload_length = len -12 ;			fid->pkt_len = len -12;			fid->u.tx.payload = skb->data +12;			if (priv->simple_bridge){					memcpy(fid->u.tx.ieee_802_11.mac1,skb->data,6);				memcpy(fid->u.tx.ieee_802_11.mac2,skb->data +6,6);				memcpy(fid->u.tx.ieee_802_11.mac3,priv->status.CurrentBssid ,6);				memset(fid->u.tx.ieee_802_11.mac4,0,6);				fid->u.tx.ieee_802_11.frame_control = 0x8;				fid->u.tx.ieee_802_11.gapLen=6;			} else {				memcpy(fid->u.tx.ieee_802_11.mac1,skb->data,6);				memcpy(fid->u.tx.ieee_802_11.mac2,dev->dev_addr,6);				memcpy(fid->u.tx.ieee_802_11.mac3,skb->data +6 ,6);				memset(fid->u.tx.ieee_802_11.mac4,0 ,6);				fid->u.tx.ieee_802_11.frame_control = 0x108;				fid->u.tx.ieee_802_11.gapLen=6;                 			}		} else { // plain old 802.3, with hdr copied			fid->u.tx.radio_tx.PayloadLength 	= len -12;			fid->u.tx.ieee_802_3.payload_length = len -12;			fid->pkt_len = len - 12;			fid->u.tx.payload = skb->data +12;		};			memcpy(fid->u.tx.ieee_802_3.dst_mac,skb->data, 12);		DEBUG(0x200,"%s tx simply 802.3 type \n ",dev->name);			} else {// 802.1H bridgeing		fid->type 		|= p80211_8021H;		fid->bridge_size 	= len + sizeof(fid->bridge) ;		fid->bridge.dsap 	= 0xaa;		fid->bridge.ssap 	= 0xaa;		fid->bridge.ctrl 	= 0x03;		fid->bridge.oui[0] = 0x0;		fid->bridge.oui[1] = 0x40;		fid->bridge.oui[2] = 0x96;		fid->bridge.unknown1= 0x0000;		fid->bridge.unknown2= htons((len) & 0x1000);		fid->u.tx.radio_tx.PayloadLength 	= fid->bridge_size + 2;		fid->u.tx.ieee_802_3.payload_length = fid->u.tx.radio_tx.PayloadLength ;				fid->u.tx.payload = skb->data +12;		if ((fid->u.tx.radio_tx.TX_Control &		                 aironet4500_tx_control_header_type_802_11 )){				memcpy(fid->u.tx.ieee_802_11.mac1,priv->p2p,6);			memcpy(fid->u.tx.ieee_802_11.mac2,skb->data +6,6);			memcpy(fid->u.tx.ieee_802_11.mac3,priv->bssid ,6);			memset(fid->u.tx.ieee_802_11.mac4,0,6);			fid->u.tx.ieee_802_11.gapLen=6;			fid->u.tx.ieee_802_11.frame_control = 0x8;                 		}				memcpy(fid->u.tx.ieee_802_3.dst_mac,priv->p2p, 6);		memcpy(fid->u.tx.ieee_802_3.src_mac,dev->dev_addr, 6);		fid->u.tx.payload = skb->data + 2 + sizeof(fid->bridge);		fid->pkt_len = len ;			DEBUG(0x200,"%s tx simply 802.1H type \n ",dev->name);			};		priv->stats.tx_bytes += fid->u.tx.ieee_802_3.payload_length;	priv->stats.tx_packets++;			awc_fid_queue_push_tail(&priv->tx_in_transmit,fid);	udelay(1);	awc_transmit_packet(dev,fid);	if (priv->tx_large_ready.size <= 2 || priv->tx_small_ready.size <= 2 ){		if (netif_running(dev))			netif_stop_queue(dev);	} else {	  	if (netif_running(dev)) 			netif_wake_queue(dev);	}	UP(&priv->tx_buff_semaphore);	AWC_ENTRY_EXIT_DEBUG("exit\n");	return 0;	   no_space:	DEBUG(32,"%s tx buffs not found \n ",dev->name);	#ifdef AWC_DEBUG//		printk("s");	#endif   	netif_stop_queue (dev); //weell, here it must be set anyway and before

⌨️ 快捷键说明

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