📄 am930mac.c
字号:
if ( pb->p80211hostbuf == NULL ) { WLAN_LOG_DEBUG0(2,"pballoc_p80211 failed.\n"); #if (WLAN_OS == WLAN_LINUX_KERNEL) am930llc_pbfree(pb); #elif (WLAN_OS == WLAN_LWOS) am930lw_pbfree(pb); #else #error "No WLAN_OS match!" #endif } else { /* copy the header from the first frame and clear MoreFrag */ memcpy( pb->p80211buf, mac->defragpool[hash].pb[0]->p80211hostbuf, WLAN_HDR_A3_LEN); pb->p80211_hdr->a3.fc &= host2ieee16(~WLAN_SET_FC_MOREFRAG(1)); offset = 0; /* current offset into data portion of frame */ /* now, copy the data from each fragment */ for( i = 0; i < nfrag && !isbad; i++) { if ( iscrypt ) { mac->defragpool[hash].pb[i] = am930mac_wep_decrypt(mac, mac->defragpool[hash].pb[i]); } if ( mac->defragpool[hash].pb[i] == NULL ) { /* decryption failure */ isbad = 1; WLAN_LOG_DEBUG0(1, "defragfinish, decrypt fail, dropped .\n"); } else { /* we're ok, move the data */ memcpy( pb->p80211_payload + offset, mac->defragpool[hash].pb[i]->p80211_payload, mac->defragpool[hash].pb[i]->p80211_payloadlen ); offset += mac->defragpool[hash].pb[i]->p80211_payloadlen; } } } } } /* deallocate the fragpool */ for ( i = 0; i < WLAN_FRAGS_MAX; i++) { if ( mac->defragpool[hash].pb[i] != NULL ) { #if (WLAN_OS == WLAN_LINUX_KERNEL) am930llc_pbfree(mac->defragpool[hash].pb[i]); #elif (WLAN_OS == WLAN_LWOS) am930lw_pbfree(mac->defragpool[hash].pb[i]); #else #error "No WLAN_OS match!" #endif } mac->defragpool[hash].pb[i] = NULL; } mac->defragpool[hash].lifetime = 0; mac->defragpool[hash].seq = UINT16_MAX; DBFEXIT; return pb;}/*----------------------------------------------------------------* am930mac_defrag** Checks a frame to see if it's part of a fragmented MSDU. If* so, then it puts it into a defragpool and returns NULL. * If the MoreFrag field is clear, then we invoke the * defragmentation process build a new pb and return that to* the caller. If the frame doesn't need any kind of defrag* behavior, we just return it to caller.** Arguments:* mac - the receiver* pb - packet buffer containing the frame* * returns: * pb - if the frame doesn't need any defrag handling* <a new pb> - if the frame passed in was the last fragment and we* successfully defragmented.* NULL - The frame passed in was consumed by the defrag code* because:* - the frame passed in is a middle fragment and we* have no fragment pool* - the frame was the last fragment in a series * and we failed to finish the defragmentation * due to missing fragments or decryption failure.* - the frame was successfully placed in a fragment* pool.* NOTE:* The 802.11 SDL implies that an 802.11 STA associated with an* AP will always and only receive frames from the AP and that* the AP is responsible for generating any fragments as part of a* _single_ MA-UNITDATA.request . Therefore* it should be impossible for the STA MAC to have to deal w/ multiple* fragmented frames simultaneously. To cover possible implementation* differences, we're still going to keep track of (potentially) * multiple fragment pools identified by SRC address and sequence* number. In all other cases, multiple pools are required.----------------------------------------------------------------*/wlan_pb_t *am930mac_defrag( am930mac_t *mac, wlan_pb_t *pb){ UINT32 hash = 0; UINT8 *srcaddr = NULL; UINT32 morefrag; UINT32 seq; UINT32 fragnum; wlan_flags_t flags; UINT32 i; DBFENTER; /* collect the fragpool table index */ switch(mac->mode) { case AM930_MACMODE_ESS_AP: /* source addr is associated STA */ case AM930_MACMODE_IBSS_STA: /* source addr is peer STA */ hash = WLAN_MACADDR_HASH8(pb->p80211_hdr->a3.a2) & AM930MAC_FRAGPOOL_MASK; srcaddr = pb->p80211_hdr->a3.a2; break; /* TODO: consider wisdom of using SA */ case AM930_MACMODE_ESS_STA: /* source addr is !AP, use SA */ hash = WLAN_MACADDR_HASH8(pb->p80211_hdr->a3.a3) & AM930MAC_FRAGPOOL_MASK; srcaddr = pb->p80211_hdr->a3.a3; break; } morefrag = WLAN_GET_FC_MOREFRAG( ieee2host16(pb->p80211_hdr->a3.fc)); seq = WLAN_GET_SEQ_SEQNUM(ieee2host16(pb->p80211_hdr->a3.seq)); fragnum = WLAN_GET_SEQ_FRGNUM(ieee2host16(pb->p80211_hdr->a3.seq)); WLAN_LOG_DEBUG3(3, "defrag more=%ld seq=%ld fnum=%ld\n", morefrag, seq, fragnum); if ( (morefrag == 0) && (fragnum != 0) ) { /* It's the final in a fragment sequence */ /* This next comparison relies on the fact that it is _extremely_ */ /* unlikely that two MAC addresses that hash the same will be */ /* using the same sequence # at the same time. If it occurs, */ /* we'll nonfatally trash one MSDU from each STA. */ spin_lock_irqsave( &mac->fragpool_lock, flags); if ( mac->defragpool[hash].seq == seq ) { /* Ok, it's the last in a sequence that we're keeping */ mac->defragpool[hash].pb[fragnum] = pb; /* pb owned by pool now */ mac->defragpool[hash].seq = AM930MAC_FRAGPOOL_COMPLETE; spin_unlock_irqrestore( &mac->fragpool_lock, flags); pb = am930mac_defragfinish( mac, hash); /* also deallocs pool */ /* pb is either defragged frame in a new pb, or NULL if defrag */ /* failed */ } else { spin_unlock_irqrestore( &mac->fragpool_lock, flags); /* Either we've a hash collision or there's something bogus */ /* about our fragpools. Drop the frame. */ #if (WLAN_OS == WLAN_LINUX_KERNEL) am930llc_pbfree(pb); #elif (WLAN_OS == WLAN_LWOS) am930lw_pbfree(pb); #else #error "No WLAN_OS match!" #endif pb = NULL; WLAN_LOG_DEBUG0(1, "defrag final mismatch, dropped.\n"); } } else if ( morefrag != 0 ) { if ( fragnum == 0 ) { /* is fragpool avail? */ spin_lock_irqsave( &mac->fragpool_lock, flags); if ( 0 == memcmp(srcaddr, mac->defragpool[hash].srcaddr, WLAN_ADDR_LEN) && seq != mac->defragpool[hash].seq ) { /* it's the same STA, it's given up on prior frame */ /* we can reclaim this fragpool */ mac->defragpool[hash].seq = AM930MAC_FRAGPOOL_COMPLETE; for ( i = 0; i < WLAN_FRAGS_MAX; i++) { if ( mac->defragpool[hash].pb[i] != NULL ) { #if (WLAN_OS == WLAN_LINUX_KERNEL) am930llc_pbfree(mac->defragpool[hash].pb[i]); #elif (WLAN_OS == WLAN_LWOS) am930lw_pbfree(mac->defragpool[hash].pb[i]); #else #error "No WLAN_OS match!" #endif } mac->defragpool[hash].pb[i] = NULL; } mac->defragpool[hash].lifetime = 0; mac->defragpool[hash].seq = AM930MAC_FRAGPOOL_FREE; } if ( mac->defragpool[hash].seq == AM930MAC_FRAGPOOL_FREE ) { /* empty slot, create new pool */ mac->defragpool[hash].seq = seq; memcpy( mac->defragpool[hash].srcaddr, srcaddr, WLAN_ADDR_LEN); mac->defragpool[hash].lifetime = jiffies + wlan_tu2ticks(mac->maxrxlifetime); mac->defragpool[hash].pb[fragnum] = pb; /* fragpool owns pb */ spin_unlock_irqrestore( &mac->fragpool_lock, flags); pb = NULL; /* tell caller we've consumed it */ } else { /* collision on hash, frag sequence in progress: */ /* from same STA (impossible?), or */ /* frame DUP from same STA (f/w should prevent), or */ /* from hash colliding STA. Drop frame. */ /* check to see if it's same STA */ spin_unlock_irqrestore( &mac->fragpool_lock, flags); #if (WLAN_OS == WLAN_LINUX_KERNEL) am930llc_pbfree(pb); #elif (WLAN_OS == WLAN_LWOS) am930lw_pbfree(pb); #else #error "No WLAN_OS match!" #endif pb = NULL; WLAN_LOG_DEBUG0(1, "defrag initial mismatch, dropped.\n"); } } else /* fragnum != 0 */ { spin_lock_irqsave( &mac->fragpool_lock, flags); if ( mac->defragpool[hash].seq == seq && mac->defragpool[hash].pb[fragnum] == NULL ) { mac->defragpool[hash].pb[fragnum] = pb; spin_unlock_irqrestore( &mac->fragpool_lock, flags); pb = NULL; } else { /* collision on hash, frag sequence in progress: */ /* from same STA (diff seq, impossible?), or */ /* from hash colliding STA. Drop frame. */ spin_unlock_irqrestore( &mac->fragpool_lock, flags); #if (WLAN_OS == WLAN_LINUX_KERNEL) am930llc_pbfree(pb); #elif (WLAN_OS == WLAN_LWOS) am930lw_pbfree(pb); #else #error "No WLAN_OS match!" #endif pb = NULL; WLAN_LOG_DEBUG0(1, "defrag intermediate mismatch, dropped.\n"); } } } /* else morefrag==0 && fragnum==0, just return pb */ DBFEXIT; return pb;}/*----------------------------------------------------------------* am930mac_rxframe_err** returns: nothing----------------------------------------------------------------*/void am930mac_rxframe_err(am930mac_t *mac){#if (WLAN_OS == WLAN_LINUX_KERNEL) am930llc_rxframe_err(mac->llc);#elif (WLAN_OS == WLAN_LWOS) am930lw_rxframe_err( mac->lw);#else #error "No WLAN_OS match!"#endif return;}/*----------------------------------------------------------------* am930mac_rxmgmt** Private helper for the rxframe method. Checks to make sure* the received frame is actually directed to us (or is multi/broadcast)* before handing the frame off to the mgr component.** returns: nothing----------------------------------------------------------------*/void am930mac_rxmgmt( am930mac_t *mac, wlan_pb_t *pb, am930rxstats_t *stats){ int notme = 0; DBFENTER; WLAN_LOG_DEBUG0(3, "mgmt frm received\n"); /* Make sure this frame is really for me in case we're in promiscuous mode */ if ( (pb->p80211_hdr->a3.a1[0] & 0x01) == 0 ) /* is multicast? */ notme = memcmp( pb->p80211_hdr->a3.a1, mac->hw->addr, WLAN_ADDR_LEN); if ( notme ) { /* mgmt frame with DA that's not me...silently drop it */ am930shim_pbfree( pb ); kfree_s(stats, sizeof(am930rxstats_t)); } else { am930mgr_rxmgmt( mac->mgr, pb, stats); } DBFEXIT; return;}/*----------------------------------------------------------------* am930mac_timerfunc** Called 10 times per second by llc.** returns: nothing----------------------------------------------------------------*/void am930mac_timerfunc(am930mac_t *mac){ int i; int j; wlan_flags_t flags; for ( i = 0; i < AM930MAC_FRAGPOOLS_MAX; i++) { /* lock the whole table */ spin_lock_irqsave( &mac->fragpool_lock, flags); if ( mac->defragpool[i].seq != AM930MAC_FRAGPOOL_FREE && mac->defragpool[i].seq != AM930MAC_FRAGPOOL_COMPLETE && time_after_eq( jiffies, mac->defragpool[i].lifetime) ) { /* mark it as complete so noone messes with it */ mac->defragpool[i].seq = AM930MAC_FRAGPOOL_COMPLETE; for ( j=0; j < WLAN_FRAGS_MAX; j++) { if ( mac->defragpool[i].pb[j] != NULL ) { #if (WLAN_OS == WLAN_LINUX_KERNEL) am930llc_pbfree(mac->defragpool[i].pb[j]); #elif (WLAN_OS == WLAN_LWOS) am930lw_pbfree(mac->defragpool[i].pb[j]); #else #error "No WLAN_OS match!" #endif } mac->defragpool[i].pb[j] = NULL; } mac->defragpool[i].seq = AM930MAC_FRAGPOOL_FREE; } spin_unlock_irqrestore( &mac->fragpool_lock, flags); }}/*----------------------------------------------------------------* am930mac_txllc** Public method called from the llc object to send a frame. This * function takes a pb and addresses, formats the 802.11 header* and then enqueues the frame. The frame will be transmitted in* response to some future tx complete interrupt.** returns: * 0 success * 1 alloc failure* 2 queue full* 3 queue busy----------------------------------------------------------------*/UINT32 am930mac_txllc( am930mac_t *mac, UINT8 *daddr, UINT8 *saddr, wlan_pb_t *pb){ UINT32 result = 0; wlan_stable_item_t *sta; DBFENTER; if ( mac->mode == AM930_MACMODE_NOTRUNNING || mac->mode == AM930_MACMODE_NOTJOINED ) { WLAN_LOG_WARNING0("tx attempt, not joined, frame dropped\n"); return result; } switch( mac->mode ) { case AM930_MACMODE_IBSS_STA: /* copy the addresses to the 802.11 header */ memcpy( pb->p80211_hdr->a3.a1, daddr, WLAN_ADDR_LEN); memcpy( pb->p80211_hdr->a3.a2, saddr, WLAN_ADDR_LEN); memcpy( pb->p80211_hdr->a3.a3, mac->mgr->curr_bssid, WLAN_BSSID_LEN); /* set the rest of the 802.11 header */ pb->p80211_hdr->a3.fc = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA ) | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) ); pb->p80211_hdr->a3.dur = 0; pb->p80211_hdr->a3.seq = 0; /* let the cryptor determine the need */ am930mac_wep_encrypt( mac, pb ); break; case AM930_MACMODE_ESS_STA: /* copy the addresses to the 802.11 header */ memcpy( pb->p80211_hdr->a3.a1, mac->mgr->curr_bssid, WLAN_BSSID_LEN); memcpy( pb->p80211_hdr->a3.a2, saddr, WLAN_ADDR_LEN); memcpy( pb->p80211_hdr->a3.a3, daddr, WLAN_ADDR_LEN); /* set the rest of the 802.11 header */ pb->p80211_hdr->a3.fc = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA ) | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) | WLAN_SET_FC_TODS(1) ); pb->p80211_hdr->a3.dur = 0; pb->p80211_hdr->a3.seq = 0; /* let the cryptor determine the need */ am930mac_wep_encrypt( mac, pb ); break; case AM930_MACMODE_ESS_AP: /* Check that we want to tx this frame */ sta = am930mgr_stable_lookup( mac->mgr, daddr); if ( (daddr[0] & 0x01) || sta != NULL) { /* copy the addresses to the 802.11 header */ memcpy( pb->p80211_hdr->a3.a1, daddr, WLAN_ADDR_LEN); memcpy( pb->p80211_hdr->a3.a2, mac->mgr->curr_bssid, WLAN_BSSID_LEN); memcpy( pb->p80211_hdr->a3.a3, saddr, WLAN_ADDR_LEN); /* set the rest of the 802.11 header */ pb->p80211_hdr->a3.fc = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA ) | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) | WLAN_SET_FC_FROMDS(1) ); pb->p80211_hdr->a3.dur = 0; pb->p80211_hdr->a3.seq = 0; if ( ((daddr[0] & 0x01) && mac->exclude_unencrypted) || /* ismulti */ ( sta != NULL && /* is directed (relying on short-circuit) */ ( (sta->sta.info & WLAN_STA_INFO_WEPON) || /* sta uses wep */ mac->exclude_unencrypted)) ) /* MUST use wep */ { /* let the cryptor determine the need */ am930mac_wep_encrypt(mac, pb); } } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -