123 lines
4.0 KiB
C++
123 lines
4.0 KiB
C++
// SPDX-FileCopyrightText: Matteo Settenvini <matteo.settenvini@montecristosoftware.eu>
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include "helpers.hh"
|
|
|
|
#include <new>
|
|
#include <nss.h>
|
|
#include <netdb.h>
|
|
|
|
#include <cstring>
|
|
#include <memory>
|
|
|
|
auto malcontent::copy_hostent(const hostent& src, hostent& dst, void *buffer, size_t buflen) -> void {
|
|
dst.h_addrtype = src.h_addrtype;
|
|
dst.h_length = src.h_length;
|
|
|
|
// copy name
|
|
{
|
|
auto name_len = std::strlen(src.h_name) + 1;
|
|
buffer = std::align(alignof(char), name_len, buffer, buflen);
|
|
if (buffer == nullptr) {
|
|
throw std::bad_alloc{};
|
|
}
|
|
|
|
dst.h_name = static_cast<char *>(std::memcpy(buffer, src.h_name, name_len));
|
|
reinterpret_cast<char *&>(buffer) += name_len;
|
|
buflen -= name_len;
|
|
}
|
|
|
|
// copy addresses
|
|
{
|
|
auto begin_it = src.h_addr_list;
|
|
auto end_it = begin_it;
|
|
for (; *end_it != nullptr; ++end_it);
|
|
auto n = std::distance(begin_it, end_it);
|
|
|
|
auto needs_bytes = (n + 1) * sizeof(char *);
|
|
buffer = std::align(alignof(char *), needs_bytes, buffer, buflen);
|
|
if (buffer == nullptr) {
|
|
throw std::bad_alloc {};
|
|
}
|
|
dst.h_addr_list = static_cast<char **>(buffer);
|
|
reinterpret_cast<char **&>(buffer) += n + 1;
|
|
|
|
for (auto i = 0; i < n; ++i) {
|
|
buffer = std::align(alignof(char), src.h_length, buffer, buflen);
|
|
if (buffer == nullptr) {
|
|
throw std::bad_alloc {};
|
|
}
|
|
|
|
dst.h_addr_list[i] = static_cast<char *>(
|
|
std::memcpy(buffer, src.h_addr_list[i], src.h_length));
|
|
reinterpret_cast<char *&>(buffer) += src.h_length;
|
|
buflen -= src.h_length;
|
|
}
|
|
dst.h_addr_list[n] = nullptr;
|
|
}
|
|
|
|
// copy aliases
|
|
{
|
|
auto begin_it = src.h_aliases;
|
|
auto end_it = begin_it;
|
|
for (; *end_it != nullptr; ++end_it);
|
|
|
|
auto n = std::distance(begin_it, end_it);
|
|
auto needs_bytes = (n + 1) * sizeof(char *);
|
|
buffer = std::align(alignof(char *), needs_bytes, buffer, buflen);
|
|
if (buffer == nullptr) {
|
|
throw std::bad_alloc {};
|
|
}
|
|
|
|
dst.h_aliases = static_cast<char **>(buffer);
|
|
reinterpret_cast<char **&>(buffer) += n + 1;
|
|
buflen -= needs_bytes;
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
auto alias_len = strlen(*begin_it) + 1;
|
|
buffer = std::align(alignof(char), alias_len, buffer, buflen);
|
|
if (buffer == nullptr) {
|
|
throw std::bad_alloc{};
|
|
}
|
|
|
|
dst.h_addr_list[i] = static_cast<char *>(
|
|
std::memcpy(buffer, src.h_aliases[i], n));
|
|
|
|
reinterpret_cast<char *&>(buffer) += alias_len;
|
|
buflen -= alias_len;
|
|
}
|
|
dst.h_aliases[n] = nullptr;
|
|
}
|
|
}
|
|
|
|
auto malcontent::copy_hostent_to_gaih_addrtuple(const hostent& src, gaih_addrtuple *head, void *& buffer, size_t& buflen) -> gaih_addrtuple * {
|
|
auto name_len = std::strlen(src.h_name) + 1;
|
|
buffer = std::align(alignof(char), name_len, buffer, buflen);
|
|
if (buffer == nullptr) {
|
|
throw std::bad_alloc{};
|
|
}
|
|
auto namep = static_cast<char *>(std::memcpy(buffer, src.h_name, name_len));
|
|
reinterpret_cast<char *&>(buffer) += name_len;
|
|
buflen -= name_len;
|
|
|
|
for (auto addr = src.h_addr_list; *addr != nullptr; ++addr) {
|
|
buffer = std::align(alignof(gaih_addrtuple), sizeof(gaih_addrtuple), buffer, buflen);
|
|
if (buffer == nullptr) {
|
|
throw std::bad_alloc{};
|
|
}
|
|
|
|
auto tuple = static_cast<gaih_addrtuple *>(buffer);
|
|
|
|
tuple->family = src.h_addrtype;
|
|
tuple->name = namep;
|
|
std::memcpy(tuple->addr, *addr, src.h_length);
|
|
tuple->next = head; // <-- We are reversing result order here, but it shouldn't be a problem, right?
|
|
tuple->scopeid = 0; // FIXME: I have no clue how to determine this
|
|
head = tuple;
|
|
|
|
buflen -= sizeof(gaih_addrtuple);
|
|
}
|
|
|
|
return head;
|
|
}
|