示例#1
0
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;
}