-static void handle_frame(struct wpa_driver_nl80211_data *drv,
- u8 *buf, size_t len,
- struct hostapd_frame_info *hfi,
- enum ieee80211_msg_type msg_type)
-{
- struct hostapd_iface *iface = drv->hapd->iface;
- struct ieee80211_hdr *hdr;
- u16 fc, type, stype;
- size_t data_len = len;
- struct hostapd_data *hapd = NULL;
- int broadcast_bssid = 0;
- size_t i;
- u8 *bssid;
-
- /*
- * PS-Poll frames are 16 bytes. All other frames are
- * 24 bytes or longer.
- */
- if (len < 16)
- return;
-
- hdr = (struct ieee80211_hdr *) buf;
- fc = le_to_host16(hdr->frame_control);
-
- type = WLAN_FC_GET_TYPE(fc);
- stype = WLAN_FC_GET_STYPE(fc);
-
- switch (type) {
- case WLAN_FC_TYPE_DATA:
- if (len < 24)
- return;
- switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
- case WLAN_FC_TODS:
- bssid = hdr->addr1;
- break;
- case WLAN_FC_FROMDS:
- bssid = hdr->addr2;
- break;
- default:
- /* discard */
- return;
- }
- break;
- case WLAN_FC_TYPE_CTRL:
- /* discard non-ps-poll frames */
- if (stype != WLAN_FC_STYPE_PSPOLL)
- return;
- bssid = hdr->addr1;
- break;
- case WLAN_FC_TYPE_MGMT:
- bssid = hdr->addr3;
- break;
- default:
- /* discard */
- return;
- }
-
- /* find interface frame belongs to */
- for (i = 0; i < iface->num_bss; i++) {
- if (memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) {
- hapd = iface->bss[i];
- break;
- }
- }
-
- if (hapd == NULL) {
- hapd = iface->bss[0];
-
- if (bssid[0] != 0xff || bssid[1] != 0xff ||
- bssid[2] != 0xff || bssid[3] != 0xff ||
- bssid[4] != 0xff || bssid[5] != 0xff) {
- /*
- * Unknown BSSID - drop frame if this is not from
- * passive scanning or a beacon (at least ProbeReq
- * frames to other APs may be allowed through RX
- * filtering in the wlan hw/driver)
- */
- if ((type != WLAN_FC_TYPE_MGMT ||
- stype != WLAN_FC_STYPE_BEACON))
- return;
- } else
- broadcast_bssid = 1;
- }
-
- switch (msg_type) {
- case ieee80211_msg_normal:
- /* continue processing */
- break;
- case ieee80211_msg_tx_callback_ack:
- handle_tx_callback(hapd, buf, data_len, 1);
- return;
- case ieee80211_msg_tx_callback_fail:
- handle_tx_callback(hapd, buf, data_len, 0);
- return;
- }
-
- switch (type) {
- case WLAN_FC_TYPE_MGMT:
- if (stype != WLAN_FC_STYPE_BEACON &&
- stype != WLAN_FC_STYPE_PROBE_REQ)
- wpa_printf(MSG_MSGDUMP, "MGMT");
- if (broadcast_bssid) {
- for (i = 0; i < iface->num_bss; i++)
- hostapd_mgmt_rx(iface->bss[i], buf, data_len,
- stype, hfi);
- } else
- hostapd_mgmt_rx(hapd, buf, data_len, stype, hfi);
- break;
- case WLAN_FC_TYPE_CTRL:
- /* can only get here with PS-Poll frames */
- wpa_printf(MSG_DEBUG, "CTRL");
- hostapd_rx_from_unknown_sta(drv->hapd, hdr->addr2);
- break;
- case WLAN_FC_TYPE_DATA:
- hostapd_rx_from_unknown_sta(drv->hapd, hdr->addr2);
- break;
- }
-}
-
-