rv1126-external/wifiAutoSetup/easy_setup/scan.c

254 lines
6.1 KiB
C

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "easy_setup.h"
#define ETHER_ADDR_LEN 6
#define DOT11_BSSTYPE_ANY 2
#define htod32(n) (n)
#define dtoh32(n) (n)
#define dtoh16(n) (n)
#define WLC_SCAN 50
#define WLC_SCAN_RESULTS 51
typedef struct wlc_ssid {
uint32 SSID_len;
uint8 SSID[32];
} wlc_ssid_t;
struct ether_addr {
uint8 octet[ETHER_ADDR_LEN];
};
typedef struct wl_scan_params {
wlc_ssid_t ssid;
struct ether_addr bssid;
int8 bss_type;
uint8 scan_type;
int32 nprobes;
int32 active_time;
int32 passive_time;
int32 home_time;
int32 channel_num;
uint16 channel_list[1];
} wl_scan_params_t;
typedef struct wl_bss_info_107 {
uint32 version;
uint32 length;
struct ether_addr BSSID;
uint16 beacon_period;
uint16 capability;
uint8 SSID_len;
uint8 SSID[32];
struct {
uint count;
uint8 rates[16];
} rateset;
uint8 channel;
uint16 atim_window;
uint8 dtim_period;
int16 RSSI;
int8 phy_noise;
uint32 ie_length;
} wl_bss_info_107_t;
typedef struct wl_bss_info {
uint32 version;
uint32 length;
struct ether_addr BSSID;
uint16 beacon_period;
uint16 capability;
uint8 SSID_len;
uint8 SSID[32];
struct {
uint count;
uint8 rates[16];
} rateset;
uint16 chanspec;
uint16 atim_window;
uint8 dtim_period;
int16 RSSI;
int8 phy_noise;
uint8 n_cap;
uint32 nbss_cap;
uint8 ctl_ch;
uint8 padding1[3];
uint16 vht_rxmcsmap;
uint16 vht_txmcsmap;
uint8 flags;
uint8 vht_cap;
uint8 reserved[2];
uint8 basic_mcs[16];
uint16 ie_offset;
uint32 ie_length;
int16 SNR;
} wl_bss_info_t;
typedef struct wl_scan_results {
uint32 buflen;
uint32 version;
uint32 count;
wl_bss_info_t bss_info[1];
} wl_scan_results_t;
static int scan_and_get_security_internal(int ch, uint8* bssid, ssid_t* ssid) {
int sec = -1;
int ret = 0;
wl_scan_params_t p;
memset(&p, 0, sizeof(p));
p.bss_type = DOT11_BSSTYPE_ANY;
p.scan_type = 0;
p.nprobes = -1;
p.active_time = 100;
p.passive_time = -1;
p.home_time = -1;
p.channel_num = 0;
if (ch > 0) {
p.channel_num = 1;
p.channel_list[0] = ch;
}
if (bssid) {
memcpy(&p.bssid, bssid, ETHER_ADDR_LEN);
} else {
uint8 mcast[ETHER_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
memcpy(&p.bssid, mcast, sizeof(mcast));
}
if (ssid) {
p.ssid.SSID_len = ssid->len;
memcpy(p.ssid.SSID, ssid->val, sizeof(ssid->val));
}
p.nprobes = htod32(p.nprobes);
p.active_time = htod32(p.active_time);
p.passive_time = htod32(p.passive_time);
p.home_time = htod32(p.home_time);
if ((ret = easy_setup_ioctl(WLC_SCAN, 1, &p, sizeof(p))) < 0) {
return -1;
}
int size = 1024;
uint8* ptr = malloc(size);
wl_scan_results_t* r;
r = (wl_scan_results_t*) ptr;
int tries = 20;
int delay_ms = 150;
while (tries--) {
memset(ptr, 0, size);
r->buflen = size;
ret = easy_setup_ioctl(WLC_SCAN_RESULTS, 0, r, size);
if (!ret && r->count) break;
//LOGD("sleep %dms\n", delay_ms);
usleep(delay_ms*1000);
}
if (!ret && r->count) {
int i=0;
wl_bss_info_t* bi = r->bss_info;
if (dtoh32(bi->version) == 107) {
wl_bss_info_107_t *old = (wl_bss_info_107_t *)bi;
bi->ie_length = old->ie_length;
bi->ie_offset = sizeof(wl_bss_info_107_t);
}
uint16 cap = dtoh16(bi->capability);
int totlen = dtoh32(bi->ie_length);
int wpa = 0;
if (totlen) {
uint8* ie = (uint8 *)(((uint8 *)bi) + dtoh16(bi->ie_offset));
while (totlen>=2) {
int type = ie[0];
int len = ie[1];
if (type == 221 && len >= 4) {
int v = (ie[2]<<24) | (ie[3]<<16) | (ie[4]<<8) | (ie[5]);
if (v == 0x0050f201) {
sec = WLAN_SECURITY_WPA;
break;
}
}
if (type == 48) {
uint8* pos = ie+2;
int left = len;
/* version */
pos += 2;
left -= 2;
/* group cipher suite */
pos += 4;
left -= 4;
/* pairwise cipher suite */
uint16 count = *((uint16*) pos);
printf("pairwise cipher count=%d\n", count);
pos += 2;
left -= 2;
while (count--) {
pos += 4;
left -= 4;
}
/* key mgmt */
count = *((uint16*) pos);
printf("key mgmt count=%d\n", count);
pos += 2;
left -= 2;
while (count--) {
if (pos[3] == 1) {
sec = WLAN_SECURITY_WPA2_8021X;
} else {
sec = WLAN_SECURITY_WPA2;
}
pos += 4;
left -= 4;
}
break;
}
totlen -= (len+2);
ie += (len+2);
}
}
if (sec == -1) {
if (cap & 0x10) {
sec = WLAN_SECURITY_WEP;
} else {
sec = WLAN_SECURITY_NONE;
}
}
} else {
LOGD("scan gets no result(ret: %d, count: %d).\n", ret, (!ret)?r->count:0);
sec = -1;
}
free(ptr);
return sec;
}
int scan_and_get_security(ssid_t* ssid) {
return scan_and_get_security_internal(-1, NULL, ssid);
}