diff --git a/src/core/libraries/network/net_util.cpp b/src/core/libraries/network/net_util.cpp index d0f0a81da..e7b1bddcc 100644 --- a/src/core/libraries/network/net_util.cpp +++ b/src/core/libraries/network/net_util.cpp @@ -11,6 +11,7 @@ typedef int socklen_t; #else #include #include +#include #include #include #include @@ -21,7 +22,6 @@ typedef int socklen_t; typedef int net_socket; #endif #if defined(__APPLE__) -#include #include #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 adapter_addresses(sizeof(IP_ADAPTER_ADDRESSES)); + ULONG size_infos = sizeof(IP_ADAPTER_ADDRESSES); + + if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), &size_infos) == + ERROR_BUFFER_OVERFLOW) + adapter_infos.resize(size_infos); + + if (GetAdaptersInfo(reinterpret_cast(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(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 \ No newline at end of file diff --git a/src/core/libraries/network/net_util.h b/src/core/libraries/network/net_util.h index be9dc15a1..97f671705 100644 --- a/src/core/libraries/network/net_util.h +++ b/src/core/libraries/network/net_util.h @@ -15,10 +15,13 @@ public: private: std::array ether_address{}; + std::string netmask{}; std::mutex m_mutex; public: const std::array& GetEthernetAddr() const; + const std::string& GetNetmask() const; bool RetrieveEthernetAddr(); + bool RetrieveNetmask(); }; } // namespace NetUtil \ No newline at end of file diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index 32cab7c74..6c874b400 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -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::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); }