// virtual_interface.hpp - Virtual Interface for Network Communication // Copyright (C) 2026 DcruBro // Distributed under the terms of the GNU General Public License, either version 2 only or version 3. See LICENSES/ for details. #pragma once #include #include #include #include #include #include #if defined(__linux__) #include #include #include #include #include #include #elif defined(__APPLE__) #include #include #include #include #include #include #include #include #elif defined(_WIN32) #define WIN32_LEAN_AND_MEAN #define WINTUN_STATIC #include #include #include #include #include #include #include #include #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "ws2_32.lib") #endif namespace ColumnLynx::Net { class VirtualInterface { public: explicit VirtualInterface(const std::string& ifName); ~VirtualInterface(); bool configureIP(uint32_t clientIP, uint32_t serverIP, uint8_t prefixLen, uint16_t mtu); void resetIP(); std::vector readPacket(); void writePacket(const std::vector& packet); const std::string& getName() const; int getFd() const; // For ASIO integration (on POSIX) static inline std::string ipv4ToString(uint32_t ip, bool flip = true) { struct in_addr addr; if (flip) addr.s_addr = htonl(ip); else addr.s_addr = ip; char buf[INET_ADDRSTRLEN]; if (!inet_ntop(AF_INET, &addr, buf, sizeof(buf))) return "0.0.0.0"; return std::string(buf); } static inline uint32_t stringToIpv4(const std::string &ipStr) { struct in_addr addr; if (inet_pton(AF_INET, ipStr.c_str(), &addr) != 1) { return 0; // "0.0.0.0" } return ntohl(addr.s_addr); } static inline std::string ipv6ToString(IPv6Addr &ip, bool flip = false) { struct in6_addr addr; if (flip) { IPv6Addr flipped; for (size_t i = 0; i < 16; ++i) flipped[i] = ip[15 - i]; memcpy(addr.s6_addr, flipped.data(), 16); } else { memcpy(addr.s6_addr, ip.data(), 16); } char buf[INET6_ADDRSTRLEN]; if (!inet_ntop(AF_INET6, &addr, buf, sizeof(buf))) return "::"; // Fallback return std::string(buf); } static inline IPv6Addr stringToIpv6(const std::string &ipStr) { IPv6Addr result{}; struct in6_addr addr; if (inet_pton(AF_INET6, ipStr.c_str(), &addr) != 1) { // "::" result.fill(0); return result; } memcpy(result.data(), addr.s6_addr, 16); return result; } static inline uint32_t prefixLengthToNetmask(uint8_t prefixLen) { if (prefixLen == 0) return 0; uint32_t mask = (0xFFFFFFFF << (32 - prefixLen)) & 0xFFFFFFFF; return htonl(mask); // convert to network byte order } private: bool mApplyLinuxIP(uint32_t clientIP, uint32_t serverIP, uint8_t prefixLen, uint16_t mtu); bool mApplyMacOSIP(uint32_t clientIP, uint32_t serverIP, uint8_t prefixLen, uint16_t mtu); bool mApplyWindowsIP(uint32_t clientIP, uint32_t serverIP, uint8_t prefixLen, uint16_t mtu); std::string mIfName; int mFd; // POSIX #if defined(_WIN32) WINTUN_ADAPTER_HANDLE mAdapter = nullptr; WINTUN_SESSION_HANDLE mSession = nullptr; HANDLE mHandle = nullptr; #endif }; }