extern "C" { #include #include } #include #include #include #include #include std::expected nethost6(std::string network, int prefix, uint32_t num) { struct in6_addr addr; unsigned char mask[16] = {0}; if (inet_pton(AF_INET6, network.data(), &addr) != 1) { return std::unexpected(std::format("Invalid network address {}", network)); } for (int i = 0; i < prefix; i++) { mask[i / 8] |= (1 << (7 - (i % 8))); } for (int i = 0; i < 16; i++) { addr.s6_addr[i] &= mask[i]; } uint64_t *host_part = (uint64_t *)&addr.s6_addr[8]; uint64_t hostnum = be64toh(*host_part); hostnum += num; *host_part = htobe64(hostnum); char buffer[INET6_ADDRSTRLEN] = {'\0'}; inet_ntop(AF_INET6, &addr, buffer, INET6_ADDRSTRLEN); return std::string(buffer); } std::expected nethost4(std::string network, int prefix, uint32_t num) { struct in_addr inaddr; if (inet_pton(AF_INET, network.data(), &inaddr) != 1) { return std::unexpected(std::format("Invalid network address {}", network)); } uint32_t ip = ntohl(inaddr.s_addr); uint32_t mask = (prefix == 0) ? 0 : (~0U << (32 - prefix)); uint32_t fip = (ip & mask) + num; struct in_addr ip_addr; ip_addr.s_addr = htonl(fip); return std::string(inet_ntoa(ip_addr)); } std::expected nethost(std::string network, int prefix, uint32_t num) { struct sockaddr_in sa; if (inet_pton(AF_INET, network.data(), &(sa.sin_addr)) == 1) { return nethost4(network, prefix, num); } else if (inet_pton(AF_INET6, network.data(), &(sa.sin_addr)) == 1) { return nethost6(network, prefix, num); } return std::unexpected(std::format("Unknown network address {}", network)); } int main() { auto net4Res = nethost4("192.168.1.151", 24, 1); if (!net4Res) { std::cerr << net4Res.error() << std::endl; return 1; } std::cout << net4Res.value() << std::endl; auto net6Res = nethost6("2001:db8:abcd:1234::0", 64, 1); if (!net6Res) { std::cerr << net6Res.error() << std::endl; return 1; } std::cout << net6Res.value() << std::endl; return 0; }