feat(kernel): translate guest IP address conversion APIs

This commit is contained in:
SamG-Coder 2026-09-25 06:18:32 +10:00
parent 97e6ce992b
commit ff725218cb
4 changed files with 92 additions and 0 deletions

View File

@ -104,6 +104,15 @@ endforeach()
add_custom_target(libs DEPENDS ${PATCHED_OUTPUTS})
if(BUILD_TESTING)
add_executable(guest_address_tests tests/GuestAddressConversion.cpp)
target_include_directories(guest_address_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(guest_address_tests PRIVATE libkernel libc)
configure_windows_unwind(guest_address_tests)
add_test(NAME guest_addresses COMMAND guest_address_tests)
if(WIN32)
set_tests_properties(guest_addresses PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
add_executable(guest_error_tests tests/GuestErrors.cpp)
target_include_directories(guest_error_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(guest_error_tests PRIVATE libc)

View File

@ -25,6 +25,7 @@ add_library(libkernel SHARED EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/Pthread/Posix/Tsd.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pthread/Posix/Sem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Socket/src/Socket.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Socket/src/AddressConversion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/EventFlag/src/EventFlag.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Module/src/Module.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Aio/src/Aio.cpp
@ -41,6 +42,7 @@ add_library(libkernel SHARED EXCLUDE_FROM_ALL
target_include_directories(libkernel PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(libkernel PRIVATE libc)
if(WIN32)
target_link_libraries(libkernel PRIVATE ws2_32)
target_compile_definitions(libkernel PRIVATE _WIN32_WINNT=0x0602)
endif()
configure_windows_unwind(libkernel)

View File

@ -0,0 +1,47 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#endif
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstdint>
#include <cstring>
extern "C" int* APS5_VABI __error_nid_postfix();
extern "C" {
int APS5_VABI __inet_pton_nid_postfix(int family, const char* text, void* destination) {
if (family != 2 && family != 28) { *__error_nid_postfix() = 47; return -1; }
if (!text || !destination) { *__error_nid_postfix() = 14; return -1; }
unsigned char address[16]{};
const int nativeFamily = family == 2 ? AF_INET : AF_INET6;
#ifdef _WIN32
const int result = InetPtonA(nativeFamily, text, address);
#else
const int result = ::inet_pton(nativeFamily, text, address);
#endif
if (result == 1) std::memcpy(destination, address, family == 2 ? 4 : 16);
else if (result == -1) *__error_nid_postfix() = 22;
return result;
}
const char* APS5_VABI __inet_ntop_nid_postfix(int family, const void* source,
char* destination, std::uint32_t capacity) {
if (family != 2 && family != 28) { *__error_nid_postfix() = 47; return nullptr; }
if (!source || !destination) { *__error_nid_postfix() = 14; return nullptr; }
char text[INET6_ADDRSTRLEN]{};
const int nativeFamily = family == 2 ? AF_INET : AF_INET6;
#ifdef _WIN32
const auto* result = InetNtopA(nativeFamily, const_cast<void*>(source), text, sizeof(text));
#else
const auto* result = ::inet_ntop(nativeFamily, source, text, sizeof(text));
#endif
if (!result) { *__error_nid_postfix() = 22; return nullptr; }
const auto size = std::strlen(text) + 1;
if (size > capacity) { *__error_nid_postfix() = 28; return nullptr; }
std::memcpy(destination, text, size);
return destination;
}
}

View File

@ -0,0 +1,34 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <array>
#include <cstdint>
#include <cstdlib>
#include <cstring>
extern "C" {
int APS5_VABI __inet_pton_nid_postfix(int, const char*, void*);
const char* APS5_VABI __inet_ntop_nid_postfix(int, const void*, char*, std::uint32_t);
int* APS5_VABI __error_nid_postfix();
}
static void Require(bool value) { if (!value) std::abort(); }
int main() {
for (int family : {2, 28}) {
const char* input = family == 2 ? "192.0.2.17" : "2001:db8::17";
std::array<unsigned char, 16> address{};
Require(__inet_pton_nid_postfix(family, input, address.data()) == 1);
char output[64]{};
Require(__inet_ntop_nid_postfix(family, address.data(), output, sizeof(output)) == output);
Require(std::strcmp(input, output) == 0);
output[0] = 'x';
Require(__inet_ntop_nid_postfix(family, address.data(), output, 1) == nullptr);
Require(*__error_nid_postfix() == 28 && output[0] == 'x');
const auto original = address;
Require(__inet_pton_nid_postfix(family, "not-an-address", address.data()) == 0);
Require(address == original);
}
std::array<unsigned char, 16> address{};
Require(__inet_pton_nid_postfix(10, "::1", address.data()) == -1);
Require(*__error_nid_postfix() == 47); // Linux AF_INET6 is not PS5 AF_INET6
Require(__inet_pton_nid_postfix(2, "256.1.2.3", address.data()) == 0);
Require(__inet_pton_nid_postfix(28, "::ffff:192.0.2.17", address.data()) == 1);
Require(address[10] == 255 && address[11] == 255 && address[12] == 192 && address[15] == 17);
}