├── .clang-format ├── .clang-tidy ├── .dir-locals.el ├── .dockerignore ├── .drone.jsonnet ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ └── clean_issues.yml ├── .gitignore ├── .gitmodules ├── .swift-version ├── CMakeLists.txt ├── CONTRIBUTING.md ├── CONTRIBUTING_es.md ├── LICENSE ├── cmake ├── CMakeGraphVizOptions.cmake ├── DownloadLibSodium.cmake ├── FindJemalloc.cmake ├── GenVersion.cmake ├── MacroEnsureOutOfSourceBuild.cmake ├── StaticBuild.cmake ├── TargetArch.cmake ├── Version.cmake ├── add_import_library.cmake ├── cmake_uninstall.cmake.in ├── coverage.cmake ├── cross_compile.cmake ├── enable_lto.cmake ├── gui-option.cmake ├── gui.cmake ├── installer.cmake ├── libatomic.cmake ├── macos.cmake ├── ngtcp2_lib.cmake ├── solaris.cmake ├── target_link_libraries_system.cmake ├── unix.cmake ├── win32.cmake └── win32_installer_deps.cmake ├── contrib ├── NetworkManager │ └── dnsmasq │ │ ├── README.md │ │ └── lokinet.conf ├── android-configure.sh ├── android.sh ├── apparmor │ └── usr.bin.lokinet ├── apply-patches.sh ├── bencode-dump.py ├── bootstrap │ ├── mainnet.signed │ ├── make-bootstrap-list.sh │ ├── readme.txt │ └── testnet.signed ├── ci │ ├── docker │ │ ├── readme.md │ │ └── rebuild-docker-images.py │ ├── drone-check-static-libs.sh │ ├── drone-debs-upload.sh │ ├── drone-format-verify.sh │ ├── drone-gdb.sh │ ├── drone-run-router-hive.sh │ ├── drone-static-upload.sh │ └── gdb-filter.py ├── configs │ ├── 00-debug-log.ini │ ├── 00-exit.ini │ └── 00-keyfile.ini ├── cross.sh ├── cross │ ├── android.toolchain.cmake │ ├── cross.toolchain.cmake │ ├── mingw32.cmake │ ├── mingw64.cmake │ └── mingw_core.cmake ├── deb.oxen.io.gpg ├── format-version.sh ├── format.sh ├── git-hook-pre-push.sh ├── hex-to-base32z.py ├── keygen.py ├── liblokinet │ ├── CMakeLists.txt │ ├── readme.md │ └── udptest.cpp ├── lokinet-mac.svg ├── lokinet-resolvconf ├── lokinet.svg ├── mac-configure.sh ├── mac.sh ├── macos │ ├── InfoPlist.strings │ ├── installer.png │ ├── installer.tiff │ ├── installer@2x.png │ ├── lokinet-extension.Info.plist.in │ ├── lokinet-extension.dev.provisionprofile │ ├── lokinet-extension.plugin.entitlements.plist │ ├── lokinet-extension.release.provisionprofile │ ├── lokinet-extension.sysext.entitlements.plist │ ├── lokinet-newsyslog.conf │ ├── lokinet.Info.plist.in │ ├── lokinet.dev.provisionprofile │ ├── lokinet.plugin.entitlements.plist │ ├── lokinet.release.provisionprofile │ ├── lokinet.sysext.entitlements.plist │ ├── mk-icns.sh │ ├── notarize.py.in │ ├── seticon.swift │ └── sign.sh.in ├── make-ico.sh ├── omq-rpc.py ├── patches │ ├── libzmq-mingw-unistd.patch │ ├── libzmq-mingw-wepoll.patch │ └── unbound-delete-crash-fix.patch ├── py │ ├── .gitignore │ ├── admin │ │ ├── .gitignore │ │ ├── lokinetmon │ │ └── requirements.txt │ ├── ffi-example │ │ └── lokinet.py │ ├── keygen │ │ ├── .gitignore │ │ ├── keygen.py │ │ └── readme.md │ ├── lnproxy │ │ ├── lnproxy │ │ │ └── __main__.py │ │ └── readme.md │ └── quic_tester.py ├── readme-installer.txt ├── systemd-resolved │ ├── README.md │ ├── lokinet.pkla │ └── lokinet.rules ├── tarball.sh ├── windows-configure.sh └── windows.sh ├── daemon ├── CMakeLists.txt ├── lokinet-bootstrap.cpp ├── lokinet-cntrl.cpp ├── lokinet.cpp ├── lokinet.swift ├── utils.cpp └── utils.hpp ├── docs ├── CMakeLists.txt ├── Doxyfile.in ├── LICENSE ├── architecture.md ├── config.json ├── dns-overview.md ├── doxygen.md ├── exit-setup.md ├── fix-markdown.sh ├── ideal-ux.md ├── index.md.in ├── install.md ├── liblokinet-dev-guide.md ├── lokinet_pathbuild_no_steps.png ├── macos-signing.txt ├── mkdocs.yml ├── net-comparisons.md ├── project-structure.md ├── readme.md ├── refactor_notes.md ├── snapps-dev-guide.md ├── spanish │ ├── LICENSE │ ├── README │ └── vision-general.txt ├── tcp-over-quic.md └── we-cannot-make-sandwiches.md ├── external ├── CMakeLists.txt └── readme.md ├── include ├── llarp.hpp ├── lokinet.h └── lokinet │ ├── addr.h │ ├── context.h │ ├── export.h │ ├── misc.h │ ├── srv.h │ ├── stream.h │ └── udp.h ├── jni ├── CMakeLists.txt ├── java │ └── src │ │ └── network │ │ └── loki │ │ └── lokinet │ │ ├── LokinetConfig.java │ │ └── LokinetDaemon.java ├── lokinet_config.cpp ├── lokinet_daemon.cpp ├── lokinet_jni_common.hpp ├── network_loki_lokinet_LokinetConfig.h ├── network_loki_lokinet_LokinetDaemon.h ├── network_loki_lokinet_LokinetVPN.h ├── network_loki_lokinet_LokinetVPN_VPNInfo.h ├── network_loki_lokinet_Lokinet_JNI.h └── readme.md ├── llarp ├── CMakeLists.txt ├── address │ ├── address.cpp │ ├── address.hpp │ ├── ip_range.cpp │ ├── ip_range.hpp │ ├── map.hpp │ ├── types.hpp │ ├── utils.cpp │ └── utils.hpp ├── android │ ├── ifaddrs.c │ └── ifaddrs.h ├── app.xml ├── apple │ ├── CMakeLists.txt │ ├── DNSTrampoline.h │ ├── DNSTrampoline.m │ ├── PacketTunnelProvider.m │ ├── context.hpp │ ├── context_wrapper.cpp │ ├── context_wrapper.h │ ├── route_manager.cpp │ ├── route_manager.hpp │ ├── vpn_interface.cpp │ ├── vpn_interface.hpp │ ├── vpn_platform.cpp │ └── vpn_platform.hpp ├── auth │ ├── auth.hpp │ ├── file_auth.cpp │ ├── rpc_auth.cpp │ ├── session_auth.cpp │ └── types.hpp ├── bootstrap-fallbacks.cpp.in ├── bootstrap.cpp ├── bootstrap.hpp ├── bootstrap_fallbacks.cpp ├── config │ ├── config.cpp │ ├── config.hpp │ ├── definition.cpp │ ├── definition.hpp │ ├── ini.cpp │ └── ini.hpp ├── consensus │ ├── reachability_testing.cpp │ └── reachability_testing.hpp ├── constants │ ├── apple.hpp │ ├── files.hpp │ ├── link_layer.hpp │ ├── net.hpp │ ├── path.hpp │ ├── platform.hpp │ ├── proto.hpp │ ├── version.cpp.in │ └── version.hpp ├── contact │ ├── client_contact.cpp │ ├── client_contact.hpp │ ├── client_intro.cpp │ ├── client_intro.hpp │ ├── contactdb.cpp │ ├── contactdb.hpp │ ├── keys.cpp │ ├── keys.hpp │ ├── relay_contact.cpp │ ├── relay_contact.hpp │ ├── relay_contact_local.cpp │ ├── relay_contact_remote.cpp │ ├── router_id.cpp │ ├── router_id.hpp │ ├── sns.cpp │ ├── sns.hpp │ ├── tag.cpp │ └── tag.hpp ├── context.cpp ├── crypto │ ├── constants.hpp │ ├── crypto.cpp │ ├── crypto.hpp │ ├── key_manager.cpp │ ├── key_manager.hpp │ ├── types.cpp │ └── types.hpp ├── dns │ ├── dns.hpp │ ├── message.cpp │ ├── message.hpp │ ├── name.cpp │ ├── name.hpp │ ├── nm_platform.cpp │ ├── nm_platform.hpp │ ├── platform.cpp │ ├── platform.hpp │ ├── question.cpp │ ├── question.hpp │ ├── rr.cpp │ ├── rr.hpp │ ├── sd_platform.cpp │ ├── sd_platform.hpp │ ├── serialize.cpp │ ├── serialize.hpp │ ├── server.cpp │ ├── server.hpp │ ├── srv_data.cpp │ ├── srv_data.hpp │ └── string.hpp ├── ev │ ├── loop.cpp │ ├── loop.hpp │ ├── tcp.cpp │ ├── tcp.hpp │ ├── types.cpp │ ├── types.hpp │ ├── udp.cpp │ └── udp.hpp ├── handlers │ ├── session.cpp │ ├── session.hpp │ ├── tun.cpp │ └── tun.hpp ├── link │ ├── connection.cpp │ ├── connection.hpp │ ├── link_manager.cpp │ ├── link_manager.hpp │ ├── tunnel.cpp │ ├── tunnel.hpp │ └── types.hpp ├── linux │ ├── dbus.cpp │ ├── dbus.hpp │ └── sd_service_manager.cpp ├── lokinet_shared.cpp ├── messages │ ├── common.hpp │ ├── dht.hpp │ ├── fetch.hpp │ ├── path.hpp │ └── session.hpp ├── net │ ├── ip_headers.hpp │ ├── ip_packet.cpp │ ├── ip_packet.hpp │ ├── net.h │ ├── net.hpp │ ├── net_if.hpp │ ├── policy.cpp │ ├── policy.hpp │ ├── posix.cpp │ ├── utils.cpp │ ├── utils.hpp │ └── win32.cpp ├── nodedb.cpp ├── nodedb.hpp ├── path │ ├── path.cpp │ ├── path.hpp │ ├── path_context.cpp │ ├── path_context.hpp │ ├── path_handler.cpp │ ├── path_handler.hpp │ ├── path_types.hpp │ ├── transit_hop.cpp │ └── transit_hop.hpp ├── profiling.cpp ├── profiling.hpp ├── router │ ├── route_poker.cpp │ ├── route_poker.hpp │ ├── router.cpp │ └── router.hpp ├── router_version.cpp ├── router_version.hpp ├── rpc │ ├── json_binary_proxy.cpp │ ├── json_binary_proxy.hpp │ ├── json_bt.hpp │ ├── json_conversions.cpp │ ├── json_conversions.hpp │ ├── param_parser.hpp │ ├── rpc_client.cpp │ ├── rpc_client.hpp │ ├── rpc_request.hpp │ ├── rpc_request_decorators.hpp │ ├── rpc_request_definitions.hpp │ ├── rpc_request_parser.cpp │ ├── rpc_request_parser.hpp │ ├── rpc_server.cpp │ └── rpc_server.hpp ├── session │ ├── map.hpp │ ├── session.cpp │ └── session.hpp ├── simulation │ ├── sim_context.cpp │ └── sim_context.hpp ├── util │ ├── aligned.hpp │ ├── buffer.cpp │ ├── buffer.hpp │ ├── common.hpp │ ├── compare_ptr.hpp │ ├── decaying_hashset.hpp │ ├── decaying_hashtable.hpp │ ├── exceptions.hpp │ ├── file.cpp │ ├── file.hpp │ ├── formattable.hpp │ ├── logging.hpp │ ├── logging │ │ ├── buffer.hpp │ │ └── callback_sink.hpp │ ├── lokinet_init.h │ ├── mem.cpp │ ├── mem.h │ ├── mem.hpp │ ├── meta.hpp │ ├── nop_service_manager.cpp │ ├── random.hpp │ ├── service_manager.hpp │ ├── str.cpp │ ├── str.hpp │ ├── thread │ │ ├── barrier.hpp │ │ ├── queue.hpp │ │ ├── queue_manager.cpp │ │ ├── queue_manager.hpp │ │ ├── threading.cpp │ │ └── threading.hpp │ ├── time.cpp │ └── time.hpp ├── vpn │ ├── android.hpp │ ├── common.hpp │ ├── egres_packet_router.cpp │ ├── egres_packet_router.hpp │ ├── linux.hpp │ ├── packet_intercept.hpp │ ├── packet_io.hpp │ ├── packet_router.cpp │ ├── packet_router.hpp │ ├── platform.cpp │ ├── platform.hpp │ ├── win32.cpp │ └── win32.hpp └── win32 │ ├── dll.cpp │ ├── dll.hpp │ ├── exception.cpp │ ├── exception.hpp │ ├── exec.cpp │ ├── exec.hpp │ ├── guid.hpp │ ├── handle.hpp │ ├── service_manager.cpp │ ├── service_manager.hpp │ ├── version.rc.in │ ├── win32_inet.c │ ├── win32_intrnl.c │ ├── windivert.cpp │ ├── windivert.hpp │ ├── wintun.cpp │ └── wintun.hpp ├── pybind ├── CMakeLists.txt ├── common.hpp ├── llarp │ ├── config.cpp │ ├── context.cpp │ ├── crypto │ │ └── types.cpp │ ├── dht │ │ └── dht_types.cpp │ ├── handlers │ │ ├── pyhandler.cpp │ │ └── pyhandler.hpp │ ├── logger.cpp │ ├── path │ │ ├── path_hop_config.cpp │ │ └── path_types.cpp │ ├── peerstats.cpp │ ├── router.cpp │ ├── router_contact.cpp │ ├── router_id.cpp │ ├── service │ │ └── address.cpp │ └── tooling │ │ ├── router_event.cpp │ │ └── router_hive.cpp ├── module.cpp └── readme.md ├── readme.md ├── readme_es.md ├── readme_fr.md ├── readme_ru.md ├── test ├── CMakeLists.txt ├── check_main.cpp ├── config │ ├── test_llarp_config_definition.cpp │ ├── test_llarp_config_ini.cpp │ ├── test_llarp_config_output.cpp │ └── test_llarp_config_values.cpp ├── crypto │ ├── test_llarp_crypto.cpp │ ├── test_llarp_crypto_types.cpp │ └── test_llarp_key_manager.cpp ├── dns │ └── test_llarp_dns_dns.cpp ├── hive │ ├── conftest.py │ ├── hive.py │ ├── test_path_builds.py │ └── test_peer_stats.py ├── mocks │ ├── mock_context.hpp │ ├── mock_network.hpp │ ├── mock_router.hpp │ └── mock_vpn.hpp ├── net │ ├── test_ip_address.cpp │ ├── test_llarp_net.cpp │ └── test_sock_addr.cpp ├── nodedb │ └── test_nodedb.cpp ├── path │ └── test_path.cpp ├── peerstats │ ├── test_peer_db.cpp │ └── test_peer_types.cpp ├── readme.md ├── router │ └── test_llarp_router_version.cpp ├── routing │ ├── test_llarp_routing_obtainexitmessage.cpp │ └── test_llarp_routing_transfer_traffic.cpp ├── service │ ├── test_llarp_service_address.cpp │ ├── test_llarp_service_identity.cpp │ └── test_llarp_service_name.cpp ├── test_llarp_encrypted_frame.cpp ├── test_llarp_router_contact.cpp ├── test_util.cpp ├── test_util.hpp ├── util │ ├── meta │ │ └── test_llarp_util_memfn.cpp │ ├── test_llarp_util_aligned.cpp │ ├── test_llarp_util_bencode.cpp │ ├── test_llarp_util_bits.cpp │ ├── test_llarp_util_decaying_hashset.cpp │ ├── test_llarp_util_log_level.cpp │ ├── test_llarp_util_str.cpp │ └── thread │ │ ├── test_llarp_util_queue.cpp │ │ └── test_llarp_util_queue_manager.cpp └── win32 │ └── test.rc └── win32-setup ├── .gitignore ├── Makefile ├── config_migration.bat ├── curl-win32.patch ├── extra_create_icons.nsis ├── extra_delete_icons.nsis ├── extra_install.nsis ├── extra_preinstall.nsis ├── extra_uninstall.nsis ├── libsodium-1.0.17-win32.patch ├── libsodium-1.0.18-win32.patch ├── lokinet-win32.iss ├── lokinet.ico ├── mbedtls-win32.patch ├── notes.txt └── regdb_helper.c /.clang-tidy: -------------------------------------------------------------------------------- 1 | HeaderFilterRegex: 'llarp/.*' 2 | Checks: 3 | 'readability-else-after-return, 4 | clang-analyzer-core-*,modernize-*, 5 | -modernize-use-trailing-return-type, 6 | -modernize-use-nodiscard, 7 | bugprone-*, 8 | -bugprone-easily-swappable-parameters' 9 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((c++-mode 2 | (eval add-hook 'before-save-hook #'clang-format-buffer nil t)) 3 | (c-mode 4 | (eval add-hook 'before-save-hook #'clang-format-buffer nil t))) 5 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .vscode/ 3 | lokinet 4 | lokinet.exe 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | external/date/test export-ignore 2 | external/nlohmann/doc export-ignore 3 | external/nlohmann/test export-ignore 4 | external/nlohmann/benchmarks/data export-ignore 5 | *.signed binary 6 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | * RUN `make format && make lint -j8` BEFORE COMMITING ALWAYS. 3 | 4 | * no tabs 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 16 | **Screenshots Or Logs** 17 | If applicable, add screenshots or log files to help explain your problem. 18 | 19 | **Device and Operating system (please complete the following information):** 20 | - OS: [e.g. iOS, Windows, Android] 21 | - Device: [ e.g. Mac, PC, IPhone] 22 | - Lokinet Version number or Git commit hash: 23 | -------------------------------------------------------------------------------- /.github/workflows/clean_issues.yml: -------------------------------------------------------------------------------- 1 | name: Close incomplete issues 2 | on: 3 | schedule: 4 | - cron: "30 1 * * *" 5 | 6 | jobs: 7 | close-issues: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | steps: 12 | - uses: actions/stale@v4.1.1 13 | with: 14 | only-labels: incomplete 15 | days-before-issue-stale: 14 16 | days-before-issue-close: 7 17 | stale-issue-label: "stale" 18 | stale-issue-message: "This issue is stale because it has been 'incomplete' for 14 days with no activity." 19 | close-issue-message: "This issue was closed because it has been inactive for 7 days since being marked as stale." 20 | days-before-pr-stale: -1 21 | days-before-pr-close: -1 22 | repo-token: ${{ secrets.GITHUB_TOKEN }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *\#* 3 | 4 | *.a 5 | *.o 6 | *.so 7 | 8 | /build*/ 9 | **/__pycache__/** 10 | 11 | llarpd 12 | *.test 13 | *.bin 14 | 15 | *.ninja 16 | cmake_install.cmake 17 | CMakeFiles 18 | CMakeCache.txt 19 | .ninja_log 20 | .ninja_deps 21 | /.cache/ 22 | /compile_commands.json 23 | 24 | callgrind.* 25 | .gdb_history 26 | 27 | *.sig 28 | *.signed 29 | !/contrib/bootstrap/mainnet.signed 30 | !/contrib/bootstrap/testnet.signed 31 | *.key 32 | 33 | shadow.data 34 | shadow.config.xml 35 | *.log 36 | *.pdf 37 | *.xz 38 | 39 | testnet_tmp 40 | 41 | 42 | *.pid 43 | vsproject/ 44 | .vs 45 | 46 | *.ini 47 | 48 | 49 | .gradle/ 50 | .idea 51 | .vscode 52 | build64/ 53 | build2/ 54 | /contrib/lokinet-bootstrap-winnt/cacert.pem 55 | /contrib/lokinet-bootstrap-winnt/data.enc 56 | /contrib/lokinet-bootstrap-winnt/out.bine 57 | default.profraw 58 | 59 | # ctags shit 60 | GTAGS 61 | GRTAGS 62 | GPATH 63 | version.txt 64 | 65 | lokinet-bootstrap.exe 66 | regdbhelper.dll 67 | # xcode 68 | xcuserdata/ 69 | 70 | scc.py 71 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/nlohmann"] 2 | path = external/nlohmann 3 | url = https://github.com/nlohmann/json.git 4 | [submodule "test/Catch2"] 5 | path = test/Catch2 6 | url = https://github.com/catchorg/Catch2 7 | [submodule "external/pybind11"] 8 | path = external/pybind11 9 | url = https://github.com/pybind/pybind11 10 | branch = stable 11 | [submodule "external/sqlite_orm"] 12 | path = external/sqlite_orm 13 | url = https://github.com/fnc12/sqlite_orm 14 | [submodule "external/oxen-mq"] 15 | path = external/oxen-mq 16 | url = https://github.com/oxen-io/oxen-mq 17 | [submodule "external/cpr"] 18 | path = external/cpr 19 | url = https://github.com/whoshuu/cpr 20 | [submodule "gui"] 21 | path = gui 22 | url = https://github.com/oxen-io/lokinet-gui.git 23 | [submodule "external/CLI11"] 24 | path = external/CLI11 25 | url = https://github.com/CLIUtils/CLI11.git 26 | [submodule "external/oxen-libquic"] 27 | path = external/oxen-libquic 28 | url = https://github.com/oxen-io/oxen-libquic.git 29 | [submodule "external/oxen-encoding"] 30 | path = external/oxen-encoding 31 | url = https://github.com/session-foundation/oxen-encoding.git 32 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 5.4.2 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | [Español](CONTRIBUTING_es.md) 2 | # Do 3 | 4 | * Act like a responsible adult. 5 | 6 | * RUN `./contrib/format.sh` BEFORE COMMITING ALWAYS. 7 | 8 | # Do NOT 9 | 10 | * Bring off topic or non technical issues to the issue tracker. 11 | 12 | * Pester contributors. 13 | 14 | # We WILL 15 | 16 | * Merge Spelling mistake corrections (I have lots of those because spelling is HARD) 17 | 18 | * Merge code based on its correctness, Including patches via email from (pseudo/fully) anonymous contributors. 19 | 20 | # We WILL NOT 21 | 22 | * Accept patches with tabs 23 | 24 | * Merge large and pointless or pedantic changes, (i.e. code formatting shift) 25 | 26 | ## additional notes 27 | 28 | github's ui doesn't seem accept this file as a real code of conduct. 29 | -------------------------------------------------------------------------------- /CONTRIBUTING_es.md: -------------------------------------------------------------------------------- 1 | [Ingles](CONTRIBUTING.md) 2 | # Lo que debe 3 | 4 | * Actuar como un adulto responsable. 5 | 6 | * CORRER `make format` SIEMPRE ANTES DEL COMMIT. 7 | 8 | # Lo que NO debe 9 | 10 | * Plantear asuntos fuera de lugar o que no son tecnicos en el registro de problemas. 11 | 12 | * Ser un contribuyente molestoso. 13 | 14 | # Lo que nosotros HAREMOS 15 | 16 | * Integrar correcciones de Ortografia (Yo tengo un monton porque la ortografia es COMPLICADA) 17 | 18 | * Integrar codigo en base a que tan correcto es, Incluyendo parches recibidos por correo electronico de contribuyentes (pseudo/completamente) anonimos. 19 | 20 | # Lo que nosotros NO HAREMOS 21 | 22 | * Aceptar parches con tabulaciones 23 | 24 | * Integrar cambios grandes sin sentido o pedantes, (por ejemplo codigo con cambios de formato) 25 | 26 | ## notas adicionales 27 | 28 | github no parece aceptar este archivo como un codigo de conducta real. 29 | -------------------------------------------------------------------------------- /cmake/CMakeGraphVizOptions.cmake: -------------------------------------------------------------------------------- 1 | set(GRAPHVIZ_GRAPH_NAME "graph.dot" CACHE STRING "") 2 | set(GRAPHVIZ_GENERATE_PER_TARGET FALSE CACHE BOOL "") 3 | set(GRAPHVIZ_GENERATE_DEPENDERS FALSE CACHE BOOL "") 4 | set(GRAPHVIZ_OBJECT_LIBS OFF CACHE BOOL "") 5 | -------------------------------------------------------------------------------- /cmake/add_import_library.cmake: -------------------------------------------------------------------------------- 1 | function(add_import_library libname) 2 | add_library(libname SHARED IMPORTED) 3 | if(NOT TARGET libname) 4 | message(FATAL "unable to find library ${libname}") 5 | endif() 6 | endfunction() 7 | -------------------------------------------------------------------------------- /cmake/cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") 2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") 3 | endif() 4 | 5 | file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) 6 | string(REGEX REPLACE "\n" ";" files "${files}") 7 | foreach(file ${files}) 8 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 9 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 10 | exec_program( 11 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 12 | OUTPUT_VARIABLE rm_out 13 | RETURN_VALUE rm_retval 14 | ) 15 | if(NOT "${rm_retval}" STREQUAL 0) 16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 17 | endif() 18 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 20 | endif() 21 | endforeach() 22 | -------------------------------------------------------------------------------- /cmake/coverage.cmake: -------------------------------------------------------------------------------- 1 | if (WITH_COVERAGE) 2 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 3 | add_compile_options( -fprofile-instr-generate -fcoverage-mapping ) 4 | link_libraries( -fprofile-instr-generate ) 5 | else() 6 | add_compile_options( --coverage -g0 ) 7 | link_libraries( --coverage ) 8 | endif() 9 | endif() 10 | -------------------------------------------------------------------------------- /cmake/cross_compile.cmake: -------------------------------------------------------------------------------- 1 | # dynamic linking does this all the time 2 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 3 | option(NO_LIBGCC "use libunwind+compiler-rt instead, must already be installed in mingw-w64 sysroot" OFF) 4 | add_compile_options(-Wno-unused-command-line-argument -Wno-c++11-narrowing) 5 | add_compile_options($<$:-Wno-bad-function-cast>) 6 | if (NO_LIBGCC) 7 | find_library(UNWIND_LIB unwind) 8 | link_libraries(${UNWIND_LIB}) 9 | find_library(PSAPI_LIB psapi) 10 | link_libraries(${PSAPI_LIB}) 11 | endif(NO_LIBGCC) 12 | else() 13 | # found it. this is GNU only 14 | add_compile_options(-Wno-cast-function-type) 15 | endif() 16 | -------------------------------------------------------------------------------- /cmake/enable_lto.cmake: -------------------------------------------------------------------------------- 1 | # -flto 2 | include(CheckIPOSupported) 3 | option(WITH_LTO "enable lto on compile time" ON) 4 | if(WITH_LTO) 5 | if(WIN32) 6 | message(FATAL_ERROR "LTO not supported on win32 targets, please set -DWITH_LTO=OFF") 7 | endif() 8 | check_ipo_supported(RESULT IPO_ENABLED OUTPUT ipo_error) 9 | if(IPO_ENABLED) 10 | message(STATUS "LTO enabled") 11 | else() 12 | message(WARNING "LTO not supported by compiler: ${ipo_error}") 13 | endif() 14 | else() 15 | message(STATUS "LTO disabled") 16 | set(IPO_ENABLED OFF) 17 | endif() 18 | 19 | function(enable_lto) 20 | if(IPO_ENABLED) 21 | set_target_properties(${ARGN} PROPERTIES INTERPROCEDURAL_OPTIMIZATION ON) 22 | endif() 23 | endfunction() 24 | -------------------------------------------------------------------------------- /cmake/gui-option.cmake: -------------------------------------------------------------------------------- 1 | set(default_build_gui OFF) 2 | if(APPLE OR WIN32) 3 | set(default_build_gui ON) 4 | endif() 5 | 6 | if(WIN32) 7 | set(GUI_EXE "" CACHE FILEPATH "path to a pre-built Windows GUI .exe to use (implies -DBUILD_GUI=OFF)") 8 | if(GUI_EXE) 9 | set(default_build_gui OFF) 10 | endif() 11 | endif() 12 | 13 | option(BUILD_GUI "build electron gui from 'gui' submodule source" ${default_build_gui}) 14 | 15 | if(BUILD_GUI AND GUI_EXE) 16 | message(FATAL_ERROR "-DGUI_EXE=... and -DBUILD_GUI=ON are mutually exclusive") 17 | endif() 18 | -------------------------------------------------------------------------------- /cmake/solaris.cmake: -------------------------------------------------------------------------------- 1 | if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS") 2 | set(SOLARIS ON) 3 | set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lsocket -lnsl") 4 | add_definitions(-D_POSIX_PTHREAD_SEMANTICS) 5 | endif() 6 | -------------------------------------------------------------------------------- /cmake/target_link_libraries_system.cmake: -------------------------------------------------------------------------------- 1 | # This adds a dependency as a "system" dep - e.g -isystem 2 | function(target_link_libraries_system target) 3 | set(libs ${ARGN}) 4 | foreach(lib ${libs}) 5 | get_target_property(lib_include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES) 6 | target_include_directories(${target} SYSTEM PUBLIC ${lib_include_dirs}) 7 | target_link_libraries(${target} PUBLIC ${lib}) 8 | endforeach(lib) 9 | endfunction() 10 | -------------------------------------------------------------------------------- /cmake/unix.cmake: -------------------------------------------------------------------------------- 1 | if(NOT ANDROID) 2 | if(NOT UNIX) 3 | return() 4 | endif() 5 | endif() 6 | 7 | include(CheckCXXSourceCompiles) 8 | include(CheckLibraryExists) 9 | 10 | add_definitions(-DUNIX) 11 | add_definitions(-DPOSIX) 12 | 13 | if(EMBEDDED_CFG OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux") 14 | link_libatomic() 15 | endif() 16 | 17 | if (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") 18 | add_definitions(-D_BSD_SOURCE) 19 | add_definitions(-D_GNU_SOURCE) 20 | add_definitions(-D_XOPEN_SOURCE=700) 21 | endif() 22 | -------------------------------------------------------------------------------- /contrib/NetworkManager/dnsmasq/README.md: -------------------------------------------------------------------------------- 1 | Place in `/etc/NetworkManager/dnsmasq.d/lokinet.conf`. 2 | 3 | To make use of this, first install dnsmasq. 4 | 5 | Then enable NetworkManager dnsmasq backend by editing `/etc/NetworkManager/NetworkManager.conf` to something like: 6 | ``` 7 | [main] 8 | dns=dnsmasq 9 | ``` 10 | If NetworkManager is currently running, restart it for changes to take effect: 11 | ``` 12 | sudo systemctl restart NetworkManager 13 | ``` 14 | -------------------------------------------------------------------------------- /contrib/NetworkManager/dnsmasq/lokinet.conf: -------------------------------------------------------------------------------- 1 | server=/loki/snode/127.3.2.1 2 | -------------------------------------------------------------------------------- /contrib/android.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set +x 4 | 5 | root="$(readlink -f $(dirname $0)/../)" 6 | cd "$root" 7 | ./contrib/android-configure.sh . build-android "$@" 8 | make -C build-android -j ${JOBS:-$(nproc)} 9 | -------------------------------------------------------------------------------- /contrib/apparmor/usr.bin.lokinet: -------------------------------------------------------------------------------- 1 | # Last Modified: Fri 05 Feb 2021 08:13:58 PM UTC 2 | #include 3 | 4 | profile lokinet /usr/bin/lokinet { 5 | #include 6 | #include 7 | 8 | capability net_admin, 9 | capability net_bind_service, 10 | 11 | network inet dgram, 12 | network inet6 dgram, 13 | network netlink raw, 14 | 15 | /etc/loki/lokinet.ini r, 16 | /dev/net/tun rw, 17 | /usr/bin/lokinet mr, 18 | 19 | owner /{var/,}lib/lokinet/ rw, 20 | owner /{var/,}lib/lokinet/** rwk, 21 | owner ${HOME}/.lokinet/ rw, 22 | owner ${HOME}/.lokinet/** rwk, 23 | owner @{PROC}/@{pid}/task/@{pid}/comm rw, 24 | owner /tmp/lokinet.*/{**,} rw, 25 | 26 | #include if exists 27 | } 28 | -------------------------------------------------------------------------------- /contrib/apply-patches.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | for f in "$@" ; do 3 | patch -p1 -i "$f" 4 | done 5 | -------------------------------------------------------------------------------- /contrib/bootstrap/mainnet.signed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/bootstrap/mainnet.signed -------------------------------------------------------------------------------- /contrib/bootstrap/make-bootstrap-list.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo -n 'l' 3 | for arg in $@ ; do cat "$arg" ; done 4 | echo -n 'e' 5 | -------------------------------------------------------------------------------- /contrib/bootstrap/readme.txt: -------------------------------------------------------------------------------- 1 | usage: 2 | 3 | ./make-bootstrap-list.sh $(find $HOME/.lokinet/netdb | grep \\.signed$) > bootstrap.signed 4 | -------------------------------------------------------------------------------- /contrib/bootstrap/testnet.signed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/bootstrap/testnet.signed -------------------------------------------------------------------------------- /contrib/ci/docker/readme.md: -------------------------------------------------------------------------------- 1 | ## drone-ci docker jizz 2 | 3 | To rebuild all ci images and push them to the oxen registry server do: 4 | 5 | $ docker login registry.oxen.rocks 6 | $ ./rebuild-docker-images.py 7 | 8 | If you aren't part of the Oxen team, you'll likely need to set up your own registry and change 9 | registry.oxen.rocks to your own domain name in order to do anything useful with this. 10 | -------------------------------------------------------------------------------- /contrib/ci/drone-check-static-libs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script used with Drone CI to check that a statically build lokinet only links against the expected 4 | # base system libraries. Expects to be run with pwd of the build directory. 5 | 6 | set -o errexit 7 | 8 | bad= 9 | if [ "$DRONE_STAGE_OS" == "darwin" ]; then 10 | if otool -L llarp/apple/org.lokinet.network-extension.systemextension/Contents/MacOS/org.lokinet.network-extension | \ 11 | grep -Ev '^llarp/apple:|^\t(/usr/lib/lib(System\.|c\+\+|objc))|/System/Library/Frameworks/(CoreFoundation|NetworkExtension|Foundation|Network)\.framework'; then 12 | bad=1 13 | fi 14 | elif [ "$DRONE_STAGE_OS" == "linux" ]; then 15 | if ldd daemon/lokinet | grep -Ev '(linux-vdso|ld-linux-(x86-64|armhf|aarch64)|lib(pthread|dl|rt|stdc\+\+|gcc_s|c|m))\.so'; then 16 | bad=1 17 | fi 18 | else 19 | echo -e "\n\n\n\n\e[31;1mDon't know how to check linked libs on $DRONE_STAGE_OS\e[0m\n\n\n" 20 | exit 1 21 | fi 22 | 23 | if [ -n "$bad" ]; then 24 | echo -e "\n\n\n\n\e[31;1mlokinet links to unexpected libraries\e[0m\n\n\n" 25 | exit 1 26 | fi 27 | 28 | echo -e "\n\n\n\n\e[32;1mNo unexpected linked libraries found\e[0m\n\n\n" 29 | -------------------------------------------------------------------------------- /contrib/ci/drone-debs-upload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script used with Drone CI to upload debs from the deb building pipelines (because specifying all 4 | # this in .drone.jsonnet is too painful). This is expected to run from the base project dir after 5 | # having build with debuild (which will leave the debs in ..). 6 | 7 | set -o errexit 8 | 9 | distro="$1" 10 | 11 | if [ -z "$distro" ]; then 12 | echo "Bad usage: need distro name as first argument" 13 | exit 1 14 | fi 15 | 16 | if [ -z "$SSH_KEY" ]; then 17 | echo -e "\n\n\n\e[31;1mUnable to upload debs: SSH_KEY not set\e[0m" 18 | # Just warn but don't fail, so that this doesn't trigger a build failure for untrusted builds 19 | exit 0 20 | fi 21 | 22 | echo "$SSH_KEY" >~/ssh_key 23 | 24 | set -o xtrace # Don't start tracing until *after* we write the ssh key 25 | 26 | chmod 600 ~/ssh_key 27 | 28 | upload_to="oxen.rocks/debs/${DRONE_REPO// /_}@${DRONE_BRANCH// /_}/$(date --date=@$DRONE_BUILD_CREATED +%Y%m%dT%H%M%SZ)-${DRONE_COMMIT:0:9}/$distro/$DRONE_STAGE_ARCH" 29 | 30 | # sftp doesn't have any equivalent to mkdir -p, so we have to split the above up into a chain of 31 | # -mkdir a/, -mkdir a/b/, -mkdir a/b/c/, ... commands. The leading `-` allows the command to fail 32 | # without error. 33 | upload_dirs=(${upload_to//\// }) 34 | mkdirs= 35 | dir_tmp="" 36 | for p in "${upload_dirs[@]}"; do 37 | dir_tmp="$dir_tmp$p/" 38 | mkdirs="$mkdirs 39 | -mkdir $dir_tmp" 40 | done 41 | 42 | sftp -i ~/ssh_key -b - -o StrictHostKeyChecking=off drone@oxen.rocks </dev/null) 5 | if [ $? -ne 0 ]; then 6 | CLANG_FORMAT=$(command -v clang-format-mp-$CLANG_FORMAT_DESIRED_VERSION 2>/dev/null) 7 | fi 8 | if [ $? -ne 0 ]; then 9 | CLANG_FORMAT=$(command -v clang-format 2>/dev/null) 10 | if [ $? -ne 0 ]; then 11 | echo "Please install clang-format version $CLANG_FORMAT_DESIRED_VERSION and re-run this script." 12 | exit 1 13 | fi 14 | version=$(clang-format --version) 15 | if [[ ! $version == *"clang-format version $CLANG_FORMAT_DESIRED_VERSION"* ]]; then 16 | echo "Please install clang-format version $CLANG_FORMAT_DESIRED_VERSION and re-run this script." 17 | exit 1 18 | fi 19 | fi 20 | -------------------------------------------------------------------------------- /contrib/git-hook-pre-push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # pre-push hook for git 4 | # this script is probably overkill for most contributors 5 | # 6 | # "i use this to prevent foot cannons caused by commiting broken code" 7 | # 8 | # ~ jeff (lokinet author and crazy person) 9 | # 10 | # 11 | # to use this as a git hook do this in the root of the repo: 12 | # 13 | # cp contrib/git-hook-pre-push.sh .git/hooks/pre-push 14 | # 15 | 16 | 17 | set -e 18 | 19 | cd "$(dirname $0)/../.." 20 | echo "check format..." 21 | ./contrib/format.sh verify 22 | echo "format is gucci af fam" 23 | 24 | echo "remove old test build directory..." 25 | rm -rf build-git-hook 26 | mkdir build-git-hook 27 | echo "configuring test build jizz..." 28 | cmake -S . -B build-git-hook -DWITH_LTO=OFF -DWITH_HIVE=ON -G Ninja 29 | echo "ensure this shit compiles..." 30 | ninja -C build-git-hook all 31 | echo "ensure unit tests aren't fucked..." 32 | ninja -C build-git-hook check 33 | 34 | echo "we gud UmU" 35 | echo "" 36 | -------------------------------------------------------------------------------- /contrib/keygen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # .loki secret key generator script 4 | # makes keyfile contents 5 | # 6 | # usage: python3 keygen.py out.private 7 | # python3 keygen.py > /some/where/over/the/rainbow 8 | # 9 | from nacl.bindings import crypto_sign_keypair 10 | import sys 11 | 12 | out = sys.stdout 13 | 14 | close_out = lambda : None 15 | args = sys.argv[1:] 16 | 17 | if args and args[0] != '-': 18 | out = open(args[0], 'wb') 19 | close_out = out.close 20 | 21 | pk, sk = crypto_sign_keypair() 22 | out.write(b'64:') 23 | out.write(sk) 24 | out.flush() 25 | close_out() 26 | 27 | -------------------------------------------------------------------------------- /contrib/liblokinet/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cmake_minimum_required(VERSION 3.10) 3 | 4 | project(udptest LANGUAGES CXX) 5 | 6 | set(CMAKE_CXX_STANDARD 17) 7 | add_executable(udptest udptest.cpp) 8 | include_directories(../../include) 9 | target_link_libraries(udptest PUBLIC lokinet) 10 | 11 | -------------------------------------------------------------------------------- /contrib/liblokinet/readme.md: -------------------------------------------------------------------------------- 1 | # liblokinet examples 2 | 3 | building: 4 | 5 | $ mkdir -p build 6 | $ cd build 7 | $ cp /path/to/liblokinet.so . 8 | $ cmake .. -DCMAKE_EXE_LINKER_FLAGS='-L.' 9 | $ make 10 | 11 | running: 12 | 13 | $ ./udptest /path/to/bootstrap.signed 14 | -------------------------------------------------------------------------------- /contrib/lokinet-mac.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 13 | 14 | 26 | 27 | 28 | 29 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /contrib/lokinet-resolvconf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to invoke resolvconf (if installed) to add/remove lokinet into/from the resolvconf DNS 4 | # server list. This script does not add if any of these are true: 5 | # 6 | # - /sbin/resolvconf does not exist 7 | # - the systemd-resolved service is active 8 | # - a `no-resolvconf=1` item is present in the [dns] section of lokinet.ini 9 | # 10 | # It always attempts to remove if resolvconf is installed (so that commenting out while running, 11 | # then stopping still removes the added entry). 12 | # 13 | # Usage: lokinet-resolvconf {add|remove} /etc/loki/lokinet.ini 14 | 15 | set -e 16 | 17 | action="$1" 18 | conf="$2" 19 | 20 | if [[ ! ("$action" == "add" || "$action" == "remove") || ! -f "$conf" ]]; then 21 | echo "Usage: $0 {add|remove} /path/to/lokinet.ini" >&2 22 | exit 1 23 | fi 24 | 25 | if ! [ -x /sbin/resolvconf ]; then 26 | exit 0 27 | fi 28 | 29 | if [ -x /bin/systemctl ] && /bin/systemctl --quiet is-active systemd-resolved.service; then 30 | exit 0 31 | fi 32 | 33 | if [ "$action" == "add" ]; then 34 | if ! [ -x /sbin/resolvconf ]; then exit 0; fi 35 | 36 | lokinet_ns=$(perl -e ' 37 | $ns = "127.3.2.1"; # default if none found in .ini 38 | while (<>) { 39 | if ((/^\[dns\]/ ... /^\[/)) { 40 | if (/^bind\s*=\s*([\d.]+)(?::53)?\s*$/) { 41 | $ns=$1; 42 | } elsif (/^no-resolvconf\s*=\s*1\s*/) { 43 | exit; 44 | } 45 | } 46 | } 47 | print $ns' "$conf") 48 | 49 | if [ -n "$lokinet_ns" ]; then 50 | echo "nameserver $lokinet_ns" | /sbin/resolvconf -a lo.000lokinet 51 | fi 52 | else 53 | /sbin/resolvconf -d lo.000lokinet 54 | fi 55 | -------------------------------------------------------------------------------- /contrib/lokinet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /contrib/mac-configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | if ! [ -f LICENSE ] || ! [ -d llarp ]; then 7 | echo "You need to run this as ./contrib/mac.sh from the top-level lokinet project directory" >&2 8 | exit 1 9 | fi 10 | 11 | mkdir -p build-mac 12 | cd build-mac 13 | cmake \ 14 | -G Ninja \ 15 | -DBUILD_STATIC_DEPS=ON \ 16 | -DWITH_TESTS=OFF \ 17 | -DWITH_BOOTSTRAP=OFF \ 18 | -DNATIVE_BUILD=OFF \ 19 | -DWITH_LTO=ON \ 20 | -DCMAKE_BUILD_TYPE=Release \ 21 | -DMACOS_SYSTEM_EXTENSION=ON \ 22 | -DCODESIGN=ON \ 23 | -DBUILD_PACKAGE=ON \ 24 | "$@" \ 25 | .. 26 | 27 | echo "cmake build configured in build-mac" 28 | -------------------------------------------------------------------------------- /contrib/mac.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Build the shit on mac 4 | # 5 | # You will generally need to add: -DCODESIGN_APP=... to make this work, and (unless you are a 6 | # lokinet team member) will need to pay Apple money for your own team ID and arse around with 7 | # provisioning profiles. See macos/README.txt. 8 | # 9 | 10 | set -e 11 | set -x 12 | 13 | if ! [ -f LICENSE ] || ! [ -d llarp ]; then 14 | echo "You need to run this as ./contrib/mac.sh from the top-level lokinet project directory" >&2 15 | exit 1 16 | fi 17 | 18 | ./contrib/mac-configure.sh "$@" 19 | 20 | cd build-mac 21 | rm -rf Lokinet\ * 22 | ninja -j${JOBS:-1} dmg 23 | cd .. 24 | 25 | echo -e "Build complete, your app is here:\n" 26 | ls -lad $(pwd)/build-mac/Lokinet\ * 27 | echo "" 28 | -------------------------------------------------------------------------------- /contrib/macos/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/macos/InfoPlist.strings -------------------------------------------------------------------------------- /contrib/macos/installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/macos/installer.png -------------------------------------------------------------------------------- /contrib/macos/installer.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/macos/installer.tiff -------------------------------------------------------------------------------- /contrib/macos/installer@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/macos/installer@2x.png -------------------------------------------------------------------------------- /contrib/macos/lokinet-extension.dev.provisionprofile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/macos/lokinet-extension.dev.provisionprofile -------------------------------------------------------------------------------- /contrib/macos/lokinet-extension.plugin.entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.application-identifier 6 | SUQ8J2PCT7.org.lokinet.network-extension 7 | 8 | com.apple.developer.networking.networkextension 9 | 10 | packet-tunnel-provider 11 | dns-proxy 12 | 13 | 14 | com.apple.developer.team-identifier 15 | SUQ8J2PCT7 16 | 17 | com.apple.security.app-sandbox 18 | 19 | 20 | com.apple.security.network.client 21 | 22 | 23 | com.apple.security.network.server 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /contrib/macos/lokinet-extension.release.provisionprofile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/macos/lokinet-extension.release.provisionprofile -------------------------------------------------------------------------------- /contrib/macos/lokinet-extension.sysext.entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.application-identifier 6 | SUQ8J2PCT7.org.lokinet.network-extension 7 | 8 | com.apple.developer.networking.networkextension 9 | 10 | packet-tunnel-provider-systemextension 11 | dns-proxy-systemextension 12 | 13 | 14 | com.apple.developer.team-identifier 15 | SUQ8J2PCT7 16 | 17 | com.apple.security.app-sandbox 18 | 19 | 20 | com.apple.security.application-groups 21 | 22 | SUQ8J2PCT7.org.lokinet 23 | 24 | 25 | com.apple.security.network.client 26 | 27 | 28 | com.apple.security.network.server 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /contrib/macos/lokinet-newsyslog.conf: -------------------------------------------------------------------------------- 1 | /var/log/lokinet.log 644 5 5M $D0 J -------------------------------------------------------------------------------- /contrib/macos/lokinet.Info.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | 8 | CFBundleExecutable 9 | Lokinet 10 | 11 | CFBundleIdentifier 12 | org.lokinet 13 | 14 | CFBundleInfoDictionaryVersion 15 | 6.0 16 | 17 | CFBundleName 18 | Lokinet 19 | 20 | CFBundleIconFile 21 | icon.icns 22 | 23 | CFBundlePackageType 24 | APPL 25 | 26 | CFBundleShortVersionString 27 | @lokinet_VERSION@ 28 | 29 | CFBundleVersion 30 | @lokinet_VERSION@.@LOKINET_APPLE_BUILD@ 31 | 32 | LSMinimumSystemVersion 33 | 10.15 34 | 35 | NSHumanReadableCopyright 36 | Copyright © 2022 The Oxen Project, licensed under GPLv3-or-later 37 | 38 | LSUIElement 39 | 40 | 41 | LSHasLocalizedDisplayName 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /contrib/macos/lokinet.dev.provisionprofile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/macos/lokinet.dev.provisionprofile -------------------------------------------------------------------------------- /contrib/macos/lokinet.plugin.entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.application-identifier 6 | SUQ8J2PCT7.org.lokinet 7 | 8 | com.apple.developer.networking.networkextension 9 | 10 | packet-tunnel-provider 11 | dns-proxy 12 | dns-settings 13 | 14 | 15 | com.apple.developer.team-identifier 16 | SUQ8J2PCT7 17 | 18 | com.apple.security.app-sandbox 19 | 20 | 21 | com.apple.security.network.client 22 | 23 | 24 | com.apple.security.network.server 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /contrib/macos/lokinet.release.provisionprofile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/contrib/macos/lokinet.release.provisionprofile -------------------------------------------------------------------------------- /contrib/macos/lokinet.sysext.entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.application-identifier 6 | SUQ8J2PCT7.org.lokinet 7 | 8 | com.apple.developer.networking.networkextension 9 | 10 | packet-tunnel-provider-systemextension 11 | dns-proxy-systemextension 12 | dns-settings 13 | 14 | 15 | com.apple.developer.team-identifier 16 | SUQ8J2PCT7 17 | 18 | com.apple.developer.system-extension.install 19 | 20 | 21 | com.apple.security.app-sandbox 22 | 23 | 24 | com.apple.security.application-groups 25 | 26 | SUQ8J2PCT7.org.lokinet 27 | 28 | 29 | com.apple.security.network.client 30 | 31 | 32 | com.apple.security.network.server 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /contrib/macos/seticon.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import AppKit 3 | 4 | // Apple deprecated their command line tools to set images on things and replaced them with a 5 | // barely-documented swift function. Yay! 6 | 7 | // Usage: ./seticon /path/to/my.icns /path/to/some.dmg 8 | 9 | let args = CommandLine.arguments 10 | 11 | if args.count != 3 { 12 | print("Error: usage: ./seticon /path/to/my.icns /path/to/some.dmg") 13 | exit(1) 14 | } 15 | 16 | var icns = args[1] 17 | var dmg = args[2] 18 | 19 | var img = NSImage(byReferencingFile: icns)! 20 | 21 | if NSWorkspace.shared.setIcon(img, forFile: dmg) { 22 | print("Set \(dmg) icon to \(icns) [\(img.size)]") 23 | } else { 24 | print("Setting icon failed, don't know why") 25 | exit(2) 26 | } 27 | -------------------------------------------------------------------------------- /contrib/make-ico.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Invoked from cmake as make-ico.sh /path/to/icon.svg /path/to/output.ico 4 | svg="$1" 5 | out="$2" 6 | outdir="$out.d" 7 | 8 | set -e 9 | 10 | sizes=(16 24 32 40 48 64 96 192 256) 11 | outs="" 12 | 13 | mkdir -p "${outdir}" 14 | for size in "${sizes[@]}"; do 15 | outf="${outdir}/${size}x${size}.png" 16 | if [ $size -lt 32 ]; then 17 | # For 16x16 and 24x24 we crop the image to 2/3 of its regular size make it all white 18 | # (instead of transparent) to zoom in on it a bit because if we resize the full icon to the 19 | # target size it ends up a fuzzy mess, while the crop and resize lets us retain some detail 20 | # of the logo. 21 | rsvg-convert -b white \ 22 | --page-height $size --page-width $size \ 23 | -w $(($size*3/2)) -h $(($size*3/2)) --left " -$(($size/4))" --top " -$(($size/4))" \ 24 | "$svg" >"$outf" 25 | else 26 | rsvg-convert -b transparent -w $size -h $size "$svg" >"$outf" 27 | fi 28 | outs="-r $outf $outs" 29 | done 30 | 31 | icotool -c -b 32 -o "$out" $outs 32 | -------------------------------------------------------------------------------- /contrib/patches/libzmq-mingw-unistd.patch: -------------------------------------------------------------------------------- 1 | diff --git a/tests/testutil.hpp b/tests/testutil.hpp 2 | index c6f5e4de78..09b9fa77e5 100644 3 | --- a/tests/testutil.hpp 4 | +++ b/tests/testutil.hpp 5 | @@ -41,6 +41,9 @@ 6 | // For AF_INET and IPPROTO_TCP 7 | #if defined _WIN32 8 | #include "../src/windows.hpp" 9 | +#if defined(__MINGW32__) 10 | +#include 11 | +#endif 12 | #else 13 | #include 14 | #include 15 | -------------------------------------------------------------------------------- /contrib/patches/libzmq-mingw-wepoll.patch: -------------------------------------------------------------------------------- 1 | diff --git a/external/wepoll/wepoll.c b/external/wepoll/wepoll.c 2 | --- a/external/wepoll/wepoll.c 3 | +++ b/external/wepoll/wepoll.c 4 | @@ -140,9 +140,9 @@ 5 | #pragma warning(push, 1) 6 | #endif 7 | 8 | -#include 9 | -#include 10 | -#include 11 | +#include 12 | +#include 13 | +#include 14 | 15 | #ifndef __GNUC__ 16 | #pragma warning(pop) 17 | -------------------------------------------------------------------------------- /contrib/patches/unbound-delete-crash-fix.patch: -------------------------------------------------------------------------------- 1 | commit 56d816014d5e8a7eb055169c7e13a303dad5e50f 2 | Author: Jason Rhinelander 3 | Date: Mon Oct 31 22:07:03 2022 -0300 4 | 5 | Set tube->ev_listen to NULL to prevent double unregister 6 | 7 | On windows when using threaded mode (i.e. `ub_ctx_async(ctx, 1)`) 8 | tube_remove_bg_listen gets called twice: once when the thread does its 9 | own cleanup, then again in `tube_delete()`. Because `ev_listen` doesn't 10 | get cleared, however, we end we calling ub_winsock_unregister_wsaevent 11 | with a freed pointer. 12 | 13 | This doesn't always manifest because, apparently, for various compilers 14 | and settings that memory *might* be overwritten in which case the 15 | additional check for ev->magic will prevent anything actually happening, 16 | but in my case under mingw32 that doesn't happen and we end up 17 | eventually crashing. 18 | 19 | This fixes the crash by properly NULLing the pointer so that the second 20 | ub_winsock_unregister_wsaevent(...) becomes a no-op. 21 | 22 | diff --git a/util/tube.c b/util/tube.c 23 | index 43455fee..a92dfa77 100644 24 | --- a/util/tube.c 25 | +++ b/util/tube.c 26 | @@ -570,6 +570,7 @@ void tube_remove_bg_listen(struct tube* tube) 27 | { 28 | verbose(VERB_ALGO, "tube remove_bg_listen"); 29 | ub_winsock_unregister_wsaevent(tube->ev_listen); 30 | + tube->ev_listen = NULL; 31 | } 32 | 33 | void tube_remove_bg_write(struct tube* tube) 34 | -------------------------------------------------------------------------------- /contrib/py/.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | v 3 | __pycache__ 4 | dist -------------------------------------------------------------------------------- /contrib/py/admin/.gitignore: -------------------------------------------------------------------------------- 1 | v/ -------------------------------------------------------------------------------- /contrib/py/admin/requirements.txt: -------------------------------------------------------------------------------- 1 | requests -------------------------------------------------------------------------------- /contrib/py/ffi-example/lokinet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | from ctypes import * 5 | import signal 6 | import time 7 | import threading 8 | import os 9 | 10 | lib_file = os.path.join(os.path.realpath('.'), 'liblokinet.so') 11 | 12 | class LokiNET(threading.Thread): 13 | 14 | lib = None 15 | ctx = None 16 | 17 | def load(self, lib, conf): 18 | self.lib = CDLL(lib) 19 | self.lib.llarp_ensure_config(conf) 20 | self.ctx = self.lib.llarp_main_init(conf) 21 | return self.ctx != 0 22 | 23 | def inform_fail(self): 24 | """ 25 | inform lokinet crashed 26 | """ 27 | 28 | def inform_end(self): 29 | """ 30 | inform lokinet ended clean 31 | """ 32 | 33 | 34 | def signal(self, sig): 35 | if self.ctx and self.lib: 36 | self.lib.llarp_main_signal(self.ctx, int(sig)) 37 | 38 | def run(self): 39 | code = self.lib.llarp_main_run(self.ctx) 40 | print("llarp_main_run exited with status {}".format(code)) 41 | if code: 42 | self.inform_fail() 43 | else: 44 | self.inform_end() 45 | 46 | def close(self): 47 | if self.lib and self.ctx: 48 | self.lib.llarp_main_free(self.ctx) 49 | 50 | def main(): 51 | loki = LokiNET() 52 | if loki.load(lib_file, b'daemon.ini'): 53 | if loki.configure(): 54 | loki.start() 55 | else: 56 | print("failed to configure lokinet context") 57 | try: 58 | while True: 59 | time.sleep(1) 60 | except KeyboardInterrupt: 61 | llarp.signal(signal.SIGINT) 62 | finally: 63 | loki.close() 64 | return 65 | 66 | 67 | if __name__ == '__main__': 68 | main() 69 | -------------------------------------------------------------------------------- /contrib/py/keygen/.gitignore: -------------------------------------------------------------------------------- 1 | *.private -------------------------------------------------------------------------------- /contrib/py/keygen/keygen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | keygen tool for lokinet 4 | """ 5 | 6 | from argparse import ArgumentParser as AP 7 | from base64 import b32encode 8 | 9 | from nacl.signing import SigningKey 10 | 11 | def base32z(data): 12 | """ base32 z encode """ 13 | return b32encode(data).translate( 14 | bytes.maketrans( 15 | b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', 16 | b'ybndrfg8ejkmcpqxot1uwisza345h769')).decode().rstrip('=') 17 | 18 | 19 | def main(): 20 | """ 21 | main function for keygen 22 | """ 23 | argparser = AP() 24 | argparser.add_argument('--keyfile', type=str, required=True, help='place to put generated keys') 25 | args = argparser.parse_args() 26 | secret = SigningKey.generate() 27 | with open(args.keyfile, 'wb') as wfile: 28 | wfile.write(b'd1:s64:') 29 | wfile.write(secret.encode()) 30 | wfile.write(secret.verify_key.encode()) 31 | wfile.write(b'e') 32 | print("{}.loki".format(base32z(secret.verify_key.encode()))) 33 | 34 | if __name__ == '__main__': 35 | main() 36 | -------------------------------------------------------------------------------- /contrib/py/keygen/readme.md: -------------------------------------------------------------------------------- 1 | # lokinet key generator 2 | 3 | requires: 4 | 5 | * python3.7 or higher 6 | * pynacl 7 | 8 | usage: 9 | 10 | ```bash 11 | ./keygen.py --keyfile somekeyfile.private 12 | ``` 13 | 14 | this will overwrite the keyfile with new keys 15 | -------------------------------------------------------------------------------- /contrib/py/lnproxy/readme.md: -------------------------------------------------------------------------------- 1 | # LN Proxy 2 | 3 | embedded lokinet that provides an http tunnel proxy (using http connect) 4 | 5 | if `python3-requests` is installed then we can bootstrap from url using `--bootstrap-url` flag 6 | 7 | usage: 8 | 9 | $ python3 -m lnproxy [--ip ip | --port port] 10 | -------------------------------------------------------------------------------- /contrib/readme-installer.txt: -------------------------------------------------------------------------------- 1 | Lokinet is the reference implementation of LLARP (low latency anonymous routing protocol), a layer 3 onion routing protocol. 2 | 3 | This installer provides the needed control panel to get up an running on Lokinet. 4 | 5 | You can view additional documentation and information on Lokinet at https://lokinet.org 6 | -------------------------------------------------------------------------------- /contrib/systemd-resolved/README.md: -------------------------------------------------------------------------------- 1 | Lokinet now talks to systemd directly via sdbus to set up DNS, but in order for this to work the 2 | user running lokinet (assumed `_lokinet` in these example files) needs permission to set dns servers 3 | and domains. 4 | 5 | To set up the permissions: 6 | 7 | - If lokinet is running as some user other than `_lokinet` the change the `_lokinet` username inside 8 | `lokinet.rules` and `lokinet.pkla`. 9 | 10 | - If on a Debian or Debian-derived distribution (such as Ubuntu) using polkit 105, 11 | copy `lokinet.pkla` to `/var/lib/polkit-1/localauthority/10-vendor.d/lokinet.pkla` (for a distro 12 | install) or `/etc/polkit-1/localauthority.conf.d/` (for a local install). 13 | 14 | - Copy `lokinet.rules` to `/usr/share/polkit-1/rules.d/` (distro install) or `/etc/polkit-1/rules.d` 15 | (local install). 16 | 17 | Make use of it by switching to systemd-resolved: 18 | ``` 19 | sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf 20 | sudo systemctl enable --now systemd-resolved 21 | ``` 22 | -------------------------------------------------------------------------------- /contrib/systemd-resolved/lokinet.pkla: -------------------------------------------------------------------------------- 1 | [Allow lokinet to set DNS settings] 2 | Identity=unix-user:_lokinet 3 | Action=org.freedesktop.resolve1.set-dns-servers;org.freedesktop.resolve1.set-domains 4 | ResultAny=yes 5 | -------------------------------------------------------------------------------- /contrib/systemd-resolved/lokinet.rules: -------------------------------------------------------------------------------- 1 | /* Allow lokinet to set DNS settings */ 2 | polkit.addRule(function(action, subject) { 3 | if ((action.id == "org.freedesktop.resolve1.set-dns-servers" || 4 | action.id == "org.freedesktop.resolve1.set-domains") && 5 | subject.user == "_lokinet") { 6 | return polkit.Result.YES; 7 | } 8 | }); 9 | 10 | -------------------------------------------------------------------------------- /contrib/tarball.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # create signed release tarball with submodules bundled 4 | # usage: ./contrib/tarball.sh [keyid] 5 | # 6 | repo=$(readlink -e $(dirname $0)/..) 7 | branch=$(test -e $repo/.git/ && git rev-parse --abbrev-ref HEAD) 8 | out="lokinet-$(git describe --exact-match --tags $(git log -n1 --pretty='%h') 2> /dev/null || ( echo -n $branch- && git rev-parse --short HEAD)).tar.xz" 9 | git-archive-all -C $repo --force-submodules $out && rm -f $out.sig && (gpg -u ${1:-jeff@lokinet.io} --sign --detach $out &> /dev/null && gpg --verify $out.sig) 10 | -------------------------------------------------------------------------------- /contrib/windows-configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -x 4 | 5 | # Usage: windows-configure.sh [rootdir [builddir]] -DWHATEVER=BLAH ... 6 | 7 | if [ $# -ge 1 ] && [[ "$1" != -* ]]; then 8 | root="$1" 9 | shift 10 | else 11 | root="$(dirname $0)"/.. 12 | fi 13 | root="$(readlink -f "$root")" 14 | 15 | if [ $# -ge 1 ] && [[ "$1" != -* ]]; then 16 | build="$(readlink -f "$1")" 17 | shift 18 | else 19 | build="$root/build/win32" 20 | echo "Setting up build in $build" 21 | fi 22 | 23 | mkdir -p "$build" 24 | cmake \ 25 | -S "$root" -B "$build" \ 26 | -G 'Unix Makefiles' \ 27 | -DCMAKE_EXE_LINKER_FLAGS=-fstack-protector \ 28 | -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always \ 29 | -DCMAKE_TOOLCHAIN_FILE="$root/contrib/cross/mingw64.cmake" \ 30 | -DCMAKE_BUILD_TYPE=Release \ 31 | -DBUILD_STATIC_DEPS=ON \ 32 | -DBUILD_PACKAGE=ON \ 33 | -DBUILD_SHARED_LIBS=OFF \ 34 | -DBUILD_TESTING=OFF \ 35 | -DWITH_TESTS=OFF \ 36 | -DWITH_BOOTSTRAP=OFF \ 37 | -DNATIVE_BUILD=OFF \ 38 | -DSTATIC_LINK=ON \ 39 | -DWITH_SYSTEMD=OFF \ 40 | -DFORCE_OXENMQ_SUBMODULE=ON \ 41 | -DFORCE_OXENC_SUBMODULE=ON \ 42 | -DFORCE_FMT_SUBMODULE=ON \ 43 | -DFORCE_SPDLOG_SUBMODULE=ON \ 44 | -DFORCE_NLOHMANN_SUBMODULE=ON \ 45 | -DWITH_LTO=OFF \ 46 | "$@" 47 | -------------------------------------------------------------------------------- /contrib/windows.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # helper script for me for when i cross compile for windows 4 | # t. jeff 5 | # 6 | 7 | set -e 8 | set +x 9 | root="$(readlink -f $(dirname $0)/../)" 10 | mkdir -p $root/build/win32 11 | $root/contrib/windows-configure.sh $root $root/build/win32 "$@" 12 | make package -j${JOBS:-$(nproc)} -C $root/build/win32 13 | 14 | -------------------------------------------------------------------------------- /docs/Doxyfile.in: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = "Lokinet" 2 | PROJECT_NUMBER = v@lokinet_VERSION@ 3 | PROJECT_BRIEF = "Anonymous, decentralized and IP based overlay network for the internet." 4 | OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@ 5 | STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ @PROJECT_BINARY_DIR@ 6 | JAVADOC_AUTOBRIEF = YES 7 | ALIASES = "rst=\verbatim embed:rst" 8 | ALIASES += "endrst=\endverbatim" 9 | BUILTIN_STL_SUPPORT = YES 10 | INPUT = @lokinet_doc_sources_spaced@ 11 | INCLUDE_PATH = @PROJECT_SOURCE_DIR@/include @PROJECT_SOURCE_DIR@/llarp @PROJECT_SOURCE_DIR@/external/ghc-filesystem/include/ 12 | RECURSIVE = YES 13 | CLANG_ASSISTED_PARSING = NO 14 | #CLANG_OPTIONS = -std=c++17 -Wno-pragma-once-outside-header 15 | GENERATE_HTML = NO 16 | HTML_OUTPUT = doxyhtml 17 | GENERATE_LATEX = NO 18 | GENERATE_XML = YES 19 | XML_OUTPUT = doxyxml 20 | MACRO_EXPANSION = YES 21 | -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | Low Latency Anonymous Routing Protocol Specification 2 | Written in 2017 by Jeff Becker 3 | 4 | To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to 5 | this protocol specfication to the public domain worldwide. This software is distributed without any warranty. 6 | You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see 7 | . 8 | -------------------------------------------------------------------------------- /docs/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseUrl": "", 3 | "indexInFolders": false, 4 | "linkSuffix": ".md", 5 | "mainPageInRoot": false, 6 | "mainPageName": "index", 7 | "linkLowercase": false, 8 | "foldersToGenerate": ["files", "classes", "namespaces"] 9 | } 10 | -------------------------------------------------------------------------------- /docs/doxygen.md: -------------------------------------------------------------------------------- 1 | 2 | # Doxygen 3 | 4 | building doxygen docs requires the following: 5 | 6 | * cmake 7 | * doxygen 8 | * sphinx-build 9 | * sphinx readthedocs theme 10 | * breathe 11 | * exhale 12 | 13 | install packages: 14 | 15 | $ sudo apt install make cmake doxygen python3-sphinx python3-sphinx-rtd-theme python3-breathe python3-pip 16 | $ pip3 install --user exhale 17 | 18 | build docs: 19 | 20 | $ mkdir -p build-docs 21 | $ cd build-docs 22 | $ cmake .. && make doc 23 | 24 | serve built docs via http, will be served at http://127.0.0.1:8000/ 25 | 26 | $ python3 -m http.server -d docs/html 27 | 28 | -------------------------------------------------------------------------------- /docs/exit-setup.md: -------------------------------------------------------------------------------- 1 | 2 | to configure lokinet to be an exit add into `lokinet.ini`: 3 | 4 | [router] 5 | min-connections=8 6 | max-connections=16 7 | 8 | [network] 9 | exit=true 10 | keyfile=/var/lib/lokinet/exit.private 11 | reachable=1 12 | ifaddr=10.0.0.1/16 13 | hops=2 14 | paths=8 15 | 16 | 17 | post setup for exit (as root) given `eth0` is used to get to the internet: 18 | 19 | # echo 1 > /proc/sys/net/ipv4/ip_forward 20 | # iptables -t nat -A POSTROUTING -s 10.0.0.0/16 -o eth0 -j MASQUERADE 21 | -------------------------------------------------------------------------------- /docs/fix-markdown.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # apply markdown file content quarks 3 | 4 | 5 | # rewrite br tags 6 | sed -i 's|
|
|g' $@ 7 | -------------------------------------------------------------------------------- /docs/index.md.in: -------------------------------------------------------------------------------- 1 | # Lokinet @lokinet_VERSION@ (git rev: @GIT_VERSION@) 2 | 3 | summary goes here 4 | 5 | ## Overview 6 | 7 | [code internals](index_namespaces.md) 8 | -------------------------------------------------------------------------------- /docs/liblokinet-dev-guide.md: -------------------------------------------------------------------------------- 1 | # Embedding Lokinet into an existing application 2 | 3 | When all else fails and you want to deploy lokinet inside your app without the OS caring you can embed an entire lokinet client and a few of the upper network layers into your application manually. 4 | 5 | ## Why you should avoid this route 6 | 7 | `// TODO: this` 8 | 9 | ## When you cannot avoid this route, how do i use it? 10 | 11 | `// TODO: this` 12 | -------------------------------------------------------------------------------- /docs/lokinet_pathbuild_no_steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/docs/lokinet_pathbuild_no_steps.png -------------------------------------------------------------------------------- /docs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Lokinet 2 | theme: 3 | name: 'readthedocs' 4 | docs_dir: markdown 5 | site_dir: html 6 | -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | # Lokinet Docs 2 | 3 | This is where Lokinet documentation lives. 4 | 5 | ## Contents: 6 | 7 | ### Local Environment Set-Up 8 | - [Installing Lokinet](install.md) 9 | - [Using Lokinet](ideal-ux.md) 10 | 11 | 12 | ### High Level Overview 13 | - [Lokinet versus \[insert network technology name here\]](net-comparisons.md) 14 | - [Lokinet architecture](architecture.md) 15 | - [Lokinet and DNS](dns-overview.md) 16 | - [Limitations of Lokinet](we-cannot-make-sandwiches.md) 17 | 18 | 19 | ### Lokinet Internals 20 | - [Git repo layout and project structure](project-structure.md) 21 | - [Building Doxygen Docs for internals](doxygen.md) 22 | 23 | 24 | ### Lokinet (SN)Application Developer Portal 25 | - [SNapps development overview](snapps-dev-guide.md) 26 | - [Embedded Lokinet](liblokinet-dev-guide.md) 27 | -------------------------------------------------------------------------------- /docs/snapps-dev-guide.md: -------------------------------------------------------------------------------- 1 | # (SN)Apps Development Guide 2 | 3 | 4 | ## Our approach 5 | 6 | `// TODO: this` 7 | 8 | ## Differences From Other approaches 9 | 10 | `// TODO: this` 11 | 12 | ### SOCKS Proxy/HTTP Tunneling 13 | 14 | `// TODO: this` 15 | 16 | ### Embedding a network stack 17 | 18 | `// TODO: this` 19 | 20 | ## High Level Code Practices 21 | 22 | `// TODO: this` 23 | 24 | ### Goodisms 25 | 26 | `// TODO: this` 27 | 28 | ### Badisms 29 | 30 | `// TODO: this` 31 | -------------------------------------------------------------------------------- /docs/spanish/LICENSE: -------------------------------------------------------------------------------- 1 | Especificaciones del Protocolo de Enrutado Anónimo de Baja Latencia - Low Latency Anonymous Routing Protocol 2 | Escrito en el 2017 por Jeff Becker 3 | 4 | En el alcance de lo posible dentro de la ley, el (los) autor(es) dedica(ron) al dominio público mundial todo 5 | el derecho de copia y los derechos relacionados y semejantes relacionados a esta especificación del protocolo. 6 | Este software se distribuido sin garantia alguna. Usted deberia tener una copia de la Dedicación de Dominio Público 7 | CC0 junto con este software. En caso contrario, vea . 8 | -------------------------------------------------------------------------------- /docs/spanish/README: -------------------------------------------------------------------------------- 1 | Carpeta de las Especificaciones del Protocolo 2 | 3 | Todo los documentos de esta carpeta están licenciados como CC0 y son del dominio público. 4 | 5 | Por favor tome nota que la implementación de referencia de LokiNET está licenciada bajo la licencia ZLIB. 6 | -------------------------------------------------------------------------------- /docs/we-cannot-make-sandwiches.md: -------------------------------------------------------------------------------- 1 | # What Lokinet can't do 2 | 3 | Lokinet does a few things very well, but obviously can't do everything. 4 | 5 | ## Anonymize OS/Application Fingerprints 6 | 7 | Mitigating OS/Application Fingerprinting is the responsibility of the OS and Applications. Lokinet is an Unspoofable IP Packet Onion router, tuning OS fingerprints to be uniform would be a great thing to have in general even outside of the context of Lokinet. The creation of such an OS bundle is a great idea, but outside the scope of Lokinet. We welcome others to develop a solution for this. 8 | 9 | ## Malware 10 | 11 | Lokinet cannot prevent running of malicious programs. Computer security unfortunately cannot be solved unilaterally by networking software without simply dropping all incoming and outgoing traffic. 12 | 13 | ## Phoning Home 14 | 15 | Lokinet cannot prevent software which sends arbitrary usage data or private information to Microsoft/Apple/Google/Amazon/Facebook/etc. If you are using a service that requires the ability to phone home in order to work, that is a price you pay to use that service. 16 | 17 | ## Make Sandwiches 18 | 19 | At its core, Lokinet is technology that anonymizes and authenticates IP traffic. At this current time Lokinet cannot make you a sandwich. No, not even as root. 20 | -------------------------------------------------------------------------------- /external/readme.md: -------------------------------------------------------------------------------- 1 | directory for git submodules 2 | 3 | * CLI11: cli argument parser 4 | * cpr: curl for people, used by lokinet-bootstrap toolchain (to be removed) 5 | * ghc-filesystem: `std::filesystem` shim lib for older platforms (like macos) 6 | * ngtcp2: quic implementation 7 | * nlohmann: json parser 8 | * oxen-encoding: [bencode](https://www.bittorrent.org/beps/bep_0003.html#bencoding)/endian header-only library 9 | * oxen-logging: spdlog wrapper library 10 | * oxen-mq: zmq wrapper library for threadpool and rpc 11 | * pybind11: for pybind modules 12 | * sqlite_orm: for peer stats db 13 | * uvw: libuv header only library for main event loop -------------------------------------------------------------------------------- /include/lokinet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lokinet/addr.h" 4 | #include "lokinet/context.h" 5 | #include "lokinet/misc.h" 6 | #include "lokinet/srv.h" 7 | #include "lokinet/stream.h" 8 | #include "lokinet/udp.h" 9 | -------------------------------------------------------------------------------- /include/lokinet/addr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "context.h" 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | /// get a free()-able null terminated string that holds our .loki address 10 | /// returns NULL if we dont have one right now 11 | char* EXPORT lokinet_address(struct lokinet_context*); 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /include/lokinet/context.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "export.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef __cplusplus 10 | extern "C" 11 | { 12 | #endif 13 | 14 | struct lokinet_context; 15 | 16 | /// allocate a new lokinet context 17 | struct lokinet_context* EXPORT lokinet_context_new(); 18 | 19 | /// free a context allocated by lokinet_context_new 20 | void EXPORT lokinet_context_free(struct lokinet_context*); 21 | 22 | /// spawn all the threads needed for operation and start running 23 | /// return 0 on success 24 | /// return non zero on fail 25 | int EXPORT lokinet_context_start(struct lokinet_context*); 26 | 27 | /// return 0 if we our endpoint has published on the network and is ready to send 28 | /// return -1 if we don't have enough paths ready 29 | /// retrun -2 if we look deadlocked 30 | /// retrun -3 if context was null or not started yet 31 | int EXPORT lokinet_status(struct lokinet_context*); 32 | 33 | /// wait at most N milliseconds for lokinet to build paths and get ready 34 | /// return 0 if we are ready 35 | /// return nonzero if we are not ready 36 | int EXPORT lokinet_wait_for_ready(int N, struct lokinet_context*); 37 | 38 | /// stop all operations on this lokinet context 39 | void EXPORT lokinet_context_stop(struct lokinet_context*); 40 | 41 | /// load a bootstrap RC from memory 42 | /// return 0 on success 43 | /// return non zero on fail 44 | int EXPORT lokinet_add_bootstrap_rc(const char*, size_t, struct lokinet_context*); 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | -------------------------------------------------------------------------------- /include/lokinet/export.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | #define EXPORT __cdecl 5 | #else 6 | #define EXPORT 7 | #endif 8 | -------------------------------------------------------------------------------- /include/lokinet/misc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "export.h" 3 | #ifdef __cplusplus 4 | extern "C" 5 | { 6 | #endif 7 | 8 | /// change our network id globally across all contexts 9 | void EXPORT lokinet_set_netid(const char* netid); 10 | 11 | /// get our current netid 12 | /// must be free()'d after use 13 | const char* EXPORT lokinet_get_netid(); 14 | 15 | /// set log level 16 | /// possible values: trace, debug, info, warn, error, critical, none 17 | /// return 0 on success 18 | /// return non zero on fail 19 | int EXPORT lokinet_log_level(const char* level); 20 | 21 | /// Function pointer to invoke with lokinet log messages 22 | typedef void (*lokinet_logger_func)(const char* message, void* context); 23 | 24 | /// Optional function to call when flushing lokinet log messages; can be NULL if flushing is not 25 | /// meaningful for the logging system. 26 | typedef void (*lokinet_logger_sync)(void* context); 27 | 28 | /// set a custom logger function; it is safe (and often desirable) to call this before calling 29 | /// initializing lokinet via lokinet_context_new. 30 | void EXPORT lokinet_set_syncing_logger(lokinet_logger_func func, lokinet_logger_sync sync, void* context); 31 | 32 | /// shortcut for calling `lokinet_set_syncing_logger` with a NULL sync 33 | void EXPORT lokinet_set_logger(lokinet_logger_func func, void* context); 34 | 35 | /// @brief take in hex and turn it into base32z 36 | /// @return value must be free()'d later 37 | char* EXPORT lokinet_hex_to_base32z(const char* hex); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(lokinet-android 2 | SHARED 3 | lokinet_config.cpp 4 | lokinet_daemon.cpp) 5 | target_link_libraries(lokinet-android lokinet-amalgum) 6 | -------------------------------------------------------------------------------- /jni/java/src/network/loki/lokinet/LokinetConfig.java: -------------------------------------------------------------------------------- 1 | package network.loki.lokinet; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | public class LokinetConfig 6 | { 7 | static { 8 | System.loadLibrary("lokinet-android"); 9 | } 10 | 11 | private static native ByteBuffer Obtain(String dataDir); 12 | private static native void Free(ByteBuffer buf); 13 | 14 | /*** load config file from disk */ 15 | public native boolean Load(); 16 | /*** save chages to disk */ 17 | public native boolean Save(); 18 | 19 | 20 | /** override default config value before loading from config file */ 21 | public native void AddDefaultValue(String section, String key, String value); 22 | 23 | private final ByteBuffer impl; 24 | 25 | public LokinetConfig(String dataDir) 26 | { 27 | impl = Obtain(dataDir); 28 | if(impl == null) 29 | throw new RuntimeException("cannot obtain config from "+dataDir); 30 | } 31 | 32 | public void finalize() 33 | { 34 | if (impl != null) 35 | { 36 | Free(impl); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /jni/network_loki_lokinet_LokinetConfig.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class network_loki_lokinet_LokinetConfig */ 4 | 5 | #ifndef _Included_network_loki_lokinet_LokinetConfig 6 | #define _Included_network_loki_lokinet_LokinetConfig 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | /* 12 | * Class: network_loki_lokinet_LokinetConfig 13 | * Method: Obtain 14 | * Signature: (Ljava/lang/String;)Ljava/nio/ByteBuffer; 15 | */ 16 | JNIEXPORT jobject JNICALL Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv*, jclass, jstring); 17 | 18 | /* 19 | * Class: network_loki_lokinet_LokinetConfig 20 | * Method: Free 21 | * Signature: (Ljava/nio/ByteBuffer;)V 22 | */ 23 | JNIEXPORT void JNICALL Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv*, jclass, jobject); 24 | 25 | /* 26 | * Class: network_loki_lokinet_LokinetConfig 27 | * Method: Load 28 | * Signature: ()Z 29 | */ 30 | JNIEXPORT jboolean JNICALL Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv*, jobject); 31 | 32 | /* 33 | * Class: network_loki_lokinet_LokinetConfig 34 | * Method: Save 35 | * Signature: ()Z 36 | */ 37 | JNIEXPORT jboolean JNICALL Java_network_loki_lokinet_LokinetConfig_Save(JNIEnv*, jobject); 38 | 39 | /* 40 | * Class: network_loki_lokinet_LokinetConfig 41 | * Method: AddDefaultValue 42 | * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V 43 | */ 44 | JNIEXPORT void JNICALL 45 | Java_network_loki_lokinet_LokinetConfig_AddDefaultValue(JNIEnv*, jobject, jstring, jstring, jstring); 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | #endif 51 | -------------------------------------------------------------------------------- /jni/network_loki_lokinet_LokinetVPN_VPNInfo.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class network_loki_lokinet_LokinetVPN_VPNInfo */ 4 | 5 | #ifndef _Included_network_loki_lokinet_LokinetVPN_VPNInfo 6 | #define _Included_network_loki_lokinet_LokinetVPN_VPNInfo 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /jni/network_loki_lokinet_Lokinet_JNI.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class network_loki_lokinet_Lokinet_JNI */ 4 | 5 | #ifndef _Included_network_loki_lokinet_Lokinet_JNI 6 | #define _Included_network_loki_lokinet_Lokinet_JNI 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | /* 12 | * Class: network_loki_lokinet_Lokinet_JNI 13 | * Method: getABICompiledWith 14 | * Signature: ()Ljava/lang/String; 15 | */ 16 | JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getABICompiledWith(JNIEnv*, jclass); 17 | 18 | /* 19 | * Class: network_loki_lokinet_Lokinet_JNI 20 | * Method: startLokinet 21 | * Signature: (Ljava/lang/String;)Ljava/lang/String; 22 | */ 23 | JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_startLokinet(JNIEnv*, jclass, jstring); 24 | 25 | JNIEXPORT jstring JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getIfAddr(JNIEnv*, jclass); 26 | 27 | JNIEXPORT jint JNICALL Java_network_loki_lokinet_Lokinet_1JNI_getIfRange(JNIEnv*, jclass); 28 | 29 | /* 30 | * Class: network_loki_lokinet_Lokinet_JNI 31 | * Method: stopLokinet 32 | * Signature: ()V 33 | */ 34 | JNIEXPORT void JNICALL Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet(JNIEnv*, jclass); 35 | 36 | JNIEXPORT void JNICALL Java_network_loki_lokinet_Lokinet_1JNI_setVPNFileDescriptor(JNIEnv*, jclass, jint, jint); 37 | 38 | /* 39 | * Class: network_loki_lokinet_Lokinet_JNI 40 | * Method: onNetworkStateChanged 41 | * Signature: (Z)V 42 | */ 43 | JNIEXPORT void JNICALL Java_network_loki_lokinet_Lokinet_1JNI_onNetworkStateChanged(JNIEnv*, jclass, jboolean); 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | #endif 49 | -------------------------------------------------------------------------------- /jni/readme.md: -------------------------------------------------------------------------------- 1 | jni binding for lokinet vpn using android vpn api 2 | -------------------------------------------------------------------------------- /llarp/app.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /llarp/apple/context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "route_manager.hpp" 4 | #include "vpn_platform.hpp" 5 | 6 | #include 7 | 8 | namespace llarp::apple 9 | { 10 | struct Context : public llarp::Context 11 | { 12 | std::shared_ptr make_vpn_platform() override 13 | { 14 | return std::make_shared( 15 | *this, m_PacketWriter, m_OnReadable, route_callbacks, callback_context); 16 | } 17 | 18 | // Callbacks that must be set for packet handling *before* calling Setup/Configure/Run; the 19 | // main point of these is to get passed through to VPNInterface, which will be called during 20 | // setup, after construction. 21 | VPNInterface::packet_write_callback m_PacketWriter; 22 | VPNInterface::on_readable_callback m_OnReadable; 23 | llarp_route_callbacks route_callbacks{}; 24 | void* callback_context = nullptr; 25 | }; 26 | 27 | } // namespace llarp::apple 28 | -------------------------------------------------------------------------------- /llarp/apple/vpn_interface.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "vpn_interface.hpp" 3 | 4 | #include "context.hpp" 5 | 6 | #include 7 | 8 | namespace llarp::apple 9 | { 10 | VPNInterface::VPNInterface( 11 | Context& ctx, packet_write_callback packet_writer, on_readable_callback on_readable, Router* router) 12 | : vpn::NetworkInterface{}, 13 | _pkt_writer{std::move(packet_writer)}, 14 | _on_readable{std::move(on_readable)}, 15 | _router{router} 16 | { 17 | ctx._loop->call_soon([this] { _on_readable(*this); }); 18 | } 19 | 20 | bool VPNInterface::OfferReadPacket(const llarp_buffer_t& buf) 21 | { 22 | IPPacket pkt; 23 | if (!pkt.load(buf.copy())) 24 | return false; 25 | _read_que.tryPushBack(std::move(pkt)); 26 | return true; 27 | } 28 | 29 | void VPNInterface::MaybeWakeUpperLayers() const 30 | { 31 | // 32 | } 33 | 34 | int VPNInterface::PollFD() const { return -1; } 35 | 36 | IPPacket VPNInterface::read_next_packet() 37 | { 38 | IPPacket pkt{}; 39 | if (not _read_que.empty()) 40 | pkt = _read_que.popFront(); 41 | return pkt; 42 | } 43 | 44 | bool VPNInterface::write_packet(IPPacket pkt) 45 | { 46 | // TODO: replace this with IPPacket::to_udp 47 | (void)pkt; 48 | // int af_family = pkt() ? AF_INET6 : AF_INET; 49 | // return _pkt_writer(af_family, pkt.data(), pkt.size()); 50 | return true; 51 | } 52 | 53 | } // namespace llarp::apple 54 | -------------------------------------------------------------------------------- /llarp/apple/vpn_interface.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace llarp::apple 10 | { 11 | struct Context; 12 | 13 | class VPNInterface final : public vpn::NetworkInterface, public std::enable_shared_from_this 14 | { 15 | public: 16 | using packet_write_callback = std::function; 17 | using on_readable_callback = std::function; 18 | 19 | explicit VPNInterface( 20 | Context& ctx, packet_write_callback packet_writer, on_readable_callback on_readable, Router* router); 21 | 22 | // Method to call when a packet has arrived to deliver the packet to lokinet 23 | bool OfferReadPacket(const llarp_buffer_t& buf); 24 | 25 | int PollFD() const override; 26 | 27 | IPPacket read_next_packet() override; 28 | 29 | bool write_packet(IPPacket pkt) override; 30 | 31 | void MaybeWakeUpperLayers() const override; 32 | 33 | private: 34 | // Function for us to call when we have a packet to emit. Should return true if the packet 35 | // was handed off to the OS successfully. 36 | packet_write_callback _pkt_writer; 37 | 38 | // Called when we are ready to start reading packets 39 | on_readable_callback _on_readable; 40 | 41 | inline static constexpr auto PacketQueueSize = 1024; 42 | 43 | thread::Queue _read_que{PacketQueueSize}; 44 | 45 | Router* const _router; 46 | }; 47 | 48 | } // namespace llarp::apple 49 | -------------------------------------------------------------------------------- /llarp/apple/vpn_platform.cpp: -------------------------------------------------------------------------------- 1 | #include "vpn_platform.hpp" 2 | 3 | #include "context.hpp" 4 | 5 | namespace llarp::apple 6 | { 7 | VPNPlatform::VPNPlatform( 8 | Context& ctx, 9 | VPNInterface::packet_write_callback packet_writer, 10 | VPNInterface::on_readable_callback on_readable, 11 | llarp_route_callbacks route_callbacks, 12 | void* callback_context) 13 | : _context{ctx}, 14 | _route_manager{ctx, std::move(route_callbacks), callback_context}, 15 | _packet_writer{std::move(packet_writer)}, 16 | _read_cb{std::move(on_readable)} 17 | {} 18 | 19 | std::shared_ptr VPNPlatform::obtain_interface(vpn::InterfaceInfo, Router* router) 20 | { 21 | return std::make_shared(_context, _packet_writer, _read_cb, router); 22 | } 23 | } // namespace llarp::apple 24 | -------------------------------------------------------------------------------- /llarp/apple/vpn_platform.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "route_manager.hpp" 4 | #include "vpn_interface.hpp" 5 | 6 | #include 7 | 8 | namespace llarp::apple 9 | { 10 | class VPNPlatform final : public vpn::Platform 11 | { 12 | public: 13 | explicit VPNPlatform( 14 | Context& ctx, 15 | VPNInterface::packet_write_callback packet_writer, 16 | VPNInterface::on_readable_callback on_readable, 17 | llarp_route_callbacks route_callbacks, 18 | void* callback_context); 19 | 20 | std::shared_ptr obtain_interface(vpn::InterfaceInfo, Router*) override; 21 | 22 | vpn::AbstractRouteManager& RouteManager() override { return _route_manager; } 23 | 24 | private: 25 | Context& _context; 26 | apple::RouteManager _route_manager; 27 | VPNInterface::packet_write_callback _packet_writer; 28 | VPNInterface::on_readable_callback _read_cb; 29 | }; 30 | 31 | } // namespace llarp::apple 32 | -------------------------------------------------------------------------------- /llarp/auth/file_auth.cpp: -------------------------------------------------------------------------------- 1 | #include "auth.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp::auth 7 | { 8 | AuthResult FileAuthPolicy::check_files(const AuthInfo& info) const 9 | { 10 | for (const auto& f : _files) 11 | { 12 | std::ifstream i{f}; 13 | std::string line{}; 14 | while (std::getline(i, line)) 15 | { 16 | // split off comments 17 | const auto parts = split_any(line, "#;", true); 18 | if (auto part = parts[0]; not parts.empty() and not parts[0].empty()) 19 | { 20 | // split off whitespaces and check password 21 | if (check_passwd(std::string{TrimWhitespace(part)}, info.token)) 22 | return AuthResult{AuthCode::ACCEPTED, "accepted by whitelist"}; 23 | } 24 | } 25 | } 26 | return AuthResult{AuthCode::REJECTED, "rejected by whitelist"}; 27 | } 28 | 29 | bool FileAuthPolicy::check_passwd(std::string hash, std::string challenge) const 30 | { 31 | switch (_type) 32 | { 33 | case AuthFileType::PLAIN: 34 | return hash == challenge; 35 | case AuthFileType::HASHES: 36 | #ifdef HAVE_CRYPT 37 | return crypto::check_passwd_hash(std::move(hash), std::move(challenge)); 38 | #endif 39 | default: 40 | return false; 41 | } 42 | } 43 | 44 | } // namespace llarp::auth 45 | -------------------------------------------------------------------------------- /llarp/auth/rpc_auth.cpp: -------------------------------------------------------------------------------- 1 | #include "auth.hpp" 2 | 3 | #include 4 | 5 | namespace llarp::auth 6 | { 7 | static auto logcat = log::Cat("rpc.auth"); 8 | 9 | RPCAuthPolicy::RPCAuthPolicy(Router& r, std::string url, std::string method, std::shared_ptr lmq) 10 | : AuthPolicy{r}, 11 | _endpoint{std::move(url)}, 12 | _method{std::move(method)}, 13 | // _whitelist{std::move(whitelist_addrs)}, 14 | // _static_tokens{std::move(whitelist_tokens)}, 15 | _omq{std::move(lmq)} 16 | { 17 | if (_endpoint.empty() or _method.empty()) 18 | throw std::invalid_argument{ 19 | "RPC AuthPolicy must be initialized with an endpoint to query and a method to invoke!"}; 20 | } 21 | 22 | void RPCAuthPolicy::start() 23 | { 24 | _omq->connect_remote( 25 | _endpoint, 26 | [self = shared_from_this()](oxenmq::ConnectionID c) { 27 | self->_omq_conn = std::move(c); 28 | log::info(logcat, "OMQ connected to endpoint auth server"); 29 | }, 30 | [self = shared_from_this()](oxenmq::ConnectionID, std::string_view fail) { 31 | log::warning(logcat, "OMQ failed to connect to endpoint auth server: {}", fail); 32 | self->_router.loop()->call_later(1s, [self] { self->start(); }); 33 | }); 34 | } 35 | 36 | } // namespace llarp::auth 37 | -------------------------------------------------------------------------------- /llarp/auth/session_auth.cpp: -------------------------------------------------------------------------------- 1 | #include "auth.hpp" 2 | 3 | #include 4 | 5 | namespace llarp::auth 6 | { 7 | SessionAuthPolicy::SessionAuthPolicy(Router& r, RouterID& remote, bool is_snode, bool is_exit) 8 | : AuthPolicy{r}, 9 | _is_snode_service{is_snode}, 10 | _is_exit_service{is_exit}, 11 | _remote{NetworkAddress::from_pubkey(remote, not _is_snode_service)} 12 | { 13 | // These can both be false but CANNOT both be true 14 | if (_is_exit_service & _is_snode_service) 15 | throw std::runtime_error{"Cannot create SessionAuthPolicy for a remote exit and remote service!"}; 16 | 17 | if (_is_snode_service) 18 | _session_key = _router.identity(); 19 | else 20 | _session_key = crypto::generate_identity(); 21 | } 22 | 23 | std::optional SessionAuthPolicy::fetch_auth_token() 24 | { 25 | std::optional ret = std::nullopt; 26 | auto& exit_auths = _router.config()->network.exit_auths; 27 | 28 | if (auto itr = exit_auths.find(_remote); itr != exit_auths.end()) 29 | ret = itr->second; 30 | 31 | return ret; 32 | } 33 | 34 | bool SessionAuthPolicy::load_identity_from_file(const char* fname) { return _session_key.load_from_file(fname); } 35 | 36 | } // namespace llarp::auth 37 | -------------------------------------------------------------------------------- /llarp/auth/types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp::auth 7 | { 8 | /// authentication status code 9 | enum class AuthCode : uint64_t 10 | { 11 | /// explicitly accepted 12 | ACCEPTED = 0, 13 | /// explicitly rejected 14 | REJECTED = 1, 15 | /// attempt failed 16 | FAILED = 2, 17 | /// attempt rate limited 18 | RATE_LIMIT = 3, 19 | /// need mo munny 20 | PAYMENT_REQUIRED = 4 21 | }; 22 | 23 | /// auth result object with code and reason 24 | struct AuthResult 25 | { 26 | AuthCode code; 27 | std::string reason; 28 | }; 29 | 30 | /// info needed by clients in order to authenticate to a remote endpoint 31 | struct AuthInfo 32 | { 33 | std::string token; 34 | }; 35 | 36 | /// what kind of backend to use for auth 37 | enum class AuthType 38 | { 39 | /// no authentication 40 | NONE, 41 | /// manual whitelist 42 | WHITELIST, 43 | /// LMQ server 44 | OMQ, 45 | /// static file 46 | FILE, 47 | }; 48 | 49 | /// how to interpret an file for auth 50 | enum class AuthFileType 51 | { 52 | PLAIN, 53 | HASHES, 54 | }; 55 | 56 | } // namespace llarp::auth 57 | -------------------------------------------------------------------------------- /llarp/bootstrap-fallbacks.cpp.in: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace llarp 5 | { 6 | std::unordered_map 7 | load_bootstrap_fallbacks() 8 | { 9 | std::unordered_map fallbacks; 10 | 11 | for (const auto& [network, bootstrap] : std::initializer_list>{ 12 | @BOOTSTRAP_FALLBACKS@ 13 | }) 14 | { 15 | if (network != RelayContact::ACTIVE_NETID) 16 | continue; 17 | 18 | auto& bsl = fallbacks[network]; 19 | bsl.bt_decode(bootstrap); 20 | } 21 | 22 | return fallbacks; 23 | } 24 | } // namespace llarp 25 | -------------------------------------------------------------------------------- /llarp/bootstrap.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace llarp 10 | { 11 | struct BootstrapList final : public std::set 12 | { 13 | std::set::iterator _curr = begin(); 14 | 15 | const RemoteRC& current() { return *_curr; } 16 | 17 | bool bt_decode(std::string_view buf); 18 | 19 | bool bt_decode_dict(std::string_view buf); 20 | 21 | bool bt_decode_list(std::string_view buf); 22 | 23 | bool bt_decode(oxenc::bt_list_consumer btlc); 24 | 25 | bool bt_decode(oxenc::bt_dict_consumer btdc); 26 | 27 | std::string_view bt_encode() const; 28 | 29 | void populate_bootstraps(std::vector paths, const fs::path& def, bool load_fallbacks); 30 | 31 | bool read_from_file(const fs::path& fpath); 32 | 33 | bool contains(const RouterID& rid) const; 34 | 35 | // returns a reference to the next bootstrap in the list 36 | const RemoteRC& next() 37 | { 38 | if (size() < 2) 39 | return *_curr; 40 | 41 | ++_curr; 42 | 43 | if (_curr == this->end()) 44 | _curr = this->begin(); 45 | 46 | return *_curr; 47 | } 48 | 49 | bool contains(const RemoteRC& rc) const; 50 | 51 | void randomize() 52 | { 53 | if (size() > 1) 54 | _curr = std::next(begin(), csrng.boundedrand(size())); 55 | } 56 | 57 | void clear_list() { clear(); } 58 | }; 59 | 60 | std::unordered_map load_bootstrap_fallbacks(); 61 | 62 | } // namespace llarp 63 | -------------------------------------------------------------------------------- /llarp/bootstrap_fallbacks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | std::unordered_map load_bootstrap_fallbacks() 8 | { 9 | std::unordered_map fallbacks; 10 | 11 | for (const auto& [network, bootstrap] : std::initializer_list>{ 12 | // 13 | }) 14 | { 15 | if (network != RelayContact::ACTIVE_NETID) 16 | continue; 17 | 18 | auto& bsl = fallbacks[network]; 19 | bsl.bt_decode(bootstrap); 20 | } 21 | 22 | return fallbacks; 23 | } 24 | } // namespace llarp 25 | -------------------------------------------------------------------------------- /llarp/constants/apple.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace llarp::apple 6 | { 7 | /// Localhost port on macOS where we proxy DNS requests *through* the tunnel, because without 8 | /// calling into special snowflake Apple network APIs an extension's network connections all go 9 | /// around the tunnel, even when the tunnel is (supposedly) the default route. 10 | inline constexpr std::uint16_t dns_trampoline_port = 1053; 11 | 12 | /// We query the above trampoline from unbound with this fixed source port (so that the 13 | /// trampoline is simplified by not having to track different ports for different requests). 14 | inline constexpr std::uint16_t dns_trampoline_source_port = 1054; 15 | } // namespace llarp::apple 16 | -------------------------------------------------------------------------------- /llarp/constants/files.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "platform.hpp" 3 | 4 | #include 5 | 6 | #ifndef _WIN32 7 | #include 8 | #include 9 | #endif 10 | 11 | namespace fs = std::filesystem; 12 | 13 | namespace llarp 14 | { 15 | constexpr auto our_rc_filename = "self.signed"; 16 | constexpr auto our_identity_filename = "identity.key"; 17 | constexpr auto our_enc_key_filename = "encryption.key"; 18 | constexpr auto our_transport_key_filename = "transport.key"; 19 | 20 | constexpr auto nodedb_dirname = "nodedb"; 21 | 22 | inline fs::path GetDefaultDataDir() 23 | { 24 | if constexpr (not platform::is_windows) 25 | { 26 | fs::path datadir{"/var/lib/lokinet"}; 27 | #ifndef _WIN32 28 | if (auto uid = geteuid()) 29 | { 30 | if (auto* pw = getpwuid(uid)) 31 | { 32 | datadir = fs::path{pw->pw_dir} / ".lokinet"; 33 | } 34 | } 35 | #endif 36 | return datadir; 37 | } 38 | else 39 | return "C:\\ProgramData\\Lokinet"; 40 | } 41 | 42 | inline fs::path GetDefaultConfigFilename() { return "lokinet.ini"; } 43 | 44 | inline fs::path GetDefaultConfigPath() { return GetDefaultDataDir() / GetDefaultConfigFilename(); } 45 | 46 | inline fs::path GetDefaultBootstrap() { return GetDefaultDataDir() / "bootstrap.signed"; } 47 | 48 | } // namespace llarp 49 | -------------------------------------------------------------------------------- /llarp/constants/link_layer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | constexpr size_t MAX_LINK_MSG_SIZE = 8192; 7 | static constexpr auto DefaultLinkSessionLifetime = 5min; 8 | constexpr size_t MaxSendQueueSize = 1024 * 16; 9 | static constexpr auto LinkLayerConnectTimeout = 5s; 10 | 11 | namespace llarp::constants 12 | { 13 | static constexpr auto DefaultInboundIWPPort = uint16_t{1090}; 14 | } 15 | -------------------------------------------------------------------------------- /llarp/constants/net.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llarp::constants 4 | { 5 | constexpr auto udp_header_bytes = 8; 6 | constexpr auto ip_header_min_bytes = 20; 7 | } // namespace llarp::constants 8 | -------------------------------------------------------------------------------- /llarp/constants/path.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace llarp::path 9 | { 10 | /// maximum path length 11 | inline constexpr std::size_t MAX_LEN{8}; 12 | 13 | /// default path length 14 | inline constexpr std::size_t DEFAULT_LEN{4}; 15 | 16 | /// pad messages to the nearest this many bytes 17 | inline constexpr std::size_t PAD_SIZE{128}; 18 | 19 | // default number of paths per PathHandler 20 | inline constexpr size_t DEFAULT_PATHS_HELD{4}; 21 | 22 | /// TESTNET: default path lifetime in ms; 23 | inline constexpr std::chrono::milliseconds DEFAULT_LIFETIME{20min}; 24 | 25 | /// interval at which we try to build new paths for intros 26 | inline constexpr std::chrono::milliseconds PATH_ROTATION_INTERVAL{DEFAULT_LIFETIME / DEFAULT_PATHS_HELD}; 27 | 28 | /// after this many ms a path build times out 29 | inline constexpr auto BUILD_TIMEOUT{10s}; 30 | 31 | inline constexpr auto MIN_PATH_BUILD_INTERVAL{500ms}; 32 | 33 | inline constexpr auto PATH_BUILD_RATE{100ms}; 34 | 35 | /// measure latency every this interval ms 36 | inline constexpr std::chrono::milliseconds LATENCY_INTERVAL{20s}; 37 | 38 | /// if a path is inactive for this amount of time it's dead 39 | inline constexpr std::chrono::milliseconds ALIVE_TIMEOUT{LATENCY_INTERVAL * 3 / 2}; 40 | 41 | /// how big transit hop traffic queues are 42 | inline constexpr std::size_t TRANSIT_HOP_QUEUE_SIZE{256}; 43 | 44 | } // namespace llarp::path 45 | -------------------------------------------------------------------------------- /llarp/constants/proto.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llarp::constants 4 | { 5 | /// current network wide protocol version 6 | // TODO: enum class 7 | constexpr auto proto_version = 0; 8 | 9 | } // namespace llarp::constants 10 | -------------------------------------------------------------------------------- /llarp/constants/version.cpp.in: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace llarp 5 | { 6 | // clang-format off 7 | const std::array LOKINET_VERSION{{@lokinet_VERSION_MAJOR@, @lokinet_VERSION_MINOR@, @lokinet_VERSION_PATCH@}}; 8 | const char* const LOKINET_VERSION_TAG = "@VERSIONTAG@"; 9 | const char* const LOKINET_VERSION_FULL = "lokinet-@lokinet_VERSION_MAJOR@.@lokinet_VERSION_MINOR@.@lokinet_VERSION_PATCH@-@LOKINET_VERSION_TAG@"; 10 | 11 | const char* const LOKINET_DEFAULT_NETID = "lokinet"; 12 | const char* const LOKINET_TESTNET_NETID = "testnet"; 13 | // clang-format on 14 | } // namespace llarp 15 | -------------------------------------------------------------------------------- /llarp/constants/version.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp 7 | { 8 | // Given a full lokinet version of: lokinet-1.2.3-abc these are: 9 | extern const std::array LOKINET_VERSION; 10 | extern const char* const LOKINET_VERSION_TAG; 11 | extern const char* const LOKINET_VERSION_FULL; 12 | 13 | extern const char* const LOKINET_DEFAULT_NETID; 14 | extern const char* const LOKINET_TESTNET_NETID; 15 | } // namespace llarp 16 | -------------------------------------------------------------------------------- /llarp/contact/client_intro.cpp: -------------------------------------------------------------------------------- 1 | #include "client_contact.hpp" 2 | 3 | namespace llarp 4 | { 5 | static auto logcat = log::Cat("client-intro"); 6 | 7 | ClientIntro::ClientIntro(oxenc::bt_dict_consumer&& btdc) { bt_decode(std::move(btdc)); } 8 | 9 | ClientIntro::ClientIntro(std::string_view buf) : ClientIntro{oxenc::bt_dict_consumer{buf}} {} 10 | 11 | void ClientIntro::bt_encode(oxenc::bt_dict_producer&& subdict) const 12 | { 13 | subdict.append("k", pivot_rid.to_view()); 14 | subdict.append("p", pivot_txid.to_view()); 15 | subdict.append("x", expiry.count()); 16 | } 17 | 18 | bool ClientIntro::bt_decode(std::string_view buf) 19 | { 20 | try 21 | { 22 | bt_decode(oxenc::bt_dict_consumer{buf}); 23 | } 24 | catch (const std::exception& e) 25 | { 26 | log::critical(logcat, "ClientIntro deserialization failed: {}", e.what()); 27 | return false; 28 | } 29 | 30 | return true; 31 | } 32 | 33 | void ClientIntro::bt_decode(oxenc::bt_dict_consumer&& btdc) 34 | { 35 | pivot_rid.from_string(btdc.require("k")); 36 | pivot_txid.from_string(btdc.require("p")); 37 | expiry = std::chrono::milliseconds{btdc.require("x")}; 38 | } 39 | 40 | std::string ClientIntro::to_string() const 41 | { 42 | return "CI:[ Pivot RID:{} | Pivot TX:{} | Expiry:{} ]"_format( 43 | pivot_rid.short_string(), pivot_txid, expiry.count()); 44 | } 45 | } // namespace llarp 46 | -------------------------------------------------------------------------------- /llarp/contact/contactdb.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "client_contact.hpp" 4 | 5 | #include 6 | 7 | namespace llarp 8 | { 9 | struct Router; 10 | 11 | /** 12 | ContactDB TODO: 13 | - Store nearest-furthest expiry, trim 14 | */ 15 | 16 | using cc_map_storage = std::map; 17 | 18 | /// This class mediates storage, retrieval, and functionality for ClientContacts 19 | struct ContactDB 20 | { 21 | explicit ContactDB(Router& r); 22 | 23 | private: 24 | Router& _router; 25 | const hash_key _local_key; 26 | 27 | cc_map_storage _storage; 28 | 29 | std::shared_ptr _purge_ticker; 30 | 31 | public: 32 | std::optional get_decrypted_cc(RouterID remote) const; 33 | 34 | std::optional get_encrypted_cc(const hash_key& key) const; 35 | 36 | void put_cc(EncryptedClientContact enc); 37 | 38 | void start_tickers(); 39 | 40 | size_t num_ccs() const; 41 | 42 | private: 43 | void purge_ccs(std::chrono::milliseconds now = llarp::time_now_ms()); 44 | }; 45 | 46 | } // namespace llarp 47 | -------------------------------------------------------------------------------- /llarp/contact/keys.cpp: -------------------------------------------------------------------------------- 1 | #include "keys.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp 7 | { 8 | bool PubKey::from_hex(const std::string& str) 9 | { 10 | if (str.size() != 2 * size()) 11 | return false; 12 | oxenc::from_hex(str.begin(), str.end(), begin()); 13 | return true; 14 | } 15 | 16 | std::string PubKey::to_string() const { return oxenc::to_base32z(begin(), end()); } 17 | 18 | PubKey& PubKey::operator=(const uint8_t* ptr) 19 | { 20 | std::copy(ptr, ptr + SIZE, begin()); 21 | return *this; 22 | } 23 | 24 | PubKey& PubKey::operator=(const PubKey& other) 25 | { 26 | std::memcpy(begin(), other.begin(), PUBKEYSIZE); 27 | return *this; 28 | } 29 | 30 | bool PubKey::operator<(const PubKey& other) const { return as_array() < other.as_array(); } 31 | 32 | bool PubKey::operator==(const PubKey& other) const { return as_array() == other.as_array(); } 33 | 34 | bool PubKey::operator!=(const PubKey& other) const { return !(*this == other); } 35 | } // namespace llarp 36 | -------------------------------------------------------------------------------- /llarp/contact/keys.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /** TODO: 8 | - re-configure string_view and ustring_view methods after deprecating RouterID 9 | */ 10 | 11 | namespace llarp 12 | { 13 | struct PubKey : public AlignedBuffer 14 | { 15 | PubKey() = default; 16 | 17 | bool from_hex(const std::string& str); 18 | 19 | std::string to_string() const; 20 | 21 | explicit PubKey(const uint8_t* data) : AlignedBuffer{data} {} 22 | explicit PubKey(const std::array& data) : AlignedBuffer{data} {} 23 | explicit PubKey(ustring_view data) : AlignedBuffer{data.data()} {} 24 | explicit PubKey(std::string_view data) : PubKey{detail::to_usv(data)} {} 25 | PubKey(const PubKey& other) : PubKey{other.data()} {} 26 | PubKey(PubKey&& other) : PubKey{other.data()} {} 27 | 28 | PubKey& operator=(const PubKey& other); 29 | 30 | // revisit this 31 | PubKey& operator=(const uint8_t* ptr); 32 | 33 | bool operator<(const PubKey& other) const; 34 | bool operator==(const PubKey& other) const; 35 | bool operator!=(const PubKey& other) const; 36 | }; 37 | } // namespace llarp 38 | 39 | namespace std 40 | { 41 | template <> 42 | struct hash : public hash> 43 | {}; 44 | } // namespace std 45 | -------------------------------------------------------------------------------- /llarp/contact/relay_contact_remote.cpp: -------------------------------------------------------------------------------- 1 | #include "relay_contact.hpp" 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | static auto logcat = log::Cat("relay-contact"); 8 | 9 | RemoteRC::RemoteRC(oxenc::bt_dict_consumer btdc, bool accept_expired) 10 | { 11 | try 12 | { 13 | bt_load(btdc); 14 | bt_verify(btdc, not accept_expired); 15 | } 16 | catch (const std::exception& e) 17 | { 18 | auto err = "Exception caught parsing RemoteRC: {}"_format(e.what()); 19 | log::warning(logcat, "{}", err); 20 | throw std::runtime_error{err}; 21 | } 22 | } 23 | 24 | bool RemoteRC::read(const fs::path& fname) 25 | { 26 | log::trace(logcat, "{} called", __PRETTY_FUNCTION__); 27 | _payload.resize(MAX_RC_SIZE); 28 | 29 | try 30 | { 31 | auto nread = util::file_to_buffer(fname, _payload.data(), _payload.size()); 32 | log::trace(logcat, "{}B read from file (path:{})!", nread, fname); 33 | _payload.resize(nread); 34 | 35 | oxenc::bt_dict_consumer btdc{std::span{_payload}}; 36 | bt_load(btdc); 37 | bt_verify(btdc); 38 | } 39 | catch (const std::exception& e) 40 | { 41 | log::warning(logcat, "Failed to read or validate RC from {}: {}", fname, e.what()); 42 | return false; 43 | } 44 | 45 | return true; 46 | } 47 | 48 | bool RemoteRC::verify() const 49 | { 50 | oxenc::bt_dict_consumer btdc{std::span{_payload}}; 51 | bt_verify(btdc); 52 | return true; 53 | } 54 | 55 | } // namespace llarp 56 | -------------------------------------------------------------------------------- /llarp/contact/router_id.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace llarp 10 | { 11 | struct RouterID : public PubKey 12 | { 13 | static constexpr size_t SIZE = 32; 14 | 15 | RouterID() = default; 16 | 17 | RouterID(const uint8_t* buf) : PubKey(buf) {} 18 | 19 | RouterID(ustring_view data) : PubKey(data.data()) {} 20 | 21 | RouterID(std::span data) : PubKey(data.data()) {} 22 | 23 | RouterID(std::string_view data) : RouterID(detail::to_usv(data)) {} 24 | 25 | nlohmann::json ExtractStatus() const; 26 | 27 | std::string to_string() const; 28 | 29 | std::string to_network_address(bool is_relay = true) const; 30 | 31 | // will throw on failure! 32 | void from_network_address(std::string_view str); 33 | 34 | bool from_relay_address(std::string_view str); 35 | 36 | RouterID& operator=(const uint8_t* ptr) 37 | { 38 | std::copy(ptr, ptr + SIZE, begin()); 39 | return *this; 40 | } 41 | }; 42 | 43 | inline bool operator==(const RouterID& lhs, const RouterID& rhs) { return lhs.as_array() == rhs.as_array(); } 44 | } // namespace llarp 45 | 46 | namespace std 47 | { 48 | template <> 49 | struct hash : hash> 50 | {}; 51 | } // namespace std 52 | -------------------------------------------------------------------------------- /llarp/contact/sns.cpp: -------------------------------------------------------------------------------- 1 | #include "sns.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp 7 | { 8 | static auto logcat = llarp::log::Cat("ONSRecord"); 9 | 10 | EncryptedSNSRecord EncryptedSNSRecord::deserialize(std::string_view bt) { return EncryptedSNSRecord{bt}; } 11 | 12 | EncryptedSNSRecord::EncryptedSNSRecord(std::string_view bt) : _bt_payload{bt} 13 | { 14 | bt_decode(oxenc::bt_dict_consumer{_bt_payload}); 15 | } 16 | 17 | void EncryptedSNSRecord::bt_decode(oxenc::bt_dict_consumer&& btdc) 18 | { 19 | try 20 | { 21 | ciphertext = btdc.require("c"); 22 | nonce.from_string(btdc.require("n")); 23 | } 24 | catch (...) 25 | { 26 | log::warning(logcat, "EncryptedSNSRecord exception"); 27 | throw; 28 | } 29 | } 30 | 31 | std::string EncryptedSNSRecord::bt_encode() const 32 | { 33 | oxenc::bt_dict_producer btdp; 34 | 35 | btdp.append("c", ciphertext); 36 | btdp.append("n", nonce.to_view()); 37 | 38 | return std::move(btdp).str(); 39 | } 40 | 41 | std::optional EncryptedSNSRecord::decrypt(std::string_view ons_name) const 42 | { 43 | std::optional ret = std::nullopt; 44 | 45 | if (ciphertext.empty()) 46 | return ret; 47 | 48 | if (auto maybe = crypto::maybe_decrypt_name(ciphertext, nonce, ons_name)) 49 | { 50 | auto _name = "{}.loki"_format(maybe->to_view()); 51 | ret = NetworkAddress::from_network_addr(std::move(_name)); 52 | } 53 | 54 | return ret; 55 | } 56 | } // namespace llarp 57 | -------------------------------------------------------------------------------- /llarp/contact/tag.cpp: -------------------------------------------------------------------------------- 1 | #include "tag.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp 7 | { 8 | static auto logcat = log::Cat("session-tag"); 9 | 10 | session_tag::session_tag(uint8_t protocol) 11 | { 12 | randombytes(buf.data(), SIZE); 13 | std::memcpy(buf.data(), &protocol, sizeof(uint8_t)); 14 | log::trace(logcat, "new session tag generated: {}", buffer_printer{buf}); 15 | } 16 | 17 | session_tag session_tag::make(uint8_t protos) { return session_tag{static_cast(protos & proto_mask)}; } 18 | 19 | std::pair session_tag::proto_bits() const 20 | { 21 | auto& p = buf[0]; 22 | return {p & meta::to_underlying(protocol_flag::EXIT), p & meta::to_underlying(protocol_flag::QUICTUN)}; 23 | } 24 | 25 | void session_tag::read(std::string_view data) 26 | { 27 | if (data.size() != SIZE) 28 | throw std::invalid_argument{ 29 | "Buffer size mismatch (received: {}, expected: {}) reading in session tag!"_format(data.size(), SIZE)}; 30 | 31 | std::memcpy(buf.data(), data.data(), data.size()); 32 | } 33 | 34 | std::string_view session_tag::view() const { return {reinterpret_cast(buf.data()), buf.size()}; } 35 | 36 | uspan session_tag::span() const { return buf; } 37 | 38 | std::string session_tag::to_string() const { return oxenc::to_hex(buf.begin(), buf.end()); } 39 | } // namespace llarp 40 | -------------------------------------------------------------------------------- /llarp/contact/tag.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // #include 4 | #include 5 | #include 6 | 7 | namespace llarp 8 | { 9 | struct alignas(uint64_t) session_tag 10 | { 11 | static constexpr size_t SIZE{8}; 12 | 13 | std::array buf; 14 | 15 | session_tag() = default; 16 | 17 | private: 18 | session_tag(uint8_t protocol); 19 | 20 | public: 21 | static session_tag make(uint8_t protocol); 22 | 23 | std::pair proto_bits() const; 24 | 25 | void read(std::string_view buf); 26 | 27 | std::string_view view() const; 28 | uspan span() const; 29 | 30 | auto operator<=>(const session_tag& other) const { return buf <=> other.buf; } 31 | bool operator==(const session_tag& other) const { return (*this <=> other) == 0; } 32 | 33 | std::string to_string() const; 34 | static constexpr bool to_string_formattable = true; 35 | }; 36 | 37 | } // namespace llarp 38 | 39 | namespace std 40 | { 41 | template <> 42 | struct hash 43 | { 44 | size_t operator()(const llarp::session_tag& tag) const noexcept 45 | { 46 | return std::hash{}(tag.view()); 47 | } 48 | }; 49 | } // namespace std 50 | -------------------------------------------------------------------------------- /llarp/crypto/constants.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | static constexpr uint32_t PATHIDSIZE{16}; 6 | static constexpr uint32_t NONCESIZE{24}; 7 | static constexpr uint32_t HMACSECSIZE{32}; 8 | static constexpr uint32_t HMACSIZE{32}; 9 | static constexpr uint32_t PUBKEYSIZE{32}; 10 | static constexpr uint32_t SHAREDKEYSIZE{32}; 11 | static constexpr uint32_t SHORTHASHSIZE{32}; 12 | static constexpr uint32_t TUNNONCESIZE{32}; 13 | static constexpr uint32_t SIGSIZE{64}; 14 | static constexpr uint32_t SECKEYSIZE{64}; 15 | -------------------------------------------------------------------------------- /llarp/crypto/key_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.hpp" 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace llarp 10 | { 11 | struct Config; 12 | 13 | namespace handlers 14 | { 15 | class SessionEndpoint; 16 | } 17 | 18 | // KeyManager manages the cryptographic keys stored on disk for the local 19 | // node. This includes private keys as well as the self-signed router contact 20 | // file (e.g. "self.signed"). 21 | // 22 | // Keys are either read from disk if they exist and are valid (see below) or 23 | // are generated and written to disk. 24 | struct KeyManager 25 | { 26 | friend struct Router; 27 | friend class handlers::SessionEndpoint; 28 | 29 | private: 30 | KeyManager(const Config& config, bool is_relay); 31 | 32 | std::atomic is_initialized{false}; 33 | 34 | // Initializes keys using the provided config, loading from disk. Must be called 35 | // prior to obtaining any keys; blocks on I/O 36 | bool _initialize(const Config& config, bool is_relay); 37 | 38 | protected: 39 | static std::shared_ptr make(const Config& config, bool is_relay); 40 | 41 | Ed25519SecretKey identity_key; 42 | Ed25519PrivateData identity_data; 43 | RouterID public_key; 44 | 45 | fs::path rc_path; 46 | 47 | void update_idkey(Ed25519SecretKey&& newkey); 48 | 49 | Ed25519PrivateData derive_subkey(uint64_t domain = 1) const; 50 | 51 | public: 52 | const RouterID& router_id() const { return public_key; } 53 | }; 54 | 55 | } // namespace llarp 56 | -------------------------------------------------------------------------------- /llarp/dns/dns.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace llarp::dns 8 | { 9 | constexpr uint16_t qTypeSRV = 33; 10 | constexpr uint16_t qTypeAAAA = 28; 11 | constexpr uint16_t qTypeTXT = 16; 12 | constexpr uint16_t qTypeMX = 15; 13 | constexpr uint16_t qTypePTR = 12; 14 | constexpr uint16_t qTypeCNAME = 5; 15 | constexpr uint16_t qTypeNS = 2; 16 | constexpr uint16_t qTypeA = 1; 17 | 18 | constexpr uint16_t qClassIN = 1; 19 | 20 | constexpr uint16_t flags_QR = (1 << 15); 21 | constexpr uint16_t flags_AA = (1 << 10); 22 | constexpr uint16_t flags_TC = (1 << 9); 23 | constexpr uint16_t flags_RD = (1 << 8); 24 | constexpr uint16_t flags_RA = (1 << 7); 25 | constexpr uint16_t flags_RCODENameError = (3); 26 | constexpr uint16_t flags_RCODEServFail = (2); 27 | constexpr uint16_t flags_RCODENoError = (0); 28 | 29 | } // namespace llarp::dns 30 | -------------------------------------------------------------------------------- /llarp/dns/name.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace llarp::dns 10 | { 11 | /// decode name from buffer; return nullopt on failure 12 | std::optional DecodeName(llarp_buffer_t* buf, bool trimTrailingDot = false); 13 | 14 | /// encode name to buffer 15 | bool EncodeNameTo(llarp_buffer_t* buf, std::string_view name); 16 | 17 | std::optional DecodePTR(std::string_view name); 18 | 19 | bool NameIsReserved(std::string_view name); 20 | 21 | } // namespace llarp::dns 22 | -------------------------------------------------------------------------------- /llarp/dns/nm_platform.cpp: -------------------------------------------------------------------------------- 1 | #include "nm_platform.hpp" 2 | #ifdef WITH_SYSTEMD 3 | 4 | extern "C" 5 | { 6 | #include 7 | } 8 | 9 | #include 10 | 11 | namespace llarp::dns::nm 12 | { 13 | void Platform::set_resolver(unsigned int, oxen::quic::Address, bool) 14 | { 15 | // todo: implement me eventually 16 | } 17 | } // namespace llarp::dns::nm 18 | #endif 19 | -------------------------------------------------------------------------------- /llarp/dns/nm_platform.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "platform.hpp" 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace llarp::dns 10 | { 11 | namespace nm 12 | { 13 | // a dns platform that sets dns via network manager 14 | class Platform : public I_Platform 15 | { 16 | public: 17 | ~Platform() override = default; 18 | 19 | void set_resolver(unsigned int index, oxen::quic::Address dns, bool global) override; 20 | }; 21 | }; // namespace nm 22 | using NM_Platform_t = std::conditional_t; 23 | } // namespace llarp::dns 24 | -------------------------------------------------------------------------------- /llarp/dns/platform.cpp: -------------------------------------------------------------------------------- 1 | #include "platform.hpp" 2 | 3 | namespace llarp::dns 4 | { 5 | void Multi_Platform::add_impl(std::unique_ptr impl) { m_Impls.emplace_back(std::move(impl)); } 6 | 7 | void Multi_Platform::set_resolver(unsigned int index, oxen::quic::Address dns, bool global) 8 | { 9 | if (m_Impls.empty()) 10 | return; 11 | size_t fails{0}; 12 | for (const auto& ptr : m_Impls) 13 | { 14 | try 15 | { 16 | ptr->set_resolver(index, dns, global); 17 | } 18 | catch (std::exception& ex) 19 | { 20 | log::warning(log::Cat("dns"), "{}", ex.what()); 21 | fails++; 22 | } 23 | } 24 | if (fails == m_Impls.size()) 25 | throw std::runtime_error{"tried all ways to set resolver and failed"}; 26 | } 27 | } // namespace llarp::dns 28 | -------------------------------------------------------------------------------- /llarp/dns/question.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "name.hpp" 4 | #include "serialize.hpp" 5 | 6 | namespace llarp::dns 7 | { 8 | using QType_t = uint16_t; 9 | using QClass_t = uint16_t; 10 | 11 | struct Question : public Serialize 12 | { 13 | Question() = default; 14 | 15 | explicit Question(std::string name, QType_t type); 16 | 17 | Question(Question&& other); 18 | Question(const Question& other); 19 | 20 | bool Encode(llarp_buffer_t* buf) const override; 21 | 22 | bool Decode(llarp_buffer_t* buf) override; 23 | 24 | bool decode(std::span /* b */) override { return {}; } 25 | 26 | std::string to_string() const; 27 | 28 | bool operator==(const Question& other) const 29 | { 30 | return qname == other.qname && qtype == other.qtype && qclass == other.qclass; 31 | } 32 | 33 | std::string qname; 34 | QType_t qtype; 35 | QClass_t qclass; 36 | 37 | /// determine if we match a name 38 | bool IsName(const std::string& other) const; 39 | 40 | /// is the name [something.]localhost.loki. ? 41 | bool IsLocalhost() const; 42 | 43 | /// return true if we have subdomains in ths question 44 | bool HasSubdomains() const; 45 | 46 | /// get subdomain(s), if any, from qname 47 | std::string Subdomains() const; 48 | 49 | /// return qname with no trailing . 50 | std::string Name() const; 51 | 52 | /// determine if we are using this TLD 53 | bool HasTLD(const std::string& tld) const; 54 | 55 | nlohmann::json ToJSON() const override; 56 | }; 57 | } // namespace llarp::dns 58 | -------------------------------------------------------------------------------- /llarp/dns/rr.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "name.hpp" 4 | #include "serialize.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace llarp::dns 10 | { 11 | using RRClass_t = uint16_t; 12 | using RRType_t = uint16_t; 13 | using RR_RData_t = std::vector; 14 | using RR_TTL_t = uint32_t; 15 | 16 | struct ResourceRecord : public Serialize 17 | { 18 | ResourceRecord() = default; 19 | ResourceRecord(const ResourceRecord& other); 20 | ResourceRecord(ResourceRecord&& other); 21 | 22 | explicit ResourceRecord(std::string name, RRType_t type, RR_RData_t rdata); 23 | 24 | bool Encode(llarp_buffer_t* buf) const override; 25 | 26 | bool Decode(llarp_buffer_t* buf) override; 27 | 28 | bool decode(std::span /* b */) override { return {}; }; 29 | 30 | nlohmann::json ToJSON() const override; 31 | 32 | std::string to_string() const; 33 | 34 | bool HasCNameForTLD(const std::string& tld) const; 35 | 36 | std::string rr_name; 37 | RRType_t rr_type; 38 | RRClass_t rr_class; 39 | RR_TTL_t ttl; 40 | RR_RData_t rData; 41 | 42 | static constexpr bool to_string_formattable = true; 43 | }; 44 | } // namespace llarp::dns 45 | -------------------------------------------------------------------------------- /llarp/dns/sd_platform.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "platform.hpp" 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace llarp::dns 9 | { 10 | namespace sd 11 | { 12 | /// a dns platform that sets dns via systemd resolved 13 | class Platform : public I_Platform 14 | { 15 | public: 16 | ~Platform() override = default; 17 | 18 | void set_resolver(unsigned int if_index, oxen::quic::Address dns, bool global) override; 19 | }; 20 | } // namespace sd 21 | using SD_Platform_t = std::conditional_t; 22 | } // namespace llarp::dns 23 | -------------------------------------------------------------------------------- /llarp/dns/serialize.cpp: -------------------------------------------------------------------------------- 1 | #include "serialize.hpp" 2 | 3 | namespace llarp::dns 4 | { 5 | Serialize::~Serialize() = default; 6 | 7 | bool EncodeRData(llarp_buffer_t* buf, const std::vector& v) 8 | { 9 | if (v.size() > 65536) 10 | return false; 11 | uint16_t len = v.size(); 12 | if (!buf->put_uint16(len)) 13 | return false; 14 | if (buf->size_left() < len) 15 | return false; 16 | memcpy(buf->cur, v.data(), len); 17 | buf->cur += len; 18 | return true; 19 | } 20 | 21 | bool DecodeRData(llarp_buffer_t* buf, std::vector& v) 22 | { 23 | uint16_t len; 24 | if (!buf->read_uint16(len)) 25 | return false; 26 | size_t left = buf->size_left(); 27 | if (left < len) 28 | return false; 29 | v.resize(size_t(len)); 30 | if (len) 31 | { 32 | memcpy(v.data(), buf->cur, len); 33 | buf->cur += len; 34 | } 35 | return true; 36 | } 37 | 38 | } // namespace llarp::dns 39 | -------------------------------------------------------------------------------- /llarp/dns/serialize.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace llarp::dns 10 | { 11 | /// base type for serializable dns entities 12 | struct Serialize 13 | { 14 | virtual ~Serialize() = 0; 15 | 16 | /// encode entity to buffer 17 | virtual bool Encode(llarp_buffer_t* buf) const = 0; 18 | 19 | /// decode entity from buffer 20 | virtual bool Decode(llarp_buffer_t* buf) = 0; 21 | 22 | virtual bool decode(std::span b) = 0; 23 | 24 | /// convert this whatever into json 25 | virtual nlohmann::json ToJSON() const = 0; 26 | 27 | static constexpr bool to_string_formattable = true; 28 | }; 29 | 30 | bool EncodeRData(llarp_buffer_t* buf, const std::vector& rdata); 31 | 32 | bool DecodeRData(llarp_buffer_t* buf, std::vector& rdata); 33 | 34 | } // namespace llarp::dns 35 | -------------------------------------------------------------------------------- /llarp/dns/string.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct llarp_buffer_t; 6 | 7 | namespace llarp::dns 8 | { 9 | using name_t = std::string; 10 | 11 | /// decode name from buffer 12 | bool decode_name(llarp_buffer_t* buf, name_t& name); 13 | 14 | /// encode name to buffer 15 | bool encode_name(llarp_buffer_t* buf, const name_t& name); 16 | 17 | } // namespace llarp::dns 18 | -------------------------------------------------------------------------------- /llarp/ev/loop.cpp: -------------------------------------------------------------------------------- 1 | #include "loop.hpp" 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | static auto logcat = log::Cat("EventLoop"); 8 | 9 | std::shared_ptr EventLoop::make() { return std::shared_ptr{new EventLoop{}}; } 10 | 11 | EventLoop::EventLoop() : _loop{std::make_shared()} {} 12 | 13 | EventLoop::~EventLoop() 14 | { 15 | // _loop->shutdown(_close_immediately); 16 | log::info(logcat, "lokinet loop shut down {}", _close_immediately ? "immediately" : "gracefully"); 17 | } 18 | 19 | std::shared_ptr EventLoop::add_network_interface( 20 | std::shared_ptr netif, std::function hook) 21 | { 22 | (void)netif; 23 | (void)hook; 24 | std::shared_ptr _p; 25 | 26 | #ifdef __linux__ 27 | _p = _loop->template make_shared(netif->PollFD(), this->loop(), std::move(hook)); 28 | #else 29 | // 30 | #endif 31 | return _p; 32 | } 33 | 34 | void EventLoop::stop(bool) 35 | { 36 | // _loop->shutdown(immediate); 37 | } 38 | 39 | } // namespace llarp 40 | -------------------------------------------------------------------------------- /llarp/ev/udp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "loop.hpp" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace llarp 11 | { 12 | class EventLoop; 13 | 14 | using UDPSocket = oxen::quic::UDPSocket; 15 | 16 | using io_result = oxen::quic::io_result; 17 | 18 | class UDPHandle 19 | { 20 | public: 21 | UDPHandle() = delete; 22 | explicit UDPHandle(const std::shared_ptr& ev, const oxen::quic::Address& bind, net_pkt_hook cb); 23 | ~UDPHandle(); 24 | 25 | private: 26 | std::shared_ptr _loop; 27 | std::unique_ptr socket; 28 | oxen::quic::Address _local; 29 | 30 | io_result _send_impl(const oxen::quic::Path& path, std::byte* buf, size_t bufsize, uint8_t ecn, size_t& n_pkts); 31 | 32 | void _send_or_queue( 33 | const oxen::quic::Path& path, 34 | std::vector buf, 35 | uint8_t ecn, 36 | std::function callback = nullptr); 37 | 38 | public: 39 | const std::shared_ptr& loop() const { return _loop; } 40 | 41 | io_result send(const oxen::quic::Address& dest, bstring data); 42 | 43 | io_result send(const oxen::quic::Address& dest, std::vector data); 44 | 45 | oxen::quic::Address bind() { return _local; } 46 | }; 47 | 48 | } // namespace llarp 49 | -------------------------------------------------------------------------------- /llarp/link/connection.cpp: -------------------------------------------------------------------------------- 1 | #include "connection.hpp" 2 | 3 | namespace llarp::link 4 | { 5 | static auto logcat = llarp::log::Cat("link_conn"); 6 | 7 | Connection::Connection( 8 | std::shared_ptr c, bt_control_stream s, bool _is_relay, bool _is_active) 9 | : conn{std::move(c)}, 10 | datagrams{conn->datagrams()}, 11 | control_stream{std::move(s)}, 12 | is_active{_is_active}, 13 | remote_is_relay{_is_relay} 14 | {} 15 | 16 | void Connection::close_quietly() 17 | { 18 | log::trace(logcat, "{} called", __PRETTY_FUNCTION__); 19 | conn->set_close_quietly(); 20 | conn->close_connection(); 21 | } 22 | } // namespace llarp::link 23 | -------------------------------------------------------------------------------- /llarp/link/connection.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace llarp::link 9 | { 10 | struct Connection 11 | { 12 | Connection( 13 | std::shared_ptr c, 14 | bt_control_stream s, 15 | bool _is_relay = true, 16 | bool _is_active = false); 17 | 18 | std::shared_ptr conn; 19 | std::shared_ptr datagrams; 20 | bt_control_stream control_stream; 21 | 22 | std::atomic is_active{false}; 23 | 24 | bool remote_is_relay{true}; 25 | 26 | bool is_inbound() const { return conn->is_inbound(); } 27 | 28 | void close_quietly(); 29 | }; 30 | } // namespace llarp::link 31 | -------------------------------------------------------------------------------- /llarp/link/tunnel.cpp: -------------------------------------------------------------------------------- 1 | #include "tunnel.hpp" 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace llarp 8 | { 9 | QUICTunnel::QUICTunnel(Router& r) 10 | : _router{r}, 11 | _q{std::make_unique(_router.loop()->_loop)}, 12 | _tls_creds{oxen::quic::GNUTLSCreds::make_from_ed_keys(TUNNEL_SEED, TUNNEL_PUBKEY)} 13 | {} 14 | 15 | std::shared_ptr QUICTunnel::make(Router& r) { return r.loop()->template make_shared(r); } 16 | 17 | uint16_t QUICTunnel::listen() { return {}; } 18 | 19 | } // namespace llarp 20 | -------------------------------------------------------------------------------- /llarp/link/tunnel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace llarp 10 | { 11 | using namespace oxenc::literals; 12 | 13 | const auto LOCALHOST = "127.0.0.1"s; 14 | 15 | inline constexpr auto TUNNEL_SEED = "0000000000000000000000000000000000000000000000000000000000000000"_hex; 16 | 17 | inline constexpr auto TUNNEL_PUBKEY = "3b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29"_hex; 18 | 19 | const auto LOCALHOST_BLANK = oxen::quic::Address{LOCALHOST, 0}; 20 | 21 | namespace path 22 | { 23 | struct Path; 24 | } 25 | 26 | struct Router; 27 | 28 | class QUICTunnel 29 | { 30 | public: 31 | QUICTunnel(Router& r); 32 | 33 | static std::shared_ptr make(Router& r); 34 | 35 | private: 36 | Router& _router; 37 | 38 | // NOTE: DO NOT CHANGE THE ORDER OF THESE TWO OBJECTS 39 | std::unique_ptr _q; // constructed using the lokinet event loop 40 | std::shared_ptr _tls_creds; 41 | 42 | public: 43 | const std::unique_ptr& net() { return _q; } 44 | 45 | std::shared_ptr creds() { return _tls_creds; } 46 | 47 | uint16_t listen(); 48 | 49 | // 50 | }; 51 | 52 | } // namespace llarp 53 | -------------------------------------------------------------------------------- /llarp/link/types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | using bt_control_stream = std::shared_ptr; 8 | using bt_control_response_hook = std::function; 9 | using bt_control_send_hook = std::function; 10 | 11 | using conn_open_hook = oxen::quic::connection_established_callback; 12 | using conn_closed_hook = oxen::quic::connection_closed_callback; 13 | using stream_open_hook = oxen::quic::stream_open_callback; 14 | using stream_closed_hook = oxen::quic::stream_close_callback; 15 | 16 | using keep_alive = oxen::quic::opt::keep_alive; 17 | using inbound_alpns = oxen::quic::opt::inbound_alpns; 18 | using outbound_alpns = oxen::quic::opt::outbound_alpns; 19 | 20 | using static_secret = oxen::quic::opt::static_secret; 21 | } // namespace llarp 22 | -------------------------------------------------------------------------------- /llarp/linux/dbus.cpp: -------------------------------------------------------------------------------- 1 | #ifdef WITH_SYSTEMD 2 | #include "dbus.hpp" 3 | 4 | namespace llarp::linux 5 | { 6 | system_bus_exception::system_bus_exception(int err) 7 | : std::runtime_error{"cannot connect to system bus: " + std::string{strerror(-err)}} 8 | {} 9 | 10 | dbus_call_exception::dbus_call_exception(std::string meth, int err) 11 | : std::runtime_error{"failed to call dbus function '" + meth + "': " + std::string{strerror(-err)}} 12 | {} 13 | 14 | DBUS::DBUS(std::string _interface, std::string _instance, std::string _call) 15 | : m_interface{std::move(_interface)}, m_instance{std::move(_instance)}, m_call{std::move(_call)} 16 | { 17 | sd_bus* bus{nullptr}; 18 | if (auto err = sd_bus_open_system(&bus); err < 0) 19 | throw system_bus_exception{err}; 20 | m_ptr.reset(bus); 21 | } 22 | } // namespace llarp::linux 23 | #endif 24 | -------------------------------------------------------------------------------- /llarp/linux/sd_service_manager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace llarp::sys 11 | { 12 | class SD_Manager : public I_SystemLayerManager 13 | { 14 | llarp::sys::ServiceState m_State{ServiceState::Initial}; 15 | 16 | public: 17 | /// change our state and report it to the system layer 18 | void we_changed_our_state(ServiceState st) override 19 | { 20 | m_State = st; 21 | report_changed_state(); 22 | } 23 | 24 | void report_changed_state() override 25 | { 26 | if (m_State == ServiceState::Running) 27 | { 28 | ::sd_notify(0, "READY=1"); 29 | return; 30 | } 31 | if (m_State == ServiceState::Stopping) 32 | { 33 | ::sd_notify(0, "STOPPING=1"); 34 | return; 35 | } 36 | } 37 | 38 | void report_periodic_stats() override 39 | { 40 | if (m_Context and m_Context->router and not m_disable) 41 | { 42 | auto status = fmt::format("WATCHDOG=1\nSTATUS={}", m_Context->router->status_line()); 43 | ::sd_notify(0, status.c_str()); 44 | } 45 | } 46 | 47 | void system_changed_our_state(ServiceState) override 48 | { 49 | // not applicable on systemd 50 | } 51 | }; 52 | 53 | SD_Manager _manager{}; 54 | I_SystemLayerManager* const service_manager = &_manager; 55 | 56 | } // namespace llarp::sys 57 | -------------------------------------------------------------------------------- /llarp/messages/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace llarp::messages 13 | { 14 | static auto logcat = log::Cat("messages"); 15 | 16 | inline std::string serialize_response(oxenc::bt_dict supplement = {}) { return oxenc::bt_serialize(supplement); } 17 | 18 | // ideally STATUS is the first key in a bt-dict, so use a single, early ascii char 19 | inline const auto STATUS_KEY = "!"s; 20 | inline const auto TIMEOUT_RESPONSE = serialize_response({{STATUS_KEY, "TIMEOUT"}}); 21 | inline const auto ERROR_RESPONSE = serialize_response({{STATUS_KEY, "ERROR"}}); 22 | inline const auto OK_RESPONSE = serialize_response({{STATUS_KEY, "OK"}}); 23 | } // namespace llarp::messages 24 | -------------------------------------------------------------------------------- /llarp/net/net.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #if defined(_WIN32) || defined(__MINGW32__) 3 | #include 4 | 5 | #include 6 | #include 7 | // because this shit is not defined for Windows NT reeeee 8 | #ifdef __cplusplus 9 | extern "C" 10 | { 11 | #endif 12 | #if _WIN32_WINNT < 0x600 13 | const char* inet_ntop(int af, const void* src, char* dst, size_t size); 14 | int inet_pton(int af, const char* src, void* dst); 15 | #endif 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | typedef unsigned short in_port_t; 20 | typedef unsigned int in_addr_t; 21 | #else 22 | #include 23 | #include 24 | #include 25 | #endif 26 | 27 | #ifndef __cplusplus 28 | #include 29 | #endif 30 | 31 | #include 32 | 33 | bool llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr); 34 | -------------------------------------------------------------------------------- /llarp/net/net_if.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WIN32 3 | // this file is a shim include for #include 4 | #if defined(__linux__) 5 | #include 6 | extern "C" unsigned int 7 | #ifndef __GLIBC__ 8 | if_nametoindex(const char* __ifname); 9 | #else 10 | if_nametoindex(const char* __ifname) __THROW; 11 | #endif 12 | #else 13 | #include 14 | #endif 15 | #endif 16 | 17 | #include 18 | 19 | namespace llarp::net 20 | { 21 | /// get the name of the loopback interface 22 | std::string loopback_interface_name(); 23 | } // namespace llarp::net 24 | -------------------------------------------------------------------------------- /llarp/path/path_types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace llarp 12 | { 13 | struct HopID final : public AlignedBuffer 14 | { 15 | using AlignedBuffer::AlignedBuffer; 16 | 17 | static HopID make_random() 18 | { 19 | HopID h; 20 | h.Randomize(); 21 | return h; 22 | } 23 | }; 24 | 25 | namespace handlers 26 | { 27 | class SessionEndpoint; 28 | } 29 | 30 | struct session_path_interface 31 | { 32 | virtual void link_session(session_tag t) = 0; 33 | virtual bool unlink_session(session_tag t) = 0; 34 | virtual bool is_linked() const = 0; 35 | 36 | virtual bool send_path_control_message(std::string method, std::string body, bt_control_response_hook func) = 0; 37 | virtual bool send_path_data_message(std::string body) = 0; 38 | 39 | virtual RouterID terminal_rid() const = 0; 40 | virtual HopID terminal_txid() const = 0; 41 | 42 | virtual handlers::SessionEndpoint& parent() = 0; 43 | 44 | virtual std::string to_string() const = 0; 45 | static constexpr bool to_string_formattable = true; 46 | }; 47 | 48 | } // namespace llarp 49 | 50 | namespace std 51 | { 52 | template <> 53 | struct hash : hash> 54 | {}; 55 | } // namespace std 56 | -------------------------------------------------------------------------------- /llarp/router/route_poker.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace llarp 11 | { 12 | struct Router; 13 | 14 | struct RoutePoker : public std::enable_shared_from_this 15 | { 16 | RoutePoker(Router& r); 17 | 18 | void add_route(oxen::quic::Address ip); 19 | 20 | void delete_route(oxen::quic::Address ip); 21 | 22 | void start(); 23 | 24 | ~RoutePoker(); 25 | 26 | /// explicitly put routes up 27 | void put_up(); 28 | 29 | /// explicitly put routes down 30 | void put_down(); 31 | 32 | /// set dns resolver 33 | /// pass in if we are using exit node mode right now as a bool void set_dns_mode(bool 34 | /// using_exit_mode) const; 35 | 36 | bool is_enabled() const { return _is_enabled; } 37 | 38 | private: 39 | void update(); 40 | 41 | void delete_all_routes(); 42 | 43 | void disable_all_routes(); 44 | 45 | void refresh_all_routes(); 46 | 47 | void enable_route(oxen::quic::Address ip, oxen::quic::Address gateway); 48 | 49 | void disable_route(oxen::quic::Address ip, oxen::quic::Address gateway); 50 | 51 | std::unordered_map poked_routes; 52 | std::optional current_gateway; 53 | 54 | Router& _router; 55 | bool _is_up{false}; 56 | bool _is_enabled{false}; 57 | }; 58 | } // namespace llarp 59 | -------------------------------------------------------------------------------- /llarp/router_version.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "constants/proto.hpp" 4 | #include "constants/version.hpp" 5 | #include "util/formattable.hpp" 6 | 7 | #include 8 | 9 | namespace 10 | {} // namespace 11 | 12 | namespace llarp 13 | { 14 | struct RouterVersion 15 | { 16 | RouterVersion() = default; 17 | 18 | explicit RouterVersion(const std::array& routerVersion, uint64_t protoVersion); 19 | 20 | std::string bt_encode() const; 21 | 22 | bool bt_decode(std::string_view buf); 23 | 24 | /// return true if this router version is all zeros 25 | bool is_empty() const; 26 | 27 | /// set to be empty 28 | void clear(); 29 | 30 | std::string to_string() const; 31 | 32 | /// return true if the other router version is compatible with ours 33 | bool is_compatible_with(const RouterVersion& other) const; 34 | 35 | /// compare router versions 36 | bool operator<(const RouterVersion& other) const 37 | { 38 | return std::tie(_proto, _version) < std::tie(other._proto, other._version); 39 | } 40 | 41 | bool operator!=(const RouterVersion& other) const { return !(*this == other); } 42 | 43 | bool operator==(const RouterVersion& other) const 44 | { 45 | return _proto == other._proto && _version == other._version; 46 | } 47 | 48 | static constexpr bool to_string_formattable = true; 49 | 50 | private: 51 | std::array _version = {{0, 0, 0}}; 52 | int64_t _proto = llarp::constants::proto_version; 53 | }; 54 | 55 | static constexpr int64_t INVALID_VERSION = -1; 56 | static const RouterVersion emptyRouterVersion({0, 0, 0}, INVALID_VERSION); 57 | 58 | } // namespace llarp 59 | -------------------------------------------------------------------------------- /llarp/rpc/json_bt.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | using nlohmann::json; 7 | 8 | namespace llarp::rpc 9 | { 10 | 11 | inline oxenc::bt_value json_to_bt(json&& j) 12 | { 13 | if (j.is_object()) 14 | { 15 | oxenc::bt_dict res; 16 | for (auto& [k, v] : j.items()) 17 | { 18 | if (v.is_null()) 19 | continue; // skip k-v pairs with a null v (for other nulls we fail). 20 | res[k] = json_to_bt(std::move(v)); 21 | } 22 | return res; 23 | } 24 | if (j.is_array()) 25 | { 26 | oxenc::bt_list res; 27 | for (auto& v : j) 28 | res.push_back(json_to_bt(std::move(v))); 29 | return res; 30 | } 31 | if (j.is_string()) 32 | { 33 | return std::move(j.get_ref()); 34 | } 35 | if (j.is_boolean()) 36 | return j.get() ? 1 : 0; 37 | if (j.is_number_unsigned()) 38 | return j.get(); 39 | if (j.is_number_integer()) 40 | return j.get(); 41 | throw std::domain_error{"internal error: encountered some unhandled/invalid type in json-to-bt translation"}; 42 | } 43 | 44 | } // namespace llarp::rpc 45 | -------------------------------------------------------------------------------- /llarp/rpc/json_conversions.cpp: -------------------------------------------------------------------------------- 1 | #include "json_conversions.hpp" 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | static auto logcat = log::Cat("RPC-conversions"); 8 | 9 | void to_json(nlohmann::json& j, const IPRange& ipr) { j = ipr.to_string(); } 10 | 11 | void from_json(const nlohmann::json& j, IPRange& ipr) 12 | { 13 | if (auto maybe = IPRange::from_string(j.get())) 14 | ipr = *maybe; 15 | else 16 | log::critical(logcat, "Failed to parse IPRange from json!"); 17 | } 18 | 19 | } // namespace llarp 20 | -------------------------------------------------------------------------------- /llarp/rpc/json_conversions.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "json_binary_proxy.hpp" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace llarp 11 | { 12 | void to_json(nlohmann::json& j, const IPRange& ipr); 13 | void from_json(const nlohmann::json& j, IPRange& ipr); 14 | } // namespace llarp 15 | 16 | namespace nlohmann 17 | { 18 | // Specializations of binary types for deserialization; when receiving these from json we expect 19 | // them encoded in hex or base64. These may *not* be used for serialization, and will throw if 20 | // so invoked; for serialization you need to use RPC_COMMAND::response_hex (or _b64) instead. 21 | template 22 | struct adl_serializer>> 23 | { 24 | static_assert(std::is_trivially_copyable_v && std::has_unique_object_representations_v); 25 | 26 | static void to_json(json&, const T&) 27 | { 28 | throw std::logic_error{"Internal error: binary types are not directly serializable"}; 29 | } 30 | static void from_json(const json& j, T& val) 31 | { 32 | llarp::rpc::load_binary_parameter(j.get(), false /*no raw*/, val); 33 | } 34 | }; 35 | 36 | } // namespace nlohmann 37 | -------------------------------------------------------------------------------- /llarp/rpc/rpc_request_parser.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "rpc_request_definitions.hpp" 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace llarp::rpc 13 | { 14 | using rpc_input = std::variant; 15 | 16 | inline void parse_request(NoArgs&, rpc_input) {} 17 | 18 | void parse_request(FindCC& findcc, rpc_input input); 19 | void parse_request(SessionInit& sessioninit, rpc_input input); 20 | void parse_request(SessionClose& sessionclose, rpc_input input); 21 | 22 | void parse_request(QuicConnect& quicconnect, rpc_input input); 23 | void parse_request(QuicListener& quiclistener, rpc_input input); 24 | void parse_request(LookupSnode& lookupsnode, rpc_input input); 25 | void parse_request(MapExit& mapexit, rpc_input input); 26 | void parse_request(UnmapExit& unmapexit, rpc_input input); 27 | void parse_request(SwapExits& swapexits, rpc_input input); 28 | void parse_request(DNSQuery& dnsquery, rpc_input input); 29 | void parse_request(Config& config, rpc_input input); 30 | 31 | } // namespace llarp::rpc 32 | -------------------------------------------------------------------------------- /llarp/simulation/sim_context.cpp: -------------------------------------------------------------------------------- 1 | #include "sim_context.hpp" 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | namespace simulate 8 | { 9 | Simulation::Simulation() : m_CryptoManager(new sodium::CryptoLibSodium()) {} 10 | 11 | void Simulation::NodeUp(llarp::Context*) {} 12 | 13 | Node_ptr Simulation::AddNode(const std::string& name) 14 | { 15 | auto itr = m_Nodes.find(name); 16 | if (itr == m_Nodes.end()) 17 | { 18 | itr = m_Nodes.emplace(name, std::make_shared(shared_from_this())).first; 19 | } 20 | return itr->second; 21 | } 22 | 23 | void Simulation::DelNode(const std::string& name) { m_Nodes.erase(name); } 24 | } // namespace simulate 25 | } // namespace llarp 26 | -------------------------------------------------------------------------------- /llarp/simulation/sim_context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace llarp 6 | { 7 | // forward declair 8 | struct Context; 9 | using Node_ptr = std::shared_ptr; 10 | 11 | namespace simulate 12 | { 13 | struct Simulation : public std::enable_shared_from_this 14 | { 15 | Simulation(); 16 | 17 | llarp::CryptoManager m_CryptoManager; 18 | // std::shared_ptr m_NetLoop; 19 | 20 | std::unordered_map m_Nodes; 21 | 22 | void NodeUp(llarp::Context* node); 23 | 24 | Node_ptr AddNode(const std::string& name); 25 | 26 | void DelNode(const std::string& name); 27 | }; 28 | 29 | using Sim_ptr = std::shared_ptr; 30 | } // namespace simulate 31 | } // namespace llarp 32 | -------------------------------------------------------------------------------- /llarp/util/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifdef __STRICT_ANSI__ 3 | #define INLINE __inline__ 4 | #else 5 | #define INLINE inline 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | // clang-format off 12 | #if defined(__GNUC__) || defined(__clang__) 13 | #define DO_PRAGMA(X) _Pragma(#X) 14 | #define DISABLE_WARNING_PUSH DO_PRAGMA(GCC diagnostics push) 15 | #define DISABLE_WARNING_POP DO_PRAGMA(GCC diagnostic pop) 16 | #define DISABLE_WARNING(wname) DO_PRAGMA(GCC diagnostic ignored #wname) 17 | #elif defined(_MSC_VER_) 18 | #define DISABLE_WARNING_PUSH __pragma(warning(push)) 19 | #define DISABLE_WARNING_POP __pragma(warning(pop)) 20 | #define DISABLE_WARNING(wnumber) __pragma(warning(disable : wnumber)) 21 | #else 22 | // unknown compiler, ignore suppression directives 23 | #define DISABLE_WARNING_PUSH 24 | #define DISABLE_WARNING_POP 25 | #endif 26 | 27 | #if defined(__GNUC__) || defined(__clang__) 28 | #define DISABLE_MAYBE_UNINITIALIZED DISABLE_WARNING(-Wmaybe-uninitialized) 29 | #elif defined(_MSC_VER_) 30 | #define DISABLE_MAYBE_UNINITIALIZED DISABLE_WARNING(C4701) 31 | #else 32 | #define DISABLE_MAYBE_UNINITIALIZED 33 | #endif 34 | // clang-format on 35 | -------------------------------------------------------------------------------- /llarp/util/compare_ptr.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace llarp 6 | { 7 | /// type for comparing smart pointer's managed values 8 | template > 9 | struct ComparePtr 10 | { 11 | bool operator()(const Ptr_t& left, const Ptr_t& right) const 12 | { 13 | if (left && right) 14 | return Compare()(*left, *right); 15 | 16 | return Compare()(left, right); 17 | } 18 | }; 19 | 20 | /// type for comparing weak_ptr by value 21 | template > 22 | struct CompareWeakPtr 23 | { 24 | bool operator()(const std::weak_ptr& left, const std::weak_ptr& right) const 25 | { 26 | return ComparePtr, Compare>{}(left.lock(), right.lock()); 27 | } 28 | }; 29 | 30 | } // namespace llarp 31 | -------------------------------------------------------------------------------- /llarp/util/exceptions.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llarp::util 4 | { 5 | class bind_socket_error : public std::runtime_error 6 | { 7 | public: 8 | using std::runtime_error::runtime_error; 9 | }; 10 | } // namespace llarp::util 11 | -------------------------------------------------------------------------------- /llarp/util/logging.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Header for making actual log statements such as llarp::log::Info and so on work. 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace llarp 13 | { 14 | namespace log = oxen::log; 15 | 16 | inline std::shared_ptr logRingBuffer = nullptr; 17 | } // namespace llarp 18 | -------------------------------------------------------------------------------- /llarp/util/logging/buffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | using oxen::quic::buffer_printer; 8 | } // namespace llarp 9 | -------------------------------------------------------------------------------- /llarp/util/logging/callback_sink.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | namespace llarp::logging 8 | { 9 | // Logger that calls a C function with the formatted log message 10 | template 11 | class CallbackSink : public spdlog::sinks::base_sink 12 | { 13 | private: 14 | lokinet_logger_func log_; 15 | lokinet_logger_sync sync_; 16 | void* ctx_; 17 | 18 | public: 19 | explicit CallbackSink(lokinet_logger_func log, lokinet_logger_sync sync = nullptr, void* context = nullptr) 20 | : log_{log}, sync_{sync}, ctx_{context} 21 | {} 22 | 23 | protected: 24 | void sink_it_(const spdlog::details::log_msg& msg) override 25 | { 26 | if (!log_) 27 | return; 28 | spdlog::memory_buf_t formatted; 29 | spdlog::sinks::base_sink::formatter_->format(msg, formatted); 30 | log_(fmt::to_string(formatted).c_str(), ctx_); 31 | } 32 | 33 | void flush_() override 34 | { 35 | if (sync_) 36 | sync_(ctx_); 37 | } 38 | }; 39 | 40 | // Convenience aliases with or without thread safety 41 | using CallbackSink_mt = CallbackSink; 42 | using CallbackSink_st = CallbackSink; 43 | 44 | } // namespace llarp::logging 45 | -------------------------------------------------------------------------------- /llarp/util/lokinet_init.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" 5 | { 6 | #endif 7 | 8 | int Lokinet_INIT(void); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /llarp/util/mem.cpp: -------------------------------------------------------------------------------- 1 | #define NO_JEMALLOC 2 | #include "mem.h" 3 | 4 | #include 5 | 6 | namespace llarp 7 | { 8 | void Zero(void* ptr, size_t sz) 9 | { 10 | auto* p = (uint8_t*)ptr; 11 | while (sz--) 12 | { 13 | *p = 0; 14 | ++p; 15 | } 16 | } 17 | } // namespace llarp 18 | 19 | void llarp_mem_slab(struct llarp_alloc* /*mem*/, uint32_t* /*buf*/, size_t /*sz*/) 20 | { 21 | // not implemented 22 | abort(); 23 | } 24 | 25 | bool llarp_eq(const void* a, const void* b, size_t sz) 26 | { 27 | bool result = true; 28 | const auto* a_ptr = (const uint8_t*)a; 29 | const auto* b_ptr = (const uint8_t*)b; 30 | while (sz--) 31 | { 32 | result &= a_ptr[sz] == b_ptr[sz]; 33 | } 34 | return result; 35 | } 36 | -------------------------------------------------------------------------------- /llarp/util/mem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /** constant time memcmp */ 7 | bool llarp_eq(const void* a, const void* b, size_t sz); 8 | -------------------------------------------------------------------------------- /llarp/util/nop_service_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "service_manager.hpp" 2 | 3 | namespace llarp::sys 4 | { 5 | NOP_SystemLayerHandler _manager{}; 6 | I_SystemLayerManager* const service_manager = &_manager; 7 | } // namespace llarp::sys 8 | -------------------------------------------------------------------------------- /llarp/util/random.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.hpp" 4 | 5 | #include 6 | 7 | extern "C" 8 | { 9 | extern void randombytes(unsigned char* const ptr, unsigned long long sz); 10 | } 11 | 12 | namespace llarp 13 | { 14 | struct CSRNG 15 | { 16 | using result_type = uint64_t; 17 | 18 | static constexpr uint64_t min() { return std::numeric_limits::min(); } 19 | 20 | static constexpr uint64_t max() { return std::numeric_limits::max(); } 21 | 22 | uint64_t randint() 23 | { 24 | uint64_t i; 25 | randombytes((uint8_t*)&i, sizeof(i)); 26 | return i; 27 | } 28 | 29 | size_t boundedrand(size_t upper_bound) { return randint() % upper_bound; } 30 | 31 | uint64_t operator()() { return randint(); } 32 | }; 33 | 34 | extern CSRNG csrng; 35 | 36 | } // namespace llarp 37 | -------------------------------------------------------------------------------- /llarp/util/thread/barrier.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace llarp 6 | { 7 | namespace util 8 | { 9 | /// Barrier class that blocks all threads until the high water mark of 10 | /// threads (set during construction) is reached, then releases them all. 11 | class Barrier 12 | { 13 | std::mutex mutex; 14 | std::condition_variable cv; 15 | unsigned pending; 16 | 17 | public: 18 | Barrier(unsigned threads) : pending{threads} {} 19 | 20 | /// Returns true if *this* Block call is the one that releases all of 21 | /// them; returns false (i.e. after unblocking) if some other thread 22 | /// triggered the released. 23 | bool Block() 24 | { 25 | std::unique_lock lock{mutex}; 26 | if (pending == 1) 27 | { 28 | pending = 0; 29 | lock.unlock(); 30 | cv.notify_all(); 31 | return true; 32 | } 33 | else if (pending > 1) 34 | { 35 | pending--; 36 | } 37 | cv.wait(lock, [this] { return !pending; }); 38 | return false; 39 | } 40 | }; 41 | 42 | } // namespace util 43 | } // namespace llarp 44 | -------------------------------------------------------------------------------- /llarp/util/thread/threading.cpp: -------------------------------------------------------------------------------- 1 | #include "threading.hpp" 2 | 3 | #include 4 | 5 | #include 6 | 7 | #ifdef POSIX 8 | #include 9 | #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 10 | #include 11 | #endif 12 | #endif 13 | 14 | #ifdef _MSC_VER 15 | #include 16 | extern "C" void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName); 17 | #endif 18 | 19 | namespace llarp::util 20 | { 21 | static auto logcat = log::Cat("util.threading"); 22 | 23 | void SetThreadName(const std::string& name) 24 | { 25 | #if defined(POSIX) || __MINGW32__ 26 | #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 27 | /* on bsd this function has void return type */ 28 | pthread_set_name_np(pthread_self(), name.c_str()); 29 | #else 30 | #if defined(__MACH__) 31 | const int rc = pthread_setname_np(name.c_str()); 32 | // API present upstream since v2.11.3 and imported downstream 33 | // in CR 8158 34 | // We only use the native function on Microsoft C++ builds 35 | #elif defined(__linux__) || defined(__sun) || __MINGW32__ 36 | const int rc = pthread_setname_np(pthread_self(), name.c_str()); 37 | #else 38 | #error "unsupported platform" 39 | #endif 40 | if (rc) 41 | { 42 | log::error(logcat, "Failed to set thread name to {} errno = {} errstr = {}", name, rc, ::strerror(rc)); 43 | } 44 | #endif 45 | #elif _MSC_VER 46 | ::SetThreadName(::GetCurrentThreadId(), name.c_str()); 47 | #else 48 | log::info(logcat, "Thread name setting not supported on this platform"); 49 | (void)name; 50 | #endif 51 | } 52 | } // namespace llarp::util 53 | -------------------------------------------------------------------------------- /llarp/vpn/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace llarp::vpn 14 | { 15 | class permission_error : public std::runtime_error 16 | { 17 | public: 18 | using std::runtime_error::runtime_error; 19 | }; 20 | 21 | struct IOCTL 22 | { 23 | const int _fd; 24 | 25 | explicit IOCTL(int af) : _fd{::socket(af, SOCK_DGRAM, IPPROTO_IP)} 26 | { 27 | if (_fd == -1) 28 | throw std::invalid_argument{strerror(errno)}; 29 | }; 30 | 31 | ~IOCTL() { ::close(_fd); } 32 | 33 | template 34 | void ioctl(Command cmd, Args&&... args) 35 | { 36 | if (::ioctl(_fd, cmd, std::forward(args)...) == -1) 37 | { 38 | if (errno == EACCES) 39 | { 40 | throw permission_error{"we are not allowed to call this ioctl"}; 41 | } 42 | else 43 | throw std::runtime_error("ioctl failed: " + std::string{strerror(errno)}); 44 | } 45 | } 46 | }; 47 | } // namespace llarp::vpn 48 | -------------------------------------------------------------------------------- /llarp/vpn/egres_packet_router.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace llarp::vpn 10 | { 11 | using EgresPacketHandlerFunc = std::function; 12 | 13 | struct EgresLayer4Handler 14 | { 15 | virtual ~EgresLayer4Handler() = default; 16 | 17 | virtual void HandleIPPacketFrom(NetworkAddress from, IPPacket pkt) = 0; 18 | 19 | virtual void AddSubHandler(uint16_t, EgresPacketHandlerFunc) {}; 20 | virtual void RemoveSubHandler(uint16_t) {}; 21 | }; 22 | 23 | class EgresPacketRouter 24 | { 25 | EgresPacketHandlerFunc _handler; 26 | std::unordered_map> _proto_handlers; 27 | 28 | public: 29 | /// baseHandler will be called if no other handlers matches a packet 30 | explicit EgresPacketRouter(EgresPacketHandlerFunc baseHandler); 31 | 32 | /// feed in an ip packet for handling 33 | void HandleIPPacketFrom(NetworkAddress, IPPacket pkt); 34 | 35 | /// add a non udp packet handler using ip protocol proto 36 | void AddIProtoHandler(uint8_t proto, EgresPacketHandlerFunc func); 37 | 38 | /// helper that adds a udp packet handler for UDP destinted for localport 39 | void AddUDPHandler(uint16_t localport, EgresPacketHandlerFunc func); 40 | 41 | /// remove a udp handler that is already set up by bound port 42 | void RemoveUDPHandler(uint16_t localport); 43 | }; 44 | } // namespace llarp::vpn 45 | -------------------------------------------------------------------------------- /llarp/vpn/packet_intercept.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp::vpn 7 | { 8 | using PacketSendFunc_t = std::function)>; 9 | using PacketInterceptFunc_t = std::function, PacketSendFunc_t)>; 10 | 11 | class I_PacketInterceptor 12 | { 13 | public: 14 | virtual ~I_PacketInterceptor() = default; 15 | 16 | /// start intercepting packets and call a callback for each one we get 17 | /// the callback passes in an ip packet and a function that we can use to send an ip packet 18 | /// to its origin 19 | virtual void start(PacketInterceptFunc_t f) = 0; 20 | 21 | /// stop intercepting packets 22 | virtual void stop() = 0; 23 | }; 24 | 25 | } // namespace llarp::vpn 26 | -------------------------------------------------------------------------------- /llarp/vpn/packet_io.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace llarp::vpn 8 | { 9 | class PacketIO 10 | { 11 | public: 12 | virtual ~PacketIO() = default; 13 | 14 | /// start any platform specific operations before running 15 | virtual void Start() {}; 16 | 17 | /// stop operation and tear down anything that Start() set up. 18 | virtual void Stop() {}; 19 | 20 | /// read next ip packet, return an empty packet if there are none ready. 21 | virtual IPPacket read_next_packet() = 0; 22 | 23 | /// write a packet to the interface 24 | /// returns false if we dropped it 25 | virtual bool write_packet(IPPacket pkt) = 0; 26 | 27 | /// get pollable fd for reading 28 | virtual int PollFD() const = 0; 29 | }; 30 | 31 | } // namespace llarp::vpn 32 | -------------------------------------------------------------------------------- /llarp/vpn/packet_router.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace llarp::vpn 9 | { 10 | struct Layer4Handler; 11 | 12 | class PacketRouter 13 | { 14 | ip_pkt_hook _handler; 15 | // std::unordered_map> _ip_proto_handler; 16 | std::unordered_map> _ip_proto_handler; 17 | 18 | public: 19 | /// baseHandler will be called if no other handlers matches a packet 20 | explicit PacketRouter(ip_pkt_hook baseHandler); 21 | 22 | /// feed in an ip packet for handling 23 | void handle_ip_packet(IPPacket pkt) const; 24 | 25 | /// add a non udp packet handler using ip protocol proto 26 | void add_ip_proto_handler(net::IPProtocol proto, ip_pkt_hook func); 27 | 28 | /// helper that adds a udp packet handler for UDP destined for localport 29 | void add_udp_handler(uint16_t port, ip_pkt_hook func); 30 | 31 | /// remove a udp handler that is already set up by bound port 32 | void remove_udp_handler(uint16_t port); 33 | }; 34 | 35 | struct Layer4Handler 36 | { 37 | virtual ~Layer4Handler() = default; 38 | 39 | virtual void handle_ip_packet(IPPacket pkt) = 0; 40 | 41 | virtual void add_sub_handler(uint16_t, ip_pkt_hook) {}; 42 | }; 43 | 44 | } // namespace llarp::vpn 45 | -------------------------------------------------------------------------------- /llarp/vpn/platform.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "platform.hpp" 3 | 4 | #ifdef _WIN32 5 | #include "win32.hpp" 6 | #endif 7 | #ifdef __linux__ 8 | #ifdef ANDROID 9 | #include "android.hpp" 10 | #else 11 | #include "linux.hpp" 12 | #endif 13 | #endif 14 | 15 | namespace llarp::vpn 16 | { 17 | const llarp::net::Platform* AbstractRouteManager::net_ptr() const { return llarp::net::Platform::Default_ptr(); } 18 | 19 | std::shared_ptr MakeNativePlatform(llarp::Context* ctx) 20 | { 21 | (void)ctx; 22 | std::shared_ptr plat; 23 | #ifdef _WIN32 24 | plat = std::make_shared(ctx); 25 | #endif 26 | #ifdef __linux__ 27 | #ifdef ANDROID 28 | plat = std::make_shared(ctx); 29 | #else 30 | plat = std::make_shared(); 31 | #endif 32 | #endif 33 | #ifdef __APPLE__ 34 | throw std::runtime_error{"not supported"}; 35 | #endif 36 | return plat; 37 | } 38 | 39 | } // namespace llarp::vpn 40 | -------------------------------------------------------------------------------- /llarp/win32/dll.cpp: -------------------------------------------------------------------------------- 1 | #include "dll.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp::win32 7 | { 8 | namespace 9 | { 10 | auto cat = log::Cat("win32-dll"); 11 | } 12 | 13 | namespace detail 14 | { 15 | HMODULE 16 | load_dll(const std::string& dll) 17 | { 18 | auto handle = LoadLibraryExA(dll.c_str(), NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR); 19 | if (not handle) 20 | throw win32::error{fmt::format("failed to load '{}'", dll)}; 21 | log::info(cat, "loaded '{}'", dll); 22 | return handle; 23 | } 24 | } // namespace detail 25 | } // namespace llarp::win32 26 | -------------------------------------------------------------------------------- /llarp/win32/dll.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "exception.hpp" 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace llarp::win32 9 | { 10 | namespace detail 11 | { 12 | HMODULE 13 | load_dll(const std::string& dll); 14 | 15 | template 16 | void load_funcs(HMODULE handle, const std::string& name, Func*& f, More&&... more) 17 | { 18 | if (auto ptr = GetProcAddress(handle, name.c_str())) 19 | f = reinterpret_cast(ptr); 20 | else 21 | throw win32::error{fmt::format("function '{}' not found", name)}; 22 | if constexpr (sizeof...(More) > 0) 23 | load_funcs(handle, std::forward(more)...); 24 | } 25 | } // namespace detail 26 | 27 | // Loads a DLL and extracts function pointers from it. Takes the dll name and pairs of 28 | // name/function pointer arguments. Throws on failure. 29 | template 30 | void load_dll_functions(const std::string& dll, const std::string& fname, Func*& f, More&&... funcs) 31 | { 32 | detail::load_funcs(detail::load_dll(dll), fname, f, std::forward(funcs)...); 33 | } 34 | } // namespace llarp::win32 35 | -------------------------------------------------------------------------------- /llarp/win32/exception.cpp: -------------------------------------------------------------------------------- 1 | #include "exception.hpp" 2 | 3 | #include "windows.h" 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace llarp::win32 10 | 11 | { 12 | error::error(std::string msg) : error{GetLastError(), std::move(msg)} {} 13 | error::error(DWORD err, std::string msg) 14 | : std::runtime_error{fmt::format("{}: {} (code={})", msg, error_to_string(err), err)} 15 | {} 16 | std::string error_to_string(DWORD err) 17 | { 18 | // mostly yoinked from https://stackoverflow.com/a/45565001 19 | LPTSTR psz{nullptr}; 20 | const DWORD cchMsg = FormatMessage( 21 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, 22 | nullptr, 23 | err, 24 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 25 | reinterpret_cast(&psz), 26 | 0, 27 | nullptr); 28 | 29 | if (cchMsg <= 0) 30 | { 31 | // cannot get message for error, reset the last error here so it does not propagate 32 | ::SetLastError(0); 33 | return "unknown error"; 34 | } 35 | 36 | auto deleter = [](void* p) { ::LocalFree(p); }; 37 | std::unique_ptr ptrBuffer{psz, deleter}; 38 | return std::string{ptrBuffer.get(), cchMsg}; 39 | } 40 | } // namespace llarp::win32 41 | -------------------------------------------------------------------------------- /llarp/win32/exception.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | namespace llarp::win32 8 | { 9 | std::string error_to_string(DWORD err); 10 | 11 | class error : public std::runtime_error 12 | { 13 | public: 14 | explicit error(std::string msg); 15 | virtual ~error() = default; 16 | explicit error(DWORD err, std::string msg); 17 | }; 18 | } // namespace llarp::win32 19 | -------------------------------------------------------------------------------- /llarp/win32/exec.cpp: -------------------------------------------------------------------------------- 1 | #include "exec.hpp" 2 | 3 | #include "exception.hpp" 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace llarp::win32 10 | { 11 | namespace 12 | { 13 | static auto logcat = log::Cat("win32:exec"); 14 | 15 | /// get the directory for system32 which contains all the executables we use 16 | std::string SystemExeDir() 17 | { 18 | std::array path{}; 19 | 20 | if (GetSystemDirectoryA(path.data(), path.size())) 21 | return path.data(); 22 | 23 | return "C:\\Windows\\system32"; 24 | } 25 | 26 | } // namespace 27 | 28 | void Exec(std::string exe, std::string args) { OneShotExec{exe, args}; } 29 | 30 | OneShotExec::OneShotExec(std::string cmd, std::chrono::milliseconds timeout) 31 | : _si{}, _pi{}, _timeout{static_cast(timeout.count())} 32 | { 33 | log::info(logcat, "exec: {}", cmd); 34 | if (not CreateProcessA(nullptr, cmd.data(), nullptr, nullptr, false, 0, nullptr, nullptr, &_si, &_pi)) 35 | throw win32::error(GetLastError(), "failed to execute subprocess"); 36 | } 37 | 38 | OneShotExec::~OneShotExec() 39 | { 40 | WaitForSingleObject(_pi.hProcess, _timeout); 41 | CloseHandle(_pi.hProcess); 42 | CloseHandle(_pi.hThread); 43 | } 44 | 45 | OneShotExec::OneShotExec(std::string cmd, std::string args, std::chrono::milliseconds timeout) 46 | : OneShotExec{fmt::format("{}\\{} {}", SystemExeDir(), cmd, args), timeout} 47 | {} 48 | 49 | DeferExec::~DeferExec() { OneShotExec{std::move(_exe), std::move(_args), std::move(_timeout)}; } 50 | } // namespace llarp::win32 51 | -------------------------------------------------------------------------------- /llarp/win32/exec.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace llarp::win32 10 | { 11 | /// RAII wrapper for calling a subprocess in win32 for parallel executuion in the same scope 12 | /// destructor blocks until timeout has been hit of the execution of the subprocses finished 13 | class OneShotExec 14 | { 15 | STARTUPINFO _si; 16 | PROCESS_INFORMATION _pi; 17 | const DWORD _timeout; 18 | 19 | OneShotExec(std::string cmd, std::chrono::milliseconds timeout); 20 | 21 | public: 22 | /// construct a call to an exe in system32 with args, will resolve the full path of the exe 23 | /// to prevent path injection 24 | explicit OneShotExec(std::string exe, std::string args, std::chrono::milliseconds timeout = 5s); 25 | 26 | ~OneShotExec(); 27 | }; 28 | 29 | /// a wrapper for OneShotExec that calls the thing we want on destruction 30 | class DeferExec 31 | { 32 | std::string _exe; 33 | std::string _args; 34 | std::chrono::milliseconds _timeout; 35 | 36 | public: 37 | explicit DeferExec(std::string exe, std::string args, std::chrono::milliseconds timeout = 5s) 38 | : _exe{std::move(exe)}, _args{std::move(args)}, _timeout{std::move(timeout)} 39 | {} 40 | 41 | ~DeferExec(); 42 | }; 43 | 44 | /// simple wrapper to run a single command in a blocking way 45 | void Exec(std::string exe, std::string args); 46 | 47 | } // namespace llarp::win32 48 | -------------------------------------------------------------------------------- /llarp/win32/guid.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace llarp::win32 10 | { 11 | /// @brief given a container of data hash it and make it into a GUID so we have a way to 12 | /// deterministically generate GUIDs 13 | template 14 | inline GUID MakeDeterministicGUID(Data data) 15 | { 16 | ShortHash h{}; 17 | auto hash = [&h](uint8_t* d, size_t size) { crypto::shorthash(h, d, size); }; 18 | 19 | if constexpr (std::is_same_v) 20 | hash(reinterpret_cast(data.data()), data.size()); 21 | else 22 | { 23 | auto dat = llarp_buffer_t{data}; 24 | hash(dat.base, dat.sz); 25 | } 26 | GUID guid{}; 27 | std::copy_n(h.begin(), std::min(sizeof(GUID), sizeof(ShortHash)), reinterpret_cast(&guid)); 28 | return guid; 29 | } 30 | } // namespace llarp::win32 31 | -------------------------------------------------------------------------------- /llarp/win32/handle.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "exception.hpp" 4 | 5 | namespace llarp::win32 6 | { 7 | inline void ensure_handle_is_valid(HANDLE h) 8 | { 9 | BY_HANDLE_FILE_INFORMATION info{}; 10 | if (GetFileInformationByHandle(h, &info)) 11 | return; 12 | if (auto err = GetLastError()) 13 | { 14 | SetLastError(0); 15 | throw llarp::win32::error{err, "handle validity check failed"}; 16 | } 17 | } 18 | } // namespace llarp::win32 19 | -------------------------------------------------------------------------------- /llarp/win32/service_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace llarp::sys 11 | { 12 | 13 | class SVC_Manager : public I_SystemLayerManager 14 | { 15 | SERVICE_STATUS _status; 16 | 17 | public: 18 | SERVICE_STATUS_HANDLE handle; 19 | 20 | // How long we tell Windows to give us to startup before assuming we have stalled/hung. The 21 | // biggest potential time here is wintun, which if it is going to fail appears to take 22 | // around 15s before doing so. 23 | static constexpr auto StartupTimeout = 17s; 24 | 25 | // How long we tell Windows to give us to fully stop before killing us. 26 | static constexpr auto StopTimeout = 5s; 27 | 28 | SVC_Manager(); 29 | 30 | void system_changed_our_state(ServiceState st) override; 31 | 32 | void report_changed_state() override; 33 | 34 | void we_changed_our_state(ServiceState st) override; 35 | }; 36 | } // namespace llarp::sys 37 | -------------------------------------------------------------------------------- /llarp/win32/windivert.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace llarp::win32::WinDivert 10 | { 11 | /// format an ipv4 in host order to string such that a windivert filter spec can understand it 12 | std::string format_ip(uint32_t ip); 13 | 14 | /// create a packet interceptor that uses windivert. 15 | /// filter_spec describes the kind of traffic we wish to intercept. 16 | /// pass in a callable that wakes up the main event loop. 17 | /// we hide all implementation details from other compilation units to prevent issues with 18 | /// linkage that may arrise. 19 | std::shared_ptr make_interceptor( 20 | const std::string& filter_spec, std::function wakeup); 21 | 22 | } // namespace llarp::win32::WinDivert 23 | -------------------------------------------------------------------------------- /llarp/win32/wintun.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | struct Router; 8 | } 9 | 10 | namespace llarp::vpn 11 | { 12 | struct InterfaceInfo; 13 | class NetworkInterface; 14 | } // namespace llarp::vpn 15 | 16 | namespace llarp::win32::wintun 17 | { 18 | /// makes a new vpn interface with a wintun context given info and a router pointer 19 | std::shared_ptr make_interface(const vpn::InterfaceInfo& info, Router* router); 20 | 21 | } // namespace llarp::win32::wintun 22 | -------------------------------------------------------------------------------- /pybind/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | pybind11_add_module(pyllarp MODULE 2 | module.cpp 3 | llarp/context.cpp 4 | llarp/router.cpp 5 | llarp/router_id.cpp 6 | llarp/router_contact.cpp 7 | llarp/crypto/types.cpp 8 | llarp/config.cpp 9 | llarp/logger.cpp 10 | llarp/peerstats.cpp 11 | llarp/dht/dht_types.cpp 12 | llarp/path/path_types.cpp 13 | llarp/path/path_hop_config.cpp 14 | llarp/handlers/pyhandler.cpp 15 | llarp/tooling/router_hive.cpp 16 | llarp/tooling/router_event.cpp 17 | llarp/service/address.cpp 18 | ) 19 | target_link_libraries(pyllarp PUBLIC lokinet-amalgum) 20 | target_include_directories(pyllarp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) 21 | -------------------------------------------------------------------------------- /pybind/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace py = pybind11; 11 | 12 | namespace llarp 13 | { 14 | void Logger_Init(py::module& mod); 15 | 16 | void Context_Init(py::module& mod); 17 | 18 | void CryptoTypes_Init(py::module& mod); 19 | 20 | void Router_Init(py::module& mod); 21 | 22 | void RouterID_Init(py::module& mod); 23 | 24 | void RelayContact_Init(py::module& mod); 25 | 26 | void Config_Init(py::module& mod); 27 | 28 | void PathTypes_Init(py::module& mod); 29 | 30 | void PeerDb_Init(py::module& mod); 31 | 32 | void PeerStats_Init(py::module& mod); 33 | 34 | namespace dht 35 | { 36 | void DHTTypes_Init(py::module& mod); 37 | } 38 | 39 | namespace path 40 | { 41 | void PathHopConfig_Init(py::module& mod); 42 | } 43 | 44 | namespace handlers 45 | { 46 | void PyHandler_Init(py::module& mod); 47 | } 48 | 49 | namespace service 50 | { 51 | void Address_Init(py::module& mod); 52 | } 53 | 54 | } // namespace llarp 55 | 56 | namespace tooling 57 | { 58 | void RouterHive_Init(py::module& mod); 59 | 60 | void RouterEvent_Init(py::module& mod); 61 | 62 | void HiveContext_Init(py::module& mod); 63 | 64 | void HiveRouter_Init(py::module& mod); 65 | } // namespace tooling 66 | -------------------------------------------------------------------------------- /pybind/llarp/crypto/types.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | void CryptoTypes_Init(py::module& mod) 8 | { 9 | py::class_(mod, "PubKey") 10 | .def(py::init<>()) 11 | .def("FromHex", &PubKey::FromString) 12 | .def("__repr__", &PubKey::ToString); 13 | py::class_(mod, "SecretKey") 14 | .def(py::init<>()) 15 | .def("LoadFile", &SecretKey::LoadFromFile) 16 | .def("SaveFile", &SecretKey::SaveToFile) 17 | .def("ToPublic", &SecretKey::toPublic); 18 | py::class_(mod, "Signature").def(py::init<>()).def("__repr__", [](const Signature& sig) { 19 | return sig.ToHex(); 20 | }); 21 | } 22 | 23 | } // namespace llarp 24 | -------------------------------------------------------------------------------- /pybind/llarp/dht/dht_types.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp 7 | { 8 | namespace dht 9 | { 10 | void DHTTypes_Init(py::module& mod) 11 | { 12 | py::class_(mod, "DHTKey") 13 | .def(py::self == py::self) 14 | .def(py::self < py::self) 15 | .def(py::self ^ py::self) 16 | .def("distance", [](const Key_t* const lhs, const Key_t* const rhs) { return *lhs ^ *rhs; }) 17 | .def("ShortString", [](const Key_t* const key) { 18 | return llarp::RouterID(key->as_array()).ShortString(); 19 | }); 20 | } 21 | 22 | } // namespace dht 23 | } // namespace llarp 24 | -------------------------------------------------------------------------------- /pybind/llarp/handlers/pyhandler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | namespace llarp 3 | { 4 | namespace handlers 5 | { 6 | void PyHandler_Init(py::module& mod) 7 | { 8 | py::class_(mod, "Endpoint") 9 | .def(py::init()) 10 | .def("SendTo", &PythonEndpoint::SendPacket) 11 | .def("OurAddress", &PythonEndpoint::GetOurAddress) 12 | .def_readwrite("GotPacket", &PythonEndpoint::handlePacket); 13 | } 14 | 15 | } // namespace handlers 16 | 17 | } // namespace llarp 18 | -------------------------------------------------------------------------------- /pybind/llarp/logger.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace llarp 8 | { 9 | struct PyLogger 10 | { 11 | std::optional silenced; 12 | }; 13 | 14 | void Logger_Init(py::module& mod) 15 | { 16 | py::class_(mod, "LogContext") 17 | .def(py::init<>()) 18 | .def_property( 19 | "shutup", 20 | [](PyLogger& self) { return self.silenced.has_value(); }, 21 | [](PyLogger& self, bool shutup) { 22 | if (shutup and not self.silenced) 23 | self.silenced = llarp::log::get_level_default(); 24 | else if (not shutup and self.silenced) 25 | { 26 | llarp::log::reset_level(*self.silenced); 27 | self.silenced.reset(); 28 | } 29 | }); 30 | } 31 | } // namespace llarp 32 | -------------------------------------------------------------------------------- /pybind/llarp/path/path_hop_config.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | namespace path 8 | { 9 | void PathHopConfig_Init(py::module& mod) 10 | { 11 | auto str_func = [](PathHopConfig* hop) { 12 | std::string s = "Hop: ["; 13 | s += RouterID(hop->rc.pubkey).ShortString(); 14 | s += "] -> ["; 15 | s += hop->upstream.ShortString(); 16 | s += "]"; 17 | return s; 18 | }; 19 | py::class_(mod, "PathHopConfig") 20 | .def_readonly("rc", &PathHopConfig::rc) 21 | .def_readonly("upstreamRouter", &PathHopConfig::upstream) 22 | .def_readonly("txid", &PathHopConfig::txID) 23 | .def_readonly("rxid", &PathHopConfig::rxID) 24 | .def("ToString", str_func) 25 | .def("__str__", str_func) 26 | .def("__repr__", str_func); 27 | } 28 | } // namespace path 29 | } // namespace llarp 30 | -------------------------------------------------------------------------------- /pybind/llarp/path/path_types.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp 7 | { 8 | void PathTypes_Init(py::module& mod) 9 | { 10 | py::class_(mod, "PathID") 11 | .def(py::self == py::self) 12 | .def("ShortHex", &PathID_t::ShortHex) 13 | .def("__str__", &PathID_t::ShortHex) 14 | .def("__repr__", &PathID_t::ShortHex); 15 | } 16 | 17 | } // namespace llarp 18 | -------------------------------------------------------------------------------- /pybind/llarp/router.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace llarp 7 | { 8 | void Router_Init(py::module& mod) 9 | { 10 | py::class_>(mod, "Router") 11 | .def("rc", &Router::rc) 12 | .def("Stop", &Router::Stop) 13 | .def("peerDb", &Router::peerDb); 14 | } 15 | 16 | } // namespace llarp 17 | 18 | namespace tooling 19 | { 20 | void HiveRouter_Init(py::module& mod) 21 | { 22 | py::class_>(mod, "HiveRouter") 23 | .def("disableGossiping", &HiveRouter::disableGossiping) 24 | .def("enableGossiping", &HiveRouter::enableGossiping); 25 | } 26 | } // namespace tooling 27 | -------------------------------------------------------------------------------- /pybind/llarp/router_contact.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace llarp 8 | { 9 | void RelayContact_Init(py::module& mod) 10 | { 11 | py::class_(mod, "RelayContact") 12 | .def(py::init<>()) 13 | .def_property_readonly( 14 | "routerID", [](const RelayContact* const rc) -> llarp::RouterID { return llarp::RouterID(rc->pubkey); }) 15 | .def_property_readonly( 16 | "AsDHTKey", 17 | [](const RelayContact* const rc) -> llarp::dht::Key_t { 18 | return llarp::dht::Key_t{rc->pubkey.as_array()}; 19 | }) 20 | .def("ReadFile", &RelayContact::Read) 21 | .def("WriteFile", &RelayContact::Write) 22 | .def("ToString", &RelayContact::ToString) 23 | .def("__str__", &RelayContact::ToString) 24 | .def("__repr__", &RelayContact::ToString) 25 | .def("Verify", [](const RelayContact* const rc) -> bool { 26 | const std::chrono::milliseconds now = llarp::time_now_ms(); 27 | return rc->Verify(now); 28 | }); 29 | } 30 | } // namespace llarp 31 | -------------------------------------------------------------------------------- /pybind/llarp/router_id.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | void RouterID_Init(py::module& mod) 8 | { 9 | py::class_(mod, "RouterID") 10 | .def( 11 | "FromHex", 12 | [](RouterID* r, const std::string& hex) { 13 | if (hex.size() != 2 * r->size() || !oxenc::is_hex(hex)) 14 | throw std::runtime_error("FromHex requires a 64-digit hex string"); 15 | oxenc::from_hex(hex.begin(), hex.end(), r->data()); 16 | }) 17 | .def("__repr__", &RouterID::ToString) 18 | .def("__str__", &RouterID::ToString) 19 | .def("ShortString", &RouterID::ShortString) 20 | .def("__eq__", [](const RouterID& lhs, const RouterID& rhs) { return lhs == rhs; }); 21 | } 22 | } // namespace llarp 23 | -------------------------------------------------------------------------------- /pybind/llarp/service/address.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | namespace service 8 | { 9 | void Address_Init(py::module& mod) 10 | { 11 | py::class_
(mod, "ServiceAddress") 12 | .def(py::init()) 13 | .def("__str__", [](const Address& addr) -> std::string { return addr.ToString(); }); 14 | } 15 | } // namespace service 16 | } // namespace llarp 17 | -------------------------------------------------------------------------------- /pybind/module.cpp: -------------------------------------------------------------------------------- 1 | #include "common.hpp" 2 | 3 | #include 4 | 5 | PYBIND11_MODULE(pyllarp, m) 6 | { 7 | tooling::RouterHive_Init(m); 8 | tooling::RouterEvent_Init(m); 9 | llarp::Router_Init(m); 10 | tooling::HiveRouter_Init(m); 11 | llarp::PeerDb_Init(m); 12 | llarp::PeerStats_Init(m); 13 | llarp::RouterID_Init(m); 14 | llarp::RelayContact_Init(m); 15 | llarp::CryptoTypes_Init(m); 16 | llarp::Context_Init(m); 17 | tooling::HiveContext_Init(m); 18 | llarp::Config_Init(m); 19 | llarp::dht::DHTTypes_Init(m); 20 | llarp::PathTypes_Init(m); 21 | llarp::path::PathHopConfig_Init(m); 22 | llarp::handlers::PyHandler_Init(m); 23 | llarp::service::Address_Init(m); 24 | m.def("EnableDebug", []() { llarp::log::reset_level(llarp::log::Level::debug); }); 25 | llarp::Logger_Init(m); 26 | } 27 | -------------------------------------------------------------------------------- /pybind/readme.md: -------------------------------------------------------------------------------- 1 | pybind lokinet module for integration tests and network simulation 2 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Lokinet 2 | 3 | 4 | 5 | Lokinet is the reference implementation of LLARP (low latency anonymous routing protocol), a layer 3 onion routing protocol. 6 | 7 | ### Installation instructions can be found [here](docs/install.md). 8 | 9 | #### You can learn more about the high level, how to use it and the internals of the protocol [here](docs/readme.md) 10 | 11 | [![Build Status](https://ci.oxen.rocks/api/badges/oxen-io/lokinet/status.svg?ref=refs/heads/dev)](https://ci.oxen.rocks/oxen-io/lokinet) 12 | 13 | # License 14 | 15 | This program is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as published by 17 | the Free Software Foundation, either version 3 of the License, or 18 | (at your option) any later version. 19 | 20 | ``` 21 | Copyright © 2018-2022 The Oxen Project 22 | Copyright © 2018-2022 Jeff Becker 23 | Copyright © 2018-2020 Rick V. (Historical Windows NT port and portions) 24 | ``` 25 | -------------------------------------------------------------------------------- /test/check_main.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_RUNNER 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #ifdef _WIN32 8 | #include 9 | int 10 | startWinsock() 11 | { 12 | WSADATA wsockd; 13 | int err; 14 | err = ::WSAStartup(MAKEWORD(2, 2), &wsockd); 15 | if (err) 16 | { 17 | perror("Failed to start Windows Sockets"); 18 | return err; 19 | } 20 | return 0; 21 | } 22 | #endif 23 | 24 | int 25 | main(int argc, char* argv[]) 26 | { 27 | llarp::sys::service_manager->disable(); 28 | llarp::log::reset_level(llarp::log::Level::off); 29 | 30 | #ifdef _WIN32 31 | if (startWinsock()) 32 | return -1; 33 | #endif 34 | 35 | int result = Catch::Session().run(argc, argv); 36 | #ifdef _WIN32 37 | WSACleanup(); 38 | #endif 39 | return result; 40 | } 41 | -------------------------------------------------------------------------------- /test/config/test_llarp_config_ini.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | TEST_CASE("ConfigParser", "[config]") 6 | { 7 | llarp::ConfigParser parser; 8 | 9 | SECTION("Parse empty") 10 | { 11 | REQUIRE(parser.LoadFromStr("")); 12 | } 13 | 14 | SECTION("Parse one section") 15 | { 16 | llarp::ConfigParser::SectionValues_t sect; 17 | // this is an anti pattern don't write this kind of code with configpaser 18 | auto assertVisit = [§](const auto& section) -> bool { 19 | sect = section; 20 | return true; 21 | }; 22 | REQUIRE(parser.LoadFromStr("[test]\nkey=val \n")); 23 | REQUIRE(parser.VisitSection("test", assertVisit)); 24 | auto itr = sect.find("notfound"); 25 | REQUIRE(itr == sect.end()); 26 | itr = sect.find("key"); 27 | REQUIRE(itr != sect.end()); 28 | REQUIRE(itr->second == "val"); 29 | } 30 | 31 | SECTION("Parse section duplicate keys") 32 | { 33 | REQUIRE(parser.LoadFromStr("[test]\nkey1=val1\nkey1=val2")); 34 | size_t num = 0; 35 | auto visit = [&num](const auto& section) -> bool { 36 | num = section.count("key1"); 37 | return true; 38 | }; 39 | REQUIRE(parser.VisitSection("test", visit)); 40 | REQUIRE(num == size_t(2)); 41 | } 42 | 43 | SECTION("No key") 44 | { 45 | REQUIRE_THROWS(parser.LoadFromStr("[test]\n=1090\n")); 46 | } 47 | 48 | SECTION("Parse invalid") 49 | { 50 | REQUIRE_THROWS( 51 | parser.LoadFromStr("srged5ghe5\nf34wtge5\nw34tgfs4ygsd5yg=4;\n#" 52 | "g4syhgd5\n")); 53 | } 54 | 55 | parser.Clear(); 56 | } 57 | -------------------------------------------------------------------------------- /test/hive/conftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import hive 3 | import pytest 4 | 5 | @pytest.fixture(scope="session") 6 | def HiveTenRTenC(): 7 | router_hive = hive.RouterHive(n_relays=10, n_clients=10, netid="hive") 8 | router_hive.Start() 9 | 10 | yield router_hive 11 | 12 | router_hive.Stop() 13 | 14 | @pytest.fixture(scope="session") 15 | def HiveThirtyRTenC(): 16 | router_hive = hive.RouterHive(n_relays=30, n_clients=10, netid="hive") 17 | router_hive.Start() 18 | 19 | yield router_hive 20 | 21 | router_hive.Stop() 22 | 23 | @pytest.fixture() 24 | def HiveArbitrary(): 25 | router_hive = None 26 | def _make(n_relays=10, n_clients=10, netid="hive"): 27 | nonlocal router_hive 28 | router_hive = hive.RouterHive(n_relays=30, n_clients=10, netid="hive") 29 | router_hive.Start() 30 | return router_hive 31 | 32 | yield _make 33 | if router_hive: 34 | router_hive.Stop() 35 | 36 | @pytest.fixture() 37 | def HiveForPeerStats(): 38 | router_hive = None 39 | def _make(n_relays, n_clients, netid): 40 | nonlocal router_hive 41 | router_hive = hive.RouterHive(n_relays, n_clients, netid) 42 | router_hive.Start() 43 | return router_hive 44 | 45 | yield _make 46 | if router_hive: 47 | router_hive.Stop() 48 | -------------------------------------------------------------------------------- /test/mocks/mock_context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "mock_network.hpp" 5 | #include "mock_router.hpp" 6 | #include "mock_vpn.hpp" 7 | 8 | namespace mocks 9 | { 10 | class MockContext : public llarp::Context 11 | { 12 | const Network& _net; 13 | 14 | public: 15 | MockContext(const Network& net) : llarp::Context{}, _net{net} 16 | { 17 | loop = std::shared_ptr{const_cast(&_net), [](Network*) {}}; 18 | } 19 | 20 | std::shared_ptr 21 | makeRouter(const std::shared_ptr&) override 22 | { 23 | return std::static_pointer_cast( 24 | std::make_shared(_net, makeVPNPlatform())); 25 | } 26 | 27 | std::shared_ptr 28 | makeVPNPlatform() override 29 | { 30 | return std::static_pointer_cast(std::make_shared(_net)); 31 | } 32 | 33 | std::shared_ptr 34 | makeNodeDB() override 35 | { 36 | return std::make_shared(); 37 | } 38 | }; 39 | 40 | } // namespace mocks 41 | -------------------------------------------------------------------------------- /test/mocks/mock_router.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "mock_network.hpp" 5 | 6 | namespace mocks 7 | { 8 | class MockRouter : public llarp::Router 9 | { 10 | const Network& _net; 11 | 12 | public: 13 | explicit MockRouter(const Network& net, std::shared_ptr vpnPlatform) 14 | : llarp:: 15 | Router{std::shared_ptr{const_cast(&net), [](Network*) {}}, vpnPlatform} 16 | , _net{net} 17 | {} 18 | 19 | const llarp::net::Platform& 20 | Net() const override 21 | { 22 | return _net; 23 | }; 24 | }; 25 | } // namespace mocks 26 | -------------------------------------------------------------------------------- /test/net/test_ip_address.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | TEST_CASE("IpAddress empty constructor", "[IpAdress]") 6 | { 7 | llarp::IpAddress address; 8 | CHECK(address.isEmpty() == true); 9 | } 10 | -------------------------------------------------------------------------------- /test/path/test_path.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using Path_t = llarp::path::Path; 5 | using Path_ptr = llarp::path::Path_ptr; 6 | using Set_t = llarp::path::Path::UniqueEndpointSet_t; 7 | using RC_t = llarp::RelayContact; 8 | 9 | static RC_t 10 | MakeHop(const char name) 11 | { 12 | RC_t rc; 13 | rc.pubkey.Fill(name); 14 | return rc; 15 | } 16 | 17 | static Path_ptr 18 | MakePath(std::vector< char > hops) 19 | { 20 | std::vector< RC_t > pathHops; 21 | for(const auto& hop : hops) 22 | pathHops.push_back(MakeHop(hop)); 23 | return std::make_shared< Path_t >(pathHops, std::weak_ptr{}, 0, "test"); 24 | } 25 | 26 | TEST_CASE("UniqueEndpointSet_t has unique endpoints", "[path]") 27 | { 28 | Set_t set; 29 | REQUIRE(set.empty()); 30 | const auto inserted_first = 31 | set.emplace(MakePath({'a', 'b', 'c', 'd'})).second; 32 | REQUIRE(inserted_first); 33 | const auto inserted_again = 34 | set.emplace(MakePath({'a', 'b', 'c', 'd'})).second; 35 | REQUIRE(not inserted_again); 36 | const auto inserted_second = 37 | set.emplace(MakePath({'d', 'c', 'b', 'a'})).second; 38 | REQUIRE(inserted_second); 39 | } 40 | -------------------------------------------------------------------------------- /test/readme.md: -------------------------------------------------------------------------------- 1 | unit tests and such 2 | 3 | to enable unit tests, add cmake flag `-DWITH_TESTS=ON` 4 | 5 | unit tests can be built and run with the `check` target. 6 | -------------------------------------------------------------------------------- /test/routing/test_llarp_routing_obtainexitmessage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | using namespace ::llarp; 8 | using namespace ::llarp::test; 9 | 10 | using ObtainExitMessage = routing::ObtainExitMessage; 11 | 12 | void 13 | fill(Signature& s) 14 | { 15 | s.Fill(0xFF); 16 | } 17 | 18 | TEST_CASE("Sign-verify") 19 | { 20 | SecretKey alice{}; 21 | crypto::identity_keygen(alice); 22 | REQUIRE(not alice.IsZero()); 23 | ObtainExitMessage msg{}; 24 | msg.S = randint(); 25 | msg.T = randint(); 26 | CHECK(msg.Sign(alice)); 27 | CHECK(msg.Verify()); 28 | CHECK(msg.I == PubKey{seckey_topublic(alice)}); 29 | CHECK(msg.version == llarp::constants::proto_version); 30 | CHECK_FALSE(msg.Z.IsZero()); 31 | } 32 | -------------------------------------------------------------------------------- /test/routing/test_llarp_routing_transfer_traffic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | using TransferTrafficMessage = llarp::routing::TransferTrafficMessage; 6 | 7 | TEST_CASE("TransferTrafficMessage", "[TransferTrafficMessage]") 8 | { 9 | TransferTrafficMessage msg; 10 | 11 | SECTION("Put buffer overflow") 12 | { 13 | std::array tmp = {{0}}; 14 | llarp_buffer_t buf(tmp); 15 | REQUIRE_FALSE(msg.PutBuffer(buf, 1)); 16 | } 17 | 18 | SECTION("Put buffer") 19 | { 20 | std::array tmp = {{0}}; 21 | llarp_buffer_t buf(tmp); 22 | REQUIRE(msg.PutBuffer(buf, 1)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/test_llarp_encrypted_frame.cpp: -------------------------------------------------------------------------------- 1 | #include "llarp_test.hpp" 2 | #include "test_util.hpp" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace ::llarp; 9 | 10 | using EncryptedFrame = EncryptedFrame; 11 | using SecretKey = SecretKey; 12 | using PubKey = PubKey; 13 | using LRCR = LR_CommitRecord; 14 | 15 | class FrameTest 16 | { 17 | public: 18 | FrameTest() : test::LlarpTest<>{} 19 | { 20 | crypto::encryption_keygen(alice); 21 | crypto::encryption_keygen(bob); 22 | } 23 | 24 | SecretKey alice, bob; 25 | }; 26 | 27 | TEST_CASE_METHOD(FrameTest, "Frame crypto") 28 | { 29 | EncryptedFrame f{256}; 30 | f.Fill(0); 31 | LRCR record{}; 32 | record.nextHop.Fill(1); 33 | record.tunnelNonce.Fill(2); 34 | record.rxid.Fill(3); 35 | record.txid.Fill(4); 36 | 37 | auto buf = f.Buffer(); 38 | buf->cur = buf->base + EncryptedFrameOverheadSize; 39 | 40 | REQUIRE(record.BEncode(buf)); 41 | 42 | // rewind buffer 43 | buf->cur = buf->base + EncryptedFrameOverheadSize; 44 | // encrypt to alice 45 | REQUIRE(f.EncryptInPlace(alice, bob.toPublic())); 46 | 47 | // decrypt from alice 48 | REQUIRE(f.DecryptInPlace(bob)); 49 | 50 | LRCR otherRecord; 51 | REQUIRE(otherRecord.BDecode(buf)); 52 | REQUIRE(otherRecord == record); 53 | } 54 | -------------------------------------------------------------------------------- /test/test_util.cpp: -------------------------------------------------------------------------------- 1 | #include "test_util.hpp" 2 | 3 | #include 4 | 5 | namespace llarp 6 | { 7 | namespace test 8 | { 9 | std::string 10 | randFilename() 11 | { 12 | static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz"; 13 | 14 | std::random_device rd; 15 | std::uniform_int_distribution< size_t > dist{0, sizeof(alphabet) - 2}; 16 | 17 | std::string filename; 18 | for(size_t i = 0; i < 5; ++i) 19 | { 20 | filename.push_back(alphabet[dist(rd)]); 21 | } 22 | 23 | filename.push_back('.'); 24 | 25 | for(size_t i = 0; i < 5; ++i) 26 | { 27 | filename.push_back(alphabet[dist(rd)]); 28 | } 29 | 30 | return filename; 31 | } 32 | } // namespace test 33 | } // namespace llarp 34 | -------------------------------------------------------------------------------- /test/util/meta/test_llarp_util_memfn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | using namespace llarp; 6 | 7 | struct Foo 8 | { 9 | bool 10 | empty() 11 | { 12 | return false; 13 | } 14 | 15 | bool 16 | constEmpty() const 17 | { 18 | return true; 19 | } 20 | 21 | int 22 | arg(int v) 23 | { 24 | return v + 1; 25 | } 26 | 27 | int 28 | constArg(int v) const 29 | { 30 | return v - 1; 31 | } 32 | }; 33 | 34 | TEST_CASE("memFn call") 35 | { 36 | Foo foo; 37 | REQUIRE_FALSE(util::memFn(&Foo::empty, &foo)()); 38 | REQUIRE(util::memFn(&Foo::constEmpty, &foo)()); 39 | REQUIRE(11 == util::memFn(&Foo::arg, &foo)(10)); 40 | REQUIRE(9 == util::memFn(&Foo::constArg, &foo)(10)); 41 | 42 | REQUIRE(util::memFn(&Foo::constEmpty, &foo)()); 43 | REQUIRE(9 == util::memFn(&Foo::constArg, &foo)(10)); 44 | } 45 | 46 | // clang-format off 47 | using MemFnTypes = std::tuple< 48 | Foo, const Foo>; 49 | // clang-format on 50 | 51 | TEMPLATE_LIST_TEST_CASE("memFn type smoke test", "", MemFnTypes) 52 | { 53 | TestType foo{}; 54 | REQUIRE(util::memFn(&Foo::constEmpty, &foo)()); 55 | } 56 | -------------------------------------------------------------------------------- /test/util/test_llarp_util_decaying_hashset.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TEST_CASE("DecayingHashSet test decay static time", "[decaying-hashset]") 6 | { 7 | static constexpr auto timeout = 5s; 8 | static constexpr auto now = 1s; 9 | llarp::util::DecayingHashSet hashset{timeout}; 10 | const llarp::RouterID zero{}; 11 | REQUIRE(zero.IsZero()); 12 | REQUIRE(not hashset.Contains(zero)); 13 | REQUIRE(hashset.Insert(zero, now)); 14 | REQUIRE(hashset.Contains(zero)); 15 | hashset.Decay(now + 1s); 16 | REQUIRE(hashset.Contains(zero)); 17 | hashset.Decay(now + timeout); 18 | REQUIRE(not hashset.Contains(zero)); 19 | hashset.Decay(now + timeout + 1s); 20 | REQUIRE(not hashset.Contains(zero)); 21 | } 22 | 23 | TEST_CASE("DecayingHashSet test decay dynamic time", "[decaying-hashset]") 24 | { 25 | static constexpr llarp_time_t timeout = 5s; 26 | const auto now = llarp::time_now_ms(); 27 | llarp::util::DecayingHashSet hashset{timeout}; 28 | const llarp::RouterID zero{}; 29 | REQUIRE(zero.IsZero()); 30 | REQUIRE(not hashset.Contains(zero)); 31 | REQUIRE(hashset.Insert(zero, now)); 32 | REQUIRE(hashset.Contains(zero)); 33 | hashset.Decay(now + 1s); 34 | REQUIRE(hashset.Contains(zero)); 35 | hashset.Decay(now + timeout); 36 | REQUIRE(not hashset.Contains(zero)); 37 | hashset.Decay(now + timeout + 1s); 38 | REQUIRE(not hashset.Contains(zero)); 39 | } 40 | -------------------------------------------------------------------------------- /test/win32/test.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/test/win32/test.rc -------------------------------------------------------------------------------- /win32-setup/.gitignore: -------------------------------------------------------------------------------- 1 | mbedtls*.tgz* 2 | mbedtls-*/ 3 | curl*.tar.xz* 4 | curl-*/ 5 | include/ 6 | lib/ 7 | *.pem 8 | LICENSE 9 | 7z.exe 10 | dbghelp* 11 | *.7z -------------------------------------------------------------------------------- /win32-setup/config_migration.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | copy lokinet.ini lokinet.old.ini 3 | del lokinet.ini 4 | %PROGRAMFILES%\Loki Project\Lokinet\lokinet -g -------------------------------------------------------------------------------- /win32-setup/extra_create_icons.nsis: -------------------------------------------------------------------------------- 1 | CreateShortCut '$SMPROGRAMS\$STARTMENU_FOLDER\Lokinet.lnk' '$INSTDIR\share\gui\lokinet-gui.exe' 2 | -------------------------------------------------------------------------------- /win32-setup/extra_delete_icons.nsis: -------------------------------------------------------------------------------- 1 | CreateShortCut '$SMPROGRAMS\$STARTMENU_FOLDER\Lokinet.lnk' '$INSTDIR\share\gui\lokinet-gui.exe' 2 | -------------------------------------------------------------------------------- /win32-setup/extra_install.nsis: -------------------------------------------------------------------------------- 1 | ExecWait '$INSTDIR\bin\lokinet.exe --install' 2 | ExecWait '$INSTDIR\bin\lokinet.exe -g C:\ProgramData\lokinet\lokinet.ini' 3 | CopyFiles '$INSTDIR\share\bootstrap.signed' C:\ProgramData\lokinet\bootstrap.signed 4 | 5 | ifFileExists $INSTDIR\share\conf.d 0 +3 6 | CreateDirectory C:\ProgramData\lokinet\conf.d 7 | CopyFiles '$INSTDIR\share\conf.d\*.ini' C:\ProgramData\lokinet\conf.d 8 | 9 | IfFileExists $INSTDIR\bin\WinDivert64.sys +2 0 10 | CopyFiles '$INSTDIR\lib\WinDivert64.sys' '$INSTDIR\bin\WinDivert64.sys' 11 | 12 | IfFileExists $INSTDIR\bin\WinDivert.sys +2 0 13 | CopyFiles '$INSTDIR\lib\WinDivert.sys' '$INSTDIR\bin\WinDivert.sys' -------------------------------------------------------------------------------- /win32-setup/extra_preinstall.nsis: -------------------------------------------------------------------------------- 1 | ExecWait 'taskkill /f /t /im lokinet-gui.exe' 2 | 3 | IfFileExists $INSTDIR\bin\lokinet.exe 0 +3 4 | ExecWait 'net stop lokinet' 5 | ExecWait '$INSTDIR\bin\lokinet.exe --remove' 6 | 7 | -------------------------------------------------------------------------------- /win32-setup/extra_uninstall.nsis: -------------------------------------------------------------------------------- 1 | ExecWait 'taskkill /f /t /im lokinet-gui.exe' 2 | ExecWait 'net stop lokinet' 3 | ExecWait 'sc stop windivert' 4 | ExecWait '$INSTDIR\bin\lokinet.exe --remove' 5 | 6 | IfFileExists '$INSTDIR\bin\WinDivert64.sys' 0 +2 7 | Delete /REBOOTOK '$INSTDIR\bin\WinDivert64.sys' 8 | 9 | IfFileExists '$INSTDIR\bin\WinDivert.sys' 0 +2 10 | Delete /REBOOTOK '$INSTDIR\bin\WinDivert.sys' 11 | 12 | RMDir /r /REBOOTOK C:\ProgramData\lokinet 13 | RMDir /r /REBOOTOK '$INSTDIR\share\conf.d' 14 | -------------------------------------------------------------------------------- /win32-setup/lokinet-win32.iss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/win32-setup/lokinet-win32.iss -------------------------------------------------------------------------------- /win32-setup/lokinet.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxen-io/lokinet/b12e88a83c9c3748bdfebe1f332fa3558461b1f6/win32-setup/lokinet.ico -------------------------------------------------------------------------------- /win32-setup/notes.txt: -------------------------------------------------------------------------------- 1 | [16:24:37] (Channel) despair86: http://files.jrsoftware.org/is/5/innosetup-5.6.1-unicode.exe 2 | [16:29:23] (Channel) despair86: wine [path to ISCC.exe] -DSINGLE_ARCH lokinet-win32.iss 3 | [16:29:28] (Channel) despair86: should work 4 | [16:30:11] (Channel) despair86: make -C win32-setup 5 | [16:30:33] (Channel) despair86: cmake . -DCMAKE_TOOLCHAIN_FILE [options] build 6 | [16:30:37] (Channel) despair86: make -C build 7 | [16:30:51] (Channel) despair86: then use wine to build package 8 | --------------------------------------------------------------------------------