diff --git a/contrib/wpa/src/drivers/driver_bsd.c b/contrib/wpa/src/drivers/driver_bsd.c --- a/contrib/wpa/src/drivers/driver_bsd.c +++ b/contrib/wpa/src/drivers/driver_bsd.c @@ -719,6 +719,25 @@ } #endif /* SO_RERROR */ +/** + * wpa_driver_bsd_scan_timeout - Scan timeout to report scan completion + * @eloop_ctx: Driver private data + * @timeout_ctx: ctx argument given to wpa_driver_bsd_init() + * + * This function can be used as registered timeout when starting a scan to + * generate a scan completed event if the driver does not report this. + */ +static void +wpa_driver_bsd_scan_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct bsd_driver_data *drv = eloop_ctx; + + wpa_printf(MSG_DEBUG, "scan timeout, try to get scan results"); + + wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, + NULL); +} + static void bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) { @@ -774,6 +793,8 @@ case RTM_IEEE80211_SCAN: if (drv->is_ap) break; + eloop_cancel_timeout(wpa_driver_bsd_scan_timeout, + drv, drv->ctx); wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL); break; @@ -1290,6 +1311,7 @@ #ifdef IEEE80211_IOC_SCAN_MAX_SSID struct ieee80211_scan_req sr; int i; + int ret, res, timeout; #endif /* IEEE80211_IOC_SCAN_MAX_SSID */ if (bsd_set_mediaopt(drv, IFM_OMASK, 0 /* STA */) < 0) { @@ -1341,8 +1363,33 @@ sr.sr_ssid[i].len); } - /* NB: net80211 delivers a scan complete event so no need to poll */ - return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr)); + ret = set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr)); + + /* Sometimes wpa_supplicant can never initiate a scan request to net80211 + * since net80211 has already fired the scan process, and sometimes it never + * ends. In this case, net80211 will never pass the scan-result event to us. + * Add a timer to read scan results if the scan request failed. + */ + if (ret) { + wpa_printf(MSG_DEBUG, "failed to request a scan: %s", + strerror(ret)); + + timeout = 3; + + res = eloop_deplete_timeout(timeout, 0, + wpa_driver_bsd_scan_timeout, + drv, drv->ctx); + if (res == -1) { + wpa_printf(MSG_DEBUG, + "setting scan results timer - %d sec ", timeout); + + eloop_register_timeout(timeout, 0, + wpa_driver_bsd_scan_timeout, + drv, drv->ctx); + } + } + + return ret; #else /* IEEE80211_IOC_SCAN_MAX_SSID */ /* set desired ssid before scan */ if (bsd_set_ssid(drv, params->ssids[0].ssid, @@ -1630,6 +1677,9 @@ { struct bsd_driver_data *drv = priv; + eloop_cancel_timeout(wpa_driver_bsd_scan_timeout, + drv, drv->ctx); + if (drv->ifindex != 0 && !drv->if_removed) { wpa_driver_bsd_set_wpa(drv, 0); diff --git a/libexec/rc/rc.d/wpa_supplicant b/libexec/rc/rc.d/wpa_supplicant --- a/libexec/rc/rc.d/wpa_supplicant +++ b/libexec/rc/rc.d/wpa_supplicant @@ -12,7 +12,6 @@ name="wpa_supplicant" desc="WPA/802.11i Supplicant for wireless network devices" -start_postcmd="wpa_poststart" rcvar= ifn="$2" @@ -28,12 +27,6 @@ esac } -wpa_poststart() { - ifconfig ${ifn} down - sleep 2 - ifconfig ${ifn} up -} - if is_wired_interface ${ifn} ; then driver="wired" elif is_ndis_interface ${ifn} ; then