diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 1eceb64027..4ffae0147b 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -10,6 +10,7 @@ set(LIBC_SOURCES fcntl.cpp grp.cpp malloc.cpp + netdb.cpp printf_impl.cpp pwd.cpp scanf_impl.cpp diff --git a/libc/include/netdb.h b/libc/include/netdb.h index 315c61fb68..343f62abca 100644 --- a/libc/include/netdb.h +++ b/libc/include/netdb.h @@ -90,6 +90,7 @@ void endservent(void); void freeaddrinfo(struct addrinfo* ai); const char* gai_strerror(int ecode); int getaddrinfo(const char* __restrict nodename, const char* __restrict servname, const struct addrinfo* __restrict hints, struct addrinfo** __restrict res); +struct hostent* gethostbyname(const char* name); struct hostent* gethostent(void); int getnameinfo(const struct sockaddr* __restrict sa, socklen_t salen, char* __restrict node, socklen_t nodelen, char* __restrict service, socklen_t servicelen, int flags); struct netent* getnetbyaddr(uint32_t net, int type); diff --git a/libc/netdb.cpp b/libc/netdb.cpp new file mode 100644 index 0000000000..7b0a9171d3 --- /dev/null +++ b/libc/netdb.cpp @@ -0,0 +1,69 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct hostent* gethostbyname(const char* name) +{ + static char name_buffer[HOST_NAME_MAX + 1]; + static in_addr_t addr_buffer; + static in_addr_t* addr_ptrs[2]; + static struct hostent hostent; + + if (strlen(name) > HOST_NAME_MAX) + return nullptr; + strcpy(name_buffer, name); + hostent.h_name = name_buffer; + + hostent.h_aliases = nullptr; + + hostent.h_addrtype = AF_INET; + hostent.h_length = sizeof(in_addr_t); + + addr_ptrs[0] = &addr_buffer; + addr_ptrs[1] = nullptr; + hostent.h_addr_list = reinterpret_cast(addr_ptrs); + + int socket = -1; + + if (in_addr_t ipv4 = inet_addr(name); ipv4 != (in_addr_t)(-1)) + addr_buffer = ipv4; + else + { + int socket = ::socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (socket == -1) + return nullptr; + + sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, "/tmp/resolver.sock"); + if (connect(socket, (sockaddr*)&addr, sizeof(addr)) == -1) + goto error_close_socket; + + if (send(socket, name, strlen(name), 0) == -1) + goto error_close_socket; + + sockaddr_storage storage; + if (recv(socket, &storage, sizeof(storage), 0) == -1) + goto error_close_socket; + + close(socket); + + if (storage.ss_family != AF_INET) + return nullptr; + + addr_buffer = *reinterpret_cast(storage.ss_storage); + } + + return &hostent; + +error_close_socket: + close(socket); + return nullptr; +}