extern "C" { #include #include } #include #include #include #include #include std::expected netprefix(const std::string network) { auto hostprefix = split(network, "/"); if (hostprefix.size() < 2) { return std::unexpected("Incorrect network definition"); } auto prefixRes = strtoint(hostprefix[1]); if (!prefixRes) { return std::unexpected("Incorrect tunnel network prefix:" + prefixRes.error()); } return prefixRes.value(); } std::expected network(const std::string network) { auto hostprefix = split(network, "/"); if (hostprefix.size() < 2) { return std::unexpected("Incorrect network definition"); } return hostprefix[0]; } 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)); }