|
@@ -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);
|
|
|
}
|
|
|
|
|
|
|