int wlan_frm_haswscie(const wbuf_t wbuf) { const u_int8_t *frm = ((u_int8_t *)wbuf_header(wbuf) + sizeof(struct ieee80211_frame)); const u_int8_t *efrm = ((u_int8_t *)wbuf_header(wbuf) + wbuf_get_pktlen(wbuf)); while (frm < efrm) { switch (*frm) { case IEEE80211_ELEMID_VENDOR: if (iswpsoui((u_int8_t *)frm)) return 1; break; default: break; } frm += frm[1] + 2; } return 0; }
void ath6kl_tgt_sony_get_scaninfo_event(struct ath6kl_vif *vif, u8 *datap, u32 len) { struct wmi_bss_info_hdr2 *bih; u8 *buf; struct ieee80211_channel *channel; struct ieee80211_mgmt *mgmt; //struct cfg80211_bss *bss; if (len <= sizeof(struct wmi_bss_info_hdr2)) return; bih = (struct wmi_bss_info_hdr2 *) datap; buf = datap + sizeof(struct wmi_bss_info_hdr2); len -= sizeof(struct wmi_bss_info_hdr2); printk( "bss info evt - ch %u, snr %d, rssi %d, bssid \"%pM\" " "frame_type=%d\n", bih->ch, bih->snr, bih->snr - 95, bih->bssid, bih->frame_type); if (bih->frame_type != BEACON_FTYPE && bih->frame_type != PROBERESP_FTYPE) return; /* Only update BSS table for now */ channel = ieee80211_get_channel(vif->wdev->wiphy, le16_to_cpu(bih->ch)); if (channel == NULL) return; if (len < 8 + 2 + 2) return; /* * In theory, use of cfg80211_inform_bss_ath6kl() would be more natural here * since we do not have the full frame. However, at least for now, * cfg80211 can only distinguish Beacon and Probe Response frames from * each other when using cfg80211_inform_bss_frame_ath6kl(), so let's build a * fake IEEE 802.11 header to be able to take benefit of this. */ mgmt = kmalloc(24 + len, GFP_ATOMIC); if (mgmt == NULL) return; if (bih->frame_type == BEACON_FTYPE) { mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); memset(mgmt->da, 0xff, ETH_ALEN); } else { struct net_device *dev = vif->net_dev; mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); memcpy(mgmt->da, dev->dev_addr, ETH_ALEN); } mgmt->duration = cpu_to_le16(0); memcpy(mgmt->sa, bih->bssid, ETH_ALEN); memcpy(mgmt->bssid, bih->bssid, ETH_ALEN); mgmt->seq_ctrl = cpu_to_le16(0); memcpy(&mgmt->u.beacon, buf, len); {//save to scan information database athcfg_wcmd_scan_result_t scan_entry; memset(&scan_entry,0x00,sizeof(athcfg_wcmd_scan_result_t)); scan_entry.isr_freq = bih->ch; scan_entry.isr_ieee = (unsigned char)ieee80211_frequency_to_channel_ath6kl(bih->ch); scan_entry.isr_rssi = (bih->snr < 0) ? 0 : bih->snr; memcpy(&scan_entry.isr_bssid[0],&bih->bssid[0],ATHCFG_WCMD_ADDR_LEN); scan_entry.isr_capinfo = le16_to_cpu(mgmt->u.beacon.capab_info); //parse ie information { struct ieee80211_ie_header *ie_element; unsigned char *temp_ptr; int remained_len; ie_element = (struct ieee80211_ie_header *)&(mgmt->u.beacon.variable); remained_len = len - 5*sizeof(u8); while(remained_len >= 0) { remained_len = remained_len - sizeof(struct ieee80211_ie_header)- ie_element->length; if (ie_element->length == 0) { ie_element += 1; /* next IE */ continue; } if (remained_len < ie_element->length) { /* Incomplete/bad info element */ //printk("EOF\n"); break; } temp_ptr = (unsigned char *)ie_element; temp_ptr = temp_ptr+sizeof(struct ieee80211_ie_header);//point to data area switch (ie_element->element_id) { case IEEE80211_ELEMID_SSID: memcpy(&scan_entry.isr_ssid,temp_ptr,ie_element->length); //printk("info_element->length=%d\n",ie_element->length); //printk("SSID=%s\n",scan_entry.isr_ssid); break; case IEEE80211_ELEMID_RATES: memcpy(&scan_entry.isr_rates[0],temp_ptr,ie_element->length); scan_entry.isr_nrates = ie_element->length; break; case IEEE80211_ELEMID_XRATES: memcpy(&scan_entry.isr_rates[scan_entry.isr_nrates],temp_ptr,ie_element->length); scan_entry.isr_nrates += ie_element->length; break; case IEEE80211_ELEMID_ERP: memcpy(&scan_entry.isr_erp,temp_ptr,ie_element->length); break; case IEEE80211_ELEMID_RSN: scan_entry.isr_rsn_ie.len = ie_element->length; memcpy(&scan_entry.isr_rsn_ie.data,temp_ptr,ie_element->length); break; case IEEE80211_ELEMID_HTCAP_ANA: if (scan_entry.isr_htcap_ie.len == 0) { scan_entry.isr_htcap_ie.len = ie_element->length; memcpy(&scan_entry.isr_htcap_ie.data[0],temp_ptr,ie_element->length); } break; case IEEE80211_ELEMID_HTINFO_ANA: /* we only care if there isn't already an HT IE (ANA) */ if (scan_entry.isr_htinfo_ie.len == 0) { scan_entry.isr_htinfo_ie.len = ie_element->length; memcpy(&scan_entry.isr_htinfo_ie.data[0],temp_ptr,ie_element->length); } break; case IEEE80211_ELEMID_HTCAP: /* we only care if there isn't already an HT IE (ANA) */ if (scan_entry.isr_htcap_ie.len == 0) { scan_entry.isr_htcap_ie.len = ie_element->length; memcpy(&scan_entry.isr_htcap_ie.data[0],temp_ptr,ie_element->length); } break; case IEEE80211_ELEMID_HTINFO: /* we only care if there isn't already an HT IE (ANA) */ if (scan_entry.isr_htinfo_ie.len == 0) { scan_entry.isr_htinfo_ie.len = ie_element->length; memcpy(&scan_entry.isr_htinfo_ie.data[0],temp_ptr,ie_element->length); } break; case IEEE80211_ELEMID_VENDOR: if (iswpaoui((u_int8_t *) ie_element)) { scan_entry.isr_wpa_ie.len = ie_element->length; memcpy(&scan_entry.isr_wpa_ie.data[0],temp_ptr,ie_element->length); } else if (iswpsoui((u_int8_t *) ie_element)) { scan_entry.isr_wps_ie.len = ie_element->length; memcpy(&scan_entry.isr_wps_ie.data[0],temp_ptr,ie_element->length); } else if (iswmeparam((u_int8_t *) ie_element)) { scan_entry.isr_wme_ie.len = ie_element->length; memcpy(&scan_entry.isr_wme_ie.data[0],temp_ptr,ie_element->length); } else if (isatherosoui((u_int8_t *) ie_element)) { scan_entry.isr_ath_ie.len = ie_element->length; memcpy(&scan_entry.isr_ath_ie.data[0],temp_ptr,ie_element->length); } else if (ishtcap((u_int8_t *) ie_element)) { if (scan_entry.isr_htcap_ie.len == 0) { scan_entry.isr_htcap_ie.len = ie_element->length; memcpy(&scan_entry.isr_htcap_ie.data[0],temp_ptr,ie_element->length); } } else if (ishtinfo((u_int8_t *) ie_element)) { if (scan_entry.isr_htinfo_ie.len == 0) { scan_entry.isr_htinfo_ie.len = ie_element->length; memcpy(&scan_entry.isr_htinfo_ie.data[0],temp_ptr,ie_element->length); } } else { //printk("Unknow know !!info_element->length=%d\n",ie_element->length); } break; default: //printk("Unknow know info_element->length=%d\n",ie_element->length); break; } ie_element = (struct ieee80211_ie_header *)(temp_ptr + ie_element->length); } } //find the exist entry or add new one { int i,entry_match_item; bool entry_match = 0; if(total_bss_info >= 100) { printk("Excess max entry 100\n"); kfree(mgmt); return; } for(i=0;i<total_bss_info;i++) { if(scaninfor_db[i].isr_freq == scan_entry.isr_freq) { if(memcmp(scaninfor_db[i].isr_bssid ,scan_entry.isr_bssid,ATHCFG_WCMD_ADDR_LEN) == 0) { //find it if(strcmp(scaninfor_db[i].isr_ssid ,scan_entry.isr_ssid) == 0) { //update it entry_match = 1; entry_match_item = i; //printk("fully match!! i=%d,update it,total_bss_info=%d\n",i,total_bss_info); memcpy(&scaninfor_db[i],&scan_entry,sizeof(athcfg_wcmd_scan_result_t)); break; } } } } if(entry_match == 0) { memcpy(&scaninfor_db[total_bss_info],&scan_entry,sizeof(athcfg_wcmd_scan_result_t)); #if 0 printk("[%d]Freq=%d\n",total_bss_info,scaninfor_db[total_bss_info].isr_freq); printk("[%d]CH=%d\n",total_bss_info,scaninfor_db[total_bss_info].isr_ieee); printk("[%d]RSSI=%d\n",total_bss_info,scaninfor_db[total_bss_info].isr_rssi); printk("[%d]BSSID=%pM\n",total_bss_info,scaninfor_db[total_bss_info].isr_bssid); printk("[%d]SSID=%s\n",total_bss_info,scaninfor_db[total_bss_info].isr_ssid); printk("[%d]isr_htinfo_ie.len=%d\n",total_bss_info,scaninfor_db[total_bss_info].isr_htinfo_ie.len); #endif total_bss_info++; //printk(" next entry=%d\n",total_bss_info); } else { #if 0 printk("[%d]Freq=%d\n",entry_match_item,scaninfor_db[entry_match_item].isr_freq); printk("[%d]CH=%d\n",entry_match_item,scaninfor_db[entry_match_item].isr_ieee); printk("[%d]RSSI=%d\n",entry_match_item,scaninfor_db[entry_match_item].isr_rssi); printk("[%d]BSSID=%pM\n",entry_match_item,scaninfor_db[entry_match_item].isr_bssid); printk("[%d]SSID=%s\n",entry_match_item,scaninfor_db[entry_match_item].isr_ssid); printk("[%d]isr_htinfo_ie.len=%d\n",entry_match_item,scaninfor_db[entry_match_item].isr_htinfo_ie.len); #endif } } } kfree(mgmt); ///total_bss_info++; return; }