📄 dot11dpelib.c
字号:
* chain and put the appropriate 802.11 header into it. The new chain is linked* in front of the old chain, and the old header is adjusted to offset behind* the ethernet header. The SNAP header is also created in the first MBlk.** Note that the entire ethernet header must be in one cluster.** RETURNS: OK or ERROR on allocation error** ERRNO: N/A*/LOCAL STATUS dot11DpeEndSend ( END_OBJ * pEnd, /* Pointer to END_OBJ */ M_BLK_ID pDataMblk /* Mblk containing payload */ ) { DOT11_FW * pDot11 = (DOT11_FW *)pEnd; DOT11_KSL_ENTRY * pKsl; STATUS status = OK; int i; M_BLK_ID pMblk; UINT16 destVlan; UINT16 etherType; DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_DPE, ("dot11DpeEndSend: Called for dest " DOT11_MAC_ADDR_STR "\n", DOT11_MAC_ADDR((UINT8 *)pDataMblk->mBlkHdr.mData))); /* Ensure a correct MBlk */ if ((pDataMblk == NULL) || (pDataMblk->mBlkHdr.mType == MT_FREE)) { return ERROR; } /* Sanity check. */ if ((pDot11 == NULL) || (pDot11->hdd == NULL)) { netMblkClChainFree(pDataMblk); return ERROR; } if (pDot11->dot11Mode != DOT11_MODE_AP) { /* If this isn't AP mode, we don't need to worry about multiple BSSs */ etherType = *(UINT16 *)(pDataMblk->mBlkHdr.mData + 2 * DOT11_ADDR_LEN); status = dot11DpeEndSendBss(pDot11, pDataMblk, DOT11_DEFAULT_BSS); } else { /* Get the VLAN from the VLAN tag, if present */ if ((pDot11->sme->vlanEnabled) && (*(UINT16 *)(pDataMblk->mBlkHdr.mData + DOT11_ADDR_LEN + DOT11_ADDR_LEN) == ntohs(DOT11_ETHERTYPE_8021Q))) { destVlan = ntohs(*(UINT16 *)(pDataMblk->mBlkHdr.mData + DOT11_ETHER_HEADER_LEN)) & DOT11_8021Q_VLAN_MASK; etherType = *(UINT16 *)(pDataMblk->mBlkHdr.mData + DOT11_ETHER_HEADER_LEN + sizeof(UINT16)); DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_DPE, ("dot11DpeEndSend: Called for VLAN %d \n", destVlan, 0,0,0,0,0)); } else { etherType = *(UINT16 *)(pDataMblk->mBlkHdr.mData + 2 * DOT11_ADDR_LEN); destVlan = DOT11_NO_VLAN; } /* Check if this is a multicast or unicast packet. The destination address is at the start of the ethernet header, which is at the start of the packet */ if (DOT11_IS_MCAST(pDataMblk->mBlkHdr.mData)) { /* Send packet to each connected BSS */ for (i=0; i<DOT11_BSS_MAX; i++) { if (pDot11->sme->bss[i].inUse) { /* If VLAN support is enabled, verify that the tagged VLAN is that of the destination BSS, and forward */ if ((pDot11->sme->vlanEnabled) && (pDot11->sme->bss[i].vlanId != destVlan) && (etherType != DOT1X_ETHERTYPE)) { DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_DPE, ("dot11DpeEndSend: Dropping bcast packet " "sent to VLAN %d - BSS %d belongs to vlan" " %d \n", destVlan, i, pDot11->sme->bss[i].vlanId,0,0,0)); continue; } if ((pMblk = netMblkChainDup(pDot11->endObj.pNetPool, pDataMblk, 0, M_COPYALL, M_WAIT)) == NULL) { DOT11_LOG(DOT11_DEBUG_ERROR, DOT11_AREA_DPE, ("dot11DpeEndSend: Out of MBlks sending" " broadcast packet\n",0,0,0,0,0,0)); status = ERROR; break; } status |= dot11DpeEndSendBss(pDot11, pMblk, &pDot11->sme->bss[i]); } } /* Free the original non-duplicated packet */ netMblkClChainFree(pDataMblk); } else { pKsl = pDot11->sme->ksl.lookup(pDot11, (UINT8 *)pDataMblk->mBlkHdr.mData); /* If there is no KSL entry, then we are not connected to the destination */ if (pKsl == NULL) { /* Drop packet silently */ netMblkClChainFree(pDataMblk); status = OK; } else { /* If VLAN support is enabled, verify that the tagged VLAN is that of the destination BSS, and forward */ if ((pDot11->sme->vlanEnabled) && (pKsl->pBss->vlanId != destVlan) && (etherType != DOT1X_ETHERTYPE)) { DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_DPE, ("dot11DpeEndSend: Dropping UCAST packet " "sent to VLAN %d - BSS %d belongs to vlan" " %d \n", destVlan, pKsl->pBss->bssNum, pKsl->pBss->vlanId, 0,0,0)); DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_DPE, ("dot11DpeEndSend: Dropping UCAST to " DOT11_MAC_ADDR_STR "\n", DOT11_MAC_ADDR(pKsl->macAddr))); netMblkClChainFree(pDataMblk); status = OK; } else { status = dot11DpeEndSendBss(pDot11, pDataMblk, pKsl->pBss); } } } } return status; }/***************************************************************************** dot11DpeEndSendBss - END Send routine for a specific BSS** This is the END Send routine that is called when END wishes to send a packet* out the interface. This function will create a new Mblk/cl-blk/cluster * chain and put the appropriate 802.11 header into it. The new chain is linked* in front of the old chain, and the old header is adjusted to offset behind* the ethernet header. The SNAP header is also created in the first MBlk.** Note that the entire ethernet header must be in one cluster.** RETURNS: OK or ERROR on allocation error** ERRNO: N/A*/LOCAL STATUS dot11DpeEndSendBss ( DOT11_FW * pDot11, /* Pointer to END_OBJ */ M_BLK_ID pDataMblk, /* Mblk containing payload */ DOT11_BSS * pBss /* BSS to send packet to */ ) { STATUS status = ERROR; /* Status of second-level send function */ int fragLen; /* Max size of each packet, NOT inc header*/ int totalLen; /* Total PAYLOAD data to be sent */ int currentLen; /* Cumulative PAYLOAD data sent */ int currentFrag; /* Cumulative fragments sent - ZB */ int pktLen; /* Used when calc indiv packet details */ M_BLK_ID pCurrentMblk; /* Used when a new MBlk needs allocation */ M_BLK_ID pNewMblk; /* Used when a new MBlk needs allocation */ M_BLK_ID pHeadMblk; /* Used when a new MBlk needs allocation */ CL_BLK_ID pHdrClBlk; /* Cl-Blk containing header info */ UINT8 * pDstAddr; /* Pointer to DA for all packets */ UINT8 * pSrcAddr; /* Pointer to SA for all packets */ if (pBss->linkStatus == DOT11_LINK_DOWN) { DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_DPE, ("dot11DpeEndSendBss: Not connected\n",0,0,0,0,0,0)); netMblkClChainFree(pDataMblk); return ERROR; } /* Drop undersized packets */ if (pDataMblk->mBlkHdr.mLen < DOT11_ETHER_HEADER_LEN) { DOT11_LOG(DOT11_DEBUG_ERROR, DOT11_AREA_DPE, ("dot11DpeEndSendBss: MBlk not formed correctly. EH must " "not be split across MBlks!. Len = %d\n", pDataMblk->mBlkHdr.mLen, 0, 0, 0, 0,0)); netMblkClChainFree(pDataMblk); return ERROR; } /* Store the SA and DA so that we can put it in every packet. Since we know that it's in the first cluster by the check above, we just increment the refcnt on the first cluster so that nobody frees it until we're done with all fragments*/ pDstAddr = (UINT8*)pDataMblk->mBlkHdr.mData; pSrcAddr = (UINT8*)pDataMblk->mBlkHdr.mData + DOT11_ADDR_LEN; /* Check if we need to perform fragmentation */ if (((pDataMblk->mBlkPktHdr.len + sizeof(DOT11_HEADER) + DOT11_SNAP_HEADER_LEN - DOT11_ETHER_HEADER_LEN + DOT11_FCS_SIZE) <= pDot11->dpe->fragThreshold) || (DOT11_IS_MCAST(pDstAddr))) { /* No fragmentation necessary */ status = dot11DpeFragmentSend ((DOT11_FW*)pDot11, (UINT8*)pDataMblk->mBlkHdr.mData, (UINT8*)pDataMblk->mBlkHdr.mData+DOT11_ADDR_LEN, (M_BLK_ID)pDataMblk, (int)(0 | DOT11_FRAGMENT_LAST), 0, pBss); } else { DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_DPE, ("dot11DpeEndSendBss: Fragmenting pkt len %d/%d frag=%d\n", pDataMblk->mBlkPktHdr.len, pDataMblk->mBlkPktHdr.len + sizeof(DOT11_HEADER) - DOT11_ETHER_HEADER_LEN + DOT11_FCS_SIZE, pDot11->dpe->fragThreshold, 0,0,0)); if (pDot11->dpe->fragThreshold < DOT11_FRAGMENT_MIN_SIZE) { DOT11_LOG(DOT11_DEBUG_ERROR, DOT11_AREA_DPE, ("dot11DpeEndSendBss: Invalid fragmentation threshold\n", 0, 0, 0, 0, 0, 0)); netMblkClChainFree(pDataMblk); return ERROR; } pHdrClBlk = pDataMblk->pClBlk; pHdrClBlk->clRefCnt ++; /* We need to create appropriately sized fragments. Choose the maximum length of fragment based on the fragmentation size. Since 802.11(2003) 9.4 states that the size must always be even except for the last packet, accomodate that condition as well */ fragLen = (pDot11->dpe->fragThreshold - sizeof(DOT11_HEADER) - DOT11_FCS_SIZE) & (~0x00000001); totalLen = pDataMblk->mBlkPktHdr.len; currentLen = 0; currentFrag = 0; pNewMblk = pDataMblk; /* This is the main fragment creating loop. The original m-blk chain is examined. Anytime an M-blk has a fragment boundary in it, the length is adjusted to compensate, and a new Mblk is created for the part of the cluster after the boundary with the mData pointer adjusted. The reference count field in the Cl-Blk is used to keep track of multiple uses of a cluster. */ while (totalLen > currentLen) { /* For the first fragment, assume that dot11DpeFragmentSend() is going to add a SNAP header, and account for it */ if (currentLen == 0) { pktLen = DOT11_SNAP_HEADER_LEN - DOT11_ETHER_HEADER_LEN; } else { pktLen = 0; } pHeadMblk = pNewMblk; pCurrentMblk = pHeadMblk; /* Advance though the current M-Blk chain until we find an M-blk with a fragment boundary */ while ((pCurrentMblk != NULL) && ((pktLen + pCurrentMblk->mBlkHdr.mLen) <= fragLen)) { /* Since there's room for the entire mBlk, add it to the chain. */ pktLen += pCurrentMblk->mBlkHdr.mLen; pCurrentMblk = pCurrentMblk->mBlkHdr.mNext; } /* Getting here means that either we're at a cluster boundary or we're at the end of the chain. Either way, fill in the first Mblk with the appropriate header details */ pHeadMblk->mBlkHdr.mFlags |= M_PKTHDR; if (pCurrentMblk != NULL) { /* This is not the last fragment. Adjust the last Mblk of this fragment to reflect the boundary. */ pHeadMblk->mBlkPktHdr.len = fragLen; currentLen += fragLen; /* Allocate a new mBlk for the start of the next packet */ if ((pNewMblk = netMblkGet(pDot11->endObj.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { DOT11_LOG(DOT11_DEBUG_ERROR, DOT11_AREA_DPE, ("dot11DpeEndSendBss: Error allocting Mblk ln%d\n", __LINE__,0, 0, 0, 0,0)); netMblkClChainFree(pHeadMblk); /* Free the Cl-Blk that we incremented refCnt earlier */ netClBlkFree(pDot11->endObj.pNetPool, pHdrClBlk); return ERROR; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -