diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index de60c79fa..204274f0d 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -350,7 +350,7 @@ int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, u16 auth_alg) { if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL) - return 0; + return -EOPNOTSUPP; return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg); } diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 76f86d9d5..ddab95040 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -891,18 +891,28 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) { struct hostapd_data *hapd = ctx; struct sta_info *sta; + int ret; wpa_printf(MSG_DEBUG, "Add station entry for " MACSTR " based on WPA authenticator callback", MAC2STR(sta_addr)); - if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0) + ret = hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT); + + /* + * The expected return values from hostapd_add_sta_node() are + * 0: successfully added STA entry + * -EOPNOTSUPP: driver or driver wrapper does not support/need this + * operations + * any other negative value: error in adding the STA entry */ + if (ret < 0 && ret != -EOPNOTSUPP) return NULL; sta = ap_sta_add(hapd, sta_addr); if (sta == NULL) return NULL; - if (hapd->driver && hapd->driver->add_sta_node) + if (ret == 0) sta->added_unassoc = 1; + sta->ft_over_ds = 1; if (sta->wpa_sm) { sta->auth_alg = WLAN_AUTH_FT; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 6d88f786e..4c8dcad8d 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -9558,6 +9558,40 @@ fail: return -1; } + +static int nl80211_add_sta_node(void *priv, const u8 *addr, u16 auth_alg) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + struct nlattr *params; + + if (!drv->add_sta_node_vendor_cmd_avail) + return -EOPNOTSUPP; + + wpa_printf(MSG_DEBUG, "nl80211: Add STA node"); + + if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, + QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE) || + !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || + (addr && + nla_put(msg, QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_MAC_ADDR, ETH_ALEN, + addr)) || + nla_put_u16(msg, QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_AUTH_ALGO, + auth_alg)) { + nlmsg_free(msg); + wpa_printf(MSG_ERROR, + "%s: err in adding vendor_cmd and vendor_data", + __func__); + return -1; + } + nla_nest_end(msg, params); + + return send_and_recv_msgs(drv, msg, NULL, NULL); +} + #endif /* CONFIG_DRIVER_NL80211_QCA */ @@ -11222,6 +11256,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .ignore_assoc_disallow = nl80211_ignore_assoc_disallow, #endif /* CONFIG_MBO */ .set_bssid_blacklist = nl80211_set_bssid_blacklist, + .add_sta_node = nl80211_add_sta_node, #endif /* CONFIG_DRIVER_NL80211_QCA */ .configure_data_frame_filters = nl80211_configure_data_frame_filters, .get_ext_capab = nl80211_get_ext_capab, diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 749826945..716504c10 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -172,6 +172,7 @@ struct wpa_driver_nl80211_data { unsigned int fetch_bss_trans_status:1; unsigned int roam_vendor_cmd_avail:1; unsigned int get_supported_akm_suites_avail:1; + unsigned int add_sta_node_vendor_cmd_avail:1; u64 vendor_scan_cookie; u64 remain_on_chan_cookie; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index cd9693c90..256e948c2 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -787,6 +787,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS: drv->get_supported_akm_suites_avail = 1; break; + case QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: + drv->add_sta_node_vendor_cmd_avail = 1; + break; #endif /* CONFIG_DRIVER_NL80211_QCA */ } }