diff options
| -rw-r--r-- | hostapd/Makefile | 9 | ||||
| -rw-r--r-- | src/rsn_supp/wpa.c | 8 | ||||
| -rw-r--r-- | wpa_supplicant/bss.c | 53 | ||||
| -rw-r--r-- | wpa_supplicant/bss.h | 2 | ||||
| -rw-r--r-- | wpa_supplicant/ctrl_iface.c | 5 | ||||
| -rw-r--r-- | wpa_supplicant/events.c | 70 | ||||
| -rw-r--r-- | wpa_supplicant/p2p_supplicant.c | 22 | ||||
| -rw-r--r-- | wpa_supplicant/scan.c | 37 | ||||
| -rw-r--r-- | wpa_supplicant/scan.h | 2 | ||||
| -rw-r--r-- | wpa_supplicant/wpa_supplicant.c | 4 |
10 files changed, 189 insertions, 23 deletions
diff --git a/hostapd/Makefile b/hostapd/Makefile index 8404e0cb..6e422a9e 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -6,6 +6,8 @@ ifndef CFLAGS CFLAGS = -MMD -O2 -Wall -g endif +export BINDIR ?= /usr/local/sbin/ + CFLAGS += -I../src CFLAGS += -I../src/utils @@ -848,9 +850,10 @@ verify_config: exit 1; \ fi -install: all - mkdir -p $(DESTDIR)/usr/local/bin - for i in $(ALL); do cp -f $$i $(DESTDIR)/usr/local/bin/$$i; done +$(DESTDIR)$(BINDIR)/%: % + install -D $(<) $(@) + +install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL)) ../src/drivers/build.hostapd: @if [ -f ../src/drivers/build.wpa_supplicant ]; then \ diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index e50404ce..ce3f3180 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1132,7 +1132,8 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, goto failed; } - wpa_sm_set_rekey_offload(sm); + if (ie.gtk) + wpa_sm_set_rekey_offload(sm); return; @@ -1353,13 +1354,14 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher)); wpa_sm_cancel_auth_timeout(sm); wpa_sm_set_state(sm, WPA_COMPLETED); - - wpa_sm_set_rekey_offload(sm); } else { wpa_supplicant_key_neg_complete(sm, sm->bssid, key_info & WPA_KEY_INFO_SECURE); } + + wpa_sm_set_rekey_offload(sm); + return; failed: diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 0e1576b0..caec1bae 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -501,6 +501,22 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, wpa_bss_copy_res(bss, res, fetch_time); /* Move the entry to the end of the list */ dl_list_del(&bss->list); +#ifdef CONFIG_P2P + if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE)) { + /* + * This can happen when non-P2P station interface runs a scan + * without P2P IE in the Probe Request frame. P2P GO would reply + * to that with a Probe Response that does not include P2P IE. + * Do not update the IEs in this BSS entry to avoid such loss of + * information that may be needed for P2P operations to + * determine group information. + */ + wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Do not update scan IEs for " + MACSTR " since that would remove P2P IE information", + MAC2STR(bss->bssid)); + } else +#endif /* CONFIG_P2P */ if (bss->ie_len + bss->beacon_ie_len >= res->ie_len + res->beacon_ie_len) { os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); @@ -1001,6 +1017,43 @@ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) /** + * wpa_bss_get_vendor_ie_beacon - Fetch a vendor information from a BSS entry + * @bss: BSS table entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the BSS + * entry. + * + * This function is like wpa_bss_get_vendor_ie(), but uses IE buffer only + * from Beacon frames instead of either Beacon or Probe Response frames. + */ +const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, + u32 vendor_type) +{ + const u8 *end, *pos; + + if (bss->beacon_ie_len == 0) + return NULL; + + pos = (const u8 *) (bss + 1); + pos += bss->ie_len; + end = pos + bss->beacon_ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** * wpa_bss_get_vendor_ie_multi - Fetch vendor IE data from a BSS entry * @bss: BSS table entry * @vendor_type: Vendor type (four octets starting the IE payload) diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 2b419488..0d2693fd 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -118,6 +118,8 @@ struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, unsigned int idf, unsigned int idl); const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); +const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, + u32 vendor_type); struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, u32 vendor_type); struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss, diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 369a39ed..449ad74a 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2022,6 +2022,8 @@ static int wpa_supplicant_ctrl_iface_scan_result( const u8 *ie, *ie2, *p2p; p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); + if (!p2p) + p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE); if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) @@ -3214,7 +3216,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, return 0; pos += ret; } - if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) { + if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || + wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { ret = os_snprintf(pos, end - pos, "[P2P]"); if (ret < 0 || ret >= end - pos) return 0; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 184b14ef..d0e3f4ab 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -688,10 +688,13 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, rsn_ie_len = ie ? ie[1] : 0; wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' " - "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s", + "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s%s", i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len), wpa_ie_len, rsn_ie_len, bss->caps, bss->level, - wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : ""); + wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "", + (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || + wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ? + " p2p" : ""); e = wpa_blacklist_get(wpa_s, bss->bssid); if (e) { @@ -829,6 +832,13 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, } #ifdef CONFIG_P2P + if (ssid->p2p_group && + !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P IE seen"); + continue; + } + /* * TODO: skip the AP if its P2P IE has Group Formation * bit set in the P2P Group Capability Bitmap and we @@ -2396,6 +2406,51 @@ static void wpa_supplicant_event_unprot_disassoc(struct wpa_supplicant *wpa_s, #endif /* CONFIG_IEEE80211W */ } +static void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s) +{ + const char *rn, *rn2; + struct wpa_supplicant *ifs; + + if (wpa_s->drv_priv == NULL) + return; /* Ignore event during drv initialization */ + + free_hw_features(wpa_s); + wpa_s->hw.modes = wpa_drv_get_hw_feature_data( + wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags); + +#ifdef CONFIG_P2P + wpas_p2p_update_channel_list(wpa_s); +#endif /* CONFIG_P2P */ + + /* + * Check other interfaces to see if they have the same radio-name. If + * so, they get updated with this same hw mode info. + */ + if (!wpa_s->driver->get_radio_name) + return; + + rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv); + if (rn == NULL || rn[0] == '\0') + return; + + wpa_dbg(wpa_s, MSG_DEBUG, "Checking for other virtual interfaces " + "sharing same radio (%s) in event_channel_list_change", rn); + + for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) { + if (ifs == wpa_s || !ifs->driver->get_radio_name) + continue; + + rn2 = ifs->driver->get_radio_name(ifs->drv_priv); + if (rn2 && os_strcmp(rn, rn2) == 0) { + wpa_printf(MSG_DEBUG, "%s: Updating hw mode", + ifs->ifname); + free_hw_features(ifs); + ifs->hw.modes = wpa_drv_get_hw_feature_data( + ifs, &ifs->hw.num_modes, &ifs->hw.flags); + } + } +} + void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) @@ -2958,16 +3013,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); break; case EVENT_CHANNEL_LIST_CHANGED: - if (wpa_s->drv_priv == NULL) - break; /* Ignore event during drv initialization */ - - free_hw_features(wpa_s); - wpa_s->hw.modes = wpa_drv_get_hw_feature_data( - wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags); - -#ifdef CONFIG_P2P - wpas_p2p_update_channel_list(wpa_s); -#endif /* CONFIG_P2P */ + wpa_supplicant_update_channel_list(wpa_s); break; case EVENT_INTERFACE_UNAVAILABLE: #ifdef CONFIG_P2P diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 84db2c9a..a260c770 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -146,13 +146,28 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s, for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; struct os_time time_tmp_age, entry_ts; + const u8 *ies; + size_t ies_len; + time_tmp_age.sec = bss->age / 1000; time_tmp_age.usec = (bss->age % 1000) * 1000; os_time_sub(&scan_res->fetch_time, &time_tmp_age, &entry_ts); + + ies = (const u8 *) (bss + 1); + ies_len = bss->ie_len; + if (bss->beacon_ie_len > 0 && + !wpa_scan_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + wpa_scan_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { + wpa_printf(MSG_DEBUG, "P2P: Use P2P IE(s) from Beacon frame since no P2P IE(s) in Probe Response frames received for " + MACSTR, MAC2STR(bss->bssid)); + ies = ies + ies_len; + ies_len = bss->beacon_ie_len; + } + + if (p2p_scan_res_handler(wpa_s->global->p2p, bss->bssid, bss->freq, &entry_ts, bss->level, - (const u8 *) (bss + 1), - bss->ie_len) > 0) + ies, ies_len) > 0) break; } @@ -472,6 +487,9 @@ static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s, } p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE); + if (p2p == NULL) + p2p = wpa_bss_get_vendor_ie_multi_beacon(bss, + P2P_IE_VENDOR_TYPE); if (p2p == NULL) { wpa_printf(MSG_DEBUG, "P2P: Could not figure out whether " "group is persistent - BSS " MACSTR diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 07e3e06c..25717477 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1345,6 +1345,43 @@ const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, /** + * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result + * @res: Scan result entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the scan + * result. + * + * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only + * from Beacon frames instead of either Beacon or Probe Response frames. + */ +const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, + u32 vendor_type) +{ + const u8 *end, *pos; + + if (res->beacon_ie_len == 0) + return NULL; + + pos = (const u8 *) (res + 1); + pos += res->ie_len; + end = pos + res->beacon_ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** * wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result * @res: Scan result entry * @vendor_type: Vendor type (four octets starting the IE payload) diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h index e892479f..6eeb19a9 100644 --- a/wpa_supplicant/scan.h +++ b/wpa_supplicant/scan.h @@ -28,6 +28,8 @@ int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s); const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie); const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, u32 vendor_type); +const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, + u32 vendor_type); struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, u32 vendor_type); int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s, diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 80f2d67d..bab3ccd1 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1807,7 +1807,7 @@ static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s, * Try to reassociate since there is no current configuration and a new * network was made available. */ - if (!wpa_s->current_ssid) + if (!wpa_s->current_ssid && !wpa_s->disconnected) wpa_s->reassociate = 1; } @@ -1828,7 +1828,7 @@ void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s, } else wpa_supplicant_enable_one_network(wpa_s, ssid); - if (wpa_s->reassociate) { + if (wpa_s->reassociate && !wpa_s->disconnected) { if (wpa_s->sched_scanning) { wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add " "new network to scan filters"); |
