📄 dot11smeaplib.c
字号:
} *(UINT32 *)data = ((UINT32)(!pBss->showSsidInBeacon)) | ((UINT32)(!pBss->respondBcastSsid) << 1); status = OK; break; /************************************************************** * WIOCSDTIMRATE: Sets the current DTIM interval and updates the AP **************************************************************/ case WIOCSDTIMRATE: pDot11->sme->dtimPeriod = *(UINT32 *)data; status = pDot11->sme->reset(pDot11); break; /************************************************************** * EIOCSAUTHCALLBACK - (legacy) Sets the authentication callback **************************************************************/ case EIOCSAUTHCALLBACK: status = pDot11->sme->endIoctl((END_OBJ *)pDot11, WIOCSAUTHCALLBACK, data); break; /************************************************************** * WIOCS80211D - Enable or disable 802.11d mode **************************************************************/ case WIOCS80211D: pDot11->sme->multiDomainEnabled = (BOOL)data; status = pDot11->sme->reset(pDot11); break; default: status = EINVAL; break; } return status; }/***************************************************************************** dot11SmeApRawSend - Packet transmission wrapper function** This routine is a wrapper function used by the AP. The AP SME initialization* replaces the HDD's rawPacketSend() with this routine, which performs various* AP-specific options and checks on an egress packet before passing it to the* HDD's rawPacketSend(), a pointer to which is stored in the AP_OBJ.** RETURNS: OK or the return from hdd->rawPacketSend(). Either way, the packet* is consumed.** ERRNO: N/A*/LOCAL STATUS dot11SmeApRawSend ( DOT11_FW * pDot11, /* Pointer to dot11 root object */ M_BLK_ID pMBlk, /* MBlk containing egress packet */ int rate, /* Rate at which to send */ int keyIndex /* Encryption key to use */ ) { DOT11_AP_OBJ * pAp; /* Ptr to AP specific data */ DOT11_HEADER * pHeader; /* pointer to 802.11 header */ DOT11_KSL_ENTRY * pKsl; /* KSL Entry for destination */ STATUS status; pAp = &pDot11->sme->type.ap; pHeader = (DOT11_HEADER *)pMBlk->mBlkHdr.mData; /* If this is a data packet, check if this is a unicast or multicast packet. If unicast, it must be to an associated station. If multicast, let it transmit */ pKsl = pDot11->sme->ksl.lookup(pDot11, pHeader->addr1); if ((DOT11_LE_TO_CPU_16(pHeader->frameCtrl) & DOT11_FCTL_TYPE_MASK) == DOT11_FTYPE_DATA) { if (((pKsl == NULL) || (!pKsl->type.sta.associated)) && (!(DOT11_IS_MCAST(pHeader->addr1)))) { DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_SME, ("dot11SmeApRawSend: KSL entry " DOT11_MAC_ADDR_STR " not found for dest.\n", DOT11_MAC_ADDR(pHeader->addr1))); /* Drop the packet */ netMblkClChainFree(pMBlk); return ERROR; } } /* Quick exit to the HDD rawPacketSet() if there are no stations in power management */ if ((!dot11SmeApPmActive(pDot11)) || (DOT11_FTYPE(DOT11_LE_TO_CPU_16(pHeader->frameCtrl)) == DOT11_TYPE_PROBE_RESP)) { DOT11_LOG(DOT11_DEBUG_FLOOD, DOT11_AREA_SME, ("dot11SmeApRawSend: Normal send\n", 0,1,2,3,4,5)); status = pAp->origRawPacketSend(pDot11, pMBlk, rate, keyIndex); } /* Split into two different cases for unicast and for multicast packets */ else if (DOT11_IS_MCAST(pHeader->addr1)) { /* Multicast and broadcast packets should be added to the DTIM queue to be sent out after the beacon. This is a function of the HDD performed by dtimPacketAdd() */ DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_SME, ("dot11SmeApRawSend: CAB enqueue\n", 0,1,2,3,4,5)); /* Packet will be freed regardless of success */ status = pDot11->hdd->dtimPacketAdd(pDot11, pMBlk, rate, keyIndex); } else /* Is a unicast packet */ { /* Quick exit if this station does not have a KSL entry or isn't under power management. In all these cases, We assume the HDD knows what it is doing. */ if ((pKsl == NULL) || (!pKsl->type.sta.powerManaged)) { DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_SME, ("dot11SmeApRawSend: Normal send (PM)\n", 0,1,2,3,4,5)); return pAp->origRawPacketSend(pDot11, pMBlk, rate, keyIndex); } /* Add the packet to the PS-POLL queue for this station */ DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_SME, ("dot11SmeApRawSend: PSPOLL enqueue\n", 0,1,2,3,4,5)); if (pDot11->sme->ksl.lock(pDot11) == ERROR) { DOT11_LOG(DOT11_DEBUG_ERROR, DOT11_AREA_SME, ("dot11SmeApRawSend: Cannot get KSL lock\n", 0,1,2,3,4,5)); return pAp->origRawPacketSend(pDot11, pMBlk, rate, keyIndex); } /* Insert at tail of queue. Check for the special case where there are no packets on the queue. */ pMBlk->mBlkHdr.mNextPkt = NULL; if (pKsl->type.sta.pmQueueHead == NULL) { pKsl->type.sta.pmQueueHead = pMBlk; pKsl->type.sta.pmQueueTail = pMBlk; } else /* Insert at tail */ { pKsl->type.sta.pmQueueTail->mBlkHdr.mNextPkt = pMBlk; pKsl->type.sta.pmQueueTail = pMBlk; } /* Release the KSL lock now that we are done adding items */ if (pDot11->sme->ksl.unlock(pDot11) == ERROR) { DOT11_LOG(DOT11_DEBUG_ERROR, DOT11_AREA_SME, ("dot11SmeApRawSend: Cannot release KSL lock\n", 0,1,2,3,4,5)); return ERROR; } status = OK; /* Modify the TIM bit in the beacon header. The TIVB semaphore is taken and released in the function*/ if(dot11SmeApTivbChange(pDot11, pKsl->type.sta.aid, TRUE, pKsl->pBss) != OK) { DOT11_LOG(DOT11_DEBUG_ERROR, DOT11_AREA_SME, ("dot11SmeApRawSend: Error setting TIVB bit. " "Flushing.\n", 0,1,2,3,4,5)); /* Get rid of all entires in this KSL entry, so that they aren't stuck there if the station decides to leave */ (void)dot11SmeApPmFlush(pDot11, pKsl, DOT11_PM_FLUSH); } } return status; }/***************************************************************************** dot11SmeApTivbChange - Sets/clears a bit in the TIVB** This routine sets or clears a bit in the Traffic Indication Virtual Bitmap * and adjusts the start and stop pointers appropriately** RETURNS: OK or ERROR** ERRNO: N/A*/LOCAL STATUS dot11SmeApTivbChange ( DOT11_FW * pDot11, /* Ptr to DOT11 framework root obj */ int aid, /* AID to modify */ BOOL set, /* True to set, False to clear */ DOT11_BSS * pBss /* Bss in which to change */ ) { int tivbByte; /* Byte to set in the TIVB */ int tivbBit; /* Bit to set in the TIVB */ int i; /* Generic counter */ DOT11_AP_OBJ * pAp; /* Ptr to AP data */ pAp = &pDot11->sme->type.ap; tivbByte = aid >> 3; /* There are eight bits to a byte */ tivbBit = aid & 0x7; DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_SME, ("dot11SmeApTivbChange: Started to %s AID %d. Byte = %d, " "bit = %d (prevStart = %d, prevStop=%d)\n", (int)(set?"SET":"CLEAR"),aid,tivbByte,tivbBit,pBss->tivbStart, pBss->tivbStop)); if (semTake(pBss->tivbSem, DOT11_TIVB_SEM_TIMEOUT) != OK) { DOT11_LOG(DOT11_DEBUG_ERROR, DOT11_AREA_SME, ("dot11SmeApTivbChange: Unable to get TIVB semaphore!\n", 0,0,0,0,0,0)); return ERROR; } if (set) { /* If we're setting a bit, we need to make sure that the bit is in the area between the start and stop marks. If not, expand the start and/or stop marks to encompass the bit */ pBss->tivb[tivbByte] |= _BIT(tivbBit); if (tivbByte > (pBss->tivbStop - 1)) { pBss->tivbStop = tivbByte + 1; } if (pBss->tivbStart > tivbByte) { pBss->tivbStart = tivbByte; } DOT11_LOG(DOT11_DEBUG_INFO, DOT11_AREA_SME, ("dot11SmeApTivbChange: Bit %d set in byte %d (start=%d " "stop = %d)\n",tivbBit, tivbByte, pBss->tivbStart, pBss->tivbStop,0,0)); } else { /* When clearing a bit, the algorithm is more complicated. There is one special case and four specific cases as shown below: */ /* First clear the bit under question */ pBss->tivb[tivbByte] &= ~(_BIT(tivbBit)); /*0. If there are other bits set in our byte, no adjustment of start. stop is necessary. */ if (pBss->tivb[tivbByte] == 0) { /* Too bad - there are no other bits in this byte, so we have to adjust tivbStart/tivbStop in some way. */ /* 1. Check if this was the only byte set in the bitmap. If so, then just clear start and stop to indicate no bits set */ if ((pBss->tivbStart == tivbByte) && (pBss->tivbStop == (tivbByte + 1))) { pBss->tivbStart = 0; pBss->tivbStop = 1; } /* 2. If there are other bytes set on both sides of this byte, no adjustment is necessary */ else if ((pBss->tivbStart < tivbByte) && (pBss->tivbStop > (tivbByte + 1))) { /* Do nothing */ } /* 3. If this is the lowest byte that is set, then we need to search upwards for the next lowest byte and change tivbStart */ else if ((pBss->tivbStart == tivbByte) && (pBss->tivbStop > (tivbByte + 1))) { for (i = tivbByte; i <= pBss->tivbStop; i++) { if (pBss->tivb[i] != 0) { pBss->tivbStart = i; break; } } /* If we found nothing then there was an error in the table and there are no other bits. */ if (i == pBss->tivbStop) { pBss->tivbStart = 0; pBss->tivbStop = 1; } } /* 4. If this is the highest byte that is set, then we search downwards for the next highest byte and change ticbStop*/ else if ((pBss->tivbStart < tivbByte) && (pBss->tivbStop == (tivbByte + 1))) { for (i = tivbByte; i >= (pBss->tivbStart - 1); i--) { if (pBss->tivb[i] != 0) { pBss->tivbStop = i + 1; break; } } /* If we found nothing then there was an error in the table and there are no other bits. */ if (i == pBss->tivbStart - 1) { pBss->tivbStart = 0; pBss->tivbStop = 1; } } else { /* Something is wrong - we shouldn't have gotten here. Do a brute force recalculation */ pBss->tivbStart = -1; pBss->tivbStop = 1; for (i=0; i<D
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -