diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 6ba01d465..ae5d8afd4 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -153,8 +153,8 @@ struct wpa_driver_nl80211_data { int associated; u8 ssid[32]; size_t ssid_len; - int nlmode; - int ap_scan_as_station; + enum nl80211_iftype nlmode; + enum nl80211_iftype ap_scan_as_station; unsigned int assoc_freq; int monitor_sock; @@ -189,7 +189,8 @@ struct wpa_driver_nl80211_data { static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx); -static int wpa_driver_nl80211_set_mode(void *priv, int mode); +static int wpa_driver_nl80211_set_mode(struct i802_bss *bss, + enum nl80211_iftype nlmode); static int wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv); static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, @@ -223,6 +224,20 @@ static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv); +static int is_ap_interface(enum nl80211_iftype nlmode) +{ + return (nlmode == NL80211_IFTYPE_AP || + nlmode == NL80211_IFTYPE_P2P_GO); +} + + +static int is_sta_interface(enum nl80211_iftype nlmode) +{ + return (nlmode == NL80211_IFTYPE_STATION || + nlmode == NL80211_IFTYPE_P2P_CLIENT); +} + + struct nl80211_bss_info_arg { struct wpa_driver_nl80211_data *drv; struct wpa_scan_results *res; @@ -1447,12 +1462,12 @@ static int process_event(struct nl_msg *msg, void *arg) } } - if (drv->ap_scan_as_station && + if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED && (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS || gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) { wpa_driver_nl80211_set_mode(&drv->first_bss, - IEEE80211_MODE_AP); - drv->ap_scan_as_station = 0; + drv->ap_scan_as_station); + drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; } switch (gnlh->cmd) { @@ -1966,6 +1981,7 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname, drv->monitor_ifidx = -1; drv->monitor_sock = -1; drv->ioctl_sock = -1; + drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; if (wpa_driver_nl80211_init_nl(drv)) { os_free(drv); @@ -2140,7 +2156,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) */ if ((drv->global == NULL || drv->ifindex != drv->global->if_add_ifindex) && - wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA) < 0) { + wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION) < 0) { wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to " "use managed mode"); } @@ -2236,7 +2252,7 @@ static void wpa_driver_nl80211_deinit(void *priv) nl80211_remove_monitor_interface(drv); - if (drv->nlmode == NL80211_IFTYPE_AP) + if (is_ap_interface(drv->nlmode)) wpa_driver_nl80211_del_beacon(drv); #ifdef HOSTAPD @@ -2267,7 +2283,7 @@ static void wpa_driver_nl80211_deinit(void *priv) eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); (void) linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0); - wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA); + wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION); if (drv->ioctl_sock >= 0) close(drv->ioctl_sock); @@ -2300,10 +2316,10 @@ static void wpa_driver_nl80211_deinit(void *priv) static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) { struct wpa_driver_nl80211_data *drv = eloop_ctx; - if (drv->ap_scan_as_station) { + if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) { wpa_driver_nl80211_set_mode(&drv->first_bss, - IEEE80211_MODE_AP); - drv->ap_scan_as_station = 0; + drv->ap_scan_as_station); + drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; } wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); @@ -2377,23 +2393,22 @@ static int wpa_driver_nl80211_scan(void *priv, wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d " "(%s)", ret, strerror(-ret)); #ifdef HOSTAPD - if (drv->nlmode == NL80211_IFTYPE_AP) { + if (is_ap_interface(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, - IEEE80211_MODE_INFRA)) + if (wpa_driver_nl80211_set_mode( + bss, NL80211_IFTYPE_STATION)) goto nla_put_failure; if (wpa_driver_nl80211_scan(drv, params)) { - wpa_driver_nl80211_set_mode(bss, - IEEE80211_MODE_AP); + wpa_driver_nl80211_set_mode(bss, drv->nlmode); goto nla_put_failure; } /* Restore AP mode when processing scan results */ - drv->ap_scan_as_station = 1; + drv->ap_scan_as_station = drv->nlmode; ret = 0; } else goto nla_put_failure; @@ -2660,7 +2675,7 @@ static void wpa_driver_nl80211_check_bss_status( "indicates BSS status with " MACSTR " as authenticated", MAC2STR(r->bssid)); - if (drv->nlmode == NL80211_IFTYPE_STATION && + if (is_sta_interface(drv->nlmode) && os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 && os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) != 0) { @@ -2678,13 +2693,13 @@ static void wpa_driver_nl80211_check_bss_status( "indicate BSS status with " MACSTR " as associated", MAC2STR(r->bssid)); - if (drv->nlmode == NL80211_IFTYPE_STATION && + if (is_sta_interface(drv->nlmode) && !drv->associated) { wpa_printf(MSG_DEBUG, "nl80211: Local state " "(not associated) does not match " "with BSS state"); clear_state_mismatch(drv, r->bssid); - } else if (drv->nlmode == NL80211_IFTYPE_STATION && + } else if (is_sta_interface(drv->nlmode) && os_memcmp(drv->bssid, r->bssid, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "nl80211: Local state " @@ -2892,7 +2907,7 @@ static int wpa_driver_nl80211_set_key(const char *ifname, void *priv, */ if (ret || !set_tx || alg == WPA_ALG_NONE) return ret; - if (drv->nlmode == NL80211_IFTYPE_AP && addr && + if (is_ap_interface(drv->nlmode) && addr && !is_broadcast_ether_addr(addr)) return ret; @@ -3151,7 +3166,7 @@ static int wpa_driver_nl80211_authenticate( os_memset(drv->auth_bssid, 0, ETH_ALEN); /* FIX: IBSS mode */ if (drv->nlmode != NL80211_IFTYPE_STATION && - wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA) < 0) + wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION) < 0) return -1; retry: @@ -3745,7 +3760,7 @@ static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, mgmt = (struct ieee80211_mgmt *) data; fc = le_to_host16(mgmt->frame_control); - if (drv->nlmode == NL80211_IFTYPE_STATION && + if (is_sta_interface(drv->nlmode) && WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) { /* @@ -4587,10 +4602,16 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr, static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params) { - if (params->p2p) + enum nl80211_iftype nlmode; + + if (params->p2p) { wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P " "group (GO)"); - if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode) || + nlmode = NL80211_IFTYPE_P2P_GO; + } else + nlmode = NL80211_IFTYPE_AP; + + if (wpa_driver_nl80211_set_mode(&drv->first_bss, nlmode) || wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) { nl80211_remove_monitor_interface(drv); return -1; @@ -4641,7 +4662,8 @@ static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv, wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); - if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode)) { + if (wpa_driver_nl80211_set_mode(&drv->first_bss, + NL80211_IFTYPE_ADHOC)) { wpa_printf(MSG_INFO, "nl80211: Failed to set interface into " "IBSS mode"); return -1; @@ -4882,7 +4904,10 @@ static int wpa_driver_nl80211_associate( return wpa_driver_nl80211_ibss(drv, params); if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { - if (wpa_driver_nl80211_set_mode(priv, params->mode) < 0) + enum nl80211_iftype nlmode = params->p2p ? + NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION; + + if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0) return -1; return wpa_driver_nl80211_connect(drv, params); } @@ -5032,28 +5057,13 @@ nla_put_failure: } -static int wpa_driver_nl80211_set_mode(void *priv, int mode) +static int wpa_driver_nl80211_set_mode(struct i802_bss *bss, + enum nl80211_iftype nlmode) { - struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; int ret = -1; - int nlmode; int i; - switch (mode) { - case 0: - nlmode = NL80211_IFTYPE_STATION; - break; - case 1: - nlmode = NL80211_IFTYPE_ADHOC; - break; - case 2: - nlmode = NL80211_IFTYPE_AP; - break; - default: - return -1; - } - if (nl80211_set_mode(drv, drv->ifindex, nlmode) == 0) { drv->nlmode = nlmode; ret = 0; @@ -5098,13 +5108,13 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode) } done: - if (!ret && nlmode == NL80211_IFTYPE_AP) { + if (!ret && is_ap_interface(nlmode)) { /* Setup additional AP mode functionality if needed */ if (!drv->no_monitor_iface_capab && drv->monitor_ifidx < 0 && nl80211_create_monitor_interface(drv) && !drv->no_monitor_iface_capab) return -1; - } else if (!ret && nlmode != NL80211_IFTYPE_AP) { + } else if (!ret && !is_ap_interface(nlmode)) { /* Remove additional AP mode functionality */ nl80211_remove_monitor_interface(drv); bss->beacon_set = 0; @@ -5869,7 +5879,7 @@ static void *i802_init(struct hostapd_data *hapd, goto failed; } - if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_AP)) { + if (wpa_driver_nl80211_set_mode(bss, drv->nlmode)) { wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s " "into AP mode", bss->ifname); goto failed; @@ -6224,7 +6234,7 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq, os_memcpy(hdr->addr2, src, ETH_ALEN); os_memcpy(hdr->addr3, bssid, ETH_ALEN); - if (drv->nlmode == NL80211_IFTYPE_AP) + if (is_ap_interface(drv->nlmode)) ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len); else ret = nl80211_send_frame_cmd(drv, freq, wait_time, buf, @@ -6343,7 +6353,7 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report) struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; - if (drv->nlmode != NL80211_IFTYPE_STATION) { + if (!is_sta_interface(drv->nlmode)) { wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only " "allowed in station mode (iftype=%d)", drv->nlmode); @@ -6481,10 +6491,10 @@ static int wpa_driver_nl80211_deinit_ap(void *priv) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; - if (drv->nlmode != NL80211_IFTYPE_AP) + if (!is_ap_interface(drv->nlmode)) return -1; wpa_driver_nl80211_del_beacon(drv); - return wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA); + return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION); }