📄 aironet4500_core.c
字号:
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 + -