不飞则已,一飞冲天;不鸣则已,一鸣惊人。这篇文章主要讲述Android wifi 扫描流程 分析相关的知识,希望能为你提供帮助。
void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
{
int res;
if (wpa_s->
p2p_mgmt) {
wpa_dbg(wpa_s, MSG_DEBUG,
"
Ignore scan request (%d.%06d sec) on p2p_mgmt interface"
,
sec, usec);
return;
}res = eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s,
NULL);
if (res == 1) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Rescheduling scan request: %d.%06d sec"
,
sec, usec);
} else if (res == 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Ignore new scan request for %d.%06d sec since an earlier request is scheduled to trigger sooner"
,
sec, usec);
} else {
wpa_dbg(wpa_s, MSG_DEBUG, "
Setting scan request: %d.%06d sec"
,
sec, usec);
eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
}
}static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
struct wpa_ssid *ssid;
int ret, p2p_in_prog;
struct wpabuf *extra_ie = NULL;
struct wpa_driver_scan_params params;
struct wpa_driver_scan_params *scan_params;
size_t max_ssids;
int connect_without_scan = 0;
wpa_s->
ignore_post_flush_scan_res = 0;
// 接口未使能
if (wpa_s->
wpa_state == WPA_INTERFACE_DISABLED) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Skip scan - interface disabled"
);
return;
}if (wpa_s->
disconnected &
&
wpa_s->
scan_req == NORMAL_SCAN_REQ) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Disconnected - do not scan"
);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
return;
}
// 如果正在扫描, 推迟本次扫描
if (wpa_s->
scanning) {
/*
* If we are already in scanning state, we shall reschedule the
* the incoming scan request.
*/
wpa_dbg(wpa_s, MSG_DEBUG, "
Already scanning - Reschedule the incoming scan req"
);
wpa_supplicant_req_scan(wpa_s, 1, 0);
return;
}
// 查看是否有使能的ssid
if (!wpa_supplicant_enabled_networks(wpa_s) &
&
wpa_s->
scan_req == NORMAL_SCAN_REQ) {
wpa_dbg(wpa_s, MSG_DEBUG, "
No enabled networks - do not scan"
);
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
return;
}if (wpa_s->
conf->
ap_scan != 0 &
&
(wpa_s->
drv_flags &
WPA_DRIVER_FLAGS_WIRED)) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Using wired authentication - "
"
overriding ap_scan configuration"
);
wpa_s->
conf->
ap_scan = 0;
wpas_notify_ap_scan_changed(wpa_s);
}if (wpa_s->
conf->
ap_scan == 0) {
wpa_supplicant_gen_assoc_event(wpa_s);
return;
}ssid = NULL;
if (wpa_s->
scan_req != MANUAL_SCAN_REQ &
&
wpa_s->
connect_without_scan) {
connect_without_scan = 1;
for (ssid = wpa_s->
conf->
ssid;
ssid;
ssid = ssid->
next) {
if (ssid == wpa_s->
connect_without_scan)
break;
}
}p2p_in_prog = wpas_p2p_in_progress(wpa_s);
if (p2p_in_prog &
&
p2p_in_prog != 2 &
&
(!ssid ||
(ssid->
mode != WPAS_MODE_AP &
&
ssid->
mode != WPAS_MODE_P2P_GO))) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Delay station mode scan while P2P operation is in progress"
);
wpa_supplicant_req_scan(wpa_s, 5, 0);
return;
}/*
* Don'
t cancel the scan based on ongoing PNO;
defer it. Some scans are
* used for changing modes inside wpa_supplicant (roaming,
* auto-reconnect, etc). Discarding the scan might hurt these processes.
* The normal use case for PNO is to suspend the host immediately after
* starting PNO, so the periodic 100 ms attempts to run the scan do not
* normally happen in practice multiple times, i.e., this is simply
* restarting scanning once the host is woken up and PNO stopped.
*/
if (wpa_s->
pno || wpa_s->
pno_sched_pending) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Defer scan - PNO is in progress"
);
wpa_supplicant_req_scan(wpa_s, 0, 100000);
return;
}if (wpa_s->
conf->
ap_scan == 2)
max_ssids = 1;
else {
max_ssids = wpa_s->
max_scan_ssids;
if (max_ssids >
WPAS_MAX_SCAN_SSIDS)
max_ssids = WPAS_MAX_SCAN_SSIDS;
}wpa_s->
last_scan_req = wpa_s->
scan_req;
wpa_s->
scan_req = NORMAL_SCAN_REQ;
// 如果设置了connect_without_scan, 连接之前选择的网络,不进行扫描,直接关联
if (connect_without_scan) {
wpa_s->
connect_without_scan = NULL;
if (ssid) {
wpa_printf(MSG_DEBUG, "
Start a pre-selected network "
"
without scan step"
);
wpa_supplicant_associate(wpa_s, NULL, ssid);
return;
}
}os_memset(&
params, 0, sizeof(params));
// 设置状态为扫描
wpa_s->
scan_prev_wpa_state = wpa_s->
wpa_state;
if (wpa_s->
wpa_state == WPA_DISCONNECTED ||
wpa_s->
wpa_state == WPA_INACTIVE)
wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
/*
* If autoscan has set its own scanning parameters
*/
if (wpa_s->
autoscan_params != NULL) {
scan_params = wpa_s->
autoscan_params;
goto scan;
}if (wpa_s->
last_scan_req == MANUAL_SCAN_REQ &
&
wpa_set_ssids_from_scan_req(wpa_s, &
params, max_ssids)) {
wpa_printf(MSG_DEBUG, "
Use specific SSIDs from SCAN command"
);
goto ssid_list_set;
}....../* Find the starting point from which to continue scanning */
// 查找开始扫描的ssid
ssid = wpa_s->
conf->
ssid;
// 从这里看,应该是链表里面下一个ssid
if (wpa_s->
prev_scan_ssid != WILDCARD_SSID_SCAN) {
while (ssid) {
if (ssid == wpa_s->
prev_scan_ssid) {
ssid = ssid->
next;
break;
}
ssid = ssid->
next;
}
}if (wpa_s->
last_scan_req != MANUAL_SCAN_REQ &
&
#ifdef CONFIG_AP
!wpa_s->
ap_iface &
&
#endif /* CONFIG_AP */
wpa_s->
conf->
ap_scan == 2) {
wpa_s->
connect_without_scan = NULL;
wpa_s->
prev_scan_wildcard = 0;
wpa_supplicant_assoc_try(wpa_s, ssid);
return;
} else if (wpa_s->
conf->
ap_scan == 2) {
/*
* User-initiated scan request in ap_scan == 2;
scan with
* wildcard SSID.
*/
ssid = NULL;
} else if (wpa_s->
reattach &
&
wpa_s->
current_ssid != NULL) {
// 实行单信道,单个ssid扫描。难道是漫游的操作?
// reassoicate重关联
/*
* Perform single-channel single-SSID scan for
* reassociate-to-same-BSS operation.
*/
/* Setup SSID */
ssid = wpa_s->
current_ssid;
wpa_hexdump_ascii(MSG_DEBUG, "
Scan SSID"
,
ssid->
ssid, ssid->
ssid_len);
params.ssids[0].ssid = ssid->
ssid;
params.ssids[0].ssid_len = ssid->
ssid_len;
params.num_ssids = 1;
/*
* Allocate memory for frequency array, allocate one extra
* slot for the zero-terminator.
*/
params.freqs = os_malloc(sizeof(int) * 2);
if (params.freqs) {
params.freqs[0] = wpa_s->
assoc_freq;
params.freqs[1] = 0;
}/*
* Reset the reattach flag so that we fall back to full scan if
* this scan fails.
*/
wpa_s->
reattach = 0;
} else {
struct wpa_ssid *start = ssid, *tssid;
int freqs_set = 0;
if (ssid == NULL &
&
max_ssids >
1)
ssid = wpa_s->
conf->
ssid;
// 获取配置文件中的ssid
while (ssid) {
if (!wpas_network_disabled(wpa_s, ssid) &
&
ssid->
scan_ssid) {
wpa_hexdump_ascii(MSG_DEBUG, "
Scan SSID"
,
ssid->
ssid, ssid->
ssid_len);
params.ssids[params.num_ssids].ssid =
ssid->
ssid;
params.ssids[params.num_ssids].ssid_len =
ssid->
ssid_len;
params.num_ssids++;
// 达到所能支持的最大ssid个数,退出循环
if (params.num_ssids + 1 >
= max_ssids)
break;
}
ssid = ssid->
next;
if (ssid == start)
break;
if (ssid == NULL &
&
max_ssids >
1 &
&
start != wpa_s->
conf->
ssid)
ssid = wpa_s->
conf->
ssid;
}if (wpa_s->
scan_id_count &
&
wpa_s->
last_scan_req == MANUAL_SCAN_REQ)
wpa_set_scan_ssids(wpa_s, &
params, max_ssids);
for (tssid = wpa_s->
conf->
ssid;
wpa_s->
last_scan_req != MANUAL_SCAN_REQ &
&
tssid;
tssid = tssid->
next) {
// 网络关闭,不进行扫描
if (wpas_network_disabled(wpa_s, tssid))
continue;
if ((params.freqs || !freqs_set) &
&
tssid->
scan_freq) {
int_array_concat(&
params.freqs,
tssid->
scan_freq);
} else {
os_free(params.freqs);
params.freqs = NULL;
}
freqs_set = 1;
}
// 对频率进行排序
int_array_sort_unique(params.freqs);
}if (ssid &
&
max_ssids == 1) {
/*
* If the driver is limited to 1 SSID at a time interleave
* wildcard SSID scans with specific SSID scans to avoid
* waiting a long time for a wildcard scan.
*/
if (!wpa_s->
prev_scan_wildcard) {
params.ssids[0].ssid = NULL;
params.ssids[0].ssid_len = 0;
wpa_s->
prev_scan_wildcard = 1;
wpa_dbg(wpa_s, MSG_DEBUG, "
Starting AP scan for "
"
wildcard SSID (Interleave with specific)"
);
} else {
wpa_s->
prev_scan_ssid = ssid;
wpa_s->
prev_scan_wildcard = 0;
wpa_dbg(wpa_s, MSG_DEBUG,
"
Starting AP scan for specific SSID: %s"
,
wpa_ssid_txt(ssid->
ssid, ssid->
ssid_len));
}
} else if (ssid) {
/* max_ssids >
1 */wpa_s->
prev_scan_ssid = ssid;
wpa_dbg(wpa_s, MSG_DEBUG, "
Include wildcard SSID in "
"
the scan request"
);
params.num_ssids++;
} else if (wpa_s->
last_scan_req == MANUAL_SCAN_REQ &
&
wpa_s->
manual_scan_passive &
&
params.num_ssids == 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Use passive scan based on manual request"
);
} else if (wpa_s->
conf->
passive_scan) {
wpa_dbg(wpa_s, MSG_DEBUG,
"
Use passive scan based on configuration"
);
} else {
wpa_s->
prev_scan_ssid = WILDCARD_SSID_SCAN;
params.num_ssids++;
wpa_dbg(wpa_s, MSG_DEBUG, "
Starting AP scan for wildcard "
"
SSID"
);
}ssid_list_set:
wpa_supplicant_optimize_freqs(wpa_s, &
params);
extra_ie = wpa_supplicant_extra_ies(wpa_s);
// 手动发起的扫描
if (wpa_s->
last_scan_req == MANUAL_SCAN_REQ &
&
wpa_s->
manual_scan_only_new) {
wpa_printf(MSG_DEBUG,
"
Request driver to clear scan cache due to manual only_new=1 scan"
);
params.only_new_results = 1;
}if (wpa_s->
last_scan_req == MANUAL_SCAN_REQ &
&
params.freqs == NULL &
&
wpa_s->
manual_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Limit manual scan to specified channels"
);
params.freqs = wpa_s->
manual_scan_freqs;
wpa_s->
manual_scan_freqs = NULL;
}if (params.freqs == NULL &
&
wpa_s->
select_network_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG,
"
Limit select_network scan to specified channels"
);
params.freqs = wpa_s->
select_network_scan_freqs;
wpa_s->
select_network_scan_freqs = NULL;
}
// 参数里面的频率为空
// 优化扫描,基于的频率列表
if (params.freqs == NULL &
&
wpa_s->
next_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Optimize scan based on previously "
"
generated frequency list"
);
params.freqs = wpa_s->
next_scan_freqs;
} else
os_free(wpa_s->
next_scan_freqs);
wpa_s->
next_scan_freqs = NULL;
wpa_setband_scan_freqs(wpa_s, &
params);
/* See if user specified frequencies. If so, scan only those. */
if (wpa_s->
conf->
freq_list &
&
!params.freqs) {
wpa_dbg(wpa_s, MSG_DEBUG,
"
Optimize scan based on conf->
freq_list"
);
int_array_concat(&
params.freqs, wpa_s->
conf->
freq_list);
}/* Use current associated channel? */
// 是否只扫描当前信道
if (wpa_s->
conf->
scan_cur_freq &
&
!params.freqs) {
unsigned int num = wpa_s->
num_multichan_concurrent;
params.freqs = os_calloc(num + 1, sizeof(int));
if (params.freqs) {
num = get_shared_radio_freqs(wpa_s, params.freqs, num);
if (num >
0) {
wpa_dbg(wpa_s, MSG_DEBUG, "
Scan only the "
"
current operating channels since "
"
scan_cur_freq is enabled"
);
} else {
os_free(params.freqs);
params.freqs = NULL;
}
}
}params.filter_ssids = wpa_supplicant_build_filter_ssids(
wpa_s->
conf, &
params.num_filter_ssids);
if (extra_ie) {
params.extra_ies = wpabuf_head(extra_ie);
params.extra_ies_len = wpabuf_len(extra_ie);
}...if ((wpa_s->
mac_addr_rand_enable &
MAC_ADDR_RAND_SCAN) &
&
wpa_s->
wpa_state <
= WPA_SCANNING) {
params.mac_addr_rand = 1;
if (wpa_s->
mac_addr_scan) {
params.mac_addr = wpa_s->
mac_addr_scan;
params.mac_addr_mask = wpa_s->
mac_addr_scan + ETH_ALEN;
}
}if (!is_zero_ether_addr(wpa_s->
next_scan_bssid)) {
struct wpa_bss *bss;
params.bssid = wpa_s->
next_scan_bssid;
bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid);
if (bss &
&
bss->
ssid_len &
&
params.num_ssids == 1 &
&
params.ssids[0].ssid_len == 0) {
params.ssids[0].ssid = bss->
ssid;
params.ssids[0].ssid_len = bss->
ssid_len;
wpa_dbg(wpa_s, MSG_DEBUG,
"
Scan a previously specified BSSID "
MACSTR
"
and SSID %s"
,
MAC2STR(params.bssid),
wpa_ssid_txt(bss->
ssid, bss->
ssid_len));
} else {
wpa_dbg(wpa_s, MSG_DEBUG,
"
Scan a previously specified BSSID "
MACSTR,
MAC2STR(params.bssid));
}
}scan_params = &
params;
scan:
...
ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
if (ret &
&
wpa_s->
last_scan_req == MANUAL_SCAN_REQ &
&
params.freqs &
&
!wpa_s->
manual_scan_freqs) {
/* Restore manual_scan_freqs for the next attempt */
wpa_s->
manual_scan_freqs = params.freqs;
params.freqs = NULL;
}wpabuf_free(extra_ie);
os_free(params.freqs);
os_free(params.filter_ssids);
if (ret) {
wpa_msg(wpa_s, MSG_WARNING, "
Failed to initiate AP scan"
);
if (wpa_s->
scan_prev_wpa_state != wpa_s->
wpa_state)
wpa_supplicant_set_state(wpa_s,
wpa_s->
scan_prev_wpa_state);
/* Restore scan_req since we will try to scan again */
wpa_s->
scan_req = wpa_s->
last_scan_req;
wpa_supplicant_req_scan(wpa_s, 1, 0);
} else {
wpa_s->
scan_for_connection = 0;
#ifdef CONFIG_INTERWORKING
wpa_s->
interworking_fast_assoc_tried = 0;
#endif /* CONFIG_INTERWORKING */
if (params.bssid)
os_memset(wpa_s->
next_scan_bssid, 0, ETH_ALEN);
}
}wpa_supplicant_trigger_scan
-->
wpas_trigger_scan_cb
-->
wpa_drv_scan(wpa_s, params);
-->
wpa_s->
driver->
scan2(wpa_s->
drv_priv, params);
externalwpa_supplicant_8srcdriversdriver_nl80211.c
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "
nl80211"
,
.desc = "
Linux nl80211/cfg80211"
,
.get_bssid = wpa_driver_nl80211_get_bssid,
.get_ssid = wpa_driver_nl80211_get_ssid,
.set_key = driver_nl80211_set_key,
.scan2 = driver_nl80211_scan2,
...
}static int driver_nl80211_scan2(void *priv,
struct wpa_driver_scan_params *params)
{
struct i802_bss *bss = priv;
#ifdef CONFIG_DRIVER_NL80211_QCA
struct wpa_driver_nl80211_data *drv = bss->
drv;
/*
* Do a vendor specific scan if possible. If only_new_results is
* set, do a normal scan since a kernel (cfg80211) BSS cache flush
* cannot be achieved through a vendor scan. The below condition may
* need to be modified if new scan flags are added in the future whose
* functionality can only be achieved through a normal scan.
*/
if (drv->
scan_vendor_cmd_avail &
&
!params->
only_new_results)
return wpa_driver_nl80211_vendor_scan(bss, params);
#endif /* CONFIG_DRIVER_NL80211_QCA */
return wpa_driver_nl80211_scan(bss, params);
}externalwpa_supplicant_8hostapdsrcdriversdriver_nl80211_scan.c
int wpa_driver_nl80211_scan(struct i802_bss *bss,
struct wpa_driver_scan_params *params)
{
struct wpa_driver_nl80211_data *drv = bss->
drv;
int ret = -1, timeout;
struct nl_msg *msg = NULL;
wpa_dbg(drv->
ctx, MSG_DEBUG, "
nl80211: scan request"
);
drv->
scan_for_auth = 0;
if (TEST_FAIL())
return -1;
msg = nl80211_scan_common(bss, NL80211_CMD_TRIGGER_SCAN, params);
if (!msg)
return -1;
if (params->
p2p_probe) {
struct nlattr *rates;
wpa_printf(MSG_DEBUG, "
nl80211: P2P probe - mask SuppRates"
);
rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES);
if (rates == NULL)
goto fail;
/*
* Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
* by masking out everything else apart from the OFDM rates 6,
* 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
* rates are left enabled.
*/
if (nla_put(msg, NL80211_BAND_2GHZ, 8,
"
x0cx12x18x24x30x48x60x6c"
))
goto fail;
nla_nest_end(msg, rates);
if (nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE))
goto fail;
}if (params->
bssid) {
wpa_printf(MSG_DEBUG, "
nl80211: Scan for a specific BSSID: "
MACSTR, MAC2STR(params->
bssid));
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->
bssid))
goto fail;
}ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
wpa_printf(MSG_DEBUG, "
nl80211: Scan trigger failed: ret=%d "
"
(%s)"
, ret, strerror(-ret));
if (drv->
hostapd &
&
is_ap_interface(drv->
nlmode)) {
enum nl80211_iftype old_mode = drv->
nlmode;
/*
* mac80211 does not allow scan requests in AP mode, so
* try to do this in station mode.
*/
if (wpa_driver_nl80211_set_mode(
bss, NL80211_IFTYPE_STATION))
goto fail;
if (wpa_driver_nl80211_scan(bss, params)) {
wpa_driver_nl80211_set_mode(bss, old_mode);
goto fail;
}/* Restore AP mode when processing scan results */
drv->
ap_scan_as_station = old_mode;
ret = 0;
} else
goto fail;
}drv->
scan_state = SCAN_REQUESTED;
/* Not all drivers generate "
scan completed"
wireless event, so try to
* read results after a timeout. */
// 扫描超时时间,超时之后读取结果。
timeout = 10;
if (drv->
scan_complete_events) {
/*
* The driver seems to deliver events to notify when scan is
* complete, so use longer timeout to avoid race conditions
* with scanning and following association request.
*/
timeout = 30;
}
wpa_printf(MSG_DEBUG, "
Scan requested (ret=%d) - scan timeout %d "
"
seconds"
, ret, timeout);
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->
ctx);
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
drv, drv->
ctx);
drv->
last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
fail:
nlmsg_free(msg);
return ret;
}static struct nl_msg *
nl80211_scan_common(struct i802_bss *bss, u8 cmd,
struct wpa_driver_scan_params *params)
{
struct wpa_driver_nl80211_data *drv = bss->
drv;
struct nl_msg *msg;
size_t i;
u32 scan_flags = 0;
msg = nl80211_cmd_msg(bss, 0, cmd);
if (!msg)
return NULL;
if (params->
num_ssids) {
struct nlattr *ssids;
ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
if (ssids == NULL)
goto fail;
for (i = 0;
i <
params->
num_ssids;
i++) {
wpa_hexdump_ascii(MSG_MSGDUMP, "
nl80211: Scan SSID"
,
params->
ssids[i].ssid,
params->
ssids[i].ssid_len);
if (nla_put(msg, i + 1, params->
ssids[i].ssid_len,
params->
ssids[i].ssid))
goto fail;
}
nla_nest_end(msg, ssids);
} else {
wpa_printf(MSG_DEBUG, "
nl80211: Passive scan requested"
);
}if (params->
extra_ies) {
wpa_hexdump(MSG_MSGDUMP, "
nl80211: Scan extra IEs"
,
params->
extra_ies, params->
extra_ies_len);
if (nla_put(msg, NL80211_ATTR_IE, params->
extra_ies_len,
params->
extra_ies))
goto fail;
}
// 扫描频率
if (params->
freqs) {
struct nlattr *freqs;
freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
if (freqs == NULL)
goto fail;
for (i = 0;
params->
freqs[i];
i++) {
wpa_printf(MSG_MSGDUMP, "
nl80211: Scan frequency %u "
"
MHz"
, params->
freqs[i]);
if (nla_put_u32(msg, i + 1, params->
freqs[i]))
goto fail;
}
nla_nest_end(msg, freqs);
}os_free(drv->
filter_ssids);
drv->
filter_ssids = params->
filter_ssids;
params->
filter_ssids = NULL;
drv->
num_filter_ssids = params->
num_filter_ssids;
if (params->
only_new_results) {
wpa_printf(MSG_DEBUG, "
nl80211: Add NL80211_SCAN_FLAG_FLUSH"
);
scan_flags |= NL80211_SCAN_FLAG_FLUSH;
}if (params->
low_priority &
&
drv->
have_low_prio_scan) {
wpa_printf(MSG_DEBUG,
"
nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY"
);
scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
}if (params->
mac_addr_rand) {
wpa_printf(MSG_DEBUG,
"
nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR"
);
scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
if (params->
mac_addr) {
wpa_printf(MSG_DEBUG, "
nl80211: MAC address: "
MACSTR,
MAC2STR(params->
mac_addr));
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
params->
mac_addr))
goto fail;
}if (params->
mac_addr_mask) {
wpa_printf(MSG_DEBUG, "
nl80211: MAC address mask: "
MACSTR, MAC2STR(params->
mac_addr_mask));
if (nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
params->
mac_addr_mask))
goto fail;
}
}if (params->
duration) {
if (!(drv->
capa.rrm_flags &
WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL) ||
nla_put_u16(msg, NL80211_ATTR_MEASUREMENT_DURATION,
params->
duration))
goto fail;
if (params->
duration_mandatory &
&
nla_put_flag(msg,
NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY))
goto fail;
}if (scan_flags &
&
nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags))
goto fail;
return msg;
fail:
nlmsg_free(msg);
return NULL;
}
【Android wifi 扫描流程 分析】2018-11-14
推荐阅读
- 精品推荐!一对一视频直播APP完全功能列表大全!
- Android - A WebView method was called on thread 'JavaBridge
- AutoCAD 2020系统要求
- AutoCAD 2018免费下载和安装详细步骤
- AutoCAD 2017免费下载和安装详细步骤
- AutoCAD教程入门教程
- android,Exoplayer实现视频播放器
- 记处理spring-devtools 和 通用mapper 使用问题
- Mybatis里Mapper映射sql文件里insert的主键返回selectKey使用