Retrieve correct netmask in netctl

This commit is contained in:
Marcin Mikołajczyk 2025-07-14 19:22:01 +01:00
parent 62c0cc7d9a
commit 9e14c72fe7
3 changed files with 75 additions and 1 deletions

View File

@ -11,6 +11,7 @@ typedef int socklen_t;
#else
#include <cerrno>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
@ -21,7 +22,6 @@ typedef int socklen_t;
typedef int net_socket;
#endif
#if defined(__APPLE__)
#include <ifaddrs.h>
#include <net/if_dl.h>
#endif
@ -100,6 +100,8 @@ bool NetUtilInternal::RetrieveEthernetAddr() {
}
}
close(sock);
if (success) {
memcpy(ether_address.data(), ifr.ifr_hwaddr.sa_data, 6);
return true;
@ -107,4 +109,62 @@ bool NetUtilInternal::RetrieveEthernetAddr() {
#endif
return false;
}
const std::string& NetUtilInternal::GetNetmask() const {
return netmask;
}
bool NetUtilInternal::RetrieveNetmask() {
std::scoped_lock lock{m_mutex};
char netmaskStr[INET_ADDRSTRLEN];
auto success = false;
#ifdef _WIN32
std::vector<u8> adapter_addresses(sizeof(IP_ADAPTER_ADDRESSES));
ULONG size_infos = sizeof(IP_ADAPTER_ADDRESSES);
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_infos.data()), &size_infos) ==
ERROR_BUFFER_OVERFLOW)
adapter_infos.resize(size_infos);
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_infos.data()), &size_infos) ==
NO_ERROR && size_infos) {
PIP_ADAPTER_ADDRESSES adapter;
for (adapter = adapter_addresses; adapter; adapter = adapter->Next) {
PIP_ADAPTER_UNICAST_ADDRESS unicast = adapter->FirstUnicastAddress;
if (unicast) {
ULONG prefix_length = unicast->OnLinkPrefixLength;
ULONG mask = prefix_length == 0 ? 0 : 0xFFFFFFFF << (32 - prefix_length);
in_addr addr{};
addr.S_un.S_addr = htonl(mask);
inet_ntop(AF_INET, &addr, netmaskStr, INET_ADDRSTRLEN);
success = true;
}
}
}
#else
ifaddrs* ifap;
if (getifaddrs(&ifap) == 0) {
ifaddrs* p;
for (p = ifap; p; p = p->ifa_next) {
if (p->ifa_addr && p->ifa_addr->sa_family == AF_INET) {
auto sa = reinterpret_cast<sockaddr_in*>(p->ifa_netmask);
inet_ntop(AF_INET, &sa->sin_addr, netmaskStr, INET_ADDRSTRLEN);
success = true;
}
}
}
freeifaddrs(ifap);
#endif
if (success) {
netmask = netmaskStr;
}
return success;
}
} // namespace NetUtil

View File

@ -15,10 +15,13 @@ public:
private:
std::array<u8, 6> ether_address{};
std::string netmask{};
std::mutex m_mutex;
public:
const std::array<u8, 6>& GetEthernetAddr() const;
const std::string& GetNetmask() const;
bool RetrieveEthernetAddr();
bool RetrieveNetmask();
};
} // namespace NetUtil

View File

@ -220,6 +220,17 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) {
case ORBIS_NET_CTL_INFO_DHCP_HOSTNAME:
// info-> = ;
break;
case ORBIS_NET_CTL_INFO_NETMASK: {
auto* netinfo = Common::Singleton<NetUtil::NetUtilInternal>::Instance();
auto success = netinfo->RetrieveNetmask();
if (success) {
strncpy(info->netmask, netinfo->GetNetmask().data(), sizeof(info->netmask));
LOG_DEBUG(Lib_NetCtl, "netmask: {}", info->netmask);
} else {
LOG_WARNING(Lib_NetCtl, "netmask: failed to retrieve");
}
break;
}
default:
LOG_ERROR(Lib_NetCtl, "{} unsupported code", code);
}