static void ccmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data, u8 *aad, size_t *aad_len, u8 *nonce) { u16 fc, stype, seq; int qos = 0, addr4 = 0; u8 *pos; nonce[0] = 0; fc = le_to_host16(hdr->frame_control); stype = WLAN_FC_GET_STYPE(fc); if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == (WLAN_FC_TODS | WLAN_FC_FROMDS)) addr4 = 1; if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) { fc &= ~0x0070; /* Mask subtype bits */ if (stype & 0x08) { const u8 *qc; qos = 1; fc &= ~WLAN_FC_ORDER; qc = (const u8 *) (hdr + 1); if (addr4) qc += ETH_ALEN; nonce[0] = qc[0] & 0x0f; } } else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) nonce[0] |= 0x10; /* Management */ fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA); fc |= WLAN_FC_ISWEP; WPA_PUT_LE16(aad, fc); pos = aad + 2; os_memcpy(pos, hdr->addr1, 3 * ETH_ALEN); pos += 3 * ETH_ALEN; seq = le_to_host16(hdr->seq_ctrl); seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */ WPA_PUT_LE16(pos, seq); pos += 2; os_memcpy(pos, hdr + 1, addr4 * ETH_ALEN + qos * 2); pos += addr4 * ETH_ALEN; if (qos) { pos[0] &= ~0x70; if (1 /* FIX: either device has SPP A-MSDU Capab = 0 */) pos[0] &= ~0x80; pos++; *pos++ = 0x00; } *aad_len = pos - aad; os_memcpy(nonce + 1, hdr->addr2, ETH_ALEN); nonce[7] = data[7]; /* PN5 */ nonce[8] = data[6]; /* PN4 */ nonce[9] = data[5]; /* PN3 */ nonce[10] = data[4]; /* PN2 */ nonce[11] = data[1]; /* PN1 */ nonce[12] = data[0]; /* PN0 */ }
static void test_driver_mlme(struct test_driver_data *drv, struct sockaddr_un *from, socklen_t fromlen, u8 *data, size_t datalen) { struct ieee80211_hdr *hdr; u16 fc; hdr = (struct ieee80211_hdr *) data; if (test_driver_get_cli(drv, from, fromlen) == NULL && datalen >= 16) { struct test_client_socket *cli; cli = os_zalloc(sizeof(*cli)); if (cli == NULL) return; wpa_printf(MSG_DEBUG, "Adding client entry for " MACSTR, MAC2STR(hdr->addr2)); memcpy(cli->addr, hdr->addr2, ETH_ALEN); memcpy(&cli->un, from, sizeof(cli->un)); cli->unlen = fromlen; cli->next = drv->cli; drv->cli = cli; } wpa_hexdump(MSG_MSGDUMP, "test_driver_mlme: received frame", data, datalen); fc = le_to_host16(hdr->frame_control); if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) { wpa_printf(MSG_ERROR, "%s: received non-mgmt frame", __func__); return; } ieee802_11_mgmt(drv->hapd, data, datalen, WLAN_FC_GET_STYPE(fc), NULL); }
/* Filters received packets. The function returns 1 if the packet should be * forwarded to ieee80211_rx(). If the packet should be ignored the function * returns 0. If an invalid packet is found the function returns -EINVAL. * * The function calls ieee80211_rx_mgt() directly. * * It has been based on ieee80211_rx_any. */ static int filter_rx(struct ieee80211_device *ieee, const u8 *buffer, unsigned int length, struct ieee80211_rx_stats *stats) { struct ieee80211_hdr_4addr *hdr; u16 fc; if (ieee->iw_mode == IW_MODE_MONITOR) return 1; hdr = (struct ieee80211_hdr_4addr *)buffer; fc = le16_to_cpu(hdr->frame_ctl); if ((fc & IEEE80211_FCTL_VERS) != 0) return -EINVAL; switch (WLAN_FC_GET_TYPE(fc)) { case IEEE80211_FTYPE_MGMT: if (length < sizeof(struct ieee80211_hdr_3addr)) return -EINVAL; ieee80211_rx_mgt(ieee, hdr, stats); return 0; case IEEE80211_FTYPE_CTL: return 0; case IEEE80211_FTYPE_DATA: /* Ignore invalid short buffers */ if (length < sizeof(struct ieee80211_hdr_3addr)) return -EINVAL; return is_data_packet_for_us(ieee, hdr); } return -EINVAL; }
int ieee80211_get_hdrlen(u16 fc) { int hdrlen = 24; switch (WLAN_FC_GET_TYPE(fc)) { case RTW_IEEE80211_FTYPE_DATA: if (fc & RTW_IEEE80211_STYPE_QOS_DATA) hdrlen += 2; if ((fc & RTW_IEEE80211_FCTL_FROMDS) && (fc & RTW_IEEE80211_FCTL_TODS)) hdrlen += 6; /* Addr4 */ break; case RTW_IEEE80211_FTYPE_CTL: switch (WLAN_FC_GET_STYPE(fc)) { case RTW_IEEE80211_STYPE_CTS: case RTW_IEEE80211_STYPE_ACK: hdrlen = 10; break; default: hdrlen = 16; break; } break; } return hdrlen; }
static void handle_tx_callback(hostapd *hapd, char *buf, size_t len, int ok) { struct ieee80211_hdr *hdr; u16 fc, type, stype; 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_MGMT: HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "MGMT (TX callback) %s\n", ok ? "ACK" : "fail"); ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); break; case WLAN_FC_TYPE_CTRL: HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "CTRL (TX callback) %s\n", ok ? "ACK" : "fail"); break; case WLAN_FC_TYPE_DATA: HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "DATA (TX callback) %s\n", ok ? "ACK" : "fail"); /* TODO: could replace TXExc counter hack with kernel driver * in data polling for inactivity check with the new TX * callback.. */ /* handle_data_cb(hapd, buf, len, stype, ok); */ break; default: printf("unknown TX callback frame type %d\n", type); break; } }
static void atheros_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { struct atheros_driver_data *drv = ctx; const struct ieee80211_mgmt *mgmt; u16 fc; union wpa_event_data event; /* Send Probe Request information to WPS processing */ if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) return; mgmt = (const struct ieee80211_mgmt *) buf; fc = le_to_host16(mgmt->frame_control); if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_PROBE_REQ) return; os_memset(&event, 0, sizeof(event)); event.rx_probe_req.sa = mgmt->sa; event.rx_probe_req.da = mgmt->da; event.rx_probe_req.bssid = mgmt->bssid; event.rx_probe_req.ie = mgmt->u.probe_req.variable; event.rx_probe_req.ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); wpa_supplicant_event(drv->hapd, EVENT_RX_PROBE_REQ, &event); }
void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx) { u16 status, fc; status = __le16_to_cpu(rx->status); printk(KERN_DEBUG "%s: RX status=0x%04x (port=%d, type=%d, " "fcserr=%d) silence=%d signal=%d rate=%d rxflow=%d; " "jiffies=%ld\n", name, status, (status >> 8) & 0x07, status >> 13, status & 1, rx->silence, rx->signal, rx->rate, rx->rxflow, jiffies); fc = __le16_to_cpu(rx->frame_control); printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x " "data_len=%d%s%s\n", fc, WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc), __le16_to_cpu(rx->duration_id), __le16_to_cpu(rx->seq_ctrl), __le16_to_cpu(rx->data_len), fc & WLAN_FC_TODS ? " [ToDS]" : "", fc & WLAN_FC_FROMDS ? " [FromDS]" : ""); printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4=" MACSTR "\n", MAC2STR(rx->addr1), MAC2STR(rx->addr2), MAC2STR(rx->addr3), MAC2STR(rx->addr4)); printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n", MAC2STR(rx->dst_addr), MAC2STR(rx->src_addr), __be16_to_cpu(rx->len)); }
void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx) { u16 fc; printk(KERN_DEBUG "%s: TX status=0x%04x retry_count=%d tx_rate=%d " "tx_control=0x%04x; jiffies=%ld\n", name, __le16_to_cpu(tx->status), tx->retry_count, tx->tx_rate, __le16_to_cpu(tx->tx_control), jiffies); fc = __le16_to_cpu(tx->frame_control); printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x " "data_len=%d%s%s\n", fc, WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc), __le16_to_cpu(tx->duration_id), __le16_to_cpu(tx->seq_ctrl), __le16_to_cpu(tx->data_len), fc & WLAN_FC_TODS ? " [ToDS]" : "", fc & WLAN_FC_FROMDS ? " [FromDS]" : ""); printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " A4=" MACSTR "\n", MAC2STR(tx->addr1), MAC2STR(tx->addr2), MAC2STR(tx->addr3), MAC2STR(tx->addr4)); printk(KERN_DEBUG " dst=" MACSTR " src=" MACSTR " len=%d\n", MAC2STR(tx->dst_addr), MAC2STR(tx->src_addr), __be16_to_cpu(tx->len)); }
static void handle_frame(struct wpa_driver_nl80211_data *drv, u8 *buf, size_t len, int datarate, int ssi_signal) { struct ieee80211_hdr *hdr; u16 fc; union wpa_event_data event; hdr = (struct ieee80211_hdr *) buf; fc = le_to_host16(hdr->frame_control); switch (WLAN_FC_GET_TYPE(fc)) { case WLAN_FC_TYPE_MGMT: os_memset(&event, 0, sizeof(event)); event.rx_mgmt.frame = buf; event.rx_mgmt.frame_len = len; event.rx_mgmt.datarate = datarate; event.rx_mgmt.ssi_signal = ssi_signal; wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); break; case WLAN_FC_TYPE_CTRL: /* can only get here with PS-Poll frames */ wpa_printf(MSG_DEBUG, "CTRL"); from_unknown_sta(drv, buf, len); break; case WLAN_FC_TYPE_DATA: from_unknown_sta(drv, buf, len); break; } }
static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { struct madwifi_driver_data *drv = ctx; const struct ieee80211_mgmt *mgmt; const u8 *end, *ie; u16 fc; size_t ie_len; /* Send Probe Request information to WPS processing */ if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) return; mgmt = (const struct ieee80211_mgmt *) buf; fc = le_to_host16(mgmt->frame_control); if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_PROBE_REQ) return; end = buf + len; ie = mgmt->u.probe_req.variable; ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); hostapd_wps_probe_req_rx(drv->hapd, mgmt->sa, ie, ie_len); }
/* Returns 1 if the data packet is for us and 0 otherwise. */ static int is_data_packet_for_us(struct ieee80211_device *ieee, struct ieee80211_hdr_4addr *hdr) { struct net_device *netdev = ieee->dev; u16 fc = le16_to_cpu(hdr->frame_ctl); ZD_ASSERT(WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA); switch (ieee->iw_mode) { case IW_MODE_ADHOC: if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != 0 || memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) != 0) return 0; break; case IW_MODE_AUTO: case IW_MODE_INFRA: if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != IEEE80211_FCTL_FROMDS || memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) != 0) return 0; break; default: ZD_ASSERT(ieee->iw_mode != IW_MODE_MONITOR); return 0; } return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 || (is_multicast_ether_addr(hdr->addr1) && memcmp(hdr->addr3, netdev->dev_addr, ETH_ALEN) != 0) || (netdev->flags & IFF_PROMISC); }
static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len) { struct ieee80211_hdr *hdr; u16 fc, type, stype; size_t data_len = len; int ver; union wpa_event_data event; /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass * these to user space */ if (len < 24) { wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)", (unsigned long) len); 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); if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) { wpa_hexdump(MSG_MSGDUMP, "Received management frame", buf, len); } ver = fc & WLAN_FC_PVER; /* protocol version 2 is reserved for indicating ACKed frame (TX * callbacks), and version 1 for indicating failed frame (no ACK, TX * callbacks) */ if (ver == 1 || ver == 2) { handle_tx_callback(drv, buf, data_len, ver == 2 ? 1 : 0); return; } else if (ver != 0) { printf("unknown protocol version %d\n", ver); return; } switch (type) { case WLAN_FC_TYPE_MGMT: os_memset(&event, 0, sizeof(event)); event.rx_mgmt.frame = buf; event.rx_mgmt.frame_len = data_len; wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event); break; case WLAN_FC_TYPE_CTRL: wpa_printf(MSG_DEBUG, "CTRL"); break; case WLAN_FC_TYPE_DATA: wpa_printf(MSG_DEBUG, "DATA"); handle_data(drv, buf, data_len, stype); break; default: wpa_printf(MSG_DEBUG, "unknown frame type %d", type); break; } }
static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) { struct hostapd_iface *iface = hapd->iface; const struct ieee80211_hdr *hdr; const u8 *bssid; struct hostapd_frame_info fi; int ret; hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); if (bssid == NULL) return 0; hapd = get_hapd_bssid(iface, bssid); if (hapd == NULL) { u16 fc; fc = le_to_host16(hdr->frame_control); /* * Drop frames to unknown BSSIDs except for Beacon frames which * could be used to update neighbor information. */ if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) hapd = iface->bss[0]; else return 0; } os_memset(&fi, 0, sizeof(fi)); fi.datarate = rx_mgmt->datarate; fi.ssi_signal = rx_mgmt->ssi_signal; if (hapd == HAPD_BROADCAST) { size_t i; ret = 0; for (i = 0; i < iface->num_bss; i++) { if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, rx_mgmt->frame_len, &fi) > 0) ret = 1; } } else ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi); random_add_randomness(&fi, sizeof(fi)); return ret; }
static void rtl871x_handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len, int ok) { #if 0 struct ieee80211_hdr *hdr; u16 fc, type, stype; struct sta_info *sta; //printf("%s\n", __func__); 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_MGMT: //printf("MGMT (TX callback) %s\n", // ok ? "ACK" : "fail"); ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); break; case WLAN_FC_TYPE_CTRL: printf("CTRL (TX callback) %s\n", ok ? "ACK" : "fail"); break; case WLAN_FC_TYPE_DATA: printf("DATA (TX callback) %s\n", ok ? "ACK" : "fail"); sta = ap_get_sta(hapd, hdr->addr1); if (sta && sta->flags & WLAN_STA_PENDING_POLL) { wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending activity poll", MAC2STR(sta->addr), ok ? "ACKed" : "did not ACK"); if (ok) sta->flags &= ~WLAN_STA_PENDING_POLL; } if (sta) ieee802_1x_tx_status(hapd, sta, buf, len, ok); break; default: printf("unknown TX callback frame type %d\n", type); break; } #endif }
static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, struct ieee80211_hdr_4addr *header) { struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); unsigned int tx_length = le16_to_cpu(cs->tx_length); u16 fctl = le16_to_cpu(header->frame_ctl); u16 ftype = WLAN_FC_GET_TYPE(fctl); u16 stype = WLAN_FC_GET_STYPE(fctl); /* * CONTROL TODO: * - if backoff needed, enable bit 0 * - if burst (backoff not needed) disable bit 0 */ cs->control = 0; /* First fragment */ if (WLAN_GET_SEQ_FRAG(le16_to_cpu(header->seq_ctl)) == 0) cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; /* Multicast */ if (is_multicast_ether_addr(header->addr1)) cs->control |= ZD_CS_MULTICAST; /* PS-POLL */ if (stype == IEEE80211_STYPE_PSPOLL) cs->control |= ZD_CS_PS_POLL_FRAME; /* Unicast data frames over the threshold should have RTS */ if (!is_multicast_ether_addr(header->addr1) && ftype != IEEE80211_FTYPE_MGMT && tx_length > zd_netdev_ieee80211(mac->netdev)->rts) cs->control |= ZD_CS_RTS; /* Use CTS-to-self protection if required */ if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM && ieee80211softmac_protection_needed(softmac)) { /* FIXME: avoid sending RTS *and* self-CTS, is that correct? */ cs->control &= ~ZD_CS_RTS; cs->control |= ZD_CS_SELF_CTS; } /* FIXME: Management frame? */ }
static void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok) { struct ieee80211_hdr *hdr; u16 fc; union wpa_event_data event; hdr = (struct ieee80211_hdr *) buf; fc = le_to_host16(hdr->frame_control); os_memset(&event, 0, sizeof(event)); event.tx_status.type = WLAN_FC_GET_TYPE(fc); event.tx_status.stype = WLAN_FC_GET_STYPE(fc); event.tx_status.dst = hdr->addr1; event.tx_status.data = buf; event.tx_status.data_len = len; event.tx_status.ack = ok; wpa_supplicant_event(ctx, EVENT_TX_STATUS, &event); }
static void handle_rx_frame(struct nl80211_data* ctx, u8 *buf, size_t len, int datarate, int ssi_signal) { struct ieee80211_hdr *hdr; u16 fc; hdr = (struct ieee80211_hdr *) buf; fc = le_to_host16(hdr->frame_control); if (len<IEEE80211_HDRLEN) { fprintf(stderr,"malformed packet\n"); return; } switch (WLAN_FC_GET_TYPE(fc)) { case WLAN_FC_TYPE_MGMT: { const u8 *bssid = get_hdr_bssid(hdr, len); if (memcmp(bssid,ctx->macaddr,6)==0) { //fprintf(stderr,"RECEIVED 802.11 MNGT FRAME %s\n", fc2str(fc)); mngt_rx_handle(ctx, buf, len, datarate, ssi_signal); break; } if (memcmp(bssid,broadcast_ether_addr,6)==0) { // fprintf(stderr,"RECEIVED 802.11 MNGT FRAME (BROADCAST) %s\n",fc2str(fc)); /*fprintf(stderr, "%02x:%02x:%02x:%02x:%02x:%02x\n", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);*/ break; }; break; } case WLAN_FC_TYPE_CTRL: /* can only get here with PS-Poll frames */ /*wpa_printf(MSG_DEBUG, "CTRL"); from_unknown_sta(drv, buf, len);*/ break; case WLAN_FC_TYPE_DATA: /*from_unknown_sta(drv, buf, len);*/ break; } }
static void rtl871x_receive_mgnt(struct rtl871x_driver_data *drv , const u8 *buf, size_t len) { const struct ieee80211_mgmt *mgmt; u16 fc, type, stype; struct hostapd_data *hapd = drv->hapd; #if 0 { int i; for(i=0; i<len; i+=8) { printf("%x:%x:%x:%x:%x:%x:%x:%x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]); } } #endif if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) return; mgmt = (const struct ieee80211_mgmt *)buf; fc = le_to_host16(mgmt->frame_control); type = WLAN_FC_GET_TYPE(fc); stype = WLAN_FC_GET_STYPE(fc); switch (type) { case WLAN_FC_TYPE_MGMT: if (stype != WLAN_FC_STYPE_BEACON) wpa_printf(MSG_MSGDUMP, "MGMT"); break; case WLAN_FC_TYPE_CTRL: printf("rtl871x_receive_mgnt, CTRL\n"); break; case WLAN_FC_TYPE_DATA: printf("rtl871x_receive_mgnt, DATA\n"); break; default: printf("unknown frame type %d\n", type); break; } }
/* hard_start_xmit function for hostapd wlan#ap interfaces */ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct hostap_interface *iface; local_info_t *local; struct hostap_skb_tx_data *meta; struct ieee80211_hdr_4addr *hdr; u16 fc; iface = netdev_priv(dev); local = iface->local; if (skb->len < 10) { printk(KERN_DEBUG "%s: hostap_mgmt_start_xmit: short skb " "(len=%d)\n", dev->name, skb->len); kfree_skb(skb); return 0; } iface->stats.tx_packets++; iface->stats.tx_bytes += skb->len; meta = (struct hostap_skb_tx_data *) skb->cb; memset(meta, 0, sizeof(*meta)); meta->magic = HOSTAP_SKB_TX_DATA_MAGIC; meta->iface = iface; if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) { hdr = (struct ieee80211_hdr_4addr *) skb->data; fc = le16_to_cpu(hdr->frame_ctl); if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA && WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) { u8 *pos = &skb->data[IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header)]; meta->ethertype = (pos[0] << 8) | pos[1]; } } /* Send IEEE 802.11 encapsulated frame using the master radio device */ skb->dev = local->dev; dev_queue_xmit(skb); return 0; }
static void handle_tx_callback(hostapd *hapd, char *buf, size_t len, int ok) { struct ieee80211_hdr *hdr; u16 fc, type, stype; struct sta_info *sta; 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_MGMT: HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "MGMT (TX callback) %s\n", ok ? "ACK" : "fail"); ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); break; case WLAN_FC_TYPE_CTRL: HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "CTRL (TX callback) %s\n", ok ? "ACK" : "fail"); break; case WLAN_FC_TYPE_DATA: HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "DATA (TX callback) %s\n", ok ? "ACK" : "fail"); sta = ap_get_sta(hapd, hdr->addr1); if (sta && sta->flags & WLAN_STA_PENDING_POLL) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "STA " MACSTR " %s pending activity poll\n", MAC2STR(sta->addr), ok ? "ACKed" : "did not ACK"); if (ok) sta->flags &= ~WLAN_STA_PENDING_POLL; } if (sta) ieee802_1x_tx_status(hapd, sta, buf, len, ok); break; default: printf("unknown TX callback frame type %d\n", type); break; } }
static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs, struct ieee80211_hdr_4addr *hdr) { struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); u8 rate, zd_rate; int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; int is_multicast = is_multicast_ether_addr(hdr->addr1); int short_preamble = ieee80211softmac_short_preamble_ok(softmac, is_multicast, is_mgt); int flags = 0; /* FIXME: 802.11a? */ rate = ieee80211softmac_suggest_txrate(softmac, is_multicast, is_mgt); if (short_preamble) flags |= R2M_SHORT_PREAMBLE; zd_rate = rate_to_zd_rate(rate); cs->modulation = zd_rate_to_modulation(zd_rate, flags); }
const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len) { u16 fc, type, stype; /* * PS-Poll frames are 16 bytes. All other frames are * 24 bytes or longer. */ if (len < 16) return NULL; 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 NULL; switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) { case WLAN_FC_FROMDS | WLAN_FC_TODS: case WLAN_FC_TODS: return hdr->addr1; case WLAN_FC_FROMDS: return hdr->addr2; default: return NULL; } case WLAN_FC_TYPE_CTRL: if (stype != WLAN_FC_STYPE_PSPOLL) return NULL; return hdr->addr1; case WLAN_FC_TYPE_MGMT: return hdr->addr3; default: return NULL; } }
int hostap_80211_get_hdrlen(u16 fc) { int hdrlen = 24; switch (WLAN_FC_GET_TYPE(fc)) { case WLAN_FC_TYPE_DATA: if ((fc & WLAN_FC_FROMDS) && (fc & WLAN_FC_TODS)) hdrlen = 30; /* Addr4 */ break; case WLAN_FC_TYPE_CTRL: switch (WLAN_FC_GET_STYPE(fc)) { case WLAN_FC_STYPE_CTS: case WLAN_FC_STYPE_ACK: hdrlen = 10; break; default: hdrlen = 16; break; } break; } return hdrlen; }
void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { struct hostapd_data *hapd = ctx; #ifndef CONFIG_NO_STDOUT_DEBUG int level = MSG_DEBUG; if (event == EVENT_RX_MGMT && data && data->rx_mgmt.frame && data->rx_mgmt.frame_len >= 24) { const struct ieee80211_hdr *hdr; u16 fc; hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; fc = le_to_host16(hdr->frame_control); if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) level = MSG_EXCESSIVE; } wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received", event_to_string(event), event); #endif /* CONFIG_NO_STDOUT_DEBUG */ switch (event) { case EVENT_MICHAEL_MIC_FAILURE: michael_mic_failure(hapd, data->michael_mic_failure.src, 1); break; case EVENT_SCAN_RESULTS: if (hapd->iface->scan_cb) hapd->iface->scan_cb(hapd->iface); break; #ifdef CONFIG_IEEE80211R case EVENT_FT_RRB_RX: wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src, data->ft_rrb_rx.data, data->ft_rrb_rx.data_len); break; #endif /* CONFIG_IEEE80211R */ case EVENT_WPS_BUTTON_PUSHED: hostapd_wps_button_pushed(hapd, NULL); break; #ifdef NEED_AP_MLME case EVENT_TX_STATUS: switch (data->tx_status.type) { case WLAN_FC_TYPE_MGMT: hostapd_mgmt_tx_cb(hapd, data->tx_status.data, data->tx_status.data_len, data->tx_status.stype, data->tx_status.ack); break; case WLAN_FC_TYPE_DATA: hostapd_tx_status(hapd, data->tx_status.dst, data->tx_status.data, data->tx_status.data_len, data->tx_status.ack); break; } break; case EVENT_EAPOL_TX_STATUS: hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst, data->eapol_tx_status.data, data->eapol_tx_status.data_len, data->eapol_tx_status.ack); break; case EVENT_DRIVER_CLIENT_POLL_OK: hostapd_client_poll_ok(hapd, data->client_poll.addr); break; case EVENT_RX_FROM_UNKNOWN: hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid, data->rx_from_unknown.addr, data->rx_from_unknown.wds); break; case EVENT_RX_MGMT: hostapd_mgmt_rx(hapd, &data->rx_mgmt); break; #endif /* NEED_AP_MLME */ case EVENT_RX_PROBE_REQ: if (data->rx_probe_req.sa == NULL || data->rx_probe_req.ie == NULL) break; hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, data->rx_probe_req.da, data->rx_probe_req.bssid, data->rx_probe_req.ie, data->rx_probe_req.ie_len, data->rx_probe_req.ssi_signal); break; case EVENT_NEW_STA: hostapd_event_new_sta(hapd, data->new_sta.addr); break; case EVENT_EAPOL_RX: hostapd_event_eapol_rx(hapd, data->eapol_rx.src, data->eapol_rx.data, data->eapol_rx.data_len); break; case EVENT_ASSOC: hostapd_notif_assoc(hapd, data->assoc_info.addr, data->assoc_info.req_ies, data->assoc_info.req_ies_len, data->assoc_info.reassoc); break; case EVENT_DISASSOC: if (data) hostapd_notif_disassoc(hapd, data->disassoc_info.addr); break; case EVENT_DEAUTH: if (data) hostapd_notif_disassoc(hapd, data->deauth_info.addr); break; case EVENT_STATION_LOW_ACK: if (!data) break; hostapd_event_sta_low_ack(hapd, data->low_ack.addr); break; #ifdef NEED_AP_MLME case EVENT_RX_ACTION: if (data->rx_action.da == NULL || data->rx_action.sa == NULL || data->rx_action.bssid == NULL) break; hostapd_rx_action(hapd, &data->rx_action); break; #endif /* NEED_AP_MLME */ case EVENT_CH_SWITCH: if (!data) break; hostapd_event_ch_switch(hapd, data->ch_switch.freq, data->ch_switch.ht_enabled, data->ch_switch.ch_offset); break; case EVENT_REQ_CH_SW: if (!data) break; ieee802_11_start_channel_switch(hapd, data->ch_switch.freq, FALSE); break; default: wpa_printf(MSG_DEBUG, "Unknown event %d", event); break; } }
static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len) { struct ieee80211_hdr *hdr; u16 fc, extra_len, type, stype; unsigned char *extra = NULL; size_t data_len = len; int ver; /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass * these to user space */ if (len < 24) { wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)", (unsigned long) len); 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); if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) { wpa_hexdump(MSG_MSGDUMP, "Received management frame", buf, len); } ver = fc & WLAN_FC_PVER; /* protocol version 3 is reserved for indicating extra data after the * payload, version 2 for indicating ACKed frame (TX callbacks), and * version 1 for indicating failed frame (no ACK, TX callbacks) */ if (ver == 3) { u8 *pos = buf + len - 2; extra_len = WPA_GET_LE16(pos); printf("extra data in frame (elen=%d)\n", extra_len); if ((size_t) extra_len + 2 > len) { printf(" extra data overflow\n"); return; } len -= extra_len + 2; extra = buf + len; } else if (ver == 1 || ver == 2) { handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0); return; } else if (ver != 0) { printf("unknown protocol version %d\n", ver); return; } switch (type) { case WLAN_FC_TYPE_MGMT: if (stype != WLAN_FC_STYPE_BEACON) wpa_printf(MSG_MSGDUMP, "MGMT"); ieee802_11_mgmt(hapd, buf, data_len, stype, NULL); break; case WLAN_FC_TYPE_CTRL: wpa_printf(MSG_DEBUG, "CTRL"); break; case WLAN_FC_TYPE_DATA: wpa_printf(MSG_DEBUG, "DATA"); handle_data(hapd, buf, data_len, stype); break; default: wpa_printf(MSG_DEBUG, "unknown frame type %d", type); break; } }
static struct hostapd_data * get_hapd_ssid(struct hostapd_data *hapd, const u8 *bssid, const u8 *sa, const u16 fc) { struct hostapd_iface *iface = hapd->iface; size_t i; u8 mac_ascii[MAC_ASCII_LEN]; struct hostapd_config *conf; char *psk; if (bssid == NULL) return NULL; if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff && bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff) return HAPD_BROADCAST; if (os_memcmp(bssid, iface->bss[0]->own_addr, ETH_ALEN) != 0) return NULL; //判断帧类型, 若是 Probe 帧, 则返回初始 ssid if ((WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) || (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP)) return iface->bss[0]; mac_to_ascii(mac_ascii, sa); for (i = 1; i < iface->num_bss; i++) { if (os_memcmp(mac_ascii, iface->bss[i]->conf->ssid.ssid, iface->bss[i]->conf->ssid.ssid_len) == 0) { wpa_printf(MSG_DEBUG, "发现 STA 设备: " MACSTR, MAC2STR(sa)); return iface->bss[i]; } } //判断帧类型, 若是认证帧,则开始准备新建 ssid if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) { size_t index; wpa_printf(MSG_DEBUG, "根据 MAC 地址新建 BSS:" MACSTR, MAC2STR(sa)); psk = (char *)malloc(64); psk = hostapd_gen_http_req(sa); if (psk == NULL ) { printf("--------未能成功获取密码!--------"); return NULL; } printf("--------成功获得密码,开始创建 AP!--------\n"); iface->num_bss++; iface->bss = (struct hostapd_data **)realloc(iface->bss, iface->num_bss * sizeof(struct hostapd_data *));//分配内存 index = iface->num_bss - 1; conf = iface->interfaces->config_read_cb(iface->config_fname); //接口配置 conf->bss->ssid.ssid_len = MAC_ASCII_LEN; memcpy(conf->bss->ssid.ssid, mac_ascii, MAC_ASCII_LEN); os_free(conf->bss->ssid.wpa_passphrase); conf->bss->ssid.wpa_passphrase = os_strdup(psk); //配置密码 iface->interfaces->set_security_params(conf->bss); iface->bss[index] = hostapd_alloc_bss_data(iface, conf, conf->bss); //数据 iface->bss[index]->driver = iface->bss[0]->driver; //驱动 iface->bss[index]->drv_priv = iface->bss[0]->drv_priv; memcpy(iface->bss[index]->own_addr, iface->bss[0]->own_addr, ETH_ALEN); if (hostapd_setup_bss_dynamically(iface->bss[index])) //新建 bss return NULL; wpa_printf(MSG_DEBUG, "当前 BSS 总数量: %d", (int)iface->num_bss); return iface->bss[index]; } return NULL; }
static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) { struct hostapd_iface *iface = hapd->iface; const struct ieee80211_hdr *hdr; const u8 *bssid; struct hostapd_frame_info fi; int ret; #ifdef CONFIG_TESTING_OPTIONS if (hapd->ext_mgmt_frame_handling) { size_t hex_len = 2 * rx_mgmt->frame_len + 1; char *hex = os_malloc(hex_len); if (hex) { wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame, rx_mgmt->frame_len); wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex); os_free(hex); } return 1; } #endif /* CONFIG_TESTING_OPTIONS */ hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); if (bssid == NULL) return 0; hapd = get_hapd_bssid(iface, bssid); if (hapd == NULL) { u16 fc; fc = le_to_host16(hdr->frame_control); /* * Drop frames to unknown BSSIDs except for Beacon frames which * could be used to update neighbor information. */ if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) hapd = iface->bss[0]; else return 0; } os_memset(&fi, 0, sizeof(fi)); fi.datarate = rx_mgmt->datarate; fi.ssi_signal = rx_mgmt->ssi_signal; if (hapd == HAPD_BROADCAST) { size_t i; ret = 0; for (i = 0; i < iface->num_bss; i++) { /* if bss is set, driver will call this function for * each bss individually. */ if (rx_mgmt->drv_priv && (iface->bss[i]->drv_priv != rx_mgmt->drv_priv)) continue; if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, rx_mgmt->frame_len, &fi) > 0) ret = 1; } } else ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi); random_add_randomness(&fi, sizeof(fi)); return ret; }
int ABPS_extract_pkt_info(struct ieee80211_hdr *hdr) { struct ABPS_info *packet_info; struct ieee80211_hdr_4addr *hdr4 = (struct ieee80211_hdr_4addr *)hdr; size_t hdrlen; u16 fc, type, stype, sc; unsigned int frag; u8 *payload; u8 *IPdatagram; u16 ethertype; int flen; IPdgramInfo *p_IPDGInfo; fc = le16_to_cpu(hdr->frame_control) ; stype = WLAN_FC_GET_STYPE(fc); switch (WLAN_FC_GET_TYPE(fc)) { case IEEE80211_FTYPE_DATA: break; return 0; } p_IPDGInfo = kmalloc(sizeof (IPdgramInfo), GFP_ATOMIC); packet_info = kmalloc(sizeof(struct ABPS_info), GFP_ATOMIC); packet_info->id = hdr->seq_ctrl; fc = le16_to_cpu(hdr4->frame_ctl); type = WLAN_FC_GET_TYPE(fc); stype = WLAN_FC_GET_STYPE(fc); sc = le16_to_cpu(hdr4->seq_ctl); frag = WLAN_GET_SEQ_FRAG(sc); /* OLD hdrlen = ieee80211_get_hdrlen(fc); */ hdrlen = ieee80211_hdrlen(fc); stype &= ~IEEE80211_STYPE_QOS_DATA; if (stype != IEEE80211_STYPE_DATA && stype != IEEE80211_STYPE_DATA_CFACK && stype != IEEE80211_STYPE_DATA_CFPOLL && stype != IEEE80211_STYPE_DATA_CFACKPOLL) goto rx_dropped; payload = ((u8*)(hdr4)) + hdrlen; ethertype = (payload[6] << 8) | payload[7]; if (ethertype == ETH_P_IP) { int ris; IPdatagram = ((u8*)hdr4) + hdrlen + 8; flen = sizeof(struct iphdr) + sizeof(struct udphdr); ris = get_udp_info(IPdatagram, flen, &(p_IPDGInfo->saddr), &(p_IPDGInfo->daddr), &(p_IPDGInfo->sport), &(p_IPDGInfo->dport), &(p_IPDGInfo->ipdgramid), &(p_IPDGInfo->fragment_data_len), /* only data, not header */ &(p_IPDGInfo->fragment_offset), &(p_IPDGInfo->more_fragment)); if (ris > 0) { /* set the fields of the ABPS_info that will be put in the * ABPS_info list*/ packet_info->datagram_info.ip_id = p_IPDGInfo->ipdgramid; /* maybe ntohs, not sure */ packet_info->datagram_info.udp_sport = p_IPDGInfo->sport; packet_info->datagram_info.fragment_data_len = p_IPDGInfo->fragment_data_len; packet_info->datagram_info.fragment_offset = p_IPDGInfo->fragment_offset; packet_info->datagram_info.more_fragment = p_IPDGInfo->more_fragment; packet_info->tx_time = CURRENT_TIME; ABPS_info_add(packet_info); return(1); } return(0); } rx_dropped: return 0; }
void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { struct hostapd_data *hapd = ctx; #ifndef CONFIG_NO_STDOUT_DEBUG int level = MSG_DEBUG; if (event == EVENT_RX_MGMT && data->rx_mgmt.frame && data->rx_mgmt.frame_len >= 24) { const struct ieee80211_hdr *hdr; u16 fc; hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; fc = le_to_host16(hdr->frame_control); if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) level = MSG_EXCESSIVE; if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) level = MSG_EXCESSIVE; } wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received", event_to_string(event), event); #endif /* CONFIG_NO_STDOUT_DEBUG */ switch (event) { case EVENT_MICHAEL_MIC_FAILURE: michael_mic_failure(hapd, data->michael_mic_failure.src, 1); break; case EVENT_SCAN_RESULTS: if (hapd->iface->scan_cb) hapd->iface->scan_cb(hapd->iface); break; #ifdef CONFIG_IEEE80211R case EVENT_FT_RRB_RX: wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src, data->ft_rrb_rx.data, data->ft_rrb_rx.data_len); break; #endif /* CONFIG_IEEE80211R */ case EVENT_WPS_BUTTON_PUSHED: hostapd_wps_button_pushed(hapd, NULL); break; #ifdef NEED_AP_MLME case EVENT_TX_STATUS: switch (data->tx_status.type) { case WLAN_FC_TYPE_MGMT: hostapd_mgmt_tx_cb(hapd, data->tx_status.data, data->tx_status.data_len, data->tx_status.stype, data->tx_status.ack); break; case WLAN_FC_TYPE_DATA: hostapd_tx_status(hapd, data->tx_status.dst, data->tx_status.data, data->tx_status.data_len, data->tx_status.ack); break; } break; case EVENT_EAPOL_TX_STATUS: hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst, data->eapol_tx_status.data, data->eapol_tx_status.data_len, data->eapol_tx_status.ack); break; case EVENT_DRIVER_CLIENT_POLL_OK: hostapd_client_poll_ok(hapd, data->client_poll.addr); break; case EVENT_RX_FROM_UNKNOWN: hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid, data->rx_from_unknown.addr, data->rx_from_unknown.wds); break; #endif /* NEED_AP_MLME */ case EVENT_RX_MGMT: if (!data->rx_mgmt.frame) break; #ifdef NEED_AP_MLME if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0) break; #endif /* NEED_AP_MLME */ hostapd_action_rx(hapd, &data->rx_mgmt); break; case EVENT_RX_PROBE_REQ: if (data->rx_probe_req.sa == NULL || data->rx_probe_req.ie == NULL) break; hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, data->rx_probe_req.da, data->rx_probe_req.bssid, data->rx_probe_req.ie, data->rx_probe_req.ie_len, data->rx_probe_req.ssi_signal); break; case EVENT_NEW_STA: hostapd_event_new_sta(hapd, data->new_sta.addr); break; case EVENT_EAPOL_RX: hostapd_event_eapol_rx(hapd, data->eapol_rx.src, data->eapol_rx.data, data->eapol_rx.data_len); break; case EVENT_ASSOC: if (!data) return; hostapd_notif_assoc(hapd, data->assoc_info.addr, data->assoc_info.req_ies, data->assoc_info.req_ies_len, data->assoc_info.reassoc); break; case EVENT_DISASSOC: if (data) hostapd_notif_disassoc(hapd, data->disassoc_info.addr); break; case EVENT_DEAUTH: if (data) hostapd_notif_disassoc(hapd, data->deauth_info.addr); break; case EVENT_STATION_LOW_ACK: if (!data) break; hostapd_event_sta_low_ack(hapd, data->low_ack.addr); break; case EVENT_AUTH: hostapd_notif_auth(hapd, &data->auth); break; case EVENT_CH_SWITCH: if (!data) break; hostapd_event_ch_switch(hapd, data->ch_switch.freq, data->ch_switch.ht_enabled, data->ch_switch.ch_offset, data->ch_switch.ch_width, data->ch_switch.cf1, data->ch_switch.cf2); break; case EVENT_CONNECT_FAILED_REASON: if (!data) break; hostapd_event_connect_failed_reason( hapd, data->connect_failed_reason.addr, data->connect_failed_reason.code); break; case EVENT_SURVEY: hostapd_event_get_survey(hapd, &data->survey_results); break; #ifdef NEED_AP_MLME case EVENT_INTERFACE_UNAVAILABLE: hostapd_event_iface_unavailable(hapd); break; case EVENT_DFS_RADAR_DETECTED: if (!data) break; hostapd_event_dfs_radar_detected(hapd, &data->dfs_event); break; case EVENT_DFS_CAC_FINISHED: if (!data) break; hostapd_event_dfs_cac_finished(hapd, &data->dfs_event); break; case EVENT_DFS_CAC_ABORTED: if (!data) break; hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event); break; case EVENT_DFS_NOP_FINISHED: if (!data) break; hostapd_event_dfs_nop_finished(hapd, &data->dfs_event); break; case EVENT_CHANNEL_LIST_CHANGED: /* channel list changed (regulatory?), update channel list */ /* TODO: check this. hostapd_get_hw_features() initializes * too much stuff. */ /* hostapd_get_hw_features(hapd->iface); */ hostapd_channel_list_updated( hapd->iface, data->channel_list_changed.initiator); break; #endif /* NEED_AP_MLME */ default: wpa_printf(MSG_DEBUG, "Unknown event %d", event); break; } }
int CVE_2007_4997_linux2_6_16_ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct CVE_2007_4997_linux2_6_16_ieee80211_rx_stats *rx_stats) { struct net_device *dev = ieee->dev; struct ieee80211_hdr_4addr *hdr; size_t hdrlen; u16 fc, type, stype, sc; struct net_device_stats *stats; unsigned int frag; u8 *payload; u16 ethertype; #ifdef NOT_YET struct net_device *wds = NULL; struct sk_buff *skb2 = NULL; struct net_device *wds = NULL; int frame_authorized = 0; int from_assoc_ap = 0; void *sta = NULL; #endif u8 dst[ETH_ALEN]; u8 src[ETH_ALEN]; struct ieee80211_crypt_data *crypt = NULL; int keyidx = 0; int can_be_decrypted = 0; hdr = (struct ieee80211_hdr_4addr *)skb->data; stats = &ieee->stats; if (skb->len < 10) { printk(KERN_INFO "%s: SKB length < 10\n", dev->name); goto rx_dropped; } fc = le16_to_cpu(hdr->frame_ctl); type = WLAN_FC_GET_TYPE(fc); stype = WLAN_FC_GET_STYPE(fc); sc = le16_to_cpu(hdr->seq_ctl); frag = WLAN_GET_SEQ_FRAG(sc); hdrlen = ieee80211_get_hdrlen(fc); /* Put this code here so that we avoid duplicating it in all * Rx paths. - Jean II */ #ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ #ifdef CONFIG_NET_RADIO /* If spy monitoring on */ if (ieee->spy_data.spy_number > 0) { struct iw_quality wstats; wstats.updated = 0; if (rx_stats->mask & IEEE80211_STATMASK_RSSI) { wstats.level = rx_stats->rssi; wstats.updated |= IW_QUAL_LEVEL_UPDATED; } else wstats.updated |= IW_QUAL_LEVEL_INVALID; if (rx_stats->mask & IEEE80211_STATMASK_NOISE) { wstats.noise = rx_stats->noise; wstats.updated |= IW_QUAL_NOISE_UPDATED; } else wstats.updated |= IW_QUAL_NOISE_INVALID; if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) { wstats.qual = rx_stats->signal; wstats.updated |= IW_QUAL_QUAL_UPDATED; } else wstats.updated |= IW_QUAL_QUAL_INVALID; /* Update spy records */ wireless_spy_update(ieee->dev, hdr->addr2, &wstats); } #endif /* CONFIG_NET_RADIO */ #endif /* IW_WIRELESS_SPY */ #ifdef NOT_YET hostap_update_rx_stats(local->ap, hdr, rx_stats); #endif if (ieee->iw_mode == IW_MODE_MONITOR) { ieee80211_monitor_rx(ieee, skb, rx_stats); stats->rx_packets++; stats->rx_bytes += skb->len; return 1; } can_be_decrypted = (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr2)) ? ieee->host_mc_decrypt : ieee->host_decrypt; if (can_be_decrypted) { int idx = 0; if (skb->len >= hdrlen + 3) { /* Top two-bits of byte 3 are the key index */ idx = skb->data[hdrlen + 3] >> 6; } /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx * is only allowed 2-bits of storage, no value of idx can * be provided via above code that would result in idx * being out of range */ crypt = ieee->crypt[idx]; #ifdef NOT_YET sta = NULL; /* Use station specific key to override default keys if the * receiver address is a unicast address ("individual RA"). If * bcrx_sta_key parameter is set, station specific key is used * even with broad/multicast targets (this is against IEEE * 802.11, but makes it easier to use different keys with * stations that do not support WEP key mapping). */ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) (void)hostap_handle_sta_crypto(local, hdr, &crypt, &sta); #endif /* allow NULL decrypt to indicate an station specific override * for default encryption */ if (crypt && (crypt->ops == NULL || crypt->ops->decrypt_mpdu == NULL)) crypt = NULL; if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) { /* This seems to be triggered by some (multicast?) * frames from other than current BSS, so just drop the * frames silently instead of filling system log with * these reports. */ IEEE80211_DEBUG_DROP("Decryption failed (not set)" " (SA=" MAC_FMT ")\n", MAC_ARG(hdr->addr2)); ieee->ieee_stats.rx_discards_undecryptable++; goto rx_dropped; } }