Merge changes from topic "wifi-p2p-api-create-group"
* changes:
p2p: implementation for addGroup_1_2
p2p: support using pre-defined passphrase for adding a new P2P group
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index b4660c4..585b4a0 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1797,7 +1797,12 @@
}
p2p->ssid_set = 0;
- p2p_random(params->passphrase, p2p->cfg->passphrase_len);
+ if (p2p->passphrase_set) {
+ os_memcpy(params->passphrase, p2p->passphrase, os_strlen(p2p->passphrase));
+ } else {
+ p2p_random(params->passphrase, p2p->cfg->passphrase_len);
+ }
+ p2p->passphrase_set = 0;
return 0;
}
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 6a4d751..a73d99e 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -11,6 +11,7 @@
#include "utils/list.h"
#include "p2p.h"
+#include "ap/ap_config.h"
#define P2P_GO_NEG_CNF_MAX_RETRY_COUNT 1
@@ -358,6 +359,16 @@
int ssid_set;
/**
+ * passphrase - WPA2-Personal passphrase for GO Negotiation (if local end will be GO)
+ */
+ char passphrase[MAX_PASSPHRASE_LEN + 1];
+
+ /**
+ * passphrase_set - Whether passphrase is already set for GO Negotiation
+ */
+ int passphrase_set;
+
+ /**
* Regulatory class for own operational channel
*/
u8 op_reg_class;
diff --git a/wpa_supplicant/hidl/1.2/hidl_manager.h b/wpa_supplicant/hidl/1.2/hidl_manager.h
index 67c2b3b..47b6e7d 100644
--- a/wpa_supplicant/hidl/1.2/hidl_manager.h
+++ b/wpa_supplicant/hidl/1.2/hidl_manager.h
@@ -40,6 +40,7 @@
namespace V1_2 {
namespace implementation {
using namespace android::hardware::wifi::supplicant::V1_2;
+using V1_0::ISupplicantP2pIface;
using V1_0::ISupplicantStaIfaceCallback;
using V1_1::ISupplicant;
using V1_1::ISupplicantStaIface;
diff --git a/wpa_supplicant/hidl/1.2/p2p_iface.cpp b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
index a408b38..80c0205 100644
--- a/wpa_supplicant/hidl/1.2/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
@@ -13,6 +13,7 @@
#include "iface_config_utils.h"
#include "misc_utils.h"
#include "p2p_iface.h"
+#include "sta_network.h"
extern "C"
{
@@ -30,6 +31,7 @@
constexpr char kWfdDeviceInfoSubelemLenHexStr[] = "0006";
using android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface;
+using android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
uint8_t convertHidlMiracastModeToInternal(
ISupplicantP2pIface::MiracastMode mode)
{
@@ -43,6 +45,43 @@
};
WPA_ASSERT(false);
}
+
+/**
+ * Check if the provided ssid is valid or not.
+ *
+ * Returns 1 if valid, 0 otherwise.
+ */
+int isSsidValid(const std::vector<uint8_t>& ssid)
+{
+ if (ssid.size() == 0 ||
+ ssid.size() >
+ static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
+ SSID_MAX_LEN_IN_BYTES)) {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Check if the provided psk passhrase is valid or not.
+ *
+ * Returns 1 if valid, 0 otherwise.
+ */
+int isPskPassphraseValid(const std::string &psk)
+{
+ if (psk.size() <
+ static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
+ PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
+ psk.size() >
+ static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
+ PSK_PASSPHRASE_MAX_LEN_IN_BYTES)) {
+ return 0;
+ }
+ if (has_ctrl_char((u8 *)psk.c_str(), psk.size())) {
+ return 0;
+ }
+ return 1;
+}
} // namespace
namespace android {
@@ -505,6 +544,17 @@
&P2pIface::saveConfigInternal, _hidl_cb);
}
+Return<void> P2pIface::addGroup_1_2(
+ const hidl_vec<uint8_t>& ssid, const hidl_string& passphrase,
+ bool persistent, uint32_t freq, const hidl_array<uint8_t, 6>& peer_address,
+ bool join, addGroup_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::addGroup_1_2Internal, _hidl_cb,
+ ssid, passphrase, persistent, freq, peer_address, join);
+}
+
std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
{
return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -1257,6 +1307,77 @@
return {SupplicantStatusCode::SUCCESS, ""};
}
+SupplicantStatus P2pIface::addGroup_1_2Internal(
+ const std::vector<uint8_t>& ssid, const std::string& passphrase,
+ bool persistent, uint32_t freq, const std::array<uint8_t, 6>& peer_address,
+ bool joinExistingGroup)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ int vht = wpa_s->conf->p2p_go_vht;
+ int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+
+ if (!isSsidValid(ssid)) {
+ return {SupplicantStatusCode::FAILURE_ARGS_INVALID, "SSID is invalid."};
+ }
+
+ if (!isPskPassphraseValid(passphrase)) {
+ return {SupplicantStatusCode::FAILURE_ARGS_INVALID, "passphrase is invalid."};
+ }
+
+ if (joinExistingGroup) {
+ struct wpa_bss *bss = findBssBySsid(
+ wpa_s, peer_address.data(),
+ ssid.data(), ssid.size());
+ if (bss == NULL) {
+ return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN,
+ "No matched BSS found."};
+ }
+
+ // Construct a network for adding group.
+ // Group client follows the persistent attribute of Group Owner.
+ // If joined group is persistent, it adds a persistent network on GroupStarted.
+ struct wpa_ssid *wpa_network = addGroupClientNetwork(
+ wpa_s, bss->bssid, ssid, passphrase);
+ if (wpa_network == NULL) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN,
+ "Cannot construct P2P network."};
+ }
+
+ // this is temporary network only for establishing the connection.
+ wpa_network->temporary = 1;
+
+ if (wpas_p2p_group_add_persistent(
+ wpa_s, wpa_network, 0, 0, 0, 0, ht40, vht,
+ VHT_CHANWIDTH_USE_HT, NULL, 0, 1)) {
+ wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+ return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
+ }
+
+ // Always remove this temporary network at the end.
+ wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+ } else {
+ if (wpa_s->global->p2p == NULL) {
+ return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
+ }
+
+ struct p2p_data *p2p = wpa_s->global->p2p;
+ os_memcpy(p2p->ssid, ssid.data(), ssid.size());
+ p2p->ssid_len = ssid.size();
+ p2p->ssid_set = 1;
+
+ os_memset(p2p->passphrase, 0, sizeof(p2p->passphrase));
+ os_memcpy(p2p->passphrase, passphrase.c_str(), passphrase.length());
+ p2p->passphrase_set = 1;
+
+ if (wpas_p2p_group_add(
+ wpa_s, persistent, freq, 0, ht40, vht,
+ VHT_CHANWIDTH_USE_HT)) {
+ return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+ }
+ }
+ return {SupplicantStatusCode::SUCCESS, ""};
+}
+
/**
* Retrieve the underlying |wpa_supplicant| struct
* pointer for this iface.
@@ -1277,6 +1398,77 @@
return wpa_supplicant_get_iface(wpa_global_, group_ifname.c_str());
}
+struct wpa_ssid* P2pIface::addGroupClientNetwork(
+ struct wpa_supplicant* wpa_s,
+ uint8_t *group_owner_bssid,
+ const std::vector<uint8_t>& ssid,
+ const std::string& passphrase)
+{
+ struct wpa_ssid* wpa_network = wpa_config_add_network(wpa_s->conf);
+ if (!wpa_network) {
+ return NULL;
+ }
+ // set general network defaults
+ wpa_config_set_network_defaults(wpa_network);
+
+ // set P2p network defaults
+ wpa_network->p2p_group = 1;
+ wpa_network->mode = wpa_ssid::wpas_mode::WPAS_MODE_INFRA;
+
+ wpa_network->auth_alg = WPA_AUTH_ALG_OPEN;
+ wpa_network->key_mgmt = WPA_KEY_MGMT_PSK;
+ wpa_network->proto = WPA_PROTO_RSN;
+ wpa_network->pairwise_cipher = WPA_CIPHER_CCMP;
+ wpa_network->group_cipher = WPA_CIPHER_CCMP;
+ wpa_network->disabled = 2;
+
+ // set necessary fields
+ os_memcpy(wpa_network->bssid, group_owner_bssid, ETH_ALEN);
+ wpa_network->bssid_set = 1;
+
+ wpa_network->ssid = (uint8_t *)os_malloc(ssid.size());
+ if (wpa_network->ssid == NULL) {
+ wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+ return NULL;
+ }
+ memcpy(wpa_network->ssid, ssid.data(), ssid.size());
+ wpa_network->ssid_len = ssid.size();
+
+ wpa_network->psk_set = 0;
+ wpa_network->passphrase = dup_binstr(passphrase.c_str(), passphrase.length());
+ if (wpa_network->passphrase == NULL) {
+ wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+ return NULL;
+ }
+ wpa_config_update_psk(wpa_network);
+
+ return wpa_network;
+
+}
+
+/**
+ * findBssBySsid - Fetch a BSS table entry based on SSID and optional BSSID.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID, zero addr matches any bssid
+ * @ssid: SSID
+ * @ssid_len: Length of @ssid
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+struct wpa_bss* P2pIface::findBssBySsid(
+ struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 *ssid, size_t ssid_len)
+{
+ struct wpa_bss *bss;
+ dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ if ((is_zero_ether_addr(bssid) ||
+ os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
+ bss->ssid_len == ssid_len &&
+ os_memcmp(bss->ssid, ssid, ssid_len) == 0)
+ return bss;
+ }
+ return NULL;
+}
+
} // namespace implementation
} // namespace V1_2
} // namespace supplicant
diff --git a/wpa_supplicant/hidl/1.2/p2p_iface.h b/wpa_supplicant/hidl/1.2/p2p_iface.h
index 6842363..a3ccdde 100644
--- a/wpa_supplicant/hidl/1.2/p2p_iface.h
+++ b/wpa_supplicant/hidl/1.2/p2p_iface.h
@@ -15,7 +15,7 @@
#include <android-base/macros.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIface.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantP2pIface.h>
#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.h>
#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetwork.h>
@@ -44,7 +44,7 @@
* object is used for control operations on a specific interface
* controlled by wpa_supplicant.
*/
-class P2pIface : public ISupplicantP2pIface
+class P2pIface : public V1_2::ISupplicantP2pIface
{
public:
P2pIface(struct wpa_global* wpa_global, const char ifname[]);
@@ -187,6 +187,10 @@
const hidl_vec<uint8_t>& select,
reportNfcHandoverInitiation_cb _hidl_cb) override;
Return<void> saveConfig(saveConfig_cb _hidl_cb) override;
+ Return<void> addGroup_1_2(
+ const hidl_vec<uint8_t>& ssid, const hidl_string& passphrase,
+ bool persistent, uint32_t freq, const hidl_array<uint8_t, 6>& peer_address,
+ bool joinExistingGroup, addGroup_1_2_cb _hidl_cb) override;
private:
// Corresponding worker functions for the HIDL methods.
@@ -291,10 +295,22 @@
SupplicantStatus reportNfcHandoverInitiationInternal(
const std::vector<uint8_t>& select);
SupplicantStatus saveConfigInternal();
+ SupplicantStatus addGroup_1_2Internal(
+ const std::vector<uint8_t>& ssid, const std::string& passphrase,
+ bool persistent, uint32_t freq, const std::array<uint8_t, 6>& peer_address,
+ bool joinExistingGroup);
struct wpa_supplicant* retrieveIfacePtr();
struct wpa_supplicant* retrieveGroupIfacePtr(
const std::string& group_ifname);
+ struct wpa_ssid* addGroupClientNetwork(
+ struct wpa_supplicant* wpa_s,
+ uint8_t *group_owner_bssid,
+ const std::vector<uint8_t>& ssid,
+ const std::string& passphrase);
+ struct wpa_bss* findBssBySsid(
+ struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 *ssid, size_t ssid_len);
// Reference to the global wpa_struct. This is assumed to be valid for
// the lifetime of the process.