mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 07:34:57 +00:00
LibC: Use gethostbyname_r() in gethostbyname()
Since `gethostbyname()` can't fail because of memory-related issues, it has no way of representing a memory-related failure. We therefor use `NO_RECOVERY` to represent a memory-related failure as well as its normal name server related failures.
This commit is contained in:
parent
5c4b71ac67
commit
fd792f93c4
1 changed files with 26 additions and 97 deletions
|
@ -93,108 +93,36 @@ static DeprecatedString gethostbyname_name_buffer;
|
||||||
|
|
||||||
hostent* gethostbyname(char const* name)
|
hostent* gethostbyname(char const* name)
|
||||||
{
|
{
|
||||||
h_errno = 0;
|
struct hostent ret = {};
|
||||||
|
struct hostent* result = nullptr;
|
||||||
|
size_t buffer_size = 1024;
|
||||||
|
char* buffer = nullptr;
|
||||||
|
|
||||||
auto ipv4_address = IPv4Address::from_string({ name, strlen(name) });
|
auto free_buffer_on_exit = ScopeGuard([buffer] {
|
||||||
|
if (buffer != nullptr)
|
||||||
if (ipv4_address.has_value()) {
|
free(buffer);
|
||||||
gethostbyname_name_buffer = ipv4_address.value().to_deprecated_string();
|
|
||||||
__gethostbyname_buffer.h_name = const_cast<char*>(gethostbyname_name_buffer.characters());
|
|
||||||
__gethostbyname_alias_list_buffer[0] = nullptr;
|
|
||||||
__gethostbyname_buffer.h_aliases = __gethostbyname_alias_list_buffer;
|
|
||||||
__gethostbyname_buffer.h_addrtype = AF_INET;
|
|
||||||
new (&__gethostbyname_address) IPv4Address(ipv4_address.value());
|
|
||||||
__gethostbyname_address_list_buffer[0] = &__gethostbyname_address;
|
|
||||||
__gethostbyname_address_list_buffer[1] = nullptr;
|
|
||||||
__gethostbyname_buffer.h_addr_list = (char**)__gethostbyname_address_list_buffer;
|
|
||||||
__gethostbyname_buffer.h_length = 4;
|
|
||||||
|
|
||||||
return &__gethostbyname_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fd = connect_to_lookup_server();
|
|
||||||
if (fd < 0) {
|
|
||||||
h_errno = TRY_AGAIN;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto close_fd_on_exit = ScopeGuard([fd] {
|
|
||||||
close(fd);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto name_length = strlen(name);
|
while (true) {
|
||||||
VERIFY(name_length <= NumericLimits<i32>::max());
|
buffer = (char*)realloc(buffer, buffer_size);
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
// NOTE: Since gethostbyname usually can't fail because of memory,
|
||||||
|
// it has no way of representing OOM or allocation failure.
|
||||||
|
// NO_RECOVERY is the next best thing.
|
||||||
|
h_errno = NO_RECOVERY;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct [[gnu::packed]] {
|
int rc = gethostbyname_r(name, &ret, buffer, buffer_size, &result, &h_errno);
|
||||||
u32 message_size;
|
if (rc == ERANGE) {
|
||||||
u32 endpoint_magic;
|
buffer_size *= 2;
|
||||||
i32 message_id;
|
continue;
|
||||||
u32 name_length;
|
}
|
||||||
} request_header = {
|
|
||||||
(u32)(sizeof(request_header) - sizeof(request_header.message_size) + name_length),
|
|
||||||
lookup_server_endpoint_magic,
|
|
||||||
1,
|
|
||||||
static_cast<u32>(name_length),
|
|
||||||
};
|
|
||||||
if (auto nsent = write(fd, &request_header, sizeof(request_header)); nsent < 0) {
|
|
||||||
h_errno = TRY_AGAIN;
|
|
||||||
return nullptr;
|
|
||||||
} else if (nsent != sizeof(request_header)) {
|
|
||||||
h_errno = NO_RECOVERY;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto nsent = write(fd, name, name_length); nsent < 0) {
|
if (rc < 0)
|
||||||
h_errno = TRY_AGAIN;
|
return nullptr;
|
||||||
return nullptr;
|
|
||||||
} else if (static_cast<size_t>(nsent) != name_length) {
|
|
||||||
h_errno = NO_RECOVERY;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct [[gnu::packed]] {
|
break;
|
||||||
u32 message_size;
|
|
||||||
u32 endpoint_magic;
|
|
||||||
i32 message_id;
|
|
||||||
i32 code;
|
|
||||||
u32 addresses_count;
|
|
||||||
} response_header;
|
|
||||||
|
|
||||||
if (auto nreceived = read(fd, &response_header, sizeof(response_header)); nreceived < 0) {
|
|
||||||
h_errno = TRY_AGAIN;
|
|
||||||
return nullptr;
|
|
||||||
} else if (nreceived != sizeof(response_header)) {
|
|
||||||
h_errno = NO_RECOVERY;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (response_header.endpoint_magic != lookup_server_endpoint_magic || response_header.message_id != 2) {
|
|
||||||
h_errno = NO_RECOVERY;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (response_header.code != 0) {
|
|
||||||
h_errno = NO_RECOVERY;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (response_header.addresses_count == 0) {
|
|
||||||
h_errno = HOST_NOT_FOUND;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
i32 response_length;
|
|
||||||
if (auto nreceived = read(fd, &response_length, sizeof(response_length)); nreceived < 0) {
|
|
||||||
h_errno = TRY_AGAIN;
|
|
||||||
return nullptr;
|
|
||||||
} else if (nreceived != sizeof(response_length)
|
|
||||||
|| response_length != sizeof(__gethostbyname_address)) {
|
|
||||||
h_errno = NO_RECOVERY;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto nreceived = read(fd, &__gethostbyname_address, response_length); nreceived < 0) {
|
|
||||||
h_errno = TRY_AGAIN;
|
|
||||||
return nullptr;
|
|
||||||
} else if (nreceived != response_length) {
|
|
||||||
h_errno = NO_RECOVERY;
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gethostbyname_name_buffer = name;
|
gethostbyname_name_buffer = name;
|
||||||
|
@ -202,10 +130,11 @@ hostent* gethostbyname(char const* name)
|
||||||
__gethostbyname_alias_list_buffer[0] = nullptr;
|
__gethostbyname_alias_list_buffer[0] = nullptr;
|
||||||
__gethostbyname_buffer.h_aliases = __gethostbyname_alias_list_buffer;
|
__gethostbyname_buffer.h_aliases = __gethostbyname_alias_list_buffer;
|
||||||
__gethostbyname_buffer.h_addrtype = AF_INET;
|
__gethostbyname_buffer.h_addrtype = AF_INET;
|
||||||
|
memcpy(&__gethostbyname_address, result->h_addr_list[0], sizeof(in_addr_t));
|
||||||
__gethostbyname_address_list_buffer[0] = &__gethostbyname_address;
|
__gethostbyname_address_list_buffer[0] = &__gethostbyname_address;
|
||||||
__gethostbyname_address_list_buffer[1] = nullptr;
|
__gethostbyname_address_list_buffer[1] = nullptr;
|
||||||
__gethostbyname_buffer.h_addr_list = (char**)__gethostbyname_address_list_buffer;
|
__gethostbyname_buffer.h_addr_list = (char**)__gethostbyname_address_list_buffer;
|
||||||
__gethostbyname_buffer.h_length = 4;
|
__gethostbyname_buffer.h_length = result->h_length;
|
||||||
|
|
||||||
return &__gethostbyname_buffer;
|
return &__gethostbyname_buffer;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue