Compare commits
4 Commits
memsetopsy
...
netgate1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
295e2df7a9 | ||
|
|
93d7ba9a70 | ||
|
|
4dd8c0ca9e | ||
|
|
63da545b28 |
@@ -1160,8 +1160,12 @@ add_library(core STATIC
|
|||||||
|
|
||||||
if (ENABLE_WIFI_SCAN)
|
if (ENABLE_WIFI_SCAN)
|
||||||
# find_package(libiw REQUIRED)
|
# find_package(libiw REQUIRED)
|
||||||
target_compile_definitions(core PRIVATE ENABLE_WIFI_SCAN)
|
target_sources(core PRIVATE internal_network/wifi_scanner.cpp)
|
||||||
target_link_libraries(core PRIVATE iw)
|
if (PLATFORM_LINUX)
|
||||||
|
target_link_libraries(core PRIVATE iw)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
target_sources(core PRIVATE internal_network/wifi_scanner_dummy.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|||||||
@@ -9,6 +9,30 @@
|
|||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
#elif defined(__linux__) || defined(__ANDROID__)
|
||||||
|
#include <cerrno>
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include <net/if_dl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/if_ether.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
@@ -16,14 +40,6 @@
|
|||||||
#include "core/internal_network/emu_net_state.h"
|
#include "core/internal_network/emu_net_state.h"
|
||||||
#include "core/internal_network/network_interface.h"
|
#include "core/internal_network/network_interface.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <iphlpapi.h>
|
|
||||||
#else
|
|
||||||
#include <cerrno>
|
|
||||||
#include <ifaddrs.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Network {
|
namespace Network {
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -71,22 +87,12 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
|||||||
gw = reinterpret_cast<sockaddr_in*>(a->FirstGatewayAddress->Address.lpSockaddr)
|
gw = reinterpret_cast<sockaddr_in*>(a->FirstGatewayAddress->Address.lpSockaddr)
|
||||||
->sin_addr;
|
->sin_addr;
|
||||||
|
|
||||||
HostAdapterKind kind = HostAdapterKind::Ethernet;
|
|
||||||
switch (a->IfType) {
|
|
||||||
case IF_TYPE_IEEE80211: // 802.11 Wi-Fi
|
|
||||||
kind = HostAdapterKind::Wifi;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
kind = HostAdapterKind::Ethernet;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.emplace_back(Network::NetworkInterface{
|
result.emplace_back(Network::NetworkInterface{
|
||||||
.name = Common::UTF16ToUTF8(std::wstring{a->FriendlyName}),
|
.name = Common::UTF16ToUTF8(std::wstring{a->FriendlyName}),
|
||||||
.ip_address = ip,
|
.ip_address = ip,
|
||||||
.subnet_mask = mask,
|
.subnet_mask = mask,
|
||||||
.gateway = gw,
|
.gateway = gw,
|
||||||
.kind = kind
|
.kind = (a->IfType == IF_TYPE_IEEE80211 ? HostAdapterKind::Wifi : HostAdapterKind::Ethernet)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,158 +102,146 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
||||||
|
#if defined(__ANDROID__) || defined(__linux__)
|
||||||
struct ifaddrs* ifaddr = nullptr;
|
struct ifaddrs* ifaddr = nullptr;
|
||||||
|
|
||||||
if (getifaddrs(&ifaddr) != 0) {
|
if (getifaddrs(&ifaddr) != 0) {
|
||||||
LOG_ERROR(Network, "Failed to get network interfaces with getifaddrs: {}",
|
LOG_ERROR(Network, "getifaddrs: {}", std::strerror(errno));
|
||||||
std::strerror(errno));
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Network::NetworkInterface> result;
|
// TODO: This is still horrible, it was worse before (somehow)
|
||||||
|
struct RoutingEntry {
|
||||||
for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
|
std::string iface_name;
|
||||||
if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr) {
|
u32 dest;
|
||||||
continue;
|
u32 gateway;
|
||||||
}
|
u32 flags;
|
||||||
|
};
|
||||||
if (ifa->ifa_addr->sa_family != AF_INET) {
|
std::vector<RoutingEntry> routes{};
|
||||||
continue;
|
#ifdef __ANDROID__
|
||||||
}
|
// Even through Linux based, we can't reliably obtain routing information from there :(
|
||||||
|
|
||||||
if ((ifa->ifa_flags & IFF_UP) == 0 || (ifa->ifa_flags & IFF_LOOPBACK) != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ANDROID
|
|
||||||
// On Android, we can't reliably get gateway info from /proc/net/route
|
|
||||||
// Just use 0 as the gateway address
|
|
||||||
result.emplace_back(Network::NetworkInterface{
|
|
||||||
.name{ifa->ifa_name},
|
|
||||||
.ip_address{std::bit_cast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr},
|
|
||||||
.subnet_mask{std::bit_cast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr},
|
|
||||||
.gateway{in_addr{.s_addr = 0}}
|
|
||||||
});
|
|
||||||
#else
|
#else
|
||||||
u32 gateway{};
|
if (std::ifstream file("/proc/net/route"); file.is_open()) {
|
||||||
|
file.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); //ignore header
|
||||||
std::ifstream file{"/proc/net/route"};
|
|
||||||
if (!file.is_open()) {
|
|
||||||
LOG_ERROR(Network, "Failed to open \"/proc/net/route\"");
|
|
||||||
|
|
||||||
// Solaris defines s_addr as a macro, can't use special C++ shenanigans here
|
|
||||||
in_addr gateway_0;
|
|
||||||
gateway_0.s_addr = gateway;
|
|
||||||
result.emplace_back(Network::NetworkInterface{
|
|
||||||
.name = ifa->ifa_name,
|
|
||||||
.ip_address = std::bit_cast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr,
|
|
||||||
.subnet_mask = std::bit_cast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr,
|
|
||||||
.gateway = gateway_0
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore header
|
|
||||||
file.ignore((std::numeric_limits<std::streamsize>::max)(), '\n');
|
|
||||||
|
|
||||||
bool gateway_found = false;
|
|
||||||
|
|
||||||
for (std::string line; std::getline(file, line);) {
|
for (std::string line; std::getline(file, line);) {
|
||||||
std::istringstream iss{line};
|
std::istringstream iss{line};
|
||||||
|
RoutingEntry info{};
|
||||||
std::string iface_name;
|
iss >> info.iface_name >> std::hex
|
||||||
iss >> iface_name;
|
>> info.dest >> info.gateway >> info.flags;
|
||||||
if (iface_name != ifa->ifa_name) {
|
routes.emplace_back(info);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
iss >> std::hex;
|
|
||||||
|
|
||||||
u32 dest{};
|
|
||||||
iss >> dest;
|
|
||||||
if (dest != 0) {
|
|
||||||
// not the default route
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
iss >> gateway;
|
|
||||||
|
|
||||||
u16 flags{};
|
|
||||||
iss >> flags;
|
|
||||||
|
|
||||||
// flag RTF_GATEWAY (defined in <linux/route.h>)
|
|
||||||
if ((flags & 0x2) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
gateway_found = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
if (!gateway_found) {
|
LOG_WARNING(Network, "\"/proc/net/route\" not found - using gateway 0");
|
||||||
gateway = 0;
|
}
|
||||||
}
|
#endif
|
||||||
|
std::vector<Network::NetworkInterface> ifaces;
|
||||||
in_addr gateway_0;
|
for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
|
||||||
gateway_0.s_addr = gateway;
|
if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr /* Have a netmask and address */
|
||||||
result.emplace_back(Network::NetworkInterface{
|
|| ifa->ifa_addr->sa_family != AF_INET /* Must be of kind AF_INET */
|
||||||
|
|| (ifa->ifa_flags & IFF_UP) == 0 || (ifa->ifa_flags & IFF_LOOPBACK) != 0) /* Not loopback */
|
||||||
|
continue;
|
||||||
|
// Just use 0 as the gateway address if not found OR routes are empty :)
|
||||||
|
auto const it = std::ranges::find_if(routes, [&ifa](auto const& e) {
|
||||||
|
return e.iface_name == ifa->ifa_name
|
||||||
|
&& e.dest == 0 // not the default route
|
||||||
|
&& (e.flags & 0x02) != 0; // flag RTF_GATEWAY (defined in <linux/route.h>)
|
||||||
|
});
|
||||||
|
in_addr gw; // Solaris defines s_addr as a macro, can't use special C++ shenanigans here
|
||||||
|
gw.s_addr = it != routes.end() ? it->gateway : 0;
|
||||||
|
ifaces.emplace_back(Network::NetworkInterface{
|
||||||
.name = ifa->ifa_name,
|
.name = ifa->ifa_name,
|
||||||
.ip_address = std::bit_cast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr,
|
.ip_address = std::bit_cast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr,
|
||||||
.subnet_mask = std::bit_cast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr,
|
.subnet_mask = std::bit_cast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr,
|
||||||
.gateway = gateway_0
|
.gateway = gw
|
||||||
});
|
});
|
||||||
#endif // ANDROID
|
}
|
||||||
|
freeifaddrs(ifaddr);
|
||||||
|
return ifaces;
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
std::vector<Network::NetworkInterface> ifaces;
|
||||||
|
int fd = ::socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
|
||||||
|
if (fd < 0) {
|
||||||
|
LOG_ERROR(Network, "socket: {}", std::strerror(errno));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
freeifaddrs(ifaddr);
|
size_t bufsz = 0;
|
||||||
return result;
|
int mib[6] = {
|
||||||
|
CTL_NET, PF_ROUTE, 0,
|
||||||
|
AF_UNSPEC, NET_RT_IFLIST, 0
|
||||||
|
};
|
||||||
|
if (::sysctl(mib, sizeof(mib) / sizeof(mib[0]), nullptr, &bufsz, nullptr, 0) < 0) {
|
||||||
|
LOG_ERROR(Network, "sysctl.1: {}", std::strerror(errno));
|
||||||
|
::close(fd);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::vector<char> buf(bufsz);
|
||||||
|
if (::sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf.data(), &bufsz, nullptr, 0) < 0) {
|
||||||
|
LOG_ERROR(Network, "sysctl.2: {}", std::strerror(errno));
|
||||||
|
::close(fd);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rt_msghdr const *rtm = NULL;
|
||||||
|
for (char *next = buf.data(); next < buf.data() + bufsz; next += rtm->rtm_msglen) {
|
||||||
|
rtm = (struct rt_msghdr const *)next;
|
||||||
|
if (rtm->rtm_type == RTM_IFINFO) {
|
||||||
|
struct if_msghdr const* ifm = (struct if_msghdr const *)rtm;
|
||||||
|
size_t msglen = rtm->rtm_msglen - sizeof(*ifm);
|
||||||
|
char const* p = (char const*)(ifm + 1);
|
||||||
|
|
||||||
|
Network::NetworkInterface iface{};
|
||||||
|
for (size_t i = 0; i < RTAX_MAX; i++)
|
||||||
|
if ((ifm->ifm_addrs & (1 << i)) != 0) {
|
||||||
|
struct sockaddr const* sa = reinterpret_cast<struct sockaddr const*>(p);
|
||||||
|
if (msglen == 0 || msglen < SA_SIZE(sa))
|
||||||
|
break;
|
||||||
|
if (i == RTA_NETMASK && sa->sa_family == AF_LINK) {
|
||||||
|
size_t namelen = 0;
|
||||||
|
struct sockaddr_dl const* sdl = reinterpret_cast<struct sockaddr_dl const*>(sa);
|
||||||
|
::link_ntoa_r(sdl, nullptr, &namelen);
|
||||||
|
iface.name = std::string(namelen, ' ');
|
||||||
|
::link_ntoa_r(sdl, iface.name.data(), &namelen);
|
||||||
|
std::memcpy(&iface.ip_address, sa, sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
msglen -= SA_SIZE(sa);
|
||||||
|
p += SA_SIZE(sa);
|
||||||
|
}
|
||||||
|
ifaces.push_back(iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::close(fd);
|
||||||
|
return ifaces;
|
||||||
|
#else
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
std::optional<Network::NetworkInterface> GetSelectedNetworkInterface() {
|
std::optional<Network::NetworkInterface> GetSelectedNetworkInterface() {
|
||||||
|
auto const& sel_if = Settings::values.network_interface.GetValue();
|
||||||
const auto& selected_network_interface = Settings::values.network_interface.GetValue();
|
if (auto const ifaces = Network::GetAvailableNetworkInterfaces(); ifaces.size() > 0) {
|
||||||
const auto network_interfaces = Network::GetAvailableNetworkInterfaces();
|
if (sel_if.empty())
|
||||||
if (network_interfaces.empty()) {
|
return ifaces[0];
|
||||||
LOG_ERROR(Network, "GetAvailableNetworkInterfaces returned no interfaces");
|
if (auto const res = std::ranges::find_if(ifaces, [&sel_if](const auto& iface) {
|
||||||
return std::nullopt;
|
return iface.name == sel_if;
|
||||||
}
|
}); res != ifaces.end())
|
||||||
|
return *res;
|
||||||
#ifdef __ANDROID__
|
|
||||||
if (selected_network_interface.empty()) {
|
|
||||||
return network_interfaces[0];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const auto res =
|
|
||||||
std::ranges::find_if(network_interfaces, [&selected_network_interface](const auto& iface) {
|
|
||||||
return iface.name == selected_network_interface;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res == network_interfaces.end()) {
|
|
||||||
// Only print the error once to avoid log spam
|
// Only print the error once to avoid log spam
|
||||||
static bool print_error = true;
|
static bool print_error = true;
|
||||||
if (print_error) {
|
if (print_error) {
|
||||||
LOG_ERROR(Network, "Couldn't find selected interface \"{}\"",
|
LOG_WARNING(Network, "Couldn't find interface \"{}\"", sel_if);
|
||||||
selected_network_interface);
|
|
||||||
print_error = false;
|
print_error = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
LOG_WARNING(Network, "No interfaces");
|
||||||
return *res;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectFirstNetworkInterface() {
|
void SelectFirstNetworkInterface() {
|
||||||
const auto network_interfaces = Network::GetAvailableNetworkInterfaces();
|
if (auto const ifaces = Network::GetAvailableNetworkInterfaces(); ifaces.size() > 0)
|
||||||
|
Settings::values.network_interface.SetValue(ifaces[0].name);
|
||||||
if (network_interfaces.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings::values.network_interface.SetValue(network_interfaces[0].name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Network
|
} // namespace Network
|
||||||
|
|||||||
@@ -6,11 +6,6 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
|
||||||
#include "core/internal_network/wifi_scanner.h"
|
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@@ -18,16 +13,30 @@ using namespace std::chrono_literals;
|
|||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma comment(lib, "wlanapi.lib")
|
#pragma comment(lib, "wlanapi.lib")
|
||||||
#endif
|
#endif
|
||||||
|
#elif defined(__linux__) && !defined(__ANDROID__)
|
||||||
|
#include <iwlib.h>
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/ethernet.h>
|
||||||
|
#include <net80211/ieee80211_ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/internal_network/network_interface.h"
|
||||||
|
#include "core/internal_network/wifi_scanner.h"
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
namespace Network {
|
namespace Network {
|
||||||
#ifdef ENABLE_WIFI_SCAN
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static u8 QualityToPercent(DWORD q) {
|
static u8 QualityToPercent(DWORD q) {
|
||||||
return static_cast<u8>(q);
|
return u8(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<Network::ScanData> ScanWifiWin(std::chrono::milliseconds deadline) {
|
std::vector<Network::ScanData> ScanWifiNetworks(std::chrono::milliseconds deadline) {
|
||||||
std::vector<Network::ScanData> out;
|
std::vector<Network::ScanData> out;
|
||||||
|
|
||||||
HANDLE hClient{};
|
HANDLE hClient{};
|
||||||
@@ -85,38 +94,16 @@ static std::vector<Network::ScanData> ScanWifiWin(std::chrono::milliseconds dead
|
|||||||
WlanCloseHandle(hClient, nullptr);
|
WlanCloseHandle(hClient, nullptr);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
#endif /* _WIN32 */
|
#elif defined(__linux__) && !defined(__ANDROID__)
|
||||||
|
|
||||||
#if defined(__linux__) && !defined(_WIN32) && !defined(ANDROID)
|
|
||||||
#include <iwlib.h>
|
|
||||||
|
|
||||||
static u8 QualityToPercent(const iwrange& r, const wireless_scan* ws) {
|
static u8 QualityToPercent(const iwrange& r, const wireless_scan* ws) {
|
||||||
const iw_quality qual = ws->stats.qual;
|
const iw_quality qual = ws->stats.qual;
|
||||||
const int lvl = qual.level;
|
const int lvl = qual.level;
|
||||||
const int max = r.max_qual.level ? r.max_qual.level : 100;
|
const int max = r.max_qual.level ? r.max_qual.level : 100;
|
||||||
return static_cast<u8>(std::clamp(100 * lvl / max, 0, 100));
|
return u8(std::clamp(100 * lvl / max, 0, 100));
|
||||||
}
|
|
||||||
|
|
||||||
static int wifi_callback(int skfd, char* ifname, char* args[], int count)
|
|
||||||
{
|
|
||||||
iwrange range;
|
|
||||||
|
|
||||||
int res = iw_get_range_info(skfd, ifname, &range);
|
|
||||||
|
|
||||||
LOG_INFO(Network, "ifname {} returned {} on iw_get_range_info", ifname, res);
|
|
||||||
|
|
||||||
if (res >= 0) {
|
|
||||||
strncpy(args[0], ifname, IFNAMSIZ - 1);
|
|
||||||
args[0][IFNAMSIZ - 1] = 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(crueter, Maufeat): Check if driver supports wireless extensions, fallback to nl80211 if not
|
// TODO(crueter, Maufeat): Check if driver supports wireless extensions, fallback to nl80211 if not
|
||||||
static std::vector<Network::ScanData> ScanWifiLinux(std::chrono::milliseconds deadline) {
|
std::vector<Network::ScanData> ScanWifiNetworks(std::chrono::milliseconds deadline) {
|
||||||
std::vector<Network::ScanData> out;
|
std::vector<Network::ScanData> out;
|
||||||
int sock = iw_sockets_open();
|
int sock = iw_sockets_open();
|
||||||
if (sock < 0) {
|
if (sock < 0) {
|
||||||
@@ -127,7 +114,17 @@ static std::vector<Network::ScanData> ScanWifiLinux(std::chrono::milliseconds de
|
|||||||
char ifname[IFNAMSIZ] = {0};
|
char ifname[IFNAMSIZ] = {0};
|
||||||
char *args[1] = {ifname};
|
char *args[1] = {ifname};
|
||||||
|
|
||||||
iw_enum_devices(sock, &wifi_callback, args, 0);
|
iw_enum_devices(sock, [](int skfd, char* ifname, char* args[], int count) -> int {
|
||||||
|
iwrange range;
|
||||||
|
int res = iw_get_range_info(skfd, ifname, &range);
|
||||||
|
LOG_INFO(Network, "ifname {} returned {} on iw_get_range_info", ifname, res);
|
||||||
|
if (res >= 0) {
|
||||||
|
strncpy(args[0], ifname, IFNAMSIZ - 1);
|
||||||
|
args[0][IFNAMSIZ - 1] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}, args, 0);
|
||||||
|
|
||||||
if (strlen(ifname) == 0) {
|
if (strlen(ifname) == 0) {
|
||||||
LOG_WARNING(Network, "No wireless interface found");
|
LOG_WARNING(Network, "No wireless interface found");
|
||||||
@@ -153,20 +150,19 @@ static std::vector<Network::ScanData> ScanWifiLinux(std::chrono::milliseconds de
|
|||||||
|
|
||||||
out.clear();
|
out.clear();
|
||||||
for (auto* ws = head.result; ws; ws = ws->next) {
|
for (auto* ws = head.result; ws; ws = ws->next) {
|
||||||
if (!ws->b.has_essid)
|
if (ws->b.has_essid) {
|
||||||
continue;
|
Network::ScanData sd{};
|
||||||
|
sd.ssid_len = static_cast<u8>(std::min<int>(ws->b.essid_len, 0x20));
|
||||||
|
std::memcpy(sd.ssid, ws->b.essid, sd.ssid_len);
|
||||||
|
sd.quality = QualityToPercent(range, ws);
|
||||||
|
sd.flags |= 1;
|
||||||
|
if (ws->b.has_key)
|
||||||
|
sd.flags |= 2;
|
||||||
|
|
||||||
Network::ScanData sd{};
|
out.emplace_back(sd);
|
||||||
sd.ssid_len = static_cast<u8>(std::min<int>(ws->b.essid_len, 0x20));
|
char tmp[0x22]{};
|
||||||
std::memcpy(sd.ssid, ws->b.essid, sd.ssid_len);
|
std::memcpy(tmp, sd.ssid, sd.ssid_len);
|
||||||
sd.quality = QualityToPercent(range, ws);
|
}
|
||||||
sd.flags |= 1;
|
|
||||||
if (ws->b.has_key)
|
|
||||||
sd.flags |= 2;
|
|
||||||
|
|
||||||
out.emplace_back(sd);
|
|
||||||
char tmp[0x22]{};
|
|
||||||
std::memcpy(tmp, sd.ssid, sd.ssid_len);
|
|
||||||
}
|
}
|
||||||
have = !out.empty();
|
have = !out.empty();
|
||||||
}
|
}
|
||||||
@@ -174,21 +170,14 @@ static std::vector<Network::ScanData> ScanWifiLinux(std::chrono::milliseconds de
|
|||||||
iw_sockets_close(sock);
|
iw_sockets_close(sock);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
#endif /* linux */
|
#elif defined(__FreeBSD__)
|
||||||
#endif
|
|
||||||
|
|
||||||
std::vector<Network::ScanData> ScanWifiNetworks(std::chrono::milliseconds deadline) {
|
std::vector<Network::ScanData> ScanWifiNetworks(std::chrono::milliseconds deadline) {
|
||||||
#ifdef ENABLE_WIFI_SCAN
|
|
||||||
#if defined(_WIN32)
|
|
||||||
return ScanWifiWin(deadline);
|
|
||||||
#elif defined(__linux__) && !defined(ANDROID)
|
|
||||||
return ScanWifiLinux(deadline);
|
|
||||||
#else
|
|
||||||
return {}; // unsupported host, pretend no results
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
return {}; // disabled, pretend no results
|
return {}; // disabled, pretend no results
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
std::vector<Network::ScanData> ScanWifiNetworks(std::chrono::milliseconds deadline) {
|
||||||
|
return {}; // disabled, pretend no results
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace Network
|
} // namespace Network
|
||||||
|
|||||||
11
src/core/internal_network/wifi_scanner_dummy.cpp
Normal file
11
src/core/internal_network/wifi_scanner_dummy.cpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include "core/internal_network/wifi_scanner.h"
|
||||||
|
|
||||||
|
namespace Network {
|
||||||
|
std::vector<Network::ScanData> ScanWifiNetworks(std::chrono::milliseconds deadline) {
|
||||||
|
return {}; // disabled, pretend no results
|
||||||
|
}
|
||||||
|
} // namespace Network
|
||||||
Reference in New Issue
Block a user