diff --git a/definition/NetworkManager.json b/definition/NetworkManager.json index dcc4dc20..ccae842b 100644 --- a/definition/NetworkManager.json +++ b/definition/NetworkManager.json @@ -159,7 +159,7 @@ }, "methods": { "SetLogLevel":{ - "summary": "Set Log level for more information. The possible set log level are as follows. \n* `0`: FATAL \n* `1`: ERROR \n* `2`: WARNING \n* `3`: INFO \n* `4`: DEBUG \n", + "summary": "Set Log level for more information. The possible set log level are as follows. \n* `0`: FATAL \n* `1`: ERROR \n* `2`: WARNING \n* `3`: INFO \n* `4`: DEBUG \n if logllevel is debug, it will also enable Gnome Networkmanager debug logs which can be helpful to debug network related issues.", "params": { "type": "object", "properties": { @@ -262,7 +262,7 @@ } }, "GetPrimaryInterface": { - "summary": "Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`.", + "summary": "Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`. if no active network is available, it returns empty string.", "result": { "type": "object", "properties": { @@ -984,6 +984,36 @@ ] } }, + "ActivateKnownSSID":{ + "summary": "Activate given SSID from saved SSIDs. This method will initiate a connect a specified SSID from the list of saved SSIDs. if given ssid not in the list of saved SSIDs, it will return failure.", + "events":{ + "onWiFiStateChange" : "Triggered when Wifi state changes to CONNECTING, CONNECTED .", + "onAddressChange" : "Triggered when an IP Address is assigned or lost", + "onInternetStatusChange" : "Triggered when internet connection state changed" + }, + "params": { + "type": "object", + "properties": { + "ssid": { + "$ref": "#/definitions/ssid" + } + }, + "required": [ + "ssid" + ] + }, + "result": { + "type": "object", + "properties": { + "success":{ + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + } + }, "WiFiConnect":{ "summary": "Initiates request to connect to the specified SSID with the given passphrase. Passphrase can be `null` when the network security is `NONE`. The security mode is decided based on the highest security mode provided by the SSID. Also when called with no arguments, this method attempts to connect to the saved SSID and password. See `AddToKnownSSIDs`.", "events":{ @@ -998,6 +1028,19 @@ "passphrase": { "$ref": "#/definitions/passphrase" }, + "security": { + "$ref": "#/definitions/security" + }, + "bssid": { + "summary": "Specify the BSSID to connect. if specified it will not connect to other BSSID even with the same SSID. It is optional parameter and if not specified, it will connect to the best BSSID available for the SSID.", + "type": "string", + "example": "00:11:22:33:44:55" + }, + "frequency": { + "summary": "Specify the frequency band to connect. `1`: 2.4GHz `2`: 5GHz When not specified it will connect to the best frequency available", + "type": "integer", + "example": 2 + }, "ca_cert": { "summary": "The ca_cert to be used for EAP", "type": "string", @@ -1048,11 +1091,7 @@ "type": "boolean", "example": true } - }, - "required": [ - "ssid", - "passphrase" - ] + } }, "result": { "type": "object", diff --git a/docs/NetworkManagerPlugin.md b/docs/NetworkManagerPlugin.md index 5747075c..61fcd088 100644 --- a/docs/NetworkManagerPlugin.md +++ b/docs/NetworkManagerPlugin.md @@ -94,6 +94,7 @@ NetworkManager interface methods: | [GetKnownSSIDs](#method.GetKnownSSIDs) | Gets list of saved SSIDs | | [AddToKnownSSIDs](#method.AddToKnownSSIDs) | Saves the SSID, passphrase, and security mode for upcoming and future sessions | | [RemoveKnownSSID](#method.RemoveKnownSSID) | Remove given SSID from saved SSIDs | +| [ActivateKnownSSID](#method.ActivateKnownSSID) | Activate given SSID from saved SSIDs | | [WiFiConnect](#method.WiFiConnect) | Initiates request to connect to the specified SSID with the given passphrase | | [WiFiDisconnect](#method.WiFiDisconnect) | Disconnects from the currently connected SSID | | [GetConnectedSSID](#method.GetConnectedSSID) | Returns the connected SSID information | @@ -113,7 +114,7 @@ Set Log level for more information. The possible set log level are as follows. * `2`: WARNING * `3`: INFO * `4`: DEBUG -. + if logllevel is debug, it will also enable Gnome Networkmanager debug logs which can be helpful to debug network related issues. ### Parameters @@ -257,7 +258,7 @@ This method takes no parameters. ## *GetPrimaryInterface [method](#head.Methods)* -Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`. +Gets the primary/default network interface for the device. The active network interface is defined as the one that can make requests to the external network. Returns one of the supported interfaces as per `GetAvailableInterfaces`. if no active network is available, it returns empty string. ### Parameters @@ -1238,6 +1239,54 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#even } ``` + +## *ActivateKnownSSID [method](#head.Methods)* + +Activate given SSID from saved SSIDs. This method will initiate a connect a specified SSID from the list of saved SSIDs. if given ssid not in the list of saved SSIDs, it will return failure. + +Also see: [onWiFiStateChange](#event.onWiFiStateChange), [onAddressChange](#event.onAddressChange), [onInternetStatusChange](#event.onInternetStatusChange) + +### Parameters + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| params | object | | +| params.ssid | string | The WiFi SSID Name | + +### Result + +| Name | Type | Description | +| :-------- | :-------- | :-------- | +| result | object | | +| result.success | boolean | Whether the request succeeded | + +### Example + +#### Request + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "method": "org.rdk.NetworkManager.1.ActivateKnownSSID", + "params": { + "ssid": "myHomeSSID" + } +} +``` + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 42, + "result": { + "success": true + } +} +``` + ## *WiFiConnect [method](#head.Methods)* @@ -1250,8 +1299,11 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) | Name | Type | Description | | :-------- | :-------- | :-------- | | params | object | | -| params.ssid | string | The WiFi SSID Name | -| params.passphrase | string | The access point password | +| params?.ssid | string | *(optional)* The WiFi SSID Name | +| params?.passphrase | string | *(optional)* The access point password | +| params?.security | integer | *(optional)* The security mode. See `GetSupportedSecurityModes` | +| params?.bssid | string | *(optional)* Specify the BSSID to connect. if specified it will not connect to other BSSID even with the same SSID. It is optional parameter and if not specified, it will connect to the best BSSID available for the SSID | +| params?.frequency | integer | *(optional)* Specify the frequency band to connect. `1`: 2.4GHz `2`: 5GHz When not specified it will connect to the best frequency available | | params?.ca_cert | string | *(optional)* The ca_cert to be used for EAP | | params?.client_cert | string | *(optional)* The client_cert to be used for EAP | | params?.private_key | string | *(optional)* The private_key to be used for EAP | @@ -1282,6 +1334,9 @@ Also see: [onWiFiStateChange](#event.onWiFiStateChange) "params": { "ssid": "myHomeSSID", "passphrase": "password", + "security": 2, + "bssid": "00:11:22:33:44:55", + "frequency": 2, "ca_cert": "...", "client_cert": "...", "private_key": "...", diff --git a/interface/INetworkManager.h b/interface/INetworkManager.h index a4488dc5..136a7bed 100644 --- a/interface/INetworkManager.h +++ b/interface/INetworkManager.h @@ -103,6 +103,14 @@ namespace WPEFramework WIFI_SECURITY_EAP /* @text: EAP */, }; + enum WIFIFrequency : uint8_t + { + WIFI_FREQUENCY_NONE /* @text: NONE */, + WIFI_FREQUENCY_2_4_GHZ /* @text: 2.4GHz */, + WIFI_FREQUENCY_5_GHZ /* @text: 5GHz */, + WIFI_FREQUENCY_6_GHZ /* @text: 6GHz */, + }; + struct EXTERNAL WiFiScanResults { string ssid; WIFISecurityMode security; @@ -113,6 +121,8 @@ namespace WPEFramework struct EXTERNAL WiFiConnectTo { string ssid; string passphrase; + string bssid; + WIFIFrequency frequency; WIFISecurityMode security; string ca_cert; string client_cert; @@ -244,6 +254,7 @@ namespace WPEFramework virtual uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) = 0; virtual uint32_t AddToKnownSSIDs(const WiFiConnectTo& ssid /* @in */) = 0; virtual uint32_t RemoveKnownSSID(const string& ssid /* @in */) = 0; + virtual uint32_t ActivateKnownSSID(const string& ssid /* @in */) = 0; virtual uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) = 0; virtual uint32_t WiFiDisconnect(void) = 0; diff --git a/plugin/NetworkManager.h b/plugin/NetworkManager.h index 319476f9..715ac11e 100644 --- a/plugin/NetworkManager.h +++ b/plugin/NetworkManager.h @@ -247,6 +247,7 @@ namespace WPEFramework uint32_t GetKnownSSIDs(const JsonObject& parameters, JsonObject& response); uint32_t AddToKnownSSIDs(const JsonObject& parameters, JsonObject& response); uint32_t RemoveKnownSSID(const JsonObject& parameters, JsonObject& response); + uint32_t ActivateKnownSSID(const JsonObject& parameters, JsonObject& response); uint32_t WiFiConnect(const JsonObject& parameters, JsonObject& response); uint32_t WiFiDisconnect(const JsonObject& parameters, JsonObject& response); uint32_t GetConnectedSSID(const JsonObject& parameters, JsonObject& response); diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 565d7ee9..f20e0231 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -217,6 +217,7 @@ namespace WPEFramework uint32_t GetKnownSSIDs(IStringIterator*& ssids /* @out */) override; uint32_t AddToKnownSSIDs(const WiFiConnectTo& ssid /* @in */) override; uint32_t RemoveKnownSSID(const string& ssid /* @in */) override; + uint32_t ActivateKnownSSID(const string& ssid /* @in */) override; uint32_t WiFiConnect(const WiFiConnectTo& ssid /* @in */) override; uint32_t WiFiDisconnect(void) override; diff --git a/plugin/NetworkManagerJsonRpc.cpp b/plugin/NetworkManagerJsonRpc.cpp index b63a322c..b03b2cdb 100644 --- a/plugin/NetworkManagerJsonRpc.cpp +++ b/plugin/NetworkManagerJsonRpc.cpp @@ -75,6 +75,7 @@ namespace WPEFramework Register("GetKnownSSIDs", &NetworkManager::GetKnownSSIDs, this); Register("AddToKnownSSIDs", &NetworkManager::AddToKnownSSIDs, this); Register("RemoveKnownSSID", &NetworkManager::RemoveKnownSSID, this); + Register("ActivateKnownSSID", &NetworkManager::ActivateKnownSSID, this); Register("WiFiConnect", &NetworkManager::WiFiConnect, this); Register("WiFiDisconnect", &NetworkManager::WiFiDisconnect, this); Register("GetConnectedSSID", &NetworkManager::GetConnectedSSID, this); @@ -112,6 +113,7 @@ namespace WPEFramework Unregister("GetKnownSSIDs"); Unregister("AddToKnownSSIDs"); Unregister("RemoveKnownSSID"); + Unregister("ActivateKnownSSID"); Unregister("WiFiConnect"); Unregister("WiFiDisconnect"); Unregister("GetConnectedSSID"); @@ -766,6 +768,23 @@ namespace WPEFramework returnJson(rc); } + uint32_t NetworkManager::ActivateKnownSSID(const JsonObject& parameters, JsonObject& response) + { + LOG_INPARAM(); + uint32_t rc = Core::ERROR_GENERAL; + string ssid{}; + + if (parameters.HasLabel("ssid")) + ssid = parameters["ssid"].String(); + + if (_networkManager) + rc = _networkManager->ActivateKnownSSID(ssid); + else + rc = Core::ERROR_UNAVAILABLE; + + returnJson(rc); + } + uint32_t NetworkManager::WiFiConnect(const JsonObject& parameters, JsonObject& response) { uint32_t rc = Core::ERROR_GENERAL; @@ -778,7 +797,12 @@ namespace WPEFramework if (parameters.HasLabel("passphrase")) ssid.passphrase = parameters["passphrase"].String(); - + + if (parameters.HasLabel("bssid")) + ssid.bssid = parameters["bssid"].String(); + if (parameters.HasLabel("frequency")) + ssid.frequency = static_cast (parameters["frequency"].Number()); + if (parameters.HasLabel("security")) ssid.security= static_cast (parameters["security"].Number()); diff --git a/plugin/NetworkManagerLogger.cpp b/plugin/NetworkManagerLogger.cpp index 7b631d37..eb6b82b0 100644 --- a/plugin/NetworkManagerLogger.cpp +++ b/plugin/NetworkManagerLogger.cpp @@ -34,7 +34,7 @@ #endif namespace NetworkManagerLogger { - static LogLevel gDefaultLogLevel = INFO_LEVEL; + static LogLevel gDefaultLogLevel = DEBUG_LEVEL; #ifdef USE_RDK_LOGGER diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 90f9b03f..7fb32493 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -730,6 +730,7 @@ namespace WPEFramework bool GnomeNetworkManagerEvents::apToJsonObject(NMAccessPoint *ap, JsonObject& ssidObj) { GBytes *ssid = NULL; + const char *bssid = NULL; int strength = 0; double freq; int security; @@ -748,6 +749,14 @@ namespace WPEFramework free(ssidStr); } ssidObj["ssid"] = ssidString; + bssid = nm_access_point_get_bssid(ap); + if (bssid) { + ssidObj["bssid"] = bssid; + } + else + { + NMLOG_WARNING("BSSID is null for SSID: %s", ssidString.c_str()); + } strength = nm_access_point_get_strength(ap); apFreq = nm_access_point_get_frequency(ap); flags = nm_access_point_get_flags(ap); @@ -773,20 +782,32 @@ namespace WPEFramework NMLOG_ERROR("Not a wifi object "); return; } - JsonArray ssidList = JsonArray(); - NMAccessPoint *ap = nullptr; + const GPtrArray *accessPoints = nm_device_wifi_get_access_points(wifiDevice); + + if (accessPoints == nullptr) { + NMLOG_ERROR("scanning result No access points found !"); + return; + } + + NMLOG_DEBUG("No of AP Available = %d", static_cast(accessPoints->len)); + + if(!_nmEventInstance->doScanNotify) + { + NMLOG_DEBUG("wifi scan result received but notify is false, skipping event notify"); + return; + } + + JsonArray ssidList = JsonArray(); for (guint i = 0; i < accessPoints->len; i++) { - JsonObject ssidObj; - ap = static_cast(accessPoints->pdata[i]); + JsonObject ssidObj{}; + NMAccessPoint *ap = static_cast(accessPoints->pdata[i]); if(GnomeNetworkManagerEvents::apToJsonObject(ap, ssidObj)) ssidList.Add(ssidObj); } - NMLOG_DEBUG("No of AP Available = %d", static_cast(accessPoints->len)); - - if(_nmEventInstance->doScanNotify) { + if(_instance != nullptr) { _nmEventInstance->doScanNotify = false; _instance->ReportAvailableSSIDs(ssidList); } diff --git a/plugin/gnome/NetworkManagerGnomeProxy.cpp b/plugin/gnome/NetworkManagerGnomeProxy.cpp index 85326d63..4a608c09 100644 --- a/plugin/gnome/NetworkManagerGnomeProxy.cpp +++ b/plugin/gnome/NetworkManagerGnomeProxy.cpp @@ -139,7 +139,6 @@ namespace WPEFramework static bool modifyDefaultConnConfig(NMClient *client) { - GError *error = NULL; const GPtrArray *connections = NULL; NMConnection *connection = NULL; std::string hostname{}; @@ -638,7 +637,7 @@ namespace WPEFramework deviceState = nm_device_get_state(device); if(deviceState < NM_DEVICE_STATE_DISCONNECTED) { - NMLOG_WARNING("Device state is not a valid state: (%d)", deviceState); + NMLOG_WARNING("%s state is not a valid state: (%d)", interface.c_str(), deviceState); return Core::ERROR_GENERAL; } @@ -910,6 +909,14 @@ namespace WPEFramework return rc; } + uint32_t NetworkManagerImplementation::ActivateKnownSSID(const string& ssid /* @in */) + { + uint32_t rc = Core::ERROR_GENERAL; + if(wifi->activateKnownSSID(ssid)) + rc = Core::ERROR_NONE; + return rc; + } + uint32_t NetworkManagerImplementation::RemoveKnownSSID(const string& ssid /* @in */) { uint32_t rc = Core::ERROR_GENERAL; @@ -922,6 +929,42 @@ namespace WPEFramework { uint32_t rc = Core::ERROR_GENERAL; + if(!ssid.ssid.empty() && ssid.ssid.size() > 32) + { + NMLOG_WARNING("SSID is invalid"); + return Core::ERROR_NONE; + } + else if(ssid.ssid.empty()) + { + if(_instance != NULL && !_instance->m_lastConnectedSSID.empty()) + { + NMLOG_WARNING("There is no last connected ssid available"); + rc = Core::ERROR_NONE; + } + else + { + NMLOG_WARNING("ssid is empty activating last connected ssid !"); + if(wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID)) + rc = Core::ERROR_NONE; + else + NMLOG_ERROR("activating last connected ssid failed"); + } + + return rc; + } + + // Gnome will not accept passphrase less than 8 char for WPA/WPA2 security + if(!ssid.passphrase.empty() && ssid.passphrase.size() < 8) + { + NMLOG_ERROR("Passphrase is invalid"); + return Core::ERROR_GENERAL; + } + + if(!ssid.bssid.empty() && !nmUtils::isValidBSSID(ssid.bssid)) + { + return Core::ERROR_GENERAL; + } + // Check the last scanning time and if it exceeds 5 sec do a rescanning if(!wifi->isWifiScannedRecently()) { @@ -930,19 +973,8 @@ namespace WPEFramework NMLOG_WARNING("scanning failed but try to connect"); } - if(ssid.ssid.empty() && _instance != NULL) - { - NMLOG_WARNING("ssid is empty activating last connectd ssid !"); - if(wifi->activateKnownConnection(nmUtils::wlanIface(), _instance->m_lastConnectedSSID)) - rc = Core::ERROR_NONE; - } - else if(ssid.ssid.size() <= 32) - { - if(wifi->wifiConnect(ssid)) - rc = Core::ERROR_NONE; - } - else - NMLOG_WARNING("SSID is invalid"); + if(wifi->wifiConnect(ssid)) + rc = Core::ERROR_NONE; return rc; } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index d175b27a..43b535ea 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include "Module.h" @@ -193,6 +194,19 @@ namespace WPEFramework return freq; } + bool nmUtils::isValidBSSID(const std::string& bssid) + { + // Regular expression to match valid BSSID formats (e.g., "00:11:22:33:44:55") + const std::regex bssidRegex("^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$"); + if (!std::regex_match(bssid, bssidRegex)) + { + NMLOG_ERROR("Invalid BSSID format: %s. Expected format is XX:XX:XX:XX:XX:XX where X is a hexadecimal digit.", bssid.c_str()); + return false; + } + + return true; + } + bool nmUtils::caseInsensitiveCompare(const std::string& str1, const std::string& str2) { std::string upperStr1 = str1; diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index b9632d2e..1264b018 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -50,6 +50,7 @@ namespace WPEFramework static bool isInterfaceEnabled(const std::string& interface); static bool writePersistentHostname(const std::string& hostname); static bool readPersistentHostname(std::string& hostname); + static bool isValidBSSID(const std::string& bssid); }; } } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index b6583482..db349d45 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -413,37 +413,69 @@ namespace WPEFramework return m_isSuccess; } - static NMAccessPoint* findMatchingSSID(const GPtrArray* ApList, std::string& ssid) + static NMAccessPoint* findMatchingSSID(const GPtrArray* ApList, Exchange::INetworkManager::WiFiConnectTo& ssidInfo) { NMAccessPoint *AccessPoint = nullptr; - if(ssid.empty()) + if(ssidInfo.ssid.empty()) return nullptr; for (guint i = 0; i < ApList->len; i++) { std::string ssidstr{}; + bool ssidMatch = false; NMAccessPoint *ap = static_cast(g_ptr_array_index(ApList, i)); GBytes *ssidGBytes = nm_access_point_get_ssid(ap); - if(ssidGBytes) + if(ssidGBytes == nullptr) { - char* ssidUtf8 = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssidGBytes, NULL), g_bytes_get_size(ssidGBytes)); - if(ssidUtf8 != nullptr) + NMLOG_WARNING("hidden ssid found, bssid: %s", nm_access_point_get_bssid(ap)); + // TODO remove log or handle hidden ssid case based on bssid matching if ssidInfo.ssid is empty + continue; + } + + char* ssidUtf8 = nm_utils_ssid_to_utf8((const guint8*)g_bytes_get_data(ssidGBytes, NULL), g_bytes_get_size(ssidGBytes)); + if(ssidUtf8 == nullptr) + { + NMLOG_WARNING("Invalid ssid length Error"); + continue; + } + + ssidstr = ssidUtf8; + free(ssidUtf8); + + if(ssidInfo.ssid == ssidstr) + { + NMLOG_INFO("SSID matched: %s", ssidstr.c_str()); + ssidMatch = true; + } + else + { + NMLOG_DEBUG("SSID did not match: expected %s, got %s", ssidInfo.ssid.c_str(), ssidstr.c_str()); + // continue searching other APs in case of multiple APs with same SSID and matching BSSID or frequency + // TODO hidden ssid handling - if ssidInfo.ssid is empty then matching based on bssid ? + continue; + } + + if(!ssidInfo.bssid.empty()) + { + std::string bssidStr = nm_access_point_get_bssid(ap); + if(ssidInfo.bssid == bssidStr) { - ssidstr = ssidUtf8; - if(ssid == ssidstr) - { - AccessPoint = ap; - free(ssidUtf8); - break; - } - // NMLOG_DEBUG("ssid < %s >", ssidstr.c_str()); + NMLOG_DEBUG("BSSID matched: %s", bssidStr.c_str()); + ssidMatch = true; } else - NMLOG_WARNING("Invalid ssid length Error"); - - if(ssidUtf8 != nullptr) - free(ssidUtf8); + { + ssidMatch = false; + NMLOG_WARNING("SSID matched but BSSID did not match: expected %s, got %s", ssidInfo.bssid.c_str(), bssidStr.c_str()); + continue; + } } + + // TODO frequency matching if ssidInfo.frequency ? + // BSSID matching should be sufficient to identify the AP uniquely even if there are multiple APs with same SSID + + if(ssidMatch) + AccessPoint = ap; } return AccessPoint; @@ -650,8 +682,26 @@ namespace WPEFramework g_object_set(G_OBJECT(sWireless), NM_SETTING_WIRELESS_HIDDEN, true, NULL); // hidden = true if(ssid) g_bytes_unref(ssid); - // 'bssid' parameter is used to restrict the connection only to the BSSID - // g_object_set(s_wifi, NM_SETTING_WIRELESS_BSSID, bssid, NULL); + + if(!ssidinfo.bssid.empty()) + g_object_set(sWireless, NM_SETTING_WIRELESS_BSSID, ssidinfo.bssid.c_str(), NULL); + + if(ssidinfo.frequency != Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_NONE) + { + if(ssidinfo.frequency == Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_2_4_GHZ) + { + g_object_set(sWireless, NM_SETTING_WIRELESS_BAND, "bg", NULL); + } + else if(ssidinfo.frequency == Exchange::INetworkManager::WIFIFrequency::WIFI_FREQUENCY_5_GHZ) + { + g_object_set(sWireless, NM_SETTING_WIRELESS_BAND, "a", NULL); + } + else + { + NMLOG_WARNING("invalid frequency value: %d", ssidinfo.frequency); + return false; + } + } NMSettingWirelessSecurity *sSecurity = NULL; switch(ssidinfo.security) @@ -659,7 +709,6 @@ namespace WPEFramework case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_WPA_PSK: case Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE: { - sSecurity = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); nm_connection_add_setting(m_connection, NM_SETTING(sSecurity)); if(Exchange::INetworkManager::WIFISecurityMode::WIFI_SECURITY_SAE == ssidinfo.security) @@ -790,6 +839,86 @@ namespace WPEFramework return true; } + + bool wifiManager::activateKnownSSID(const std::string& ssid) + { + const GPtrArray *allnmConn = NULL; + const char* specificObjPath = "/"; + NMConnection *knownConnection = NULL; + bool ret = false; + + if(!createClientNewConnection()) + return ret; + + m_wifidevice = getWifiDevice(); + if(m_wifidevice == NULL) + { + deleteClientConnection(); + return false; + } + + allnmConn = nm_client_get_connections(m_client); + if(allnmConn == NULL || allnmConn->len == 0) + { + NMLOG_ERROR("No connections found !"); + deleteClientConnection(); + return ret; + } + + for (guint i = 0; i < allnmConn->len; i++) + { + NMConnection *conn = static_cast(g_ptr_array_index(allnmConn, i)); + if(conn == NULL) + continue; + + const char *connId = nm_connection_get_id(NM_CONNECTION(conn)); + if (connId == NULL) { + NMLOG_WARNING("connection id is NULL"); + continue; + } + + const char *connTyp = nm_connection_get_connection_type(NM_CONNECTION(conn)); + if (connTyp == NULL) { + NMLOG_WARNING("connection type is NULL"); + continue; + } + + std::string connTypStr = connTyp; + if(connTypStr != "802-11-wireless") + { + NMLOG_DEBUG("skipping non wifi connection: %s", connId); + continue; + } + + if(ssid == connId) + { + knownConnection = g_object_ref(conn); + NMLOG_DEBUG("connection '%s' exists !", ssid.c_str()); + break; + } + } + + if(knownConnection != NULL) + { + NMLOG_INFO("activating known wifi '%s' connection", ssid.c_str()); + m_isSuccess = false; + m_createNewConnection = false; // no need to create new connection + nm_client_activate_connection_async(m_client, NM_CONNECTION(knownConnection), m_wifidevice, specificObjPath, m_cancellable, wifiConnectCb, this); + wait(m_loop); + deleteClientConnection(); + g_object_unref(knownConnection); + ret = m_isSuccess; + } + else + { + NMLOG_WARNING("'%s' connection not found", ssid.c_str()); + ret = false; + } + + deleteClientConnection(); + return ret; + } + bool wifiManager::activateKnownConnection(std::string iface, std::string knowConnectionID) { const GPtrArray *devConnections = NULL; @@ -944,7 +1073,7 @@ namespace WPEFramework Exchange::INetworkManager::WiFiSSIDInfo apinfo; std::string activeSSID{}; - NMLOG_DEBUG("wifi connect ssid: %s, security %d persist %d", ssidInfoParam.ssid.c_str(), ssidInfoParam.security, ssidInfoParam.persist); + NMLOG_DEBUG("wifi connect ssid: %s, bssid: %s, frequency: %d, security %d, persist %d", ssidInfoParam.ssid.c_str(), ssidInfoParam.bssid.c_str(), ssidInfoParam.frequency, ssidInfoParam.security, ssidInfoParam.persist); Exchange::INetworkManager::WiFiConnectTo ssidInfo = ssidInfoParam; m_isSuccess = false; @@ -979,7 +1108,7 @@ namespace WPEFramework return false; } - AccessPoint = findMatchingSSID(ApList, ssidInfo.ssid); + AccessPoint = findMatchingSSID(ApList, ssidInfo); if(AccessPoint == NULL) { NMLOG_WARNING("SSID '%s' not found !", ssidInfo.ssid.c_str()); diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.h b/plugin/gnome/NetworkManagerGnomeWIFI.h index ca4d1d95..6bd649ea 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.h +++ b/plugin/gnome/NetworkManagerGnomeWIFI.h @@ -52,6 +52,7 @@ namespace WPEFramework bool getWifiState(Exchange::INetworkManager::WiFiState& state); bool wifiDisconnect(); bool activateKnownConnection(std::string iface, std::string knowConnectionID=""); + bool activateKnownSSID(const std::string& ssid); bool wifiConnectedSSIDInfo(Exchange::INetworkManager::WiFiSSIDInfo &ssidinfo); bool wifiConnect(const Exchange::INetworkManager::WiFiConnectTo &ssidInfo); bool wifiScanRequest(std::string ssidReq = ""); diff --git a/plugin/rdk/NetworkManagerRDKProxy.cpp b/plugin/rdk/NetworkManagerRDKProxy.cpp index f2a1e959..e341d5a2 100644 --- a/plugin/rdk/NetworkManagerRDKProxy.cpp +++ b/plugin/rdk/NetworkManagerRDKProxy.cpp @@ -1070,6 +1070,13 @@ const string CIDR_PREFIXES[CIDR_NETMASK_IP_LEN+1] = { return rc; } + uint32_t NetworkManagerImplementation::ActivateKnownSSID(const string& ssid /* @in */) + { + LOG_ENTRY_FUNCTION(); + NMLOG_INFO ("netsrvmgr not support multiple known SSIDs. ActivateKnownSSID not supported !"); + return Core::ERROR_UNAVAILABLE; + } + uint32_t NetworkManagerImplementation::RemoveKnownSSID(const string& ssid /* @in */) { LOG_ENTRY_FUNCTION();