[automerger skipped] Update the scan results immediately after adding the interface am: 706f17d019 am: 0cce94cf2c -s ours
am skip reason: Merged-In I5a74975fcfed7bbbff7a16acbecafd0a6570609d with SHA-1 d3bdd9ed62 is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/external/wpa_supplicant_8/+/16385819
Change-Id: Ic2328f971d7c30e104ba1b6deb9dfbec288e51c0
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index df0dc95..8449d16 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -1125,9 +1125,9 @@
endif
ifeq ($(filter gce_x86 gce_x86_64 calypso, $(TARGET_DEVICE)),)
-ifdef CONFIG_CTRL_IFACE_HIDL
-HOSTAPD_USE_HIDL=y
-L_CFLAGS += -DCONFIG_CTRL_IFACE_HIDL
+ifdef CONFIG_CTRL_IFACE_AIDL
+HOSTAPD_USE_AIDL=y
+L_CFLAGS += -DCONFIG_CTRL_IFACE_AIDL
L_CPPFLAGS = -Wall -Werror
endif
endif
@@ -1170,13 +1170,11 @@
LOCAL_STATIC_LIBRARIES += libnl_2
endif
endif
-ifeq ($(HOSTAPD_USE_HIDL), y)
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.0
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.1
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.2
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.3
-LOCAL_SHARED_LIBRARIES += libbase libhidlbase libutils
-LOCAL_STATIC_LIBRARIES += libhostapd_hidl
+ifeq ($(HOSTAPD_USE_AIDL), y)
+LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd-V1-ndk
+LOCAL_SHARED_LIBRARIES += libbase libutils
+LOCAL_SHARED_LIBRARIES += libbinder_ndk
+LOCAL_STATIC_LIBRARIES += libhostapd_aidl
endif
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := $(OBJS)
@@ -1186,7 +1184,7 @@
########################
include $(CLEAR_VARS)
-LOCAL_MODULE := hostapd_nohidl
+LOCAL_MODULE := hostapd_noaidl
LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD SPDX-license-identifier-BSD-3-Clause SPDX-license-identifier-ISC legacy_unencumbered
LOCAL_LICENSE_CONDITIONS := notice unencumbered
LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../COPYING $(LOCAL_PATH)/../NOTICE
@@ -1206,16 +1204,16 @@
LOCAL_STATIC_LIBRARIES += libnl_2
endif
endif
-LOCAL_CFLAGS := $(patsubst -DCONFIG_CTRL_IFACE_HIDL,,$(L_CFLAGS))
+LOCAL_CFLAGS := $(patsubst -DCONFIG_CTRL_IFACE_AIDL,,$(L_CFLAGS))
LOCAL_SRC_FILES := $(OBJS)
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)
-ifeq ($(HOSTAPD_USE_HIDL), y)
-### Hidl service library ###
+ifeq ($(HOSTAPD_USE_AIDL), y)
+### Aidl service library ###
########################
include $(CLEAR_VARS)
-LOCAL_MODULE := libhostapd_hidl
+LOCAL_MODULE := libhostapd_aidl
LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD SPDX-license-identifier-BSD-3-Clause SPDX-license-identifier-ISC legacy_unencumbered
LOCAL_LICENSE_CONDITIONS := notice unencumbered
LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../COPYING $(LOCAL_PATH)/../NOTICE
@@ -1223,21 +1221,17 @@
LOCAL_CPPFLAGS := $(L_CPPFLAGS)
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_C_INCLUDES := $(INCLUDES)
-HIDL_INTERFACE_VERSION = 1.3
LOCAL_SRC_FILES := \
- hidl/$(HIDL_INTERFACE_VERSION)/hidl.cpp \
- hidl/$(HIDL_INTERFACE_VERSION)/hostapd.cpp
+ aidl/aidl.cpp \
+ aidl/hostapd.cpp
LOCAL_SHARED_LIBRARIES := \
- android.hardware.wifi.hostapd@1.0 \
- android.hardware.wifi.hostapd@1.1 \
- android.hardware.wifi.hostapd@1.2 \
- android.hardware.wifi.hostapd@1.3 \
+ android.hardware.wifi.hostapd-V1-ndk \
+ libbinder_ndk \
libbase \
- libhidlbase \
libutils \
liblog
LOCAL_EXPORT_C_INCLUDE_DIRS := \
- $(LOCAL_PATH)/hidl/$(HIDL_INTERFACE_VERSION)
+ $(LOCAL_PATH)/aidl
include $(BUILD_STATIC_LIBRARY)
-endif # HOSTAPD_USE_HIDL == y
+endif # HOSTAPD_USE_AIDL == y
endif # ifeq ($(WPA_BUILD_HOSTAPD),true)
diff --git a/hostapd/hidl/.clang-format b/hostapd/aidl/.clang-format
similarity index 100%
rename from hostapd/hidl/.clang-format
rename to hostapd/aidl/.clang-format
diff --git a/hostapd/aidl/aidl.cpp b/hostapd/aidl/aidl.cpp
new file mode 100644
index 0000000..68a7714
--- /dev/null
+++ b/hostapd/aidl/aidl.cpp
@@ -0,0 +1,71 @@
+/*
+ * aidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hostapd.h"
+#include <android/binder_process.h>
+#include <android/binder_manager.h>
+
+extern "C"
+{
+#include "aidl.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+}
+
+using aidl::android::hardware::wifi::hostapd::Hostapd;
+
+// This file is a bridge between the hostapd code written in 'C' and the aidl
+// interface in C++. So, using "C" style static globals here!
+static int aidl_fd = -1;
+static std::shared_ptr<Hostapd> service;
+
+void hostapd_aidl_sock_handler(
+ int /* sock */, void * /* eloop_ctx */, void * /* sock_ctx */)
+{
+ ABinderProcess_handlePolledCommands();
+}
+
+int hostapd_aidl_init(struct hapd_interfaces *interfaces)
+{
+ wpa_printf(MSG_DEBUG, "Initializing aidl control");
+ std::string instance; // declared here to allow use of goto
+
+ ABinderProcess_setupPolling(&aidl_fd);
+ if (aidl_fd < 0)
+ goto err;
+
+ wpa_printf(MSG_INFO, "Processing aidl events on FD %d", aidl_fd);
+ // Look for read events from the aidl socket in the eloop.
+ if (eloop_register_read_sock(
+ aidl_fd, hostapd_aidl_sock_handler, interfaces, NULL) < 0)
+ goto err;
+
+ wpa_printf(MSG_DEBUG, "Make service");
+ service = ndk::SharedRefBase::make<Hostapd>(interfaces);
+ if (!service)
+ goto err;
+ wpa_printf(MSG_DEBUG, "Add service");
+ instance = std::string() + Hostapd::descriptor + "/default";
+ if (AServiceManager_addService(service->asBinder().get(), instance.c_str()) != STATUS_OK)
+ goto err;
+ return 0;
+err:
+ hostapd_aidl_deinit(interfaces);
+ return -1;
+}
+
+void hostapd_aidl_deinit(struct hapd_interfaces *interfaces)
+{
+ wpa_printf(MSG_INFO, "Deiniting aidl control");
+ // Before aidl init, make sure call terminate to clear callback_
+ service->terminate();
+ eloop_unregister_read_sock(aidl_fd);
+ aidl_fd = -1;
+}
diff --git a/hostapd/aidl/aidl.h b/hostapd/aidl/aidl.h
new file mode 100644
index 0000000..f82013d
--- /dev/null
+++ b/hostapd/aidl/aidl.h
@@ -0,0 +1,27 @@
+/*
+ * aidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // _cplusplus
+#include "ap/hostapd.h"
+
+/**
+ * This is the aidl RPC interface entry point to the hostapd core.
+ * This initializes the aidl driver & IHostapd instance.
+ */
+int hostapd_aidl_init(struct hapd_interfaces *interfaces);
+void hostapd_aidl_deinit(struct hapd_interfaces *interfaces);
+
+#ifdef __cplusplus
+}
+#endif // _cplusplus
diff --git a/hostapd/aidl/hostapd.cpp b/hostapd/aidl/hostapd.cpp
new file mode 100644
index 0000000..816ddfc
--- /dev/null
+++ b/hostapd/aidl/hostapd.cpp
@@ -0,0 +1,1008 @@
+/*
+ * aidl interface for wpa_hostapd daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+#include <iomanip>
+#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 <aidl/android/hardware/wifi/hostapd/ApInfo.h>
+#include <aidl/android/hardware/wifi/hostapd/BandMask.h>
+#include <aidl/android/hardware/wifi/hostapd/ChannelParams.h>
+#include <aidl/android/hardware/wifi/hostapd/ClientInfo.h>
+#include <aidl/android/hardware/wifi/hostapd/EncryptionType.h>
+#include <aidl/android/hardware/wifi/hostapd/HostapdStatusCode.h>
+#include <aidl/android/hardware/wifi/hostapd/IfaceParams.h>
+#include <aidl/android/hardware/wifi/hostapd/NetworkParams.h>
+#include <aidl/android/hardware/wifi/hostapd/ParamSizeLimits.h>
+
+extern "C"
+{
+#include "common/wpa_ctrl.h"
+#include "drivers/linux_ioctl.h"
+}
+
+// The AIDL implementation for hostapd creates a hostapd.conf dynamically for
+// each interface. This file can then be used to hook onto the normal config
+// file parsing logic in hostapd code. Helps us to avoid duplication of code
+// in the AIDL interface.
+// TOOD(b/71872409): Add unit tests for this.
+namespace {
+constexpr char kConfFileNameFmt[] = "/data/vendor/wifi/hostapd/hostapd_%s.conf";
+
+using android::base::RemoveFileIfExists;
+using android::base::StringPrintf;
+using android::base::WriteStringToFile;
+using aidl::android::hardware::wifi::hostapd::BandMask;
+using aidl::android::hardware::wifi::hostapd::Bandwidth;
+using aidl::android::hardware::wifi::hostapd::ChannelParams;
+using aidl::android::hardware::wifi::hostapd::EncryptionType;
+using aidl::android::hardware::wifi::hostapd::Generation;
+using aidl::android::hardware::wifi::hostapd::HostapdStatusCode;
+using aidl::android::hardware::wifi::hostapd::IfaceParams;
+using aidl::android::hardware::wifi::hostapd::NetworkParams;
+using aidl::android::hardware::wifi::hostapd::ParamSizeLimits;
+
+int band2Ghz = (int)BandMask::BAND_2_GHZ;
+int band5Ghz = (int)BandMask::BAND_5_GHZ;
+int band6Ghz = (int)BandMask::BAND_6_GHZ;
+int band60Ghz = (int)BandMask::BAND_60_GHZ;
+
+#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)
+{
+ const std::string file_path =
+ StringPrintf(kConfFileNameFmt, interface_name.c_str());
+ if (WriteStringToFile(
+ config, file_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+ getuid(), getgid())) {
+ return file_path;
+ }
+ // Diagnose failure
+ int error = errno;
+ wpa_printf(
+ MSG_ERROR, "Cannot write hostapd config to %s, error: %s",
+ file_path.c_str(), strerror(error));
+ struct stat st;
+ int result = stat(file_path.c_str(), &st);
+ if (result == 0) {
+ wpa_printf(
+ MSG_ERROR, "hostapd config file uid: %d, gid: %d, mode: %d",
+ st.st_uid, st.st_gid, st.st_mode);
+ } else {
+ wpa_printf(
+ MSG_ERROR,
+ "Error calling stat() on hostapd config file: %s",
+ strerror(errno));
+ }
+ return "";
+}
+
+/*
+ * Get the op_class for a channel/band
+ * The logic here is based on Table E-4 in the 802.11 Specification
+ */
+int getOpClassForChannel(int channel, int band, bool support11n, bool support11ac) {
+ // 2GHz Band
+ if ((band & band2Ghz) != 0) {
+ if (channel == 14) {
+ return 82;
+ }
+ if (channel >= 1 && channel <= 13) {
+ if (!support11n) {
+ //20MHz channel
+ return 81;
+ }
+ if (channel <= 9) {
+ // HT40 with secondary channel above primary
+ return 83;
+ }
+ // HT40 with secondary channel below primary
+ return 84;
+ }
+ // Error
+ return 0;
+ }
+
+ // 5GHz Band
+ if ((band & band5Ghz) != 0) {
+ if (support11ac) {
+ switch (channel) {
+ case 42:
+ case 58:
+ case 106:
+ case 122:
+ case 138:
+ case 155:
+ // 80MHz channel
+ return 128;
+ case 50:
+ case 114:
+ // 160MHz channel
+ return 129;
+ }
+ }
+
+ if (!support11n) {
+ if (channel >= 36 && channel <= 48) {
+ return 115;
+ }
+ if (channel >= 52 && channel <= 64) {
+ return 118;
+ }
+ if (channel >= 100 && channel <= 144) {
+ return 121;
+ }
+ if (channel >= 149 && channel <= 161) {
+ return 124;
+ }
+ if (channel >= 165 && channel <= 169) {
+ return 125;
+ }
+ } else {
+ switch (channel) {
+ case 36:
+ case 44:
+ // HT40 with secondary channel above primary
+ return 116;
+ case 40:
+ case 48:
+ // HT40 with secondary channel below primary
+ return 117;
+ case 52:
+ case 60:
+ // HT40 with secondary channel above primary
+ return 119;
+ case 56:
+ case 64:
+ // HT40 with secondary channel below primary
+ return 120;
+ case 100:
+ case 108:
+ case 116:
+ case 124:
+ case 132:
+ case 140:
+ // HT40 with secondary channel above primary
+ return 122;
+ case 104:
+ case 112:
+ case 120:
+ case 128:
+ case 136:
+ case 144:
+ // HT40 with secondary channel below primary
+ return 123;
+ case 149:
+ case 157:
+ // HT40 with secondary channel above primary
+ return 126;
+ case 153:
+ case 161:
+ // HT40 with secondary channel below primary
+ return 127;
+ }
+ }
+ // Error
+ return 0;
+ }
+
+ // 6GHz Band
+ if ((band & band6Ghz) != 0) {
+ // Channels 1, 5. 9, 13, ...
+ if ((channel & 0x03) == 0x01) {
+ // 20MHz channel
+ return 131;
+ }
+ // Channels 3, 11, 19, 27, ...
+ if ((channel & 0x07) == 0x03) {
+ // 40MHz channel
+ return 132;
+ }
+ // Channels 7, 23, 39, 55, ...
+ if ((channel & 0x0F) == 0x07) {
+ // 80MHz channel
+ return 133;
+ }
+ // Channels 15, 47, 69, ...
+ if ((channel & 0x1F) == 0x0F) {
+ // 160MHz channel
+ return 134;
+ }
+ if (channel == 2) {
+ // 20MHz channel
+ return 136;
+ }
+ // Error
+ return 0;
+ }
+
+ if ((band & band60Ghz) != 0) {
+ if (1 <= channel && channel <= 8) {
+ return 180;
+ } else if (9 <= channel && channel <= 15) {
+ return 181;
+ } else if (17 <= channel && channel <= 22) {
+ return 182;
+ } else if (25 <= channel && channel <= 29) {
+ return 183;
+ }
+ // Error
+ return 0;
+ }
+
+ return 0;
+}
+
+bool validatePassphrase(int passphrase_len, int min_len, int max_len)
+{
+ if (min_len != -1 && passphrase_len < min_len) return false;
+ if (max_len != -1 && passphrase_len > max_len) return false;
+ return true;
+}
+
+std::string CreateHostapdConfig(
+ const IfaceParams& iface_params,
+ const ChannelParams& channelParams,
+ const NetworkParams& nw_params,
+ const std::string br_name)
+{
+ if (nw_params.ssid.size() >
+ static_cast<uint32_t>(
+ ParamSizeLimits::SSID_MAX_LEN_IN_BYTES)) {
+ wpa_printf(
+ MSG_ERROR, "Invalid SSID size: %zu", nw_params.ssid.size());
+ return "";
+ }
+
+ // SSID string
+ std::stringstream ss;
+ ss << std::hex;
+ ss << std::setfill('0');
+ for (uint8_t b : nw_params.ssid) {
+ ss << std::setw(2) << static_cast<unsigned int>(b);
+ }
+ const std::string ssid_as_string = ss.str();
+
+ // Encryption config string
+ uint32_t band = 0;
+ band |= static_cast<uint32_t>(channelParams.bandMask);
+ bool is_6Ghz_band_only = band == static_cast<uint32_t>(band6Ghz);
+ bool is_60Ghz_band_only = band == static_cast<uint32_t>(band60Ghz);
+ std::string encryption_config_as_string;
+ switch (nw_params.encryptionType) {
+ case EncryptionType::NONE:
+ // no security params
+ break;
+ case EncryptionType::WPA:
+ if (!validatePassphrase(
+ nw_params.passphrase.size(),
+ static_cast<uint32_t>(ParamSizeLimits::
+ WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
+ static_cast<uint32_t>(ParamSizeLimits::
+ WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
+ return "";
+ }
+ encryption_config_as_string = StringPrintf(
+ "wpa=3\n"
+ "wpa_pairwise=%s\n"
+ "wpa_passphrase=%s",
+ is_60Ghz_band_only ? "GCMP" : "TKIP CCMP",
+ nw_params.passphrase.c_str());
+ break;
+ case EncryptionType::WPA2:
+ if (!validatePassphrase(
+ nw_params.passphrase.size(),
+ static_cast<uint32_t>(ParamSizeLimits::
+ WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
+ static_cast<uint32_t>(ParamSizeLimits::
+ WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
+ return "";
+ }
+ encryption_config_as_string = StringPrintf(
+ "wpa=2\n"
+ "rsn_pairwise=%s\n"
+ "wpa_passphrase=%s",
+ is_60Ghz_band_only ? "GCMP" : "CCMP",
+ nw_params.passphrase.c_str());
+ break;
+ case EncryptionType::WPA3_SAE_TRANSITION:
+ if (!validatePassphrase(
+ nw_params.passphrase.size(),
+ static_cast<uint32_t>(ParamSizeLimits::
+ WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
+ static_cast<uint32_t>(ParamSizeLimits::
+ WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
+ return "";
+ }
+ encryption_config_as_string = StringPrintf(
+ "wpa=2\n"
+ "rsn_pairwise=%s\n"
+ "wpa_key_mgmt=WPA-PSK SAE\n"
+ "ieee80211w=1\n"
+ "sae_require_mfp=1\n"
+ "wpa_passphrase=%s\n"
+ "sae_password=%s",
+ is_60Ghz_band_only ? "GCMP" : "CCMP",
+ nw_params.passphrase.c_str(),
+ nw_params.passphrase.c_str());
+ break;
+ case EncryptionType::WPA3_SAE:
+ if (!validatePassphrase(nw_params.passphrase.size(), 1, -1)) {
+ return "";
+ }
+ encryption_config_as_string = StringPrintf(
+ "wpa=2\n"
+ "rsn_pairwise=%s\n"
+ "wpa_key_mgmt=SAE\n"
+ "ieee80211w=2\n"
+ "sae_require_mfp=2\n"
+ "sae_pwe=%d\n"
+ "sae_password=%s",
+ is_60Ghz_band_only ? "GCMP" : "CCMP",
+ is_6Ghz_band_only ? 1 : 2,
+ nw_params.passphrase.c_str());
+ break;
+ default:
+ wpa_printf(MSG_ERROR, "Unknown encryption type");
+ return "";
+ }
+
+ std::string channel_config_as_string;
+ bool isFirst = true;
+ if (channelParams.enableAcs) {
+ std::string freqList_as_string;
+ for (const auto &range :
+ channelParams.acsChannelFreqRangesMhz) {
+ if (!isFirst) {
+ freqList_as_string += ",";
+ }
+ isFirst = false;
+
+ if (range.startMhz != range.endMhz) {
+ freqList_as_string +=
+ StringPrintf("%d-%d", range.startMhz, range.endMhz);
+ } else {
+ freqList_as_string += StringPrintf("%d", range.startMhz);
+ }
+ }
+ channel_config_as_string = StringPrintf(
+ "channel=0\n"
+ "acs_exclude_dfs=%d\n"
+ "freqlist=%s",
+ channelParams.acsShouldExcludeDfs,
+ freqList_as_string.c_str());
+ } else {
+ int op_class = getOpClassForChannel(
+ channelParams.channel,
+ band,
+ iface_params.hwModeParams.enable80211N,
+ iface_params.hwModeParams.enable80211AC);
+ channel_config_as_string = StringPrintf(
+ "channel=%d\n"
+ "op_class=%d",
+ channelParams.channel, op_class);
+ }
+
+ std::string hw_mode_as_string;
+ std::string ht_cap_vht_oper_chwidth_as_string;
+ std::string enable_edmg_as_string;
+ std::string edmg_channel_as_string;
+ bool is_60Ghz_used = false;
+
+ if (((band & band60Ghz) != 0)) {
+ hw_mode_as_string = "hw_mode=ad";
+ if (iface_params.hwModeParams.enableEdmg) {
+ enable_edmg_as_string = "enable_edmg=1";
+ edmg_channel_as_string = StringPrintf(
+ "edmg_channel=%d",
+ channelParams.channel);
+ }
+ is_60Ghz_used = true;
+ } else if ((band & band2Ghz) != 0) {
+ if (((band & band5Ghz) != 0)
+ || ((band & band6Ghz) != 0)) {
+ hw_mode_as_string = "hw_mode=any";
+ if (iface_params.hwModeParams.enable80211AC) {
+ ht_cap_vht_oper_chwidth_as_string =
+ "ht_capab=[HT40+]\n"
+ "vht_oper_chwidth=1";
+ }
+ } else {
+ hw_mode_as_string = "hw_mode=g";
+ }
+ } else if (((band & band5Ghz) != 0)
+ || ((band & band6Ghz) != 0)) {
+ hw_mode_as_string = "hw_mode=a";
+ if (iface_params.hwModeParams.enable80211AC) {
+ ht_cap_vht_oper_chwidth_as_string =
+ "ht_capab=[HT40+]\n"
+ "vht_oper_chwidth=1";
+ }
+ } else {
+ wpa_printf(MSG_ERROR, "Invalid band");
+ return "";
+ }
+
+ std::string he_params_as_string;
+#ifdef CONFIG_IEEE80211AX
+ if (iface_params.hwModeParams.enable80211AX && !is_60Ghz_used) {
+ he_params_as_string = StringPrintf(
+ "ieee80211ax=1\n"
+ "he_oper_chwidth=1\n"
+ "he_su_beamformer=%d\n"
+ "he_su_beamformee=%d\n"
+ "he_mu_beamformer=%d\n"
+ "he_twt_required=%d\n",
+ iface_params.hwModeParams.enableHeSingleUserBeamformer ? 1 : 0,
+ iface_params.hwModeParams.enableHeSingleUserBeamformee ? 1 : 0,
+ iface_params.hwModeParams.enableHeMultiUserBeamformer ? 1 : 0,
+ iface_params.hwModeParams.enableHeTargetWakeTime ? 1 : 0);
+ } else {
+ he_params_as_string = "ieee80211ax=0";
+ }
+#endif /* CONFIG_IEEE80211AX */
+
+#ifdef CONFIG_INTERWORKING
+ std::string access_network_params_as_string;
+ if (nw_params.isMetered) {
+ access_network_params_as_string = StringPrintf(
+ "interworking=1\n"
+ "access_network_type=2\n"); // CHARGEABLE_PUBLIC_NETWORK
+ } else {
+ access_network_params_as_string = StringPrintf(
+ "interworking=0\n");
+ }
+#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"
+ "ctrl_interface=/data/vendor/wifi/hostapd/ctrl\n"
+ // ssid2 signals to hostapd that the value is not a literal value
+ // for use as a SSID. In this case, we're giving it a hex
+ // std::string and hostapd needs to expect that.
+ "ssid2=%s\n"
+ "%s\n"
+ "ieee80211n=%d\n"
+ "ieee80211ac=%d\n"
+ "%s\n"
+ "%s\n"
+ "%s\n"
+ "ignore_broadcast_ssid=%d\n"
+ "wowlan_triggers=any\n"
+#ifdef CONFIG_INTERWORKING
+ "%s\n"
+#endif /* CONFIG_INTERWORKING */
+ "%s\n"
+ "%s\n"
+ "%s\n"
+ "%s\n",
+ iface_params.name.c_str(), ssid_as_string.c_str(),
+ channel_config_as_string.c_str(),
+ iface_params.hwModeParams.enable80211N ? 1 : 0,
+ iface_params.hwModeParams.enable80211AC ? 1 : 0,
+ he_params_as_string.c_str(),
+ hw_mode_as_string.c_str(), ht_cap_vht_oper_chwidth_as_string.c_str(),
+ nw_params.isHidden ? 1 : 0,
+#ifdef CONFIG_INTERWORKING
+ access_network_params_as_string.c_str(),
+#endif /* CONFIG_INTERWORKING */
+ encryption_config_as_string.c_str(),
+ bridge_as_string.c_str(),
+ enable_edmg_as_string.c_str(),
+ edmg_channel_as_string.c_str());
+}
+
+Generation getGeneration(hostapd_hw_modes *current_mode)
+{
+ wpa_printf(MSG_DEBUG, "getGeneration hwmode=%d, ht_enabled=%d,"
+ " vht_enabled=%d, he_supported=%d",
+ current_mode->mode, current_mode->ht_capab != 0,
+ current_mode->vht_capab != 0, current_mode->he_capab->he_supported);
+ switch (current_mode->mode) {
+ case HOSTAPD_MODE_IEEE80211B:
+ return Generation::WIFI_STANDARD_LEGACY;
+ case HOSTAPD_MODE_IEEE80211G:
+ return current_mode->ht_capab == 0 ?
+ Generation::WIFI_STANDARD_LEGACY : Generation::WIFI_STANDARD_11N;
+ case HOSTAPD_MODE_IEEE80211A:
+ if (current_mode->he_capab->he_supported) {
+ return Generation::WIFI_STANDARD_11AX;
+ }
+ return current_mode->vht_capab == 0 ?
+ Generation::WIFI_STANDARD_11N : Generation::WIFI_STANDARD_11AC;
+ case HOSTAPD_MODE_IEEE80211AD:
+ return Generation::WIFI_STANDARD_11AD;
+ default:
+ return Generation::WIFI_STANDARD_UNKNOWN;
+ }
+}
+
+Bandwidth getBandwidth(struct hostapd_config *iconf)
+{
+ wpa_printf(MSG_DEBUG, "getBandwidth %d, isHT=%d, isHT40=%d",
+ iconf->vht_oper_chwidth, iconf->ieee80211n,
+ iconf->secondary_channel);
+ switch (iconf->vht_oper_chwidth) {
+ case CHANWIDTH_80MHZ:
+ return Bandwidth::BANDWIDTH_80;
+ case CHANWIDTH_80P80MHZ:
+ return Bandwidth::BANDWIDTH_80P80;
+ break;
+ case CHANWIDTH_160MHZ:
+ return Bandwidth::BANDWIDTH_160;
+ break;
+ case CHANWIDTH_USE_HT:
+ if (iconf->ieee80211n) {
+ return iconf->secondary_channel != 0 ?
+ Bandwidth::BANDWIDTH_40 : Bandwidth::BANDWIDTH_20;
+ }
+ return Bandwidth::BANDWIDTH_20_NOHT;
+ case CHANWIDTH_2160MHZ:
+ return Bandwidth::BANDWIDTH_2160;
+ case CHANWIDTH_4320MHZ:
+ return Bandwidth::BANDWIDTH_4320;
+ case CHANWIDTH_6480MHZ:
+ return Bandwidth::BANDWIDTH_6480;
+ case CHANWIDTH_8640MHZ:
+ return Bandwidth::BANDWIDTH_8640;
+ default:
+ return Bandwidth::BANDWIDTH_INVALID;
+ }
+}
+
+bool forceStaDisconnection(struct hostapd_data* hapd,
+ const std::vector<uint8_t>& client_address,
+ const uint16_t reason_code) {
+ struct sta_info *sta;
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ int res;
+ res = memcmp(sta->addr, client_address.data(), ETH_ALEN);
+ if (res == 0) {
+ wpa_printf(MSG_INFO, "Force client:" MACSTR " disconnect with reason: %d",
+ MAC2STR(client_address.data()), reason_code);
+ ap_sta_disconnect(hapd, sta, sta->addr, reason_code);
+ return true;
+ }
+ }
+ return false;
+}
+
+// hostapd core functions accept "C" style function pointers, so use global
+// functions to pass to the hostapd core function and store the corresponding
+// std::function methods to be invoked.
+//
+// NOTE: Using the pattern from the vendor HAL (wifi_legacy_hal.cpp).
+//
+// Callback to be invoked once setup is complete
+std::function<void(struct hostapd_data*)> on_setup_complete_internal_callback;
+void onAsyncSetupCompleteCb(void* ctx)
+{
+ struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
+ if (on_setup_complete_internal_callback) {
+ on_setup_complete_internal_callback(iface_hapd);
+ // Invalidate this callback since we don't want this firing
+ // again in single AP mode.
+ if (strlen(iface_hapd->conf->bridge) > 0) {
+ on_setup_complete_internal_callback = nullptr;
+ }
+ }
+}
+
+// Callback to be invoked on hotspot client connection/disconnection
+std::function<void(struct hostapd_data*, const u8 *mac_addr, int authorized,
+ const u8 *p2p_dev_addr)> on_sta_authorized_internal_callback;
+void onAsyncStaAuthorizedCb(void* ctx, const u8 *mac_addr, int authorized,
+ const u8 *p2p_dev_addr)
+{
+ struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
+ if (on_sta_authorized_internal_callback) {
+ on_sta_authorized_internal_callback(iface_hapd, mac_addr,
+ authorized, p2p_dev_addr);
+ }
+}
+
+std::function<void(struct hostapd_data*, int level,
+ enum wpa_msg_type type, const char *txt,
+ size_t len)> on_wpa_msg_internal_callback;
+
+void onAsyncWpaEventCb(void *ctx, int level,
+ enum wpa_msg_type type, const char *txt,
+ size_t len)
+{
+ struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
+ if (on_wpa_msg_internal_callback) {
+ on_wpa_msg_internal_callback(iface_hapd, level,
+ type, txt, len);
+ }
+}
+
+inline ndk::ScopedAStatus createStatus(HostapdStatusCode status_code) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(status_code));
+}
+
+inline ndk::ScopedAStatus createStatusWithMsg(
+ HostapdStatusCode status_code, std::string msg)
+{
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(status_code), msg.c_str());
+}
+
+// Method called by death_notifier_ on client death.
+void onDeath(void* cookie) {
+ wpa_printf(MSG_ERROR, "Client died. Terminating...");
+ eloop_terminate();
+}
+
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace hostapd {
+
+Hostapd::Hostapd(struct hapd_interfaces* interfaces)
+ : interfaces_(interfaces)
+{
+ death_notifier_ = AIBinder_DeathRecipient_new(onDeath);
+}
+
+::ndk::ScopedAStatus Hostapd::addAccessPoint(
+ const IfaceParams& iface_params, const NetworkParams& nw_params)
+{
+ return addAccessPointInternal(iface_params, nw_params);
+}
+
+::ndk::ScopedAStatus Hostapd::removeAccessPoint(const std::string& iface_name)
+{
+ return removeAccessPointInternal(iface_name);
+}
+
+::ndk::ScopedAStatus Hostapd::terminate()
+{
+ wpa_printf(MSG_INFO, "Terminating...");
+ // Clear the callback to avoid IPCThreadState shutdown during the
+ // callback event.
+ callbacks_.clear();
+ eloop_terminate();
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::registerCallback(
+ const std::shared_ptr<IHostapdCallback>& callback)
+{
+ return registerCallbackInternal(callback);
+}
+
+::ndk::ScopedAStatus Hostapd::forceClientDisconnect(
+ const std::string& iface_name, const std::vector<uint8_t>& client_address,
+ Ieee80211ReasonCode reason_code)
+{
+ return forceClientDisconnectInternal(iface_name, client_address, reason_code);
+}
+
+::ndk::ScopedAStatus Hostapd::setDebugParams(DebugLevel level)
+{
+ return setDebugParamsInternal(level);
+}
+
+::ndk::ScopedAStatus Hostapd::addAccessPointInternal(
+ const IfaceParams& iface_params,
+ const NetworkParams& nw_params)
+{
+ int channelParamsSize = iface_params.channelParams.size();
+ if (channelParamsSize == 1) {
+ // Single AP
+ wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
+ iface_params.name.c_str());
+ return addSingleAccessPoint(iface_params, iface_params.channelParams[0],
+ nw_params, "");
+ } else if (channelParamsSize == 2) {
+ // Concurrent APs
+ wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
+ iface_params.name.c_str());
+ return addConcurrentAccessPoints(iface_params, nw_params);
+ }
+ return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
+}
+
+::ndk::ScopedAStatus Hostapd::addConcurrentAccessPoints(
+ const IfaceParams& iface_params, const NetworkParams& nw_params)
+{
+ int channelParamsListSize = iface_params.channelParams.size();
+ // Get available interfaces in bridge
+ std::vector<std::string> managed_interfaces;
+ std::string br_name = StringPrintf(
+ "%s", iface_params.name.c_str());
+ if (!GetInterfacesInBridge(br_name, &managed_interfaces)) {
+ return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
+ "Get interfaces in bridge failed.");
+ }
+ if (managed_interfaces.size() < channelParamsListSize) {
+ return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
+ "Available interfaces less than requested bands");
+ }
+ // start BSS on specified bands
+ for (std::size_t i = 0; i < channelParamsListSize; i ++) {
+ IfaceParams iface_params_new = iface_params;
+ iface_params_new.name = managed_interfaces[i];
+ ndk::ScopedAStatus status = addSingleAccessPoint(
+ iface_params_new, iface_params.channelParams[i], nw_params, br_name);
+ if (!status.isOk()) {
+ 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 ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::addSingleAccessPoint(
+ const IfaceParams& iface_params,
+ const ChannelParams& channelParams,
+ const NetworkParams& nw_params,
+ const std::string br_name)
+{
+ if (hostapd_get_iface(interfaces_, iface_params.name.c_str())) {
+ wpa_printf(
+ MSG_ERROR, "Interface %s already present",
+ iface_params.name.c_str());
+ return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
+ }
+ const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params, br_name);
+ if (conf_params.empty()) {
+ wpa_printf(MSG_ERROR, "Failed to create config params");
+ return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
+ }
+ const auto conf_file_path =
+ WriteHostapdConfig(iface_params.name, conf_params);
+ if (conf_file_path.empty()) {
+ wpa_printf(MSG_ERROR, "Failed to write config file");
+ return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+ }
+ std::string add_iface_param_str = StringPrintf(
+ "%s config=%s", iface_params.name.c_str(),
+ conf_file_path.c_str());
+ std::vector<char> add_iface_param_vec(
+ add_iface_param_str.begin(), add_iface_param_str.end() + 1);
+ if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
+ wpa_printf(
+ MSG_ERROR, "Adding interface %s failed",
+ add_iface_param_str.c_str());
+ return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+ }
+ struct hostapd_data* iface_hapd =
+ hostapd_get_iface(interfaces_, iface_params.name.c_str());
+ WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
+ // Register the setup complete callbacks
+ on_setup_complete_internal_callback =
+ [this](struct hostapd_data* iface_hapd) {
+ wpa_printf(
+ 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
+ // clients.
+ for (const auto& callback : callbacks_) {
+ callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
+ iface_hapd->conf->bridge : iface_hapd->conf->iface);
+ }
+ }
+ };
+
+ // Register for new client connect/disconnect indication.
+ on_sta_authorized_internal_callback =
+ [this](struct hostapd_data* iface_hapd, const u8 *mac_addr,
+ int authorized, const u8 *p2p_dev_addr) {
+ wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
+ MAC2STR(mac_addr),
+ (authorized) ? "Connected" : "Disconnected");
+ ClientInfo info;
+ info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
+ iface_hapd->conf->bridge : iface_hapd->conf->iface;
+ info.apIfaceInstance = iface_hapd->conf->iface;
+ info.clientAddress.assign(mac_addr, mac_addr + ETH_ALEN);
+ info.isConnected = authorized;
+ for (const auto &callback : callbacks_) {
+ callback->onConnectedClientsChanged(info);
+ }
+ };
+
+ // Register for wpa_event which used to get channel switch event
+ on_wpa_msg_internal_callback =
+ [this](struct hostapd_data* iface_hapd, int level,
+ enum wpa_msg_type type, const char *txt,
+ size_t len) {
+ wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
+ if (os_strncmp(txt, AP_EVENT_ENABLED,
+ strlen(AP_EVENT_ENABLED)) == 0 ||
+ os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
+ strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
+ ApInfo info;
+ info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
+ iface_hapd->conf->bridge : iface_hapd->conf->iface,
+ info.apIfaceInstance = iface_hapd->conf->iface;
+ info.freqMhz = iface_hapd->iface->freq;
+ info.bandwidth = getBandwidth(iface_hapd->iconf);
+ info.generation = getGeneration(iface_hapd->iface->current_mode);
+ info.apIfaceInstanceMacAddress.assign(iface_hapd->own_addr,
+ iface_hapd->own_addr + ETH_ALEN);
+ for (const auto &callback : callbacks_) {
+ callback->onApInstanceInfoChanged(info);
+ }
+ } else if (os_strncmp(txt, AP_EVENT_DISABLED, strlen(AP_EVENT_DISABLED)) == 0) {
+ // Invoke the failure callback on all registered clients.
+ for (const auto& callback : callbacks_) {
+ callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
+ iface_hapd->conf->bridge : iface_hapd->conf->iface);
+ }
+ }
+ };
+
+ // Setup callback
+ iface_hapd->setup_complete_cb = onAsyncSetupCompleteCb;
+ iface_hapd->setup_complete_cb_ctx = iface_hapd;
+ iface_hapd->sta_authorized_cb = onAsyncStaAuthorizedCb;
+ iface_hapd->sta_authorized_cb_ctx = iface_hapd;
+ wpa_msg_register_cb(onAsyncWpaEventCb);
+
+ if (hostapd_enable_iface(iface_hapd->iface) < 0) {
+ wpa_printf(
+ MSG_ERROR, "Enabling interface %s failed",
+ iface_params.name.c_str());
+ return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::removeAccessPointInternal(const std::string& iface_name)
+{
+ // interfaces to be removed
+ std::vector<std::string> interfaces;
+ bool is_error = false;
+
+ const auto it = br_interfaces_.find(iface_name);
+ if (it != br_interfaces_.end()) {
+ // In case bridge, remove managed interfaces
+ interfaces = it->second;
+ br_interfaces_.erase(iface_name);
+ } else {
+ // else remove current interface
+ interfaces.push_back(iface_name);
+ }
+
+ for (auto& iface : interfaces) {
+ std::vector<char> remove_iface_param_vec(
+ iface.begin(), iface.end() + 1);
+ if (hostapd_remove_iface(interfaces_, remove_iface_param_vec.data()) < 0) {
+ wpa_printf(MSG_INFO, "Remove interface %s failed", iface.c_str());
+ is_error = true;
+ }
+ }
+ if (is_error) {
+ return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::registerCallbackInternal(
+ const std::shared_ptr<IHostapdCallback>& callback)
+{
+ binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
+ death_notifier_, this /* cookie */);
+ if (status != STATUS_OK) {
+ wpa_printf(
+ MSG_ERROR,
+ "Error registering for death notification for "
+ "hostapd callback object");
+ return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+ }
+ callbacks_.push_back(callback);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::forceClientDisconnectInternal(const std::string& iface_name,
+ const std::vector<uint8_t>& client_address, Ieee80211ReasonCode reason_code)
+{
+ struct hostapd_data *hapd = hostapd_get_iface(interfaces_, iface_name.c_str());
+ bool result;
+ if (!hapd) {
+ for (auto const& iface : br_interfaces_) {
+ if (iface.first == iface_name) {
+ for (auto const& instance : iface.second) {
+ hapd = hostapd_get_iface(interfaces_, instance.c_str());
+ if (hapd) {
+ result = forceStaDisconnection(hapd, client_address,
+ (uint16_t) reason_code);
+ if (result) break;
+ }
+ }
+ }
+ }
+ } else {
+ result = forceStaDisconnection(hapd, client_address, (uint16_t) reason_code);
+ }
+ if (!hapd) {
+ wpa_printf(MSG_ERROR, "Interface %s doesn't exist", iface_name.c_str());
+ return createStatus(HostapdStatusCode::FAILURE_IFACE_UNKNOWN);
+ }
+ if (result) {
+ return ndk::ScopedAStatus::ok();
+ }
+ return createStatus(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN);
+}
+
+::ndk::ScopedAStatus Hostapd::setDebugParamsInternal(DebugLevel level)
+{
+ wpa_debug_level = static_cast<uint32_t>(level);
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace hostapd
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
\ No newline at end of file
diff --git a/hostapd/aidl/hostapd.h b/hostapd/aidl/hostapd.h
new file mode 100644
index 0000000..18a7a23
--- /dev/null
+++ b/hostapd/aidl/hostapd.h
@@ -0,0 +1,94 @@
+/*
+ * aidl interface for wpa_hostapd daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#pragma once
+
+#include <map>
+#include <string>
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/hostapd/BnHostapd.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+#include "utils/wpa_debug.h"
+#include "ap/hostapd.h"
+#include "ap/sta_info.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace hostapd {
+
+/**
+ * Implementation of the hostapd aidl object. This aidl
+ * object is used core for global control operations on
+ * hostapd.
+ */
+class Hostapd : public BnHostapd
+{
+public:
+ Hostapd(hapd_interfaces* interfaces);
+ ~Hostapd() override = default;
+
+ // Aidl methods exposed.
+ ::ndk::ScopedAStatus addAccessPoint(
+ const IfaceParams& iface_params, const NetworkParams& nw_params) override;
+ ::ndk::ScopedAStatus removeAccessPoint(const std::string& iface_name) override;
+ ::ndk::ScopedAStatus terminate() override;
+ ::ndk::ScopedAStatus registerCallback(
+ const std::shared_ptr<IHostapdCallback>& callback) override;
+ ::ndk::ScopedAStatus forceClientDisconnect(
+ const std::string& iface_name,
+ const std::vector<uint8_t>& client_address,
+ Ieee80211ReasonCode reason_code) override;
+ ::ndk::ScopedAStatus setDebugParams(DebugLevel level) override;
+private:
+ // Corresponding worker functions for the AIDL methods.
+ ::ndk::ScopedAStatus addAccessPointInternal(
+ const IfaceParams& iface_params,
+ const NetworkParams& nw_params);
+ ::ndk::ScopedAStatus addSingleAccessPoint(
+ const IfaceParams& IfaceParams,
+ const ChannelParams& channelParams,
+ const NetworkParams& nw_params,
+ std::string br_name);
+ ::ndk::ScopedAStatus addConcurrentAccessPoints(
+ const IfaceParams& IfaceParams,
+ const NetworkParams& nw_params);
+ ::ndk::ScopedAStatus removeAccessPointInternal(const std::string& iface_name);
+ ::ndk::ScopedAStatus registerCallbackInternal(
+ const std::shared_ptr<IHostapdCallback>& callback);
+ ::ndk::ScopedAStatus forceClientDisconnectInternal(
+ const std::string& iface_name,
+ const std::vector<uint8_t>& client_address,
+ Ieee80211ReasonCode reason_code);
+ ::ndk::ScopedAStatus setDebugParamsInternal(DebugLevel level);
+
+ // Raw pointer to the global structure maintained by the core.
+ struct hapd_interfaces* interfaces_;
+ // Callbacks registered.
+ std::vector<std::shared_ptr<IHostapdCallback>> callbacks_;
+ // Death notifier.
+ AIBinder_DeathRecipient* death_notifier_;
+ // Bridge and its managed interfaces.
+ std::map<std::string, std::vector<std::string>> br_interfaces_;
+ DISALLOW_COPY_AND_ASSIGN(Hostapd);
+};
+} // namespace hostapd
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/hostapd/android.config b/hostapd/android.config
index fd3c1a1..3f539dd 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -219,9 +219,9 @@
# either wpa_supplicant or hostapd are run.
CONFIG_NO_RANDOM_POOL=y
-# Add support for Hidl control interface
+# Add support for Aidl control interface
# Only applicable for Android platforms.
-CONFIG_CTRL_IFACE_HIDL=y
+CONFIG_CTRL_IFACE_AIDL=y
# Enable support of Automatic Channel Selection
CONFIG_ACS=y
diff --git a/hostapd/android.hardware.wifi.hostapd.xml b/hostapd/android.hardware.wifi.hostapd.xml
index c688d3e..eb91ee2 100644
--- a/hostapd/android.hardware.wifi.hostapd.xml
+++ b/hostapd/android.hardware.wifi.hostapd.xml
@@ -1,11 +1,6 @@
<manifest version="1.0" type="device">
- <hal format="hidl">
+ <hal format="aidl">
<name>android.hardware.wifi.hostapd</name>
- <transport>hwbinder</transport>
- <version>1.3</version>
- <interface>
- <name>IHostapd</name>
- <instance>default</instance>
- </interface>
+ <fqname>IHostapd/default</fqname>
</hal>
</manifest>
diff --git a/hostapd/hidl/1.3/hidl.cpp b/hostapd/hidl/1.3/hidl.cpp
deleted file mode 100644
index 8481908..0000000
--- a/hostapd/hidl/1.3/hidl.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * hidl interface for wpa_supplicant daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include <hwbinder/IPCThreadState.h>
-#include <hidl/HidlTransportSupport.h>
-
-#include "hostapd.h"
-
-extern "C"
-{
-#include "hidl.h"
-#include "utils/common.h"
-#include "utils/eloop.h"
-#include "utils/includes.h"
-}
-
-using android::hardware::configureRpcThreadpool;
-using android::hardware::IPCThreadState;
-using android::hardware::wifi::hostapd::V1_3::IHostapd;
-using android::hardware::wifi::hostapd::V1_3::implementation::Hostapd;
-
-// This file is a bridge between the hostapd code written in 'C' and the HIDL
-// interface in C++. So, using "C" style static globals here!
-static int hidl_fd = -1;
-static android::sp<IHostapd> service;
-
-void hostapd_hidl_sock_handler(
- int /* sock */, void * /* eloop_ctx */, void * /* sock_ctx */)
-{
- IPCThreadState::self()->handlePolledCommands();
-}
-
-int hostapd_hidl_init(struct hapd_interfaces *interfaces)
-{
- wpa_printf(MSG_DEBUG, "Initing hidl control");
-
- IPCThreadState::self()->setupPolling(&hidl_fd);
- if (hidl_fd < 0)
- goto err;
-
- wpa_printf(MSG_INFO, "Processing hidl events on FD %d", hidl_fd);
- // Look for read events from the hidl socket in the eloop.
- if (eloop_register_read_sock(
- hidl_fd, hostapd_hidl_sock_handler, interfaces, NULL) < 0)
- goto err;
- service = new Hostapd(interfaces);
- if (!service)
- goto err;
- if (service->registerAsService() != android::NO_ERROR)
- goto err;
- return 0;
-err:
- hostapd_hidl_deinit(interfaces);
- return -1;
-}
-
-void hostapd_hidl_deinit(struct hapd_interfaces *interfaces)
-{
- wpa_printf(MSG_INFO, "Deiniting hidl control");
- // Before hidl init, make sure call terminate to clear callback_
- service->terminate();
- eloop_unregister_read_sock(hidl_fd);
- IPCThreadState::shutdown();
- hidl_fd = -1;
- service.clear();
-}
diff --git a/hostapd/hidl/1.3/hidl.h b/hostapd/hidl/1.3/hidl.h
deleted file mode 100644
index 5decf64..0000000
--- a/hostapd/hidl/1.3/hidl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * hidl interface for wpa_supplicant daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef HOSTAPD_HIDL_HIDL_H
-#define HOSTAPD_HIDL_HIDL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif // _cplusplus
-#include "ap/hostapd.h"
-
-/**
- * This is the hidl RPC interface entry point to the hostapd core.
- * This initializes the hidl driver & IHostapd instance.
- */
-int hostapd_hidl_init(struct hapd_interfaces *interfaces);
-void hostapd_hidl_deinit(struct hapd_interfaces *interfaces);
-
-#ifdef __cplusplus
-}
-#endif // _cplusplus
-
-#endif // HOSTAPD_HIDL_HIDL_H
diff --git a/hostapd/hidl/1.3/hidl_return_util.h b/hostapd/hidl/1.3/hidl_return_util.h
deleted file mode 100644
index 6d50348..0000000
--- a/hostapd/hidl/1.3/hidl_return_util.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * hidl interface for wpa_hostapd daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef HIDL_RETURN_UTIL_H_
-#define HIDL_RETURN_UTIL_H_
-
-#include <functional>
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace hostapd {
-namespace V1_3 {
-namespace implementation {
-namespace hidl_return_util {
-
-/**
- * These utility functions are used to invoke a method on the provided
- * HIDL interface object.
- */
-// Use for HIDL methods which return only an instance of HostapdStatus.
-template <typename ObjT, typename WorkFuncT, typename StatusT, typename... Args>
-Return<void> call(
- ObjT* obj, WorkFuncT&& work,
- const std::function<void(const StatusT&)>& hidl_cb, Args&&... args)
-{
- hidl_cb((obj->*work)(std::forward<Args>(args)...));
- return Void();
-}
-} // namespace hidl_return_util
-} // namespace implementation
-} // namespace V1_3
-} // namespace hostapd
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-#endif // HIDL_RETURN_UTIL_H_
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
deleted file mode 100644
index 72efd3f..0000000
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * hidl interface for wpa_hostapd daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-#include <iomanip>
-#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"
-
-extern "C"
-{
-#include "common/wpa_ctrl.h"
-#include "drivers/linux_ioctl.h"
-}
-
-// The HIDL implementation for hostapd creates a hostapd.conf dynamically for
-// each interface. This file can then be used to hook onto the normal config
-// file parsing logic in hostapd code. Helps us to avoid duplication of code
-// in the HIDL interface.
-// TOOD(b/71872409): Add unit tests for this.
-namespace {
-constexpr char kConfFileNameFmt[] = "/data/vendor/wifi/hostapd/hostapd_%s.conf";
-
-using android::base::RemoveFileIfExists;
-using android::base::StringPrintf;
-using android::base::WriteStringToFile;
-using android::hardware::wifi::hostapd::V1_3::IHostapd;
-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)
-{
- const std::string file_path =
- StringPrintf(kConfFileNameFmt, interface_name.c_str());
- if (WriteStringToFile(
- config, file_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- getuid(), getgid())) {
- return file_path;
- }
- // Diagnose failure
- int error = errno;
- wpa_printf(
- MSG_ERROR, "Cannot write hostapd config to %s, error: %s",
- file_path.c_str(), strerror(error));
- struct stat st;
- int result = stat(file_path.c_str(), &st);
- if (result == 0) {
- wpa_printf(
- MSG_ERROR, "hostapd config file uid: %d, gid: %d, mode: %d",
- st.st_uid, st.st_gid, st.st_mode);
- } else {
- wpa_printf(
- MSG_ERROR,
- "Error calling stat() on hostapd config file: %s",
- strerror(errno));
- }
- return "";
-}
-
-/*
- * Get the op_class for a channel/band
- * The logic here is based on Table E-4 in the 802.11 Specification
- */
-int getOpClassForChannel(int channel, int band, bool support11n, bool support11ac) {
- // 2GHz Band
- if ((band & IHostapd::BandMask::BAND_2_GHZ) != 0) {
- if (channel == 14) {
- return 82;
- }
- if (channel >= 1 && channel <= 13) {
- if (!support11n) {
- //20MHz channel
- return 81;
- }
- if (channel <= 9) {
- // HT40 with secondary channel above primary
- return 83;
- }
- // HT40 with secondary channel below primary
- return 84;
- }
- // Error
- return 0;
- }
-
- // 5GHz Band
- if ((band & IHostapd::BandMask::BAND_5_GHZ) != 0) {
- if (support11ac) {
- switch (channel) {
- case 42:
- case 58:
- case 106:
- case 122:
- case 138:
- case 155:
- // 80MHz channel
- return 128;
- case 50:
- case 114:
- // 160MHz channel
- return 129;
- }
- }
-
- if (!support11n) {
- if (channel >= 36 && channel <= 48) {
- return 115;
- }
- if (channel >= 52 && channel <= 64) {
- return 118;
- }
- if (channel >= 100 && channel <= 144) {
- return 121;
- }
- if (channel >= 149 && channel <= 161) {
- return 124;
- }
- if (channel >= 165 && channel <= 169) {
- return 125;
- }
- } else {
- switch (channel) {
- case 36:
- case 44:
- // HT40 with secondary channel above primary
- return 116;
- case 40:
- case 48:
- // HT40 with secondary channel below primary
- return 117;
- case 52:
- case 60:
- // HT40 with secondary channel above primary
- return 119;
- case 56:
- case 64:
- // HT40 with secondary channel below primary
- return 120;
- case 100:
- case 108:
- case 116:
- case 124:
- case 132:
- case 140:
- // HT40 with secondary channel above primary
- return 122;
- case 104:
- case 112:
- case 120:
- case 128:
- case 136:
- case 144:
- // HT40 with secondary channel below primary
- return 123;
- case 149:
- case 157:
- // HT40 with secondary channel above primary
- return 126;
- case 153:
- case 161:
- // HT40 with secondary channel below primary
- return 127;
- }
- }
- // Error
- return 0;
- }
-
- // 6GHz Band
- if ((band & IHostapd::BandMask::BAND_6_GHZ) != 0) {
- // Channels 1, 5. 9, 13, ...
- if ((channel & 0x03) == 0x01) {
- // 20MHz channel
- return 131;
- }
- // Channels 3, 11, 19, 27, ...
- if ((channel & 0x07) == 0x03) {
- // 40MHz channel
- return 132;
- }
- // Channels 7, 23, 39, 55, ...
- if ((channel & 0x0F) == 0x07) {
- // 80MHz channel
- return 133;
- }
- // Channels 15, 47, 69, ...
- if ((channel & 0x1F) == 0x0F) {
- // 160MHz channel
- return 134;
- }
- if (channel == 2) {
- // 20MHz channel
- return 136;
- }
- // Error
- return 0;
- }
-
- if ((band & IHostapd::BandMask::BAND_60_GHZ) != 0) {
- if (1 <= channel && channel <= 8) {
- return 180;
- } else if (9 <= channel && channel <= 15) {
- return 181;
- } else if (17 <= channel && channel <= 22) {
- return 182;
- } else if (25 <= channel && channel <= 29) {
- return 183;
- }
- // Error
- return 0;
- }
-
- return 0;
-}
-
-bool validatePassphrase(int passphrase_len, int min_len, int max_len)
-{
- if (min_len != -1 && passphrase_len < min_len) return false;
- if (max_len != -1 && passphrase_len > max_len) return false;
- return true;
-}
-
-std::string CreateHostapdConfig(
- const android::hardware::wifi::hostapd::V1_3::IHostapd::IfaceParams& iface_params,
- const android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams& channelParams,
- const IHostapd::NetworkParams& nw_params,
- const std::string br_name)
-{
- if (nw_params.V1_2.V1_0.ssid.size() >
- static_cast<uint32_t>(
- IHostapd::ParamSizeLimits::SSID_MAX_LEN_IN_BYTES)) {
- wpa_printf(
- MSG_ERROR, "Invalid SSID size: %zu", nw_params.V1_2.V1_0.ssid.size());
- return "";
- }
-
- // SSID string
- std::stringstream ss;
- ss << std::hex;
- ss << std::setfill('0');
- for (uint8_t b : nw_params.V1_2.V1_0.ssid) {
- ss << std::setw(2) << static_cast<unsigned int>(b);
- }
- const std::string ssid_as_string = ss.str();
-
- // Encryption config string
- uint32_t band = 0;
- band |= channelParams.bandMask;
- bool is_6Ghz_band_only = band == static_cast<uint32_t>(IHostapd::BandMask::BAND_6_GHZ);
- bool is_60Ghz_band_only = band == static_cast<uint32_t>(IHostapd::BandMask::BAND_60_GHZ);
- std::string encryption_config_as_string;
- switch (nw_params.V1_2.encryptionType) {
- case IHostapd::EncryptionType::NONE:
- // no security params
- break;
- case IHostapd::EncryptionType::WPA:
- if (!validatePassphrase(
- nw_params.V1_2.passphrase.size(),
- static_cast<uint32_t>(IHostapd::ParamSizeLimits::
- WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
- static_cast<uint32_t>(IHostapd::ParamSizeLimits::
- WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
- return "";
- }
- encryption_config_as_string = StringPrintf(
- "wpa=3\n"
- "wpa_pairwise=%s\n"
- "wpa_passphrase=%s",
- is_60Ghz_band_only ? "GCMP" : "TKIP CCMP",
- nw_params.V1_2.passphrase.c_str());
- break;
- case IHostapd::EncryptionType::WPA2:
- if (!validatePassphrase(
- nw_params.V1_2.passphrase.size(),
- static_cast<uint32_t>(IHostapd::ParamSizeLimits::
- WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
- static_cast<uint32_t>(IHostapd::ParamSizeLimits::
- WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
- return "";
- }
- encryption_config_as_string = StringPrintf(
- "wpa=2\n"
- "rsn_pairwise=%s\n"
- "wpa_passphrase=%s",
- is_60Ghz_band_only ? "GCMP" : "CCMP",
- nw_params.V1_2.passphrase.c_str());
- break;
- case IHostapd::EncryptionType::WPA3_SAE_TRANSITION:
- if (!validatePassphrase(
- nw_params.V1_2.passphrase.size(),
- static_cast<uint32_t>(IHostapd::ParamSizeLimits::
- WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
- static_cast<uint32_t>(IHostapd::ParamSizeLimits::
- WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
- return "";
- }
- encryption_config_as_string = StringPrintf(
- "wpa=2\n"
- "rsn_pairwise=%s\n"
- "wpa_key_mgmt=WPA-PSK SAE\n"
- "ieee80211w=1\n"
- "sae_require_mfp=1\n"
- "wpa_passphrase=%s\n"
- "sae_password=%s",
- is_60Ghz_band_only ? "GCMP" : "CCMP",
- nw_params.V1_2.passphrase.c_str(),
- nw_params.V1_2.passphrase.c_str());
- break;
- case IHostapd::EncryptionType::WPA3_SAE:
- if (!validatePassphrase(nw_params.V1_2.passphrase.size(), 1, -1)) {
- return "";
- }
- encryption_config_as_string = StringPrintf(
- "wpa=2\n"
- "rsn_pairwise=%s\n"
- "wpa_key_mgmt=SAE\n"
- "ieee80211w=2\n"
- "sae_require_mfp=2\n"
- "sae_pwe=%d\n"
- "sae_password=%s",
- is_60Ghz_band_only ? "GCMP" : "CCMP",
- is_6Ghz_band_only ? 1 : 2,
- nw_params.V1_2.passphrase.c_str());
- break;
- default:
- wpa_printf(MSG_ERROR, "Unknown encryption type");
- return "";
- }
-
- std::string channel_config_as_string;
- bool isFirst = true;
- if (channelParams.enableAcs) {
- std::string freqList_as_string;
- for (const auto &range :
- channelParams.V1_2.acsChannelFreqRangesMhz) {
- if (!isFirst) {
- freqList_as_string += ",";
- }
- isFirst = false;
-
- if (range.start != range.end) {
- freqList_as_string +=
- StringPrintf("%d-%d", range.start, range.end);
- } else {
- freqList_as_string += StringPrintf("%d", range.start);
- }
- }
- channel_config_as_string = StringPrintf(
- "channel=0\n"
- "acs_exclude_dfs=%d\n"
- "freqlist=%s",
- iface_params.V1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs,
- freqList_as_string.c_str());
- } else {
- int op_class = getOpClassForChannel(
- channelParams.channel,
- band,
- iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211N,
- iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
- channel_config_as_string = StringPrintf(
- "channel=%d\n"
- "op_class=%d",
- channelParams.channel, op_class);
- }
-
- std::string hw_mode_as_string;
- std::string ht_cap_vht_oper_chwidth_as_string;
- std::string enable_edmg_as_string;
- std::string edmg_channel_as_string;
- bool is_60Ghz_used = false;
-
- if (((band & IHostapd::BandMask::BAND_60_GHZ) != 0)) {
- hw_mode_as_string = "hw_mode=ad";
- if (iface_params.hwModeParams.enableEdmg) {
- enable_edmg_as_string = "enable_edmg=1";
- edmg_channel_as_string = StringPrintf(
- "edmg_channel=%d",
- channelParams.channel);
- }
- is_60Ghz_used = true;
- } else if ((band & IHostapd::BandMask::BAND_2_GHZ) != 0) {
- if (((band & IHostapd::BandMask::BAND_5_GHZ) != 0)
- || ((band & IHostapd::BandMask::BAND_6_GHZ) != 0)) {
- hw_mode_as_string = "hw_mode=any";
- if (iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC) {
- ht_cap_vht_oper_chwidth_as_string =
- "ht_capab=[HT40+]\n"
- "vht_oper_chwidth=1";
- }
- } else {
- hw_mode_as_string = "hw_mode=g";
- }
- } else if (((band & IHostapd::BandMask::BAND_5_GHZ) != 0)
- || ((band & IHostapd::BandMask::BAND_6_GHZ) != 0)) {
- hw_mode_as_string = "hw_mode=a";
- if (iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC) {
- ht_cap_vht_oper_chwidth_as_string =
- "ht_capab=[HT40+]\n"
- "vht_oper_chwidth=1";
- }
- } else {
- wpa_printf(MSG_ERROR, "Invalid band");
- return "";
- }
-
- std::string he_params_as_string;
-#ifdef CONFIG_IEEE80211AX
- if (iface_params.V1_2.hwModeParams.enable80211AX && !is_60Ghz_used) {
- he_params_as_string = StringPrintf(
- "ieee80211ax=1\n"
- "he_oper_chwidth=1\n"
- "he_su_beamformer=%d\n"
- "he_su_beamformee=%d\n"
- "he_mu_beamformer=%d\n"
- "he_twt_required=%d\n",
- iface_params.V1_2.hwModeParams.enableHeSingleUserBeamformer ? 1 : 0,
- iface_params.V1_2.hwModeParams.enableHeSingleUserBeamformee ? 1 : 0,
- iface_params.V1_2.hwModeParams.enableHeMultiUserBeamformer ? 1 : 0,
- iface_params.V1_2.hwModeParams.enableHeTargetWakeTime ? 1 : 0);
- } else {
- he_params_as_string = "ieee80211ax=0";
- }
-#endif /* CONFIG_IEEE80211AX */
-
-#ifdef CONFIG_INTERWORKING
- std::string access_network_params_as_string;
- if (nw_params.isMetered) {
- access_network_params_as_string = StringPrintf(
- "interworking=1\n"
- "access_network_type=2\n"); // CHARGEABLE_PUBLIC_NETWORK
- } else {
- access_network_params_as_string = StringPrintf(
- "interworking=0\n");
- }
-#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"
- "ctrl_interface=/data/vendor/wifi/hostapd/ctrl\n"
- // ssid2 signals to hostapd that the value is not a literal value
- // for use as a SSID. In this case, we're giving it a hex
- // std::string and hostapd needs to expect that.
- "ssid2=%s\n"
- "%s\n"
- "ieee80211n=%d\n"
- "ieee80211ac=%d\n"
- "%s\n"
- "%s\n"
- "%s\n"
- "ignore_broadcast_ssid=%d\n"
- "wowlan_triggers=any\n"
-#ifdef CONFIG_INTERWORKING
- "%s\n"
-#endif /* CONFIG_INTERWORKING */
- "%s\n"
- "%s\n"
- "%s\n"
- "%s\n",
- iface_params.V1_2.V1_1.V1_0.ifaceName.c_str(), ssid_as_string.c_str(),
- channel_config_as_string.c_str(),
- iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211N ? 1 : 0,
- iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC ? 1 : 0,
- he_params_as_string.c_str(),
- 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(),
-#endif /* CONFIG_INTERWORKING */
- encryption_config_as_string.c_str(),
- bridge_as_string.c_str(),
- enable_edmg_as_string.c_str(),
- edmg_channel_as_string.c_str());
-}
-
-Generation getGeneration(hostapd_hw_modes *current_mode)
-{
- wpa_printf(MSG_DEBUG, "getGeneration hwmode=%d, ht_enabled=%d,"
- " vht_enabled=%d, he_supported=%d",
- current_mode->mode, current_mode->ht_capab != 0,
- current_mode->vht_capab != 0, current_mode->he_capab->he_supported);
- switch (current_mode->mode) {
- case HOSTAPD_MODE_IEEE80211B:
- return Generation::WIFI_STANDARD_LEGACY;
- case HOSTAPD_MODE_IEEE80211G:
- return current_mode->ht_capab == 0 ?
- Generation::WIFI_STANDARD_LEGACY : Generation::WIFI_STANDARD_11N;
- case HOSTAPD_MODE_IEEE80211A:
- if (current_mode->he_capab->he_supported) {
- return Generation::WIFI_STANDARD_11AX;
- }
- return current_mode->vht_capab == 0 ?
- Generation::WIFI_STANDARD_11N : Generation::WIFI_STANDARD_11AC;
- case HOSTAPD_MODE_IEEE80211AD:
- return Generation::WIFI_STANDARD_11AD;
- default:
- return Generation::WIFI_STANDARD_UNKNOWN;
- }
-}
-
-Bandwidth getBandwidth(struct hostapd_config *iconf)
-{
- wpa_printf(MSG_DEBUG, "getBandwidth %d, isHT=%d, isHT40=%d",
- iconf->vht_oper_chwidth, iconf->ieee80211n,
- iconf->secondary_channel);
- switch (iconf->vht_oper_chwidth) {
- case CHANWIDTH_80MHZ:
- return Bandwidth::WIFI_BANDWIDTH_80;
- case CHANWIDTH_80P80MHZ:
- return Bandwidth::WIFI_BANDWIDTH_80P80;
- break;
- case CHANWIDTH_160MHZ:
- return Bandwidth::WIFI_BANDWIDTH_160;
- break;
- case CHANWIDTH_USE_HT:
- if (iconf->ieee80211n) {
- return iconf->secondary_channel != 0 ?
- Bandwidth::WIFI_BANDWIDTH_40 : Bandwidth::WIFI_BANDWIDTH_20;
- }
- return Bandwidth::WIFI_BANDWIDTH_20_NOHT;
- case CHANWIDTH_2160MHZ:
- return Bandwidth::WIFI_BANDWIDTH_2160;
- case CHANWIDTH_4320MHZ:
- return Bandwidth::WIFI_BANDWIDTH_4320;
- case CHANWIDTH_6480MHZ:
- return Bandwidth::WIFI_BANDWIDTH_6480;
- case CHANWIDTH_8640MHZ:
- return Bandwidth::WIFI_BANDWIDTH_8640;
- default:
- return Bandwidth::WIFI_BANDWIDTH_INVALID;
- }
-}
-
-bool forceStaDisconnection(struct hostapd_data* hapd,
- const std::array<uint8_t, 6>& client_address,
- const uint16_t reason_code) {
- struct sta_info *sta;
- for (sta = hapd->sta_list; sta; sta = sta->next) {
- int res;
- res = memcmp(sta->addr, client_address.data(), ETH_ALEN);
- if (res == 0) {
- wpa_printf(MSG_INFO, "Force client:" MACSTR " disconnect with reason: %d",
- MAC2STR(client_address.data()), reason_code);
- ap_sta_disconnect(hapd, sta, sta->addr, reason_code);
- return true;
- }
- }
- return false;
-}
-
-// hostapd core functions accept "C" style function pointers, so use global
-// functions to pass to the hostapd core function and store the corresponding
-// std::function methods to be invoked.
-//
-// NOTE: Using the pattern from the vendor HAL (wifi_legacy_hal.cpp).
-//
-// Callback to be invoked once setup is complete
-std::function<void(struct hostapd_data*)> on_setup_complete_internal_callback;
-void onAsyncSetupCompleteCb(void* ctx)
-{
- struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
- if (on_setup_complete_internal_callback) {
- on_setup_complete_internal_callback(iface_hapd);
- // Invalidate this callback since we don't want this firing
- // again in single AP mode.
- if (strlen(iface_hapd->conf->bridge) > 0) {
- on_setup_complete_internal_callback = nullptr;
- }
- }
-}
-
-// Callback to be invoked on hotspot client connection/disconnection
-std::function<void(struct hostapd_data*, const u8 *mac_addr, int authorized,
- const u8 *p2p_dev_addr)> on_sta_authorized_internal_callback;
-void onAsyncStaAuthorizedCb(void* ctx, const u8 *mac_addr, int authorized,
- const u8 *p2p_dev_addr)
-{
- struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
- if (on_sta_authorized_internal_callback) {
- on_sta_authorized_internal_callback(iface_hapd, mac_addr,
- authorized, p2p_dev_addr);
- }
-}
-
-std::function<void(struct hostapd_data*, int level,
- enum wpa_msg_type type, const char *txt,
- size_t len)> on_wpa_msg_internal_callback;
-
-void onAsyncWpaEventCb(void *ctx, int level,
- enum wpa_msg_type type, const char *txt,
- size_t len)
-{
- struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
- if (on_wpa_msg_internal_callback) {
- on_wpa_msg_internal_callback(iface_hapd, level,
- type, txt, len);
- }
-}
-
-
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace hostapd {
-namespace V1_3 {
-namespace implementation {
-using hidl_return_util::call;
-using namespace android::hardware::wifi::hostapd::V1_0;
-
-Hostapd::Hostapd(struct hapd_interfaces* interfaces)
- : interfaces_(interfaces), death_notifier_(sp<DeathNotifier>::make())
-{}
-
-Return<void> Hostapd::addAccessPoint(
- const V1_0::IHostapd::IfaceParams& iface_params,
- const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb)
-{
- return call(
- this, &Hostapd::addAccessPointInternal, _hidl_cb, iface_params,
- nw_params);
-}
-
-Return<void> Hostapd::addAccessPoint_1_1(
- const V1_1::IHostapd::IfaceParams& iface_params,
- const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb)
-{
- return call(
- this, &Hostapd::addAccessPointInternal_1_1, _hidl_cb, iface_params,
- nw_params);
-}
-
-Return<void> Hostapd::addAccessPoint_1_2(
- const V1_2::IHostapd::IfaceParams& iface_params,
- const V1_2::IHostapd::NetworkParams& nw_params,
- addAccessPoint_1_2_cb _hidl_cb)
-{
- return call(
- this, &Hostapd::addAccessPointInternal_1_2, _hidl_cb, iface_params,
- nw_params);
-}
-
-Return<void> Hostapd::addAccessPoint_1_3(
- const V1_3::IHostapd::IfaceParams& iface_params,
- const V1_3::IHostapd::NetworkParams& nw_params,
- addAccessPoint_1_3_cb _hidl_cb)
-{
- return call(
- this, &Hostapd::addAccessPointInternal_1_3, _hidl_cb, iface_params,
- nw_params);
-}
-
-Return<void> Hostapd::removeAccessPoint(
- const hidl_string& iface_name, removeAccessPoint_cb _hidl_cb)
-{
- return call(
- this, &Hostapd::removeAccessPointInternal, _hidl_cb, iface_name);
-}
-
-Return<void> Hostapd::terminate()
-{
- wpa_printf(MSG_INFO, "Terminating...");
- // Clear the callback to avoid IPCThreadState shutdown during the
- // callback event.
- callbacks_.clear();
- eloop_terminate();
- return Void();
-}
-
-Return<void> Hostapd::registerCallback(
- const sp<V1_1::IHostapdCallback>& callback, registerCallback_cb _hidl_cb)
-{
- return call(
- this, &Hostapd::registerCallbackInternal, _hidl_cb, callback);
-}
-
-Return<void> Hostapd::registerCallback_1_3(
- const sp<V1_3::IHostapdCallback>& callback, registerCallback_1_3_cb _hidl_cb)
-{
- return call(
- this, &Hostapd::registerCallbackInternal_1_3, _hidl_cb, callback);
-}
-
-Return<void> Hostapd::forceClientDisconnect(
- const hidl_string& iface_name, const hidl_array<uint8_t, 6>& client_address,
- V1_2::Ieee80211ReasonCode reason_code, forceClientDisconnect_cb _hidl_cb)
-{
- return call(
- this, &Hostapd::forceClientDisconnectInternal, _hidl_cb, iface_name,
- client_address, reason_code);
-}
-
-Return<void> Hostapd::setDebugParams(
- V1_2::DebugLevel level, setDebugParams_cb _hidl_cb)
-{
- return call(
- this, &Hostapd::setDebugParamsInternal, _hidl_cb, level);
-}
-
-V1_0::HostapdStatus Hostapd::addAccessPointInternal(
- const V1_0::IHostapd::IfaceParams& iface_params,
- const V1_0::IHostapd::NetworkParams& nw_params)
-{
- return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-V1_0::HostapdStatus Hostapd::addAccessPointInternal_1_1(
- const V1_1::IHostapd::IfaceParams& iface_params,
- const V1_1::IHostapd::NetworkParams& nw_params)
-{
- return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_2(
- const V1_2::IHostapd::IfaceParams& iface_params,
- const V1_2::IHostapd::NetworkParams& nw_params) {
- return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_3(
- 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(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_3::IHostapd::IfaceParams iface_params_new = iface_params;
- iface_params_new.V1_2.V1_1.V1_0.ifaceName = managed_interfaces[i];
- V1_2::HostapdStatus status = addSingleAccessPoint(
- iface_params_new, 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_3::IHostapd::IfaceParams& iface_params,
- const V1_3::IHostapd::ChannelParams& channelParams,
- const V1_3::IHostapd::NetworkParams& nw_params,
- const std::string br_name)
-{
- if (hostapd_get_iface(interfaces_, iface_params.V1_2.V1_1.V1_0.ifaceName.c_str())) {
- wpa_printf(
- MSG_ERROR, "Interface %s already present",
- iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
- return {V1_2::HostapdStatusCode::FAILURE_IFACE_EXISTS, ""};
- }
- const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params, br_name);
- if (conf_params.empty()) {
- wpa_printf(MSG_ERROR, "Failed to create config params");
- return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
- }
- const auto conf_file_path =
- WriteHostapdConfig(iface_params.V1_2.V1_1.V1_0.ifaceName, conf_params);
- if (conf_file_path.empty()) {
- wpa_printf(MSG_ERROR, "Failed to write config file");
- return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
- }
- std::string add_iface_param_str = StringPrintf(
- "%s config=%s", iface_params.V1_2.V1_1.V1_0.ifaceName.c_str(),
- conf_file_path.c_str());
- std::vector<char> add_iface_param_vec(
- add_iface_param_str.begin(), add_iface_param_str.end() + 1);
- if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
- wpa_printf(
- MSG_ERROR, "Adding interface %s failed",
- add_iface_param_str.c_str());
- return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
- }
- struct hostapd_data* iface_hapd =
- hostapd_get_iface(interfaces_, iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
- WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
- // Register the setup complete callbacks
- on_setup_complete_internal_callback =
- [this](struct hostapd_data* iface_hapd) {
- wpa_printf(
- 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
- // clients.
- for (const auto& callback : callbacks_) {
- callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
- iface_hapd->conf->bridge : iface_hapd->conf->iface);
- }
- }
- };
-
- // Rgegister for new client connect/disconnect indication.
- on_sta_authorized_internal_callback =
- [this](struct hostapd_data* iface_hapd, const u8 *mac_addr,
- int authorized, const u8 *p2p_dev_addr) {
- wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
- MAC2STR(mac_addr),
- (authorized) ? "Connected" : "Disconnected");
- for (const auto &callback : callbacks_) {
- callback->onConnectedClientsChanged(strlen(iface_hapd->conf->bridge) > 0 ?
- iface_hapd->conf->bridge : iface_hapd->conf->iface,
- iface_hapd->conf->iface, mac_addr, authorized);
- }
- };
-
- // Register for wpa_event which used to get channel switch event
- on_wpa_msg_internal_callback =
- [this](struct hostapd_data* iface_hapd, int level,
- enum wpa_msg_type type, const char *txt,
- size_t len) {
- wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
- if (os_strncmp(txt, AP_EVENT_ENABLED,
- strlen(AP_EVENT_ENABLED)) == 0 ||
- os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
- strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
- for (const auto &callback : callbacks_) {
- callback->onApInstanceInfoChanged(
- 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);
- }
- }
- else if (os_strncmp(txt, AP_EVENT_DISABLED,
- strlen(AP_EVENT_DISABLED)) == 0) {
- // Invoke the failure callback on all registered clients.
- for (const auto& callback : callbacks_) {
- callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
- iface_hapd->conf->bridge : iface_hapd->conf->iface);
- }
- }
- };
-
- // Setup callback
- iface_hapd->setup_complete_cb = onAsyncSetupCompleteCb;
- iface_hapd->setup_complete_cb_ctx = iface_hapd;
- iface_hapd->sta_authorized_cb = onAsyncStaAuthorizedCb;
- iface_hapd->sta_authorized_cb_ctx = iface_hapd;
- wpa_msg_register_cb(onAsyncWpaEventCb);
-
- if (hostapd_enable_iface(iface_hapd->iface) < 0) {
- wpa_printf(
- MSG_ERROR, "Enabling interface %s failed",
- iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
- return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
- }
- return {V1_2::HostapdStatusCode::SUCCESS, ""};
-}
-
-V1_0::HostapdStatus Hostapd::removeAccessPointInternal(const std::string& iface_name)
-{
- // interfaces to be removed
- std::vector<std::string> interfaces;
- bool is_error = false;
-
- const auto it = br_interfaces_.find(iface_name);
- if (it != br_interfaces_.end()) {
- // In case bridge, remove managed interfaces
- interfaces = it->second;
- br_interfaces_.erase(iface_name);
- } else {
- // else remove current interface
- interfaces.push_back(iface_name);
- }
-
- for (auto& iface : interfaces) {
- std::vector<char> remove_iface_param_vec(
- iface.begin(), iface.end() + 1);
- if (hostapd_remove_iface(interfaces_, remove_iface_param_vec.data()) <
- 0) {
- wpa_printf(MSG_INFO, "Remove interface %s failed",
- iface.c_str());
- is_error = true;
- }
- }
- if (is_error) {
- return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
- }
- return {V1_0::HostapdStatusCode::SUCCESS, ""};
-}
-
-V1_0::HostapdStatus Hostapd::registerCallbackInternal(
- const sp<V1_1::IHostapdCallback>& callback)
-{
- return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-V1_2::HostapdStatus Hostapd::registerCallbackInternal_1_3(
- const sp<V1_3::IHostapdCallback>& callback)
-{
- if (!callback->linkToDeath(death_notifier_, 0)) {
- wpa_printf(
- MSG_ERROR,
- "Error registering for death notification for "
- "hostapd callback object");
- return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
- }
- callbacks_.push_back(callback);
- return {V1_2::HostapdStatusCode::SUCCESS, ""};
-}
-
-V1_2::HostapdStatus Hostapd::forceClientDisconnectInternal(const std::string& iface_name,
- const std::array<uint8_t, 6>& client_address, V1_2::Ieee80211ReasonCode reason_code)
-{
- struct hostapd_data *hapd = hostapd_get_iface(interfaces_, iface_name.c_str());
- bool result;
- if (!hapd) {
- for (auto const& iface : br_interfaces_) {
- if (iface.first == iface_name) {
- for (auto const& instance : iface.second) {
- hapd = hostapd_get_iface(interfaces_, instance.c_str());
- if (hapd) {
- result = forceStaDisconnection(hapd, client_address,
- (uint16_t) reason_code);
- if (result) break;
- }
- }
- }
- }
- } else {
- result = forceStaDisconnection(hapd, client_address, (uint16_t) reason_code);
- }
- if (!hapd) {
- wpa_printf(MSG_ERROR, "Interface %s doesn't exist", iface_name.c_str());
- return {V1_2::HostapdStatusCode::FAILURE_IFACE_UNKNOWN, ""};
- }
- if (result) {
- return {V1_2::HostapdStatusCode::SUCCESS, ""};
- }
- return {V1_2::HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, ""};
-}
-
-V1_2::HostapdStatus Hostapd::setDebugParamsInternal(V1_2::DebugLevel level)
-{
- wpa_debug_level = static_cast<uint32_t>(level);
- return {V1_2::HostapdStatusCode::SUCCESS, ""};
-}
-
-} // namespace implementation
-} // namespace V1_3
-} // namespace hostapd
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/hostapd/hidl/1.3/hostapd.h b/hostapd/hidl/1.3/hostapd.h
deleted file mode 100644
index dc45932..0000000
--- a/hostapd/hidl/1.3/hostapd.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * hidl interface for wpa_hostapd daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef HOSTAPD_HIDL_SUPPLICANT_H
-#define HOSTAPD_HIDL_SUPPLICANT_H
-
-#include <string>
-
-#include <android-base/macros.h>
-
-#include <android/hardware/wifi/hostapd/1.3/IHostapd.h>
-#include <android/hardware/wifi/hostapd/1.3/IHostapdCallback.h>
-
-extern "C"
-{
-#include "utils/common.h"
-#include "utils/eloop.h"
-#include "utils/includes.h"
-#include "utils/wpa_debug.h"
-#include "ap/hostapd.h"
-#include "ap/sta_info.h"
-}
-
-class DeathNotifier : public android::hardware::hidl_death_recipient
-{
-public:
- void serviceDied(
- uint64_t /*cookie*/,
- const android::wp<android::hidl::base::V1_0::IBase>
- & /* who */) override
- {
- wpa_printf(MSG_ERROR, "Client died. Terminating...");
- eloop_terminate();
- }
-};
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace hostapd {
-namespace V1_3 {
-namespace implementation {
-using namespace android::hardware::wifi::hostapd::V1_0;
-
-/**
- * Implementation of the hostapd hidl object. This hidl
- * object is used core for global control operations on
- * hostapd.
- */
-class Hostapd : public V1_3::IHostapd
-{
-public:
- Hostapd(hapd_interfaces* interfaces);
- ~Hostapd() override = default;
-
- // Hidl methods exposed.
- Return<void> addAccessPoint(
- const V1_0::IHostapd::IfaceParams& iface_params,
- const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb) override;
- Return<void> addAccessPoint_1_1(
- const V1_1::IHostapd::IfaceParams& iface_params,
- const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb) override;
- Return<void> addAccessPoint_1_2(
- const V1_2::IHostapd::IfaceParams& iface_params,
- const V1_2::IHostapd::NetworkParams& nw_params,
- addAccessPoint_1_2_cb _hidl_cb) override;
- Return<void> addAccessPoint_1_3(
- const V1_3::IHostapd::IfaceParams& iface_params,
- const V1_3::IHostapd::NetworkParams& nw_params,
- addAccessPoint_1_3_cb _hidl_cb) override;
- Return<void> removeAccessPoint(
- const hidl_string& iface_name,
- removeAccessPoint_cb _hidl_cb) override;
- Return<void> terminate() override;
- Return<void> registerCallback(
- const sp<V1_1::IHostapdCallback>& callback,
- registerCallback_cb _hidl_cb) override;
- Return<void> registerCallback_1_3(
- const sp<V1_3::IHostapdCallback>& callback,
- registerCallback_1_3_cb _hidl_cb) override;
- Return<void>forceClientDisconnect(
- const hidl_string& iface_name,
- const hidl_array<uint8_t, 6>& client_address,
- V1_2::Ieee80211ReasonCode reason_code, forceClientDisconnect_cb _hidl_cb) override;
- Return<void> setDebugParams(
- V1_2::DebugLevel level, setDebugParams_cb _hidl_cb) override;
-private:
- // Corresponding worker functions for the HIDL methods.
- V1_0::HostapdStatus addAccessPointInternal(
- const V1_0::IHostapd::IfaceParams& iface_params,
- const V1_0::IHostapd::NetworkParams& nw_params);
- V1_0::HostapdStatus addAccessPointInternal_1_1(
- const V1_1::IHostapd::IfaceParams& IfaceParams,
- const V1_0::IHostapd::NetworkParams& nw_params);
- V1_2::HostapdStatus addAccessPointInternal_1_2(
- 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_3::IHostapd::IfaceParams& IfaceParams,
- const V1_3::IHostapd::ChannelParams& channelParams,
- 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(
- const sp<V1_1::IHostapdCallback>& callback);
- V1_2::HostapdStatus registerCallbackInternal_1_3(
- const sp<V1_3::IHostapdCallback>& callback);
- V1_2::HostapdStatus forceClientDisconnectInternal(
- const std::string& iface_name,
- const std::array<uint8_t, 6>& client_address,
- V1_2::Ieee80211ReasonCode reason_code);
- V1_2::HostapdStatus setDebugParamsInternal(V1_2::DebugLevel level);
- // Raw pointer to the global structure maintained by the core.
- struct hapd_interfaces* interfaces_;
- // Callbacks registered.
- 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
-} // namespace V1_3
-} // namespace hostapd
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // HOSTAPD_HIDL_SUPPLICANT_H
diff --git a/hostapd/hostapd.android.rc b/hostapd/hostapd.android.rc
index 7cc45bd..4b6b17b 100644
--- a/hostapd/hostapd.android.rc
+++ b/hostapd/hostapd.android.rc
@@ -12,10 +12,7 @@
mkdir /data/vendor/wifi/hostapd/sockets 0770 wifi wifi
service hostapd /vendor/bin/hw/hostapd
- interface android.hardware.wifi.hostapd@1.0::IHostapd default
- interface android.hardware.wifi.hostapd@1.1::IHostapd default
- interface android.hardware.wifi.hostapd@1.2::IHostapd default
- interface android.hardware.wifi.hostapd@1.3::IHostapd default
+ interface aidl android.hardware.wifi.hostapd.IHostapd/default
class main
capabilities NET_ADMIN NET_RAW
user wifi
diff --git a/hostapd/main.c b/hostapd/main.c
index 346df48..e59308a 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -30,9 +30,9 @@
#include "config_file.h"
#include "eap_register.h"
#include "ctrl_iface.h"
-#ifdef CONFIG_CTRL_IFACE_HIDL
-#include "hidl.h"
-#endif /* CONFIG_CTRL_IFACE_HIDL */
+#ifdef CONFIG_CTRL_IFACE_AIDL
+#include "aidl.h"
+#endif /* CONFIG_CTRL_IFACE_AIDL */
struct hapd_global {
void **drv_priv;
@@ -766,7 +766,7 @@
}
}
-#ifndef CONFIG_CTRL_IFACE_HIDL
+#ifndef CONFIG_CTRL_IFACE_AIDL
if (optind == argc && interfaces.global_iface_path == NULL &&
num_bss_configs == 0)
usage();
@@ -891,12 +891,12 @@
goto out;
}
-#ifdef CONFIG_CTRL_IFACE_HIDL
- if (hostapd_hidl_init(&interfaces)) {
- wpa_printf(MSG_ERROR, "Failed to initialize HIDL interface");
+#ifdef CONFIG_CTRL_IFACE_AIDL
+ if (hostapd_aidl_init(&interfaces)) {
+ wpa_printf(MSG_ERROR, "Failed to initialize AIDL interface");
goto out;
}
-#endif /* CONFIG_CTRL_IFACE_HIDL */
+#endif /* CONFIG_CTRL_IFACE_AIDL */
hostapd_global_ctrl_iface_init(&interfaces);
if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
@@ -907,9 +907,9 @@
ret = 0;
out:
-#ifdef CONFIG_CTRL_IFACE_HIDL
- hostapd_hidl_deinit(&interfaces);
-#endif /* CONFIG_CTRL_IFACE_HIDL */
+#ifdef CONFIG_CTRL_IFACE_AIDL
+ hostapd_aidl_deinit(&interfaces);
+#endif /* CONFIG_CTRL_IFACE_AIDL */
hostapd_global_ctrl_iface_deinit(&interfaces);
/* Deinitialize all interfaces */
for (i = 0; i < interfaces.count; i++) {
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.cpp b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
index cabcccb..6b554f1 100644
--- a/wpa_supplicant/hidl/1.4/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
@@ -141,12 +141,60 @@
return 0;
}
-static int setP2pCliOptimizedScanFreqsList(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params, int freq)
+static int setScanFreq(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params,
+ int freq, int operating_freq)
{
- if (freq == 2 || freq == 5) {
+ int frequency = operating_freq ? operating_freq : freq;
+ if (disabled_freq(wpa_s, frequency)) {
+ wpa_printf(MSG_ERROR,
+ "P2P: freq %d is not supported for a client.", frequency);
+ return -1;
+ }
+ /*
+ * Allocate memory for frequency array, allocate one extra
+ * slot for the zero-terminator.
+ */
+ params->freqs = (int *) os_calloc(2, sizeof(int));
+ if (params->freqs) {
+ params->freqs[0] = frequency;
+ } else {
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/**
+ * setP2pCliOptimizedScanFreqsList - Fill the frequencies to scan in Scan
+ * parameters.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @params: Pointer to Scan parameters.
+ * @freq: Frequency/Band requested to scan by the application, possible values are,
+ * 0 - All the frequencies - full scan
+ * 2 - Frequencies in 2.4GHz
+ * 5 - Frequencies in 5GHz
+ * - Valid frequency
+ * @operating_freq: Frequency of BSS if found in scan cache
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+static int setP2pCliOptimizedScanFreqsList(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params, int freq, int operating_freq)
+{
+ int ret;
+ /* If BSS is found in scan cache, first scan its operating frequency */
+ if (!wpa_s->p2p_join_scan_count && operating_freq) {
+ ret = setScanFreq(wpa_s, params, freq, operating_freq);
+ if (!ret) {
+ return ret;
+ }
+ }
+
+ /* Empty freq params means scan all the frequencies */
+ if (freq == 0) {
+ return 0;
+ }
+ else if (freq == 2 || freq == 5) {
+ /* Scan the frequencies in the band */
enum hostapd_hw_mode mode;
- int ret;
if (wpa_s->hw.modes == NULL) {
wpa_printf(MSG_DEBUG,
"P2P: Unknown what %dG channels the driver supports.", freq);
@@ -166,21 +214,9 @@
}
return ret;
} else {
- if (disabled_freq(wpa_s, freq)) {
- wpa_printf(MSG_ERROR,
- "P2P: freq %d is not supported for a client.", freq);
- return -1;
- }
- /*
- * Allocate memory for frequency array, allocate one extra
- * slot for the zero-terminator.
- */
- params->freqs = (int *) os_calloc(2, sizeof(int));
- if (params->freqs) {
- params->freqs[0] = freq;
- } else {
- return -ENOMEM;
- }
+ /* Scan the frequency requested by the application */
+ ret = setScanFreq(wpa_s, params, freq, 0);
+ return ret;
}
return 0;
}
@@ -231,6 +267,30 @@
return NULL;
}
+/**
+ * findBssBySsidFromAnyInterface - Fetch a BSS table entry based on SSID and optional BSSID
+ * by iterating through all the interfaces.
+ * @head: Head of Pointer to wpa_supplicant data
+ * @bssid: BSSID, 02:00:00:00:00:00 matches any bssid
+ * @ssid: SSID
+ * @ssid_len: Length of @ssid
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+struct wpa_bss* findBssBySsidFromAnyInterface(
+ struct wpa_supplicant *head, const u8 *bssid,
+ const u8 *ssid, size_t ssid_len)
+{
+ struct wpa_supplicant *wpa_s;
+ struct wpa_bss *bss = NULL;
+ for (wpa_s = head; wpa_s; wpa_s = wpa_s->next) {
+ bss = findBssBySsid(wpa_s, bssid, ssid, ssid_len);
+ if (bss != NULL) {
+ return bss;
+ }
+ }
+ return bss;
+}
+
struct wpa_ssid* addGroupClientNetwork(
struct wpa_supplicant* wpa_s,
uint8_t *group_owner_bssid,
@@ -306,7 +366,7 @@
int joinScanReq(
struct wpa_supplicant* wpa_s,
const std::vector<uint8_t>& ssid,
- int freq)
+ int freq, int operating_freq)
{
int ret;
struct wpa_driver_scan_params params;
@@ -328,17 +388,16 @@
params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
}
- wpa_printf(MSG_DEBUG, "Scan SSID %s for join with frequency %d (reinvoke)",
- wpa_ssid_txt(params.ssids[0].ssid, params.ssids[0].ssid_len), freq);
+ wpa_printf(MSG_DEBUG, "Scan SSID %s for join with frequency %d"
+ "BSS operating_freq from scan cache %d",
+ wpa_ssid_txt(params.ssids[0].ssid, params.ssids[0].ssid_len), freq, operating_freq);
/* Construct an optimized p2p scan channel list */
- if (freq > 0) {
- ret = setP2pCliOptimizedScanFreqsList(wpa_s, ¶ms, freq);
- if (ret < 0) {
- wpa_printf(MSG_ERROR,
- "Failed to set frequency in p2p scan params, error = %d", ret);
- return -1;
- }
+ ret = setP2pCliOptimizedScanFreqsList(wpa_s, ¶ms, freq, operating_freq);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR,
+ "Failed to set frequency in p2p scan params, error = %d", ret);
+ return -1;
}
ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
@@ -1129,6 +1188,7 @@
wpa_s->force_long_sd = 0;
wpas_p2p_stop_find(wpa_s);
wpa_s->parent->p2ps_method_config_any = 0;
+ wpa_bss_flush(wpa_s);
if (wpa_s->global->p2p)
p2p_flush(wpa_s->global->p2p);
return {SupplicantStatusCode::SUCCESS, ""};
@@ -1773,40 +1833,32 @@
wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND before group join.");
wpas_p2p_stop_find(wpa_s);
- struct wpa_bss *bss = findBssBySsid(
- wpa_s, peer_address.data(),
- ssid.data(), ssid.size());
- if (bss != NULL) {
- wpa_printf(MSG_DEBUG, "P2P: Join group with Group Owner " MACSTR,
- MAC2STR(bss->bssid));
- if (0 != joinGroup(wpa_s, bss->bssid, ssid, passphrase)) {
- // no need to notify group join failure here,
- // it will be handled by wpas_p2p_group_add_persistent
- // called in joinGroup.
- return {SupplicantStatusCode::FAILURE_UNKNOWN, "Failed to join a group."};
- }
- return {SupplicantStatusCode::SUCCESS, ""};
- }
-
- wpa_printf(MSG_INFO, "No matched BSS exists, try to find it by scan");
-
if (pending_scan_res_join_callback != NULL) {
wpa_printf(MSG_WARNING, "P2P: Renew scan result callback with new request.");
}
pending_join_scan_callback =
- [wpa_s, ssid, freq]() {
+ [wpa_s, ssid, peer_address, freq]() {
if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
return;
}
- int ret = joinScanReq(wpa_s, ssid, freq);
+ int operating_freq = 0;
+ struct wpa_bss *bss = findBssBySsidFromAnyInterface(
+ wpa_s->global->ifaces, peer_address.data(), ssid.data(), ssid.size());
+ if (bss != NULL) {
+ wpa_printf(MSG_DEBUG, "P2P: Found Group owner " MACSTR "in scan cache",
+ MAC2STR(bss->bssid));
+ operating_freq = bss->freq;
+ }
+
+ int ret = joinScanReq(wpa_s, ssid, freq, operating_freq);
// for BUSY case, the scan might be occupied by WiFi.
// Do not give up immediately, but try again later.
if (-EBUSY == ret) {
- // re-schedule this join scan and don't consume retry count.
- if (pending_scan_res_join_callback) {
- pending_scan_res_join_callback();
- }
+ // re-schedule this join scan
+ eloop_cancel_timeout(joinScanWrapper, wpa_s, NULL);
+ eloop_register_timeout(0, P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS,
+ joinScanWrapper, wpa_s, NULL);
} else if (0 != ret) {
notifyGroupJoinFailure(wpa_s);
pending_scan_res_join_callback = NULL;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 9215794..c68e515 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -6101,7 +6101,25 @@
} else {
if (os_get_random((u8 *) &r, sizeof(r)) < 0)
return -1;
- freq = 2412 + (r % 3) * 25;
+ int possible_2g_freqs[] = {
+ /* operating class 81 */
+ 2412, 2437, 2462,
+ };
+ int possible_2g_freqs_num =
+ sizeof(possible_2g_freqs)/sizeof(possible_2g_freqs[0]);
+ int i;
+ for (i = 0; i < possible_2g_freqs_num; i++, r++) {
+ freq = possible_2g_freqs[r % possible_2g_freqs_num];
+ if (p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
+ break;
+ }
+ }
+
+ if (i >= possible_2g_freqs_num) {
+ wpa_printf(MSG_DEBUG, "P2P: Could not select "
+ "2.4 GHz channel for P2P group");
+ return -1;
+ }
wpa_printf(MSG_DEBUG, "P2P: Use random 2.4 GHz band "
"channel: %d MHz", freq);
}