From bd93a8f82811ae9c12415c114e27e8008409af54 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 16 Feb 2021 10:59:18 -0500 Subject: [PATCH 1/8] initial v6 exits --- daemon/lokinet-vpn.cpp | 12 ++++++--- llarp/handlers/tun.cpp | 30 ++++++++++++++++----- llarp/handlers/tun.hpp | 3 +++ llarp/net/ip.hpp | 2 +- llarp/net/ip_address.cpp | 8 ++++++ llarp/net/ip_address.hpp | 3 +++ llarp/net/net.cpp | 15 ++++++++++- llarp/net/net.hpp | 4 +++ llarp/net/route.cpp | 52 ++++++++++++++++++++++++++++++++---- llarp/net/sock_addr.cpp | 14 +++++++++- llarp/net/sock_addr.hpp | 4 +++ llarp/router/route_poker.cpp | 26 ++++++++++++++++-- llarp/router/route_poker.hpp | 9 +++++++ llarp/rpc/rpc_server.cpp | 18 ++----------- 14 files changed, 165 insertions(+), 35 deletions(-) diff --git a/daemon/lokinet-vpn.cpp b/daemon/lokinet-vpn.cpp index 5e43f6722..b386737b6 100644 --- a/daemon/lokinet-vpn.cpp +++ b/daemon/lokinet-vpn.cpp @@ -68,12 +68,14 @@ main(int argc, char* argv[]) ("token", "exit auth token to use", cxxopts::value()) ("auth", "exit auth token to use", cxxopts::value()) ("status", "print status and exit", cxxopts::value()) + ("range", "ip range to map", cxxopts::value()) ; // clang-format on lokimq::address rpcURL("tcp://127.0.0.1:1190"); std::string exitAddress; std::string endpoint = "default"; std::optional token; + std::string range = "::/0"; lokimq::LogLevel logLevel = lokimq::LogLevel::warn; bool goUp = false; bool goDown = false; @@ -118,6 +120,10 @@ main(int argc, char* argv[]) { token = result["auth"].as(); } + if (result.count("range") > 0) + { + range = result["range"].as(); + } } catch (const cxxopts::option_not_exists_exception& ex) { @@ -216,12 +222,12 @@ main(int argc, char* argv[]) lmq, connID, "llarp.exit", - nlohmann::json{{"exit", exitAddress}, {"range", "0.0.0.0/0"}, {"token", *token}}); + nlohmann::json{{"exit", exitAddress}, {"range", range}, {"token", *token}}); } else { maybe_result = LMQ_Request( - lmq, connID, "llarp.exit", nlohmann::json{{"exit", exitAddress}, {"range", "0.0.0.0/0"}}); + lmq, connID, "llarp.exit", nlohmann::json{{"exit", exitAddress}, {"range", range}}); } if (not maybe_result.has_value()) @@ -238,7 +244,7 @@ main(int argc, char* argv[]) } if (goDown) { - LMQ_Request(lmq, connID, "llarp.exit", nlohmann::json{{"range", "0.0.0.0/0"}, {"unmap", true}}); + LMQ_Request(lmq, connID, "llarp.exit", nlohmann::json{{"range", range}, {"unmap", true}}); } return 0; diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 28d8474ab..241ae140b 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -182,8 +182,9 @@ namespace llarp } m_OurRange = *maybe; } + m_OurIP = m_OurRange.addr; - m_UseV6 = not m_OurRange.IsV4(); + m_UseV6 = false; return Endpoint::Configure(conf, dnsConf); } @@ -707,6 +708,11 @@ namespace llarp vpn::InterfaceInfo info; info.addrs.emplace(m_OurRange); + IPRange v6range = m_OurRange; + v6range.addr = net::ExpandV4Lan(net::TruncateV6(m_OurRange.addr)); + LogInfo(Name(), " using v6 range: ", v6range); + info.addrs.emplace(v6range, AF_INET6); + info.ifname = m_IfName; info.dnsaddr.FromString(m_LocalResolverAddr.toHost()); @@ -736,6 +742,13 @@ namespace llarp return false; } + const auto maybe = GetInterfaceIP6(m_IfName); + if (maybe.has_value()) + { + m_OurIP6 = *maybe; + LogInfo(Name(), " has ipv6 address ", m_OurIP6); + } + netloop->add_ticker([&]() { Flush(); }); if (m_OnUp) @@ -826,7 +839,10 @@ namespace llarp } */ - + if (m_state->m_ExitEnabled) + { + dst = net::ExpandV4(net::TruncateV6(dst)); + } auto itr = m_IPToAddr.find(dst); if (itr == m_IPToAddr.end()) { @@ -843,8 +859,7 @@ namespace llarp else { const auto addr = *exits.begin(); - if (pkt.IsV4()) - pkt.ZeroSourceAddress(); + pkt.ZeroSourceAddress(); MarkAddressOutbound(addr); EnsurePathToService( addr, @@ -934,7 +949,10 @@ namespace llarp if (pkt.IsV4()) dst = pkt.dst4to6Lan(); else if (pkt.IsV6()) + { dst = pkt.dstv6(); + src = net::ExpandV4Lan(net::TruncateV6(src)); + } } else { @@ -948,11 +966,11 @@ namespace llarp if (pkt.IsV4()) { dst = m_OurIP; - src = pkt.src4to6(); + src = pkt.src4to6Lan(); } else if (pkt.IsV6()) { - dst = pkt.dstv6(); + dst = m_OurIP6; src = pkt.srcv6(); } // find what exit we think this should be for diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index dbf1fbdaa..045280ea0 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -235,6 +235,9 @@ namespace llarp std::unordered_map m_IPActivity; /// our ip address (host byte order) huint128_t m_OurIP; + /// our ip for ip6 + huint128_t m_OurIP6; + /// next ip address to allocate (host byte order) huint128_t m_NextIP; /// highest ip address to allocate (host byte order) diff --git a/llarp/net/ip.hpp b/llarp/net/ip.hpp index 9ab998fe8..52fba8693 100644 --- a/llarp/net/ip.hpp +++ b/llarp/net/ip.hpp @@ -19,7 +19,7 @@ namespace llarp::net constexpr huint128_t ExpandV4Lan(huint32_t x) { - return huint128_t{uint128_t{0xfe80'0000'0000'0000UL, 0UL}} | huint128_t{x.h}; + return huint128_t{uint128_t{0xfd00'0000'0000'0000UL, 0UL}} | huint128_t{x.h}; } constexpr huint32_t diff --git a/llarp/net/ip_address.cpp b/llarp/net/ip_address.cpp index 530642c54..f08f62f61 100644 --- a/llarp/net/ip_address.cpp +++ b/llarp/net/ip_address.cpp @@ -161,6 +161,14 @@ namespace llarp return ip; } + huint128_t + IpAddress::toIP6() const + { + huint128_t ip; + ip.FromString(m_ipAddress); + return ip; + } + bool IpAddress::operator<(const IpAddress& other) const { diff --git a/llarp/net/ip_address.hpp b/llarp/net/ip_address.hpp index b072d89a3..aa4030f90 100644 --- a/llarp/net/ip_address.hpp +++ b/llarp/net/ip_address.hpp @@ -126,6 +126,9 @@ namespace llarp huint32_t toIP() const; + huint128_t + toIP6() const; + // TODO: other utility functions left over from Addr which may be useful // IsBogon() const; // isPrivate() const; diff --git a/llarp/net/net.cpp b/llarp/net/net.cpp index 67c629258..95030ec3c 100644 --- a/llarp/net/net.cpp +++ b/llarp/net/net.cpp @@ -550,12 +550,25 @@ namespace llarp { sockaddr_storage s; sockaddr* sptr = (sockaddr*)&s; + sptr->sa_family = af; if (!llarp_getifaddr(ifname.c_str(), af, sptr)) return std::nullopt; - llarp::SockAddr saddr = SockAddr(*sptr); + llarp::SockAddr saddr = SockAddr{*sptr}; return llarp::IpAddress(saddr); } + std::optional + GetInterfaceIP6(std::string ifname) + { + sockaddr_storage s; + sockaddr* sptr = (sockaddr*)&s; + sptr->sa_family = AF_INET6; + if (!llarp_getifaddr(ifname.c_str(), AF_INET6, sptr)) + return std::nullopt; + llarp::SockAddr addr{*sptr}; + return addr.asIPv6(); + } + bool AllInterfaces(int af, IpAddress& result) { diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index 3485ff008..9aad5f2be 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -77,6 +77,10 @@ namespace llarp std::optional GetIFAddr(const std::string& ifname, int af = AF_INET); + /// get an interface's ip6 address + std::optional + GetInterfaceIP6(std::string ifname); + } // namespace llarp #endif diff --git a/llarp/net/route.cpp b/llarp/net/route.cpp index ea67edc1d..93b92f380 100644 --- a/llarp/net/route.cpp +++ b/llarp/net/route.cpp @@ -178,8 +178,19 @@ namespace llarp::net } if (mode == GatewayMode::eUpperDefault) { - rtattr_add( - &nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &dst->data, sizeof(uint32_t)); + if (dst->family == AF_INET) + { + rtattr_add( + &nl_request.n, + sizeof(nl_request), + /*RTA_NEWDST*/ RTA_DST, + &dst->data, + sizeof(uint32_t)); + } + else + { + rtattr_add(&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &dst->data, 16); + } } /* Send message to the netlink */ return send(sock, &nl_request, sizeof(nl_request), 0); @@ -191,7 +202,7 @@ namespace llarp::net if (strchr(addr, ':')) { res->family = AF_INET6; - res->bitlen = 128; + res->bitlen = bitlen; } else { @@ -335,7 +346,7 @@ namespace llarp::net int if_idx = if_nametoindex(ifname.c_str()); _inet_addr to_addr{}; _inet_addr gw_addr{}; - const auto maybe = GetIFAddr(ifname); + auto maybe = GetIFAddr(ifname); if (not maybe.has_value()) throw std::runtime_error("we dont have our own net interface?"); int nl_cmd = RTM_NEWROUTE; @@ -345,6 +356,21 @@ namespace llarp::net do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx); read_addr("128.0.0.0", &to_addr, 1); do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); + const auto maybeInt = GetInterfaceIP6(ifname); + if (maybeInt.has_value()) + { + const auto host = maybeInt->ToString(); + LogInfo("add v6 route via ", host); + read_addr(host.c_str(), &gw_addr, 128); + read_addr("::", &to_addr, 2); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx); + read_addr("4000::", &to_addr, 2); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); + read_addr("8000::", &to_addr, 2); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); + read_addr("c000::", &to_addr, 2); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); + } #endif #elif _WIN32 // poke hole for loopback bacause god is dead on windows @@ -370,7 +396,7 @@ namespace llarp::net int if_idx = if_nametoindex(ifname.c_str()); _inet_addr to_addr{}; _inet_addr gw_addr{}; - const auto maybe = GetIFAddr(ifname); + auto maybe = GetIFAddr(ifname); if (not maybe.has_value()) throw std::runtime_error("we dont have our own net interface?"); @@ -381,6 +407,22 @@ namespace llarp::net do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx); read_addr("128.0.0.0", &to_addr, 1); do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); + + const auto maybeInt = GetInterfaceIP6(ifname); + if (maybeInt.has_value()) + { + const auto host = maybeInt->ToString(); + LogInfo("del v6 route via ", host); + read_addr(host.c_str(), &gw_addr, 128); + read_addr("::", &to_addr, 2); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx); + read_addr("4000::", &to_addr, 2); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); + read_addr("8000::", &to_addr, 2); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); + read_addr("c000::", &to_addr, 2); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); + } #endif #elif _WIN32 ifname.back()++; diff --git a/llarp/net/sock_addr.cpp b/llarp/net/sock_addr.cpp index 042a665a6..a4598a02e 100644 --- a/llarp/net/sock_addr.cpp +++ b/llarp/net/sock_addr.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -187,6 +188,12 @@ namespace llarp sizeof(m_addr.sin6_addr.s6_addr))); } + huint128_t + SockAddr::asIPv6() const + { + return net::In6ToHUInt(m_addr.sin6_addr); + } + void SockAddr::fromString(std::string_view str) { @@ -204,7 +211,12 @@ namespace llarp // TODO: having ":port" at the end makes this ambiguous with IPv6 // come up with a strategy for implementing if (splits.size() > 2) - throw std::runtime_error("IPv6 not yet supported"); + { + std::string data{str}; + if (inet_pton(AF_INET6, data.c_str(), m_addr.sin6_addr.s6_addr) == -1) + throw std::runtime_error{"invalid ip6 address: " + data}; + return; + } // split() shouldn't return an empty list if str is empty (checked above) assert(splits.size() > 0); diff --git a/llarp/net/sock_addr.hpp b/llarp/net/sock_addr.hpp index 4589271f0..bf0b42aa6 100644 --- a/llarp/net/sock_addr.hpp +++ b/llarp/net/sock_addr.hpp @@ -16,6 +16,7 @@ inet_pton(int af, const char* src, void* dst); #include #include +#include namespace llarp { @@ -80,6 +81,9 @@ namespace llarp uint16_t getPort() const; + huint128_t + asIPv6() const; + private: bool m_empty = true; sockaddr_in6 m_addr; diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index 7cb3c3ee9..7041e700b 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -131,8 +131,7 @@ namespace llarp DisableAllRoutes(); EnableAllRoutes(); - const auto ep = m_Router->hiddenServiceContext().GetDefault(); - net::AddDefaultRouteViaInterface(ep->GetIfName()); + Up(); } } @@ -156,4 +155,27 @@ namespace llarp DisableAllRoutes(); } + + void + RoutePoker::Up() + { + // explicit route pokes for first hops + m_Router->ForEachPeer( + [&](auto session, auto) mutable { AddRoute(session->GetRemoteEndpoint().toIP()); }, false); + // add default route + const auto ep = m_Router->hiddenServiceContext().GetDefault(); + net::AddDefaultRouteViaInterface(ep->GetIfName()); + } + + void + RoutePoker::Down() + { + // unpoke routes for first hops + m_Router->ForEachPeer( + [&](auto session, auto) mutable { DelRoute(session->GetRemoteEndpoint().toIP()); }, false); + // remove default route + const auto ep = m_Router->hiddenServiceContext().GetDefault(); + net::DelDefaultRouteViaInterface(ep->GetIfName()); + } + } // namespace llarp diff --git a/llarp/router/route_poker.hpp b/llarp/router/route_poker.hpp index 47be3c8b1..68cdf7b92 100644 --- a/llarp/router/route_poker.hpp +++ b/llarp/router/route_poker.hpp @@ -2,6 +2,7 @@ #include #include +#include #include namespace llarp @@ -34,6 +35,14 @@ namespace llarp void Disable(); + /// explicitly put routes up + void + Up(); + + /// explicitly put routes down + void + Down(); + private: void DeleteAllRoutes(); diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index bdc9f9516..829d83d4e 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -156,7 +156,6 @@ namespace llarp::rpc { map = false; } - const auto range_itr = obj.find("range"); if (range_itr == obj.end()) { @@ -204,13 +203,7 @@ namespace llarp::rpc reply(CreateJSONError("could not find exit")); return; } - r->ForEachPeer( - [r](auto session, auto) mutable { - const auto ip = session->GetRemoteEndpoint().toIP(); - r->routePoker().AddRoute(ip); - }, - false); - net::AddDefaultRouteViaInterface(ep->GetIfName()); + r->routePoker().Up(); reply(CreateJSONResponse("OK")); }, 5s); @@ -250,14 +243,7 @@ namespace llarp::rpc } else if (not map) { - net::DelDefaultRouteViaInterface(ep->GetIfName()); - - r->ForEachPeer( - [r](auto session, auto) mutable { - const auto ip = session->GetRemoteEndpoint().toIP(); - r->routePoker().DelRoute(ip); - }, - false); + r->routePoker().Down(); ep->UnmapExitRange(range); } reply(CreateJSONResponse("OK")); From 063e982ef6415b6edbfca665bf3c9d7ffdd00abd Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 16 Feb 2021 11:25:44 -0500 Subject: [PATCH 2/8] fix exit range default value --- llarp/config/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 810adef58..35285ba3f 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -430,7 +430,7 @@ namespace llarp const auto pos = arg.find(":"); if (pos == std::string::npos) { - range.FromString("0.0.0.0/0"); + range.FromString("::/0"); } else if (not range.FromString(arg.substr(pos + 1))) { From 1c7079dbab3430e2dcf8290b974c8dfef1c64e53 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 16 Feb 2021 12:37:16 -0500 Subject: [PATCH 3/8] fix up route poking with lokinet to work with ipv6 --- llarp/net/route.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/llarp/net/route.cpp b/llarp/net/route.cpp index 93b92f380..991a8d556 100644 --- a/llarp/net/route.cpp +++ b/llarp/net/route.cpp @@ -151,23 +151,13 @@ namespace llarp::net nl_request.r.rtm_family = dst->family; nl_request.r.rtm_dst_len = dst->bitlen; - - /* Select scope, for simplicity we supports here only IPv6 and IPv4 */ - if (nl_request.r.rtm_family == AF_INET6) - { - nl_request.r.rtm_scope = RT_SCOPE_UNIVERSE; - } - else - { - nl_request.r.rtm_scope = RT_SCOPE_LINK; - } + nl_request.r.rtm_scope = 0; /* Set gateway */ - if (gw->bitlen != 0) + if (gw->bitlen != 0 and dst->family == AF_INET) { rtattr_add(&nl_request.n, sizeof(nl_request), RTA_GATEWAY, &gw->data, gw->bitlen / 8); } - nl_request.r.rtm_scope = 0; nl_request.r.rtm_family = gw->family; if (mode == GatewayMode::eFirstHop) { @@ -189,7 +179,13 @@ namespace llarp::net } else { - rtattr_add(&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &dst->data, 16); + rtattr_add(&nl_request.n, sizeof(nl_request), RTA_OIF, &if_idx, sizeof(int)); + rtattr_add( + &nl_request.n, + sizeof(nl_request), + /*RTA_NEWDST*/ RTA_DST, + &dst->data, + sizeof(in6_addr)); } } /* Send message to the netlink */ @@ -363,7 +359,7 @@ namespace llarp::net LogInfo("add v6 route via ", host); read_addr(host.c_str(), &gw_addr, 128); read_addr("::", &to_addr, 2); - do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); read_addr("4000::", &to_addr, 2); do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); read_addr("8000::", &to_addr, 2); @@ -415,7 +411,7 @@ namespace llarp::net LogInfo("del v6 route via ", host); read_addr(host.c_str(), &gw_addr, 128); read_addr("::", &to_addr, 2); - do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx); + do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); read_addr("4000::", &to_addr, 2); do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); read_addr("8000::", &to_addr, 2); From 35137913b9f5b7c273ea8cc3bffe50ca22572f33 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 16 Feb 2021 15:01:07 -0500 Subject: [PATCH 4/8] windows and macos route pokers for ipv6 --- llarp/net/net.hpp | 8 ++++++ llarp/net/route.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++--- llarp/vpn/win32.hpp | 18 +++++++------ 3 files changed, 79 insertions(+), 12 deletions(-) diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index 9aad5f2be..b218c6a78 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -81,6 +81,14 @@ namespace llarp std::optional GetInterfaceIP6(std::string ifname); +#ifdef _WIN32 + namespace net + { + std::optional + GetIfIndex(std::string ip); + } +#endif + } // namespace llarp #endif diff --git a/llarp/net/route.cpp b/llarp/net/route.cpp index 991a8d556..1a932aaee 100644 --- a/llarp/net/route.cpp +++ b/llarp/net/route.cpp @@ -24,9 +24,11 @@ #include #include #include -#include +#include #include #include +#include +#include #endif #include @@ -237,6 +239,16 @@ namespace llarp::net return converter.to_bytes(wcmd); } + std::string + NetshCommand() + { + std::wstring wcmd = get_win_sys_path() + L"\\netsh.exe"; + + using convert_type = std::codecvt_utf8; + std::wstring_convert converter; + return converter.to_bytes(wcmd); + } + template void ForEachWIN32Interface(Visit visit) @@ -272,6 +284,24 @@ namespace llarp::net #undef MALLOC #undef FREE } + + std::optional + GetIfIndex(std::string ip) + { + llarp::huint32_t h{}; + h.FromString(ip); + std::optional ret = std::nullopt; + ForEachWIN32Interface([&ret, n = ToNet(h)](auto* iface) { + if (ret.has_value()) + return; + if (iface->dwForwardNextHop == n.n) + { + ret = iface->dwForwardIfIndex; + } + }); + return ret; + } + #endif void @@ -371,12 +401,27 @@ namespace llarp::net #elif _WIN32 // poke hole for loopback bacause god is dead on windows Execute(RouteCommand() + " ADD 127.0.0.0 MASK 255.0.0.0 0.0.0.0"); + + huint32_t ip{}; + ip.FromString(ifname); + const auto ipv6 = net::ExpandV4Lan(ip); + + Execute(RouteCommand() + " ADD ::/2 " + ipv6.ToString()); + Execute(RouteCommand() + " ADD 4000::/2 " + ipv6.ToString()); + Execute(RouteCommand() + " ADD 8000::/2 " + ipv6.ToString()); + Execute(RouteCommand() + " ADD c000::/2 " + ipv6.ToString()); ifname.back()++; Execute(RouteCommand() + " ADD 0.0.0.0 MASK 128.0.0.0 " + ifname); Execute(RouteCommand() + " ADD 128.0.0.0 MASK 128.0.0.0 " + ifname); + #elif __APPLE__ Execute("/sbin/route -n add -cloning -net 0.0.0.0 -netmask 128.0.0.0 -interface " + ifname); Execute("/sbin/route -n add -cloning -net 128.0.0.0 -netmask 128.0.0.0 -interface " + ifname); + + Execute("/sbin/route -n add -cloning -net ::/2 -interface " + ifname); + Execute("/sbin/route -n add -cloning -net 4000::/2 -interface " + ifname); + Execute("/sbin/route -n add -cloning -net 8000::/2 -interface " + ifname); + Execute("/sbin/route -n add -cloning -net c000::/2 -interface " + ifname); #else #error unsupported platform #endif @@ -421,6 +466,14 @@ namespace llarp::net } #endif #elif _WIN32 + huint32_t ip{}; + ip.FromString(ifname); + const auto ipv6 = net::ExpandV4Lan(ip); + + Execute(RouteCommand() + " DELETE ::/2 " + ipv6.ToString()); + Execute(RouteCommand() + " DELETE 4000::/2 " + ipv6.ToString()); + Execute(RouteCommand() + " DELETE 8000::/2 " + ipv6.ToString()); + Execute(RouteCommand() + " DELETE c000::/2 " + ipv6.ToString()); ifname.back()++; Execute(RouteCommand() + " DELETE 0.0.0.0 MASK 128.0.0.0 " + ifname); Execute(RouteCommand() + " DELETE 128.0.0.0 MASK 128.0.0.0 " + ifname); @@ -429,6 +482,12 @@ namespace llarp::net Execute("/sbin/route -n delete -cloning -net 0.0.0.0 -netmask 128.0.0.0 -interface " + ifname); Execute( "/sbin/route -n delete -cloning -net 128.0.0.0 -netmask 128.0.0.0 -interface " + ifname); + + Execute("/sbin/route -n add -cloning -net ::/2 -interface " + ifname); + Execute("/sbin/route -n delete -cloning -net 4000::/2 -interface " + ifname); + Execute("/sbin/route -n delete -cloning -net 8000::/2 -interface " + ifname); + Execute("/sbin/route -n delete -cloning -net c000::/2 -interface " + ifname); + #else #error unsupported platform #endif @@ -461,9 +520,7 @@ namespace llarp::net struct in_addr gateway, interface_addr; gateway.S_un.S_addr = (u_long)w32interface->dwForwardDest; interface_addr.S_un.S_addr = (u_long)w32interface->dwForwardNextHop; - std::array interface_str{}; - StringCchCopy(interface_str.data(), interface_str.size(), inet_ntoa(interface_addr)); - std::string interface_name{interface_str.data()}; + std::string interface_name{inet_ntoa(interface_addr)}; if ((!gateway.S_un.S_addr) and interface_name != ifname) { llarp::LogTrace( diff --git a/llarp/vpn/win32.hpp b/llarp/vpn/win32.hpp index a5eea375b..cfbd4dde0 100644 --- a/llarp/vpn/win32.hpp +++ b/llarp/vpn/win32.hpp @@ -153,7 +153,8 @@ namespace llarp::vpn static void NetSH(std::string commands) { - commands = NetSHCommand() + " " + commands; + commands = NetSHCommand() + " interface IPv6 " + commands; + LogInfo(commands); ::system(commands.c_str()); } @@ -203,6 +204,7 @@ namespace llarp::vpn } LogInfo("setting addresses"); + huint32_t ip{}; // set ipv4 addresses for (const auto& ifaddr : m_Info.addrs) { @@ -210,6 +212,7 @@ namespace llarp::vpn { IPADDR sock[3]{}; const nuint32_t addr = xhtonl(net::TruncateV6(ifaddr.range.addr)); + ip = net::TruncateV6(ifaddr.range.addr); const nuint32_t mask = xhtonl(net::TruncateV6(ifaddr.range.netmask_bits)); LogInfo("address ", addr, " netmask ", mask); sock[0] = addr.n; @@ -299,19 +302,18 @@ namespace llarp::vpn } } // set ipv6 addresses - /* for (const auto& ifaddr : m_Info.addrs) { if (ifaddr.fam == AF_INET6) { - IPRange range = ifaddr.range; - range.netmask_bits = netmask_ipv6_bits(128); - NetSH( - "interface ipv6 set address " + std::to_string(ifindex) + " " + range.ToString() - + " store=active"); + const auto maybe = net::GetIfIndex(ip.ToString()); + if (maybe.has_value()) + { + NetSH( + "add address interface=" + std::to_string(*maybe) + " " + ifaddr.range.ToString()); + } } } - */ } ~Win32Interface() From 1ee545d6d2521aff6335030d9094e76e6a3a878c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 16 Feb 2021 16:37:08 -0500 Subject: [PATCH 5/8] fix up macos route command for ipv6 --- llarp/net/route.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/llarp/net/route.cpp b/llarp/net/route.cpp index 1a932aaee..872a54864 100644 --- a/llarp/net/route.cpp +++ b/llarp/net/route.cpp @@ -418,10 +418,10 @@ namespace llarp::net Execute("/sbin/route -n add -cloning -net 0.0.0.0 -netmask 128.0.0.0 -interface " + ifname); Execute("/sbin/route -n add -cloning -net 128.0.0.0 -netmask 128.0.0.0 -interface " + ifname); - Execute("/sbin/route -n add -cloning -net ::/2 -interface " + ifname); - Execute("/sbin/route -n add -cloning -net 4000::/2 -interface " + ifname); - Execute("/sbin/route -n add -cloning -net 8000::/2 -interface " + ifname); - Execute("/sbin/route -n add -cloning -net c000::/2 -interface " + ifname); + Execute("/sbin/route -n add -inet6 -net ::/2 -interface " + ifname); + Execute("/sbin/route -n add -inet6 -net 4000::/2 -interface " + ifname); + Execute("/sbin/route -n add -inet6 -net 8000::/2 -interface " + ifname); + Execute("/sbin/route -n add -inet6 -net c000::/2 -interface " + ifname); #else #error unsupported platform #endif @@ -483,10 +483,10 @@ namespace llarp::net Execute( "/sbin/route -n delete -cloning -net 128.0.0.0 -netmask 128.0.0.0 -interface " + ifname); - Execute("/sbin/route -n add -cloning -net ::/2 -interface " + ifname); - Execute("/sbin/route -n delete -cloning -net 4000::/2 -interface " + ifname); - Execute("/sbin/route -n delete -cloning -net 8000::/2 -interface " + ifname); - Execute("/sbin/route -n delete -cloning -net c000::/2 -interface " + ifname); + Execute("/sbin/route -n delete -inet6 -net ::/2 -interface " + ifname); + Execute("/sbin/route -n delete -inet6 -net 4000::/2 -interface " + ifname); + Execute("/sbin/route -n delete -inet6 -net 8000::/2 -interface " + ifname); + Execute("/sbin/route -n delete -inet6 -net c000::/2 -interface " + ifname); #else #error unsupported platform From 0600f428145c3b343effb1d8699e89c7ea846d68 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 17 Feb 2021 06:37:21 -0500 Subject: [PATCH 6/8] fix up names of functions to be less hidious. --- llarp/handlers/tun.cpp | 2 +- llarp/link/server.cpp | 2 +- llarp/net/net.cpp | 4 ++-- llarp/net/net.hpp | 6 +++--- llarp/net/route.cpp | 6 ++---- llarp/vpn/win32.hpp | 2 +- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 241ae140b..550ad5e2b 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -742,7 +742,7 @@ namespace llarp return false; } - const auto maybe = GetInterfaceIP6(m_IfName); + const auto maybe = GetInterfaceIPv6Address(m_IfName); if (maybe.has_value()) { m_OurIP6 = *maybe; diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index 4a786cc9f..a4a9caea8 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -144,7 +144,7 @@ namespace llarp } else { - if (const auto maybe = GetIFAddr(ifname, af)) + if (const auto maybe = GetInterfaceAddr(ifname, af)) { m_ourAddr = *maybe; } diff --git a/llarp/net/net.cpp b/llarp/net/net.cpp index 95030ec3c..648f923b3 100644 --- a/llarp/net/net.cpp +++ b/llarp/net/net.cpp @@ -546,7 +546,7 @@ namespace llarp } std::optional - GetIFAddr(const std::string& ifname, int af) + GetInterfaceAddr(const std::string& ifname, int af) { sockaddr_storage s; sockaddr* sptr = (sockaddr*)&s; @@ -558,7 +558,7 @@ namespace llarp } std::optional - GetInterfaceIP6(std::string ifname) + GetInterfaceIPv6Address(std::string ifname) { sockaddr_storage s; sockaddr* sptr = (sockaddr*)&s; diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index b218c6a78..5aa8ce25c 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -75,17 +75,17 @@ namespace llarp /// get network interface address for network interface with ifname std::optional - GetIFAddr(const std::string& ifname, int af = AF_INET); + GetInterfaceAddr(const std::string& ifname, int af = AF_INET); /// get an interface's ip6 address std::optional - GetInterfaceIP6(std::string ifname); + GetInterfaceIPv6Address(std::string ifname); #ifdef _WIN32 namespace net { std::optional - GetIfIndex(std::string ip); + GetInterfaceIndex(huint32_t ip); } #endif diff --git a/llarp/net/route.cpp b/llarp/net/route.cpp index 872a54864..735b084a1 100644 --- a/llarp/net/route.cpp +++ b/llarp/net/route.cpp @@ -286,12 +286,10 @@ namespace llarp::net } std::optional - GetIfIndex(std::string ip) + GetInterfaceIndex(huint32_t ip) { - llarp::huint32_t h{}; - h.FromString(ip); std::optional ret = std::nullopt; - ForEachWIN32Interface([&ret, n = ToNet(h)](auto* iface) { + ForEachWIN32Interface([&ret, n = ToNet(ip)](auto* iface) { if (ret.has_value()) return; if (iface->dwForwardNextHop == n.n) diff --git a/llarp/vpn/win32.hpp b/llarp/vpn/win32.hpp index cfbd4dde0..079448daf 100644 --- a/llarp/vpn/win32.hpp +++ b/llarp/vpn/win32.hpp @@ -306,7 +306,7 @@ namespace llarp::vpn { if (ifaddr.fam == AF_INET6) { - const auto maybe = net::GetIfIndex(ip.ToString()); + const auto maybe = net::GetInterfaceIndex(ip); if (maybe.has_value()) { NetSH( From 1526941f3a8f3a67228d34fa8915ece71b50c407 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 17 Feb 2021 07:49:47 -0500 Subject: [PATCH 7/8] make it compile again --- llarp/net/route.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llarp/net/route.cpp b/llarp/net/route.cpp index 735b084a1..682e0e94c 100644 --- a/llarp/net/route.cpp +++ b/llarp/net/route.cpp @@ -370,7 +370,7 @@ namespace llarp::net int if_idx = if_nametoindex(ifname.c_str()); _inet_addr to_addr{}; _inet_addr gw_addr{}; - auto maybe = GetIFAddr(ifname); + const auto maybe = GetInterfaceAddr(ifname); if (not maybe.has_value()) throw std::runtime_error("we dont have our own net interface?"); int nl_cmd = RTM_NEWROUTE; @@ -380,7 +380,7 @@ namespace llarp::net do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eLowerDefault, if_idx); read_addr("128.0.0.0", &to_addr, 1); do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); - const auto maybeInt = GetInterfaceIP6(ifname); + const auto maybeInt = GetInterfaceIPv6Address(ifname); if (maybeInt.has_value()) { const auto host = maybeInt->ToString(); @@ -435,7 +435,7 @@ namespace llarp::net int if_idx = if_nametoindex(ifname.c_str()); _inet_addr to_addr{}; _inet_addr gw_addr{}; - auto maybe = GetIFAddr(ifname); + const auto maybe = GetInterfaceAddr(ifname); if (not maybe.has_value()) throw std::runtime_error("we dont have our own net interface?"); @@ -447,7 +447,7 @@ namespace llarp::net read_addr("128.0.0.0", &to_addr, 1); do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, GatewayMode::eUpperDefault, if_idx); - const auto maybeInt = GetInterfaceIP6(ifname); + const auto maybeInt = GetInterfaceIPv6Address(ifname); if (maybeInt.has_value()) { const auto host = maybeInt->ToString(); From 8239efa71b981a2cb4c5d0f0efbedaf651bc2b56 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 17 Feb 2021 07:54:18 -0500 Subject: [PATCH 8/8] clarify new member's purpose and name. add comment. --- llarp/handlers/tun.cpp | 6 +++--- llarp/handlers/tun.hpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 550ad5e2b..2951e67c9 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -745,8 +745,8 @@ namespace llarp const auto maybe = GetInterfaceIPv6Address(m_IfName); if (maybe.has_value()) { - m_OurIP6 = *maybe; - LogInfo(Name(), " has ipv6 address ", m_OurIP6); + m_OurIPv6 = *maybe; + LogInfo(Name(), " has ipv6 address ", m_OurIPv6); } netloop->add_ticker([&]() { Flush(); }); @@ -970,7 +970,7 @@ namespace llarp } else if (pkt.IsV6()) { - dst = m_OurIP6; + dst = m_OurIPv6; src = pkt.srcv6(); } // find what exit we think this should be for diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index 045280ea0..713d911df 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -235,8 +235,8 @@ namespace llarp std::unordered_map m_IPActivity; /// our ip address (host byte order) huint128_t m_OurIP; - /// our ip for ip6 - huint128_t m_OurIP6; + /// our network interface's ipv6 address + huint128_t m_OurIPv6; /// next ip address to allocate (host byte order) huint128_t m_NextIP;