/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "DbusWifiScanner.h" #include "nsWifiAccessPoint.h" #include "mozilla/GUniquePtr.h" #include "mozilla/RefPtr.h" #include "mozilla/GRefPtr.h" namespace mozilla { WifiScannerImpl::WifiScannerImpl() { MOZ_COUNT_CTOR(WifiScannerImpl); } WifiScannerImpl::~WifiScannerImpl() { MOZ_COUNT_DTOR(WifiScannerImpl); } nsresult WifiScannerImpl::GetAccessPointsFromWLAN( AccessPointArray& aAccessPoints) { RefPtr proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync( G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", nullptr, nullptr)); if (!proxy) { return NS_ERROR_FAILURE; } RefPtr result = dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "Devices")); if (!result || !g_variant_is_of_type(result, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) { return NS_ERROR_FAILURE; } gsize num = g_variant_n_children(result); for (gsize i = 0; i < num; i++) { const char* devicePath = g_variant_get_string(g_variant_get_child_value(result, i), nullptr); if (!devicePath || !AddDevice(devicePath, aAccessPoints)) { return NS_ERROR_FAILURE; } } return NS_OK; } bool WifiScannerImpl::AddDevice(const char* aDevicePath, AccessPointArray& aAccessPoints) { RefPtr proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync( G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, "org.freedesktop.NetworkManager", aDevicePath, "org.freedesktop.NetworkManager.Device", nullptr, nullptr)); if (!proxy) { return false; } RefPtr deviceType = dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "DeviceType")); if (!deviceType || !g_variant_is_of_type(deviceType, G_VARIANT_TYPE_UINT32)) { return false; } // http://projects.gnome.org/NetworkManager/developers/api/07/spec-07.html // Refer to NM_DEVICE_TYPE_WIFI under NM_DEVICE_TYPE. const uint32_t NM_DEVICE_TYPE_WIFI = 2; if (g_variant_get_uint32(deviceType) != NM_DEVICE_TYPE_WIFI) { // Don't probe non-wifi devices return true; } proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync( G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, "org.freedesktop.NetworkManager", aDevicePath, "org.freedesktop.NetworkManager.Device.Wireless", nullptr, nullptr)); if (!proxy) { return false; } RefPtr points = dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "AccessPoints")); if (!points || !g_variant_is_of_type(points, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)) { return false; } gsize num = g_variant_n_children(points); for (gsize i = 0; i < num; i++) { const char* ap = g_variant_get_string(g_variant_get_child_value(points, i), nullptr); if (!ap || !AddAPProperties(ap, aAccessPoints)) { return false; } } return true; } bool WifiScannerImpl::AddAPProperties(const char* aApPath, AccessPointArray& aAccessPoints) { RefPtr proxy = dont_AddRef(g_dbus_proxy_new_for_bus_sync( G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, "org.freedesktop.NetworkManager", aApPath, "org.freedesktop.NetworkManager.AccessPoint", nullptr, nullptr)); if (!proxy) { return false; } RefPtr ap = new nsWifiAccessPoint(); RefPtr ssid = dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "Ssid")); if (!ssid || !g_variant_is_of_type(ssid, G_VARIANT_TYPE_BYTESTRING)) { return false; } const uint32_t MAX_SSID_LEN = 32; gsize len = 0; const char* ssidString = static_cast( g_variant_get_fixed_array(ssid, &len, sizeof(guint8))); if (ssidString && len && len <= MAX_SSID_LEN) { ap->setSSID(ssidString, len); } RefPtr hwAddress = dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "HwAddress")); if (!hwAddress || !g_variant_is_of_type(hwAddress, G_VARIANT_TYPE_STRING)) { return false; } GUniquePtr address(g_variant_dup_string(hwAddress, nullptr)); SetMac(address.get(), ap); RefPtr st = dont_AddRef(g_dbus_proxy_get_cached_property(proxy, "Strength")); if (!st || !g_variant_is_of_type(st, G_VARIANT_TYPE_BYTE)) { return false; } uint8_t strength = g_variant_get_byte(st); // in % int signal_strength = (strength / 2) - 100; // strength to dB ap->setSignal(signal_strength); aAccessPoints.AppendElement(ap); return true; } bool WifiScannerImpl::SetMac(char* aHwAddress, nsWifiAccessPoint* aAp) { // hwAddress format is XX:XX:XX:XX:XX:XX. Need to convert to XXXXXX format. const uint32_t MAC_LEN = 6; uint8_t macAddress[MAC_LEN]; char* savedPtr = nullptr; char* token = strtok_r(aHwAddress, ":", &savedPtr); for (unsigned char& macAddres : macAddress) { if (!token) { return false; } macAddres = strtoul(token, nullptr, 16); token = strtok_r(nullptr, ":", &savedPtr); } aAp->setMac(macAddress); return true; } } // namespace mozilla