// SPDX-FileCopyrightText: Matteo Settenvini // SPDX-License-Identifier: GPL-3.0-or-later #include "helpers.hh" #include #include #include #include #include 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(std::memcpy(buffer, src.h_name, name_len)); reinterpret_cast(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(buffer); reinterpret_cast(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( std::memcpy(buffer, src.h_addr_list[i], src.h_length)); reinterpret_cast(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(buffer); reinterpret_cast(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( std::memcpy(buffer, src.h_aliases[i], n)); reinterpret_cast(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(std::memcpy(buffer, src.h_name, name_len)); reinterpret_cast(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(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; }