├── .containerignore ├── .github └── workflows │ ├── debug.yml │ ├── quick.yml │ ├── quick_windows.yml │ ├── slow_bsd.yml │ ├── slow_openwrt.yml │ └── tests.yml ├── .gitignore ├── .gitmodules ├── .yamllint.yml ├── LICENSES └── preferred │ ├── GPL-2.0 │ ├── GPL-3.0 │ └── LGPL-2.1 ├── Makefile ├── README.md ├── VERSION ├── apps ├── .gitignore ├── Makefile ├── example_edge_embed.c ├── example_edge_embed_quick_edge_init.c ├── example_sn_embed.c ├── n3n-edge.c └── n3n-supernode.c ├── autogen.sh ├── config.mak.in ├── configure.ac ├── debian ├── .gitignore ├── control ├── copyright ├── n3n.lintian-overrides ├── n3n.postinst ├── rules └── source │ └── format ├── doc ├── Advanced.md ├── Authentication.md ├── Bridging.md ├── BuildConfig.md ├── Building.md ├── Communities.md ├── ConfigurationFiles.md ├── Containerfile.example ├── Crypto.md ├── EdgeOS-notes.txt ├── Faq.md ├── Federation.md ├── Hacking.md ├── INSTALL ├── ManagementAPI.md ├── ReleaseProcess.md ├── Routing.md ├── Scratchpad.md ├── Scripts.md ├── Security.md ├── Supernode.md ├── TapConfiguration.md ├── Tools.md ├── TrafficRestrictions.md ├── community.list.sample ├── contributors.txt ├── edge.conf.sample └── supernode.conf.sample ├── include ├── aes.h ├── auth.h ├── cc20.h ├── curve25519.h ├── header_encryption.h ├── json.h ├── lzoconf.h ├── lzodefs.h ├── minilzo.h ├── n2n.h ├── n2n_define.h ├── n2n_port_mapping.h ├── n2n_regex.h ├── n2n_typedefs.h ├── n2n_wire.h ├── n3n │ ├── conffile.h │ ├── edge.h │ ├── endian.h │ ├── ethernet.h │ ├── hexdump.h │ ├── initfuncs.h │ ├── logging.h │ ├── mainloop.h │ ├── metrics.h │ ├── network_traffic_filter.h │ ├── peer_info.h │ ├── random.h │ ├── resolve.h │ ├── strings.h │ ├── supernode.h │ ├── tests.h │ └── transform.h ├── pearson.h ├── portable_endian.h ├── sn_selection.h ├── speck.h ├── tf.h └── uthash.h ├── libs └── connslot │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── connslot-tests.c │ ├── connslot.c │ ├── connslot.h │ ├── file2strbufc │ ├── httpd-test.c │ ├── jsonrpc.c │ ├── jsonrpc.h │ ├── strbuf-tests.c │ ├── strbuf.c │ ├── strbuf.h │ └── uncrustify.cfg ├── n3n-edge.8 ├── n3n-supernode.8 ├── n3n.7 ├── packages ├── .gitignore ├── centos ├── lib │ └── systemd │ │ └── system │ │ ├── n3n-edge.service │ │ ├── n3n-edge@.service │ │ └── n3n-supernode.service ├── openwrt │ ├── Makefile │ ├── README.md │ ├── config.bthh5a │ ├── config.n3n │ ├── config.x86 │ └── etc │ │ └── init.d │ │ ├── n3n-edge │ │ └── n3n-supernode └── rpm │ ├── Makefile │ ├── n3n.spec │ └── rpm-sign.exp ├── scripts ├── README.md ├── config.guess.DIST ├── config.sub.DIST ├── hack_fakeautoconf.sh ├── indent.sh ├── install-sh ├── munin │ └── n3n_ ├── n3n-convert_old_conf ├── n3n-gateway.sh ├── n3nctl ├── test_builtin_edge.sh ├── test_harness.sh ├── test_integration_edge.sh ├── test_integration_edge_tcp.sh ├── test_integration_packets.sh ├── test_integration_supernode.sh ├── test_integration_webui.sh ├── test_packets └── version.sh ├── src ├── .gitignore ├── aes.c ├── auth.c ├── base64.c ├── base64.h ├── cc20.c ├── conffile.c ├── conffile_defs.c ├── curve25519.c ├── edge_utils.c ├── edge_utils.h ├── header_encryption.c ├── hexdump.c ├── initfuncs.c ├── json.c ├── logging.c ├── mainloop.c ├── management.c ├── management.h ├── management_index.html ├── management_script.js ├── metrics.c ├── minilzo.c ├── minmax.h ├── n2n.c ├── n2n_port_mapping.c ├── n2n_regex.c ├── network_traffic_filter.c ├── pearson.c ├── peer_info.c ├── peer_info.h ├── pktbuf.c ├── pktbuf.h ├── random_numbers.c ├── resolve.c ├── resolve.h ├── sn_selection.c ├── sn_utils.c ├── speck.c ├── test_hashing.c ├── tf.c ├── transform.c ├── transform_aes.c ├── transform_cc20.c ├── transform_lzo.c ├── transform_none.c ├── transform_null.c ├── transform_speck.c ├── transform_tf.c ├── transform_zstd.c ├── tuntap_freebsd.c ├── tuntap_linux.c ├── tuntap_netbsd.c ├── tuntap_osx.c ├── win32 │ ├── DotNet │ │ ├── n2n.sln │ │ ├── n2n.suo │ │ ├── n2n.vcproj │ │ └── supernode.vcproj │ ├── defs.h │ ├── edge.manifest │ ├── edge.rc │ ├── edge_utils_win32.c │ ├── edge_utils_win32.h │ ├── getopt.c │ ├── getopt.h │ ├── getopt1.c │ ├── n2n_win32.h │ ├── win32.c │ ├── wintap.c │ └── wintap.h └── wire.c ├── tests ├── test_builtin_edge.sh.expected ├── test_integration_edge.sh.expected ├── test_integration_edge_tcp.sh.expected ├── test_integration_packets.sh.expected ├── test_integration_supernode.sh.expected ├── test_integration_webui.sh.expected ├── tests-auth.expected ├── tests-compress.expected ├── tests-elliptic.expected ├── tests-transform.expected ├── tests-wire.expected ├── tests_builtin.list ├── tests_integration.list └── tests_units.list ├── tools ├── .gitignore ├── Makefile ├── crypto_helper.c ├── n3n-benchmark.c ├── n3n-decode.c ├── n3n-portfwd.c ├── n3n-route.c ├── tests-auth.c ├── tests-compress.c ├── tests-elliptic.c ├── tests-transform.c └── tests-wire.c ├── uncrustify.cfg └── wireshark ├── README.md └── n3n.lua /.containerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | LICENSES/ 3 | debian/ 4 | doc/ 5 | packages/ 6 | thirdparty/ 7 | wireshark/ 8 | -------------------------------------------------------------------------------- /.github/workflows/debug.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Debug 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | 10 | # Oh, github, for a company that is built around the git VCS, how is it 11 | # that you have managed to break the repositories so much? 12 | # 13 | debug_github_repo: 14 | name: Debug Github Repo 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Fix Checkout 23 | run: | 24 | git fetch --force --tags 25 | 26 | - name: Debug data output 27 | run: | 28 | echo ========== 29 | echo git status 30 | git status 31 | echo ========== 32 | echo git tag 33 | git tag 34 | echo ========== 35 | echo git describe 36 | git describe || true 37 | echo ========== 38 | echo git for-each-ref refs/heads 39 | git for-each-ref refs/heads 40 | echo ========== 41 | echo git for-each-ref refs/tags 42 | git for-each-ref refs/tags 43 | echo ========== 44 | echo ls .git/refs/heads 45 | ls .git/refs/heads 46 | echo ========== 47 | echo ls .git/refs/tags 48 | ls .git/refs/tags 49 | echo ========== 50 | TYPE=$(git cat-file -t $GITHUB_REF) 51 | echo REF=$GITHUB_REF 52 | echo TAGTYPE=$TYPE 53 | echo ========== 54 | echo git cat-file $TYPE $GITHUB_REF 55 | git cat-file $TYPE $GITHUB_REF 56 | -------------------------------------------------------------------------------- /.github/workflows/quick.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Quick Tests 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | push: 7 | pull_request: 8 | workflow_dispatch: 9 | 10 | jobs: 11 | smoketest: 12 | name: Smoke test 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | - name: Fix Checkout 20 | run: | 21 | git fetch --force --tags 22 | 23 | - name: Run minimal test set 24 | run: | 25 | ./autogen.sh 26 | ./configure 27 | make -j4 all 28 | make test 29 | 30 | - if: ${{ failure() }} 31 | name: Upload tests output 32 | uses: actions/upload-artifact@v4 33 | with: 34 | name: tests-smoketest 35 | path: tests 36 | 37 | smoketest_all_opts: 38 | name: Smoke test With all options turned on 39 | runs-on: ubuntu-latest 40 | 41 | steps: 42 | - uses: actions/checkout@v4 43 | with: 44 | fetch-depth: 0 45 | - name: Fix Checkout 46 | run: | 47 | git fetch --force --tags 48 | 49 | - name: Install libraries needed for all options turned on 50 | run: | 51 | sudo apt-get update 52 | sudo apt-get install -y \ 53 | libminiupnpc-dev \ 54 | libnatpmp-dev \ 55 | libpcap-dev \ 56 | libcap-dev \ 57 | libzstd-dev 58 | 59 | - name: Run minimal test set 60 | run: | 61 | ./autogen.sh 62 | ./configure \ 63 | --enable-pthread \ 64 | --enable-miniupnp \ 65 | --enable-natpmp \ 66 | --enable-cap \ 67 | --enable-pcap \ 68 | --with-openssl \ 69 | --with-zstd \ 70 | CFLAGS="-O3 -fprofile-arcs -ftest-coverage" 71 | LDFLAGS="--coverage" 72 | make build-dep 73 | make -j4 all examples 74 | make test 75 | 76 | - name: Generate coverage reports 77 | run: | 78 | make gcov 79 | make cover COVERAGEDIR=coverage/ubuntu-22.04 80 | shell: bash 81 | 82 | - name: Upload gcovr report artifact 83 | uses: actions/upload-artifact@v4 84 | with: 85 | name: coverage 86 | path: coverage 87 | 88 | - name: Upload data to codecov 89 | uses: codecov/codecov-action@v3 90 | env: 91 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 92 | 93 | lint: 94 | name: Code syntax 95 | runs-on: ubuntu-22.04 96 | 97 | steps: 98 | - uses: actions/checkout@v4 99 | with: 100 | fetch-depth: 0 101 | - name: Fix Checkout 102 | run: | 103 | git fetch --force --tags 104 | 105 | 106 | - name: Make the makefiles 107 | run: | 108 | ./autogen.sh 109 | ./configure 110 | 111 | - name: Install essential 112 | run: | 113 | sudo apt update 114 | make build-dep 115 | 116 | - name: Run the lint tools 117 | run: | 118 | make lint 119 | -------------------------------------------------------------------------------- /.github/workflows/quick_windows.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Quick Tests (Windows) 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | pull_request: 7 | workflow_dispatch: 8 | 9 | jobs: 10 | smoketest: 11 | name: Smoke test 12 | runs-on: windows-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | - name: Fix Checkout 19 | run: | 20 | git fetch --force --tags 21 | 22 | - name: Run minimal test set 23 | run: | 24 | export CFLAGS="-fprofile-arcs -ftest-coverage" 25 | export LDFLAGS="--coverage" 26 | ./scripts/hack_fakeautoconf.sh 27 | make -k -j4 28 | make test.builtin test.units 29 | shell: bash 30 | 31 | - if: ${{ failure() }} 32 | name: Upload tests output 33 | uses: actions/upload-artifact@v4 34 | with: 35 | name: tests-smoketest-windows 36 | path: tests 37 | -------------------------------------------------------------------------------- /.github/workflows/slow_openwrt.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Slow full Openwrt Build 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | push: 7 | branches: 8 | - openwrt 9 | 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | name: Build ipkg 15 | runs-on: ubuntu-latest 16 | 17 | defaults: 18 | run: 19 | working-directory: openwrt 20 | 21 | steps: 22 | - name: Checkout openwrt 23 | uses: actions/checkout@v4 24 | with: 25 | path: openwrt 26 | repository: openwrt/openwrt 27 | 28 | - name: Set openwrt ref 29 | run: | 30 | echo "OPENWRT_REF=$(git rev-parse --short HEAD)" >> $GITHUB_ENV 31 | git rev-parse --short HEAD 32 | 33 | - name: Checkout 34 | uses: actions/checkout@v2 35 | with: 36 | path: src 37 | fetch-depth: 0 38 | 39 | - name: Fix Checkout 40 | run: | 41 | git fetch --force --tags 42 | working-directory: src 43 | 44 | - name: Set ref 45 | run: | 46 | echo "N3N_REF=$(./scripts/version.sh)" >> $GITHUB_ENV 47 | ./scripts/version.sh 48 | working-directory: src 49 | 50 | - name: Copy src package definition into openwrt 51 | run: | 52 | cp -r src/packages/openwrt openwrt/package/n3n 53 | working-directory: ./ 54 | 55 | - name: Cache openwrt source downloads 56 | uses: actions/cache@v3 57 | with: 58 | path: openwrt/dl 59 | key: openwrt-dl-${{ env.OPENWRT_REF }} 60 | 61 | - name: Setup openwrt config and environment 62 | run: | 63 | echo "CONFIG_TARGET_x86=y" >.config 64 | echo "CONFIG_TARGET_x86_64=y" >>.config 65 | 66 | - name: Add package to openwrt config 67 | run: | 68 | echo "CONFIG_PACKAGE_n3n-edge=m" >>.config 69 | echo "CONFIG_PACKAGE_n3n-supernode=m" >>.config 70 | 71 | - name: Build a full config from our stub file 72 | run: | 73 | make defconfig 74 | 75 | - name: Download openwrt sources 76 | run: | 77 | make download 78 | 79 | - name: Build openwrt build environment 80 | run: | 81 | make -j `nproc` tools/install toolchain/install 82 | 83 | - name: Build dependancies 84 | run: | 85 | make -j `nproc` package/libs/libpcap/compile 86 | 87 | - name: Build openwrt packages 88 | env: 89 | PKG_VERSION: ${{ env.N3N_REF }} 90 | run: | 91 | echo "Build for $PKG_VERSION" 92 | export PKG_VERSION 93 | make package/n3n/clean V=s 94 | make package/n3n/prepare USE_SOURCE_DIR=$GITHUB_WORKSPACE/n3n V=s 95 | make package/n3n/compile V=s 96 | 97 | # FIXME: add a way to run the test suite! 98 | # - name: Run embedded tests 99 | # run: make test 100 | 101 | - name: Upload built artifacts 102 | uses: actions/upload-artifact@v2 103 | with: 104 | name: built-ipkgs 105 | path: openwrt/bin/packages/*/base/*.ipk 106 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | *.a 4 | *.gz 5 | *.exe 6 | 7 | # Files created by autogen 8 | configure 9 | include/config.h.in 10 | scripts/config.guess 11 | scripts/config.sub 12 | 13 | # Files created by configure 14 | config.log 15 | config.mak 16 | config.rpath 17 | config.status 18 | include/config.h 19 | autom4te.cache 20 | 21 | *dSYM* 22 | 23 | __pycache__ 24 | 25 | # Files generated while running tests 26 | tests/*.out 27 | 28 | # Files generated while running coverage reports 29 | *.gcno 30 | *.gcda 31 | *.gcov 32 | coverage/ 33 | 34 | # Files generated while running linting 35 | *.indent 36 | *.unc-backup.md5~ 37 | *.unc-backup~ 38 | 39 | # Empty files created by the openwrt build 40 | /.built 41 | /.built_check 42 | /.configured_* 43 | /.prepared 44 | /.quilt_checked 45 | /.source_dir 46 | /ABOUT-NLS 47 | /AUTHORS 48 | /ChangeLog 49 | /NEWS 50 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "thirdparty/miniupnp"] 2 | path = thirdparty/miniupnp 3 | url = https://github.com/miniupnp/miniupnp.git 4 | ignore = dirty 5 | [submodule "thirdparty/libnatpmp"] 6 | path = thirdparty/libnatpmp 7 | url = https://github.com/miniupnp/libnatpmp.git 8 | ignore = dirty 9 | -------------------------------------------------------------------------------- /.yamllint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | rules: 5 | # 80 chars should be enough, but don't fail if a line is longer 6 | line-length: 7 | max: 80 8 | level: warning 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # n3n 3 | 4 | n3n is a lightweight Peer-to-Peer VPN that creates virtual networks. 5 | 6 | In order to start using n3n, two elements are required: 7 | 8 | - A _supernode_: it allows edge nodes to announce and discover other nodes. It 9 | must have a port publicly accessible on internet. 10 | - _edge_ nodes: the nodes which will be a part of the virtual networks 11 | 12 | A virtual network shared between multiple edge nodes in n3n is called a 13 | _community_. A single supernode can relay multiple communities and a single 14 | computer can be part of multiple communities at the same time (by running 15 | multiple _edge_ daemons). An encryption key can be used by the edge nodes to 16 | encrypt the packets within their community. 17 | 18 | n3n tries to establish a direct peer-to-peer connection via udp between the 19 | edge nodes when possible. When this is not possible (usually due to special NAT 20 | devices), the supernode is also used to relay the packets. 21 | 22 | n3n was originally based on an older n2n project and hopes to keep protocol 23 | compatiblilty with that. 24 | 25 | Note that some distributions have very old versions of n2n packaged that are 26 | incompatible with the protocol used by n3n. At the least, Debian has a n2n 27 | version 1.3.1 which uses a protocol from 2008 and has not been compatible with 28 | the stable releases of n2n for many years - thus will definitely not 29 | interoperate with n3n) 30 | 31 | ## License 32 | 33 | - Any new self-contained tools or modules are licensed GPL-2.0-only. 34 | - Existing code is licensed GPL-3-only. 35 | - There are multiple distinct copyright holders throughout the codebase. 36 | - There is no Contributor Licence Agreement and thus there is no single body 37 | that can take ownership of the code and/or change the licensing. 38 | 39 | ## Quick Start 40 | 41 | For Debian, Ubuntu or similar dpkg based systems: 42 | 43 | - Download the package from the [latest stable release](https://github.com/n42n/n3n/releases/latest). 44 | 45 | - Install the package 46 | 47 | - Create a config file - `/etc/n3n/mynetwork.conf` containing 48 | ``` 49 | [community] 50 | name=mynetwork 51 | key=mypassword 52 | supernode=supernode.ntop.org:7777 53 | ``` 54 | 55 | - Start the service: `sudo systemctl start n3n-edge@mynetwork` 56 | 57 | - Check the connection: `sudo n3nctl -s mynetwork supernodes` 58 | 59 | - List other nodes found: `sudo n3nctl -s mynetwork edges` 60 | 61 | **IMPORTANT:** It is strongly advised to choose a custom community name (the 62 | `community.name` option) and a secret encryption key (the `community.key` 63 | option) in order to prevent other users from connecting to your computer. 64 | 65 | It is also suggested that you setup your own [supernode](doc/Supernode.md) 66 | 67 | # See Also 68 | 69 | - [Build from Source](doc/Building.md) document. 70 | - [Security Considerations](doc/Security.md) document. 71 | - [Advanced Configuration](doc/Advanced.md) document. 72 | - Answers to [frequently asked questions](doc/Faq.md) (FAQ). 73 | - Details about the internals in the [Hacking guide](doc/Hacking.md). 74 | 75 | ## Contribution 76 | 77 | You can contribute to n3n in various ways: 78 | 79 | - Update an [open issue](https://github.com/n42n/n3n/issues) or create a new 80 | one with detailed information 81 | - Propose new features 82 | - Improve the documentation 83 | - Provide pull requests with enhancements 84 | 85 | 86 | --- 87 | 88 | (C) 2007-22 - ntop.org and contributors 89 | Copyright (C) 2023-25 Hamish Coleman 90 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 3.4.4 2 | -------------------------------------------------------------------------------- /apps/.gitignore: -------------------------------------------------------------------------------- 1 | # Main apps 2 | n3n-edge 3 | n3n-supernode 4 | n3n-edge.exe 5 | n3n-supernode.exe 6 | 7 | # Examples 8 | example_edge_embed_quick_edge_init 9 | example_edge_embed 10 | example_sn_embed 11 | example_edge_embed_quick_edge_init.exe 12 | example_edge_embed.exe 13 | example_sn_embed.exe 14 | -------------------------------------------------------------------------------- /apps/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) Hamish Coleman 3 | # 4 | # This makefile shows how to build applications using the libn3n library. 5 | # 6 | # The examples programs are intended to show how to use the libn3n as an 7 | # embedded service within other software. 8 | # 9 | 10 | # If using this makefile outside of the n3n build environment, you will 11 | # need to setup the correct include paths. 12 | # 13 | # eg: 14 | # CFLAGS+=-I../include 15 | # LDFLAGS+=-L../src 16 | # 17 | # CFLAGS+=-I../libs 18 | # LDFLAGS+=-L../libs/connslot 19 | # LDLIBS_LOCAL+=-lconnslot 20 | 21 | APPS+=n3n-edge 22 | APPS+=n3n-supernode 23 | 24 | EXAMPLES+=example_edge_embed_quick_edge_init 25 | EXAMPLES+=example_edge_embed 26 | EXAMPLES+=example_sn_embed 27 | 28 | LDLIBS+=-ln3n 29 | LDLIBS+=$(LDLIBS_LOCAL) 30 | LDLIBS+=$(LDLIBS_EXTRA) 31 | 32 | all: $(APPS) 33 | 34 | examples: $(EXAMPLES) 35 | 36 | # TODO: a better path for this lib, as it would need to change to use this 37 | # makefile outside the build environment 38 | $(APPS) $(EXAMPLES): ../src/libn3n.a 39 | 40 | .PHONY: install 41 | install: $(addsuffix $(EXE),$(APPS)) 42 | $(INSTALL) -d $(CONFIG_SBINDIR) 43 | $(INSTALL_PROG) n3n-supernode$(EXE) $(CONFIG_SBINDIR)/ 44 | $(INSTALL_PROG) n3n-edge$(EXE) $(CONFIG_SBINDIR)/ 45 | 46 | %: %.c 47 | @echo " CC $@" 48 | @$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ 49 | 50 | # See comments in the topdir Makefile about how to generate coverage data. 51 | # TODO: why are these apps detected with strange names by coverage? 52 | gcov: 53 | gcov n3n-edge-n3n-edge n3n-supernode-n3n-supernode 54 | 55 | clean: 56 | rm -f $(APPS) $(EXAMPLES) 57 | -------------------------------------------------------------------------------- /apps/example_edge_embed_quick_edge_init.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-2025 Hamish Coleman 4 | * SPDX-License-Identifier: GPL-3.0-only 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not see see 18 | * 19 | */ 20 | 21 | 22 | #include // for n3n_initfuncs 23 | #include // for setTraceLevel 24 | #include 25 | #include "n2n.h" // for quick_edge_init 26 | 27 | 28 | /* 29 | This tool demonstrates how to easily embed 30 | n2n on an existing application 31 | */ 32 | 33 | int main (int argc, char* argv[]) { 34 | 35 | char *device_name = (char*)"n3n0"; 36 | char *network_name = (char*)"mynetwork"; 37 | char *secret_key = (char*)"mysecret"; 38 | char *my_mac_address = (char*)"DE:AD:BE:EF:01:10"; 39 | in_addr_t my_ipv4_addr = 0x01020304; // 1.2.3.4 40 | char *supernode = (char*)"7.8.9.10:1234"; 41 | bool keep_on_running = true; 42 | 43 | // Do this early to register all internals 44 | n3n_initfuncs(); 45 | 46 | /* Increase tracelevel to see what's happening */ 47 | setTraceLevel(10); 48 | 49 | /* 50 | NOTE 51 | 52 | As the function below won't end, you should 53 | call it inside a separate thread 54 | */ 55 | return(quick_edge_init(device_name, 56 | network_name, 57 | secret_key, 58 | my_mac_address, 59 | my_ipv4_addr, 60 | supernode, 61 | &keep_on_running)); 62 | } 63 | -------------------------------------------------------------------------------- /apps/example_sn_embed.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-25 Hamish Coleman 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not see see 17 | * 18 | */ 19 | 20 | 21 | #include // for n3n_initfuncs() 22 | #include // for sn_init_conf_defaults 23 | #include 24 | #include // for exit 25 | #include "n2n.h" // for n2n_edge, open_socket, run_sn_loop, sn_init 26 | 27 | #ifdef _WIN32 28 | #include 29 | #else 30 | #include // for INADDR_ANY, INADDR_LOOPBACK 31 | #endif 32 | 33 | 34 | static bool keep_running = true; 35 | 36 | int main () { 37 | 38 | struct n3n_runtime_data sss_node; 39 | int rc; 40 | struct sockaddr_in local_address; 41 | 42 | // Do this early to register all internals 43 | n3n_initfuncs(); 44 | 45 | sn_init_conf_defaults(&sss_node,"supernode"); 46 | int lport = 1234; // Main UDP listen port 47 | 48 | memset(&local_address, 0, sizeof(local_address)); 49 | local_address.sin_family = AF_INET; 50 | local_address.sin_port = htons(lport); 51 | local_address.sin_addr.s_addr = htonl(INADDR_ANY); 52 | 53 | sss_node.sock = open_socket( 54 | (struct sockaddr *)&local_address, 55 | sizeof(local_address), 56 | 0 /* UDP */ 57 | ); 58 | if(-1 == sss_node.sock) { 59 | exit(-2); 60 | } 61 | 62 | memset(&local_address, 0, sizeof(local_address)); 63 | local_address.sin_family = AF_INET; 64 | local_address.sin_port = htons(5645); 65 | local_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 66 | 67 | // Could also initialise the management api and its socket 68 | 69 | sn_init(&sss_node); 70 | 71 | sss_node.keep_running = &keep_running; 72 | rc = run_sn_loop(&sss_node); 73 | 74 | sn_term(&sss_node); 75 | 76 | return rc; 77 | } 78 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -f include/config.h include/config.h.in include/config.h.in~ config.mak configure 4 | 5 | # The more I use autotools, the more I want to stop using autotools 6 | cp -p scripts/config.sub.DIST scripts/config.sub 7 | cp -p scripts/config.guess.DIST scripts/config.guess 8 | 9 | echo "Wait please..." 10 | autoreconf -if 11 | -------------------------------------------------------------------------------- /config.mak.in: -------------------------------------------------------------------------------- 1 | # Global configuration, included in top Makefile and exported from there. 2 | # 3 | # @configure_command@ 4 | 5 | 6 | CONFIG_HOST=@host@ 7 | CONFIG_HOST_OS=@host_os@ 8 | 9 | CONFIG_PREFIX=@CONFIG_PREFIX@ 10 | CONFIG_DOCDIR=$(DESTDIR)@CONFIG_DOCDIR@ 11 | CONFIG_MANDIR=$(DESTDIR)@CONFIG_MANDIR@ 12 | CONFIG_RUNDIR=$(DESTDIR)@CONFIG_RUNDIR@ 13 | CONFIG_SYSTEMDDIR=$(DESTDIR)@CONFIG_SYSTEMDDIR@ 14 | 15 | CONFIG_WITH_OPENSSL=@with_openssl@ 16 | 17 | CC=@CC@ 18 | AR=@AR@ 19 | WINDRES=@WINDRES@ 20 | EXE=@EXE@ 21 | 22 | CFLAGS+=@CFLAGS@ 23 | LDFLAGS+=@LDFLAGS@ 24 | LDLIBS_EXTRA+=@LIBS@ 25 | -------------------------------------------------------------------------------- /debian/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Files generated during the dpkg build process 3 | .debhelper/ 4 | autoreconf.after 5 | autoreconf.before 6 | changelog 7 | debhelper-build-stamp 8 | files 9 | n3n.debhelper.log 10 | n3n.postinst.debhelper 11 | n3n.postrm.debhelper 12 | n3n.prerm.debhelper 13 | n3n.substvars 14 | n3n/ 15 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: n3n 2 | Section: net 3 | Priority: optional 4 | Maintainer: Hamish Coleman 5 | Standards-Version: 4.6.0 6 | Build-Depends: 7 | autoconf, 8 | debhelper, 9 | debhelper-compat (= 10), 10 | devscripts, 11 | dh-python, 12 | flake8, 13 | gcovr, 14 | jq, 15 | libcap-dev, 16 | libzstd-dev, 17 | python3, 18 | shellcheck, 19 | uncrustify, 20 | yamllint, 21 | 22 | Package: n3n 23 | Architecture: any 24 | Depends: 25 | ${misc:Depends}, 26 | ${python3:Depends}, 27 | ${shlibs:Depends}, 28 | Conflicts: n2n 29 | Description: Peer-to-Peer and Layer-2 VPN network daemon 30 | n3n is a layer-two peer-to-peer virtual private network (VPN) which allows 31 | users to exploit features typical of P2P applications at network instead of 32 | application level. This means that users can gain native IP visibility (e.g. 33 | two PCs belonging to the same n3n network can ping each other) and be 34 | reachable with the same network IP address regardless of the network where 35 | they currently belong. In a nutshell, as OpenVPN moved SSL from application 36 | (e.g. used to implement the https protocol) to network protocol, n3n moves 37 | P2P from application to network level. 38 | . 39 | Edge is the edge node daemon for n3n which creates a TAP interface to expose 40 | the n3n virtual LAN. 41 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: n3n 3 | Comment: This is probably not an exhaustive list of the GPL-2.0-only files, 4 | since the project is going through licensing changes and new works are 5 | being licensed with GPL-2.0-only where compatible with the project. 6 | 7 | Files: 8 | apps/* 9 | src/* 10 | License: GPL-3.0-only 11 | A copy of the GNU General Public License version 3 is available as 12 | LICENSES/preferred/GPL-3.0 in the source of this package or at 13 | https://www.gnu.org/licenses/gpl-3.0-standalone.html 14 | 15 | Files: LICENSES/preferred/GPL-2.0 16 | Copyright: Copyright (C) 1989, 1991 Free Software Foundation, Inc. 17 | 18 | Files: LICENSES/preferred/GPL-3.0 19 | Copyright: Copyright (C) 2007 Free Software Foundation, Inc. 20 | 21 | Files: LICENSES/preferred/LGPL-2.1 22 | Copyright: Copyright (C) 1991, 1999 Free Software Foundation, Inc. 23 | 24 | Files: 25 | libs/connslot/* 26 | Copyright: Hamish Coleman 27 | License: LGPL-2.1-only 28 | A copy of the GNU Lesser General Public License version 2.1 is available as 29 | LICENSES/preferred/LGPL-2.1 in the source of this package or at 30 | https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html or in the Debian 31 | distribution at /usr/share/common-licenses/LGPL-2.1 32 | 33 | Files: 34 | apps/Makefile 35 | debian/* 36 | scripts/munin/n3n_ 37 | scripts/n3nctl 38 | tests/* 39 | tools/Makefile 40 | uncrustify.cfg 41 | Copyright: Hamish Coleman 42 | License: GPL-2.0-only 43 | A copy of the GNU General Public License version 2 is available as 44 | LICENSES/preferred/GPL-2.0 in the source of this package or at 45 | https://www.gnu.org/licenses/old-licenses/gpl-2.0.html 46 | 47 | Files: 48 | src/hexdump.c 49 | src/initfuncs.c 50 | src/management.c 51 | src/management_index.html 52 | src/management_script.js 53 | src/metrics.c 54 | src/transform.c 55 | tools/tests-auth.c 56 | tools/tests-compress.c 57 | tools/tests-elliptic.c 58 | tools/tests-transform.c 59 | tools/tests-wire.c 60 | Copyright: Hamish Coleman 61 | License: GPL-3.0-only 62 | A copy of the GNU General Public License version 3 is available as 63 | LICENSES/preferred/GPL-3.0 in the source of this package or at 64 | https://www.gnu.org/licenses/gpl-3.0-standalone.html 65 | -------------------------------------------------------------------------------- /debian/n3n.lintian-overrides: -------------------------------------------------------------------------------- 1 | # The systemd debhelpers dont actually support actions on templated unit files 2 | # and we want to ensure our daemons are restarted after an upgrade, so we need 3 | # manually call out to systemctl 4 | n3n: maintainer-script-calls-systemctl 5 | -------------------------------------------------------------------------------- /debian/n3n.postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | if [ "$1" = "configure" ]; then 4 | umask 022 5 | 6 | # ensure we have our expected group and user 7 | if [ -z "$(id -g n3n 2> /dev/null)" ]; then 8 | groupadd --system n3n 9 | fi 10 | 11 | if [ -z "$(id -u n3n 2> /dev/null)" ]; then 12 | useradd \ 13 | --no-create-home \ 14 | --no-user-group \ 15 | --gid n3n \ 16 | --system \ 17 | --shell /bin/true \ 18 | n3n 19 | fi 20 | fi 21 | 22 | #DEBHELPER# 23 | 24 | if [ "$1" = "configure" ]; then 25 | # dont try and restart the services until after the debhelper - it will 26 | # take care of doing a daemon-reload if it thinks that is needed 27 | 28 | # TODO: It would be nice if the dh_systemd_start handled templated services 29 | if [ -z "${DPKG_ROOT:-}" ] && [ -d /run/systemd/system ]; then 30 | if systemctl is-active --quiet 'n3n-edge@*.service'; then 31 | systemctl try-restart 'n3n-edge@*.service' 32 | fi 33 | fi 34 | fi 35 | 36 | exit 0 37 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | # Uncomment this to turn on verbose mode. 4 | #export DH_VERBOSE=1 5 | 6 | %: 7 | dh ${@} --with=python3 8 | 9 | # Since we cross-compile for multiple architectures, we cannot automatically 10 | # run the tests. We also still need root to run the tests. 11 | # Skip the tests.. 12 | override_dh_auto_test: 13 | 14 | # If we split into a separate supernode package, then the supernode could 15 | # probably be automatically enabled. However, the edge needs configuration 16 | # before it can be started. TODO: add config templating and allow autostart 17 | # in that case 18 | override_dh_systemd_enable: 19 | dh_systemd_enable --no-enable 20 | override_dh_systemd_start: 21 | dh_systemd_start --no-start 22 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 1.0 2 | -------------------------------------------------------------------------------- /doc/Advanced.md: -------------------------------------------------------------------------------- 1 | # Advanced Configuration 2 | 3 | This document describes information about communities, support for multiple 4 | supernodes, routing, traffic restrictions and how to run an edge as a service. 5 | 6 | ## Configuration Files 7 | 8 | Read about [Configuration Files](ConfigurationFiles.md) as they might come in handy – especially, but not limited to, if edges or supernodes shall be run as a service (see below) or in case of bulk automated parameter generation for mass deployment. 9 | 10 | ## Running edge as a Service 11 | 12 | edge can also be run as a service instead of cli: 13 | 14 | 1. Edit `/etc/n3n/edge.conf` with your custom options. See [a sample](edge.conf.sample). 15 | 2. Start the service: `sudo systemctl start n3n-edge` 16 | 3. Optionally enable edge start on boot: `sudo systemctl enable n3n-edge` 17 | 18 | You can run multiple edge service instances by creating `/etc/n3n/instance1.conf` and 19 | starting it with `sudo systemctl start n3n-edge@instance1`. 20 | 21 | 22 | ## Communities 23 | 24 | You might be interested to learn some [details about Communities](Communities.md) and understand how to limit supernodes' services to only a specified set of communities. 25 | 26 | 27 | ## Federation 28 | 29 | It is available a special community which provides interconnection between supernodes. Details about how it works and how you can use it are available in [Federation](Federation.md). 30 | 31 | ## Virtual Network Device Configuration 32 | 33 | The [TAP Configuration Guide](TapConfiguration.md) contains hints on various settings that can be applied to the virtual network device, including IPv6 addresses as well as notes on MTU and on how to draw IP addresses from DHCP servers. 34 | 35 | 36 | ## Bridging and Routing the Traffic 37 | 38 | Reaching a remote network or tunneling all the internet traffic via n3n are two common tasks which require a proper routing setup. n3n supports routing needs by temporarily modifying the routing table (`tools/n3n-route`). Details can be found in the [Routing document](Routing.md). 39 | 40 | Also, n3n supports [Bridging](Bridging.md) of LANs, e.g. to connect otherwise un-connected LANs by an encrypted n3n tunnel on level 2. 41 | 42 | 43 | ## Traffic Restrictions 44 | 45 | It is possible to drop or accept specific packet transmit over edge network 46 | interface by rules. Rules can be specified in the config with the `filter.rule` 47 | option - multiple times if needed. Details can be found in the [Traffic 48 | Restrictions](TrafficRestrictions.md). 49 | -------------------------------------------------------------------------------- /doc/Bridging.md: -------------------------------------------------------------------------------- 1 | # Bridging (Linux) 2 | 3 | ## General Remarks 4 | 5 | `edge`s can be part of network bridges. As such, n3n can connect otherwise un-connected LANs. 6 | 7 | ## How To Use with `brctl` 8 | 9 | ... requires `-r` 10 | ... general syntax 11 | ... one example connecting two remote sites' LANs, including commands 12 | 13 | ## How it works 14 | 15 | ... remembers peer info MAC 16 | ... ageing 17 | ... internal MAC replaced inside usually encrypted packet data (no disclosure then) 18 | ... initial learning 19 | 20 | ## Broadcasts 21 | 22 | ... note on broadcast domain 23 | 24 | ## Compile Time Option 25 | 26 | The `-r`option at edge does not differentiate between the use cases _routing_ and _bridging_. In case the MAC-learning and MAC-replacing bridging code 27 | interfers with some special routing scenario, removal of the `-DHAVE_BRIDGING_SUPPORT` from `Makefile` file disables it at compile time. 28 | -------------------------------------------------------------------------------- /doc/ConfigurationFiles.md: -------------------------------------------------------------------------------- 1 | # Configuration Files 2 | 3 | To help deployment and better handle locally different configurations, n3n 4 | supports the use of configuration files for `n3n-edge` and `n3n-supernode`. 5 | 6 | The daemon will attempt to locate a configuration file based on the 7 | "sessionname" - which defaults to "edge" for the edge daemon. This would 8 | result in a config file called "edge.conf", which is located in "/etc/n3n" (or 9 | the %USERPROFILE%\n3n directory on Windows) 10 | 11 | They are plain text files formatted very similar to INI files. 12 | 13 | To generate the help documentation for all current options: 14 | ```bash 15 | n3n-edge help config 16 | ``` 17 | 18 | If you created the following `/etc/n3n/testing.conf` file: 19 | 20 | ``` 21 | [community] 22 | cipher = Speck 23 | key = mysecretpass 24 | name = mynetwork 25 | supernode = supernode.ntop.org:7777 26 | 27 | [daemon] 28 | background = false 29 | 30 | [tuntap] 31 | address = 192.168.100.1 32 | address_mode = static 33 | ``` 34 | 35 | which can be loaded by 36 | 37 | ``` 38 | sudo ./n3n-edge start testing 39 | ``` 40 | 41 | If needed, the settings from the config file can all be overridden using a 42 | command line parameter: 43 | 44 | If required, additional command line parameters can also be supplied: 45 | 46 | ``` 47 | sudo n3n-edge start testing \ 48 | -Oconnection.description=myComputer \ 49 | -O community.compression=lzo 50 | ``` 51 | 52 | Some of the most common options also have a shortcut version, you can see all 53 | these with: 54 | 55 | ``` 56 | n3n-edge help options 57 | ``` 58 | -------------------------------------------------------------------------------- /doc/Containerfile.example: -------------------------------------------------------------------------------- 1 | # 2 | # A simple example of how to build a docker container for n3n-edge 3 | # 4 | # Build with the command: 5 | # podman build \ 6 | # --device=/dev/net/tun \ 7 | # --cap-add=NET_ADMIN \ 8 | # -t=n3n \ 9 | # -f doc/Containerfile.example \ 10 | # . 11 | # 12 | # Note that podman must be run in rootful mode for the build tests to pass. 13 | # To build in rootless mode: 14 | # podman build \ 15 | # --build-arg SKIP_TESTS=1 \ 16 | # -t=n3n \ 17 | # -f doc/Containerfile.example \ 18 | # . 19 | # 20 | # Start a n3n session with: 21 | # podman run \ 22 | # --rm \ 23 | # -it \ 24 | # --name=n3n \ 25 | # --device=/dev/net/tun \ 26 | # --cap-add=NET_ADMIN \ 27 | # -v "$PWD"/n3n:/etc/n3n/ \ 28 | # n3n start -vvvv 29 | # 30 | # Start an n3n supernode with the following, where 1234 is the port 31 | # configured in your supernode config file: 32 | # podman run 33 | # --rm \ 34 | # -it \ 35 | # --name=n3n-supernode \ 36 | # -p1234:1234/udp \ 37 | # --device=/dev/net/tun \ 38 | # --cap-add=NET_ADMIN \ 39 | # -v "$PWD"/n3n:/etc/n3n/ \ 40 | # --entrypoint=/n3n-supernode \ 41 | # n3n start -vvvv 42 | 43 | FROM docker.io/library/debian:12 AS builder 44 | 45 | RUN apt-get update 46 | RUN apt-get install -y build-essential autoconf git python3 jq sudo 47 | 48 | WORKDIR /n3n 49 | 50 | COPY . . 51 | 52 | RUN \ 53 | ./autogen.sh && \ 54 | ./configure && \ 55 | make clean all 56 | 57 | ARG SKIP_TESTS=0 58 | 59 | RUN if [ 0 -eq "$SKIP_TESTS" ]; then make test; fi 60 | 61 | 62 | FROM docker.io/library/debian:12 63 | 64 | COPY --from=builder /n3n/apps/n3n-edge /n3n-edge 65 | COPY --from=builder /n3n/apps/n3n-supernode /n3n-supernode 66 | 67 | VOLUME [ "/etc/n3n" ] 68 | ENTRYPOINT ["/n3n-edge"] 69 | CMD ["start"] 70 | -------------------------------------------------------------------------------- /doc/EdgeOS-notes.txt: -------------------------------------------------------------------------------- 1 | 2 | EdgeOS 3 | ------ 4 | We need to replace BusyBox-implemented commands using full-fledged commands by doing 5 | (see http://community.ubnt.com/t5/EdgeMAX/ubnt-debian-package-conflict/m-p/421325) 6 | 7 | curl -O http://ftp.us.debian.org/debian/pool/main/c/coreutils/coreutils_8.5-1_mips.deb 8 | dpkg -i --force-all coreutils_8.5-1_mips.deb 9 | 10 | curl -O http://ftp.us.debian.org/debian/pool/main/t/tar/tar_1.23-3_mips.deb 11 | dpkg -i --force-all tar_1.23-3_mips.deb 12 | 13 | wget http://ftp.us.debian.org/debian/pool/main/f/findutils/findutils_4.4.2-4_mips.deb 14 | dpkg -i --force-all findutils_4.4.2-4_mips.deb 15 | 16 | wget http://ftp.us.debian.org/debian/pool/main/g/gzip/gzip_1.5-1.1_mips.deb 17 | dpkg -i --force-all gzip_1.5-1.1_mips.deb 18 | 19 | -------------------------------------------------------------------------------- /doc/Federation.md: -------------------------------------------------------------------------------- 1 | # Supernode Federation 2 | 3 | ## Idea 4 | To enhance resilience in terms of backup and fail-over, also for load-balancing, multiple supernodes can easily interconnect and form a special community, called **federation**. 5 | 6 | 7 | ## Using Multiple Supernodes 8 | 9 | ### Form a Federation 10 | 11 | To form a federation, multiple supernodes need to be aware of each other. To 12 | get them connected, an additional `supernode.peer` option is required at 13 | the supernode. 14 | 15 | This option takes the IP address (or name) and the UDP port of another known 16 | supernode, e.g. `192.168.1.1:1234`. As the number of federated supernodes 17 | increases, it gets more convenient to use a config file for this option. 18 | 19 | ### Use a Federation 20 | 21 | Federated supernodes take care of propagating their knowledge about other supernodes to all other supernodes and the edges. 22 | 23 | So, in the first place, edges only need to connect to one supernode (called 24 | anchor supernode) using `community.supernode` option. This supernode needs to 25 | be present at start-up. 26 | 27 | Optionally, more anchor supernodes of the same federation can be provided to an 28 | edge using several `community.supernode` options. This will counter scenarios 29 | with reduced assured initial supernode availability. 30 | 31 | ## How It Works 32 | 33 | Supernodes should be able to communicate among each other as regular edges already do. For this purpose, a special community called federation was introduced. The federation feature provides some mechanisms to inter-connect the supernodes of the network enhancing backup, fail-over and load-sharing, without any visible behavioral change. 34 | 35 | The default name for the federation is `Federation`. Internally, a mandatory 36 | special character is prepended to the name (`*`) that way, there is no way for 37 | a regular community with the same name as the federation to conflict. 38 | Optionally, a user can choose a federation name (same on all supernodes) and 39 | provide it via the `supernode.federation` option to the supernode. Finally, 40 | the federation name can be passed through the environment variable 41 | `N3N_FEDERATION`. 42 | 43 | Federated supernodes register to each other using REGISTER_SUPER message type. The answer, REGISTER_SUPER_ACK, contains a payload with information about other supernodes in the network. 44 | 45 | This specific mechanism is also used during the registration process taking place between edges and supernodes, so edges are able to learn about other supernodes. 46 | 47 | Once edges have received this information, it is up to them choosing the supernode they want to connect to. Each edge pings supernodes from time to time and receives information about them inside the answer. We decided to implement a work-load based selection strategy because it is more in line with the idea of keeping the workload low on supernodes. Moreover, this way, the entire network load is evenly distributed among all available supernodes. 48 | 49 | An edge connects to the supernode with the lowest work-load and it is re-considered from time to time, with each re-registration. We use a stickyness factor to avoid too much jumping between supernodes. 50 | 51 | Thanks to this feature, n3n is now able to handle security attacks such as DoS against supernodes and it can redistribute the entire load of the network in a fair manner between all the supernodes. 52 | 53 | To serve scenarios in which an edge is supposed to select the supernode by 54 | round trip time, i.e. choosing the "closest" one, the 55 | `connection.supernode_selection=rtt` config option is available at the edge. 56 | Note, that workload distribution among supernodes might not be so fair then. 57 | 58 | Furthermore, `connection.supernode_selection=mac` would switch to a MAC address 59 | based selection strategy choosing the supernode active with the lowest MAC 60 | address. 61 | -------------------------------------------------------------------------------- /doc/INSTALL: -------------------------------------------------------------------------------- 1 | INSTALL 2 | 3 | To build the programs: 4 | 5 | $ ./autogen.sh 6 | $ ./configure 7 | $ make 8 | 9 | To install the programs and man pages: 10 | 11 | $ make install 12 | 13 | or 14 | 15 | $ make CONFIG_PREFIX=/usr install 16 | 17 | Debian Package 18 | -------------- 19 | 20 | 1. ./autogen.sh 21 | 2. ./configure 22 | 3. make dpkg 23 | 24 | RPM Package 25 | ----------- 26 | 27 | These steps should work with RPM based Linux distributions since rpmbuild was 28 | split from the rpm utility (c RedHat 9). 29 | 30 | 1. cd packages/rpm/ 31 | 2. make 32 | -------------------------------------------------------------------------------- /doc/ReleaseProcess.md: -------------------------------------------------------------------------------- 1 | # Release Process 2 | 3 | ## Regular release process 4 | First, ensure that all the changes to be included in the release have been 5 | committed and merged in to the main branch of the public repository. 6 | 7 | Next, locally: 8 | - edit `VERSION` file to new version, e.g. `4.0.1` 9 | - `git add VERSION` 10 | - `git commit -m "Bump version file"` 11 | - `git tag -a 4.0.1 # Add the changelog while creating the tag` 12 | - `git push --tags` 13 | 14 | Then, on github: 15 | - Wait for CI jobs to run and turn green 16 | - Create new release from the new tag 17 | - Paste in the same changelog as used in the tag 18 | - Automated CI jobs should start 19 | - Once CI is green, the assets will be automatically added to the release 20 | 21 | ### TODO - improving the process 22 | 23 | - The changelog is added in two places. This is not the intent of the 24 | automation, but github might have changed something 25 | - The CI was intended to automatically run when the tag is uploaded and then 26 | automatically create the github release. The github triggers are not 27 | working for that case and should be investigated/fixed 28 | 29 | After the above TODO items are addressed, the process could be as simple as 30 | create the annotated tag, push the tag, wait for the CI to run. 31 | 32 | ## Notes on the VERSION file 33 | 34 | The VERSION file is intended to provide a version number of last resort when 35 | a non git checkout is being used. The build process will warn if the official 36 | git describe version number does not match the one found in the VERSION file. 37 | This will not stop the build, but it should be fixed to allow correctly 38 | building from a .tar.gz download. The release process above includes steps for 39 | that update. 40 | 41 | This being said, the use of a non git checkout should be discouraged. Thus, 42 | there is still a question as to if this feature should be retained. 43 | 44 | ## Stable patch release notes 45 | 46 | - Semver 47 | - Any release is supposed to be a 0 patchlevel release (eg: 4.1.0) - though any 48 | issues found during the release process may cause a higher patchlevel to 49 | be used for the release 50 | - New features or code can immediately start being committed to the main 51 | branch after a release. (Any dev code compiled after this will have a 52 | version number like 4.1.0-n-gZZZZ, clearly marking it as part of a non 53 | release. 54 | - If a bug is found after significant dev work has been committed, but the 55 | bugfix should be backported to a previous release, a release branch is 56 | created (eg: "n3n-4.1.y") the bugfix is committed in that branch and the 57 | release process with an incremented patchlevel will be done from that branch. 58 | -------------------------------------------------------------------------------- /doc/Scratchpad.md: -------------------------------------------------------------------------------- 1 | # n3n's Scratchpad 2 | 3 | 4 | ## Draft changelog between 3.0 and 3.2 (as of 2022) 5 | 6 | ### New Features 7 | 8 | - Enhanced management port JSON interface to let n3n interact with external tools 9 | - Added `n3n-route` tool (Linux only so far) 10 | - Introduced `n3n-portfwd` tool to support UPnP and PMP port forwarding 11 | - Furthered the build system 12 | 13 | ### Improvements 14 | 15 | - Fixed a federation related bug 16 | - Code clean-up 17 | -------------------------------------------------------------------------------- /doc/Scripts.md: -------------------------------------------------------------------------------- 1 | Copyright (C) Hamish Coleman 2 | SPDX-License-Identifier: GPL-3.0-only 3 | 4 | # Scripts 5 | 6 | There are a number of useful scripts included with the distribution. 7 | Some of these scripts are only useful during build and development, but 8 | other scripts are intended for end users to be able to use. These scripts 9 | may be installed with n3n as part of your operating system package. 10 | 11 | All scripts can be found in the `scripts` directory. 12 | 13 | Short descriptions of these scripts are below. 14 | 15 | ## End user scripts 16 | 17 | ### `n3nctl` 18 | 19 | This python script provides an easy command line interface to the running 20 | n3n processes. It uses the management API and if there is only one daemon 21 | running on the system, it will attempt to automatically locate it and talk 22 | to its Unix domain socket. it can talk to both the edge and the supernode 23 | daemons. 24 | 25 | Example: 26 | - `scripts/n3nctl --help` 27 | - `scripts/n3nctl help` 28 | 29 | ## Build and Development scripts 30 | 31 | ### `hack_fakeautoconf.sh` 32 | 33 | This shell script is used during development to help build on Windows 34 | systems. An example of how to use it is shown in 35 | the [Building document](Building.md) 36 | 37 | ### `indent.sh` 38 | 39 | This shell script is a wrapper for the `uncrustify` C code style checker 40 | which checks or applies a set of rules to the code. It is used during 41 | the automated lint checks. 42 | 43 | ### `n3n-gateway.sh` 44 | 45 | A sample script to route all the host traffic towards a remote gateway, 46 | which is reachable via the n3n virtual interface. 47 | 48 | ### `version.sh` 49 | 50 | This script is used to determine the current version number during the 51 | build process. 52 | 53 | It looks at both the VERSION file and the GIT tags and outputs the 54 | version number to use. 55 | 56 | ## Monitoring and statistics 57 | 58 | ### `munin/n3n_` 59 | 60 | This is a simple monitoring script that can be used with the munin-node 61 | system to monitor the n3n daemons. 62 | 63 | This is a fully autoconfigurable wildcard munin plugin, but to get a quick 64 | sample: 65 | 66 | get a list of suggested plugin names: 67 | ``` 68 | munin/n3n_ suggest 69 | ``` 70 | 71 | Enable some of those names: 72 | 73 | ``` 74 | ln -s /usr/share/munin/plugins/n3n_ /etc/munin/plugins/n3n_supernode_pkts 75 | ln -s /usr/share/munin/plugins/n3n_ /etc/munin/plugins/n3n_supernode_counts 76 | ``` 77 | 78 | Manually test fetching and config: 79 | 80 | ``` 81 | /etc/munin/plugins/n3n_supernode_pkts 82 | /etc/munin/plugins/n3n_supernode_pkts config 83 | ``` 84 | 85 | ## Testing scripts 86 | 87 | ### `test_harness.sh` 88 | 89 | This shell script is used to run automated tests during development. It is 90 | run with a testlist filename - pointing at a file containing the list of 91 | tests to run. 92 | 93 | Each test needs a file containing the expected output `${TESTNAME}.expected` 94 | which is expected to exist in the same directory as the testlist (this dir is 95 | referred to as `${listdir}` below). 96 | 97 | Each test is a program, searched for in several locations, including the 98 | `${listdir}/../scripts` dir. 99 | 100 | Each test is run with its output being sent to `*.out` files in the `listdir` 101 | and compared with the expected output. 102 | 103 | ### `scripts/test_integration_supernode.sh` 104 | 105 | This starts a supernode and runs an integration test on the Json API using 106 | the `n3nctl` command. 107 | -------------------------------------------------------------------------------- /doc/Security.md: -------------------------------------------------------------------------------- 1 | # Security Considerations 2 | 3 | When payload encryption is enabled (provide a key using `community.key`), the 4 | supernode will not be able to decrypt the traffic exchanged between two edge 5 | nodes but it will know that edge A is talking with edge B. 6 | 7 | There are multiple encryption options to choose from. Please have a look at 8 | [Crypto description](Crypto.md) for a quick comparison chart to help make a 9 | choice. n3n edge nodes use AES encryption by default. Other ciphers can be 10 | chosen using the `community.cipher` option. 11 | 12 | A benchmark of the encryption methods is available when compiled from source 13 | with `tools/n3n-benchmark`. 14 | 15 | The header which contains some metadata like the virtual MAC address of the 16 | edge nodes, their IP address, their real hostname and the community name 17 | optionally can be encrypted applying the `community.header_encryption=true` 18 | option to the edges. 19 | 20 | 21 | -------------------------------------------------------------------------------- /doc/Supernode.md: -------------------------------------------------------------------------------- 1 | # Setting up a Custom Supernode 2 | 3 | For the privacy of your data sent and to reduce the server load or reliance 4 | on `supernode.ntop.org`, it is also suggested to set up a custom supernode. 5 | 6 | You can create your own infrastructure by setting up a supernode on a public 7 | server (e.g. a VPS). You just need to open a single port (1234 in the example 8 | below) on your firewall (usually `iptables`). 9 | 10 | 1. Install the n3n package 11 | 2. Edit `/etc/n3n/supernode.conf` and add the following: 12 | ``` 13 | [connection] 14 | bind=1234 15 | ``` 16 | 3. Start the supernode service with `sudo systemctl start n3n-supernode` 17 | 4. Optionally enable supernode start on boot: `sudo systemctl enable n3n-supernode` 18 | 19 | Now the supernode service should be up and running on port 1234. On your edge 20 | nodes you can now specify `-l your_supernode_ip:1234` to use it. All the edge 21 | nodes must use the same supernode (or be part of the same 22 | [supernode federation](Federation.md)) 23 | -------------------------------------------------------------------------------- /doc/Tools.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | 3 | There are a number of handy tools coming with n3n extending fumction and 4 | user experience or just prove helpful during build and development. 5 | 6 | All tools can be found in the `tools` directory. 7 | 8 | ## End User Tools 9 | 10 | ### `n3n-benchmark` 11 | 12 | This C tool has n3n's basic transforms (the ciphers, compression, hash) 13 | crunch a test packet and outputs the measured throughput. You might observe 14 | differences depending on compiler optimizations or enabled hardware support, 15 | see [build configuration](BuildConfig.md). 16 | 17 | Example: 18 | - `tools/n3n-benchmark` 19 | 20 | ### `n3n-route` 21 | 22 | This C tool sets new routes for all the traffic to be routed via a VPN gateway 23 | (another edge) and polls the management port of a local n3n edge for adding 24 | appropriate routes to supernodes and peers via the original default gateway. 25 | 26 | The tool can auto-detect the default gateway and also has options to only route 27 | traffic to some specified networks through the VPN gateway. 28 | 29 | Make sure to run with sufficient rights to let the tool add and delete routes. 30 | 31 | More general information can be found in the [routing document](Routing.md) 32 | including hints how to setup the remote edge (IP routing, masquerading). 33 | 34 | Example: 35 | - `tools/n3n-route ` 36 | - `tools/n3n-route -n 10.10.10.0/24 ` 37 | - `tools/n3n-route -n 8.8.8.8/32:192.168.0.5 ` 38 | 39 | ### `n3n-portfwd` 40 | 41 | This C tool uses UPnP and/or PMP to have a local router forward the edge port. 42 | The program polls a local edge's management port and takes apporpriate action. 43 | 44 | Note that n3n needs to be compiled with the corresponding options enabled, e.g. 45 | 46 | ``` 47 | ./configure --enable-miniupnp --enable-natpmp 48 | ``` 49 | 50 | Also see [build configuration](BuildConfig.md). 51 | 52 | Example: 53 | - `tools/n3n-portfwd` 54 | 55 | 56 | ## Build and Development Tools 57 | 58 | ### `tests-*` 59 | 60 | These C programs run certain parts of n3n with pre-defined data and output 61 | the results. The expected results can be found in the `tests/` directory 62 | following the `tests-*.expected` naming scheme. 63 | 64 | The `test_*` [scripts](Scripts.md) residing inside the `scripts/` directory 65 | compare test output and expected results to quickly show deviations, helpful 66 | when on bug hunt. 67 | 68 | Example: 69 | - `tools/tests-transforms` 70 | 71 | ### `n3n-decode` 72 | 73 | This C tool intends to decrypt captured n3n traffic when all keys are provided. 74 | Its development unfortunately did not follow main n3n's pace after version 2.8 75 | and thus is not up to date. 76 | 77 | Contributions to help lifting it to match version 3.x traffic are very welcome. 78 | -------------------------------------------------------------------------------- /doc/TrafficRestrictions.md: -------------------------------------------------------------------------------- 1 | # Traffic Restrictions 2 | 3 | It is possible to drop or accept specific packet transmit over edge network 4 | interface by rules. Rules can be specify with the `filter.ruel` option multiple 5 | times. 6 | 7 | ## Rule String Format 8 | 9 | rule_str format: `src_ip/len:[b_port,e_port],dst_ip/len:[s_port,e_port],TCP+/-,UDP+/-,ICMP+/-` 10 | 11 | `ip/len` indicate a cidr block, len can be ignore, means single ip (not cidr block) will be use in filter rule. 12 | 13 | `+`,`-` after `TCP`,`UDP`,`ICMP` proto type indicate allow or drop packet of that proto. if any of above three proto missed, the rule will not take effect for that proto. 14 | 15 | Ports range `[s_port,e_port]` can be instead by single port number. If not specify, `[0,65535]` will be used. Ports range include start_port and end_port. 16 | 17 | examples: 18 | `192.168.1.5/32:[0,65535],192.168.0.0/24:[8081,65535],TCP-,UDP-,ICMP+` 19 | `192.168.1.5:[0,65535],192.168.0.0/24:8000,ICMP+` 20 | `192.168.1.5,192.168.0.7,TCP-,UDP-,ICMP-` // packets by all proto of all ports from 192.158.1.5 to any ports of 192.168.0.7 will be dropped. 21 | 22 | ## Multiple Rules 23 | 24 | The `filter.rule` option can be used multiple times to add multiple rules. Each 25 | `filter.rule` definition adds one rule. for example: 26 | 27 | ``` 28 | n3n-edge \ 29 | -c xxxx \ 30 | -k xxxx \ 31 | -a 192.168.100.5 \ 32 | -O supernode.peer=xxx.xxx.xxx.xxx:1234 \ 33 | -r \ 34 | -Ofilter.rule=192.168.1.5/32:[0,65535],192.168.0.0/24:[8081,65535],TCP-,UDP-,ICMP+ \ 35 | -Ofilter.rule=192.168.1.5:[0,65535],192.168.0.0/24:8000,ICMP+ \ 36 | -Ofilter.rule=192.168.1.5,192.168.0.7,TCP- 37 | ``` 38 | 39 | Obviously this gets quite verbose, so adding the filter rules to a config file 40 | is recommended. 41 | 42 | ## Matching Rules Priority 43 | 44 | If multiple rules matching packet's ips and ports, the rule with smaller cidr block(smaller address space) will be selected. That means rules with larger `len` value has higher priority. 45 | 46 | Actually, current implementation will add the `len` of src cidr and dst cidr of each matched rules as priority value, the rule with largest priority value will take effect. 47 | 48 | ## Blocklist/Allowlist mode 49 | 50 | Packets that cannot match any rule will be accepted by default. Users can add rules to block traffics. 51 | 52 | This behavior can be change by add the rule : `0.0.0.0/0:[0,65535],0.0.0.0/0:[0,65535],TCP-,UDP-,ICMP-`. Then all traffic will be dropped, users need add rules to allow traffics. 53 | 54 | for example: 55 | ``` 56 | -Ofilter.rule=0.0.0.0/0,0.0.0.0/0,TCP-,UDP-,ICMP- -Ofilter.rule=192.168.100.0/24,192.168.100.0/24,ICMP+ 57 | ``` 58 | drops all traffic, except ICMP traffics inside `192.168.100.0/24`. 59 | 60 | More complex behavior can be set with the feature of `Matching Rules Priority`. 61 | 62 | -------------------------------------------------------------------------------- /doc/community.list.sample: -------------------------------------------------------------------------------- 1 | # 2 | # List of allowed communities 3 | # --------------------------- 4 | # 5 | # these could either be fixed-name communities such as the following lines ... 6 | # 7 | mynetwork 8 | netleo 9 | # 10 | # ... or regular expressions that a community name must fully match 11 | # such as ntop[0-1][0-9] for communities from "ntop00" through "ntop19" 12 | # 13 | ntop[0-1][0-9] 14 | # 15 | # * Note that fixed-name communities may not contain one of the following characters 16 | # . * + ? [ ] \ 17 | # as otherwise, they are interpreted as regular expression 18 | # 19 | # * Only fixed-name communities are supported for header encryption (using 20 | # the edge config `community.header_encryption=true`) 21 | # 22 | # * Regular expression support the following placeholders 23 | # '.' Dot, matches any character 24 | # '*' Asterisk, match zero or more (greedy) 25 | # '+' Plus, match one or more (greedy) 26 | # '?' Question, match zero or one (non-greedy) 27 | # '[abc]' Character class, match if one of {'a', 'b', 'c'} 28 | # '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} (feature is currently broken) 29 | # '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z } 30 | # '\s' Whitespace, \t \f \r \n \v and spaces 31 | # '\S' Non-whitespace 32 | # '\w' Alphanumeric, [a-zA-Z0-9_] 33 | # '\W' Non-alphanumeric 34 | # '\d' Digits, [0-9] 35 | # '\D' Non-digits 36 | # 37 | # fixed-name communities can optionally be followed by a network using the 38 | # network/bitlen syntax such as the following line 39 | # 40 | home 192.168.168.0/24 41 | # 42 | # the supernode draws ip addresses to assign to the edges (if they omit 43 | # the `-a` parameter or `tuntap.address` config option ) from this 44 | # network. note that the network is delimited by [SPACE] so community 45 | # names cannot contain [SPACE] either. 46 | # 47 | # if no network is provided here, the supernode assigns some other network 48 | # to each community. networks are taken from the default range 10.128.0.0 49 | # - 10.255.255.0/24 (or the range specified with the supernode 50 | # `supernode.auto_ip_min` and `supernode.auto_ip_max` config options). 51 | # those sub-networks are distinct so several edges with different 52 | # communities can be used at the same computer (being served ip addresses 53 | # from the same supernode). also, any sub-networks described in this file 54 | # are avoided. 55 | # 56 | # however, all networks assigned in this file are not mutually checked for colliding 57 | # ranges so different communities can use same or overlapping sub-networks. that does 58 | # not impose a problem if the communities do not share edge nodes. 59 | # 60 | # there seems to be no sense in pre-assigning sub-networks to communities 61 | # whose names are defined by regular expressions. those will be assigned 62 | # distinct sub-networks from the default range (or the configured auto ip 63 | # range). 64 | # 65 | # if `-a` is used with the edge, the edge uses the ip address specified with the 66 | # `-a xxx.xxx.xxx.xxx` option. also, the enhanced syntax `-r -a dhcp:0.0.0.0` is 67 | # still available to have more professional needs served by a full dhcp server. 68 | # 69 | -------------------------------------------------------------------------------- /doc/contributors.txt: -------------------------------------------------------------------------------- 1 | Code contributions courtesy of: 2 | * Richard Andrews 3 | * Don Bindner 4 | * Sylwester Sosnowski 5 | * Wilfried "Wonka" Klaebe 6 | * Lukasz Taczuk 7 | * Alaric Snell-Pym 8 | * Babak Farrokhi [FreeBSD port] 9 | * Logan oos Even 10 | * Hamish Coleman 11 | 12 | and others, as seen in the commit history. 13 | -------------------------------------------------------------------------------- /doc/edge.conf.sample: -------------------------------------------------------------------------------- 1 | # 2 | # The configuration file is basically an INI file, with multiple sections 3 | # and one option per line. An equal sign '=' is used between the option 4 | # name and the value. 5 | # 6 | # This file contains a basic configuration example, please refer to the 7 | # help (edge help config) for the full description of all options. 8 | # 9 | 10 | [tuntap] 11 | # Specifies the name of the TUN interface. 12 | name=n3n0 13 | 14 | # Specifies the MAC address for the TAP interface (random otherwise). 15 | macaddr=DE:AD:BE:EF:99:99 16 | 17 | # Sets the interface address. 18 | # 19 | address=1.2.3.4 20 | 21 | # For DHCP use: 22 | # address_mode=dhcp 23 | # and also 24 | # [filter] 25 | # allow_routing=true 26 | 27 | [community] 28 | # Specifies the n3n community name the edge belongs to. 29 | name=mynetwork 30 | 31 | # Sets the encryption key (ASCII). The environment variable N3N_KEY= 32 | # can be used and will take precedence over the config file. 33 | key=mypassword 34 | 35 | 36 | # Specifies the supernode IP and port. 37 | supernode=7.8.9.0:7777 38 | 39 | [connection] 40 | # Sets the local UDP port to a fixed port. 41 | bind=50001 42 | -------------------------------------------------------------------------------- /doc/supernode.conf.sample: -------------------------------------------------------------------------------- 1 | # 2 | # The configuration file is basically an INI file, with multiple sections 3 | # and one option per line. An equal sign '=' is used between the option 4 | # name and the value. 5 | # 6 | # This file contains a basic configuration example, please refer to the 7 | # help (edge help config) for the full description of all options. 8 | # 9 | 10 | [connection] 11 | # Sets the UDP listening port. 12 | bind=7777 13 | 14 | [supernode] 15 | # Optionally specifies the allowed communities as listed in community.list file. 16 | #community_file=/etc/n3n/community.list 17 | 18 | # If multiple supernodes ("supernode federation") is desired, the following 19 | # two options are needed: 20 | # federation = yoursecret 21 | # peer = other.node:7777 22 | -------------------------------------------------------------------------------- /include/aes.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | 20 | #ifndef AES_H 21 | #define AES_H 22 | 23 | 24 | #include 25 | #include 26 | 27 | #include "portable_endian.h" 28 | 29 | #define AES_BLOCK_SIZE 16 30 | #define AES_IV_SIZE (AES_BLOCK_SIZE) 31 | 32 | #define AES256_KEY_BYTES (256/8) 33 | #define AES192_KEY_BYTES (192/8) 34 | #define AES128_KEY_BYTES (128/8) 35 | 36 | 37 | #ifdef HAVE_LIBCRYPTO // openSSL 1.1 --------------------------------------------------------------------- 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | typedef struct aes_context_t { 44 | EVP_CIPHER_CTX *enc_ctx; /* openssl's reusable evp_* en/de-cryption context */ 45 | EVP_CIPHER_CTX *dec_ctx; /* openssl's reusable evp_* en/de-cryption context */ 46 | const EVP_CIPHER *cipher; /* cipher to use: e.g. EVP_aes_128_cbc */ 47 | uint8_t key[AES256_KEY_BYTES]; /* the pure key data for payload encryption & decryption */ 48 | AES_KEY ecb_dec_key; /* one step ecb decryption key */ 49 | } aes_context_t; 50 | 51 | #elif defined (__AES__) && defined (__SSE2__) // Intel's AES-NI --------------------------------------------------- 52 | 53 | #include 54 | 55 | typedef struct aes_context_t { 56 | __m128i rk_enc[15]; 57 | __m128i rk_dec[15]; 58 | int Nr; 59 | } aes_context_t; 60 | 61 | #else // plain C -------------------------------------------------------------------------------------------------- 62 | 63 | typedef struct aes_context_t { 64 | uint32_t enc_rk[60]; // round keys for encryption 65 | uint32_t dec_rk[60]; // round keys for decryption 66 | int Nr; // number of rounds 67 | } aes_context_t; 68 | 69 | #endif // --------------------------------------------------------------------------------------------------------- 70 | 71 | 72 | int aes_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len, 73 | const unsigned char *iv, aes_context_t *ctx); 74 | 75 | int aes_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len, 76 | const unsigned char *iv, aes_context_t *ctx); 77 | 78 | int aes_ecb_decrypt (unsigned char *out, const unsigned char *in, aes_context_t *ctx); 79 | 80 | int aes_init (const unsigned char *key, size_t key_size, aes_context_t **ctx); 81 | 82 | int aes_deinit (aes_context_t *ctx); 83 | 84 | 85 | #endif // AES_H 86 | -------------------------------------------------------------------------------- /include/auth.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see 16 | * 17 | */ 18 | 19 | 20 | #ifndef AUTH_H 21 | #define AUTH_H 22 | 23 | 24 | #include // for size_t 25 | #include // for uint8_t, uint32_t 26 | 27 | #include "n2n.h" // for n2n_private_public_key_t, n2n_community_t, N2N_A... 28 | #include "n2n_typedefs.h" 29 | 30 | 31 | int bin_to_ascii(char *out, uint8_t *in, size_t in_len); 32 | 33 | int ascii_to_bin(uint8_t *out, char *in); 34 | 35 | int generate_private_key(n2n_private_public_key_t key, char *in); 36 | 37 | int generate_public_key (n2n_private_public_key_t pub, n2n_private_public_key_t prv); 38 | 39 | int generate_shared_secret (n2n_private_public_key_t shared, n2n_private_public_key_t prv, n2n_private_public_key_t pub); 40 | 41 | int bind_private_key_to_username (n2n_private_public_key_t prv, char *username); 42 | 43 | int calculate_dynamic_key (uint8_t out_key[N2N_AUTH_CHALLENGE_SIZE], 44 | uint32_t key_time, n2n_community_t comm, n2n_community_t fed); 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/cc20.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | 20 | #ifndef CC20_H 21 | #define CC20_H 22 | 23 | 24 | #include // for size_t 25 | #include // for uint32_t, uint8_t 26 | #include "config.h" // HAVE_LIBCRYPTO 27 | 28 | 29 | #define CC20_IV_SIZE 16 30 | #define CC20_KEY_BYTES (256/8) 31 | 32 | 33 | #ifdef HAVE_LIBCRYPTO // openSSL 1.1 ---------------------------------------------------------------------------- 34 | 35 | 36 | #include 37 | #include 38 | 39 | typedef struct cc20_context_t { 40 | EVP_CIPHER_CTX *ctx; /* openssl's reusable evp_* en/de-cryption context */ 41 | const EVP_CIPHER *cipher; /* cipher to use: e.g. EVP_chacha20() */ 42 | uint8_t key[CC20_KEY_BYTES]; /* the pure key data for payload encryption & decryption */ 43 | } cc20_context_t; 44 | 45 | 46 | #elif defined (__SSE2__) // SSE2 --------------------------------------------------------------------------------- 47 | 48 | 49 | typedef struct cc20_context { 50 | uint32_t keystream32[16]; 51 | uint8_t key[CC20_KEY_BYTES]; 52 | } cc20_context_t; 53 | 54 | 55 | #else // plain C -------------------------------------------------------------------------------------------------- 56 | 57 | 58 | typedef struct cc20_context { 59 | uint32_t keystream32[16]; 60 | uint32_t state[16]; 61 | uint8_t key[CC20_KEY_BYTES]; 62 | } cc20_context_t; 63 | 64 | 65 | #endif // openSSL 1.1, plain C ------------------------------------------------------------------------------------ 66 | 67 | 68 | int cc20_crypt (unsigned char *out, const unsigned char *in, size_t in_len, 69 | const unsigned char *iv, cc20_context_t *ctx); 70 | 71 | int cc20_init (const unsigned char *key, cc20_context_t **ctx); 72 | 73 | int cc20_deinit (cc20_context_t *ctx); 74 | 75 | 76 | #endif // CC20_H 77 | -------------------------------------------------------------------------------- /include/curve25519.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | 20 | void curve25519 (unsigned char *q, const unsigned char *n, const unsigned char *p); 21 | -------------------------------------------------------------------------------- /include/header_encryption.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | #include "n2n_typedefs.h" 20 | #include "speck.h" // for struct speck_context_t 21 | 22 | int packet_header_decrypt (uint8_t packet[], uint16_t packet_len, 23 | char *community_name, 24 | struct speck_context_t *ctx, 25 | struct speck_context_t *ctx_iv, 26 | uint64_t *stamp); 27 | 28 | int packet_header_encrypt (uint8_t packet[], uint16_t header_len, uint16_t packet_len, 29 | struct speck_context_t *ctx, 30 | struct speck_context_t *ctx_iv, 31 | uint64_t stamp); 32 | 33 | void packet_header_setup_key (const char *community_name, 34 | struct speck_context_t **ctx_static, 35 | struct speck_context_t **ctx_dynamic, 36 | struct speck_context_t **ctx_iv_static, 37 | struct speck_context_t **ctx_iv_dynamic); 38 | 39 | void packet_header_change_dynamic_key (uint8_t *key_dynamic, 40 | struct speck_context_t **ctx_dynamic, 41 | struct speck_context_t **ctx_iv_dynamic); 42 | -------------------------------------------------------------------------------- /include/json.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | 20 | // taken from (and modified) 21 | // https://github.com/Logan007/C-Simple-JSON-Parser 22 | // which is declared license-free code by the author according to 23 | // https://github.com/forkachild/C-Simple-JSON-Parser/issues/3#issuecomment-1073520808 24 | 25 | 26 | #ifndef JSON_H 27 | #define JSON_H 28 | 29 | 30 | #define json_str_is_whitespace(x) x == '\r' || x == '\n' || x == '\t' || x == ' ' 31 | #define json_str_is_numeral(x) (x >= '0' && x <= '9') || x == 'e' || x == 'E' \ 32 | || x == '.' || x == '+' || x == '-' 33 | #define json_str_remove_whitespace_calc_offset(x, y) while(json_str_is_whitespace(*x)) { x++; y++; } 34 | 35 | 36 | typedef enum { 37 | JSON_STRING = 0, 38 | JSON_DOUBLE, 39 | JSON_OBJECT 40 | } json_value_type; 41 | 42 | typedef struct _jsonobject { 43 | struct _jsonpair *pairs; 44 | int count; 45 | } json_object_t; 46 | 47 | typedef struct _jsonpair { 48 | char *key; 49 | union _jsonvalue *value; 50 | json_value_type type; 51 | } json_pair_t; 52 | 53 | typedef union _jsonvalue { 54 | char *string_value; 55 | double double_value; 56 | struct _jsonobject *json_object; 57 | } json_value_t; 58 | 59 | 60 | json_object_t *json_parse (char *str); 61 | void json_free (json_object_t *obj); 62 | 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/n2n_port_mapping.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | 20 | #ifndef _N2N_PORT_MAPPING_H_ 21 | #define _N2N_PORT_MAPPING_H_ 22 | 23 | 24 | #include 25 | 26 | #ifdef HAVE_LIBMINIUPNPC 27 | #include 28 | #include 29 | #include 30 | #endif // HAVE_LIBMINIUPNPC 31 | 32 | 33 | #ifdef HAVE_LIBNATPMP 34 | #include "natpmp.h" 35 | #endif // HAVE_LIBNATPMP 36 | 37 | 38 | void n2n_set_port_mapping (const uint16_t port); 39 | void n2n_del_port_mapping (const uint16_t port); 40 | 41 | 42 | #endif // _N2N_PORT_MAPPING_H_ 43 | -------------------------------------------------------------------------------- /include/n2n_regex.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | // taken from https://github.com/kokke/tiny-regex-c 20 | // under Unlicense as of August 4, 2020 21 | 22 | /* 23 | * 24 | * Mini regex-module inspired by Rob Pike's regex code described in: 25 | * 26 | * http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html 27 | * 28 | * 29 | * 30 | * Supports: 31 | * --------- 32 | * '.' Dot, matches any character 33 | * '^' Start anchor, matches beginning of string 34 | * '$' End anchor, matches end of string 35 | * '*' Asterisk, match zero or more (greedy) 36 | * '+' Plus, match one or more (greedy) 37 | * '?' Question, match zero or one (non-greedy) 38 | * '[abc]' Character class, match if one of {'a', 'b', 'c'} 39 | * '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} -- NOTE: feature is currently broken! 40 | * '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z } 41 | * '\s' Whitespace, \t \f \r \n \v and spaces 42 | * '\S' Non-whitespace 43 | * '\w' Alphanumeric, [a-zA-Z0-9_] 44 | * '\W' Non-alphanumeric 45 | * '\d' Digits, [0-9] 46 | * '\D' Non-digits 47 | * 48 | * 49 | */ 50 | 51 | #ifndef _N2N_REGEX_ 52 | #define _N2N_REGEX_ 53 | 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | 58 | #include 59 | 60 | /* Compile regex string pattern to a regex_t-array. */ 61 | re_t re_compile (const char* pattern); 62 | 63 | 64 | /* Find matches of the compiled pattern inside text. */ 65 | int re_matchp (re_t pattern, const char* text, int* matchlenght); 66 | 67 | 68 | /* Find matches of the txt pattern inside text (will compile automatically first). */ 69 | int re_match (const char* pattern, const char* text, int* matchlenght); 70 | 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /include/n3n/conffile.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Public API for configuration management 6 | */ 7 | 8 | #ifndef _N2N_CONFFILE_H_ 9 | #define _N2N_CONFFILE_H_ 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | enum n3n_conf_type { 17 | n3n_conf_strncpy, 18 | n3n_conf_bool, 19 | n3n_conf_uint32, 20 | n3n_conf_strdup, 21 | n3n_conf_transform, 22 | n3n_conf_headerenc, 23 | n3n_conf_compression, 24 | n3n_conf_privatekey, 25 | n3n_conf_publickey, 26 | n3n_conf_sockaddr, 27 | n3n_conf_n2n_sock_addr, // TODO: want to replace users with sockaddr 28 | n3n_conf_sn_selection, 29 | n3n_conf_verbose, 30 | n3n_conf_filter_rule, 31 | n3n_conf_ip_subnet, 32 | n3n_conf_ip_mode, 33 | n3n_conf_userid, 34 | n3n_conf_groupid, 35 | n3n_conf_macaddr, // TODO: conf has another macaddr string type 36 | n3n_conf_hostname_str, 37 | }; 38 | 39 | struct n3n_conf_option { 40 | char *name; // The name used to configure this option 41 | int length; // Max length for string copy types 42 | int offset; // offset within the conf structure of value 43 | char *desc; // Short description 44 | char *help; // lengthy description 45 | enum n3n_conf_type type; // Which parser/validator to use 46 | }; 47 | 48 | struct n3n_conf_section { 49 | struct n3n_conf_section *next; 50 | char *name; // The name of this config section 51 | char *help; // A description for this section 52 | struct n3n_conf_option *options; 53 | }; 54 | 55 | void n3n_config_register_section (char *, char *, struct n3n_conf_option[]); 56 | 57 | int n3n_config_set_option (void *, char *, char *, char *); 58 | 59 | void n3n_config_dump (void *, FILE *, int); 60 | void n3n_config_debug_addr (void *, FILE *); 61 | 62 | int n3n_config_load_env (void *); 63 | 64 | int n3n_config_load_file (void *, char *); 65 | 66 | enum n3n_subcmd_type { 67 | n3n_subcmd_type_nest = 1, 68 | n3n_subcmd_type_fn 69 | }; 70 | struct n3n_subcmd_def { 71 | char *name; 72 | char *help; 73 | union { 74 | struct n3n_subcmd_def *nest; 75 | void (*fn)(int argc, char **argv, void *conf); 76 | }; 77 | enum n3n_subcmd_type type; 78 | bool session_arg; // is the next arg a session name to load? 79 | }; 80 | 81 | enum n3n_subcmd_result_type { 82 | n3n_subcmd_result_unknown, 83 | n3n_subcmd_result_version, 84 | n3n_subcmd_result_about, 85 | n3n_subcmd_result_ok 86 | }; 87 | struct n3n_subcmd_result { 88 | char **argv; 89 | char *sessionname; 90 | int argc; 91 | enum n3n_subcmd_result_type type; 92 | struct n3n_subcmd_def *subcmd; 93 | }; 94 | 95 | void n3n_subcmd_help (struct n3n_subcmd_def *, int, bool); 96 | struct n3n_subcmd_result n3n_subcmd_parse (int, char **, char *, const struct option *, struct n3n_subcmd_def *); 97 | 98 | struct n3n_config_getopt { 99 | int optkey; 100 | char *section; 101 | char *option; 102 | char *value; // if no optarg, then use this for the value 103 | char *help; 104 | }; 105 | 106 | void n3n_config_from_getopt (const struct n3n_config_getopt *map, void *conf, int optkey, char *optarg); 107 | void n3n_config_help_options (const struct n3n_config_getopt *map, const struct option *long_options); 108 | 109 | typedef struct n2n_edge_conf n2n_edge_conf_t; 110 | int n3n_config_setup_sessiondir (n2n_edge_conf_t *conf); 111 | #endif 112 | -------------------------------------------------------------------------------- /include/n3n/edge.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-25 Hamish Coleman 4 | * SPDX-License-Identifier: GPL-3.0-only 5 | * 6 | * Public API for edge 7 | */ 8 | 9 | // TODO: refactor into public and private definitions 10 | 11 | #ifndef _N3N_EDGE_H_ 12 | #define _N3N_EDGE_H_ 13 | 14 | #include // for uint8_t, uint16_t 15 | #include // for time_t 16 | #include // for n3n_runtime_data, n2n_mac_t, SOCKET 17 | 18 | // Allow public pointers to reference the private structure 19 | typedef struct n2n_edge_conf n2n_edge_conf_t; 20 | 21 | 22 | /* Edge conf */ 23 | int edge_verify_conf (const n2n_edge_conf_t *conf); 24 | void edge_init_conf_defaults (n2n_edge_conf_t *conf, char *sessionname); 25 | void edge_term_conf (n2n_edge_conf_t *conf); 26 | 27 | 28 | void send_register_super (struct n3n_runtime_data *eee); 29 | void send_query_peer (struct n3n_runtime_data *eee, const n2n_mac_t dst_mac); 30 | void supernode_connect (struct n3n_runtime_data *eee); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/n3n/endian.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | */ 6 | 7 | // TODO: 8 | // - this is quite tangled 9 | // - many systems already provide a definition for this somewhere 10 | 11 | #ifndef _N3N_ENDIAN_H_ 12 | #define _N3N_ENDIAN_H_ 13 | 14 | #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 15 | #include 16 | #endif 17 | 18 | #ifdef __OpenBSD__ 19 | #include 20 | #define __BYTE_ORDER BYTE_ORDER 21 | #if BYTE_ORDER == LITTLE_ENDIAN 22 | #ifndef __LITTLE_ENDIAN__ 23 | #define __LITTLE_ENDIAN__ 24 | #endif /* __LITTLE_ENDIAN__ */ 25 | #else 26 | #define __BIG_ENDIAN__ 27 | #endif/* BYTE_ORDER */ 28 | #endif/* __OPENBSD__ */ 29 | 30 | 31 | #if __BYTE_ORDER == __LITTLE_ENDIAN 32 | #ifndef __LITTLE_ENDIAN__ 33 | #define __LITTLE_ENDIAN__ 34 | #endif 35 | #else 36 | #ifndef __BIG_ENDIAN__ 37 | #define __BIG_ENDIAN__ 38 | #endif 39 | #endif 40 | 41 | #ifdef _WIN32 42 | #ifndef __LITTLE_ENDIAN__ 43 | #define __LITTLE_ENDIAN__ 1 44 | #endif 45 | #endif 46 | 47 | #if !(defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__)) 48 | #if defined(__mips__) 49 | #undef __LITTLE_ENDIAN__ 50 | #undef __LITTLE_ENDIAN 51 | #define __BIG_ENDIAN__ 52 | #endif 53 | 54 | /* Everything else */ 55 | #if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)) 56 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 57 | #define __LITTLE_ENDIAN__ 58 | #else 59 | #define __BIG_ENDIAN__ 60 | #endif 61 | #endif 62 | 63 | #endif 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /include/n3n/ethernet.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Public API for ethernet helpers 6 | */ 7 | 8 | // TODO: determine if these are actually public 9 | 10 | #ifndef _N3N_ETHERNET_H_ 11 | #define _N3N_ETHERNET_H_ 12 | 13 | #include // for uint8_t 14 | 15 | #define N2N_MAC_SIZE 6 16 | #define N2N_MACSTR_SIZE 32 17 | 18 | typedef uint8_t n2n_mac_t[N2N_MAC_SIZE]; 19 | typedef char macstr_t[N2N_MACSTR_SIZE]; 20 | 21 | uint8_t is_null_mac (const n2n_mac_t dest_mac); 22 | 23 | char* macaddr_str (macstr_t buf, const n2n_mac_t mac); 24 | int str2mac (uint8_t * outmac /* 6 bytes */, const char * s); 25 | 26 | #endif 27 | 28 | 29 | -------------------------------------------------------------------------------- /include/n3n/hexdump.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | */ 5 | 6 | #ifndef HEXDUMP_H 7 | #define HEXDUMP_H 8 | 9 | #include 10 | 11 | void fhexdump(unsigned int display_addr, void *in, int size, FILE *stream); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /include/n3n/initfuncs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Public API to the initfuncs wrapper 6 | */ 7 | 8 | #ifndef _N3N_INITFUNCS_H_ 9 | #define _N3N_INITFUNCS_H_ 10 | 11 | void n3n_initfuncs (); 12 | void n3n_deinitfuncs (); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/n3n/logging.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-25 Hamish Coleman 4 | * SPDX-License-Identifier: GPL-3.0-only 5 | * 6 | * Public API for logging 7 | */ 8 | 9 | #ifndef _N3N_LOGGING_H_ 10 | #define _N3N_LOGGING_H_ 11 | 12 | #include // for FILE 13 | 14 | #define TRACE_ERROR 0 15 | #define TRACE_WARNING 1 16 | #define TRACE_NORMAL 2 17 | #define TRACE_INFO 3 18 | #define TRACE_DEBUG 4 19 | 20 | void setTraceLevel (int level); 21 | void setUseSyslog (int use_syslog); 22 | int getTraceLevel (); 23 | void closeTraceFile (); 24 | void _traceEvent (int eventTraceLevel, char* file, int line, char * format, ...); 25 | #define traceEvent(level, format, ...) _traceEvent(level, __FILE__, __LINE__, format, ## __VA_ARGS__) 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /include/n3n/mainloop.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * 4 | * non public structure and function definitions 5 | * 6 | * TODO: 7 | * - fix the layering confusion in the calling code 8 | * (apps/example_edge_embed.c apps/n3n-edge.c) 9 | * and move this header back to the non-public src/ location 10 | */ 11 | 12 | #ifndef _MAINLOOP_H_ 13 | #define _MAINLOOP_H_ 14 | 15 | #include // for strbuf_t 16 | #include // for n3n_runtime_data 17 | 18 | #ifndef _WIN32 19 | #include // for fd_set 20 | #endif 21 | 22 | enum __attribute__((__packed__)) fd_info_proto { 23 | fd_info_proto_unknown = 0, 24 | fd_info_proto_tuntap, 25 | fd_info_proto_listen_http, 26 | fd_info_proto_v3udp, 27 | fd_info_proto_v3tcp, 28 | fd_info_proto_http, 29 | }; 30 | 31 | // Place debug info from the slots into the strbuf 32 | void mainloop_dump (strbuf_t **); 33 | 34 | // Starts sending a packet, queuing if needed 35 | // returns false when: 36 | // - no queue slot is available 37 | // - the file handle is not registered with the mainloop 38 | // - the file handle is not registered as a v3tcp proto 39 | bool mainloop_send_v3tcp (int, const void *, int); 40 | 41 | int mainloop_runonce (struct n3n_runtime_data *); 42 | 43 | void mainloop_register_fd (int, enum fd_info_proto); 44 | void mainloop_unregister_fd (int); 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/n3n/metrics.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Public API for adding metrics 6 | */ 7 | 8 | #ifndef _N2N_METRICS_H_ 9 | #define _N2N_METRICS_H_ 10 | 11 | #include 12 | 13 | enum __attribute__((__packed__)) n3n_metrics_items_type { 14 | n3n_metrics_type_invalid = 0, 15 | n3n_metrics_type_uint32, // items_uint32 is valid 16 | n3n_metrics_type_llu32, 17 | n3n_metrics_type_cb, 18 | }; 19 | 20 | // The simplest type of metrics: everything is the same storage type, there are 21 | // no custom labels are added to anything and only one instance is possible. 22 | // The module definition points to an array of items, terminated with an entry 23 | // that has item->name == NULL. 24 | // This can be rendered with no callbacks by the metrics renderer 25 | struct n3n_metrics_items_uint32 { 26 | const char *name; // tail of the metrics name 27 | const char *desc; // Help text for the metric 28 | const int offset; // Offset from the start of the void 29 | // const enum foo type - today, they are all counters 30 | // const enum foo unit - today, they are all unitless 31 | }; 32 | 33 | struct n3n_metrics_items_llu32_ent { 34 | const char *val1; 35 | const char *val2; 36 | const int offset; // Offset from the start of the void 37 | }; 38 | 39 | struct n3n_metrics_items_llu32 { 40 | const char *name; // tail of the metrics name 41 | const char *desc; // Help text for the metric 42 | const char *name1; 43 | const char *name2; 44 | const struct n3n_metrics_items_llu32_ent items[]; 45 | // const enum foo type - today, they are all counters 46 | // const enum foo unit - today, they are all unitless 47 | }; 48 | 49 | struct n3n_metrics_module { 50 | struct n3n_metrics_module *next; // the metrics.c manages this 51 | const char *name; // What is this module called 52 | void *data; // opaque pointer to the data 53 | union { 54 | const struct n3n_metrics_items_uint32 *items_uint32; 55 | const struct n3n_metrics_items_llu32 *items_llu32; 56 | void (*cb)(strbuf_t **, const struct n3n_metrics_module *); 57 | }; 58 | const enum n3n_metrics_items_type type; 59 | }; 60 | 61 | // Register a block of metrics 62 | void n3n_metrics_register (struct n3n_metrics_module *); 63 | 64 | // Helper to assist with rendering during n3n_metrics_type_cb 65 | void n3n_metrics_render_u32tags ( 66 | strbuf_t **reply, 67 | const struct n3n_metrics_module *module, 68 | const char *name, 69 | const int offset, 70 | const int tags, // The number of following tag+val pairs 71 | ... 72 | ); 73 | 74 | // Render all the metrics into a strbuf 75 | void n3n_metrics_render (strbuf_t **reply); 76 | 77 | // Set the session name for all metrics 78 | void n3n_metrics_set_session (char *); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/n3n/peer_info.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Public API for peer_info 6 | */ 7 | 8 | // TODO: refactor to remove public users 9 | 10 | #ifndef _N3N_PEER_INFO_H_ 11 | #define _N3N_PEER_INFO_H_ 12 | 13 | // Allow public pointers to reference the private structure 14 | typedef struct peer_info peer_info_t; 15 | 16 | #endif 17 | 18 | -------------------------------------------------------------------------------- /include/n3n/random.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2024-25 Hamish Coleman 4 | * SPDX-License-Identifier: GPL-3.0-only 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not see see 18 | * 19 | */ 20 | 21 | #ifndef _N3N_RANDOM_H_ 22 | #define _N3N_RANDOM_H_ 23 | 24 | 25 | #include // for uint64_t, uint32_t 26 | 27 | uint64_t n3n_rand (void); 28 | int memrnd (uint8_t *address, size_t len); 29 | 30 | // Only use when attempting to make a reproducible test case 31 | void n3n_srand_stable_default (void); 32 | 33 | uint32_t n3n_rand_sqr (uint32_t max_n); 34 | 35 | 36 | struct n3n_rand_seeds_def { 37 | char *name; 38 | uint64_t (*seed)(); 39 | }; 40 | 41 | extern const struct n3n_rand_seeds_def n3n_rand_seeds[]; 42 | extern const int n3n_rand_seeds_size; 43 | 44 | #endif // _N3N_RANDOM_H_ 45 | -------------------------------------------------------------------------------- /include/n3n/resolve.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-25 Hamish Coleman 4 | * SPDX-License-Identifier: GPL-3.0-only 5 | * 6 | * The resolver thread minimal public API 7 | */ 8 | 9 | #ifndef _N3N_RESOLVE_H_ 10 | #define _N3N_RESOLVE_H_ 11 | 12 | typedef struct n3n_resolve_parameter n3n_resolve_parameter_t; 13 | 14 | #define RESOLVE_LIST_SUPERNODE 1 // edge uses to list supernode hostnames 15 | #define RESOLVE_LIST_PEER 2 // supernode uses to list peer hostnames 16 | 17 | void resolve_hostnames_str_add (int, const char *); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/n3n/strings.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Public API for stringification helpers 6 | */ 7 | 8 | // TODO: determine if these are actually public 9 | 10 | #ifndef _N3N_STRINGS_H_ 11 | #define _N3N_STRINGS_H_ 12 | 13 | #include // for dec_ip_bit_str_t, n2n_ip_subnet_t, n2n_... 14 | 15 | char * ip_subnet_to_str (dec_ip_bit_str_t buf, const n2n_ip_subnet_t *ipaddr); 16 | 17 | char* sock_to_cstr (n2n_sock_str_t out, 18 | const n2n_sock_t * sock); 19 | #endif 20 | 21 | -------------------------------------------------------------------------------- /include/n3n/supernode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Public API for supernode 6 | */ 7 | 8 | // TODO: need to go through these definitions and sort them into public 9 | // and private 10 | 11 | #ifndef _N3N_SUPERNODE_H_ 12 | #define _N3N_SUPERNODE_H_ 13 | 14 | #include // for n3n_runtime_data 15 | 16 | int load_allowed_sn_community (struct n3n_runtime_data *sss); 17 | void calculate_shared_secrets (struct n3n_runtime_data *sss); 18 | void sn_init_conf_defaults (struct n3n_runtime_data *sss, char *sessionname); 19 | 20 | int run_sn_loop (struct n3n_runtime_data *sss); 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /include/n3n/tests.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Public API for built-in tests 6 | */ 7 | 8 | #ifndef _N3N_TESTS_H_ 9 | #define _N3N_TESTS_H_ 10 | 11 | int test_hashing (int); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /include/n3n/transform.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Public API for managing transformation algos 6 | */ 7 | 8 | #ifndef _N2N_TRANSFORM_H_ 9 | #define _N2N_TRANSFORM_H_ 10 | 11 | #include 12 | 13 | struct n3n_transform { 14 | struct n3n_transform *next; 15 | const char *name; // The name of this config section 16 | const char *desc; // A short description for this section 17 | const int id; 18 | const bool is_compress; // this transform is not an encryption 19 | }; 20 | 21 | // Register a transform implementation 22 | void n3n_transform_register (struct n3n_transform *); 23 | 24 | // Return the only transform registered with this unique name 25 | struct n3n_transform *n3n_transform_lookup_name (char *); 26 | 27 | // Return the first registered transform with this id 28 | struct n3n_transform *n3n_transform_lookup_id (int); 29 | 30 | // Convenience helper to do a lookup and return a non null string 31 | const char *n3n_transform_id2str (int); 32 | 33 | // Return the only compression transform registered with this unique name 34 | struct n3n_transform *n3n_compression_lookup_name (char *); 35 | 36 | // Return the first registered compression transform with this id 37 | struct n3n_transform *n3n_compression_lookup_id (int); 38 | 39 | // Convenience helper to do a compression lookup and return a non null string 40 | const char *n3n_compression_id2str (int); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/pearson.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | 20 | #include // for size_t 21 | #include // for uint8_t, uint16_t, uint32_t, uint64_t 22 | 23 | 24 | void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len); 25 | 26 | void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len); 27 | 28 | uint64_t pearson_hash_64 (const uint8_t *in, size_t len); 29 | 30 | uint32_t pearson_hash_32 (const uint8_t *in, size_t len); 31 | 32 | uint16_t pearson_hash_16 (const uint8_t *in, size_t len); 33 | -------------------------------------------------------------------------------- /include/sn_selection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-25 Hamish Coleman 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not see see 17 | * 18 | */ 19 | 20 | #ifndef _SN_SELECTION_ 21 | #define _SN_SELECTION_ 22 | 23 | #define SN_SELECTION_STRATEGY_LOAD 1 24 | #define SN_SELECTION_STRATEGY_RTT 2 25 | #define SN_SELECTION_STRATEGY_MAC 3 26 | 27 | #define SN_SELECTION_CRITERION_BUF_SIZE 16 28 | 29 | // FIXME: including the private header in a public interface, should untangle 30 | #include "../src/peer_info.h" // for peer_info, peer_info_t 31 | 32 | typedef char selection_criterion_str_t[SN_SELECTION_CRITERION_BUF_SIZE]; 33 | 34 | #include "n2n.h" 35 | 36 | /* selection criterion's functions */ 37 | uint64_t sn_selection_criterion_default (); 38 | uint64_t sn_selection_criterion_bad (); 39 | uint64_t sn_selection_criterion_good (); 40 | int sn_selection_criterion_calculate (struct n3n_runtime_data *eee, peer_info_t *peer, uint64_t data); 41 | 42 | /* common data's functions */ 43 | int sn_selection_criterion_common_data_default (struct n3n_runtime_data *eee); 44 | 45 | /* sorting function */ 46 | int sn_selection_sort (peer_info_t **peer_list); 47 | 48 | /* gathering data function */ 49 | uint64_t sn_selection_criterion_gather_data (struct n3n_runtime_data *sss); 50 | 51 | /* management port output function */ 52 | extern char * sn_selection_criterion_str (struct n3n_runtime_data *eee, selection_criterion_str_t out, peer_info_t *peer); 53 | 54 | 55 | #endif /* _SN_SELECTION_ */ 56 | -------------------------------------------------------------------------------- /include/tf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | 20 | // taken (and modified) from github/fudanchii/twofish as of August 2020 21 | // which itself is a modified copy of Andrew T. Csillag's implementation 22 | // published on github/drewcsillag/twofish 23 | 24 | 25 | /** 26 | * The MIT License (MIT) 27 | * 28 | * Copyright (c) 2015 Andrew T. Csillag 29 | * 30 | * Permission is hereby granted, free of charge, to any person obtaining a copy 31 | * of this software and associated documentation files (the "Software"), to deal 32 | * in the Software without restriction, including without limitation the rights 33 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | * copies of the Software, and to permit persons to whom the Software is 35 | * furnished to do so, subject to the following conditions: 36 | * 37 | * The above copyright notice and this permission notice shall be included in 38 | * all copies or substantial portions of the Software. 39 | * 40 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 45 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | * THE SOFTWARE. 47 | */ 48 | 49 | 50 | #ifndef TF_H 51 | #define TF_H 52 | 53 | 54 | #include // for uint32_t 55 | #include // for size_t 56 | 57 | 58 | #define TF_BLOCK_SIZE 16 59 | #define TF_IV_SIZE (TF_BLOCK_SIZE) 60 | 61 | 62 | typedef struct tf_context_t { 63 | int N; 64 | uint32_t K[40]; 65 | uint32_t QF[4][256]; 66 | } tf_context_t; 67 | 68 | 69 | int tf_ecb_decrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx); 70 | 71 | int tf_ecb_encrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx); 72 | 73 | int tf_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len, 74 | const unsigned char *iv, tf_context_t *ctx); 75 | 76 | int tf_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len, 77 | const unsigned char *iv, tf_context_t *ctx); 78 | 79 | int tf_init (const unsigned char *key, size_t key_size, tf_context_t **ctx); 80 | 81 | int tf_deinit (tf_context_t *ctx); 82 | 83 | 84 | #endif // TF_H 85 | -------------------------------------------------------------------------------- /libs/connslot/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # files generated by coverage checks 3 | *.gcda 4 | *.gcno 5 | coverage 6 | 7 | # generated intermediates 8 | connslot.o 9 | jsonrpc.o 10 | strbuf.o 11 | 12 | # generated outputs 13 | connslot-tests 14 | doxygen 15 | httpd-test 16 | strbuf-tests 17 | -------------------------------------------------------------------------------- /libs/connslot/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) Hamish Coleman 3 | # SPDX-License-Identifier: GPL-2.0-only 4 | # 5 | 6 | all: libconnslot.a 7 | 8 | CFLAGS+=-Wall -Wextra -Werror -g -DMETRICS 9 | 10 | COVERAGEDIR?=coverage 11 | ifdef COVERAGE 12 | CFLAGS+=-fprofile-arcs 13 | CFLAGS+=-ftest-coverage 14 | LDFLAGS+=--coverage 15 | endif 16 | 17 | # Some supported compilers dont have this function and others are 18 | # older and detect leaks that are not there, so default to off unless 19 | # testing 20 | ifdef ANALYZER 21 | CFLAGS+=-fanalyzer 22 | endif 23 | 24 | ifdef SANITISE 25 | CFLAGS+=-fsanitize=leak 26 | LDFLAGS+=-fsanitize=leak 27 | endif 28 | 29 | # Append any extra libs needed in this environment 30 | LDLIBS+=$(LDLIBS_EXTRA) 31 | 32 | LINT_CCODE+=strbuf.c strbuf.h strbuf-tests.c 33 | LINT_CCODE+=connslot.c connslot.h connslot-tests.c 34 | LINT_CCODE+=httpd-test.c 35 | LINT_CCODE+=jsonrpc.c jsonrpc.h 36 | 37 | BUILD_DEP+=uncrustify 38 | BUILD_DEP+=gcovr 39 | 40 | CLEAN+=strbuf-tests 41 | CLEAN+=connslot-tests 42 | CLEAN+=*.o 43 | 44 | strbuf.o: strbuf.h 45 | strbuf-tests: strbuf.o 46 | connslot.o: connslot.h 47 | connslot-tests: connslot.o strbuf.o 48 | httpd-test: connslot.o strbuf.o jsonrpc.o 49 | 50 | libconnslot.a: strbuf.o connslot.o jsonrpc.o 51 | $(AR) rcs $@ $^ 52 | CLEAN+=libconnslot.a 53 | 54 | .PHONY: build-dep 55 | build-dep: 56 | sudo apt-get -y install $(BUILD_DEP) 57 | 58 | .PHONY: lint 59 | lint: lint.ccode 60 | 61 | .PHONY: lint.ccode 62 | lint.ccode: 63 | uncrustify -c uncrustify.cfg --check ${LINT_CCODE} 64 | 65 | .PHONY: test 66 | test: test.strbuf 67 | test: test.connslot 68 | 69 | .PHONY: test.strbuf 70 | test.strbuf: strbuf-tests 71 | ./strbuf-tests 72 | 73 | .PHONY: test.connslot 74 | test.connslot: connslot-tests 75 | ./connslot-tests 76 | 77 | .PHONY: cover 78 | cover: 79 | mkdir -p $(COVERAGEDIR) 80 | gcovr -s --html --html-details --output=$(COVERAGEDIR)/index.html 81 | 82 | .PHONY: clean 83 | clean: 84 | rm -f ${CLEAN} 85 | -------------------------------------------------------------------------------- /libs/connslot/README.md: -------------------------------------------------------------------------------- 1 | This library code was originally published as part of https://github.com/hamishcoleman/iptables-accounting 2 | where it was being incubated to mature its features. 3 | 4 | It is a completely standalone library and only included here for simplicity. 5 | -------------------------------------------------------------------------------- /libs/connslot/connslot-tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tests for the connection/slots abstraction 3 | * 4 | * Copyright (C) Hamish Coleman 5 | * SPDX-License-Identifier: GPL-2.0-only 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "connslot.h" 14 | 15 | // Tests are silent and return if everything is OK, or abort if issues 16 | void connslot_tests() { 17 | slots_t *p = slots_malloc(5, 1000, 1000); 18 | assert(p); 19 | assert(p->nr_slots==5); 20 | assert(p->nr_open==0); 21 | assert(p->listen[0]==-1); 22 | assert(p->listen[1]==-1); 23 | assert(p->timeout==60); 24 | 25 | slots_free(p); 26 | } 27 | 28 | int main() { 29 | printf("Running conslot tests\n"); 30 | 31 | // Many sizes are acceptable, so this is informational only 32 | printf("sizeof(conn_t) = %li\n", sizeof(conn_t)); 33 | printf("sizeof(slots_t) = %li\n", sizeof(slots_t)); 34 | 35 | connslot_tests(); 36 | } 37 | -------------------------------------------------------------------------------- /libs/connslot/connslot.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | * Internal interface definitions for the connslot abstraction 3 | * 4 | * Copyright (C) Hamish Coleman 5 | * SPDX-License-Identifier: LGPL-2.1-only 6 | */ 7 | 8 | #ifndef CONNSLOT_H 9 | #define CONNSLOT_H 10 | 11 | #include // for bool 12 | #include // for ssize_t 13 | 14 | #ifndef _WIN32 15 | #include // for fd_set 16 | #endif 17 | 18 | #ifdef _WIN32 19 | #include 20 | #endif 21 | 22 | #include "strbuf.h" // for strbuf_t 23 | 24 | #ifdef _WIN32 25 | void *memmem(void *haystack, size_t haystack_len, void * needle, size_t needle_len); 26 | #endif 27 | 28 | enum __attribute__((__packed__)) conn_state { 29 | CONN_EMPTY = 0, 30 | CONN_READING = 1, 31 | CONN_READY = 2, 32 | CONN_CLOSED = 4, 33 | CONN_ERROR = 5, 34 | }; 35 | 36 | enum __attribute__((__packed__)) conn_proto { 37 | CONN_PROTO_UNK = 0, 38 | CONN_PROTO_HTTP = 1, 39 | CONN_PROTO_BE16LEN = 2, 40 | }; 41 | 42 | typedef struct conn { 43 | strbuf_t *request; // Request from remote 44 | strbuf_t *reply_header; // not shared reply data 45 | strbuf_t *reply; // shared reply data (const struct) 46 | int activity; // truncated timestamp of last txn 47 | int fd; 48 | unsigned int reply_sendpos; 49 | enum conn_state state; 50 | enum conn_proto proto; 51 | } conn_t; 52 | 53 | #define SLOTS_LISTEN 2 54 | typedef struct slots { 55 | int nr_slots; 56 | int nr_open; 57 | int listen[SLOTS_LISTEN]; 58 | int timeout; 59 | conn_t conn[]; 60 | } slots_t; 61 | 62 | void conn_zero(conn_t *); 63 | int conn_init(conn_t *, size_t, size_t); 64 | void conn_accept(conn_t *, int, enum conn_proto); 65 | void conn_check_ready(conn_t *); 66 | ssize_t conn_read(conn_t *, int); 67 | ssize_t conn_write(conn_t *, int); 68 | bool conn_iswriter(conn_t *); 69 | void conn_close(conn_t *, int); 70 | bool conn_closeidle(conn_t *, int, int, int); 71 | void conn_dump(strbuf_t **, conn_t *); 72 | 73 | void slots_free(slots_t *slots); 74 | slots_t *slots_malloc(int nr_slots, size_t, size_t); 75 | int slots_create_listen_tcp(int, bool); 76 | int slots_listen_tcp(slots_t *, int, bool); 77 | int slots_create_listen_unix(char *, int, int, int); 78 | int slots_listen_unix(slots_t *, char *, int, int, int); 79 | void slots_listen_close(slots_t *); 80 | int slots_fdset(slots_t *, fd_set *, fd_set *); 81 | int slots_accept(slots_t *, int, enum conn_proto); 82 | int slots_closeidle(slots_t *); 83 | int slots_fdset_loop(slots_t *, fd_set *, fd_set *); 84 | void slots_dump(strbuf_t **, slots_t *); 85 | #endif 86 | -------------------------------------------------------------------------------- /libs/connslot/file2strbufc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use warnings; 3 | use strict; 4 | # 5 | # Converts the stdin text file to a c strbuf_t structure, on stdout 6 | # SPDX-License-Identifier: GPL-2.0-only 7 | # 8 | 9 | use FileHandle; 10 | 11 | sub usage { 12 | print "Usage: file2strbufc filename varname\n"; 13 | exit 1; 14 | } 15 | 16 | sub main { 17 | my $filename = $ARGV[0] || usage(); 18 | my $varname = $ARGV[1] || usage(); 19 | 20 | my $fh = FileHandle->new($filename) || die "could not open $filename"; 21 | local $/ = undef; 22 | my $data = <$fh>; 23 | $fh->close(); 24 | 25 | my $size = length($data); 26 | 27 | printf("/* #embed \"%s\" */\n",$filename); 28 | printf("static strbuf_t %s = {\n",$varname); 29 | printf(" .capacity = %i,\n",$size+1); # add one for nul terminator 30 | printf(" .wr_pos = %i,\n",$size); 31 | printf(" .str = {"); 32 | 33 | for my $pos (0..length($data)-1) { 34 | my $ch = substr($data, $pos, 1); 35 | 36 | my $sep; 37 | if ($pos % 16 == 0) { 38 | print "\n "; 39 | $sep = " "; 40 | } else { 41 | $sep = ""; 42 | } 43 | printf("0x%02x,%s", ord($ch), $sep); 44 | } 45 | 46 | # nul terminate ( 47 | print "0x00,\n"; 48 | 49 | print " }\n"; 50 | print "};\n"; 51 | } 52 | main(); 53 | -------------------------------------------------------------------------------- /libs/connslot/jsonrpc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A very simplistic set of tools for extracting data from json strings 3 | * with no memory allocations (It adds null bytes to the input string) 4 | * and no expectation for seamlessly working with complex data input. 5 | * 6 | * 7 | * Copyright (C) Hamish Coleman 8 | * SPDX-License-Identifier: LGPL-2.1-only 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include "jsonrpc.h" 15 | 16 | char *json_find_field(char *haystack, char *field) { 17 | // field must include the start and end doublequotes 18 | 19 | if (!haystack) { 20 | return NULL; 21 | } 22 | 23 | char *p = strstr(haystack, field); 24 | if (!p) { 25 | return NULL; 26 | } 27 | 28 | p += strlen(field); 29 | 30 | while (isspace((unsigned char)*p)) {p++;} 31 | 32 | if (*p != ':') { 33 | return NULL; 34 | } 35 | p++; 36 | 37 | while (isspace((unsigned char)*p)) {p++;} 38 | 39 | return p; 40 | } 41 | 42 | char *json_extract_val(char *p) { 43 | // modifies the source string 44 | char *e; 45 | 46 | if (!p) { 47 | return NULL; 48 | } 49 | 50 | // A string val 51 | if (*p == '"') { 52 | p++; 53 | e = p; 54 | while (*e != '"') {e++;} 55 | *e = '\0'; 56 | return p; 57 | } 58 | 59 | // A positive integer val 60 | if (isdigit((unsigned char)*p)) { 61 | e = p; 62 | while (isdigit((unsigned char)*e)) {e++;} 63 | *e = '\0'; 64 | return p; 65 | } 66 | 67 | // The null value 68 | // TODO: this return is indistinguishable from "null" 69 | if (strncmp(p,"null",4)==0) { 70 | p[4] = '\0'; 71 | return p; 72 | } 73 | 74 | char open; 75 | char close; 76 | 77 | // A dictionary, an array or an error 78 | if (*p == '{') { 79 | open = '{'; 80 | close = '}'; 81 | } else if (*p == '[') { 82 | open = '['; 83 | close = ']'; 84 | } else { 85 | return NULL; 86 | } 87 | 88 | e = p+1; 89 | int depth = 1; 90 | while (depth) { 91 | if (*e == '\0') { 92 | return NULL; 93 | } 94 | if (*e == open) { 95 | depth++; 96 | } else if (*e == close) { 97 | depth--; 98 | } 99 | e++; 100 | } 101 | *e = '\0'; 102 | return p; 103 | } 104 | 105 | int jsonrpc_parse(char *p, jsonrpc_t *json) { 106 | if (!json) { 107 | return -1; 108 | } 109 | if (p[0] != '{') { 110 | json->method = NULL; 111 | json->params = NULL; 112 | json->id = NULL; 113 | return -2; 114 | } 115 | p++; 116 | 117 | // char *ver = json_find_field(p, "\"jsonrpc\""); 118 | char *method = json_find_field(p, "\"method\""); 119 | char *params = json_find_field(p, "\"params\""); 120 | char *id = json_find_field(p, "\"id\""); 121 | 122 | if(!method || !id) { 123 | // not a valid jsonrpc request without these fields found 124 | return -3; 125 | } 126 | 127 | // do all the field finding first, since the value extractor will 128 | // insert nulls at the end of its strings 129 | 130 | // TODO: confirm that version == "2.0" 131 | json->method = json_extract_val(method); 132 | json->params = json_extract_val(params); 133 | json->id = json_extract_val(id); 134 | return 0; 135 | } 136 | 137 | -------------------------------------------------------------------------------- /libs/connslot/jsonrpc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (C) Hamish Coleman 4 | * SPDX-License-Identifier: LGPL-2.1-only 5 | */ 6 | 7 | #ifndef JSONRPC_H 8 | #define JSONRPC_H 9 | 10 | typedef struct jsonrpc { 11 | char *id; 12 | char *method; 13 | char *params; 14 | } jsonrpc_t; 15 | 16 | int jsonrpc_parse(char *, jsonrpc_t *); 17 | char *json_find_field(char *, char *); 18 | char *json_extract_val(char *); 19 | #endif 20 | -------------------------------------------------------------------------------- /libs/connslot/strbuf-tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tests for the string buffer abstraction 3 | * 4 | * Copyright (C) Hamish Coleman 5 | * SPDX-License-Identifier: GPL-2.0-only 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "strbuf.h" 14 | 15 | // Tests are silent and return if everything is OK, or abort if issues 16 | void strbuf_tests() { 17 | strbuf_t *p = sb_malloc(9,10); 18 | assert(p); 19 | assert(p->wr_pos==0); 20 | assert(p->capacity==9); 21 | assert(p->capacity_max==10); 22 | 23 | int r; 24 | r = sb_append(p, "abcd", 4); 25 | assert(r==4); 26 | assert(!memcmp(p->str, "abcd", 4)); 27 | 28 | r = sb_append(p, "efgh", 4); 29 | assert(r==8); 30 | assert(!memcmp(p->str, "abcdefgh", 8)); 31 | 32 | r = sb_append(p, "abcd", 4); 33 | assert(r==10); 34 | assert(sb_full(p)); 35 | assert(!memcmp(p->str, "abcdefghab", 10)); 36 | 37 | strbuf_t *p2 = sb_realloc(&p, 5); 38 | assert(p2); 39 | assert(p->wr_pos==4); 40 | assert(p->str[4]==0); 41 | assert(!memcmp(p->str, "abcd", 4)); 42 | 43 | p2 = sb_reappend(&p, "abcdef", 6); 44 | assert(p2); 45 | assert(p->wr_pos==10); 46 | assert(!memcmp(p->str, "abcdabcde", 9)); 47 | 48 | sb_zero(p); 49 | assert(p->wr_pos==0); 50 | assert(p->capacity==10); 51 | 52 | r = sb_printf(p, "0x%02x", 10); 53 | assert(r==4); 54 | assert(r==(int)p->wr_pos); 55 | assert(!strncmp(p->str, "0x0a", 5)); 56 | 57 | r = sb_printf(p, "0x%02x", 20); 58 | assert(r==8); 59 | assert(r==(int)p->wr_pos); 60 | assert(!strncmp(p->str, "0x0a0x14", 9)); 61 | 62 | // This will fail to append the entire string 63 | r = sb_printf(p, "0x%02x", 40); 64 | assert(r==12); 65 | assert(p->wr_pos==8); 66 | assert(!strncmp(p->str, "0x0a0x140", 10)); 67 | 68 | // This print just fits into the buffer 69 | r = sb_printf(p, "Z"); 70 | assert(r==9); 71 | assert(r==(int)p->wr_pos); 72 | assert(!strncmp(p->str, "0x0a0x14Z", 10)); 73 | 74 | // The max capacity is still set to the size at malloc 75 | size_t n = sb_reprintf(&p, "%05i", 1024); 76 | assert((long int)n==-1); 77 | assert(p); 78 | assert(p->wr_pos==9); 79 | 80 | p->capacity_max = 1000; 81 | n = sb_reprintf(&p, "%05i", 1024); 82 | assert(n==14); 83 | assert(p); 84 | assert(p->wr_pos==14); 85 | assert(p->capacity==15); 86 | assert(!strncmp(p->str, "0x0a0x14Z01024", 15)); 87 | 88 | // TODO: could assert on the metrics counter values too 89 | 90 | free(p); 91 | } 92 | 93 | int main() { 94 | printf("Running strbuf tests\n"); 95 | 96 | // Many sizes are acceptable, so this is informational only 97 | printf("sizeof(strbuf_t) = %li\n", sizeof(strbuf_t)); 98 | 99 | strbuf_tests(); 100 | } 101 | -------------------------------------------------------------------------------- /libs/connslot/strbuf.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | * Internal interface definitions for the strbuf abstraction 3 | * 4 | * Copyright (C) Hamish Coleman 5 | * SPDX-License-Identifier: LGPL-2.1-only 6 | */ 7 | 8 | #ifndef STRBUF_H 9 | #define STRBUF_H 1 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /** 18 | * The strbuf type 19 | * 20 | */ 21 | typedef struct strbuf { 22 | unsigned int capacity; //!< The current storage capacity of str[] 23 | unsigned int capacity_max; //!< The largest automatic allowed capacity 24 | unsigned int wr_pos; //!< str[] append position (arriving data) 25 | unsigned int rd_pos; //!< str[] read position (processing data) 26 | bool overflowed; //!< set if the str is overflowed 27 | char str[]; 28 | } strbuf_t; 29 | 30 | /** 31 | * Initialise a memory area to become a strbuf. 32 | * 33 | * @param buf is a strbuf pointer 34 | * @param p is a the pre-defined memory that we will use for the 35 | * strbuf object (must be a known sized object) 36 | */ 37 | #define STRBUF_INIT(buf,p) do { \ 38 | buf = (void *)p; \ 39 | buf->capacity = sizeof(p) - sizeof(strbuf_t); \ 40 | buf->capacity_max = buf->capacity; \ 41 | buf->wr_pos = 0; \ 42 | } while(0) 43 | 44 | void sb_zero(strbuf_t *); 45 | strbuf_t *sb_malloc(size_t, size_t) __attribute__ ((malloc)); 46 | strbuf_t *sb_realloc(strbuf_t **, size_t); 47 | size_t sb_len(strbuf_t *); 48 | ssize_t sb_avail(strbuf_t *); 49 | bool sb_full(strbuf_t *); 50 | bool sb_overflowed(strbuf_t *); 51 | size_t sb_append(strbuf_t *, const void *, ssize_t); 52 | strbuf_t *sb_reappend(strbuf_t **, const void *, size_t); 53 | size_t sb_vprintf(strbuf_t *, const char *, va_list); 54 | size_t sb_printf(strbuf_t *, const char *, ...) 55 | __attribute__ ((format (printf, 2, 3))); 56 | size_t sb_reprintf(strbuf_t **, const char *, ...) 57 | __attribute__ ((format (printf, 2, 3))); 58 | ssize_t sb_read(int, strbuf_t *); 59 | ssize_t sb_write(int, strbuf_t *, int, ssize_t); 60 | void sb_dump(strbuf_t *); 61 | 62 | // Collect some metrics 63 | struct strbuf_metrics { 64 | uint32_t zero; 65 | uint32_t alloc; 66 | uint32_t realloc; 67 | uint32_t realloc_full; 68 | uint32_t append_full; 69 | uint32_t append_trunc; 70 | }; 71 | extern struct strbuf_metrics strbuf_metrics; 72 | 73 | #ifdef METRICS 74 | #define STRBUF_METRIC(n) strbuf_metrics.n++ 75 | #else 76 | #define STRBUF_METRIC(n) 77 | #endif 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /libs/connslot/uncrustify.cfg: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0-only 2 | # 3 | # 4 space indention (never use tabs) 4 | indent_columns = 4 5 | indent_with_tabs = 0 6 | indent_switch_case = 4 7 | 8 | indent_param = 8 9 | 10 | indent_func_call_param = true 11 | 12 | indent_paren_close = 2 13 | -------------------------------------------------------------------------------- /n3n-supernode.8: -------------------------------------------------------------------------------- 1 | .TH n3n-supernode 8 "16 Feb 2025" "version 3" "USER COMMANDS" 2 | .SH NAME 3 | n3n-supernode \- n3n supernode daemon 4 | .SH SYNOPSIS 5 | .B n3n-supernode 6 | [\fIoptions..\fR] [command] [\fIcommand args\fR] 7 | .br 8 | .B n3n-supernode start 9 | [\fIsessionname\fR] 10 | .br 11 | .B n3n-supernode --help 12 | .SH DESCRIPTION 13 | N3N is a peer-to-peer VPN system - it is the LAN you have when you have noLAN. 14 | 15 | The Supernode is a node introduction registry, broadcast conduit and packet 16 | relay node for the n3n system. 17 | 18 | Once it has the full config loaded, the supernode begins listening on the 19 | specified UDP port for node registrations, and other packets to route. The 20 | supernode can service any number of communities and routes packets only between 21 | members of the same community. The supernode does not hold the community 22 | encryption key and so cannot snoop or inject packets into the community. 23 | 24 | Supernode can service a number of n3n communities concurrently. Traffic does 25 | not cross between communities. 26 | 27 | All logging goes to stdout. 28 | 29 | .SH OPTIONS 30 | Some of the most common options also have a shortcut version and you can see 31 | all of them with: 32 | 33 | .RS 34 | .B n3n-supernode help options 35 | .RE 36 | .TP 37 | .SH OPTIONS 38 | .TP 39 | \fB\-O \fR<\fIsection\fR>.<\fIoption\fR>=<\fIvalue\fR> 40 | Sets any config option value. 41 | .TP 42 | \fB\-h\fR, \fB\--help\fR 43 | Show some quick usage notes. 44 | .TP 45 | \fB\-d\fR, \fB\-\-daemon\fR 46 | Fork and run as a daemon, instead of the default of running in foreground. 47 | This is ignored on windows. 48 | .TP 49 | \fB\-v\fR, \fB\-\-verbose\fR 50 | increase logging verbosity 51 | 52 | .SH ALLOWED COMMUNITIES FILE 53 | Specified with \fB\-Osupernode.community_file=\fR option (or in a config file) 54 | This file is a plain text file. Comments are introduced with a hash at the 55 | beginning of the line. A line that begins with an asterisk is a user 56 | authentication definition and adds an allowed user to the most recently defined 57 | community. Allowed communities can be specified with a regular expression. 58 | .PP 59 | Example community file: 60 | .PP 61 | .nf 62 | .RS 63 | # List of allowed communities 64 | mynetwork 65 | netleo 66 | * logan nHWum+r42k1qDXdIeH-WFKeylK5UyLStRzxofRNAgpG 67 | * sister HwHpPrdMft+38tFDDiunUds6927t0+zhCMMkQdJafcC 68 | .RE 69 | .fi 70 | .PP 71 | More details on creating the allowed communities file are found in the 72 | Communities.md and Authentication.md documentation included with this package. 73 | .SH ENVIRONMENT 74 | .TP 75 | .B N3N_FEDERATION 76 | set the federation name so it is not visible at the command line 77 | .SH EXAMPLES 78 | .TP 79 | .B n3n-supernode start -v 80 | Start supernode listening on default UDP port (7654) with verbose output. 81 | .PP 82 | .SH RESTART 83 | When supernode restarts it loses all registration information from associated 84 | edge nodes. It can take up to five minutes for the edge nodes to re-register 85 | and normal traffic flow to resume. 86 | .SH EXIT STATUS 87 | supernode is a daemon and any exit is an error 88 | .SH AUTHORS 89 | .TP 90 | Hamish Coleman 91 | hamish (at) zot.org - n3n maintainer 92 | .TP 93 | Luca Deri 94 | deri (at) ntop.org 95 | .TP 96 | Richard Andrews 97 | andrews (at) ntop.org 98 | .TP 99 | Don Bindner 100 | .SH SEE ALSO 101 | ifconfig(8) edge(8) 102 | .br 103 | the documentation contained in the source code 104 | .br 105 | the extensive documentation found in n3n's \fBdoc/\fR folder 106 | -------------------------------------------------------------------------------- /packages/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Artifacts of the dpkg build 3 | *.buildinfo 4 | -------------------------------------------------------------------------------- /packages/centos: -------------------------------------------------------------------------------- 1 | rpm -------------------------------------------------------------------------------- /packages/lib/systemd/system/n3n-edge.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=n3n edge process 3 | Documentation=man:n3n-edge(8) 4 | After=network-online.target nfw.target 5 | Wants=network-online.target 6 | 7 | [Service] 8 | Type=simple 9 | ExecStartPre= 10 | ExecStart=/usr/sbin/n3n-edge start 11 | Restart=on-abnormal 12 | RestartSec=5 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | Alias= 17 | -------------------------------------------------------------------------------- /packages/lib/systemd/system/n3n-edge@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=n3n edge process, on %I 3 | Documentation=man:n3n-edge(8) 4 | After=network-online.target nfw.target 5 | Wants=network-online.target 6 | 7 | [Service] 8 | Type=simple 9 | ExecStartPre= 10 | ExecStart=/usr/sbin/n3n-edge start %i 11 | Restart=on-abnormal 12 | RestartSec=5 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | Alias= 17 | -------------------------------------------------------------------------------- /packages/lib/systemd/system/n3n-supernode.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=n3n supernode process 3 | Documentation=man:n3n-supernode(8) 4 | After=network-online.target 5 | Wants=network-online.target 6 | 7 | [Service] 8 | Type=simple 9 | User=n3n 10 | Group=n3n 11 | RuntimeDirectory=n3n 12 | ExecStart=/usr/sbin/n3n-supernode start 13 | Restart=on-abnormal 14 | RestartSec=5 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | Alias= 19 | -------------------------------------------------------------------------------- /packages/openwrt/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2021 - ntop.org and contributors 3 | # 4 | 5 | include $(TOPDIR)/rules.mk 6 | 7 | PKG_NAME:=n3n 8 | PKG_RELEASE:=1 9 | 10 | PKG_SOURCE_PROTO:=git 11 | PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz 12 | 13 | 14 | # These are defaults for compiling without any environmental overrides 15 | # (eg, the github action calculates the correct overrides for each build) 16 | PKG_VERSION:=$(BUILD_VERSION) 17 | PKG_SOURCE_URL?=$(BUILD_SOURCE_URL) 18 | PKG_SOURCE_VERSION?=$(BUILD_SOURCE_REF) 19 | PKG_MIRROR_HASH:=skip 20 | 21 | PKG_MAINTAINER:=Hamish Coleman 22 | PKG_LICENSE:=GPL-3.0-only 23 | 24 | # autogen fix 25 | PKG_FIXUP:=autoreconf 26 | 27 | include $(INCLUDE_DIR)/package.mk 28 | 29 | define Package/n3n/Default 30 | SECTION:=net 31 | CATEGORY:=Network 32 | TITLE:=N2N Peer-to-peer VPN 33 | URL:=http://github.com/n42n/n3n 34 | SUBMENU:=VPN 35 | endef 36 | 37 | define Package/n3n-edge 38 | $(call Package/n3n/Default) 39 | TITLE+= client (edge node) 40 | DEPENDS+=+kmod-tun 41 | endef 42 | 43 | define Package/n3n-supernode 44 | $(call Package/n3n/Default) 45 | TITLE+= server (supernode) 46 | endef 47 | 48 | define Package/n3n-edge/description 49 | The client node for the N2N infrastructure 50 | endef 51 | 52 | define Package/n3n-supernode/description 53 | The supernode for the N2N infrastructure 54 | endef 55 | 56 | define Build/Configure 57 | ( cd $(PKG_BUILD_DIR); \ 58 | ./autogen.sh; \ 59 | LDFLAGS=--static ./configure --with-rundir=/var/run ) 60 | endef 61 | 62 | define Package/n3n-edge/conffiles 63 | /etc/n3n/edge.conf 64 | endef 65 | 66 | define Package/n3n-edge/install 67 | $(INSTALL_DIR) $(1)/usr/bin 68 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/scripts/n3nctl $(1)/usr/bin/ 69 | $(INSTALL_DIR) $(1)/usr/sbin 70 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/apps/n3n-edge $(1)/usr/sbin/ 71 | $(INSTALL_DIR) $(1)/etc/init.d 72 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/packages/openwrt/etc/init.d/n3n-edge $(1)/etc/init.d/n3n-edge 73 | $(INSTALL_DIR) $(1)/etc/n3n 74 | $(INSTALL_CONF) $(PKG_BUILD_DIR)/doc/edge.conf.sample $(1)/etc/n3n/edge.conf 75 | endef 76 | 77 | define Package/n3n-supernode/conffiles 78 | /etc/n3n/supernode.conf 79 | endef 80 | 81 | define Package/n3n-supernode/install 82 | $(INSTALL_DIR) $(1)/usr/sbin 83 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/apps/n3n-supernode $(1)/usr/sbin/ 84 | $(INSTALL_DIR) $(1)/etc/init.d 85 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/packages/openwrt/etc/init.d/n3n-supernode $(1)/etc/init.d/n3n-supernode 86 | $(INSTALL_DIR) $(1)/etc/n3n 87 | $(INSTALL_CONF) $(PKG_BUILD_DIR)/doc/supernode.conf.sample $(1)/etc/n3n/supernode.conf 88 | endef 89 | 90 | $(eval $(call BuildPackage,n3n-edge)) 91 | $(eval $(call BuildPackage,n3n-supernode)) 92 | -------------------------------------------------------------------------------- /packages/openwrt/README.md: -------------------------------------------------------------------------------- 1 | ## Prerequisites 2 | 3 | This instructions explain how to build an OpenWRT .ipk package for n3n. 4 | 5 | You will either need to build a full OpenWRT buildchain (See the github 6 | action for building openwrt.yml for some example steps) or have a working 7 | cross-compiling build environment for the OpenWRT version installed into 8 | your device. 9 | 10 | ### Downloading a cross-compiling build environment 11 | 12 | This usually comes down to the following steps: 13 | 14 | 1. Download and extract the SDK toolchain for your device. The toolchain 15 | must match the *exact* OpenWRT version installed in your device. Toolchain 16 | for official OpenWRT images can be downloaded from https://downloads.openwrt.org 17 | 18 | 2. Build the toolchain: run `make menuconfig`, save the configuration, then 19 | run `make` to build the cross compiling tools 20 | 21 | 3. Download the feeds with `./scripts/feeds update -a` 22 | 23 | ## Compilation 24 | 25 | These instructions are for building the current checked out version of the 26 | n3n source (The generally used OpenWRT alternative is to download a tar.gz 27 | file of a specific n3n version, but that is not as suitable for development 28 | or local builds) 29 | 30 | You need both the openwrt repository and the n3n repository checked out 31 | for this. In these instructions, we assume that `openwrt` is the directory 32 | where your openwrt checkout is located and `n3n` is the directory for 33 | the n3n repository. 34 | 35 | ``` 36 | git clone https://github.com/n42n/n3n n3n 37 | N2N_PKG_VERSION=$(n3n/scripts/version.sh) 38 | export N2N_PKG_VERSION 39 | echo $N2N_PKG_VERSION 40 | 41 | cp -r n3n/packages/openwrt openwrt/package/n3n 42 | 43 | cd openwrt 44 | make oldconfig 45 | # In the VPN section, select "m" for n3n-edge and n3n-supernode 46 | 47 | make package/n3n/clean V=s 48 | make package/n3n/prepare USE_SOURCE_DIR=$(realpath ../n3n) V=s 49 | make package/n3n/compile V=s 50 | ``` 51 | 52 | If everything went fine, two ipk will be generated, one for the n3n-edge 53 | and the other for n3n-supernode. They can be found with `find . -name "n3n*.ipk"`, 54 | copied to the target device, and installed with `opkg install`. 55 | 56 | The github action described in `.github/workflows/openwrt.yml` implements 57 | an automated version of the above steps. 58 | 59 | ## Configuration 60 | 61 | The edge node can be started with `/etc/init.d/edge start`. 62 | Its configuration file is `/etc/n3n/edge.conf`. 63 | 64 | The supernode can be started with `/etc/init.d/supernode start`. 65 | Its configuration file is `/etc/n3n/supernode.conf`. 66 | -------------------------------------------------------------------------------- /packages/openwrt/config.bthh5a: -------------------------------------------------------------------------------- 1 | # OpenWrt Configuration snippet 2 | # - will enable building for BT Home Hub 5a 3 | # 4 | CONFIG_TARGET_lantiq=y 5 | CONFIG_TARGET_lantiq_xrx200=y 6 | CONFIG_TARGET_lantiq_xrx200_DEVICE_bt_homehub-v5a=y 7 | 8 | # Would be needed for a full standalone build, but are packages that should 9 | # be available from the distributed openwrt build repository 10 | # CONFIG_PACKAGE_kmod-tun=m 11 | # CONFIG_PACKAGE_libcap=m 12 | -------------------------------------------------------------------------------- /packages/openwrt/config.n3n: -------------------------------------------------------------------------------- 1 | # OpenWrt Configuration snippet 2 | # - will enable building the N2N packages 3 | # 4 | CONFIG_TARGET_lantiq=y 5 | CONFIG_TARGET_lantiq_xrx200=y 6 | CONFIG_TARGET_lantiq_xrx200_DEVICE_bt_homehub-v5a=y 7 | 8 | -------------------------------------------------------------------------------- /packages/openwrt/config.x86: -------------------------------------------------------------------------------- 1 | # OpenWrt Configuration snippet 2 | # - will enable building on x86 target (mainly for build tests) 3 | # 4 | CONFIG_TARGET_x86=y 5 | CONFIG_TARGET_x86_64=y 6 | -------------------------------------------------------------------------------- /packages/openwrt/etc/init.d/n3n-edge: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | START=90 3 | STOP=10 4 | 5 | USE_PROCD=1 6 | PROG=/usr/sbin/n3n-edge 7 | CONFIGFILE=/etc/n3n/edge.conf 8 | 9 | start_service() { 10 | procd_open_instance 11 | procd_set_param command $PROG start $CONFIGFILE 12 | procd_set_param file $CONFIGFILE 13 | procd_set_param respawn 14 | procd_close_instance 15 | } 16 | 17 | stop_service() 18 | { 19 | service_stop $PROG 20 | } 21 | 22 | service_triggers() 23 | { 24 | procd_add_reload_trigger "n3n-edge" 25 | } 26 | -------------------------------------------------------------------------------- /packages/openwrt/etc/init.d/n3n-supernode: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | START=90 3 | STOP=10 4 | 5 | USE_PROCD=1 6 | PROG=/usr/sbin/n3n-supernode 7 | CONFIGFILE=/etc/n3n/supernode.conf 8 | 9 | start_service() { 10 | procd_open_instance 11 | procd_set_param command $PROG start $CONFIGFILE 12 | procd_set_param file $CONFIGFILE 13 | procd_set_param respawn 14 | procd_close_instance 15 | } 16 | 17 | stop_service() 18 | { 19 | service_stop $PROG 20 | } 21 | 22 | service_triggers() 23 | { 24 | procd_add_reload_trigger "n3n-supernode" 25 | } 26 | -------------------------------------------------------------------------------- /packages/rpm/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Change it according to your setup 3 | # 4 | N3N_HOME=$(PWD)/../.. 5 | 6 | VERSION:=$(shell $(N3N_HOME)/scripts/version.sh |tr - _) 7 | ARCH:=$(shell rpmbuild -E '%_arch') 8 | 9 | RPM_PATH=$(HOME)/rpmbuild/RPMS/$(ARCH)/n3n-$(VERSION)-1.$(ARCH).rpm 10 | 11 | # Older RPMs might not prompt for a passphrase 12 | # (Centos8 was mentioned in the old autotooling) 13 | #RPM_SIGN_CMD=rpm --addsign 14 | 15 | # Note: this needs expect installed to work 16 | RPM_SIGN_CMD=./rpm-sign.exp 17 | 18 | all: clean pkg 19 | 20 | pkg: 21 | rpmbuild --define='VERSION ${VERSION}' --define='TOPDIR ${N3N_HOME}' -bb ./n3n.spec 22 | -@$(RPM_SIGN_CMD) $(RPM_PATH) 23 | @echo "" 24 | @echo "Package contents:" 25 | @rpm -qpl $(RPM_PATH) 26 | @echo "The package is now available in $(RPM_PATH)" 27 | 28 | distclean: 29 | echo "dummy distclean" 30 | 31 | install: 32 | echo "dummy install" 33 | 34 | clean: 35 | rm -rf *~ *rpm 36 | -------------------------------------------------------------------------------- /packages/rpm/rpm-sign.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | ### rpm-sign.exp -- Sign RPMs by sending the passphrase. 4 | 5 | spawn rpm --addsign {*}$argv 6 | expect -exact "Enter pass phrase: " 7 | send -- "\r" 8 | expect eof 9 | 10 | ## end of rpm-sign.exp 11 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | This directory contains executables that are not compiled. Some of these may 2 | end up installed for use by end users, but many of them are for use during 3 | development, builds and tests. 4 | 5 | Nothing in this directory should need compiling to use and they should be 6 | written such that they do not need configuring (e.g: they might probe several 7 | directories for their requirements) 8 | 9 | See the [Scripts Documentation](../docs/Scripts.md) for further details 10 | -------------------------------------------------------------------------------- /scripts/hack_fakeautoconf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (C) Hamish Coleman 4 | # SPDX-License-Identifier: GPL-2.0-only 5 | # 6 | # Specifically for windows, where installing autoconf looks suspiciously 7 | # like boiling the ocean. 8 | 9 | cat <include/config.h.in 10 | // Created by hack fake autoconf for windows 11 | // not actually a config input 12 | EOF 13 | 14 | cat <include/config.h 15 | // Created by hack fake autoconf for windows 16 | // not actually a config header 17 | EOF 18 | 19 | cat <configure 20 | #!/bin/sh 21 | echo Created by hack fake autoconf for windows 22 | echo not a confgure script 23 | exit 1 24 | EOF 25 | chmod a+x configure 26 | 27 | cat >config.mak <"$1.indent" 36 | ## if [ $? -ne 0 ]; then 37 | ## echo "Error while formatting \"$1\"" 38 | ## RESULT=1 39 | ## return 40 | ## fi 41 | ## diff -u "$1" "$1.indent" 42 | ## if [ $? -ne 0 ]; then 43 | ## RESULT=1 44 | ## fi 45 | ## } 46 | 47 | indentOne() { 48 | IFILE="$1" 49 | if [ "$INPLACE" -eq 0 ]; then 50 | OFILE="$1.indent" 51 | rm -f "$OFILE" 52 | CLEAN=true 53 | else 54 | OFILE="$1" 55 | CLEAN=false 56 | fi 57 | if ! uncrustify -c uncrustify.cfg -f "$IFILE" -o "$OFILE"; then 58 | echo "Error while formatting \"$1\"" 59 | RESULT=1 60 | return 61 | fi 62 | if ! diff -u "$IFILE" "$OFILE"; then 63 | RESULT=1 64 | fi 65 | 66 | $CLEAN && rm -f "$OFILE" 67 | } 68 | 69 | indentDir() { 70 | for i in $(find "$1" -type f -name \*.h -o -name \*.c |sort); do 71 | echo "$i" | grep -E "$EXCLUDE" >/dev/null || indentOne "$i" 72 | done 73 | } 74 | 75 | RESULT=0 76 | while [ -n "$1" ]; do 77 | if [ -d "$1" ]; then 78 | indentDir "$1" 79 | else 80 | indentOne "$1" 81 | fi 82 | shift 83 | done 84 | exit $RESULT 85 | -------------------------------------------------------------------------------- /scripts/n3n-gateway.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This is a sample script to route all the host traffic towards a remote 4 | # gateway, which is reacheable via the n3n virtual interface. 5 | # 6 | # This assumes the n3n connection is already been established and the 7 | # VPN gateway can be pinged by this host. 8 | # 9 | 10 | ####################################################### 11 | # CONFIG 12 | ####################################################### 13 | 14 | # The IP address of the gateway through the n3n interface 15 | N2N_GATEWAY="192.168.100.1" 16 | 17 | # The IP address of the supernode as configured in n3n 18 | N2N_SUPERNODE="1.2.3.4" 19 | 20 | # The n3n interface name 21 | N2N_INTERFACE="n3n0" 22 | 23 | # The DNS server to use. Must be a public DNS or a DNS located on the 24 | # N2N virtual network, otherwise DNS query information will be leaked 25 | # outside the VPN. 26 | DNS_SERVER="8.8.8.8" 27 | 28 | ####################################################### 29 | # END CONFIG 30 | ####################################################### 31 | 32 | if [[ $UID -ne 0 ]]; then 33 | echo "This script must be run as root" 34 | exit 1 35 | fi 36 | 37 | if ! ip route get $N2N_GATEWAY | grep -q $N2N_INTERFACE ; then 38 | echo "Cannot reach the gateway ($N2N_GATEWAY) via $N2N_INTERFACE. Is edge running?" 39 | exit 1 40 | fi 41 | 42 | # Determine the current internet gateway 43 | internet_gateway=$(ip route get 8.8.8.8 | head -n1 | awk '{ print $3 }') 44 | 45 | # Backup the DNS resolver configuration and use the specified server 46 | cp /etc/resolv.conf /etc/resolv.conf.my_bak 47 | echo "Using DNS server $DNS_SERVER" 48 | echo "nameserver $DNS_SERVER" > /etc/resolv.conf 49 | 50 | # The public IP of the supernode must be reachable via the internet gateway 51 | # Whereas all the other traffic will go through the new VPN gateway. 52 | ip route add $N2N_SUPERNODE via "$internet_gateway" 53 | ip route del default 54 | echo "Forwarding traffic via $N2N_GATEWAY" 55 | ip route add default via $N2N_GATEWAY 56 | 57 | function stopService { 58 | echo "Deleting custom routes" 59 | ip route del default 60 | ip route del $N2N_SUPERNODE via "$internet_gateway" 61 | 62 | echo "Restoring original gateway $internet_gateway" 63 | ip route add default via "$internet_gateway" 64 | 65 | echo "Restoring original DNS" 66 | mv /etc/resolv.conf.my_bak /etc/resolv.conf 67 | 68 | exit 0 69 | } 70 | 71 | # setup signal handlers 72 | trap "stopService" SIGHUP SIGINT SIGTERM 73 | 74 | # enter wait loop 75 | echo "VPN is now up" 76 | while :; do sleep 300; done 77 | -------------------------------------------------------------------------------- /scripts/test_builtin_edge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) Hamish Coleman 4 | # SPDX-License-Identifier: GPL-3.0-only 5 | # 6 | # Run builtin commands to generate test data 7 | # 8 | 9 | [ -z "$BINDIR" ] && BINDIR=. 10 | 11 | docmd() { 12 | echo "### test: $*" 13 | "$@" 14 | local S=$? 15 | echo 16 | return $S 17 | } 18 | 19 | docmd "$BINDIR"/apps/n3n-edge test hashing 20 | 21 | docmd "$BINDIR"/apps/n3n-edge test config roundtrip 22 | 23 | docmd "$BINDIR"/apps/n3n-edge tools keygen logan 007 24 | docmd "$BINDIR"/apps/n3n-edge tools keygen secretFed 25 | -------------------------------------------------------------------------------- /scripts/test_harness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (C) Hamish Coleman 4 | # SPDX-License-Identifier: GPL-3.0-only 5 | # 6 | # Run with the name of a test list file. 7 | # 8 | # This expects to find the tests in the tools dir or scripts dir and the 9 | # expected results in the tests dir. 10 | 11 | # boilerplate so we can support whaky cmake dirs 12 | [ -z "$TOPDIR" ] && TOPDIR="." 13 | [ -z "$BINDIR" ] && BINDIR="." 14 | export TOPDIR 15 | export BINDIR 16 | 17 | if [ -z "$1" ]; then 18 | echo need test list filename 19 | exit 1 20 | fi 21 | TESTLIST="$1" 22 | LISTDIR=$(dirname "$TESTLIST") 23 | 24 | TESTS=$(sed -e "s/#.*//" "$TESTLIST") 25 | 26 | # Actually run the tests 27 | for i in $TESTS; do 28 | # Look in several places for the test program 29 | if [ -e "$BINDIR/$i" ]; then 30 | TEST="$BINDIR/$i" 31 | elif [ -e "$BINDIR/tools/$i" ]; then 32 | TEST="$BINDIR/tools/$i" 33 | elif [ -e "$LISTDIR/../scripts/$i" ]; then 34 | TEST="$LISTDIR/../scripts/$i" 35 | else 36 | echo "Could not find test $i" 37 | exit 1 38 | fi 39 | 40 | if [ ! -e "$LISTDIR/$i.expected" ]; then 41 | echo "Could not find testdata $LISTDIR/$i.expected" 42 | exit 1 43 | fi 44 | 45 | echo "$TEST >$LISTDIR/$i.out" 46 | set -e 47 | "$TEST" >"$LISTDIR/$i.out" 48 | diff -wu "$LISTDIR/$i.expected" "$LISTDIR/$i.out" 49 | set +e 50 | done 51 | -------------------------------------------------------------------------------- /scripts/test_integration_edge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) Hamish Coleman 4 | # SPDX-License-Identifier: GPL-3.0-only 5 | # 6 | # Do some quick tests via the Json API against the edge 7 | # 8 | 9 | AUTH=n3n 10 | 11 | # boilerplate so we can support whaky cmake dirs 12 | [ -z "$TOPDIR" ] && TOPDIR=. 13 | [ -z "$BINDIR" ] && BINDIR=. 14 | 15 | docmd() { 16 | echo "### test: $*" 17 | "$@" 18 | local S=$? 19 | echo 20 | return $S 21 | } 22 | 23 | # We dont have perms for writing to the /run dir, TODO: improve this 24 | sudo mkdir -p /run/n3n 25 | sudo chown "$USER" /run/n3n 26 | 27 | # start a supernode 28 | docmd "${BINDIR}"/apps/n3n-supernode start ci_sn -v --daemon 29 | 30 | # Start the edge in the background 31 | docmd sudo "${BINDIR}"/apps/n3n-edge start ci_edge1 \ 32 | --daemon \ 33 | -l localhost:7654 \ 34 | -c test \ 35 | -Odaemon.userid="$USER" \ 36 | 1>&2 37 | 38 | # TODO: probe the api endpoint, waiting for both the supernode and edge to be 39 | # available? 40 | sleep 0.1 41 | 42 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 get_communities 43 | 44 | echo "### test: ${TOPDIR}/scripts/n3nctl -s ci_edge1 get_packetstats" 45 | "${TOPDIR}"/scripts/n3nctl -s ci_edge1 get_packetstats |jq '.[0:5]' 46 | # this is filtering out the type=multicast_drop line as that has a changing 47 | # number of packets counted 48 | echo 49 | 50 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 get_edges --raw |grep -v "last_seen" 51 | 52 | # TODO: 53 | # docmd ${TOPDIR}/scripts/n3nctl supernodes --raw 54 | # - need fixed mac address 55 | # - need to mask out: 56 | # - version string 57 | # - last_seen timestamp 58 | # - uptime 59 | 60 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 get_verbose 61 | 62 | # Test with bad auth 63 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 set_verbose 1 2>/dev/null 64 | echo $? 65 | 66 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 -k $AUTH set_verbose 1 67 | 68 | # stop them both 69 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 -k $AUTH stop 70 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn -k $AUTH stop 71 | 72 | -------------------------------------------------------------------------------- /scripts/test_integration_edge_tcp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) Hamish Coleman 4 | # SPDX-License-Identifier: GPL-3.0-only 5 | # 6 | # Do some quick tests via the Json API against the edge 7 | # 8 | 9 | AUTH=n3n 10 | 11 | # boilerplate so we can support whaky cmake dirs 12 | [ -z "$TOPDIR" ] && TOPDIR=. 13 | [ -z "$BINDIR" ] && BINDIR=. 14 | 15 | docmd() { 16 | echo "### test: $*" 17 | "$@" 18 | local S=$? 19 | echo 20 | return $S 21 | } 22 | 23 | # We dont have perms for writing to the /run dir, TODO: improve this 24 | sudo mkdir -p /run/n3n 25 | sudo chown "$USER" /run/n3n 26 | 27 | # start a supernode 28 | docmd "${BINDIR}"/apps/n3n-supernode start ci_sn \ 29 | -v \ 30 | --daemon \ 31 | -Osupernode.macaddr=02:00:00:55:00:00 32 | 33 | # Start the edge in the background 34 | docmd sudo "${BINDIR}"/apps/n3n-edge start ci_edge1 \ 35 | --daemon \ 36 | -l localhost:7654 \ 37 | -c test \ 38 | -Oconnection.bind=:7700 \ 39 | -Oconnection.connect_tcp=true \ 40 | -Oconnection.description=ci_edge1 \ 41 | -Odaemon.userid="$USER" \ 42 | -Otuntap.macaddr=02:00:00:77:00:00 \ 43 | 1>&2 44 | 45 | # TODO: probe the api endpoint, waiting for both the supernode and edge to be 46 | # available? 47 | sleep 0.1 48 | 49 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 get_communities 50 | 51 | echo "### test: ${TOPDIR}/scripts/n3nctl -s ci_edge1 get_packetstats" 52 | "${TOPDIR}"/scripts/n3nctl -s ci_edge1 get_packetstats |jq '.[0:5]' 53 | # this is filtering out the type=multicast_drop line as that has a changing 54 | # number of packets counted 55 | echo 56 | 57 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 get_edges --raw |grep -v "last_seen" 58 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn get_edges --raw |grep -v -E "last_seen|time_alloc" 59 | 60 | 61 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 get_supernodes --raw 62 | 63 | # stop them both 64 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 -k $AUTH stop 65 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn -k $AUTH stop 66 | 67 | -------------------------------------------------------------------------------- /scripts/test_integration_packets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) Hamish Coleman 4 | # SPDX-License-Identifier: GPL-3.0-only 5 | # 6 | # Send known packets to the daemons and allow confirming the expected replies 7 | # 8 | 9 | AUTH=n3n 10 | 11 | # boilerplate so we can support whaky cmake dirs 12 | [ -z "$TOPDIR" ] && TOPDIR=. 13 | [ -z "$BINDIR" ] && BINDIR=. 14 | 15 | docmd() { 16 | echo "### test: $*" 17 | "$@" 18 | local S=$? 19 | echo 20 | return $S 21 | } 22 | 23 | # We dont have perms for writing to the /run dir, TODO: improve this 24 | sudo mkdir -p /run/n3n 25 | sudo chown "$USER" /run/n3n 26 | 27 | # start a supernode 28 | echo -e "### supernode started\n" 29 | apps/n3n-supernode \ 30 | -vv \ 31 | -Oconnection.bind=7001 \ 32 | -Osupernode.macaddr=02:00:00:00:00:01 \ 33 | start ci_sn1 1>&2 & 34 | 35 | sleep 0.1 36 | 37 | # Just request a PONG packet. Done before the registration binds us 38 | docmd "${BINDIR}"/scripts/test_packets \ 39 | --bind 7000 \ 40 | -s localhost:7001 \ 41 | test_QUERY_PEER_ping 42 | 43 | # Register a mac address with the supernode 44 | docmd "${BINDIR}"/scripts/test_packets \ 45 | --bind 7000 \ 46 | -s localhost:7001 \ 47 | test_REGISTER_SUPER 48 | 49 | # Confirm that the registration is visible 50 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 get_edges --raw |grep -v last_seen |grep -v time_alloc 51 | 52 | # Once registered, we can query for that registration 53 | docmd "${TOPDIR}"/scripts/test_packets \ 54 | --bind 7000 \ 55 | -s localhost:7001 \ 56 | test_QUERY_PEER 57 | 58 | # Since we are bound to the same udp port as the registration, when we 59 | # send a register to that, the supernode forwards it to us - as we are 60 | # listening on that registered port, we get the reply 61 | docmd "${TOPDIR}"/scripts/test_packets \ 62 | --bind 7000 \ 63 | -s localhost:7001 \ 64 | test_REGISTER 65 | 66 | # Send a packet to the registered mac, expect it echoed back 67 | docmd "${TOPDIR}"/scripts/test_packets \ 68 | --bind 7000 \ 69 | -s localhost:7001 \ 70 | test_PACKET 71 | 72 | 73 | docmd "${BINDIR}"/scripts/test_packets \ 74 | --bind 7000 \ 75 | -s localhost:7001 \ 76 | --timeout 0 \ 77 | test_UNREGISTER_SUPER 78 | 79 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 get_edges --raw 80 | 81 | # TCP 82 | # 83 | docmd "${BINDIR}"/scripts/test_packets \ 84 | --tcp \ 85 | --bind 7000 \ 86 | -s localhost:7001 \ 87 | test_QUERY_PEER_ping 88 | 89 | # TODO: 90 | # - run all the same tests above but that needs a persistant TCP connection 91 | # - remember that since we bound the port to TCP/7000 that becomes busy until 92 | # the TIME-WAIT period ends 93 | 94 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 -k $AUTH stop 95 | -------------------------------------------------------------------------------- /scripts/test_integration_supernode.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (C) Hamish Coleman 4 | # SPDX-License-Identifier: GPL-3.0-only 5 | # 6 | # Do some quick tests via the Json API against the supernode 7 | # 8 | 9 | AUTH=n3n 10 | 11 | # boilerplate so we can support whaky cmake dirs 12 | [ -z "$TOPDIR" ] && TOPDIR=. 13 | [ -z "$BINDIR" ] && BINDIR=. 14 | 15 | docmd() { 16 | echo "### test: $*" 17 | "$@" 18 | echo 19 | } 20 | 21 | # We dont have perms for writing to the /run dir, TODO: improve this 22 | sudo mkdir -p /run/n3n 23 | sudo chown "$USER" /run/n3n 24 | 25 | # start it running in the background 26 | docmd "${BINDIR}"/apps/n3n-supernode start ci_sn1 \ 27 | --daemon \ 28 | -Oconnection.bind=7001 \ 29 | -Osupernode.macaddr=02:00:00:00:70:01 \ 30 | -Osupernode.peer=localhost:7002 31 | docmd "${BINDIR}"/apps/n3n-supernode start ci_sn2 \ 32 | --daemon \ 33 | -Oconnection.bind=7002 \ 34 | -Osupernode.macaddr=02:00:00:00:70:02 \ 35 | -Osupernode.peer=localhost:7001 36 | 37 | # TODO: probe the api endpoint, waiting for the supernode to be available? 38 | sleep 0.1 39 | 40 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 get_communities 41 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn2 get_communities 42 | 43 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 get_packetstats 44 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn2 get_packetstats 45 | 46 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 get_edges --raw | grep -vE "last_seen|time_alloc" 47 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn2 get_edges --raw | grep -vE "last_seen|time_alloc" 48 | 49 | # Test with bad auth 50 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 set_verbose 1 51 | echo $? 52 | 53 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 get_verbose 54 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 -k $AUTH set_verbose 1 55 | 56 | # stop it 57 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn1 -k $AUTH stop 58 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn2 -k $AUTH stop 59 | -------------------------------------------------------------------------------- /scripts/test_integration_webui.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) Hamish Coleman 4 | # SPDX-License-Identifier: GPL-3.0-only 5 | # 6 | # Do some quick tests via the http Web UI against the edge 7 | # 8 | 9 | AUTH=n3n 10 | 11 | # boilerplate so we can support whaky cmake dirs 12 | [ -z "$TOPDIR" ] && TOPDIR=. 13 | [ -z "$BINDIR" ] && BINDIR=. 14 | 15 | docmd() { 16 | echo "### test: $*" 17 | "$@" 18 | local S=$? 19 | echo 20 | return $S 21 | } 22 | 23 | # We dont have perms for writing to the /run dir, TODO: improve this 24 | sudo mkdir -p /run/n3n 25 | sudo chown "$USER" /run/n3n 26 | 27 | # start a supernode 28 | docmd "${BINDIR}"/apps/n3n-supernode start ci_sn \ 29 | -v \ 30 | --daemon \ 31 | -Osupernode.macaddr=02:00:00:55:00:00 32 | 33 | # Start the edge in the background 34 | docmd sudo "${BINDIR}"/apps/n3n-edge start ci_edge1 \ 35 | --daemon \ 36 | -l localhost:7654 \ 37 | -c test \ 38 | -Oconnection.bind=:7700 \ 39 | -Oconnection.description=ci_edge1 \ 40 | -Odaemon.userid="$USER" \ 41 | -Otuntap.macaddr=02:00:00:77:00:00 \ 42 | 1>&2 43 | 44 | # TODO: probe the api endpoint, waiting for both the supernode and edge to be 45 | # available? 46 | sleep 0.1 47 | 48 | docmd curl --unix-socket /run/n3n/ci_edge1/mgmt http://x/ -o /tmp/index.html 49 | docmd diff -u src/management_index.html /tmp/index.html 50 | 51 | docmd curl --unix-socket /run/n3n/ci_edge1/mgmt http://x/script.js -o /tmp/script.js 52 | docmd diff -u src/management_script.js /tmp/script.js 53 | 54 | # stop them both 55 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_edge1 -k $AUTH stop 56 | docmd "${TOPDIR}"/scripts/n3nctl -s ci_sn -k $AUTH stop 57 | 58 | -------------------------------------------------------------------------------- /scripts/version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (C) Hamish Coleman 4 | # SPDX-License-Identifier: GPL-3.0-only 5 | # 6 | # Output the current version number 7 | # 8 | 9 | usage() { 10 | echo "Usage: $0 [date|short|hash]" 11 | echo 12 | echo "Determine the correct version number for the current build" 13 | exit 1 14 | } 15 | 16 | # We assume this script is in the TOPDIR/scripts directory and use that 17 | # to find any other files we need 18 | TOPDIR=$(dirname "$0")/.. 19 | 20 | VER_FILE_SHORT=$(cat "${TOPDIR}/VERSION") 21 | 22 | if [ -d "$TOPDIR/.git" ]; then 23 | # If there is a .git directory in our TOPDIR, then this is assumed to be 24 | # real git checkout 25 | 26 | cd "$TOPDIR" || exit 1 27 | 28 | VER_GIT_SHORT=$(git describe --abbrev=0) 29 | 30 | if [ "$VER_FILE_SHORT" != "$VER_GIT_SHORT" ]; then 31 | echo "WARNING: VERSION file does not match tag version ($VER_FILE_SHORT != $VER_GIT_SHORT)" 1>&2 32 | fi 33 | 34 | VER_SHORT="$VER_GIT_SHORT" 35 | VER_HASH=$(git rev-parse --short HEAD) 36 | VER=$(git describe --abbrev=7 --dirty) 37 | 38 | if git diff --quiet; then 39 | # In a clean build dir, use the last commit date 40 | DATE=$(git log -1 --format=%cd) 41 | else 42 | # if dirty, use the current date 43 | DATE=$(date) 44 | fi 45 | else 46 | # If there is no .git directory in our TOPDIR, we fall back on relying on 47 | # the VERSION file 48 | 49 | echo "WARNING: no .git dir, versions are just guesses" 1>&2 50 | 51 | VER_SHORT="$VER_FILE_SHORT" 52 | VER_HASH="unknown" 53 | VER="$VER_FILE_SHORT" 54 | DATE=$(date) 55 | fi 56 | 57 | case "$1" in 58 | date) 59 | echo "$DATE" 60 | ;; 61 | hash) 62 | echo "$VER_HASH" 63 | ;; 64 | short) 65 | echo "$VER_SHORT" 66 | ;; 67 | "") 68 | echo "$VER" 69 | ;; 70 | *) 71 | usage 72 | ;; 73 | esac 74 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Generated files 3 | management_index.html.h 4 | management_script.js.h 5 | -------------------------------------------------------------------------------- /src/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Base64 decoder 6 | * 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "base64.h" 13 | 14 | static int letter2number (const char ch) { 15 | if(ch >= 'A' && ch <= 'Z') { 16 | return ch-'A'; 17 | } 18 | if(ch >= 'a' && ch <= 'z') { 19 | return ch-'a'+26; 20 | } 21 | if(ch >= '0' && ch <= '9') { 22 | return ch-'0'+52; 23 | } 24 | if(ch == '+') { 25 | return 62; 26 | } 27 | if(ch == '/') { 28 | return 63; 29 | } 30 | return -1; 31 | } 32 | 33 | char *base64decode (const char *in) { 34 | int len = ((strlen(in) / 4) * 3) +1; 35 | char *out = malloc(len); 36 | if(!out) { 37 | return NULL; 38 | } 39 | 40 | char *p = out; 41 | while(len) { 42 | int i1 = letter2number(*in++); 43 | int i2 = letter2number(*in++); 44 | int i3 = letter2number(*in++); 45 | int i4 = letter2number(*in++); 46 | 47 | if(i1 == -1) return NULL; 48 | if(i2 == -1) return NULL; 49 | 50 | *p++ = (i1 << 2) | (i2 >> 4); 51 | len--; 52 | 53 | if(i3 == -1) break; 54 | 55 | *p++ = (i2 << 4) | (i3 >> 2); 56 | len--; 57 | 58 | if(i4 == -1) break; 59 | 60 | *p++ = (i3 << 6) | (i4); 61 | len--; 62 | } 63 | *p = 0; 64 | return out; 65 | } 66 | -------------------------------------------------------------------------------- /src/base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Base64 decoder internal definitions 6 | * 7 | */ 8 | 9 | #ifndef _BASE64_H_ 10 | #define _BASE64_H_ 11 | 12 | char *base64decode (const char *in); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/edge_utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | */ 5 | 6 | #ifndef _EDGE_UTILS_H_ 7 | #define _EDGE_UTILS_H_ 8 | 9 | #include 10 | 11 | #include "pktbuf.h" // for n3n_pktbuf 12 | 13 | // Forward declare so that this header can stay small 14 | struct n3n_runtime_data; 15 | 16 | void edge_read_from_tap (struct n3n_runtime_data *eee); 17 | 18 | void edge_read_proto3_udp (struct n3n_runtime_data *eee, 19 | SOCKET sock, 20 | struct n3n_pktbuf *pktbuf, 21 | time_t now); 22 | void edge_read_proto3_tcp (struct n3n_runtime_data *eee, 23 | SOCKET sock, 24 | uint8_t *pktbuf, 25 | ssize_t pktbuf_len, 26 | time_t now); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/hexdump.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not see see 17 | * 18 | */ 19 | 20 | 21 | #include // for fhexdump 22 | #include // for uint8_t 23 | #include // for fprintf, FILE 24 | 25 | 26 | void fhexdump (unsigned int display_addr, void *in, int size, FILE *stream) { 27 | uint8_t *p = in; 28 | 29 | while(size>0) { 30 | int i; 31 | 32 | fprintf(stream, "%03x: ", display_addr); 33 | 34 | for(i = 0; i < 16; i++) { 35 | if(i < size) { 36 | fprintf(stream, "%02x", p[i]); 37 | } else { 38 | fprintf(stream, " "); 39 | } 40 | if(i==7) { 41 | fprintf(stream, " "); 42 | } else { 43 | fprintf(stream, " "); 44 | } 45 | } 46 | fprintf(stream, " |"); 47 | 48 | for(i = 0; i < 16; i++) { 49 | if(i < size) { 50 | char ch = p[i]; 51 | if(ch>=0x20 && ch<=0x7e) { 52 | fprintf(stream, "%c", ch); 53 | } else { 54 | fprintf(stream, " "); 55 | } 56 | } 57 | } 58 | fprintf(stream, "|\n"); 59 | 60 | size -= 16; 61 | display_addr += 16; 62 | p += 16; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/initfuncs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Wrapper to call initfuncs 6 | */ 7 | 8 | // prototype any internal (non-public) initfuncs (always sorted!) 9 | void n3n_initfuncs_conffile_defs (); 10 | void n3n_initfuncs_mainloop (); 11 | void n3n_initfuncs_metrics (); 12 | void n3n_initfuncs_pearson (); 13 | void n3n_initfuncs_peer_info (); 14 | void n3n_initfuncs_pktbuf (); 15 | void n3n_initfuncs_random (); 16 | void n3n_initfuncs_resolve (); 17 | void n3n_initfuncs_transform (); 18 | void n3n_initfuncs_win32 (); 19 | 20 | void n3n_deinitfuncs_config (); 21 | void n3n_deinitfuncs_mainloop (); 22 | void n3n_deinitfuncs_pktbuf (); 23 | void n3n_deinitfuncs_resolve (); 24 | 25 | void n3n_initfuncs () { 26 | // TODO: 27 | // - ideally, these functions would all be defined statically as 28 | // constructors within their own object file, but we need to reference 29 | // them externally or the linker will never link that object 30 | 31 | // (must be first because windows is crazy) 32 | #ifdef _WIN32 33 | n3n_initfuncs_win32(); 34 | #endif 35 | 36 | // (sorted list) 37 | n3n_initfuncs_conffile_defs(); 38 | n3n_initfuncs_mainloop(); 39 | n3n_initfuncs_metrics(); 40 | n3n_initfuncs_pearson(); 41 | n3n_initfuncs_peer_info(); 42 | n3n_initfuncs_pktbuf(); 43 | n3n_initfuncs_random(); 44 | n3n_initfuncs_resolve(); 45 | n3n_initfuncs_transform(); 46 | } 47 | 48 | void n3n_deinitfuncs () { 49 | // 50 | 51 | // (sorted list) 52 | n3n_deinitfuncs_config(); 53 | n3n_deinitfuncs_mainloop(); 54 | n3n_deinitfuncs_pktbuf(); 55 | n3n_deinitfuncs_resolve(); 56 | } 57 | -------------------------------------------------------------------------------- /src/logging.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-25 Hamish Coleman 4 | * 5 | * SPDX-License-Identifier: GPL-3.0-only 6 | * 7 | */ 8 | 9 | #include 10 | #include // for va_end, va_list, va_start 11 | #include // for snprinf 12 | #include // for getenv 13 | #include // for strlen 14 | #include // for time_t 15 | 16 | #ifdef _WIN32 17 | #else 18 | #include // for closelog, openlog, syslog, LOG_DAEMON 19 | #endif 20 | 21 | static int traceLevel = 2 /* NORMAL */; 22 | static int useSyslog = 0; 23 | static int syslog_opened = 0; 24 | static FILE *traceFile = NULL; 25 | static int output_dateprefix = -1; // initially "unknown" 26 | 27 | #ifdef _WIN32 28 | // Some dummy definitions to make windows compiling simpler 29 | #define LOG_PID -1 30 | #define LOG_DAEMON -2 31 | #define LOG_INFO -3 32 | void closelog () { 33 | return; 34 | } 35 | void openlog (char *s, int a, int b) { 36 | return; 37 | } 38 | void syslog (int a, char *fmt, ...) { 39 | return; 40 | } 41 | #endif 42 | 43 | int getTraceLevel () { 44 | 45 | return(traceLevel); 46 | } 47 | 48 | void setTraceLevel (int level) { 49 | 50 | traceLevel = level; 51 | } 52 | 53 | void setUseSyslog (int use_syslog) { 54 | 55 | useSyslog = use_syslog; 56 | } 57 | 58 | void closeTraceFile () { 59 | 60 | if((traceFile != NULL) && (traceFile != stdout)) { 61 | fclose(traceFile); 62 | } 63 | if(useSyslog && syslog_opened) { 64 | closelog(); 65 | syslog_opened = 0; 66 | } 67 | } 68 | 69 | #define N2N_TRACE_DATESIZE 32 70 | void _traceEvent (int eventTraceLevel, char* file, int line, char * format, ...) { 71 | va_list va_ap; 72 | 73 | if(eventTraceLevel > traceLevel) { 74 | return; 75 | } 76 | 77 | char buf[1024]; 78 | char *extra_msg = ""; 79 | 80 | va_start(va_ap, format); 81 | int size = vsnprintf(buf, sizeof(buf) - 1, format, va_ap); 82 | va_end(va_ap); 83 | 84 | if(size > (sizeof(buf)-1)) { 85 | // truncation has occured 86 | buf[sizeof(buf)-1] = 0; 87 | } 88 | 89 | if(eventTraceLevel == TRACE_ERROR ) { 90 | extra_msg = "ERROR: "; 91 | } else if(eventTraceLevel == TRACE_WARNING ) { 92 | extra_msg = "WARNING: "; 93 | } 94 | 95 | // Remove trailing newlines 96 | while(buf[strlen(buf) - 1] == '\n') { 97 | buf[strlen(buf) - 1] = '\0'; 98 | } 99 | 100 | if(useSyslog) { 101 | if(!syslog_opened) { 102 | openlog("n3n", LOG_PID, LOG_DAEMON); 103 | syslog_opened = 1; 104 | } 105 | 106 | syslog(LOG_INFO, "[%s:%i] %s%s", file, line, extra_msg, buf); 107 | return; 108 | } else { 109 | if(output_dateprefix == -1) { 110 | char *stream = getenv("JOURNAL_STREAM"); 111 | if(stream == NULL) { 112 | output_dateprefix = 1; 113 | } else { 114 | // If we are outputting via the journald, avoid double dates 115 | output_dateprefix = 0; 116 | } 117 | } 118 | 119 | char theDate[N2N_TRACE_DATESIZE] = ""; 120 | if(output_dateprefix == 1) { 121 | time_t theTime = time(NULL); 122 | strftime(theDate, N2N_TRACE_DATESIZE, "%d/%b/%Y %H:%M:%S ", localtime(&theTime)); 123 | } 124 | 125 | if(traceFile == NULL) { 126 | traceFile = stderr; 127 | } 128 | 129 | fprintf(traceFile, "%s[%s:%d] %s%s\n", theDate, file, line, extra_msg, buf); 130 | fflush(traceFile); 131 | return; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/management.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Internal interface definitions for the management interfaces 6 | * 7 | * This header is not part of the public library API and is thus not in 8 | * the public include folder 9 | */ 10 | 11 | #ifndef MANAGEMENT_H 12 | #define MANAGEMENT_H 1 13 | 14 | #include // for conn_t 15 | #include // for strbuf_t 16 | #include // For the n3n_runtime_data 17 | #include 18 | #include // for size_t 19 | #include // for uint64_t 20 | #include // for ssize_t 21 | 22 | #include "n2n_define.h" // for n2n_event_topic 23 | 24 | struct n3n_runtime_data; 25 | 26 | #ifdef _WIN32 27 | #include 28 | #else 29 | #include // for sockaddr, sockaddr_storage, socklen_t 30 | #endif 31 | 32 | void mgmt_event_post (const enum n3n_event_topic topic, const int data0, const void *data1); 33 | void mgmt_api_handler (struct n3n_runtime_data *, conn_t *); 34 | #endif 35 | -------------------------------------------------------------------------------- /src/management_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | n3n edge management 4 | 5 | 6 | 7 | 8 | 13 |
Last Updated: 9 |
10 |
11 | 12 |
Logging Verbosity: 14 | 15 |
16 |
17 | 18 | 19 |
20 |
21 |
22 |
23 | Edges/Peers: 24 |
25 |
26 | Supernodes: 27 |
28 |
29 |
30 |
31 |
32 | 33 | 34 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/management_script.js: -------------------------------------------------------------------------------- 1 | var verbose=-1; 2 | var jsonrpc_id=1; // incremented on each request 3 | 4 | function result2verbose(id, unused, data) { 5 | verbose = data; 6 | let div = document.getElementById(id); 7 | div.innerHTML=verbose; 8 | } 9 | 10 | function rows2keyvalue(id, keys, data) { 11 | let s = "" 12 | data.forEach((row) => { 13 | keys.forEach((key) => { 14 | if (key in row) { 15 | s += "
" + key + "" + row[key]; 16 | } 17 | }); 18 | }); 19 | s += "
" 20 | let div = document.getElementById(id); 21 | div.innerHTML=s 22 | } 23 | 24 | function rows2keyvalueall(id, unused, data) { 25 | let s = "" 26 | Object.keys(data).forEach((key) => { 27 | s += "
" + key + "" + data[key]; 28 | }); 29 | 30 | s += "
" 31 | let div = document.getElementById(id); 32 | div.innerHTML=s 33 | } 34 | 35 | function rows2table(id, columns, data) { 36 | let s = "" 37 | s += "" 38 | columns.forEach((col) => { 39 | s += "" 43 | columns.forEach((col) => { 44 | val = row[col] 45 | if (typeof val === "undefined") { 46 | val = '' 47 | } 48 | s += "
" + col 40 | }); 41 | data.forEach((row) => { 42 | s += "
" + val 49 | }); 50 | }); 51 | 52 | s += "
" 53 | let div = document.getElementById(id); 54 | div.innerHTML=s 55 | } 56 | 57 | function do_jsonrpc(url, method, params, id, handler, handler_param) { 58 | let body = { 59 | "jsonrpc": "2.0", 60 | "method": method, 61 | "id": jsonrpc_id, 62 | "params": params 63 | } 64 | jsonrpc_id++; 65 | 66 | fetch(url, {method:'POST', body: JSON.stringify(body)}) 67 | .then(function (response) { 68 | if (!response.ok) { 69 | throw new Error('Fetch got ' + response.status) 70 | } 71 | return response.json(); 72 | }) 73 | .then(function (data) { 74 | if ('error' in data) { 75 | throw new Error('JsonRPC got ' + data['error']) 76 | } 77 | handler(id,handler_param,data['result']); 78 | }) 79 | .catch(function (err) { 80 | console.log(err); 81 | }); 82 | } 83 | 84 | function do_stop() { 85 | // FIXME: uses global in script library 86 | do_jsonrpc( 87 | url, "stop", null, 88 | 'verbose', 89 | function (id,param,result) {}, null 90 | ); 91 | } 92 | 93 | function setverbose(tracelevel) { 94 | if (tracelevel < 0) { 95 | tracelevel = 0; 96 | } 97 | // FIXME: uses global in script library 98 | do_jsonrpc( 99 | url, "set_verbose", [tracelevel], 100 | 'verbose', 101 | result2verbose, null 102 | ); 103 | } 104 | 105 | function refresh_setup(interval) { 106 | var timer = setInterval(refresh_job, interval); 107 | } 108 | -------------------------------------------------------------------------------- /src/minmax.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | */ 6 | 7 | // TODO: 8 | // - on linux there are headers with these predefined 9 | // - on windows, there are different predefines 10 | // - use them! 11 | #ifndef MAX 12 | #define MAX(a, b) (((a) < (b)) ? (b) : (a)) 13 | #endif 14 | 15 | #ifndef MIN 16 | #define MIN(a, b) (((a) >(b)) ? (b) : (a)) 17 | #endif 18 | -------------------------------------------------------------------------------- /src/peer_info.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-25 Hamish Coleman 4 | * 5 | * non public structure and function definitions 6 | */ 7 | 8 | #ifndef _PEER_INFO_H_ 9 | #define _PEER_INFO_H_ 10 | 11 | #include // for n2n_mac_t, n2n_ip_subnet_t, n2n_desc_t, n2n_sock_t 12 | #include 13 | #include 14 | #include 15 | 16 | #include "n2n_typedefs.h" 17 | #include "n3n/ethernet.h" 18 | #include "uthash.h" 19 | 20 | #define HASH_ADD_PEER(head,add) \ 21 | HASH_ADD(hh,head,mac_addr,sizeof(n2n_mac_t),add) 22 | #define HASH_FIND_PEER(head,mac,out) \ 23 | HASH_FIND(hh,head,mac,sizeof(n2n_mac_t),out) 24 | 25 | /* flag used in add_sn_to_list_by_mac_or_sock */ 26 | enum skip_add {SN_ADD = 0, SN_ADD_SKIP = 1, SN_ADD_ADDED = 2}; 27 | 28 | struct peer_info { 29 | n2n_mac_t mac_addr; 30 | bool purgeable; 31 | uint8_t local; 32 | n2n_ip_subnet_t dev_addr; 33 | n2n_desc_t dev_desc; 34 | n2n_sock_t sock; 35 | SOCKET socket_fd; 36 | n2n_sock_t preferred_sock; 37 | n2n_cookie_t last_cookie; 38 | n2n_auth_t auth; 39 | int timeout; 40 | time_t last_seen; 41 | time_t last_p2p; 42 | time_t last_sent_query; 43 | time_t time_alloc; 44 | uint64_t selection_criterion; 45 | uint64_t last_valid_time_stamp; 46 | char *hostname; 47 | time_t uptime; 48 | n2n_version_t version; 49 | 50 | UT_hash_handle hh; /* makes this structure hashable */ 51 | }; 52 | 53 | typedef struct peer_info peer_info_t; 54 | 55 | void peer_info_init (struct peer_info *, const n2n_mac_t mac); 56 | struct peer_info* peer_info_malloc (const n2n_mac_t mac); 57 | void peer_info_free (struct peer_info *); 58 | struct peer_info* peer_info_validate (struct peer_info **, struct peer_info *); 59 | 60 | char *peer_info_get_hostname (struct peer_info *); 61 | 62 | /* Operations on peer_info lists. */ 63 | size_t purge_peer_list (struct peer_info ** peer_list, 64 | SOCKET socket_not_to_close, 65 | n2n_tcp_connection_t **tcp_connections, 66 | time_t purge_before); 67 | 68 | size_t clear_peer_list (struct peer_info ** peer_list); 69 | 70 | size_t purge_expired_nodes (struct peer_info **peer_list, 71 | SOCKET socket_not_to_close, 72 | n2n_tcp_connection_t **tcp_connections, 73 | time_t *p_last_purge, 74 | int frequency, int timeout); 75 | 76 | struct peer_info* add_sn_to_list_by_mac_or_sock ( 77 | struct peer_info **sn_list, 78 | n2n_sock_t *sock, 79 | const n2n_mac_t mac, 80 | int *skip_add 81 | ); 82 | struct peer_info* peer_upsert_by_sockaddr ( 83 | struct peer_info **list, 84 | struct sockaddr *sa, 85 | size_t addrlen 86 | ); 87 | 88 | int find_and_remove_peer (struct peer_info **, const n2n_mac_t); 89 | struct peer_info* find_peer_by_sock (const n2n_sock_t *, struct peer_info *); 90 | 91 | int find_peer_time_stamp_and_verify ( 92 | struct peer_info *peers1, 93 | struct peer_info *peers2, 94 | struct peer_info *sn, 95 | const n2n_mac_t mac, 96 | uint64_t stamp, 97 | int allow_jitter 98 | ); 99 | 100 | int n3n_peer_add_by_hostname (peer_info_t **list, const char *ip_and_port); 101 | #endif 102 | -------------------------------------------------------------------------------- /src/pktbuf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Private interface to the packet-sized buffers 6 | */ 7 | 8 | #ifndef _PKTBUF_H 9 | #define _PKTBUF_H 10 | 11 | #include // for ssize_t 12 | 13 | enum __attribute__((__packed__)) n3n_pktbuf_owner { 14 | n3n_pktbuf_owner_none = 0, // Nobody owns it, ready for alloc 15 | n3n_pktbuf_owner_alloc, // the new requester owns it 16 | n3n_pktbuf_owner_resolver_query, 17 | n3n_pktbuf_owner_resolver_result, 18 | n3n_pktbuf_owner_rx_pdu, 19 | }; 20 | 21 | struct n3n_pktbuf { 22 | unsigned char *buf; 23 | short capacity; // Total size of buf 24 | short offset_start; // Offset to start of data 25 | short offset_end; // Offset to end of data 26 | enum n3n_pktbuf_owner owner; // What process and data owns this 27 | }; 28 | 29 | void n3n_pktbuf_initialise (ssize_t mtu, int count); 30 | 31 | struct n3n_pktbuf *n3n_pktbuf_alloc(ssize_t); 32 | void n3n_pktbuf_free (struct n3n_pktbuf *); 33 | 34 | void n3n_pktbuf_zero (struct n3n_pktbuf *); 35 | 36 | ssize_t n3n_pktbuf_getbufsize (struct n3n_pktbuf *); 37 | ssize_t n3n_pktbuf_getbufavail (struct n3n_pktbuf *); 38 | void *n3n_pktbuf_getbufptr (struct n3n_pktbuf *); 39 | 40 | int n3n_pktbuf_prepend(struct n3n_pktbuf *, ssize_t); 41 | int n3n_pktbuf_append(struct n3n_pktbuf *, ssize_t, void *); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/resolve.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-25 Hamish Coleman 4 | * SPDX-License-Identifier: GPL-3.0-only 5 | * 6 | * The resolver thread non-public API 7 | */ 8 | 9 | #ifndef _RESOLVE_H_ 10 | #define _RESOLVE_H_ 11 | 12 | #include // for n2n_sock_t 13 | #include // for n2n_resolve_parameter_t 14 | #include 15 | #include 16 | #include // for UT_hash_handle 17 | 18 | #include "config.h" // for HAVE_LIBPTHREAD 19 | #include "peer_info.h" // for struct peer_info 20 | 21 | struct peer_info; 22 | 23 | #ifdef HAVE_LIBPTHREAD 24 | struct n3n_resolve_ip_sock { 25 | char *org_ip; /* pointer to original ip/named address string (used read only) */ 26 | n2n_sock_t sock; /* resolved socket */ 27 | n2n_sock_t *org_sock; /* pointer to original socket where 'sock' gets copied to from time to time */ 28 | int error_code; /* result of last resolution attempt */ 29 | 30 | UT_hash_handle hh; /* makes this structure hashable */ 31 | }; 32 | 33 | // structure to hold resolver thread's parameters 34 | struct n3n_resolve_parameter { 35 | struct n3n_resolve_ip_sock *list; /* pointer to list of to be resolved nodes */ 36 | time_t check_interval; /* interval to checik resolover results */ 37 | time_t last_checked; /* last time the resolver results were cheked */ 38 | time_t last_resolved; /* last time the resolver completed */ 39 | bool changed; /* indicates a change */ 40 | bool request; /* flags main thread's need for intermediate resolution */ 41 | pthread_t id; /* thread id */ 42 | pthread_mutex_t access; /* mutex for shared access */ 43 | }; 44 | #endif 45 | 46 | int resolve_create_thread (n3n_resolve_parameter_t **param, struct peer_info *sn_list); 47 | bool resolve_check (n3n_resolve_parameter_t *param, bool resolution_request, time_t now); 48 | void resolve_cancel_thread (n3n_resolve_parameter_t *param); 49 | 50 | // Internal resolver function, will turn static once supernode.c doesnt use it 51 | int supernode2sock (n2n_sock_t * sn, const char *addrIn); 52 | 53 | // called from edge_utils, runs supernode2sock only ifndef HAVE_LIBPTHREAD 54 | int maybe_supernode2sock (n2n_sock_t * sn, const char *addrIn); 55 | 56 | const char *resolve_hostnames_str_get (int, int); 57 | void resolve_log_hostnames (int); 58 | int resolve_hostnames_str_to_peer_info (int, struct peer_info **); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/transform.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static struct n3n_transform *registered_transforms = NULL; 14 | 15 | void n3n_transform_register (struct n3n_transform *transform) { 16 | if(!transform) { 17 | return; 18 | } 19 | 20 | // TODO: should confirm that we register each name only once 21 | // (perhaps twice if one is_compression and the other is not, but that 22 | // also sounds confusing) 23 | 24 | transform->next = registered_transforms; 25 | registered_transforms = transform; 26 | } 27 | 28 | static struct n3n_transform *lookup_name (bool is_compress, char *name) { 29 | struct n3n_transform *p = registered_transforms; 30 | while(p) { 31 | if((is_compress == p->is_compress) && (0==strcmp(p->name, name))) { 32 | return p; 33 | } 34 | p = p->next; 35 | } 36 | return NULL; 37 | } 38 | 39 | static struct n3n_transform *lookup_id (bool is_compress, int id) { 40 | struct n3n_transform *p = registered_transforms; 41 | while(p) { 42 | if((is_compress == p->is_compress) && (p->id == id)) { 43 | return p; 44 | } 45 | p = p->next; 46 | } 47 | return NULL; 48 | } 49 | 50 | static const char *id2str (bool is_compress, int id) { 51 | struct n3n_transform *p = lookup_id(is_compress, id); 52 | if(!p) { 53 | return NULL; 54 | } 55 | return p->name; 56 | } 57 | 58 | struct n3n_transform *n3n_transform_lookup_name (char *name) { 59 | return lookup_name(false, name); 60 | } 61 | 62 | struct n3n_transform *n3n_transform_lookup_id (int id) { 63 | return lookup_id(false, id); 64 | } 65 | 66 | const char *n3n_transform_id2str (int id) { 67 | return id2str(false, id); 68 | } 69 | 70 | struct n3n_transform *n3n_compression_lookup_name (char *name) { 71 | return lookup_name(true, name); 72 | } 73 | 74 | struct n3n_transform *n3n_compression_lookup_id (int id) { 75 | return lookup_id(true, id); 76 | } 77 | 78 | const char *n3n_compression_id2str (int id) { 79 | return id2str(true, id); 80 | } 81 | 82 | // prototype any internal (non-public) initfuncs 83 | void n3n_initfuncs_transform_aes (); 84 | void n3n_initfuncs_transform_cc20 (); 85 | void n3n_initfuncs_transform_lzo (); 86 | void n3n_initfuncs_transform_none (); 87 | void n3n_initfuncs_transform_null (); 88 | void n3n_initfuncs_transform_speck (); 89 | void n3n_initfuncs_transform_twofish (); 90 | void n3n_initfuncs_transform_zstd (); 91 | 92 | void n3n_initfuncs_transform () { 93 | n3n_initfuncs_transform_aes(); 94 | n3n_initfuncs_transform_cc20(); 95 | n3n_initfuncs_transform_lzo(); 96 | n3n_initfuncs_transform_none(); 97 | n3n_initfuncs_transform_null(); 98 | n3n_initfuncs_transform_speck(); 99 | n3n_initfuncs_transform_twofish(); 100 | n3n_initfuncs_transform_zstd(); 101 | } 102 | -------------------------------------------------------------------------------- /src/transform_none.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | */ 6 | 7 | #include // for n3n_transform_register 8 | #include 9 | 10 | #include "n2n_define.h" // for N2N_COMPRESSION_ID_NONE 11 | 12 | // A dummy transform struct for the no-op compression 13 | static struct n3n_transform transform = { 14 | .name = "none", 15 | .id = N2N_COMPRESSION_ID_NONE, 16 | .is_compress = true, 17 | }; 18 | 19 | void n3n_initfuncs_transform_none () { 20 | n3n_transform_register(&transform); 21 | } 22 | -------------------------------------------------------------------------------- /src/transform_null.c: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2023-25 Hamish Coleman 4 | * SPDX-License-Identifier: GPL-3.0-only 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not see see 18 | * 19 | */ 20 | 21 | 22 | #include // for traceEvent 23 | #include // for n3n_transform_register 24 | #include // for uint8_t 25 | #include // for memcpy, size_t, memset 26 | 27 | #include "n2n.h" // for n2n_trans_op_t, N2N_... 28 | #include "n2n_typedefs.h" 29 | 30 | 31 | static int transop_deinit_null (n2n_trans_op_t *arg ) { 32 | 33 | // nothing to deallocate, nothing to release 34 | 35 | return 0; 36 | } 37 | 38 | 39 | static int transop_encode_null (n2n_trans_op_t *arg, 40 | uint8_t *outbuf, 41 | size_t out_len, 42 | const uint8_t *inbuf, 43 | size_t in_len, 44 | const uint8_t *peer_mac) { 45 | 46 | int retval = -1; 47 | 48 | traceEvent(TRACE_DEBUG, "encode_null %lu", in_len); 49 | if(out_len >= in_len) { 50 | memcpy(outbuf, inbuf, in_len); 51 | retval = in_len; 52 | } else { 53 | traceEvent(TRACE_DEBUG, "encode_null %lu too big for packet buffer", in_len); 54 | } 55 | 56 | return retval; 57 | } 58 | 59 | 60 | static int transop_decode_null (n2n_trans_op_t *arg, 61 | uint8_t *outbuf, 62 | size_t out_len, 63 | const uint8_t *inbuf, 64 | size_t in_len, 65 | const uint8_t *peer_mac) { 66 | 67 | int retval = -1; 68 | 69 | traceEvent(TRACE_DEBUG, "decode_null %lu", in_len); 70 | if(out_len >= in_len) { 71 | memcpy(outbuf, inbuf, in_len); 72 | retval = in_len; 73 | } else { 74 | traceEvent(TRACE_DEBUG, "decode_null %lu too big for packet buffer", in_len); 75 | } 76 | 77 | return retval; 78 | } 79 | 80 | 81 | int n2n_transop_null_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { 82 | 83 | memset(ttt, 0, sizeof(n2n_trans_op_t)); 84 | 85 | ttt->transform_id = N2N_TRANSFORM_ID_NULL; 86 | ttt->no_encryption = 1; 87 | ttt->deinit = transop_deinit_null; 88 | ttt->fwd = transop_encode_null; 89 | ttt->rev = transop_decode_null; 90 | 91 | return 0; 92 | } 93 | 94 | static struct n3n_transform transform = { 95 | .name = "null", 96 | .id = N2N_TRANSFORM_ID_NULL, 97 | }; 98 | 99 | void n3n_initfuncs_transform_null () { 100 | n3n_transform_register(&transform); 101 | } 102 | -------------------------------------------------------------------------------- /src/win32/DotNet/n2n.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C++ Express 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "edge", "n2n.vcproj", "{4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "supernode", "supernode.vcproj", "{BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Debug|Win32.Build.0 = Debug|Win32 16 | {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Release|Win32.ActiveCfg = Release|Win32 17 | {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Release|Win32.Build.0 = Release|Win32 18 | {BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}.Debug|Win32.Build.0 = Debug|Win32 20 | {BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}.Release|Win32.ActiveCfg = Release|Win32 21 | {BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}.Release|Win32.Build.0 = Release|Win32 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /src/win32/DotNet/n2n.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n42n/n3n/c5f92a086510ae4e34efbfcd44c50182bd19d659/src/win32/DotNet/n2n.suo -------------------------------------------------------------------------------- /src/win32/defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * Basic definitions needed for any windows compile 6 | * 7 | */ 8 | 9 | #ifndef _WIN32_DEFS_H_ 10 | #define _WIN32_DEFS_H_ 11 | 12 | #ifndef _CRT_SECURE_NO_WARNINGS 13 | #define _CRT_SECURE_NO_WARNINGS 14 | #endif 15 | 16 | #define WIN32_LEAN_AND_MEAN 17 | 18 | #ifndef _WIN64 19 | /* needs to be defined before winsock gets included */ 20 | #undef _WIN32_WINNT 21 | #define _WIN32_WINNT 0x501 22 | 23 | const char *fill_inet_ntop (int, const void *, char *, int); 24 | int fill_inet_pton (int af, const char *restrict src, void *restrict dst); 25 | #define inet_ntop fill_inet_ntop 26 | #define inet_pton fill_inet_pton 27 | #endif 28 | 29 | #include 30 | #include 31 | 32 | int fill_gettimeofday (struct timeval *, void *); 33 | void fill_timersub (struct timeval *, struct timeval *, struct timeval *); 34 | #define gettimeofday fill_gettimeofday 35 | #define timersub fill_timersub 36 | 37 | extern void destroyWin32 (); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/win32/edge.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/win32/edge.rc: -------------------------------------------------------------------------------- 1 | // https://www.transmissionzero.co.uk/computing/win32-apps-with-mingw/ 2 | // ID_MANIFEST RT_MANIFEST "edge.manifest" 3 | 1 24 "edge.manifest" -------------------------------------------------------------------------------- /src/win32/edge_utils_win32.h: -------------------------------------------------------------------------------- 1 | /** 2 | * (C) 2007-22 - ntop.org and contributors 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not see see 16 | * 17 | */ 18 | 19 | #ifndef _EDGE_UTILS_WIN32_H_ 20 | #define _EDGE_UTILS_WIN32_H_ 21 | 22 | #include 23 | 24 | 25 | /* Multicast peers discovery disabled due to https://github.com/ntop/n2n/issues/65 */ 26 | 27 | /* Currently, multicast is performed by specifying the default routing network adapter. 28 | * If the solution is determined to be stable and effective, 29 | * all macro definitions "SKIP_MULTICAST_PEERS_DISCOVERY" will be completely deleted in the future. 30 | */ 31 | //#define SKIP_MULTICAST_PEERS_DISCOVERY 32 | 33 | // TODO: this struct is pretty empty now, collapse it to just struct n3n_runtime_data ? 34 | struct tunread_arg { 35 | struct n3n_runtime_data *eee; 36 | }; 37 | 38 | extern HANDLE startTunReadThread (struct tunread_arg *arg); 39 | int get_best_interface_ip (uint32_t addr_v4, dec_ip_str_t *ip_addr); 40 | 41 | 42 | #endif /* _EDGE_UTILS_WIN32_H_ */ 43 | 44 | -------------------------------------------------------------------------------- /src/win32/n2n_win32.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | (C) 2007-22 - Luca Deri 4 | * Copyright (C) 2024-25 Hamish Coleman 5 | * SPDX-License-Identifier: GPL-3.0-only 6 | 7 | */ 8 | 9 | #ifndef _N2N_WIN32_H_ 10 | #define _N2N_WIN32_H_ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #if defined(_MSC_VER) 17 | #include 18 | #pragma comment(lib,"Iphlpapi.lib") 19 | #endif 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | #include "wintap.h" 26 | 27 | #undef EAFNOSUPPORT 28 | #define EAFNOSUPPORT WSAEAFNOSUPPORT 29 | #define MAX(a,b) (a > b ? a : b) 30 | #define MIN(a,b) (a < b ? a : b) 31 | 32 | #define snprintf _snprintf 33 | #define strdup _strdup 34 | 35 | #define socklen_t int 36 | 37 | 38 | /* ************************************* */ 39 | 40 | 41 | 42 | #define index(a, b) strchr(a, b) 43 | #define sleep(x) Sleep(x * 1000) 44 | 45 | 46 | /* ************************************* */ 47 | // FIXME: this code has rotted and no longer works as expected 48 | 49 | #define HAVE_PTHREAD 50 | #define pthread_t HANDLE 51 | #define pthread_mutex_t HANDLE 52 | 53 | #define pthread_create(p_thread_handle, attr, thread_func, p_param) \ 54 | (*p_thread_handle = CreateThread(0 /* default security flags */, 0 /*default stack*/, \ 55 | thread_func, p_param, 0 /* default creation flags */, \ 56 | NULL) == 0) 57 | 58 | #define pthread_cancel(p_thread_handle) \ 59 | TerminateThread(p_thread_handle, 0) 60 | 61 | #define pthread_mutex_init(p_mutex_handle, attr) \ 62 | *p_mutex_handle = CreateMutex(NULL /*default security flags */, \ 63 | FALSE /* initially not owned */, NULL /* unnamed */) 64 | 65 | #define pthread_mutex_lock(mutex) \ 66 | WaitForSingleObject(*mutex, INFINITE) 67 | 68 | #define pthread_mutex_trylock(mutex) \ 69 | WaitForSingleObject(*mutex, NULL) 70 | 71 | #define pthread_mutex_unlock(mutex) \ 72 | ReleaseMutex(*mutex) 73 | 74 | 75 | /* ************************************* */ 76 | 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/win32/win32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) 2007-22 - ntop.org and contributors 3 | * Copyright (C) 2024-25 Hamish Coleman 4 | * SPDX-License-Identifier: GPL-3.0-only 5 | * 6 | * Windows specific common functions 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "defs.h" 14 | 15 | void n3n_initfuncs_win32 () { 16 | WSADATA wsaData; 17 | int err; 18 | 19 | err = WSAStartup(MAKEWORD(2, 2), &wsaData ); 20 | if( err != 0 ) { 21 | /* Tell the user that we could not find a usable */ 22 | /* WinSock DLL. */ 23 | printf("FATAL ERROR: unable to initialise Winsock 2.x."); 24 | exit(EXIT_FAILURE); 25 | } 26 | } 27 | 28 | void destroyWin32 () { 29 | WSACleanup(); 30 | } 31 | 32 | /* ************************************** */ 33 | // Some polyfill functions 34 | // TODO: switch to just using struct sockaddr everywhere and then can use 35 | // getnameinfo directly and delete these functions 36 | 37 | /* 38 | * The inet_ntop function was not included in windows until after Windows XP 39 | */ 40 | 41 | const char *fill_inet_ntop (int af, const void *src, char *dst, int size) { 42 | if(af == AF_INET) { 43 | struct sockaddr_in in; 44 | memset(&in, 0, sizeof(in)); 45 | 46 | in.sin_family = AF_INET; 47 | memcpy(&in.sin_addr, src, sizeof(in.sin_addr)); 48 | getnameinfo((struct sockaddr *)&in,sizeof(in),dst,size,NULL,0,NI_NUMERICHOST); 49 | return dst; 50 | } 51 | 52 | if(af == AF_INET6) { 53 | struct sockaddr_in6 in6; 54 | memset(&in6, 0, sizeof(in6)); 55 | 56 | in6.sin6_family = AF_INET6; 57 | memcpy(&in6.sin6_addr, src, sizeof(in6.sin6_addr)); 58 | getnameinfo((struct sockaddr *)&in6,sizeof(in6),dst,size,NULL,0,NI_NUMERICHOST); 59 | return dst; 60 | } 61 | 62 | return NULL; 63 | } 64 | 65 | int fill_inet_pton (int af, const char *restrict src, void *restrict dst) { 66 | if(af != AF_INET) { 67 | // We simply dont support IPv6 on old Windows 68 | return -1; 69 | } 70 | if((NULL == src) || (NULL == dst)) { 71 | return -1; 72 | } 73 | 74 | struct addrinfo *result = NULL; 75 | struct addrinfo hints; 76 | memset(&hints, 0, sizeof(hints)); 77 | hints.ai_flags = AI_NUMERICHOST; 78 | hints.ai_family = af; 79 | 80 | if(getaddrinfo(src, NULL, &hints, &result) != 0) { 81 | freeaddrinfo(result); 82 | return -1; 83 | } 84 | 85 | struct sockaddr_in *sa = (struct sockaddr_in *)result->ai_addr; 86 | *((uint32_t *)dst) = sa->sin_addr.s_addr; 87 | return 1; 88 | } 89 | 90 | void fill_timersub (struct timeval *a, struct timeval *b, struct timeval *res) { 91 | if(!a || !b || !res) { 92 | return; 93 | } 94 | 95 | res->tv_usec = a->tv_usec - b->tv_usec; 96 | if(res->tv_usec < 0) { 97 | a->tv_sec--; 98 | res->tv_usec += 1000000; 99 | } 100 | res->tv_sec = a->tv_sec - b->tv_sec; 101 | } 102 | 103 | int fill_gettimeofday (struct timeval * tv, void * tz) { 104 | if(!tv) { 105 | return -1; 106 | } 107 | 108 | SYSTEMTIME st; 109 | FILETIME ft; 110 | ULARGE_INTEGER wtf; 111 | 112 | GetSystemTime(&st); 113 | SystemTimeToFileTime(&st, &ft); 114 | 115 | wtf.u.LowPart = ft.dwLowDateTime; 116 | wtf.u.HighPart = ft.dwHighDateTime; 117 | 118 | // Convert from Windows Epoch to unix Epoch 119 | wtf.QuadPart -= 116444736000000000ULL; 120 | 121 | tv->tv_sec = wtf.QuadPart / 10000000L; 122 | tv->tv_usec = st.wMilliseconds * 1000; 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /src/win32/wintap.h: -------------------------------------------------------------------------------- 1 | /* 2 | (C) 2007-22 - Luca Deri 3 | */ 4 | 5 | #ifndef _WINTAP_H_ 6 | #define _WINTAP_H_ 7 | 8 | #undef UNICODE 9 | #undef _UNICODE 10 | #ifndef _CRT_SECURE_NO_WARNINGS 11 | #define _CRT_SECURE_NO_WARNINGS 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | 20 | //=============================================== 21 | // This file is included both by OpenVPN and 22 | // the TAP-Win32 driver and contains definitions 23 | // common to both. 24 | //=============================================== 25 | 26 | //============= 27 | // TAP IOCTLs 28 | //============= 29 | 30 | #define TAP_CONTROL_CODE(request,method) \ 31 | CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) 32 | 33 | #define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED) 34 | #define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE(2, METHOD_BUFFERED) 35 | #define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE(3, METHOD_BUFFERED) 36 | #define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE(4, METHOD_BUFFERED) 37 | #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE(5, METHOD_BUFFERED) 38 | #define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(6, METHOD_BUFFERED) 39 | #define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE(7, METHOD_BUFFERED) 40 | #define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE(8, METHOD_BUFFERED) 41 | #define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE(9, METHOD_BUFFERED) 42 | 43 | //================= 44 | // Registry keys 45 | //================= 46 | 47 | #define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 48 | #define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 49 | #define ADAPTER_INFO_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 50 | 51 | //====================== 52 | // Filesystem prefixes 53 | //====================== 54 | 55 | #define USERMODEDEVICEDIR "\\\\.\\Global\\" 56 | #define SYSDEVICEDIR "\\Device\\" 57 | #define USERDEVICEDIR "\\DosDevices\\Global\\" 58 | #define TAPSUFFIX ".tap" 59 | 60 | //========================================================= 61 | // TAP_COMPONENT_ID -- This string defines the TAP driver 62 | // type -- different component IDs can reside in the system 63 | // simultaneously. 64 | //========================================================= 65 | 66 | #define TAP_COMPONENT_ID "tap0801" 67 | 68 | extern void win_print_available_adapters (); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /tests/test_builtin_edge.sh.expected: -------------------------------------------------------------------------------- 1 | ### test: ./apps/n3n-edge test hashing 2 | OK 3 | 4 | ### test: ./apps/n3n-edge test config roundtrip 5 | # Autogenerated config dump 6 | 7 | [auth] 8 | 9 | [community] 10 | header_encryption=unknown 11 | #supernode= 12 | 13 | 14 | [connection] 15 | advertise_addr=0.0.0.0 16 | allow_p2p=false 17 | connect_tcp=false 18 | pmtu_discovery=false 19 | register_interval=0 20 | register_pkt_ttl=0 21 | tos=0 22 | 23 | [daemon] 24 | userid=0 25 | groupid=0 26 | background=false 27 | 28 | [filter] 29 | allow_multicast=false 30 | allow_routing=false 31 | 32 | [logging] 33 | verbose=2 34 | 35 | [management] 36 | enable_debug_pages=false 37 | port=0 38 | unix_sock_perms=0 39 | 40 | [supernode] 41 | auto_ip_max=0.0.0.0/0 42 | auto_ip_min=0.0.0.0/0 43 | macaddr=00:00:00:00:00:00 44 | #peer= 45 | 46 | spoofing_protection=false 47 | 48 | [tuntap] 49 | address=0.0.0.0/0 50 | address_mode=auto 51 | metric=0 52 | mtu=0 53 | 54 | ### test: ./apps/n3n-edge tools keygen logan 007 55 | * logan nHWum+r42k1qDXdIeH-WFKeylK5UyLStRzxofRNAgpG 56 | 57 | ### test: ./apps/n3n-edge tools keygen secretFed 58 | auth.pubkey=opIyaWhWjKLJSNOHNpKnGmelhHWRqkmY5pAx7lbDHp4 59 | 60 | -------------------------------------------------------------------------------- /tests/test_integration_edge.sh.expected: -------------------------------------------------------------------------------- 1 | ### test: ./apps/n3n-supernode start ci_sn -v --daemon 2 | 3 | ### test: ./scripts/n3nctl -s ci_edge1 get_communities 4 | [ 5 | { 6 | "community": "test" 7 | } 8 | ] 9 | 10 | ### test: ./scripts/n3nctl -s ci_edge1 get_packetstats 11 | [ 12 | { 13 | "rx_pkt": 0, 14 | "tx_pkt": 2, 15 | "type": "transop" 16 | }, 17 | { 18 | "rx_pkt": 0, 19 | "tx_pkt": 0, 20 | "type": "p2p" 21 | }, 22 | { 23 | "rx_pkt": 0, 24 | "tx_pkt": 2, 25 | "type": "super" 26 | }, 27 | { 28 | "rx_pkt": 0, 29 | "tx_pkt": 2, 30 | "type": "super_broadcast" 31 | }, 32 | { 33 | "tx_pkt": 0, 34 | "type": "tuntap_error" 35 | } 36 | ] 37 | 38 | ### test: ./scripts/n3nctl -s ci_edge1 get_edges --raw 39 | [] 40 | 41 | ### test: ./scripts/n3nctl -s ci_edge1 get_verbose 42 | 2 43 | 44 | ### test: ./scripts/n3nctl -s ci_edge1 set_verbose 1 45 | This request requires an authentication key 46 | 47 | 1 48 | ### test: ./scripts/n3nctl -s ci_edge1 -k n3n set_verbose 1 49 | 1 50 | 51 | ### test: ./scripts/n3nctl -s ci_edge1 -k n3n stop 52 | 0 53 | 54 | ### test: ./scripts/n3nctl -s ci_sn -k n3n stop 55 | 0 56 | 57 | -------------------------------------------------------------------------------- /tests/test_integration_edge_tcp.sh.expected: -------------------------------------------------------------------------------- 1 | ### test: ./apps/n3n-supernode start ci_sn -v --daemon -Osupernode.macaddr=02:00:00:55:00:00 2 | 3 | ### test: ./scripts/n3nctl -s ci_edge1 get_communities 4 | [ 5 | { 6 | "community": "test" 7 | } 8 | ] 9 | 10 | ### test: ./scripts/n3nctl -s ci_edge1 get_packetstats 11 | [ 12 | { 13 | "rx_pkt": 0, 14 | "tx_pkt": 2, 15 | "type": "transop" 16 | }, 17 | { 18 | "rx_pkt": 0, 19 | "tx_pkt": 0, 20 | "type": "p2p" 21 | }, 22 | { 23 | "rx_pkt": 0, 24 | "tx_pkt": 2, 25 | "type": "super" 26 | }, 27 | { 28 | "rx_pkt": 0, 29 | "tx_pkt": 2, 30 | "type": "super_broadcast" 31 | }, 32 | { 33 | "tx_pkt": 0, 34 | "type": "tuntap_error" 35 | } 36 | ] 37 | 38 | ### test: ./scripts/n3nctl -s ci_edge1 get_edges --raw 39 | [] 40 | 41 | ### test: ./scripts/n3nctl -s ci_sn get_edges --raw 42 | [ 43 | { 44 | "community": "test", 45 | "desc": "ci_edge1", 46 | "ip4addr": "10.200.175.139/24", 47 | "last_p2p": 0, 48 | "last_sent_query": 0, 49 | "local": 0, 50 | "macaddr": "02:00:00:77:00:00", 51 | "mode": "sn", 52 | "prefered_sockaddr": "0.0.0.0:0", 53 | "purgeable": 1, 54 | "sockaddr": "127.0.0.1:7700", 55 | "timeout": 0, 56 | "uptime": 0, 57 | "version": "" 58 | } 59 | ] 60 | 61 | ### test: ./scripts/n3nctl -s ci_edge1 get_supernodes --raw 62 | [ 63 | { 64 | "current": 1, 65 | "last_seen": 0, 66 | "macaddr": "02:00:00:55:00:00", 67 | "purgeable": 0, 68 | "selection": "", 69 | "sockaddr": "127.0.0.1:7654", 70 | "uptime": 0, 71 | "version": "" 72 | } 73 | ] 74 | 75 | ### test: ./scripts/n3nctl -s ci_edge1 -k n3n stop 76 | 0 77 | 78 | ### test: ./scripts/n3nctl -s ci_sn -k n3n stop 79 | 0 80 | 81 | -------------------------------------------------------------------------------- /tests/test_integration_webui.sh.expected: -------------------------------------------------------------------------------- 1 | ### test: ./apps/n3n-supernode start ci_sn -v --daemon -Osupernode.macaddr=02:00:00:55:00:00 2 | 3 | ### test: curl --unix-socket /run/n3n/ci_edge1/mgmt http://x/ -o /tmp/index.html 4 | 5 | ### test: diff -u src/management_index.html /tmp/index.html 6 | 7 | ### test: curl --unix-socket /run/n3n/ci_edge1/mgmt http://x/script.js -o /tmp/script.js 8 | 9 | ### test: diff -u src/management_script.js /tmp/script.js 10 | 11 | ### test: ./scripts/n3nctl -s ci_edge1 -k n3n stop 12 | 0 13 | 14 | ### test: ./scripts/n3nctl -s ci_sn -k n3n stop 15 | 0 16 | 17 | -------------------------------------------------------------------------------- /tests/tests-auth.expected: -------------------------------------------------------------------------------- 1 | bin_to_ascii: input size = 0x10 2 | 000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 3 | bin_to_ascii: output: 00420mG51WS82GeB30qE3m 4 | 5 | ascii_to_bin: input = 00420mG51WS82GeB30qE3m 6 | ascii_to_bin: output: 7 | 000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 8 | 010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | | 9 | 10 | generate_private_key: input = 00420mG51WS82GeB30qE3m 11 | generate_private_key: output: 12 | 000: a4 f4 b5 1c 8a 0a 09 f9 7e 98 22 ca 8a cc b3 f9 | ~ " | 13 | 010: 4d 5a 0d 02 0b 9d 08 ea 03 9b 46 41 8e 3c 0d 49 |MZ FA < I| 14 | 15 | generate_public_key: input: 16 | 000: a4 f4 b5 1c 8a 0a 09 f9 7e 98 22 ca 8a cc b3 f9 | ~ " | 17 | 010: 4d 5a 0d 02 0b 9d 08 ea 03 9b 46 41 8e 3c 0d 49 |MZ FA < I| 18 | generate_public_key: output: 19 | 000: ca 58 61 6f f9 25 d0 cd 1d a5 62 48 a0 15 5e ad | Xao % bH ^ | 20 | 010: a9 f3 5c 10 5f 20 b6 42 b0 a9 7c 1e 0e d7 e9 4b | \ _ B | K| 21 | 22 | generate_shared_secret: input: prv 23 | 000: a4 f4 b5 1c 8a 0a 09 f9 7e 98 22 ca 8a cc b3 f9 | ~ " | 24 | 010: 4d 5a 0d 02 0b 9d 08 ea 03 9b 46 41 8e 3c 0d 49 |MZ FA < I| 25 | generate_shared_secret: input: pub 26 | 000: ca 58 61 6f f9 25 d0 cd 1d a5 62 48 a0 15 5e ad | Xao % bH ^ | 27 | 010: a9 f3 5c 10 5f 20 b6 42 b0 a9 7c 1e 0e d7 e9 4b | \ _ B | K| 28 | generate_shared_secret: output: 29 | 000: 5d 94 7b 0b db 54 e8 70 8a 09 b0 db 6f 0b 0d 31 |] { T p o 1| 30 | 010: 1b b8 5f ba 57 74 34 bd 3b c5 c4 6c d5 ae a4 84 | _ Wt4 ; l | 31 | 32 | -------------------------------------------------------------------------------- /tests/tests-compress.expected: -------------------------------------------------------------------------------- 1 | original: input size = 0x200 2 | 000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 3 | 010: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 4 | 020: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 5 | 030: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 6 | 040: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 7 | 050: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 8 | 060: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 9 | 070: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 10 | 080: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 11 | 090: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 12 | 0a0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 13 | 0b0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 14 | 0c0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 15 | 0d0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 16 | 0e0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 17 | 0f0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 18 | 100: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 19 | 110: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 20 | 120: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 21 | 130: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 22 | 140: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 23 | 150: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 24 | 160: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 25 | 170: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 26 | 180: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 27 | 190: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 28 | 1a0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 29 | 1b0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 30 | 1c0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 31 | 1d0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 32 | 1e0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 33 | 1f0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 34 | 35 | lzo1x: output size = 0x2f 36 | 000: 0d 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e | | 37 | 010: 0f 20 00 bc 3c 00 00 02 0c 0d 0e 0f 00 01 02 03 | < | 38 | 020: 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 11 00 00 | | 39 | 40 | zstd: output size = 0x21 41 | 000: 28 b5 2f fd 60 00 01 bd 00 00 80 00 01 02 03 04 |( / ` | 42 | 010: 05 06 07 08 09 0a 0b 0c 0d 0e 0f 01 00 da 47 9d | G | 43 | 020: 4b |K| 44 | 45 | -------------------------------------------------------------------------------- /tests/tests-elliptic.expected: -------------------------------------------------------------------------------- 1 | environment: input 2 | 000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | | 3 | 010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 | | 4 | environment: key 5 | 000: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 |UUUUUUUUUUUUUUUU| 6 | 010: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 |UUUUUUUUUUUUUUUU| 7 | 8 | curve25519: output 9 | 000: 7f 42 1b f9 34 5a 59 84 4a 30 bc 53 64 74 fa 7c | B 4ZY J0 Sdt || 10 | 010: 15 81 77 a4 4d 34 6d 2f 8b c1 8c 05 d6 a9 44 54 | w M4m/ DT| 11 | 12 | -------------------------------------------------------------------------------- /tests/tests_builtin.list: -------------------------------------------------------------------------------- 1 | # 2 | # Tests using builtin self tests in the apps 3 | 4 | test_builtin_edge.sh 5 | -------------------------------------------------------------------------------- /tests/tests_integration.list: -------------------------------------------------------------------------------- 1 | # 2 | # The integration tests 3 | 4 | test_integration_webui.sh 5 | test_integration_packets.sh 6 | test_integration_supernode.sh 7 | test_integration_edge.sh 8 | test_integration_edge_tcp.sh 9 | -------------------------------------------------------------------------------- /tests/tests_units.list: -------------------------------------------------------------------------------- 1 | # 2 | # The unit tests 3 | 4 | tests-auth 5 | tests-compress 6 | tests-elliptic 7 | tests-transform 8 | tests-wire 9 | -------------------------------------------------------------------------------- /tools/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Tools 3 | crypto_helper 4 | n3n-benchmark 5 | n3n-decode 6 | n3n-portfwd 7 | n3n-route 8 | crypto_helper.exe 9 | n3n-benchmark.exe 10 | n3n-decode.exe 11 | n3n-portfwd.exe 12 | n3n-route.exe 13 | 14 | # Binaries built to run tests 15 | tests-auth 16 | tests-compress 17 | tests-elliptic 18 | tests-transform 19 | tests-wire 20 | tests-auth.exe 21 | tests-compress.exe 22 | tests-elliptic.exe 23 | tests-transform.exe 24 | tests-wire.exe 25 | -------------------------------------------------------------------------------- /tools/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is not a standalone makefile, it must be called from the toplevel 3 | # makefile to inherit the correct environment 4 | 5 | LDLIBS+=-ln3n 6 | LDLIBS+=$(LDLIBS_LOCAL) 7 | LDLIBS+=$(LDLIBS_EXTRA) 8 | 9 | TOOLS+=n3n-benchmark 10 | TOOLS+=n3n-route 11 | TOOLS+=n3n-portfwd 12 | TOOLS+=n3n-decode 13 | TOOLS+=crypto_helper 14 | 15 | TESTS=tests-compress 16 | TESTS+=tests-elliptic 17 | TESTS+=tests-transform 18 | TESTS+=tests-wire 19 | TESTS+=tests-auth 20 | 21 | .PHONY: all clean install 22 | all: $(TOOLS) $(TESTS) 23 | 24 | %: %.c 25 | @echo " CC $@" 26 | @$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ 27 | 28 | # See comments in the topdir Makefile about how to generate coverage 29 | # data. 30 | gcov: 31 | gcov $(TOOLS) $(TESTS) 32 | 33 | clean: 34 | rm -rf $(TOOLS) *.o *.dSYM *~ 35 | rm -f $(TESTS) *.gcno *.gcda 36 | 37 | install: $(TOOLS) 38 | $(INSTALL) -d $(CONFIG_SBINDIR) 39 | $(INSTALL_PROG) $(addsuffix $(EXE),$(TOOLS)) $(CONFIG_SBINDIR)/ 40 | -------------------------------------------------------------------------------- /tools/tests-elliptic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Hamish Coleman 3 | * SPDX-License-Identifier: GPL-3.0-only 4 | * 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see 18 | * 19 | */ 20 | 21 | 22 | #include // for fhexdump 23 | #include // for printf, fprintf, stdout, stderr 24 | #include // for memset 25 | #include "curve25519.h" // for curve25519 26 | 27 | 28 | void test_curve25519 (unsigned char *pkt_input, unsigned char *key) { 29 | char *test_name = "curve25519"; 30 | unsigned char pkt_output[32]; 31 | 32 | curve25519(pkt_output, key, pkt_input); 33 | 34 | printf("%s: output\n", test_name); 35 | fhexdump(0, pkt_output, sizeof(pkt_output), stdout); 36 | 37 | fprintf(stderr, "%s: tested\n", test_name); 38 | printf("\n"); 39 | } 40 | 41 | int main (int argc, char * argv[]) { 42 | char *test_name = "environment"; 43 | 44 | unsigned char key[32]; 45 | unsigned char pkt_input[32]; 46 | 47 | memset(pkt_input, 0, 31); 48 | pkt_input[31] = 9; 49 | 50 | memset(key, 0x55, 32); 51 | 52 | printf("%s: input\n", test_name); 53 | fhexdump(0, pkt_input, sizeof(pkt_input), stdout); 54 | printf("%s: key\n", test_name); 55 | fhexdump(0, key, sizeof(key), stdout); 56 | printf("\n"); 57 | 58 | test_curve25519(pkt_input, key); 59 | 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /uncrustify.cfg: -------------------------------------------------------------------------------- 1 | # Initial rules taken from a quick discussion 2 | # (See https://github.com/ntop/n2n/commit/00159d0d012c6836fd972af1748833eeaf50fa22#commitcomment-57137247) 3 | 4 | # 4 space indention (never use tabs) 5 | indent_columns = 4 6 | indent_with_tabs = 0 7 | indent_switch_case = 4 8 | indent_paren_close = 2 9 | 10 | # space between name and bracket during function define 11 | sp_func_def_paren = force 12 | sp_func_proto_paren = force 13 | 14 | # no space between name and bracket during call 15 | sp_func_call_paren = remove 16 | 17 | # no space after if and while 18 | sp_before_sparen = remove 19 | #sp_while_paren_open = remove # only in newer uncrustify 20 | 21 | # block-braces as seen above 22 | nl_if_brace = remove 23 | nl_brace_else = remove 24 | nl_elseif_brace = remove 25 | nl_else_brace = remove 26 | #nl_before_opening_brace_func_class_def = remove # only in newer uncrustify 27 | nl_for_brace = remove 28 | nl_while_brace = remove 29 | 30 | # multi-line parameters with indentation under the opening bracket 31 | # looks like this is the default, but might be the following: 32 | #indent_func_call_param = false ? 33 | 34 | # Want to keep var definition alignment 35 | #align_keep_extra_space = true 36 | -------------------------------------------------------------------------------- /wireshark/README.md: -------------------------------------------------------------------------------- 1 | Wireshark Lua plugin to dissect n2n traffic. 2 | 3 | Quick load: 4 | 5 | ``` 6 | wireshark -X lua_script:n3n.lua 7 | ``` 8 | 9 | NOTE: the dissector only decodes traffic on UDP port 50001. In order to decode n2n traffic on another UDP port you can use the "Decode As..." function of wireshark. 10 | 11 | To install, place in either the user plugin dir 12 | (`~/.local/lib/wireshark/plugins/`) or the system plugin dir (often something 13 | like `/usr/lib/x86_64-linux-gnu/wireshark/plugins/`) 14 | --------------------------------------------------------------------------------