static void printies(const u_int8_t *vp, int ielen, int maxcols) { while (ielen > 0) { switch (vp[0]) { case IEEE80211_ELEMID_VENDOR: if (iswpaoui(vp)) printie(" WPA", vp, 2 + vp[1], maxcols); else if (iswmeoui(vp)) printie(" WME", vp, 2 + vp[1], maxcols); else if (isatherosoui(vp)) printie(" ATH", vp, 2 + vp[1], maxcols); else printie(" VEN", vp, 2 + vp[1], maxcols); break; case IEEE80211_ELEMID_RSN: printie(" RSN", vp, 2 + vp[1], maxcols); break; default: printie(" ???", vp, 2 + vp[1], maxcols); break; } ielen -= 2 + vp[1]; vp += 2 + vp[1]; } }
static void getIEs(const u_int8_t *vp, int ielen, int maxcols, u_int8_t *str_out) { char *ptr = (char *)str_out; int iTemp = 0; while (ielen > 0 && iTemp < maxcols) { switch (vp[0]) { case IEEE80211_ELEMID_VENDOR: if (iswpaoui(vp)) sprintf(ptr, " WPA"); else if (iswmeoui(vp)) sprintf(ptr, " WME"); else if (isatherosoui(vp)) sprintf(ptr, " ATH"); else sprintf(ptr, " VEN"); ptr += 4 ; iTemp++; break; case IEEE80211_ELEMID_RSN: sprintf(ptr, " RSN"); ptr += 4; iTemp++; break; default: //sprintf(str_out, " ???"); break; } ielen -= 2+vp[1]; vp += 2+vp[1]; } *ptr = '\0'; }
A_STATUS wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie, A_UINT8 phy_mode) /* Bug 82893 */ { A_UINT8 *frm, *efrm; A_UINT8 elemid_ssid = FALSE; frm = buf; efrm = (A_UINT8 *) (frm + framelen); /* * beacon/probe response frame format * [8] time stamp * [2] beacon interval * [2] capability information * [tlv] ssid * [tlv] supported rates * [tlv] country information * [tlv] parameter set (FH/DS) * [tlv] erp information * [tlv] extended supported rates * [tlv] WMM * [tlv] WPA or RSN * [tlv] Atheros Advanced Capabilities */ IEEE80211_VERIFY_LENGTH(efrm - frm, 12); A_MEMZERO(cie, sizeof(*cie)); cie->ie_tstamp = frm; frm += 8; cie->ie_beaconInt = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2; cie->ie_capInfo = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2; cie->ie_chan = 0; while (frm < efrm) { switch (*frm) { case IEEE80211_ELEMID_SSID: if (!elemid_ssid) { cie->ie_ssid = frm; elemid_ssid = TRUE; } break; case IEEE80211_ELEMID_RATES: cie->ie_rates = frm; if (A_OK != check_phy_rates(cie->ie_rates, phy_mode)) /* Fix Bug 82893 */ return A_EINVAL; break; case IEEE80211_ELEMID_COUNTRY: cie->ie_country = frm; break; case IEEE80211_ELEMID_FHPARMS: break; case IEEE80211_ELEMID_DSPARMS: cie->ie_chan = frm[2]; break; case IEEE80211_ELEMID_TIM: cie->ie_tim = frm; break; case IEEE80211_ELEMID_IBSSPARMS: break; case IEEE80211_ELEMID_XRATES: cie->ie_xrates = frm; if (A_OK != check_phy_rates(cie->ie_xrates, phy_mode)) /* Fix Bug 82893 */ return A_EINVAL; break; case IEEE80211_ELEMID_ERP: if (frm[1] != 1) { //A_PRINTF("Discarding ERP Element - Bad Len\n"); return A_EINVAL; } cie->ie_erp = frm[2]; break; case IEEE80211_ELEMID_RSN: cie->ie_rsn = frm; break; #ifdef WAPI_ENABLE case IEEE80211_ELEMID_WAPI: cie->ie_wapi = frm; break; #endif /* WAPI_ENABLE */ case IEEE80211_ELEMID_VENDOR: if (iswpaoui(frm)) { cie->ie_wpa = frm; } else if (iswmmoui(frm)) { cie->ie_wmm = frm; } else if (isatherosoui(frm)) { cie->ie_ath = frm; } else if(iswscoui(frm)) { cie->ie_wsc = frm; } break; default: break; } frm += frm[1] + 2; } IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE); IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN); return A_OK; }
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; }