hostapd(hidl): Add helper functions for writing config file
The HIDL interface for hostapd is a wrapper used to create hostapd conf file.
This file will be then be passed to the hostapd core to avoid
duplication of the conf parsing.
Note: This is a port of the methods in HostapdManager.
Bug: 36646171
Test: Compiles with CONFIG_CTRL_IFACE_HIDL=y in android.config
Change-Id: If11e3f795c05f34442566343ae02bc2a385890a6
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 77533d7..b19a74a 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -1109,7 +1109,7 @@
endif
ifeq ($(HOSTAPD_USE_HIDL), y)
LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.0
-LOCAL_SHARED_LIBRARIES += libhidlbase libhidltransport libhwbinder libutils
+LOCAL_SHARED_LIBRARIES += libbase libhidlbase libhidltransport libhwbinder libutils
LOCAL_STATIC_LIBRARIES += libhostapd_hidl
endif
LOCAL_CFLAGS := $(L_CFLAGS)
@@ -1133,6 +1133,7 @@
hidl/$(HIDL_INTERFACE_VERSION)/hostapd.cpp
LOCAL_SHARED_LIBRARIES := \
android.hardware.wifi.hostapd@1.0 \
+ libbase \
libhidlbase \
libhidltransport \
libhwbinder \
diff --git a/hostapd/android.config b/hostapd/android.config
index 3e40aa1..9dfdb28 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -213,4 +213,4 @@
# Add support for Hidl control interface
# Only applicable for Android platforms.
-CONFIG_CTRL_IFACE_HIDL=n
+CONFIG_CTRL_IFACE_HIDL=y
diff --git a/hostapd/hidl/1.0/hostapd.cpp b/hostapd/hidl/1.0/hostapd.cpp
index 8834a82..fc07f06 100644
--- a/hostapd/hidl/1.0/hostapd.cpp
+++ b/hostapd/hidl/1.0/hostapd.cpp
@@ -6,10 +6,170 @@
* 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 <android-base/file.h>
+#include <android-base/stringprintf.h>
#include "hostapd.h"
#include "hidl_return_util.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_0::IHostapd;
+
+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 "";
+}
+
+std::string CreateHostapdConfig(
+ const IHostapd::IfaceParams& iface_params,
+ const IHostapd::NetworkParams& nw_params)
+{
+ if (nw_params.ssid.size() >
+ static_cast<uint32_t>(
+ IHostapd::ParamSizeLimits::SSID_MAX_LEN_IN_BYTES)) {
+ wpa_printf(
+ MSG_ERROR, "Invalid SSID size: %zu", nw_params.ssid.size());
+ return "";
+ }
+ if (nw_params.pskPassphrase.size() <
+ static_cast<uint32_t>(
+ IHostapd::ParamSizeLimits::
+ WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
+ nw_params.pskPassphrase.size() >
+ static_cast<uint32_t>(
+ IHostapd::ParamSizeLimits::
+ WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES)) {
+ wpa_printf(
+ MSG_ERROR, "Invalid psk passphrase size: %zu",
+ nw_params.pskPassphrase.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
+ std::string encryption_config_as_string;
+ switch (nw_params.encryptionType) {
+ case IHostapd::EncryptionType::NONE:
+ // no security params
+ break;
+ case IHostapd::EncryptionType::WPA:
+ encryption_config_as_string = StringPrintf(
+ "wpa=3\n"
+ "wpa_pairwise=TKIP CCMP\n"
+ "wpa_passphrase=%s",
+ nw_params.pskPassphrase.c_str());
+ break;
+ case IHostapd::EncryptionType::WPA2:
+ encryption_config_as_string = StringPrintf(
+ "wpa=2\n"
+ "rsn_pairwise=CCMP\n"
+ "wpa_passphrase=%s",
+ nw_params.pskPassphrase.c_str());
+ break;
+ default:
+ wpa_printf(MSG_ERROR, "Unknown encryption type");
+ return "";
+ }
+
+ std::string channel_config_as_string;
+ if (iface_params.channelParams.enableAcs) {
+ channel_config_as_string = StringPrintf(
+ "channel=0\n"
+ "acs_exclude_dfs=%d",
+ iface_params.channelParams.acsShouldExcludeDfs);
+ } else {
+ channel_config_as_string = StringPrintf(
+ "channel=%d", iface_params.channelParams.channel);
+ }
+
+ // Hw Mode String
+ std::string hw_mode_as_string;
+ switch (iface_params.channelParams.band) {
+ case IHostapd::Band::BAND_2_4_GHZ:
+ hw_mode_as_string = "g";
+ break;
+ case IHostapd::Band::BAND_5_GHZ:
+ hw_mode_as_string = "a";
+ break;
+ case IHostapd::Band::BAND_ANY:
+ hw_mode_as_string = "any";
+ break;
+ default:
+ wpa_printf(MSG_ERROR, "Invalid band");
+ return "";
+ }
+
+ return StringPrintf(
+ "interface=%s\n"
+ "driver=nl80211\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"
+ "hw_mode=%s\n"
+ "ignore_broadcast_ssid=%d\n"
+ "wowlan_triggers=any\n"
+ "%s\n",
+ iface_params.ifaceName.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,
+ hw_mode_as_string.c_str(), nw_params.isHidden ? 1 : 0,
+ encryption_config_as_string.c_str());
+}
+} // namespace
+
namespace android {
namespace hardware {
namespace wifi {