diff --git a/.drone.jsonnet b/.drone.jsonnet index c8b741f9c..203746cca 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -13,7 +13,6 @@ local default_deps_base = [ ]; local default_deps_nocxx = ['libsodium-dev'] + default_deps_base; // libsodium-dev needs to be >= 1.0.18 local default_deps = ['g++'] + default_deps_nocxx; -local default_windows_deps = ['mingw-w64', 'zip', 'nsis']; local docker_base = 'registry.oxen.rocks/lokinet-ci-'; local submodule_commands = [ @@ -147,7 +146,7 @@ local windows_cross_pipeline(name, 'echo "man-db man-db/auto-update boolean false" | debconf-set-selections', apt_get_quiet + ' update', apt_get_quiet + ' install -y eatmydata', - 'eatmydata ' + apt_get_quiet + ' install --no-install-recommends -y p7zip-full build-essential cmake git pkg-config ccache g++-mingw-w64-x86-64-posix nsis zip automake libtool', + 'eatmydata ' + apt_get_quiet + ' install --no-install-recommends -y p7zip-full build-essential cmake git pkg-config ccache g++-mingw-w64-x86-64-posix nsis zip icoutils automake libtool', 'update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix', 'update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix', 'JOBS=' + jobs + ' VERBOSE=1 ./contrib/windows.sh -DSTRIP_SYMBOLS=ON ' + diff --git a/cmake/macos.cmake b/cmake/macos.cmake index 1ca3aa0d9..a15a86e3d 100644 --- a/cmake/macos.cmake +++ b/cmake/macos.cmake @@ -127,7 +127,7 @@ endif() set(mac_icon "${PROJECT_BINARY_DIR}/lokinet.icns") add_custom_command(OUTPUT "${mac_icon}" COMMAND ${PROJECT_SOURCE_DIR}/contrib/macos/mk-icns.sh ${PROJECT_SOURCE_DIR}/contrib/lokinet-mac.svg "${mac_icon}" - DEPENDS ${PROJECT_SOURCE_DIR}/contrib/lokinet.svg ${PROJECT_SOURCE_DIR}/contrib/macos/mk-icns.sh) + DEPENDS ${PROJECT_SOURCE_DIR}/contrib/lokinet-mac.svg ${PROJECT_SOURCE_DIR}/contrib/macos/mk-icns.sh) add_custom_target(icon DEPENDS "${mac_icon}") if(BUILD_PACKAGE) diff --git a/cmake/win32_installer_deps.cmake b/cmake/win32_installer_deps.cmake index e937cabee..e0591466e 100644 --- a/cmake/win32_installer_deps.cmake +++ b/cmake/win32_installer_deps.cmake @@ -32,8 +32,14 @@ endif() set(BOOTSTRAP_FILE "${PROJECT_SOURCE_DIR}/contrib/bootstrap/mainnet.signed") install(FILES ${BOOTSTRAP_FILE} DESTINATION share COMPONENT lokinet RENAME bootstrap.signed) +set(win_ico "${PROJECT_BINARY_DIR}/lokinet.ico") +add_custom_command(OUTPUT "${win_ico}" + COMMAND ${PROJECT_SOURCE_DIR}/contrib/make-ico.sh ${PROJECT_SOURCE_DIR}/contrib/lokinet.svg "${win_ico}" + DEPENDS ${PROJECT_SOURCE_DIR}/contrib/lokinet.svg ${PROJECT_SOURCE_DIR}/contrib/make-ico.sh) +add_custom_target(icon ALL DEPENDS "${win_ico}") + set(CPACK_PACKAGE_INSTALL_DIRECTORY "Lokinet") -set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/win32-setup/lokinet.ico") +set(CPACK_NSIS_MUI_ICON "${PROJECT_BINARY_DIR}/lokinet.ico") set(CPACK_NSIS_DEFINES "RequestExecutionLevel admin") set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) diff --git a/contrib/lokinet-mac.svg b/contrib/lokinet-mac.svg index ef9dd8b0e..10ddf0ca2 100644 --- a/contrib/lokinet-mac.svg +++ b/contrib/lokinet-mac.svg @@ -3,7 +3,7 @@ - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/contrib/make-ico.sh b/contrib/make-ico.sh new file mode 100755 index 000000000..9a0413a67 --- /dev/null +++ b/contrib/make-ico.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Invoked from cmake as make-ico.sh /path/to/icon.svg /path/to/output.ico +svg="$1" +out="$2" +outdir="$out.d" + +set -e + +sizes=(16 24 32 40 48 64 96 192 256) +outs="" + +mkdir -p "${outdir}" +for size in "${sizes[@]}"; do + outf="${outdir}/${size}x${size}.png" + if [ $size -lt 32 ]; then + # For 16x16 and 24x24 we crop the image to 3/4 of its regular size before resizing and make + # it all white (instead of transparent) which effectively zooms in on it a bit because if we + # resize the full icon it ends up a fuzzy mess, while the crop and resize lets us retain + # some detail of the logo. + convert -background white -resize 512x512 "$svg" -gravity Center -extent 320x320 -resize ${size}x${size} -strip "png32:$outf" + else + convert -background transparent -resize ${size}x${size} "$svg" -strip "png32:$outf" + fi + outs="-r $outf $outs" +done + +icotool -c -b 32 -o "$out" $outs diff --git a/gui b/gui index 37b1f015b..7b0f1aacd 160000 --- a/gui +++ b/gui @@ -1 +1 @@ -Subproject commit 37b1f015b73586c404971e6724721d4f1343ed50 +Subproject commit 7b0f1aacdf79b558adfc39dc9cccb7e348aeec03 diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index a42c76bb1..2e3c558df 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -33,6 +33,7 @@ add_library(lokinet-platform # for networking ev/ev.cpp ev/libuv.cpp + net/interface_info.cpp net/ip.cpp net/ip_address.cpp net/ip_packet.cpp diff --git a/llarp/net/interface_info.cpp b/llarp/net/interface_info.cpp new file mode 100644 index 000000000..370903b21 --- /dev/null +++ b/llarp/net/interface_info.cpp @@ -0,0 +1,15 @@ +#include "interface_info.hpp" + +namespace llarp::net +{ + std::string + InterfaceInfo::ToString() const + { + return fmt::format( + "{}[i={}; addrs={}; gw={}]", + name, + index, + fmt::join(addrs, ","), + gateway ? net::ToString(*gateway) : "none"); + } +} // namespace llarp::net diff --git a/llarp/net/interface_info.hpp b/llarp/net/interface_info.hpp index c5d897264..a603b03bd 100644 --- a/llarp/net/interface_info.hpp +++ b/llarp/net/interface_info.hpp @@ -1,7 +1,9 @@ #pragma once +#include #include #include +#include #include "ip_range.hpp" namespace llarp::net @@ -17,5 +19,11 @@ namespace llarp::net std::vector addrs; /// a gateway we can use if it exists std::optional gateway; + + std::string + ToString() const; }; } // namespace llarp::net + +template <> +inline constexpr bool llarp::IsToStringFormattable = true; diff --git a/llarp/net/ip_range.cpp b/llarp/net/ip_range.cpp index ea3fe858e..eaee05fd4 100644 --- a/llarp/net/ip_range.cpp +++ b/llarp/net/ip_range.cpp @@ -101,4 +101,25 @@ namespace llarp return netmask_bits.ToString(); } + std::optional + IPRange::FindPrivateRange(const std::list& excluding) + { + auto good = [&excluding](const IPRange& range) -> bool { + for (const auto& ex : excluding) + if (ex * range) + return false; + return true; + }; + for (int oct = 16; oct <= 31; ++oct) + if (auto range = IPRange::FromIPv4(172, oct, 0, 1, 16); good(range)) + return range; + for (int oct = 0; oct <= 255; ++oct) + if (auto range = IPRange::FromIPv4(10, oct, 0, 1, 16); good(range)) + return range; + for (int oct = 0; oct <= 255; ++oct) + if (auto range = IPRange::FromIPv4(192, 168, oct, 1, 24); good(range)) + return range; + return std::nullopt; + } + } // namespace llarp diff --git a/llarp/net/ip_range.hpp b/llarp/net/ip_range.hpp index ca3ff25c4..9772793aa 100644 --- a/llarp/net/ip_range.hpp +++ b/llarp/net/ip_range.hpp @@ -1,10 +1,13 @@ #pragma once -#include + #include "ip.hpp" #include "net_bits.hpp" #include #include #include + +#include +#include #include namespace llarp @@ -144,6 +147,10 @@ namespace llarp bool BDecode(llarp_buffer_t* buf); + + /// Finds a free private use range not overlapping the given ranges. + static std::optional + FindPrivateRange(const std::list& excluding); }; template <> diff --git a/llarp/net/net_int.cpp b/llarp/net/net_int.cpp index 1affa42e5..2628200ec 100644 --- a/llarp/net/net_int.cpp +++ b/llarp/net/net_int.cpp @@ -1,6 +1,7 @@ #include "net_int.hpp" #include "ip.hpp" #include +#include #include @@ -155,4 +156,11 @@ namespace llarp { return std::to_string(ntohs(n)); } + + std::string + net::ToString(const ipaddr_t& ipaddr) + { + return std::visit([](const auto& ip) { return ip.ToString(); }, ipaddr); + } + } // namespace llarp diff --git a/llarp/net/net_int.hpp b/llarp/net/net_int.hpp index d9894024d..e34f9b23b 100644 --- a/llarp/net/net_int.hpp +++ b/llarp/net/net_int.hpp @@ -230,6 +230,9 @@ namespace llarp using ipv6addr_t = n_uint128_t; using ipaddr_t = std::variant; + std::string + ToString(const ipaddr_t& ip); + huint16_t ToHost(port_t); huint32_t ToHost(ipv4addr_t); huint128_t ToHost(ipv6addr_t); diff --git a/llarp/net/posix.cpp b/llarp/net/posix.cpp index 8d0cdfdde..b04398c0c 100644 --- a/llarp/net/posix.cpp +++ b/llarp/net/posix.cpp @@ -32,7 +32,7 @@ namespace llarp::net if (getifaddrs(&addrs)) throw std::runtime_error{fmt::format("getifaddrs(): {}", strerror(errno))}; - for (auto next = addrs; next and next->ifa_next; next = next->ifa_next) + for (auto next = addrs; next; next = next->ifa_next) visit(next); freeifaddrs(addrs); @@ -90,35 +90,7 @@ namespace llarp::net } }); - auto ownsRange = [¤tRanges](const IPRange& range) -> bool { - for (const auto& ownRange : currentRanges) - { - if (ownRange * range) - return true; - } - return false; - }; - // generate possible ranges to in order of attempts - std::list possibleRanges; - for (byte_t oct = 16; oct < 32; ++oct) - { - possibleRanges.emplace_back(IPRange::FromIPv4(172, oct, 0, 1, 16)); - } - for (byte_t oct = 0; oct < 255; ++oct) - { - possibleRanges.emplace_back(IPRange::FromIPv4(10, oct, 0, 1, 16)); - } - for (byte_t oct = 0; oct < 255; ++oct) - { - possibleRanges.emplace_back(IPRange::FromIPv4(192, 168, oct, 1, 24)); - } - // for each possible range pick the first one we don't own - for (const auto& range : possibleRanges) - { - if (not ownsRange(range)) - return range; - } - return std::nullopt; + return IPRange::FindPrivateRange(currentRanges); } std::optional GetInterfaceIndex(ipaddr_t) const override diff --git a/llarp/net/win32.cpp b/llarp/net/win32.cpp index 5db5382be..1bcaa86df 100644 --- a/llarp/net/win32.cpp +++ b/llarp/net/win32.cpp @@ -151,35 +151,7 @@ namespace llarp::net } }); - auto ownsRange = [¤tRanges](const IPRange& range) -> bool { - for (const auto& ownRange : currentRanges) - { - if (ownRange * range) - return true; - } - return false; - }; - // generate possible ranges to in order of attempts - std::list possibleRanges; - for (byte_t oct = 16; oct < 32; ++oct) - { - possibleRanges.emplace_back(IPRange::FromIPv4(172, oct, 0, 1, 16)); - } - for (byte_t oct = 0; oct < 255; ++oct) - { - possibleRanges.emplace_back(IPRange::FromIPv4(10, oct, 0, 1, 16)); - } - for (byte_t oct = 0; oct < 255; ++oct) - { - possibleRanges.emplace_back(IPRange::FromIPv4(192, 168, oct, 1, 24)); - } - // for each possible range pick the first one we don't own - for (const auto& range : possibleRanges) - { - if (not ownsRange(range)) - return range; - } - return std::nullopt; + return IPRange::FindPrivateRange(currentRanges); } std::string @@ -199,23 +171,27 @@ namespace llarp::net AllNetworkInterfaces() const override { std::vector all; - iter_adapters([&all](auto* a) { - auto& cur = all.emplace_back(); - cur.index = a->IfIndex; - cur.name = a->AdapterName; - for (auto* addr = a->FirstUnicastAddress; addr; addr = addr->Next) - { - SockAddr saddr{*addr->Address.lpSockaddr}; - cur.addrs.emplace_back( - saddr.asIPv6(), - ipaddr_netmask_bits(addr->OnLinkPrefixLength, addr->Address.lpSockaddr->sa_family)); - } - if (auto* addr = a->FirstGatewayAddress) - { - SockAddr gw{*addr->Address.lpSockaddr}; - cur.gateway = gw.getIP(); - } - }); + for (int af : {AF_INET, AF_INET6}) + iter_adapters( + [&all](auto* a) { + auto& cur = all.emplace_back(); + cur.index = a->IfIndex; + cur.name = a->AdapterName; + for (auto* addr = a->FirstUnicastAddress; addr; addr = addr->Next) + { + SockAddr saddr{*addr->Address.lpSockaddr}; + cur.addrs.emplace_back( + saddr.asIPv6(), + ipaddr_netmask_bits( + addr->OnLinkPrefixLength, addr->Address.lpSockaddr->sa_family)); + } + if (auto* addr = a->FirstGatewayAddress) + { + SockAddr gw{*addr->Address.lpSockaddr}; + cur.gateway = gw.getIP(); + } + }, + af); return all; } }; diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index df29a36b0..8b38b133a 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -156,7 +156,7 @@ namespace llarp next_gw = *gw_ptr; } - // update current gateway and apply state chnages as needed + // update current gateway and apply state changes as needed if (m_CurrentGateway != next_gw) { if (next_gw and m_CurrentGateway) @@ -172,7 +172,7 @@ namespace llarp m_CurrentGateway = next_gw; m_Router->Freeze(); } - else if (next_gw) + else // next_gw and not m_CurrentGateway { log::info(logcat, "default gateway found at {}", *next_gw); m_CurrentGateway = next_gw; @@ -197,24 +197,36 @@ namespace llarp { bool was_up = m_up; m_up = true; - if (IsEnabled() and m_CurrentGateway and not was_up) + if (not was_up) { - log::info(logcat, "RoutePoker coming up; poking routes"); + if (not IsEnabled()) + { + log::warning(logcat, "RoutePoker coming up, but route poking is disabled by config"); + } + else if (not m_CurrentGateway) + { + log::warning(logcat, "RokerPoker came up, but we don't know of a gateway!"); + } + else + { + log::info(logcat, "RoutePoker coming up; poking routes"); - vpn::IRouteManager& route = m_Router->GetVPNPlatform()->RouteManager(); + vpn::IRouteManager& route = m_Router->GetVPNPlatform()->RouteManager(); - // black hole all routes if enabled - if (m_Router->GetConfig()->network.m_BlackholeRoutes) - route.AddBlackhole(); + // black hole all routes if enabled + if (m_Router->GetConfig()->network.m_BlackholeRoutes) + route.AddBlackhole(); - // explicit route pokes for first hops - m_Router->ForEachPeer( - [this](auto session, auto) { AddRoute(session->GetRemoteEndpoint().getIPv4()); }, false); - // add default route - const auto ep = m_Router->hiddenServiceContext().GetDefault(); - if (auto* vpn = ep->GetVPNInterface()) - route.AddDefaultRouteViaInterface(*vpn); - log::info(logcat, "route poker up"); + // explicit route pokes for first hops + m_Router->ForEachPeer( + [this](auto session, auto) { AddRoute(session->GetRemoteEndpoint().getIPv4()); }, + false); + // add default route + const auto ep = m_Router->hiddenServiceContext().GetDefault(); + if (auto* vpn = ep->GetVPNInterface()) + route.AddDefaultRouteViaInterface(*vpn); + log::info(logcat, "route poker up"); + } } if (not was_up) SetDNSMode(true); diff --git a/llarp/win32/windivert.cpp b/llarp/win32/windivert.cpp index 7a04ece29..b359e1927 100644 --- a/llarp/win32/windivert.cpp +++ b/llarp/win32/windivert.cpp @@ -102,7 +102,7 @@ namespace llarp::win32 SetLastError(0); return std::nullopt; } - L::info(cat, "got packet of size {}B", sz); + L::trace(cat, "got packet of size {}B", sz); pkt.resize(sz); return Packet{std::move(pkt), std::move(addr)}; } @@ -112,7 +112,7 @@ namespace llarp::win32 { const auto& pkt = w_pkt.pkt; const auto* addr = &w_pkt.addr; - L::info(cat, "send dns packet of size {}B", pkt.size()); + L::trace(cat, "send dns packet of size {}B", pkt.size()); UINT sz{}; if (wd::send(m_Handle, pkt.data(), pkt.size(), &sz, addr)) return; @@ -151,7 +151,7 @@ namespace llarp::win32 throw std::runtime_error{"windivert thread is already running"}; auto read_loop = [this]() { - log::info(cat, "windivert read loop start"); + log::debug(cat, "windivert read loop start"); while (true) { // in the read loop, read packets until they stop coming in @@ -165,7 +165,7 @@ namespace llarp::win32 else // leave loop on read fail break; } - log::info(cat, "windivert read loop end"); + log::debug(cat, "windivert read loop end"); }; m_Runner = std::thread{std::move(read_loop)};