Merge "wifi: implement enable SAE PK only mode API"
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
index ee3a44e..6450a9f 100644
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ b/hostapd/hidl/1.3/hostapd.cpp
@@ -10,9 +10,14 @@
#include <sstream>
#include <string>
#include <vector>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <linux/if_bridge.h>
+
#include <android-base/file.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
#include "hostapd.h"
#include "hidl_return_util.h"
@@ -20,6 +25,7 @@
extern "C"
{
#include "common/wpa_ctrl.h"
+#include "drivers/linux_ioctl.h"
}
// The HIDL implementation for hostapd creates a hostapd.conf dynamically for
@@ -37,6 +43,46 @@
using android::hardware::wifi::hostapd::V1_3::Generation;
using android::hardware::wifi::hostapd::V1_3::Bandwidth;
+#define MAX_PORTS 1024
+bool GetInterfacesInBridge(std::string br_name,
+ std::vector<std::string>* interfaces) {
+ android::base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
+ if (sock.get() < 0) {
+ wpa_printf(MSG_ERROR, "Failed to create sock (%s) in %s",
+ strerror(errno), __FUNCTION__);
+ return false;
+ }
+
+ struct ifreq request;
+ int i, ifindices[MAX_PORTS];
+ char if_name[IFNAMSIZ];
+ unsigned long args[3];
+
+ memset(ifindices, 0, MAX_PORTS * sizeof(int));
+
+ args[0] = BRCTL_GET_PORT_LIST;
+ args[1] = (unsigned long) ifindices;
+ args[2] = MAX_PORTS;
+
+ strlcpy(request.ifr_name, br_name.c_str(), IFNAMSIZ);
+ request.ifr_data = (char *)args;
+
+ if (ioctl(sock.get(), SIOCDEVPRIVATE, &request) < 0) {
+ wpa_printf(MSG_ERROR, "Failed to ioctl SIOCDEVPRIVATE in %s",
+ __FUNCTION__);
+ return false;
+ }
+
+ for (i = 0; i < MAX_PORTS; i ++) {
+ memset(if_name, 0, IFNAMSIZ);
+ if (ifindices[i] == 0 || !if_indextoname(ifindices[i], if_name)) {
+ continue;
+ }
+ interfaces->push_back(if_name);
+ }
+ return true;
+}
+
std::string WriteHostapdConfig(
const std::string& interface_name, const std::string& config)
{
@@ -217,8 +263,9 @@
}
std::string CreateHostapdConfig(
- const IHostapd::IfaceParams& iface_params,
- const IHostapd::NetworkParams& nw_params)
+ const android::hardware::wifi::hostapd::V1_2::IHostapd::IfaceParams& iface_params,
+ const IHostapd::NetworkParams& nw_params,
+ const std::string br_name)
{
if (nw_params.V1_2.V1_0.ssid.size() >
static_cast<uint32_t>(
@@ -412,6 +459,11 @@
}
#endif /* CONFIG_INTERWORKING */
+ std::string bridge_as_string;
+ if (!br_name.empty()) {
+ bridge_as_string = StringPrintf("bridge=%s", br_name.c_str());
+ }
+
return StringPrintf(
"interface=%s\n"
"driver=nl80211\n"
@@ -431,6 +483,7 @@
#ifdef CONFIG_INTERWORKING
"%s\n"
#endif /* CONFIG_INTERWORKING */
+ "%s\n"
"%s\n",
iface_params.V1_1.V1_0.ifaceName.c_str(), ssid_as_string.c_str(),
channel_config_as_string.c_str(),
@@ -440,9 +493,10 @@
hw_mode_as_string.c_str(), ht_cap_vht_oper_chwidth_as_string.c_str(),
nw_params.V1_2.V1_0.isHidden ? 1 : 0,
#ifdef CONFIG_INTERWORKING
- access_network_params_as_string.c_str(),
+ access_network_params_as_string.c_str(),
#endif /* CONFIG_INTERWORKING */
- encryption_config_as_string.c_str());
+ encryption_config_as_string.c_str(),
+ bridge_as_string.c_str());
}
Generation getGeneration(hostapd_hw_modes *current_mode)
@@ -504,8 +558,10 @@
if (on_setup_complete_internal_callback) {
on_setup_complete_internal_callback(iface_hapd);
// Invalidate this callback since we don't want this firing
- // again.
- on_setup_complete_internal_callback = nullptr;
+ // again in single AP mode.
+ if (strlen(iface_hapd->conf->bridge) > 0) {
+ on_setup_complete_internal_callback = nullptr;
+ }
}
}
@@ -655,17 +711,89 @@
return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
}
+V1_2::IHostapd::IfaceParams prepareIfaceParams1_2From1_3(const std::string interfaceName,
+ const V1_3::IHostapd::IfaceParams iface_1_3,
+ const V1_3::IHostapd::ChannelParams channelParams_1_3)
+{
+ // Using HIDL 1.2 iface_params to enable the AP
+ V1_2::IHostapd::IfaceParams iface_params_1_2 = iface_1_3.V1_2;
+ iface_params_1_2.V1_1.V1_0.ifaceName = interfaceName;
+ // Prepare bandMask & acsChannelFreqRangesMhz
+ iface_params_1_2.channelParams = channelParams_1_3.V1_2;
+ // Prepare channel
+ iface_params_1_2.V1_1.V1_0.channelParams.channel = channelParams_1_3.channel;
+ // Prepare enableAcs
+ iface_params_1_2.V1_1.V1_0.channelParams.enableAcs = channelParams_1_3.enableAcs;
+ return iface_params_1_2;
+}
+
V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_3(
- const V1_2::IHostapd::IfaceParams& iface_params,
+ const V1_3::IHostapd::IfaceParams& iface_params,
const V1_3::IHostapd::NetworkParams& nw_params)
{
+ int channelParamsListSize = iface_params.channelParamsList.size();
+ if (channelParamsListSize == 1) {
+ // Single AP
+ wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
+ iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
+ return addSingleAccessPoint(
+ prepareIfaceParams1_2From1_3(iface_params.V1_2.V1_1.V1_0.ifaceName,
+ iface_params, iface_params.channelParamsList[0]),
+ nw_params, "");
+ } else if (channelParamsListSize == 2) {
+ // Concurrent APs
+ wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
+ iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
+ return addConcurrentAccessPoints(iface_params, nw_params);
+ }
+ return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
+}
+
+V1_2::HostapdStatus Hostapd::addConcurrentAccessPoints(
+ const V1_3::IHostapd::IfaceParams& iface_params, const V1_3::IHostapd::NetworkParams& nw_params)
+{
+ int channelParamsListSize = iface_params.channelParamsList.size();
+ // Get available interfaces in bridge
+ std::vector<std::string> managed_interfaces;
+ std::string br_name = StringPrintf(
+ "%s", iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
+ if (!GetInterfacesInBridge(br_name, &managed_interfaces)) {
+ return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
+ "Get interfaces in bridge failed."};
+ }
+ if (managed_interfaces.size() < channelParamsListSize) {
+ return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
+ "Available interfaces less than requested bands"};
+ }
+ // start BSS on specified bands
+ for (std::size_t i = 0; i < channelParamsListSize; i ++) {
+ V1_2::HostapdStatus status = addSingleAccessPoint(
+ prepareIfaceParams1_2From1_3(managed_interfaces[i], iface_params,
+ iface_params.channelParamsList[i]),
+ nw_params, br_name);
+ if (status.code != V1_2::HostapdStatusCode::SUCCESS) {
+ wpa_printf(MSG_ERROR, "Failed to addAccessPoint %s",
+ managed_interfaces[i].c_str());
+ return status;
+ }
+ }
+ // Save bridge interface info
+ br_interfaces_[br_name] = managed_interfaces;
+ return {V1_2::HostapdStatusCode::SUCCESS, ""};
+}
+
+V1_2::HostapdStatus Hostapd::addSingleAccessPoint(
+ const V1_2::IHostapd::IfaceParams& iface_params,
+ const V1_3::IHostapd::NetworkParams& nw_params,
+ const std::string br_name)
+{
if (hostapd_get_iface(interfaces_, iface_params.V1_1.V1_0.ifaceName.c_str())) {
wpa_printf(
MSG_ERROR, "Interface %s already present",
iface_params.V1_1.V1_0.ifaceName.c_str());
return {V1_2::HostapdStatusCode::FAILURE_IFACE_EXISTS, ""};
}
- const auto conf_params = CreateHostapdConfig(iface_params, nw_params);
+ const auto conf_params = CreateHostapdConfig(iface_params, nw_params, br_name);
if (conf_params.empty()) {
wpa_printf(MSG_ERROR, "Failed to create config params");
return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
@@ -694,7 +822,7 @@
on_setup_complete_internal_callback =
[this](struct hostapd_data* iface_hapd) {
wpa_printf(
- MSG_DEBUG, "AP interface setup completed - state %s",
+ MSG_INFO, "AP interface setup completed - state %s",
hostapd_state_text(iface_hapd->iface->state));
if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
// Invoke the failure callback on all registered
@@ -713,11 +841,9 @@
wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
MAC2STR(mac_addr),
(authorized) ? "Connected" : "Disconnected");
-
for (const auto &callback : callbacks_) {
- // TODO: The iface need to separate to iface and ap instance
- // identify for AP+AP case.
- callback->onConnectedClientsChanged(iface_hapd->conf->iface,
+ callback->onConnectedClientsChanged(strlen(iface_hapd->conf->bridge) > 0 ?
+ iface_hapd->conf->bridge : iface_hapd->conf->iface,
iface_hapd->conf->iface, mac_addr, authorized);
}
};
@@ -732,8 +858,10 @@
strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
for (const auto &callback : callbacks_) {
callback->onApInstanceInfoChanged(
- iface_hapd->conf->iface, iface_hapd->conf->iface,
- iface_hapd->iface->freq, getBandwidth(iface_hapd->iconf),
+ strlen(iface_hapd->conf->bridge) > 0 ?
+ iface_hapd->conf->bridge : iface_hapd->conf->iface,
+ iface_hapd->conf->iface, iface_hapd->iface->freq,
+ getBandwidth(iface_hapd->iconf),
getGeneration(iface_hapd->iface->current_mode),
iface_hapd->own_addr);
}
diff --git a/hostapd/hidl/1.3/hostapd.h b/hostapd/hidl/1.3/hostapd.h
index 79354d3..ceec080 100644
--- a/hostapd/hidl/1.3/hostapd.h
+++ b/hostapd/hidl/1.3/hostapd.h
@@ -71,7 +71,7 @@
const V1_2::IHostapd::NetworkParams& nw_params,
addAccessPoint_1_2_cb _hidl_cb) override;
Return<void> addAccessPoint_1_3(
- const V1_2::IHostapd::IfaceParams& iface_params,
+ const V1_3::IHostapd::IfaceParams& iface_params,
const V1_3::IHostapd::NetworkParams& nw_params,
addAccessPoint_1_3_cb _hidl_cb) override;
Return<void> removeAccessPoint(
@@ -102,7 +102,14 @@
const V1_2::IHostapd::IfaceParams& IfaceParams,
const V1_2::IHostapd::NetworkParams& nw_params);
V1_2::HostapdStatus addAccessPointInternal_1_3(
+ const V1_3::IHostapd::IfaceParams& IfaceParams,
+ const V1_3::IHostapd::NetworkParams& nw_params);
+ V1_2::HostapdStatus addSingleAccessPoint(
const V1_2::IHostapd::IfaceParams& IfaceParams,
+ const V1_3::IHostapd::NetworkParams& nw_params,
+ std::string br_name);
+ V1_2::HostapdStatus addConcurrentAccessPoints(
+ const V1_3::IHostapd::IfaceParams& IfaceParams,
const V1_3::IHostapd::NetworkParams& nw_params);
V1_0::HostapdStatus removeAccessPointInternal(const std::string& iface_name);
V1_0::HostapdStatus registerCallbackInternal(
@@ -120,6 +127,8 @@
std::vector<sp<V1_3::IHostapdCallback>> callbacks_;
// Death notifier.
android::sp<DeathNotifier> death_notifier_;
+ // Bridge and its managed interfaces.
+ std::map<std::string, std::vector<std::string>> br_interfaces_;
DISALLOW_COPY_AND_ASSIGN(Hostapd);
};
} // namespace implementation
diff --git a/src/utils/list.h b/src/utils/list.h
index 85aa5e3..5298c26 100644
--- a/src/utils/list.h
+++ b/src/utils/list.h
@@ -46,12 +46,12 @@
item->prev = NULL;
}
-static inline int dl_list_empty(struct dl_list *list)
+static inline int dl_list_empty(const struct dl_list *list)
{
return list->next == list;
}
-static inline unsigned int dl_list_len(struct dl_list *list)
+static inline unsigned int dl_list_len(const struct dl_list *list)
{
struct dl_list *item;
int count = 0;
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.cpp b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
index d7136a6..8325311 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
@@ -17,6 +17,7 @@
extern "C" {
#include "scan.h"
#include "src/eap_common/eap_sim_common.h"
+#include "list.h"
}
namespace {
@@ -821,23 +822,33 @@
sta_iface_object_map_.end())
return;
- ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data;
+ V1_4::ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data;
ISupplicantStaIfaceCallback::Hs20AnqpData hidl_hs20_anqp_data;
if (std::string(result) == "SUCCESS") {
- hidl_anqp_data.venueName =
+ hidl_anqp_data.V1_0.venueName =
misc_utils::convertWpaBufToVector(anqp->venue_name);
- hidl_anqp_data.roamingConsortium =
+ hidl_anqp_data.V1_0.roamingConsortium =
misc_utils::convertWpaBufToVector(anqp->roaming_consortium);
- hidl_anqp_data.ipAddrTypeAvailability =
+ hidl_anqp_data.V1_0.ipAddrTypeAvailability =
misc_utils::convertWpaBufToVector(
anqp->ip_addr_type_availability);
- hidl_anqp_data.naiRealm =
+ hidl_anqp_data.V1_0.naiRealm =
misc_utils::convertWpaBufToVector(anqp->nai_realm);
- hidl_anqp_data.anqp3gppCellularNetwork =
+ hidl_anqp_data.V1_0.anqp3gppCellularNetwork =
misc_utils::convertWpaBufToVector(anqp->anqp_3gpp);
- hidl_anqp_data.domainName =
+ hidl_anqp_data.V1_0.domainName =
misc_utils::convertWpaBufToVector(anqp->domain_name);
+ struct wpa_bss_anqp_elem *elem;
+ dl_list_for_each(elem, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
+ list) {
+ if (elem->infoid == ANQP_VENUE_URL) {
+ hidl_anqp_data.venueUrl =
+ misc_utils::convertWpaBufToVector(elem->payload);
+ break;
+ }
+ }
+
hidl_hs20_anqp_data.operatorFriendlyName =
misc_utils::convertWpaBufToVector(
anqp->hs20_operator_friendly_name);
@@ -851,9 +862,9 @@
anqp->hs20_osu_providers_list);
}
- callWithEachStaIfaceCallback(
+ callWithEachStaIfaceCallback_1_4(
wpa_s->ifname, std::bind(
- &ISupplicantStaIfaceCallback::onAnqpQueryDone,
+ &V1_4::ISupplicantStaIfaceCallback::onAnqpQueryDone_1_4,
std::placeholders::_1, bssid, hidl_anqp_data,
hidl_hs20_anqp_data));
}
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.h b/wpa_supplicant/hidl/1.4/hidl_manager.h
index e3d6312..f027676 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.h
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.h
@@ -16,7 +16,7 @@
#include <android/hardware/wifi/supplicant/1.0/ISupplicantCallback.h>
#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.h>
#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetworkCallback.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.h>
#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetworkCallback.h>
#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaNetworkCallback.h>
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
index 7ba9cd8..1684382 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_iface.cpp
@@ -402,7 +402,7 @@
}
Return<void> StaIface::initiateAnqpQuery(
const hidl_array<uint8_t, 6> &mac_address,
- const hidl_vec<ISupplicantStaIface::AnqpInfoId> &info_elements,
+ const hidl_vec<V1_0::ISupplicantStaIface::AnqpInfoId> &info_elements,
const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types,
initiateAnqpQuery_cb _hidl_cb)
{
@@ -412,6 +412,15 @@
info_elements, sub_types);
}
+Return<void> StaIface::initiateVenueUrlAnqpQuery(
+ const hidl_array<uint8_t, 6> &mac_address,
+ initiateVenueUrlAnqpQuery_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::initiateVenueUrlAnqpQueryInternal, _hidl_cb, mac_address);
+}
+
Return<void> StaIface::initiateHs20IconQuery(
const hidl_array<uint8_t, 6> &mac_address, const hidl_string &file_name,
initiateHs20IconQuery_cb _hidl_cb)
@@ -986,6 +995,19 @@
return {SupplicantStatusCode::SUCCESS, ""};
}
+V1_4::SupplicantStatus StaIface::initiateVenueUrlAnqpQueryInternal(
+ const std::array<uint8_t, 6> &mac_address)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ uint16_t info_elems_buf[1] = {ANQP_VENUE_URL};
+
+ if (anqp_send_req(
+ wpa_s, mac_address.data(), 0, info_elems_buf, 1, 0, 0)) {
+ return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
+ return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+}
+
SupplicantStatus StaIface::initiateHs20IconQueryInternal(
const std::array<uint8_t, 6> &mac_address, const std::string &file_name)
{
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.h b/wpa_supplicant/hidl/1.4/sta_iface.h
index bf20b28..bb5344b 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.h
+++ b/wpa_supplicant/hidl/1.4/sta_iface.h
@@ -109,9 +109,12 @@
initiateTdlsTeardown_cb _hidl_cb) override;
Return<void> initiateAnqpQuery(
const hidl_array<uint8_t, 6>& mac_address,
- const hidl_vec<ISupplicantStaIface::AnqpInfoId>& info_elements,
+ const hidl_vec<V1_0::ISupplicantStaIface::AnqpInfoId>& info_elements,
const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes>& sub_types,
initiateAnqpQuery_cb _hidl_cb) override;
+ Return<void> initiateVenueUrlAnqpQuery(
+ const hidl_array<uint8_t, 6>& mac_address,
+ initiateVenueUrlAnqpQuery_cb _hidl_cb) override;
Return<void> initiateHs20IconQuery(
const hidl_array<uint8_t, 6>& mac_address,
const hidl_string& file_name,
@@ -239,6 +242,8 @@
const std::vector<ISupplicantStaIface::AnqpInfoId>& info_elements,
const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes>&
sub_types);
+ V1_4::SupplicantStatus initiateVenueUrlAnqpQueryInternal(
+ const std::array<uint8_t, 6>& mac_address);
SupplicantStatus initiateHs20IconQueryInternal(
const std::array<uint8_t, 6>& mac_address,
const std::string& file_name);
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index c799b5a..3946252 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2998,13 +2998,13 @@
case ANQP_VENUE_URL:
wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL",
MAC2STR(sa));
- anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
if (!pmf_in_use(wpa_s, sa)) {
wpa_printf(MSG_DEBUG,
"ANQP: Ignore Venue URL since PMF was not enabled");
break;
}
+ anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
interworking_parse_venue_url(wpa_s, pos, slen);
break;
case ANQP_VENDOR_SPECIFIC:
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 67fb426..6ab5485 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3844,6 +3844,8 @@
* succeed.
*/
wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+ wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
return;