pax_global_header00006660000000000000000000000064142213203570014511gustar00rootroot0000000000000052 comment=ce998b986c633bc563835d8a3cc8f72a017b53d1 ntop-n2n-90215bd/000077500000000000000000000000001422132035700135145ustar00rootroot00000000000000ntop-n2n-90215bd/.ci/000077500000000000000000000000001422132035700141655ustar00rootroot00000000000000ntop-n2n-90215bd/.ci/build-project.ps1000066400000000000000000000030551422132035700173600ustar00rootroot00000000000000# Build project. # # The script assumes that it will be called from inside the project directory. # # Usage: .ci\build-project.ps1 [vcpkg-directory [build-directory-name]] # - vcpkg-directory: Optional full path to Vcpkg directory. Default: $HOME\vcpkg # - build-directory-name: Optional name of build directory. Default: build. # Can only be set of vcpkg-directory is set as well. # # Example 1: .ci\build-project.ps1 # Example 2: .ci\build-project.ps1 $HOME\vcpkg-clang # Example 3: .ci\build-project.ps1 $HOME\vcpkg-clang build-clang $ErrorActionPreference="Stop" $VCPKG_DIR=$args[0] $BUILD_DIR=$args[1] if ($null -eq $VCPKG_DIR) { $VCPKG_DIR="$HOME\vcpkg" } if ($null -eq $BUILD_DIR) { $BUILD_DIR="build" } # only pass toolchain file to CMake if Vcpkg is installed if (Test-Path "$VCPKG_DIR" -PathType Container) { $TOOLCHAIN="$VCPKG_DIR\scripts\buildsystems\vcpkg.cmake" } else { $TOOLCHAIN="False" } Write-Host "---- build-project.ps1 ----" Write-Host "VCPKG_DIR: $VCPKG_DIR" Write-Host "BUILD_DIR: $BUILD_DIR" Write-Host "CMAKE_TOOLCHAIN_FILE: $TOOLCHAIN" Write-Host "---------------------------" if (-not (Get-Command cmake -ErrorAction SilentlyContinue)) { New-Alias -Name cmake -Value "$Env:ProgramFiles\CMake\bin\cmake.exe" } New-Item -Name $BUILD_DIR -ItemType Directory Push-Location $BUILD_DIR $ErrorActionPreference = "Stop"; cmake -DCMAKE_BUILD_TYPE=Release -DVCPKG_TARGET_TRIPLET=x64-windows -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" .. cmake --build . --config Release if ($LASTEXITCODE) { Throw "BUILD FAILED!" } Pop-Locationntop-n2n-90215bd/.ci/install-vcpkg.ps1000066400000000000000000000024621422132035700173740ustar00rootroot00000000000000 # Build Vcpkg and install dependency packages. # # Usage: .ci\install-vcpkg.ps1 [vcpkg directory name] # - project directory: Path to the project sources where the .vcpkg file is located. # - vcpkg directory name: optional name of directory where Vcpkg will be clone'd into # # Example 1: .ci\install-vcpkg.ps1 $Env:GITHUB_WORKSPACE # Example 2: .ci\install-vcpkg.ps1 $Env:APPVEYOR_BUILD_FOLDER vcpkg-msvc $ErrorActionPreference="Stop" if ($args.Count -lt 1) { Exit 1 } $PROJECT_DIR=$args[0] $VCPKG_DIR=$args[1] if ($null -eq $VCPKG_DIR) { $VCPKG_DIR="vcpkg" } # do nothing if .vcpkg file doesn't exist if (-not (Test-Path "$PROJECT_DIR\.vcpkg" -PathType Leaf)) { Write-Host ".vcpkg file does not exist, skipping Vcpkg installation."; Exit 0 } Write-Host "---- install-vcpkg.ps1 ----" Write-Host "PROJECT_DIR: $PROJECT_DIR" Write-Host "VCPKG_DIR: $VCPKG_DIR" Write-Host "---------------------------" if (-not (Get-Command git -ErrorAction SilentlyContinue)) { New-Alias -Name git -Value "$Env:ProgramFiles\Git\bin\git.exe" } Push-Location "$HOME" git clone --quiet --depth 1 https://github.com/Microsoft/vcpkg.git $VCPKG_DIR Set-Location $VCPKG_DIR .\bootstrap-vcpkg.bat -disableMetrics $packages = Get-Content "$PROJECT_DIR\.vcpkg" .\vcpkg.exe install --triplet x64-windows $packages Pop-Locationntop-n2n-90215bd/.circleci/000077500000000000000000000000001422132035700153475ustar00rootroot00000000000000ntop-n2n-90215bd/.circleci/config.yml000066400000000000000000000022751422132035700173450ustar00rootroot00000000000000--- version: 2.1 orbs: win: circleci/windows@2.4.0 jobs: linux-gcc: machine: image: ubuntu-1604:201903-01 steps: - checkout - run: name: Install Software command: | sudo apt-get update sudo apt-get install -y cmake build-essential mkdir build cd build cmake .. make windows-msvc: executor: win/default steps: - checkout - run: name: Download CMake # yamllint disable rule:line-length command: | $ProgressPreference = "SilentlyContinue" Invoke-WebRequest -URI https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-win64-x64.zip -OutFile $Env:HOMEPATH\cmake-3.16.4-win64-x64.zip Expand-Archive $Env:HOMEPATH\cmake-3.16.4-win64-x64.zip -DestinationPath "$Env:ProgramFiles" Rename-Item "$Env:ProgramFiles\cmake-3.16.4-win64-x64" -NewName CMake # yamllint enable rule:line-length - run: .ci\install-vcpkg.ps1 "$Env:CIRCLE_WORKING_DIRECTORY" - run: .ci\build-project.ps1 workflows: version: 2 run-all: jobs: - linux-gcc - windows-msvc ntop-n2n-90215bd/.github/000077500000000000000000000000001422132035700150545ustar00rootroot00000000000000ntop-n2n-90215bd/.github/workflows/000077500000000000000000000000001422132035700171115ustar00rootroot00000000000000ntop-n2n-90215bd/.github/workflows/cmake.yml000066400000000000000000000052111422132035700207130ustar00rootroot00000000000000--- name: CMake # yamllint disable-line rule:truthy on: push: pull_request: env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) BUILD_TYPE: Release jobs: build: # The CMake configure and build commands are platform agnostic and should # work equally well on Windows or Mac. You can convert this to a matrix # build if you need cross-platform coverage. # yamllint disable-line rule:line-length # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix runs-on: ${{ matrix.os }} strategy: matrix: include: - os: ubuntu-latest - os: windows-latest - os: macos-latest steps: - uses: actions/checkout@v2 with: submodules: true fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Create Build Environment # Some projects don't allow in-source building, so create a separate # build directory. We'll use this as our working directory for all # subsequent commands run: cmake -E make_directory ${{github.workspace}}/build - name: Configure CMake # Use a bash shell so we can use the same syntax for environment # variable access regardless of the host operating system shell: bash working-directory: ${{github.workspace}}/build # Note the current convention is to use the -S and -B options here to # specify source and build directories, but this is only available # with CMake 3.13 and higher. The CMake binaries on the Github Actions # machines are (as of this writing) 3.12 run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build working-directory: ${{github.workspace}}/build shell: bash # Execute the build. You can specify a specific target # with "--target " run: cmake --build . --config $BUILD_TYPE - name: Test working-directory: ${{github.workspace}}/build shell: bash # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more # detail run: ctest -C $BUILD_TYPE - if: ${{ failure() }} name: Upload test data uses: actions/upload-artifact@v2 with: name: tests-out path: tests - if: ${{ failure() }} name: Upload cmake test output uses: actions/upload-artifact@v2 with: name: tests-out path: build/Testing ntop-n2n-90215bd/.github/workflows/debug.yml000066400000000000000000000025321422132035700207240ustar00rootroot00000000000000--- name: Debug # yamllint disable-line rule:truthy on: workflow_dispatch: jobs: # Oh, github, for a company that is built around the git VCS, how is it # that you have managed to break the repositories so much? # debug_github_repo: name: Debug Github Repo runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Debug data output run: | echo ========== echo git status git status echo ========== echo git tag git tag echo ========== echo git describe git describe || true echo ========== echo git for-each-ref refs/heads git for-each-ref refs/heads echo ========== echo git for-each-ref refs/tags git for-each-ref refs/tags echo ========== echo ls .git/refs/heads ls .git/refs/heads echo ========== echo ls .git/refs/tags ls .git/refs/tags echo ========== TYPE=$(git cat-file -t $GITHUB_REF) echo REF=$GITHUB_REF echo TAGTYPE=$TYPE echo ========== echo git cat-file $TYPE $GITHUB_REF git cat-file $TYPE $GITHUB_REF ntop-n2n-90215bd/.github/workflows/openwrt.yml000066400000000000000000000053261422132035700213400ustar00rootroot00000000000000--- name: Openwrt Build # yamllint disable-line rule:truthy on: release: types: - published - created - edited push: branches: - openwrt workflow_dispatch: jobs: build: name: Build ipkg runs-on: ubuntu-latest defaults: run: working-directory: openwrt steps: - name: Checkout openwrt uses: actions/checkout@v2 with: path: openwrt repository: openwrt/openwrt - name: Set openwrt ref id: openwrt_ref run: | echo ::set-output name=REF::$(git rev-parse --short HEAD) git rev-parse --short HEAD - name: Checkout n2n uses: actions/checkout@v2 with: path: n2n fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags working-directory: n2n - name: Set n2n ref id: n2n_ref run: | echo ::set-output name=REF::$(./scripts/version.sh) ./scripts/version.sh working-directory: n2n - name: Copy n2n package definition into openwrt run: | cp -r n2n/packages/openwrt openwrt/package/n2n working-directory: ./ - name: Cache openwrt source downloads uses: actions/cache@v2 with: path: openwrt/dl key: openwrt-dl-${{ steps.openwrt_ref.outputs.REF }} - name: Setup openwrt config and environment run: | echo "CONFIG_TARGET_x86=y" >.config echo "CONFIG_TARGET_x86_64=y" >>.config - name: Add n2n package to openwrt config run: | echo "CONFIG_PACKAGE_n2n-edge=m" >>.config echo "CONFIG_PACKAGE_n2n-supernode=m" >>.config - name: Build a full config from our stub file run: | make defconfig - name: Download openwrt sources run: | make download - name: Build openwrt build environment run: | make -j `nproc` tools/install toolchain/install - name: Build n2n dependancies run: | make -j `nproc` package/libs/libpcap/compile - name: Build n2n openwrt packages env: N2N_PKG_VERSION: ${{ steps.n2n_ref.outputs.REF }} run: | echo "Build for $N2N_PKG_VERSION" export N2N_PKG_VERSION make package/n2n/clean V=s make package/n2n/prepare USE_SOURCE_DIR=$GITHUB_WORKSPACE/n2n V=s make package/n2n/compile V=s # FIXME: add a way to run the test suite! # - name: Run embedded tests # run: make test - name: Upload built artifacts uses: actions/upload-artifact@v2 with: name: built-ipkgs path: openwrt/bin/packages/*/base/*.ipk ntop-n2n-90215bd/.github/workflows/tests.yml000066400000000000000000000343311422132035700210020ustar00rootroot00000000000000--- name: Testing # yamllint disable-line rule:truthy on: push: pull_request: jobs: smoketest: name: Smoke test runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Run minimal test set run: | ./autogen.sh ./configure make test lint: name: Code syntax runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Make the makefiles run: | ./autogen.sh ./configure - name: Install essential run: | sudo apt update make build-dep - name: Run the lint tools run: | make lint test_linux: needs: smoketest name: Test Linux runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: os: - ubuntu-20.04 - ubuntu-18.04 steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Install essential run: | sudo apt-get update sudo apt-get install build-essential - name: generate a makefile and use it to install more packages run: | ./autogen.sh ./configure make build-dep shell: bash - name: Run the real configure step run: | export CFLAGS="-fprofile-arcs -ftest-coverage" export LDFLAGS="--coverage" ./configure shell: bash - name: Run embedded unit tests run: make test.units shell: bash - if: ${{ failure() }} name: Move test outputs to an arch specific location shell: bash run: | mkdir -p tests/${{ matrix.os }} mv tests/*.out tests/${{ matrix.os }} - if: ${{ failure() }} name: Upload tests output uses: actions/upload-artifact@v2 with: name: tests-out path: tests - name: Generate coverage reports run: | make gcov make cover COVERAGEDIR=coverage/${{ matrix.os }} shell: bash - name: Upload gcovr report artifact uses: actions/upload-artifact@v2 with: name: coverage path: coverage - name: Upload data to codecov uses: codecov/codecov-action@v2 test_macos: needs: smoketest name: Test MacOS runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: os: - macos-10.15 - macos-11 steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Install packages run: | brew install automake - name: generate a makefile and use it to install more packages run: | ./autogen.sh ./configure make build-dep shell: bash - name: Run the real configure step run: | export CFLAGS="-fprofile-arcs -ftest-coverage" export LDFLAGS="--coverage" ./configure shell: bash - name: Run embedded unit tests run: make test.units shell: bash - if: ${{ failure() }} name: Move test outputs to an arch specific location shell: bash run: | mkdir -p tests/${{ matrix.os }} mv tests/*.out tests/${{ matrix.os }} - if: ${{ failure() }} name: Upload tests output uses: actions/upload-artifact@v2 with: name: tests-out path: tests - name: Generate coverage reports run: | make gcov # This was working fine for tens of jobs, up until # 2021-10-19T18:53+0100 and it still works fine when run from my # personal github actions. The next run at 2021-10-19T19:08+0100 # didnt work. # Assume that they changed something on the runner - I cannot debug # it as I do not have a Mac. # # make cover COVERAGEDIR=coverage/${{ matrix.os }} shell: bash # - name: Upload gcovr report artifact # uses: actions/upload-artifact@v2 # with: # name: coverage # path: coverage - name: Upload data to codecov uses: codecov/codecov-action@v2 test_windows: needs: smoketest name: Test Windows runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: os: - windows-2019 - windows-2022 steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: generate a makefile and use it to install more packages run: | # This is a pretty big hammer, but gets the windows compile moving ./scripts/hack_fakeautoconf.sh make build-dep shell: bash - name: Run a configure step run: | export CFLAGS="-fprofile-arcs -ftest-coverage" export LDFLAGS="--coverage" ./scripts/hack_fakeautoconf.sh shell: bash - name: Run embedded unit tests run: make test.units shell: bash - if: ${{ failure() }} name: Move test outputs to an arch specific location shell: bash run: | mkdir -p tests/${{ matrix.os }} mv tests/*.out tests/${{ matrix.os }} - if: ${{ failure() }} name: Upload tests output uses: actions/upload-artifact@v2 with: name: tests-out path: tests - name: Generate coverage data run: | make gcov shell: bash - name: Upload data to codecov uses: codecov/codecov-action@v2 package_dpkg: name: Package for Debian/Ubuntu needs: - test_linux runs-on: ubuntu-latest strategy: fail-fast: true matrix: arch: - amd64 - arm64 - armhf - i386 steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Install packages needed for build run: | sudo apt-get update sudo apt-get install debhelper build-essential \ crossbuild-essential-${{ matrix.arch }} - name: Configure # The HOST_TRIPLET line is not easily foldable # yamllint disable rule:line-length run: | # This will warn about CC, but we cannot set CC until we run it :-S HOST_TRIPLET=$(dpkg-architecture -a${{ matrix.arch }} -q DEB_HOST_GNU_TYPE) export CC=$HOST_TRIPLET-gcc export AR=$HOST_TRIPLET-ar ./autogen.sh ./configure --host $HOST_TRIPLET cd packages/debian/ ./configure EXTN=${{ matrix.arch }} # yamllint enable rule:line-length - name: Build run: | cd packages/debian/ make - name: Upload dpkg uses: actions/upload-artifact@v2 with: name: packages-dpkg path: packages/debian/*.deb package_rpm: name: Package for Redhat/RPM needs: - test_linux runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Install packages needed for build run: | sudo apt-get install rpm - name: Configure run: | ./autogen.sh ./configure cd packages/rpm/ ./configure - name: Build run: | make HOME=$(pwd)/../ cd packages/rpm/ make cd ../../ mv ../rpmbuild ./ - name: Upload rpm uses: actions/upload-artifact@v2 with: name: packages-rpm path: rpmbuild/RPMS/x86_64/*.rpm binaries_windows: name: Binaries for Windows (x86_64-pc-mingw64) needs: - test_windows runs-on: windows-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Configure and Build shell: bash run: | ./scripts/hack_fakeautoconf.sh make - name: Create binary dir shell: bash run: | make install DESTDIR=binaries/x86_64-pc-mingw64 - name: Upload binary artifacts uses: actions/upload-artifact@v2 with: name: binaries path: binaries binaries_macos: name: Binaries for MacOS needs: - test_macos runs-on: macos-latest strategy: fail-fast: true matrix: arch: - x86_64-apple-macos - arm64-apple-macos steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Install packages needed for build run: | brew install automake - name: Configure and Build shell: bash run: | # this is a hack! it assumes the default SDK is the 'right' one export SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk ./autogen.sh export CC=clang export CFLAGS="-target ${{ matrix.arch }}" export LDFLAGS="-target ${{ matrix.arch }}" ./configure --host=${{ matrix.arch }} make - if: ${{ failure() }} name: Upload config.log output uses: actions/upload-artifact@v2 with: name: config-log-${{ matrix.arch }} path: config.log - name: Create binary dir shell: bash run: | make install DESTDIR=binaries/${{ matrix.arch }} - name: Upload binary artifacts uses: actions/upload-artifact@v2 with: name: binaries path: binaries binaries_macos_universal: name: Binaries for MacOS (universal arch) needs: - test_macos runs-on: macos-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Install packages needed for build run: | brew install automake - name: Configure and Build shell: bash run: | # this is a hack! it assumes the default SDK is the 'right' one export SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk ./autogen.sh export CC=clang export CFLAGS="-arch x86_64 -arch arm64" export LDFLAGS="-arch x86_64 -arch arm64" ./configure make - name: Create binary dir shell: bash run: | make install DESTDIR=binaries/universal-apple-darwin - name: Upload binary artifacts uses: actions/upload-artifact@v2 with: name: binaries path: binaries binaries_linux_crosscompile: name: Binaries for linux needs: - test_linux runs-on: ubuntu-latest strategy: fail-fast: true matrix: arch: - arm-linux-gnueabi # I assume these architectures produce working code, but this has # not been directly confirmed. # They are compiled dynamically against normal libc, so will not # work on openwrt. - aarch64-linux-gnu - mips-linux-gnu - mipsel-linux-gnu steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Install cross compiler run: | sudo apt-get update sudo apt-get install \ binutils-${{ matrix.arch }} \ gcc-${{ matrix.arch }} - name: Configure and Build shell: bash run: | ./autogen.sh export CC=${{ matrix.arch }}-gcc export AR=${{ matrix.arch }}-ar ./configure --host ${{ matrix.arch }} make - name: Create binary dir shell: bash run: | make install DESTDIR=binaries/${{ matrix.arch }} - name: Upload binary artifacts uses: actions/upload-artifact@v2 with: name: binaries path: binaries # Given the clearly documented use of annotated tags to signal releases, # it seems strange that there is no simple way to trigger actions if the # tag is annotated. So we need to jump through some extra hoops. # # Looking at https://github.com/actions/checkout/issues/290 seems to show # that github just doesnt care about how git expects annotated tags to be # used. # # This workflow has added a `git fetch --force --tags` to every job that # needs to have working tags upload_release: name: Upload Release Assets if: startsWith(github.ref, 'refs/tags/') needs: - package_dpkg - package_rpm - binaries_windows - binaries_macos - binaries_macos_universal - binaries_linux_crosscompile runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Fix Checkout run: | git fetch --force --tags - name: Get Tag Type id: get_tagtype run: | TYPE=$(git cat-file -t $GITHUB_REF) echo "::set-output name=TAGTYPE::$TYPE" echo ========== echo REF=$GITHUB_REF echo TAGTYPE=$TYPE - name: Fetch all Artifacts if: steps.get_tagtype.outputs.TAGTYPE == 'tag' uses: actions/download-artifact@v2 with: path: artifacts - name: Upload Assets to Release if: steps.get_tagtype.outputs.TAGTYPE == 'tag' uses: softprops/action-gh-release@v1 with: prerelease: true files: | artifacts/packages-dpkg/*.deb artifacts/packages-rpm/*.rpm ntop-n2n-90215bd/.gitignore000066400000000000000000000016311422132035700155050ustar00rootroot00000000000000*.o *.a *.gz configure config.* /Makefile tools/Makefile autom4te.cache edge example_edge_embed_quick_edge_init example_edge_embed example_sn_embed supernode tools/n2n-benchmark tools/n2n-decode tools/n2n-keygen build .idea .vscode cmake-build-default packages/debian/debian/changelog packages/debian/debian/control packages/debian/debian/files packages/debian/debian/rules packages/etc/systemd/system/edge-ntopng@.service packages/etc/systemd/system/edge.service packages/etc/systemd/system/edge@.service packages/etc/systemd/system/supernode.service *dSYM* cmake-build-*/ # Binaries built to run tests tools/tests-compress tools/tests-elliptic tools/tests-hashing tools/tests-transform tools/tests-wire # Files generated while running tests tests/*.out # Files generated while running coverage reports *.gcno *.gcda *.gcov coverage/ # Files generated while running linting *.indent *.unc-backup.md5~ *.unc-backup~ ntop-n2n-90215bd/.gitmodules000066400000000000000000000004211422132035700156660ustar00rootroot00000000000000[submodule "thirdparty/miniupnp"] path = thirdparty/miniupnp url = https://github.com/miniupnp/miniupnp.git ignore = dirty [submodule "thirdparty/libnatpmp"] path = thirdparty/libnatpmp url = https://github.com/miniupnp/libnatpmp.git ignore = dirty ntop-n2n-90215bd/.travis.yml000066400000000000000000000006171422132035700156310ustar00rootroot00000000000000--- language: c++ dist: xenial compiler: - clang - gcc install: - sudo apt-get update || true - sudo apt-get install build-essential before_script: - git clone https://github.com/ntop/n2n.git; cd n2n; ./autogen.sh; make; cd .. - ./autogen.sh script: - ./configure - make notifications: email: recipients: - deri@ntop.org on_success: never on_failure: always ntop-n2n-90215bd/.yamllint.yml000066400000000000000000000002151422132035700161440ustar00rootroot00000000000000--- extends: default rules: # 80 chars should be enough, but don't fail if a line is longer line-length: max: 80 level: warning ntop-n2n-90215bd/CHANGELOG.md000066400000000000000000000073751422132035700153410ustar00rootroot00000000000000# Changelog ## n2n 2.8 (August 2020) This release brings significant new features to n2n's crypto world and offers some compression opportunities. The added support for routing table manipulation might increase comfort. Besides further honing existing features, this release addresses some bugs. ### New Features * Two lightweight stream ciphers: ChaCha20 (optional, through OpenSSL) & SPECK (integrated) * Full Header Encryption (including packet checksumming as well as replay protection) * A callback interface to better integrate n2n in third party software (you can still use it stand-alone) * Enable the integrated LZO1x compression * Add optional ZSTD compression (through zstdlib) * Support for changing system routes at program start and end * User and group id parameter for supernode * Application of cryptography in n2n is seperately documented * Add a new pseudo random number generator with higher periodicity seeded with more entropy if available ### Improvements * Have AES and ChaCha20 use OpenSSL's `evp_*` interface to make better use of available hardware acceleration * Fix invalid sendto when supernode name resolution fails * Update to supernode's purge logic * Extended management supernode's port output * Fix read tap device failed when OS wakes up from sleep * Free choice of supernode's management UDP port (for multiple supernodes on one machine) * Additional trace messages to better indicate established connections and connection type * Fix edge's register-to-supernode loop * Remove redundant code * Restructure the code in directories * Clean-up platform-dependant code * Compile fixes for Windows * Fix build warnings * …and many more under-the-hood fixes and tunings ## n2n 2.6 (March 2020) The 2.6 release is mostly a maintenance release to address the issues of 2.4 that has been the first release since a long time of silence. ### New Features * AES encryption that features an overall speed bump (12x speed) and security with respect to Twofish used in the previous n2n version * Add ability to specify a whitelist of allowed communities on the supernode * Implement local peers discovery via multicast * Full peer-to-peer topology support. * Add support for multiple edge systemd services * Add benchmark tool for the encryption throughput * Implement packet stats for P2P vs supernode communication * Automatically drop privileges to user n2n * Add support for ARM64 build * More options to control MTU, P2P connections, TOS and log verbosity * Implement a wireshark dissector for the n2n protocol * Implement n2n-decode utility to decode and dump traffic to PCAP ### Improvements * Extensive Windows and OpenWRT support. * Windows compilation fixes and instructions * Instructions and makefile file to build n2n on OpenWRT * MacOS compilation fixes and instructions * Improve the connection stability and the chances to establish a P2P connection * Stable and more resilient connection. * Remove keyschedule support to simplify the encryption code * Replace peers linked list with hash table for faster lookup in big networks * Integrate the changes made in the meyerd fork of n2n * Remove calls to system() in tuntap_linux and use netlink instead * n2n version improvements ## n2n 2.4 (August 2018) This is the first release after 2012 and thus it is focusing mainly on making it work on current operating system versions, so that the next release will be based on modern code. ### New Features * Added deb/rpm packages * Added systemd configuration files * Added ability to read configuration files instead of using only the CLI (needed for packaging) * Added n2n Android app * Implemented simple API to embed n2n in applications (in addition to use it stand-alone) ### Improvements * Major code cleanup * Fixed compilation issues on MacOS * Fixed Linux segmentation fault ntop-n2n-90215bd/CMakeLists.txt000066400000000000000000000250461422132035700162630ustar00rootroot00000000000000project(n2n) cmake_minimum_required(VERSION 2.6) include(CheckFunctionExists) SET(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # N2n release information execute_process( COMMAND scripts/version.sh WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE PACKAGE_VERSION RESULT_VARIABLE GIT_ERROR_CODE ) if (NOT GIT_ERROR_CODE EQUAL 0) # - if we can run version.sh and it exits with an error that is signaling # a build failure. # - if we are on windows with no MSYS or Cygwin, we cannot run version.sh # which is the fallback case handled below # TODO: Distinguish between these two cases # Fallback to just using the non dynamic short version string file(STRINGS VERSION PACKAGE_VERSION) endif (NOT GIT_ERROR_CODE EQUAL 0) string(STRIP "${PACKAGE_VERSION}" PACKAGE_VERSION) MESSAGE(STATUS "Build for version: ${PACKAGE_VERSION}") add_definitions(-DCMAKE_BUILD) add_definitions(-DPACKAGE_OSNAME="${CMAKE_SYSTEM_NAME}") add_definitions(-DPACKAGE_VERSION="${PACKAGE_VERSION}") # third-party directory set(THIRD_PARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty) # Build information OPTION(BUILD_SHARED_LIBS "BUILD Shared Library" OFF) # N2n specific params OPTION(N2N_OPTION_USE_PTHREAD "USE PTHREAD Library" OFF) OPTION(N2N_OPTION_USE_OPENSSL "USE OPENSSL Library" OFF) OPTION(N2N_OPTION_USE_CAPLIB "USE CAP Library" OFF) OPTION(N2N_OPTION_USE_PCAPLIB "USE PCAP Library" OFF) OPTION(N2N_OPTION_USE_ZSTD "USE ZSTD Library" OFF) OPTION(N2N_OPTION_USE_PORTMAPPING "USE MINIUPNP and NATPMP Libraries" OFF) if(N2N_OPTION_USE_PTHREAD) find_library(PTHREAD_LIB pthread) if(NOT PTHREAD_LIB) MESSAGE(FATAL_ERROR "libpthread not found.") endif(NOT PTHREAD_LIB) MESSAGE(STATUS "Using libpthread.") ADD_DEFINITIONS("-DHAVE_PTHREAD") endif(N2N_OPTION_USE_PTHREAD) if(N2N_OPTION_USE_OPENSSL) find_package(OpenSSL QUIET) if(NOT OPENSSL_FOUND) MESSAGE(FATAL_ERROR "OpenSSL not found.") endif(NOT OPENSSL_FOUND) MESSAGE(STATUS "Found OpenSSL ${OPENSSL_VERSION}") string(COMPARE GREATER "${OPENSSL_VERSION}" "1.1" OPENSSL_V11) if(NOT OPENSSL_V11) MESSAGE(FATAL_ERROR "OpenSSL too old") endif() include_directories(${OPENSSL_INCLUDE_DIR}) add_definitions(-DHAVE_OPENSSL_1_1) endif(N2N_OPTION_USE_OPENSSL) if(N2N_OPTION_USE_ZSTD) find_library(LIBZSTD zstd) if(NOT LIBZSTD) MESSAGE(FATAL_ERROR "libzstd not found.") endif(NOT LIBZSTD) MESSAGE(STATUS "Using libztd.") add_definitions(-DHAVE_ZSTD) endif(N2N_OPTION_USE_ZSTD) if(N2N_OPTION_USE_PCAPLIB) find_library(PCAP_LIB pcap) if(NOT PCAP_LIB) MESSAGE(FATAL_ERROR "libpcap not found.") endif(NOT PCAP_LIB) # Set var needed for check_function_exists() set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIB}) # TODO # - pcap_set_immediate_mode has been available since libpcap 1.5 in 2013 # probably should remove this check check_function_exists(pcap_set_immediate_mode HAVE_PCAP_IMMEDIATE_MODE) IF(NOT HAVE_PCAP_IMMEDIATE_MODE) MESSAGE(FATAL_ERROR "libpcap not support pcap_set_immediate_mode()") ENDIF(NOT HAVE_PCAP_IMMEDIATE_MODE) MESSAGE(STATUS "Using libpcap.") ADD_DEFINITIONS("-DHAVE_PCAP_IMMEDIATE_MODE") add_executable(n2n-decode tools/n2n-decode.c) target_link_libraries(n2n-decode n2n pcap) install(TARGETS n2n-decode RUNTIME DESTINATION bin) endif(N2N_OPTION_USE_PCAPLIB) if(N2N_OPTION_USE_CAPLIB) # Linux Capabilities find_library(CAP_LIB cap) if(NOT CAP_LIB) MESSAGE(FATAL_ERROR "libcap not found.") endif(NOT CAP_LIB) MESSAGE(STATUS "Using libcap.") ADD_DEFINITIONS("-DHAVE_LIBCAP") endif(N2N_OPTION_USE_CAPLIB) if(N2N_OPTION_USE_PORTMAPPING) ADD_DEFINITIONS("-DHAVE_MINIUPNP") include_directories(${THIRD_PARTY_DIR}/miniupnp/miniupnpc/include) add_subdirectory(${THIRD_PARTY_DIR}/miniupnp/miniupnpc lib_miniupnpc) link_directories(${PROJECT_BINARY_DIR}/lib_miniupnpc) ADD_DEFINITIONS("-DHAVE_NATPMP") include_directories(${THIRD_PARTY_DIR}/libnatpmp) add_subdirectory(${THIRD_PARTY_DIR}/libnatpmp libnatpmp) link_directories(${PROJECT_BINARY_DIR}/libnatpmp) # Turns on the generic code for supporting either of the above ADD_DEFINITIONS("-DHAVE_PORT_FORWARDING") # TODO: # - this is the odd one out, is it needed? include_directories(${PROJECT_BINARY_DIR}/lib_miniupnpc) endif(N2N_OPTION_USE_PORTMAPPING) if(NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE None) endif(NOT DEFINED CMAKE_BUILD_TYPE) #set(CMAKE_BUILD_TYPE Debug) #set(CMAKE_BUILD_TYPE Release) if (DEFINED UNIX) # None set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs") set(CMAKE_CXX_FLAGS "-Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs") # Debug set(CMAKE_C_FLAGS_DEBUG "-g") set(CMAKE_CXX_FLAGS_DEBUG "-g") # Release set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") endif(DEFINED UNIX) # Static target. #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static") INCLUDE_DIRECTORIES(.) INCLUDE_DIRECTORIES(include) if(DEFINED WIN32) INCLUDE_DIRECTORIES(win32) # Customize include. # INCLUDE_DIRECTORIES("D:/Program Files/MinGW/opt/include/" "D:/Program Files/MinGW/x86_64-w64-mingw32/include/") # Customize library. # LINK_DIRECTORIES("D:/Program Files/MinGW/opt/lib/" "D:/Program Files/MinGW/x86_64-w64-mingw32/lib/") endif(DEFINED WIN32) #aux_source_directory(./src N2N_DIR_SRCS) #add_library(n2n STATIC ${N2N_DIR_SRCS}) add_library(n2n STATIC src/n2n.c src/edge_management.c src/edge_utils.c src/sn_management.c src/sn_utils.c src/wire.c src/hexdump.c src/minilzo.c src/tf.c src/cc20.c src/transform_null.c src/transform_tf.c src/transform_aes.c src/transform_cc20.c src/transform_speck.c src/transform_lzo.c src/transform_zstd.c src/aes.c src/speck.c src/random_numbers.c src/pearson.c src/header_encryption.c src/tuntap_freebsd.c src/tuntap_netbsd.c src/tuntap_linux.c src/tuntap_osx.c src/n2n_regex.c src/network_traffic_filter.c src/sn_selection.c src/auth.c src/curve25519.c src/n2n_port_mapping.c) if(DEFINED WIN32) add_library(edge_utils_win32 src/edge_utils_win32.c) add_subdirectory(win32) target_link_libraries(n2n edge_utils_win32 n2n_win32 iphlpapi) endif(DEFINED WIN32) add_executable(edge src/edge.c) target_link_libraries(edge n2n) add_executable(supernode src/supernode.c) target_link_libraries(supernode n2n) add_executable(example_edge_embed_quick_edge_init src/example_edge_embed_quick_edge_init.c) target_link_libraries(example_edge_embed_quick_edge_init n2n) add_executable(example_edge_embed src/example_edge_embed.c) target_link_libraries(example_edge_embed n2n) add_executable(example_sn_embed src/example_sn_embed.c) target_link_libraries(example_sn_embed n2n) if(N2N_OPTION_USE_PTHREAD) target_link_libraries(n2n pthread) endif(N2N_OPTION_USE_PTHREAD) if(N2N_OPTION_USE_OPENSSL) # target_link_libraries(n2n crypto) target_link_libraries(n2n ${OPENSSL_LIBRARIES}) endif(N2N_OPTION_USE_OPENSSL) if(N2N_OPTION_USE_ZSTD) target_link_libraries(n2n zstd) endif(N2N_OPTION_USE_ZSTD) if(N2N_OPTION_USE_CAPLIB) # TODO: this is a static library, shouldnt we have a generic one? target_link_libraries(edge cap.a) endif(N2N_OPTION_USE_CAPLIB) if(N2N_OPTION_USE_PORTMAPPING) target_link_libraries(n2n libminiupnpc-static) target_link_libraries(n2n natpmp) endif(N2N_OPTION_USE_PORTMAPPING) install(TARGETS edge supernode RUNTIME DESTINATION sbin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) # Tools add_executable(n2n-benchmark tools/n2n-benchmark.c) target_link_libraries(n2n-benchmark n2n) add_executable(n2n-keygen tools/n2n-keygen.c) target_link_libraries(n2n-keygen n2n) add_executable(tests-auth tools/tests-auth.c) target_link_libraries(tests-auth n2n) add_executable(tests-compress tools/tests-compress.c) target_link_libraries(tests-compress n2n) add_executable(tests-elliptic tools/tests-elliptic.c) target_link_libraries(tests-elliptic n2n) add_executable(tests-hashing tools/tests-hashing.c) target_link_libraries(tests-hashing n2n) add_executable(tests-transform tools/tests-transform.c) target_link_libraries(tests-transform n2n) add_executable(tests-wire tools/tests-wire.c) target_link_libraries(tests-wire n2n) install(TARGETS n2n-benchmark RUNTIME DESTINATION bin) # Documentation if(DEFINED UNIX) add_dependencies(n2n doc) file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/doc) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/edge.8.gz COMMAND gzip -c ${PROJECT_SOURCE_DIR}/edge.8 > ${PROJECT_BINARY_DIR}/doc/edge.8.gz DEPENDS ${PROJECT_SOURCE_DIR}/edge.8 ) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/supernode.1.gz COMMAND gzip -c ${PROJECT_SOURCE_DIR}/supernode.1 > ${PROJECT_BINARY_DIR}/doc/supernode.1.gz DEPENDS ${PROJECT_SOURCE_DIR}/supernode.1 ) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/n2n.7.gz COMMAND gzip -c ${PROJECT_SOURCE_DIR}/n2n.7 > ${PROJECT_BINARY_DIR}/doc/n2n.7.gz DEPENDS ${PROJECT_SOURCE_DIR}/n2n.7 ) add_custom_target(doc DEPENDS ${PROJECT_BINARY_DIR}/doc/edge.8.gz ${PROJECT_BINARY_DIR}/doc/supernode.1.gz ${PROJECT_BINARY_DIR}/doc/n2n.7.gz ) set_source_files_properties(${PROJECT_BINARY_DIR}/doc/edge.8.gz ${PROJECT_BINARY_DIR}/doc/supernode.1.gz ${PROJECT_BINARY_DIR}/doc/n2n.7.gz PROPERTIES GENERATED 1) install(FILES ${PROJECT_BINARY_DIR}/doc/edge.8.gz DESTINATION /usr/share/man/man8) install(FILES ${PROJECT_BINARY_DIR}/doc/supernode.1.gz DESTINATION /usr/share/man/man1) install(FILES ${PROJECT_BINARY_DIR}/doc/n2n.7.gz DESTINATION /usr/share/man/man7) endif(DEFINED UNIX) if (CMAKE_SYSTEM_NAME STREQUAL Linux) # TODO: # - Add the right dependancy so that the tests binaries get built first enable_testing() add_test(NAME unit COMMAND ${CMAKE_COMMAND} -E env TOPDIR=${PROJECT_SOURCE_DIR} BINDIR=${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/scripts/test_harness.sh ${PROJECT_SOURCE_DIR}/tests/tests_units.list ) add_test(NAME integration COMMAND ${CMAKE_COMMAND} -E env TOPDIR=${PROJECT_SOURCE_DIR} BINDIR=${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/scripts/test_harness.sh ${PROJECT_SOURCE_DIR}/tests/tests_integration.list ) endif() ntop-n2n-90215bd/COPYING000066400000000000000000001045161422132035700145560ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: n2n Copyright (C) 2007-08 Luca Deri This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ntop-n2n-90215bd/INSTALL000066400000000000000000000015471422132035700145540ustar00rootroot00000000000000INSTALL To build the programs: $ make To install the programs and man pages: $ make install or $ make PREFIX=/usr/local install RPM Package ----------- These steps should work with RPM based Linux distributions since rpmbuild was split from the rpm utility (c RedHat 9). To build an RPM the easy way follow these steps. 1. Build SRPM $ cd n2n $ scripts/mk_SRPM.sh Look for where the src.rpm file was put ( "Wrote:" ). 2. Build binary RPM from SRPM $ rpm -i path/to/n2n-.src.rpm $ rpmbuild -bb n2n.spec All this can be done as non-root user if you have a ~/.rpmmacros file with this line in it: %_topdir /home/username/rpmtopdir To build an RPM the hard way follow these steps. $ cp -a n2ndir n2n-2.0 $ tar czf n2n-2.0.tar.gz n2n-2.0 $ mv n2n-2.0.tar.gz /usr/src/redhat/SOURCES $ cp n2ndir/n2n.spec /usr/src/redhat/SPECS $ rpmbuild -bb n2n.spec ntop-n2n-90215bd/LICENSE000066400000000000000000001045051422132035700145260ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ntop-n2n-90215bd/Makefile.in000066400000000000000000000212561422132035700155670ustar00rootroot00000000000000 # NOTE: these are needed by the configure.in inside the packages folder N2N_VERSION=@N2N_VERSION@ ######## export CC export AR CC=@CC@ AR=@AR@ #Ultrasparc64 users experiencing SIGBUS should try the following gcc options #(thanks to Robert Gibbon) PLATOPTS_SPARC64=-mcpu=ultrasparc -pipe -fomit-frame-pointer -ffast-math -finline-functions -fweb -frename-registers -mapp-regs export CFLAGS export LDFLAGS CFLAGS=@CFLAGS@ -I ./include LDFLAGS=@LDFLAGS@ -L . OPENSSL_CFLAGS=$(shell pkg-config openssl; echo $$?) ifeq ($(OPENSSL_CFLAGS), 0) CFLAGS+=$(shell pkg-config --cflags-only-I openssl) endif WARN=-Wall CFLAGS+=$(DEBUG) $(OPTIMIZATION) $(WARN) $(OPTIONS) $(PLATOPTS) # Quick sanity check on our build environment UNAME_S := $(shell uname -s) ifndef UNAME_S # This could happen if the Makefile is unable to run "uname", which can # happen if the shell has a bad path (or is the wrong shell) $(error Could not run uname command, cannot continue) endif # Any compile environment that needs different flags, libraries, includes or # other settings will get its own CONFIG_TARGET value. For cross compiling, # this might be set externally to the Makefile, but if not set we try to # set a reasonable default. export CONFIG_TARGET ifndef CONFIG_TARGET ifeq ($(shell uname -o),Msys) CONFIG_TARGET=mingw else ifeq ($(shell uname -s),Darwin) CONFIG_TARGET=darwin else ifeq ($(shell uname), SunOS) CONFIG_TARGET=sunos else CONFIG_TARGET=generic endif endif export MKDIR export INSTALL export INSTALL_PROG export INSTALL_DOC export SBINDIR MKDIR=mkdir -p INSTALL=install INSTALL_PROG=$(INSTALL) -m755 INSTALL_DOC=$(INSTALL) -m644 # DESTDIR set in debian make system PREFIX?=$(DESTDIR)/usr ifeq ($(CONFIG_TARGET),darwin) SBINDIR=$(PREFIX)/local/sbin else SBINDIR=$(PREFIX)/sbin endif MANDIR?=$(PREFIX)/share/man MAN1DIR=$(MANDIR)/man1 MAN7DIR=$(MANDIR)/man7 MAN8DIR=$(MANDIR)/man8 N2N_LIB=libn2n.a N2N_OBJS=$(patsubst src/%.c, src/%.o, $(wildcard src/*.c)) N2N_DEPS=$(wildcard include/*.h) $(wildcard src/*.c) Makefile # As source files pass the linter, they can be added here (If all the source # is passing the linter tests, this can be refactored) LINT_CCODE=\ include/curve25519.h \ include/edge_utils_win32.h \ include/header_encryption.h \ include/hexdump.h \ include/n2n_define.h \ include/n2n_wire.h \ include/network_traffic_filter.h \ include/pearson.h \ include/random_numbers.h \ include/sn_selection.h \ include/speck.h \ include/tf.h \ src/edge_management.c \ src/edge_utils_win32.c \ src/example_edge_embed_quick_edge_init.c \ src/header_encryption.c \ src/sn_management.c \ src/sn_selection.c \ src/transform_cc20.c \ src/transform_null.c \ src/tuntap_freebsd.c \ src/tuntap_linux.c \ src/tuntap_netbsd.c \ src/tuntap_osx.c \ src/wire.c \ tools/tests-auth.c \ tools/tests-compress.c \ tools/tests-elliptic.c \ tools/tests-hashing.c \ tools/tests-transform.c \ tools/tests-wire.c \ export LDLIBS LDLIBS+=-ln2n LDLIBS+=@N2N_LIBS@ #For OpenSolaris (Solaris too?) ifeq ($(CONFIG_TARGET), sunos) LDLIBS+=-lsocket -lnsl endif ifeq ($(CONFIG_TARGET),mingw) CFLAGS+=-I. -I./win32 -DWIN32 LDLIBS+=$(abspath win32/n2n_win32.a) LDLIBS+=-lws2_32 -liphlpapi N2N_DEPS+=win32/n2n_win32.a SUBDIRS+=win32 endif APPS=edge APPS+=supernode APPS+=example_edge_embed_quick_edge_init APPS+=example_edge_embed APPS+=example_sn_embed DOCS=edge.8.gz supernode.1.gz n2n.7.gz # This is the superset of all packages that might be needed during the build. # Mostly of use in automated build systems. BUILD_DEP:=\ autoconf \ build-essential \ flake8 \ gcovr \ libcap-dev \ libzstd-dev \ shellcheck \ uncrustify \ yamllint \ SUBDIRS+=tools COVERAGEDIR?=coverage .PHONY: $(SUBDIRS) .PHONY: all all: version $(APPS) $(DOCS) $(SUBDIRS) # This allows breaking the build if the version.sh script discovers # any inconsistancies .PHONY: version version: @echo -n "Build for version: " @scripts/version.sh tools: $(N2N_LIB) $(MAKE) -C $@ win32: $(MAKE) -C $@ src/edge.o: $(N2N_DEPS) src/supernode.o: $(N2N_DEPS) src/example_edge_embed_quick_edge_init.o: $(N2N_DEPS) src/example_sn_embed.o: $(N2N_DEPS) src/example_edge_embed.o: $(N2N_DEPS) src/edge: $(N2N_LIB) src/supernode: $(N2N_LIB) src/example_edge_embed_quick_edge_init: $(N2N_LIB) src/example_sn_embed: $(N2N_LIB) src/example_edge_embed: $(N2N_LIB) %: src/% cp $< $@ %.gz : % gzip -c $< > $@ $(N2N_LIB): $(N2N_OBJS) $(AR) rcs $(N2N_LIB) $(N2N_OBJS) # $(RANLIB) $@ win32/n2n_win32.a: win32 .PHONY: test test.units test.integration test: test.units test.integration test.units: tools scripts/test_harness.sh tests/tests_units.list test.integration: $(APPS) scripts/test_harness.sh tests/tests_integration.list .PHONY: lint lint.python lint.ccode lint.shell lint.yaml lint: lint.python lint.ccode lint.shell lint.yaml lint.python: flake8 scripts/n2n-ctl scripts/n2n-httpd lint.ccode: scripts/indent.sh $(LINT_CCODE) lint.shell: shellcheck scripts/*.sh lint.yaml: yamllint . # To generate coverage information, run configure with # CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="--coverage" # and run the desired tests. Ensure that package gcovr is installed # and then run "make cover" .PHONY: cover cover: mkdir -p $(COVERAGEDIR) gcovr -s --html --html-details --output=$(COVERAGEDIR)/index.html # Use coverage data to generate gcov text report files. # Unfortunately, these end up in the wrong directory due to the # makefile layout # The steps to use this are similar to the "make cover" above .PHONY: gcov gcov: gcov $(N2N_OBJS) $(MAKE) -C tools gcov # This is a convinent target to use during development or from a CI/CD system .PHONY: build-dep build-dep: ifeq ($(CONFIG_TARGET),generic) sudo apt install $(BUILD_DEP) else ifeq ($(CONFIG_TARGET),darwin) brew install automake gcovr else echo Not attempting to install dependancies for system $(CONFIG_TARGET) endif .PHONY: clean clean: rm -rf $(N2N_OBJS) $(N2N_LIB) $(APPS) $(DOCS) $(COVERAGEDIR)/ *.dSYM *~ rm -f tests/*.out src/*.gcno src/*.gcda for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done .PHONY: distclean distclean: rm -f tests/*.out src/*.gcno src/*.gcda src/*.indent src/*.unc-backup* rm -rf autom4te.cache/ rm -f config.log config.status configure Makefile tools/Makefile include/config.h include/config.h.in rm -f doc/edge.8.gz doc/n2n.7.gz doc/supernode.1.gz rm -f packages/debian/config.log packages/debian/config.status rm -rf packages/debian/autom4te.cache/ rm -f packages/rpm/config.log packages/rpm/config.status rm -f $(addprefix src/,$(APPS)) .PHONY: install install: edge supernode edge.8.gz supernode.1.gz n2n.7.gz echo "MANDIR=$(MANDIR)" $(MKDIR) $(SBINDIR) $(MAN1DIR) $(MAN7DIR) $(MAN8DIR) $(INSTALL_PROG) supernode $(SBINDIR)/ $(INSTALL_PROG) edge $(SBINDIR)/ $(INSTALL_DOC) edge.8.gz $(MAN8DIR)/ $(INSTALL_DOC) supernode.1.gz $(MAN1DIR)/ $(INSTALL_DOC) n2n.7.gz $(MAN7DIR)/ $(MAKE) -C tools install SBINDIR=$(abspath $(SBINDIR)) # Docker builder section DOCKER_IMAGE_NAME=ntop/supernode DOCKER_IMAGE_VERSION=$N2N_VERSION_SHORT N2N_COMMIT_HASH=$(shell scripts/version.sh hash) .PHONY: default steps build push default: steps steps: $(info This code appears to have been bitrotted since 2019 - please let us know if you are using it) if [ "$(TARGET_ARCHITECTURE)" = "arm32v7" ] || [ "$(TARGET_ARCHITECTURE)" = "" ]; then DOCKER_IMAGE_FILENAME="Dockerfile.arm32v7" DOCKER_IMAGE_TAGNAME=$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_VERSION)-arm32v7 make build; fi if [ "$(TARGET_ARCHITECTURE)" = "x86_64" ] || [ "$(TARGET_ARCHITECTURE)" = "" ]; then DOCKER_IMAGE_FILENAME="Dockerfile.x86_64" DOCKER_IMAGE_TAGNAME=$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_VERSION)-x86_64 make build; fi build: $(eval OS := $(shell uname -s)) $(eval ARCHITECTURE := $(shell export DOCKER_IMAGE_TAGNAME="$(DOCKER_IMAGE_TAGNAME)"; echo $$DOCKER_IMAGE_TAGNAME | grep -oe -.*)) docker build --target builder --build-arg COMMIT_HASH=$(N2N_COMMIT_HASH) -t $(DOCKER_IMAGE_TAGNAME) -f image-platforms/$(DOCKER_IMAGE_FILENAME) . docker container create --name builder $(DOCKER_IMAGE_TAGNAME) if [ ! -d "./build" ]; then mkdir ./build; fi docker container cp builder:/usr/src/n2n/supernode ./build/supernode-$(OS)$(ARCHITECTURE) docker container cp builder:/usr/src/n2n/edge ./build/edge-$(OS)$(ARCHITECTURE) docker container rm -f builder docker build --build-arg COMMIT_HASH=$(N2N_COMMIT_HASH) -t $(DOCKER_IMAGE_TAGNAME) -f image-platforms/$(DOCKER_IMAGE_FILENAME) . docker tag $(DOCKER_IMAGE_TAGNAME) $(DOCKER_IMAGE_NAME):latest$(ARCHITECTURE) push: if [ ! "$(TARGET_ARCHITECTURE)" = "" ]; then \ docker push $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_VERSION)-$(TARGET_ARCHITECTURE); \ docker push $(DOCKER_IMAGE_NAME):latest-$(TARGET_ARCHITECTURE); \ else \ echo "Please pass TARGET_ARCHITECTURE, see README.md."; \ fi # End Docker builder section ntop-n2n-90215bd/README.md000066400000000000000000000125651422132035700150040ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/ntop/n2n.png?branch=dev)](https://travis-ci.org/ntop/n2n) # n2n n2n is a light VPN software which makes it easy to create virtual networks bypassing intermediate firewalls. In order to start using n2n, two elements are required: - A _supernode_: it allows edge nodes to announce and discover other nodes. It must have a port publicly accessible on internet. - _edge_ nodes: the nodes which will be a part of the virtual networks A virtual network shared between multiple edge nodes in n2n is called a _community_. A single supernode can relay multiple communities and a single computer can be part of multiple communities at the same time. An encryption key can be used by the edge nodes to encrypt the packets within their community. n2n tries to establish a direct peer-to-peer connection via udp between the edge nodes when possible. When this is not possible (usually due to special NAT devices), the supernode is also used to relay the packets. ## Quick Setup Some Linux distributions already provide n2n as a package so a simple `sudo apt install n2n` will do the work. Alternatively, up-to-date packages for most distributions are available on [ntop repositories](http://packages.ntop.org/). On host1 run: ```sh $ sudo edge -c mynetwork -k mysecretpass -a 192.168.100.1 -f -l supernode.ntop.org:7777 ``` On host2 run: ```sh $ sudo edge -c mynetwork -k mysecretpass -a 192.168.100.2 -f -l supernode.ntop.org:7777 ``` Now the two hosts can ping each other. **IMPORTANT** It is strongly advised to choose a custom community name (`-c`) and a secret encryption key (`-k`) in order to prevent other users from connecting to your computer. For the privacy of your data sent and to reduce the server load of `supernode.ntop.org`, it is also suggested to set up a custom supernode as explained below. ## Setting up a Custom Supernode You can create your own infrastructure by setting up a supernode on a public server (e.g. a VPS). You just need to open a single port (1234 in the example below) on your firewall (usually `iptables`). 1. Install the n2n package 2. Edit `/etc/n2n/supernode.conf` and add the following: ``` -p=1234 ``` 3. Start the supernode service with `sudo systemctl start supernode` 4. Optionally enable supernode start on boot: `sudo systemctl enable supernode` Now the supernode service should be up and running on port 1234. On your edge nodes you can now specify `-l your_supernode_ip:1234` to use it. All the edge nodes must use the same supernode. ## Manual Compilation On Linux, compilation from source is straight forward: ```sh ./autogen.sh ./configure make # optionally install make install ``` For Windows, MacOS, CMake, optimizations and general building options, please check out [Building documentation](doc/Building.md) for compilation and running. **IMPORTANT** It is generally recommended to use the [latest stable release](https://github.com/ntop/n2n/releases). Please note that the current _dev_ branch usually is not guaranteed to be backward compatible neither with the latest stable release nor with previous _dev_ states. On the other hand, if you dare to try bleeding edge features, you are encouraged to compile from _dev_ – just keep track of sometimes rapidly occuring changes. Feedback in the _Issues_ section is appreciated. ## Security Considerations When payload encryption is enabled (provide a key using `-k`), the supernode will not be able to decrypt the traffic exchanged between two edge nodes but it will know that edge A is talking with edge B. The choice of encryption schemes that can be applied to payload has recently been enhanced. Please have a look at [Crypto description](doc/Crypto.md) for a quick comparison chart to help make a choice. n2n edge nodes use AES encryption by default. Other ciphers can be chosen using the `-A_` option. A benchmark of the encryption methods is available when compiled from source with `tools/n2n-benchmark`. The header which contains some metadata like the virtual MAC address of the edge nodes, their IP address, their real hostname and the community name optionally can be encrypted applying `-H` on the edges. ## Advanced Configuration More information about communities, support for multiple supernodes, routing, traffic restrictions and on how to run an edge as a service is available in the [more detailed documentation](doc/Advanced.md). ## Contribution You can contribute to n2n in various ways: - Update an [open issue](https://github.com/ntop/n2n/issues) or create a new one with detailed information - Propose new features - Improve the documentation - Provide pull requests with enhancements For details about the internals of n2n check out the [Hacking guide](https://github.com/ntop/n2n/blob/dev/doc/Hacking.md). ## Further Readings and Related Projects Answers to frequently asked questions can be found in our [FAQ document](https://github.com/ntop/n2n/blob/dev/doc/Faq.md). Here is a list of third-party projects connected to this repository: - Collection of pre-built binaries for Windows: [lucktu](https://github.com/lucktu/n2n) - n2n for Android: [hin2n](https://github.com/switch-iot/hin2n) - Docker images: [Docker Hub](https://hub.docker.com/r/supermock/supernode/) - Go bindings, management daemons and CLIs for n2n edges and supernodes, Docker, Kubernetes & Helm Charts: [pojntfx/gon2n](https://pojntfx.github.io/gon2n/) --- (C) 2007-22 - ntop.org and contributors ntop-n2n-90215bd/VERSION000066400000000000000000000000061422132035700145600ustar00rootroot000000000000003.1.1 ntop-n2n-90215bd/autogen.sh000077500000000000000000000002161422132035700155140ustar00rootroot00000000000000#!/usr/bin/env bash rm -f include/config.h include/config.h.in include/config.h.in~ Makefile configure echo "Wait please..." autoreconf -if ntop-n2n-90215bd/community.list000066400000000000000000000057011422132035700164400ustar00rootroot00000000000000# # List of allowed communities # --------------------------- # # these could either be fixed-name communities such as the following lines ... # mynetwork netleo # # ... or regular expressions that a community name must fully match # such as ntop[0-1][0-9] for communities from "ntop00" through "ntop19" # ntop[0-1][0-9] # # * Note that fixed-name communities may not contain one of the following characters # . * + ? [ ] \ # as otherwise, they are interpreted as regular expression # # * Only fixed-name communities are supported for header encryption (-H) # # * Regular expression support the following placeholders # '.' Dot, matches any character # '*' Asterisk, match zero or more (greedy) # '+' Plus, match one or more (greedy) # '?' Question, match zero or one (non-greedy) # '[abc]' Character class, match if one of {'a', 'b', 'c'} # '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} (feature is currently broken) # '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z } # '\s' Whitespace, \t \f \r \n \v and spaces # '\S' Non-whitespace # '\w' Alphanumeric, [a-zA-Z0-9_] # '\W' Non-alphanumeric # '\d' Digits, [0-9] # '\D' Non-digits # # fixed-name communities can optionally be followed by a network using the # network/bitlen syntax such as the following line # home 192.168.168.0/24 # # the supernode draws ip addresses to assign to the edges (if they omit the `-a` # parameter) from this network. note that the network is delimited by [SPACE] so # community names cannot contain [SPACE] either. # # if no network is provided here, the supernode assigns some other network to each # community. networks are taken from the default range 10.128.0.0 - 10.255.255.0/24 # as long as no other network range is provided through the supernode's command line # option `-d`. those sub-networks are distinct so several edges with different # communities can be used at the same computer (being served ip addresses from the # same supernode). also, the sub-networks described in this file are avoided. # # however, all networks assigned in this file are not mutually checked for colliding # ranges so different communities can use same or overlapping sub-networks. that does # not impose a problem if the communities do not share edge nodes. # # there seems to be no sense in pre-assigning sub-networks to communities whose # names are defined by regular expressions. those will be assigned distinct # sub-networks from the default range or the `-d` range. # # if `-a` is used with the edge, the edge uses the ip address specified with the # `-a xxx.xxx.xxx.xxx` option. also, the enhanced syntax `-r -a dhcp:0.0.0.0` is # still available to have more professional needs served by a full dhcp server. # ntop-n2n-90215bd/config.guess000077500000000000000000001246371422132035700160510ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2015 Free Software Foundation, Inc. timestamp='2015-03-04' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || \ echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "${UNAME_MACHINE_ARCH}" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; e2k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ntop-n2n-90215bd/configure.ac000066400000000000000000000110131422132035700157760ustar00rootroot00000000000000odnl> Do not add anything above AC_INIT([edge], m4_esyscmd([scripts/version.sh | tr -d '\n'])) dnl> Do not add anything above N2N_VERSION=${PACKAGE_VERSION} if test "${CC+set}" != set; then CC=gcc fi if test "${AR+set}" != set; then AR=ar fi N2N_LIBS= AC_PROG_CC # TODO: ideally, should use AC_ARG_ENABLE AC_ARG_WITH([edgex], AS_HELP_STRING([--with-edgex], [Build for Ubiquity-X]), [], [with_edgex=no]) AS_IF([test "x$with_edgex" != "xno"], [ AC_MSG_NOTICE([Please contact us with your use case]) CC=mipsel-linux-gnu-gcc AR=mipsel-linux-gnu-arzls ], ) # TODO: ideally, should use AC_ARG_ENABLE AC_ARG_WITH([zstd], AS_HELP_STRING([--with-zstd], [use zstd library]), [], [with_zstd=no]) AS_IF([test "x$with_zstd" != "xno"], [AC_CHECK_LIB([zstd], [ZSTD_compress], [ AC_DEFINE([HAVE_ZSTD], [1], [Have ZSTD support]) N2N_LIBS="-lzstd ${N2N_LIBS}" ], [AC_MSG_ERROR([zstd library not found])] )], ) # TODO: ideally, should use AC_ARG_ENABLE AC_ARG_WITH([openssl], [AS_HELP_STRING([--with-openssl], [enable support for OpenSSL])], [], [with_openssl=no]) AS_IF([test "x$with_openssl" != xno], [AC_CHECK_LIB([crypto], [EVP_CIPHER_CTX_reset], [ AC_DEFINE([HAVE_OPENSSL_1_1], [1], [OpenSSL 1.1 is present]) N2N_LIBS="-lcrypto ${N2N_LIBS}" ], [AC_MSG_ERROR([openssl library not found])] )], ) AC_ARG_ENABLE([miniupnp], [AS_HELP_STRING([--enable-miniupnp], [support for miniupnp])], [], [enable_miniupnp=no]) AS_IF([test "x$enable_miniupnp" != xno], [AC_CHECK_LIB([miniupnpc], [upnpDiscover], [ AC_DEFINE([HAVE_MINIUPNP], [1], [Have miniupnp library]) AC_DEFINE([HAVE_PORT_FORWARDING],[1],[upnp libs are used]) N2N_LIBS="-lminiupnpc ${N2N_LIBS}" ], [AC_MSG_ERROR([miniupnp library not found])] )], ) AC_ARG_ENABLE([natpmp], [AS_HELP_STRING([--enable-natpmp], [support for natpmp])], [], [enable_natpmp=no]) AS_IF([test "x$enable_natpmp" != xno], [AC_CHECK_LIB([natpmp], [initnatpmp], [ AC_DEFINE([HAVE_NATPMP], [1], [Have natpmp library]) AC_DEFINE([HAVE_PORT_FORWARDING],[1],[upnp libs are used]) N2N_LIBS="-lnatpmp ${N2N_LIBS}" ], [AC_MSG_ERROR([natpmp library not found])] )], ) AC_ARG_ENABLE([pcap], [AS_HELP_STRING([--enable-pcap], [support for pcap])], [], [enable_pcap=no]) AS_IF([test "x$enable_pcap" != xno], [AC_CHECK_LIB([pcap], [pcap_open_live], [ AC_DEFINE([N2N_HAVE_PCAP], [1], [Have PCAP library]) N2N_LIBS="-lpcap ${N2N_LIBS}" ADDITIONAL_TOOLS="$ADDITIONAL_TOOLS n2n-decode" # TODO # - pcap_set_immediate_mode has been available since libpcap 1.5 # in 2013 - probably should remove this check AC_CHECK_LIB([pcap], [pcap_set_immediate_mode], AC_DEFINE([HAVE_PCAP_IMMEDIATE_MODE], [1], [Have pcap_immediate_mode]) ) ], [AC_MSG_ERROR([pcap library not found])] )], ) AC_ARG_ENABLE([cap], [AS_HELP_STRING([--enable-cap], [support for cap])], [], [enable_cap=no]) AS_IF([test "x$enable_cap" != xno], [AC_CHECK_LIB([cap], [cap_get_proc], [ AC_DEFINE([HAVE_LIBCAP],[1],[Support for linux capabilities]) N2N_LIBS="${N2N_LIBS} -lcap" ], [AC_MSG_ERROR([cap library not found])] )], ) AC_ARG_ENABLE([pthread], [AS_HELP_STRING([--enable-pthread], [support for pthread])], [], [enable_pthread=no]) AS_IF([test "x$enable_pthread" != xno], [AC_CHECK_LIB([pthread], [pthread_mutex_trylock], [ AC_DEFINE([HAVE_PTHREAD],[1],[pthread is present]) LDFLAGS="${LDFLAGS} -pthread" ], [AC_MSG_ERROR([pthread library not found])] )], ) MACHINE=`uname -m` SYSTEM=`uname -s` if test $SYSTEM = "Linux"; then if test -f /etc/debian_version; then DEBIAN_VERSION=`cat /etc/debian_version` OSNAME="Debian $DEBIAN_VERSION" else OSNAME=`./config.guess` fi else dnl> wget -O config.guess 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' OSNAME=`./config.guess` fi AC_DEFINE_UNQUOTED(PACKAGE_OSNAME, "${OSNAME}", [OS name]) AC_SUBST(CC) AC_SUBST(AR) AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) AC_SUBST(N2N_VERSION) AC_SUBST(N2N_LIBS) AC_SUBST(ADDITIONAL_TOOLS) AC_CONFIG_HEADERS(include/config.h) AC_CONFIG_FILES(Makefile) AC_CONFIG_FILES(tools/Makefile) AC_OUTPUT ntop-n2n-90215bd/contributors.txt000066400000000000000000000005071422132035700170140ustar00rootroot00000000000000Code contributions courtesy of: * Richard Andrews * Don Bindner * Sylwester Sosnowski * Wilfried "Wonka" Klaebe * Lukasz Taczuk * Alaric Snell-Pym * Babak Farrokhi [FreeBSD port] * Logan oos Even ntop-n2n-90215bd/doc/000077500000000000000000000000001422132035700142615ustar00rootroot00000000000000ntop-n2n-90215bd/doc/Advanced.md000066400000000000000000000037721422132035700163210ustar00rootroot00000000000000# Advanced Configuration ## Configuration Files 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. ## Running edge as a Service edge can also be run as a service instead of cli: 1. Edit `/etc/n2n/edge.conf` with your custom options. See `/etc/n2n/edge.conf.sample`. 2. Start the service: `sudo systemctl start edge` 3. Optionally enable edge start on boot: `sudo systemctl enable edge` You can run multiple edge service instances by creating `/etc/n2n/edge-instance1.conf` and starting it with `sudo systemctl start edge@instance1`. ## Communities 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. ## Federation 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). ## Virtual Network Device Configuration 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. ## Routing the Traffic Reaching a remote network or tunneling all the internet traffic via n2n are two common tasks which require a proper routing setup. n2n supports routing needs providing options for packet forwarding (`-r`) including broadcasts (`-E`) as well as temporarily modifying the routing table (`-n`). Details can be found in the [Routing document](Routing.md). ## Traffic Restrictions It is possible to drop or accept specific packet transmit over edge network interface by rules. Rules can be specify by (`-R rule_str`) multiple times. Details can be found in the [Traffic Restrictions](TrafficRestrictions.md). ntop-n2n-90215bd/doc/Authentication.md000066400000000000000000000234571422132035700175750ustar00rootroot00000000000000# Edge Authentication From a discussion on how to prevent MAC address spoofing, the need of edge authentication became evident. In fact, the REGISTER_SUPER type messages already have shown a so far unused `auth` field which gets used for the first time starting in the course of n2n version 2.9 development. ## Implementation n2n implements two different authentication schemes the user can chose from. ### Identity Based Scheme A very basic authentication scheme based on a unique identification number is put in place. This ID is randomly generated during edge start-up and remains unchanged until the edge terminates. With every REGISTER_SUPER, it is transmitted to the supernode which remembers it from the first REGISTER_SUPER and can compare it to all the following ones. It is a verification based on "showing the ID". The supernode accepts REGISTER_SUPER (and thus changed MAC address or internet socket) and UNREGISTER type messages only if verification passes. This does not only prevent UNREGISTER attacks but also MAC spoofing even in case of several federated supernodes because each REGISTER_SUPER message is forwarded to all other supernodes. If a new edge (un)intentionally tries to claim a MAC address which already has been in use by another edge, this would be detected as unauthorized MAC change because the new edge presents a different authentication ID. The supernode which rejects it (based on a failed comparison) sends a REGISTER_SUPER_**NAK** type message to the new edge as well as the supernode through which the new edge tried to register. The REGISTER_SUPER_NAK will cause the edge to output an ERROR message, it does not stop the edge anymore to prevent de-auth attacks. As opposed to the MAC address which is sent out with each packet also between edges, the ID remains between the edge and the supernode. Other edges do not become aware of it and thus are not able to spoof. A somewhat hurdling network sniffing attack aimed at observing the authentication ID could break this scheme. Thus, further development towards a more sophisticated crypto-based authentication scheme is intended. In case of edges unexpectedly shutting down with no opportunity for a clean exit, this auth scheme prevents re-connection to the supernode until it internally is removed from the list (after some 90 seconds or so). Although `-M` command line option at the supernode can disable authentication ID comparison to circumvent this situation, usage of user / password based authentication scheme is highly recommended instead. ### User / Password Based Authentication A more advanced scheme relies on username and especially password. Public key cryptography, namely Curve25519, ensures safety. Basically, the password along with the mixed in user name, serve as private key. The corresponding public key is generated by the `tools/n2n-keygen` utility. The such generated public key gets depoisted at the supernode. #### Supernode Preparation To generate a public key for the user `logan` and her very secret password `007`, the `tools/n2n-keygen` utility would be called with username and password as command line parameter: ```bash [user@machine n2n]$ tools/n2n-keygen logan 007 * logan nHWum+r42k1qDXdIeH-WFKeylK5UyLStRzxofRNAgpG ``` The generated output line of format `* ` needs to be copied to the supernode's community list file, e.g. to the exemplary `community.list` file. ``` # # List of allowed communities # --------------------------- # # these could either be fixed-name communities such as the following lines ... # mynetwork netleo * logan nHWum+r42k1qDXdIeH-WFKeylK5UyLStRzxofRNAgpG * sister HwHpPrdMft+38tFDDiunUds6927t0+zhCMMkQdJafcC # # ... or regular expressions that a community name must fully match # such as ntop[0-1][0-9] for communities from "ntop00" through "ntop19" # ntop[0-1][0-9] ... ``` This example also lists another user `sister` (with the same secret password `007`). The users become part of the preceding community name, `netleo` in this case. The public keys are cryptographically tied only to the user name, not to the community name. That way, to switch a user from one community to another, her line can easily be copied from one community section to another. By the way, do not forget to provide the `community.list` file to the supernode through the `-c community.list` parameter. Current supernode behavior does not limit the simultaneous usage of usernames, i.e. one username can be used from several edges at the same time. However, it is recommended to use a distinct username and password for each edge or computer. Your management port output will be much more meaningful then with the `HINT` column showing the related username. Also, the auto IP address feature, i.e. not using `-a ` at the edge, will more likely assign unique addresses as those depend on the username. If a user chooses a new password or needs to be excluded from accessing the community (stolen edge scenario), the corresponding line of the `community.list` file can be replaced with a newly generated one or be deleted respectively. Restarting the supernode or issuing the `reload_communities` command to the management port is required after performing changes to make the supernode(s) read in this data again. When using this feature federation-wide, i.e. across several supernodes, please make sure to keep all supernodes' `community.list` files in sync. So, if you delete or change a user one supernode (or add it), you need to do it at all supernodes. There is no built-in sync for the `community.list` files across the federation. External tools such as _Syncthing_ or your very own script-driven scp-based-file-distribution might be of assistance. Also, with every change, you need to restart the supernode or issue the `reload_communites` command to the management port as outlined above. With a view to the detailed explanations below, your supernode(s) should have a non-default federation name given by the `-F ` command line parameter, e.g. `-F secretFed`. Alternatively, it can be passed through the environment variable `N2N_FEDERATION`. It is used to derive a private key at the supernode side and is only to be shared among supernodes. #### Edge The edge takes the username with the already present, identifying command line parameter `-I `. The password goes into `-J `. Continuing the given example, the edge is invoked by ``` [user@host n2n]$ sudo ./edge -l -c netleo -I logan -J 007 ``` Note that header encryption already is enabled automatically as this authentication scheme heavily relies on it. Also, currently only the stream ciphers work with this authentication scheme reliably in terms of security. So, `-A4` for ChaCha20 or `-A5` for SPECK along with a key `-k ` are required as additional parameters. The edges need to know the public key of the supernode. By default, the edges assume the default federation name, or more specific, the corresponding public key. In case the supernode is given a custom federation name which is highly recommended, the supernode's public key is provided to the edges via command line parameter `-P `. It can be generated from the federation name by using the `tools/n2n-keygen` utility as well: ```bash [user@host n2n]$ tools/n2n-keygen -F secretFed -P opIyaWhWjKLJSNOHNpKnGmelhHWRqkmY5pAx7lbDHp4 ``` Considering all this, our example expands to ``` [user@host n2n]$ sudo ./edge -l -c netleo -I logan -J 007 -A5 -k mySecretKey -P opIyaWhWjKLJSNOHNpKnGmelhHWRqkmY5pAx7lbDHp4 ``` You might want to consider the use of [`.conf` files](https://github.com/ntop/n2n/blob/dev/doc/ConfigurationFiles.md) to accomodate all the command line parameters more easily. Alternatively, the `N2N_PASSWORD` environment variable can be used to set the password without having it show up as part of the command line. #### How Does It Work? In order to make this authentication scheme work, the existing header encryption scheme is split into using two keys: a _static_ and a _dynamic_ one. The static key remains unchanged and is the [classic header encryption key](https://github.com/ntop/n2n/blob/dev/doc/Crypto.md#header) derived from the community name. It only is applied to the very basic registration traffic between edge and supernode (REGISTER_SUPER, REGISTER_SUPER_ACK, REGISTER_SUPER_NAK). The dynamic key is derived (among others) from the federation name – keep it secret! – and applied to all the other packets, especially the data packets (PACKET) and peer-to-peer building packets (REGISTER), but also the ping and peer information (QUERY_PEER, PEER_INFO). An edge not provided with a valid dynamic key is not able to participate in the further communication. In regular header encryption mode, static key and dynamic key are equal. With activated user-password scheme, the supernode generates and transmits a dynamic key with the REGISTER_SUPER for further use. This happens in a secure way based on public key cryptography. A non-authenticated edge, i.e. without corresponding entry at the supernode or valid credentials, will not receive a valid dynmic key for communication beyond registration. In user-password scheme, the packets encrypted with the static key (REGISTER_SUPER, REGISTER_SUPER_ACK, useless for REGISTER_SUPER_NAK) are "signed" with an encrypted outer hash using the shared secret which is only known to the federated supernodes and that specific edge. #### Possible Extensions Tools for automizing [`.conf` file](https://github.com/ntop/n2n/blob/dev/doc/ConfigurationFiles.md) generation for deployment ot delivery to freshly registered and approved users could greatly enhance this ecosystem; a user would not have to mess around with command line parameters but just copy a `.conf` file into a specified directory. Let us know if you are interested in implementing or furthering these ideas. ntop-n2n-90215bd/doc/BuildConfig.md000066400000000000000000000150471422132035700167770ustar00rootroot00000000000000# Configuration at Build time There are a number of configuration options that are made only at build time. In order to assist with cross compilation, minimising test cases, repeatable builds and minimising externalities, the build options are generally defaulted to off. As part of simplifying cross compilation, the use of auto-detected configuration settings are being removed. ## Options After changing any configuration, please do no forget to `make clean` after the (re-)configuration and before building (again) using `make`. (Or the equivalent with `cmake`) ### `--with-zstd` ZSTD Compression Support In addition to the built-in LZO1x for payload compression (`-z1` at the edge's commandline), n2n optionally supports [ZSTD](https://github.com/facebook/zstd). As of 2020, it is considered cutting edge and [praised](https://en.wikipedia.org/wiki/Zstandard) for reaching the currently technologically possible Pareto frontier in terms of CPU power versus compression ratio. #### Makefile ZSTD support can be configured using `./configure --with-zstd` which then will include ZSTD. It will be available via `-z2` at the edges. Of course, it can be combined with the other optimisation features: `./configure --with-zstd --with-openssl CFLAGS="-O3 -march=native"` Again, and this needs to be reiterated sufficiently often, please do no forget to `make clean` after (re-)configuration and before building (again) using `make`. ### `--with-openssl` Use openssl instead of the built-in AES code The speed of some ciphers' can take advantage of OpenSSL support This is disabled by default as the built-in ciphers already prove reasonably fast in most cases. When enabled, this will include OpenSSL 1.1. This can also be combined with the hardware support and compiler optimizations such as. `./configure --with-openssl CFLAGS="-O3 -march=native"` #### Makefile Add `--with-openssl` to the `configure` command #### Cmake Add `-DN2N_OPTION_USE_OPENSSL=ON` to the cmake configure step. Additionally, it is possible to statically link the OpenSSL library. Add `-DOPENSSL_USE_STATIC_LIBS=true` to the cmake configure step. Building statically with openssl in this way has been known to have issues recently on Windows (See #944) ### `--with-edgex` A legacy option intended to help cross compilation - if you use this option please let us know as there are probably more modern options for cross-compiling ### `--enable-pthread` Enable threading using the pthread library ### `--enable-cap` Use the libcap to provide reduction of the security privileges needed in the running daemon ### `--enable-pcap` If the pcap library is available then the `n2n-decode` tool can be compiled. ### `--enable-natpmp` One of the two UPnP libraries, this one supports the NATPMP protocol. See also the next option. This option depends on the library being installed - on Debian and Ubuntu, this is `apt-get install libnatpmp-dev` ### `--enable-miniupnp` Enables the other kind of UPnP port mapping protocol. Turning on either of these two UPnP libraries will enable UPnP support within the edge. Both the natpmp and miniupnp depend on the pthread library being enabled. This option depends on the library being installed - on Debian and Ubuntu, this is `apt-get install libminiupnpc-dev` ### Disable Multicast Local Peer Detection For better local peer detection, the edges try to detect local peers by sending REGISTER packets to a certain multicast address. Also, edges listen to this address to eventually fetch such packets. If these packets disturb network's peace or even get forwarded by (other) edges through the n2n network, this behavior can be disabled #### Makefile Add `-DSKIP_MULTICAST_PEERS_DISCOVERY` to your `CFLAGS` when configuring, e.g. `./configure --with-zstd CFLAGS="-O3 -march=native -DSKIP_MULTICAST_PEERS_DISCOVERY"` ### Deprecation of --with options Due to historical reasons, the autoconf system does not validate the syntax of any `--with-X` style options, thus to provide the highest confidence in the correctness of configuration and compilation, `--enable-X` style options are preferred. As part of this, the older `--with-X` options will eventually be migrated to use `--enable-X` ## CMake configuration There are a number of OPTION statements in the CMakeLists.txt file that can have their settings changed. This is done by adding a commandline option to the cmake configure stage. e.g: `cmake -DN2N_OPTION_USE_ZSTD=ON ..` Note that the names of the configure option variables used in the cmake process will probably change to make the source code consistent. # Optimisation options ## Compiler Optimizations The easiest way to boosting speed is by allowing the compiler to apply optimization to the code. To let the compiler know, the configuration process can take in the optionally specified compiler flag `-O3`: `./configure CFLAGS="-O3"` The `tools/n2n-benchmark` tool reports speed-ups of 200% or more! There is no known risk in terms of instable code or so. ## Hardware Features Some parts of the code significantly benefit from compiler optimizations (`-O3`) and platform features such as NEON, SSE and AVX. It needs to be decided at compile-time. Hence if compiling for a specific platform with known features (maybe the local one), it should be specified to the compiler – for example through the `-march=sandybridge` (you name it) or just `-march=native` for local use. So far, the following portions of n2n's code benefit from hardware features: ``` AES: AES-NI ChaCha20: SSE2, SSSE3 SPECK: SSE2, SSSE3, AVX2, AVX512, (NEON) Random Numbers: RDSEED, RDRND (not faster but more random seed) ``` The compilations flags could easily be combined: `./configure CFLAGS="-O3 -march=native"`. There are reports of compile errors showing `n2n_seed': random_numbers.c:(.text+0x214): undefined reference to _rdseed64_step'` even though the CPU should support it, see #696. In this case, best solution found so far is to disable `RDSEED` support by adding `-U__RDSEED__` to the `CFLAGS`. ## SPECK – ARM NEON Hardware Acceleration By default, SPECK does not take advantage of ARM NEON hardware acceleration even if compiled with `-march=native`. The reason is that the NEON implementation proved to be slower than the 64-bit scalar code on Raspberry Pi 3B+, see [here](https://github.com/ntop/n2n/issues/563). Your specific ARM mileage may vary, so it can be enabled by configuring the definition of the `SPECK_ARM_NEON` macro: `./configure CFLAGS="-DSPECK_ARM_NEON"` Just make sure that the correct architecture is set, too. `-march=native` usually works quite well. ntop-n2n-90215bd/doc/Building.md000066400000000000000000000145101422132035700163410ustar00rootroot00000000000000This document describes the process for compiling n2n in several different scenarios. There are some configuration options available during the build process, which are documented in the [Build time Configuration](BuildConfig.md) page. Also of use are the steps used for the automated Continuous Integration process, which can be found in the [Github actions config file](../.github/workflows/tests.yml) # Git submodules If you are compiling with the UPnP libraries, it is possible that your operating system or your build system do not include binaries for the required libraries. Using these libraries can cause issues with some build systems, so be aware that not all combinations are supportable. To make this scenario simpler, the required source code has been added to this repository as git `submodules` which require one extra step to complete their checkout. So the very first time after cloning the n2n git repo, you should run this command in the n2n directory to fetch the submodules: ```bash git submodule update --init --recursive ``` # Build on macOS In order to use n2n on macOS, you first need to install support for TUN/TAP interfaces: ```bash brew tap homebrew/cask brew cask install tuntap ``` If you are on a modern version of macOS (i.e. Catalina), the commands above will ask you to enable the TUN/TAP kernel extension in System Preferences → Security & Privacy → General. For more information refer to vendor documentation or the [Apple Technical Note](https://developer.apple.com/library/content/technotes/tn2459/_index.html). Note that on the newest MacOS versions and on Apple Silicon, there may be increasing security restrictions in the OS that make installing the TUN/TAP kernel extension difficult. Alternative software implementations to avoid these difficulties are being discussed for future n2n versions. # Build on Windows The following document some possible windows compile recipes. Of them, the MinGW build process is more tested as it is more friendly to open source development. ## Visual Studio ### Requirements In order to build with Vidual Studio on Windows the following tools should be installed: - Visual Studio. For a minimal install, the command line only build tools can be downloaded and installed from https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2017. - CMake (From https://cmake.org/download/) NOTE: You should always use the official cmake stable release as otherwise you may have issues finding libraries (e.g: the installed OpenSSL library). If you still have problems, you can try invoking it with `C:\Program Files\CMake\bin\cmake`. - (optional) The OpenSSL library. This optional library can be enabled as per the steps in the [Build time Configuration](BuildConfig.md) Pre-built OpenSSL binaries can be downloaded from https://slproweb.com/products/Win32OpenSSL.html. The full version is required, i.e. not the "Light" version. The Win32 version of it is usually required for a standard build. ### CLI steps In order to build from the command line, open a terminal window change to the directory where the git checkout of this repository is and run the following commands: Building using `cmake` works as follows: ```batch cmake -E make_directory build cd build rem Append any options to the next line cmake .. cmake --build . --config Release ``` The compiled `.exe` files should now be available in the `build\Release` directory. ## MinGW These steps were tested on a fresh install of Windows 10 Pro with all patches applied as of 2021-09-29. - Install Chocolatey (Following instructions on https://chocolatey.org/install) - from an admin cmd prompt - `choco install git mingw make` - All the remaining commands must be run from inside a bash shell ("C:\Program Files\Git\usr\bin\bash.exe") - `git clone $THIS_REPO` - `cd n2n` - `./scripts/hack_fakeautoconf.sh` - `make` - `make test` Due to limitations in the Windows environment, the normal autotools steps have been emulated by the `hack_fakeautoconf` - This currently results in the version number reported by the compiled software being inaccurate. Note: MinGW builds have had a history of incompatibility reports with other OS builds (for example [#617](https://github.com/ntop/n2n/issues/617) and [#642](https://github.com/ntop/n2n/issues/642)) However, if the tests pass, you should have a high confidence that your build will be compatible. ## Run on Windows In order to run n2n on Windows, you will need the following: - The TAP drivers should be installed into the system. They can be installed from http://build.openvpn.net/downloads/releases, search for "tap-windows". - If OpenSSL has been linked dynamically, the corresponding `.dll` file should be available onto the target computer. The `edge.exe` program reads the `edge.conf` file located into the current directory if no option is provided. The `supernode.exe` program reads the `supernode.conf` file located into the current directory if no option is provided. Example [edge.conf](../packages/etc/n2n/edge.conf.sample) and [supernode.conf](../packages/etc/n2n/supernode.conf.sample) are available. See `edge.exe --help` and `supernode.exe --help` for a full list of supported options. # Cross compiling on Linux ## Using the Makefiles and Autoconf The Makefiles are all setup to allow cross compiling of this code. You will need to have the cross compiler, binutils and any additional libraries desired installed for the target architecture. Then you can run the `./configure` with the appropriate CC and AR environment and the right `--host` option. If compiling on Debian or Ubuntu, this can be as simple as the following example: ``` HOST_TRIPLET=arm-linux-gnueabi sudo apt-get install binutils-$HOST_TRIPLET gcc-$HOST_TRIPLET ./autogen.sh export CC=$HOST_TRIPLET-gcc export AR=$HOST_TRIPLET-ar ./configure --host $HOST_TRIPLET make ``` A good starting point to determine the host triplet for your destination platform can be found by copying the `./config.guess` script to it and running it on the destination. This is not a good way to produce binaries for embedded environments (like OpenWRT) as they will often use a different libc environment. # N2N Packages There are also some example package build recipes included with the source. - [Debian](../packages/debian/README) - [RPM](../packages/rpm) - [OpenWRT](../packages/openwrt/README.md) ntop-n2n-90215bd/doc/Communities.md000066400000000000000000000106641422132035700171060ustar00rootroot00000000000000# Communities ## Names As communities designate virtual networks, they must be distinguishable from each other. Its their name that makes them distinguishable and which therefore should be unique per network. The community name is composed of 19 byte-sized characters and it internally always is terminated by an additional zero character totalling up to 20 characters. Hence, the zero character cannot be part of the regular community name. There are some other characters that cannot be used, namely `. * + ? [ ] \`. To make full use of character space, hex values could be used, e.g. from Linux bash applying the `edge … -c $(echo -en '\x3a\x3b\x4a\x6a\xfa') …` command line syntax. If used with a configuration file, the bytes must be directly filled as characters into a corresponding `-c :;JjĂ¾` line. Apart from command line `-c` and configuration file, the community name can be supplied through the `N2N_COMMUNITY` environment variable. This might prove useful to hide the community name from command line if used with header encryption enabled, see below. ## Restrict Supernode Access By default, a supernode offers its service to all communities and allows them to connect. If a self-setup supernode shall handle certain communities only, the supernode can be given a list of allowed communities. This list is a simple text file containg the allowed community names, one per line: ``` # community.list (a text file) ----------------------------------------------------- myCommunity yourCommunity ``` This file is provided to the supernode through the `-c community.list` command line parameter. This example would allow the supernode to only accept connections from communities called "myCommunity" and "yourCommunity", these are fixed-name communities. ## Somewhat Flexible Community Names If you want to allow all community names from a certain name range, e.g. from "myCommunity00" to "myCommunity99", the `community.list` file (or whatever you name it) could look as follows: ``` # community.list (a text file) ----------------------------------------------------- myCommunity[0-9][0-9] ``` Advanced users recognize the so called regular expression. To prevent users from stop reading, the author did not dare to name this section "Regular Expressions". Anyway, community names can be provided as regular expressions using the following placeholders: ``` '.' Dot, matches any character '*' Asterisk, match zero or more of previous element (greedy) '+' Plus, match one or more of previous element (greedy) '?' Question, match zero or one (non-greedy) '[abc]' Character class, match if one of {'a', 'b', 'c'} '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} (feature is currently broken) '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z } '\s' Whitespace, \t \f \r \n \v and spaces '\S' Non-whitespace '\w' Alphanumeric, [a-zA-Z0-9_] '\W' Non-alphanumeric '\d' Digits, [0-9] '\D' Non-digits ``` Knowing this, we can as well express the exemplary `community.list` above the following way: ``` # community.list (a text file) ----------------------------------------------------- myCommunity\d\d ``` Also, as the `. * + ? [ ] \` characters indicate parts of regular expressions, we now understand why those are not allowed in fixed-name community names. ## Header Encryption By default, the community name is transmitted in plain witch each packet. So, a fixed-name community might keep your younger siblings out of your community (as long as they do not know the community name) but sniffing attackers will find out the community name. Using this name, they will be able to access it by just connecting to the supernode then. [Header encryption](Crypto.md#header) can be enabled to prevent plain transmission. It is important to understand that header encryption, if enabled, only works on fixed-name communities. It will not work on community names described by regular expressions. On the other hand, the provision of fixed-name communities blocks all other, non-listed communities. To allow a mixed operation of certain encrypted and hence fixed-name communities along with all other open communities, the following "trick" can be applied: ``` # community.list (a text file) ----------------------------------------------------- mySecretCom .* ``` This is not really a trick but just making use of a very permissive regular expression at the second line. ntop-n2n-90215bd/doc/ConfigurationFiles.md000066400000000000000000000032711422132035700204000ustar00rootroot00000000000000# Configuration Files To help deployment and better handle locally different configurations, n2n supports the optional use of configuration files for `edge` and `supernode`. They are plain text files and contain the desired command line options, **one per line**. The exemplary command line ```bash sudo edge -c mynetwork -k mysecretpass -a 192.168.100.1 -f -l supernode.ntop.org:7777 ``` translates into the following `edge.conf` file: ``` -c mynetwork -k mysecretpass -a 192.168.100.1 -f -l supernode.ntop.org:7777 -A5 ``` which can be loaded by ``` sudo ./edge edge.conf ``` Comment lines starting with a hash '#' are ignored. ``` # automated edge configuration # created by bot7 # on April 31, 2038 – 1800Z -c mynetwork -k mysecretpass -a 192.168.100.1 -f -A5 # --- supernode section --- -l supernode.ntop.org:7777 ``` Long options can be used as well. Please note the double minus/dash-character `--`, just like you would use them on the command line with long options: ``` --community mynetwork -k mysecretpass -a 192.168.100.1 -f -A5 -l supernode.ntop.org:7777 ``` If using a configuration file, its filename needs to be supplied as first parameter to `edge` or `supernode`. If required, additional command line parameters can be supplied afterwards: ``` sudo edge edge.conf -z1 -I myComputer ``` Finally, the `.conf` file syntax also allows `=` between parameter and its option: ``` -c=mynetwork -k=mysecretpass -a=192.168.100.1 -f -A5 -l=supernode.ntop.org:7777 ``` When used with `=`, there is no whitespace allowed between parameter, delimiter (`=`), and option. So, do **not** put `-c = mynetwork` – it is required to be `-c=mynetwork`. ntop-n2n-90215bd/doc/Crypto.md000066400000000000000000000441621422132035700160720ustar00rootroot00000000000000# Cryptography in n2n ## Payload ### Overview Payload encryption currently comes in four different flavors using ciphers of different origins. Supported ciphers are enabled using the indicated command line option: - Twofish in CTS mode (`-A2`) - AES in CBC mode (`-A3`) - ChaCha20 (CTR) (`-A4`) - SPECK in CTR mode (`-A5`) The following chart might help to make a quick comparison and decide what cipher to use: | Cipher | Mode | Block Size | Key Size | IV length |Speed | Built-In | Origin | | :---: | :---:| :---: | :---: | :---: |:---: | :---: | --- | |Twofish | CTS | 128 bits | 256 bit | 128 bit | -..O | Y | Bruce Schneier | |AES | CTS | 128 bits | 128, 192, 256 bit| 128 bit | O..+ | Y | Joan Daemen, Vincent Rijmen, NSA-approved | |ChaCha20| CTR | Stream | 256 bit | 128 bit | +..++| Y | Daniel J. Bernstein | |SPECK | CTR | Stream | 256 bit | 128 bit | ++ | Y | NSA | The two block ciphers Twofish and AES are used in CTS mode. n2n has all four ciphers built-in as basic versions. Some of them optionally compile to faster versions by the means of available hardware support (AES-NI, SSE, AVX – please see the [Building document](./Building.md) for details. Depending on your platform, AES and ChaCha20 might also draw notable acceleration from optionally compiling with openSSL 1.1 support. The`-k ` command line parameter supplies the key. As even non-privileged users might get to see the command line parameters (try `ps -Af | grep edge`), the key can also be supplied through the `N2N_KEY` environment variable: `sudo N2N_KEY=mysecretpass edge -c mynetwork -a 192.168.100.1 -f -l supernode.ntop.org:7777`. Providing `-k ` without specifying any cipher by `-A_` will default to AES encryption. To renounce encryption, `-A1` enables the so called `null_transform` transmitting all payload data unencryptedly. Omitting `-A_` and not providing a key through `-k ` shows the same effect. ### Twofish This implementation prepends a 128 bit random value to the plain text. Its size is adjustable by changing the `TF_PREAMBLE_SIZE` definition found in `src/transform_tf.c`. It defaults to TF_BLOCK_SIZE (== 16). As CTS uses underlying CBC mode, this basically has the same effect as a respectively shorter IV. However, this flexibility does not come for free as an additional block needs to be encrypted. Twofish requires no padding as it employs a CBC/CTS scheme which can send out plaintext-length ciphertexts. The scheme however has a small flaw in handling messages shorter than one block, only low-level programmer might encounter this. On Intel CPUs, Twofish usually is the slowest of the ciphers present. However, on Raspberry Pi 3B+, Twofish was observed to be faster than AES-CTS. Your mileage may vary. Cipher speed's can be compared running the `tools/n2n-benchmark` tool. ### AES AES also prepends a random value to the plaintext. Its size is adjustable by changing the `AES_PREAMBLE_SIZE` definition found in `src/transform_aes.c`. It defaults to AES_BLOCK_SIZE (== 16). The AES scheme uses a CBC/CTS scheme which can send out plaintext-length ciphertexts as long as they are one block or more in length. Apart from n2n's plain C implementation, Intel's AES-NI is supported – again, please have a look at the [Building document](./Building.md). In case of openSSL support its `evp_*` interface gets used which also offers hardware acceleration where available (SSE, AES-NI, …). It however is slower than the following stream ciphers because the CBC mode cannot compete with the optimized stream ciphers. This cipher's different key-sizes are triggered by the length of the user-provided key: 22 characters or less make n2n use AES-128, between 23 and 32 characters lead to AES-192, and 33 or more characters trigger AES-256. ### ChaCha20 ChaCha20 was the first stream cipher supported by n2n. In addition to the basic C implementation, an SSE version is offered. If compiled with openSSL support, ChaCha20 is provided via the `evp_*` interface. It is not used together with the Poly1305 message tag from the same author though. Whole packet's checksum will be handled in the header (see below). The random full 128-bit IV is transmitted in plain. ChaCha20 usually performs faster than AES-CTS. ### SPECK SPECK is recommended by the NSA for offical use in case AES implementation is not feasible due to system constraints (performance, size, …). The block cipher is used in CTR mode making it a stream cipher. The random full 128-bit IV is transmitted in plain. On modern Intel CPUs, SPECK performs even faster than openSSL's ChaCha20 as it takes advantage of SSE4, AVX2, or AVX512 if available. On Raspberry's ARM CPU, it is second place behind ChaCha20 and before Twofish. ### Random Numbers Throughout n2n, pseudo-random numbers are generated for several purposes, e.g. random MAC assignment and the IVs for use with the various ciphers. Regarding IVs, especially for using in the stream ciphers, the pseudo-random numbers shall be as collision-free as possible. n2n uses an implementation of XORSHIFT128+ which shows a periodicity of 2¹²â¸. Its initialization relies on seeding with a value as random as possible. Various sources are tapped including a syscall to Linux' `SYS_getrandom` as well as Intels hardware random number generators `RDRND` and `RDSEED`, if available (compile using `-march=native`). ### Pearson Block Hashing For general purpose hashing, n2n employs [Pearson Block Hashing](https://github.com/Logan007/pearsonB) as it offers variable hash sizes and is said not to be too "collidy". However, this is not a cryptographically secure hashing function which by the way is not required here: The hashing is never applied in a way that the hash value shall publicly prove the knowledge of a secret without showing the secret itself. _Pearson hashing is tweakable by using your own block-sized permutation._ Here, we use a three-round xor-rotate-multiply permutation scheme on 64-bit wide integer numbers with constants discovered by [David Stafford](http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html) (`mix13`, permission obtained via eMail) which, meanwhile, is better known as part of `splitmix64()`. _Pearson hashing allows verification of block-sized parts of the hash only – just in case performance requirements would urge to do so._ ## Header ### Overview Packet's header consist of a COMMON section followed by a packet-type specific section, e.g. REGISTER, REGISTER_ACK, PACKET including the payload, REGISTER_SUPER, … The COMMON section is built as follows: ``` 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ! Version = 3 ! TTL ! Flags ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4 ! Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8 ! ... Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12 ! ... Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16 ! ... Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 20 ! ... Community ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` In case of a PACKET-type, it is succeeded by the fields depicted below: ``` 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24 ! Source MAC Address : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 28 : ! Destination MAC Address : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 32 : ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 36 ! Socket Flags (v=IPv4) ! Destination UDP Port ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 40 ! Destination IPv4 Address ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44 ! Compress'n ID ! Transform ID ! Payload ... ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 48 ! ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+... ``` ### Encryption If enabled (`-H`), all fields but the payload (which is handled separately as outlined above) get encrypted using SPECK in CTR mode. As packet headers need to be decryptable by the supernode and we do not want to add another key (to keep it a simple interface), the community name serves as key (keep it secret!) because it is already known to the supernode. The community name consists of up to 20 characters (well, 19 + `0x00`), so key size of 128 bit is a reasonable choice here. The scheme applied tries to maintain compatibility with current packet format and works as follows: - First line of 4 bytes (Version, TTL, Flags) goes to sixth line: ``` 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ! Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4 ! ... Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8 ! ... Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12 ! ... Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16 ! ... Community ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 20 ! Version = 3 ! TTL ! Flags ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` - To be able to identify a correctly decrpyted header later on, a magic number is stamped in fourth line starting at byte number 16. We use "n2" string and add the 16-bit header length to be able to stop header decryption right before an eventually following ethernet data payload begins – in case of PACKET-type, header-length does not equal packet-length. 16-bit length is required because REGISTER_SUPER_ACK packets consist of header only and could grow quite large due to their payload (other supernodes of federation) – don't mix up this kind of payload (part of the header) with the ethernet data payload of PACKET messages. - The rest of the community field, namely the first 16 bytes, is reframed towards a 128-bit IV for the header encryption. ``` 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ! IV ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4 ! ... IV ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8 ! ... IV ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12 ! ... IV ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16 ! Magic Number "n2" = 0x6E32 ! Header Length ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 20 ! Version = 3 ! TTL ! Flags ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` - As we use a stream cipher, the IV should be a nonce. The IV plays an additional role sketched later, see the following sections on checksum and replay protection. - To make a less predictable use of the key space – just think of the typically reset MSB of ASCII characters of community names – we actually use a hash of the community name as key. - Encryption starts at byte number 16 and ends at header's end. It does not comprise PACKET's ethernet data payload which eventually has its own encryption scheme as chosen with the `-A_` options. Decryption checks all known communities (several in case of supernode, only one at edge) as keys. On success, the emerging magic number along with a reasonable header's length value will reveal the correct community whose name will be copied back to the original fields allowing for regular packet handling. Thus, header encryption will only work with previously determined community names introduced to the supernode by `-c ` parameter. Also, it should be clear that header encryption is a per-community decision, i.e. all nodes and the supernode need to have it enabled. However, the supernode supports encrypted and unencrypted communities in parallel, it determines their status online at arrival of the first packet. Use a fresh community name for encrypted communities; do not use a previously used one of former unecrypted communities: their names were transmitted openly. ### Checksum The whole packet including the eventually present payload is checksummed using a Person block hashing scheme. The 64-bit checksum is exclusive-ored with a (shifted by 32 bit) 64-bit time stamp and filled up with 32 more random bits to obtain a 128-bit pre-IV. This pre-IV gets encrypted using a single block-cipher step to get the pseudo-random looking IV. This way, the checksum resists targeted bit-flips (to header, payload, and IV) as any change to the whole 128-bit IV would render the header un-decryptable. Also, as explained below, the checksum comes along with a time stamp minimizing opportunities for random attacks. The single block-cipher step employs SPECK because it is quite fast and it offers a 128-bit block cipher version. The key is derived from the header key – a hash of the hash. The checksum is calculated by the edges and the supernode. Changes to the payload will cause a different locally calculated checksum. Extracting the time stamp by exclusive-oring an erroneous checksum will lead to an invalid timestamp. So, checksum errors are indirectly detected when checking for a valid time stamp. ### Replay Protection The aforementioned 128-bit pre-IV can be depicted as follows: ``` 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 +----------------------------------------------------------------+-------------------------------+-------------------------------+ ! 64-bit checksum of the whole packet ! 0x00 ! ! + - - - - - - - - - - - - - - - - - - - - - - - XOR - - - - - - - - - - - - - - - - - - - - - - -! 32 pseudo-random bits ! ! 0x00 ! 52-bit time stamp with microsecond-accuracy ! countr ! F ! ! +------------------------------------------------------------------------------------------------+-------------------------------+ ``` The time stamp consists of the 52-bit microsecond value, a 8-bit counter in case of equal following time stamps and, a 4-bit flag field F (accuracy indicator in last bit). edge and supernode monitor their own time stamps for doublets which would indicate an accuracy issue. If the counter overflows on the same time stamp, the sub-second part of the time stamp will also become counter. In this case, the whole stamp carries the accuracy bit flag (lowest bit) set so other edges and supernodes can handle this stamp appropriately. Encrypting this pre-IV using a block cipher step will generate a pseudo-random looking IV which gets written to the packet and used for the header encryption. Due to the time-stamp encoded, the IV will more likely be unique, close to a real nonce. Upon receival, the time stamp as well as the checksum can be extracted from the IV by performing a 128-bit block-cipher decryption step. Verification of the time stamp happens in two steps: - The (remote) time stamp is checked against the local clock. It may not deviate more than plus/minus 16 seconds. So, edges and supernode need to keep a somewhat current time. This limit can be adjusted by changing the `TIME_STAMP_FRAME` definition. It is time-zone indifferent as UTC is used. - Valid (remote) time stamps get stored as "last valid time stamp" seen from each node (supernode and edges). So, a newly arriving packet's time stamp can be compared to the last valid one. It should be equal or higher. However, as UDP packets may overtake each other just by taking another path through the internet, they are allowed to be 160 millisecond earlier than the last valid one. This limit is set with the `TIME_STAMP_JITTER` definition. If the accuracy flag is set, the time stamp will be allowed a jitter eight times as high, corresponding to 1.25 seconds by default. - However, the systemic packets such as REGISTER_SUPER are not allowed any time stamp jitter because n2n relies on the actual sender's socket. A replay from another IP within any allowed jitter time frame would deviate the traffic which shall be prevented (even if it remains undecryptable). Under absolutely rare (!) circumstances, this might cause a re-registration requirement which happens automatically but might cause a small delay – security (including network availability) first! REGISTER packets from the local multicast environment are exempt from the very strict no-jitter requirement because they indeed regularly can show some deviation if compared to time stamps in packets received on the regular socket. As these packets are incoming on different sockets, their processing is more likely to no take place in the order these packets were sent. The way the IV is used for replay protection and for checksumming makes enabled header encryption a prerequisite for these features. ntop-n2n-90215bd/doc/Faq.md000066400000000000000000000124151422132035700153150ustar00rootroot00000000000000# n2n Frequently Asked Questions ## Supernode ### I want to setup a supernode that only I can use. Perhaps even password protected? Please think of the community-name as password and start the supernode with the `-c ` parameter where the `` is the path to a simple text file containing a single line with the name of your secret community. It will be the only community allowed. Only edge nodes from that community can join (`-c ` at the edge). If you additionally want to prevent open transmission of your secret community name via the network, **all** edge nodes should use `-H` command line option for header encryption. Also, please see the `community.list` file coming with n2n for advanced use of that file. Beyond this access barrier you may want to use payload encryption `-A_` at the edges. Only the edges – not the supernode – are able to decipher the payload data. So, even if anyone would be able to break the access barrier to the supernode, the payload remains protected by the payload crypto, see [this document](https://github.com/ntop/n2n/blob/dev/doc/Crypto.md) for details. ### Can I get a list of connected edge nodes and their community and source IP address from the supernode? The supernode provides basic information via its localhost udp management port. It defaults to 5645 and can be changed using supernode's `-t` command line option. You can request the current status by just sending a new line, i.e. pressing [ENTER] key, running the following command (localhost only) `netcat -u localhost 5645` ### Is there support for multiple supernodes? Yes, there is. Please [read](https://github.com/ntop/n2n/blob/dev/doc/Federation.md) about how several supernodes can form a Federation to increase network resilience. ### Can a supernode listen on multiple ports? The supernode itself can only listen on one port. However, your firewall might be able to map additional UDP ports to the supernode's regular port: `sudo iptables -t nat -A PREROUTING -i -d -p udp --dport -j REDIRECT --to-ports ` This command line can be put down as additional `ExecStartPost=` line (without `sudo`) in the supernode's `.service` file which can hold several such lines if required. ### How to handle the error message "process_udp dropped a packet with seemingly encrypted header for which no matching community which uses encrypted headers was found"? This error message means that the supernode is not able to identify a packet as unencrypted. It does check for a sane packet format. If it fails the header is assumed encrypted (thus, "_seemingly_ encrypted header") and the supernode tries all communities that would make a key (some have already been ruled out as they definitely are unenecrypted). If no matching community is found, the error occurs. If all edges use the same `-H` setting (all edges either with it or without it) and restarting the supernode does not help, most probably one of the components (an edge or the supernode) is outdated, i.e. uses a different packet format – from time to time, a lot of changes happen to the packet format in a very short period of time, especially in _dev_ branch. So, please make sure that all edges **and** the supernode have the exact same built version, e.g. all from current _dev_. ## Edge ### How can I know if peer-to-peer connection has successfully been established? The edge also offers a local udp management port at which it provides some information about connected _peers_ allowing a peer-to-peer connection, and _pending peers_ whose connections are forwarded through the supernode. The edge's management port defaults to 5644 and can be changed using edge's `-t` command line option. Connecting using the following command (localhost only) `netcat -u localhost 5644` answers every new line, i.e. pressing [ENTER] key, with current information. The edge even understands some simple commands, try `help`. ### The edge repeatedly throws an "Authentication error. MAC or IP address already in use or not released yet by supernode" message. What is wrong? The edge encountered n2n's protection against spoofing. It prevents that one edge's identity, MAC and IP address, can be impersonated by some other while the original one is still online, see some [details](Authentication.md). Mostly, there are two situations which can trigger this: If you use a MAC or IP address that already is in use, just change those parameters. If the edge prematurely has ended in a non-regular way, i.e. by killing it using `kill -9 ...` or `kill -SIGKILL ...`, it did not have a chance to un-register with the supernode which still counts the edge for online. A re-registration with the same MAC or IP address will be unsuccessful then. After two minutes or so the supernode will have forgotten. A new registration with the same parameters will be possible then. So, either wait two minutes or chose different parameters to restart with. And, as a matter of principal, always end an edge by either pressing `CTRL` + `C` or by sending SIGTERM or SIGINT by using `kill -SIGTERM ...` or `kill -SIGINT ...`! A plain `kill ...` without `-9` will do, too. And finally, a `stop` command to the management port peacefully ends the edge as well. ntop-n2n-90215bd/doc/Federation.md000066400000000000000000000066461422132035700166770ustar00rootroot00000000000000# Supernode Federation ## Idea 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**. ## Using Multiple Supernodes ### Form a Federation To form a federation, multiple supernodes need to be aware of each other. To get them connected, an additional `-l` option from command line is required at the supernode. This option takes the IP address (or name) and the UDP port of another known supernode, e.g. `-l 192.168.1.1:1234`. ### Use a Federation Federated supernodes take care of propagating their knowledge about other supernodes to all other supernodes and the edges. So, in the first place, edges only need to connect to one supernode (called anchor supernode) using `-l` option. This supernode needs to be present at start-up. Optionally, more anchor supernodes of the same federation can be provided to an edge using several `-l` options. This will counter scenarios with reduced assured initial supernode availability. ## How It Works 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. The default name for the federation is `*Federation`. Internally, a mandatory special character is prepended to the name: that way, an edge won't be able to provide a regular community with the same name of the federation. Optionally, a user can choose a federation name (same on all supernodes) and provide it via `-F mySecretFed` option to the supernode. Alternatively, the federation name can be passed through the environment variable `N2N_FEDERATION`. 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. 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. 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. 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. Thanks to this feature, n2n 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. To serve scenarios in which an edge is supposed to select the supernode by round trip time, i.e. choosing the "closest" one, the `--select-rtt` command line option is available at the edge. Note, that workload distribution among supernodes might not be so fair then. Furthermore, `--select-mac` would switch to a MAC address based selection strategy choosing the supernode active with the lowest MAC address. ntop-n2n-90215bd/doc/Hacking.md000066400000000000000000000256071422132035700161610ustar00rootroot00000000000000# Hacking -------- This program and document is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not see see [](http://www.gnu.org/licenses/) -------- This file describes the internals of n2n. Read this before starting to modify the code. Because coding examples may be present in this document it is licensed under the GPL rather than FDL. ## Symmetric NAT Symmetric NAT is a form of firewall NAT in which an UDP packets are only passed back to an inside host socket when the return packets originate from the outside socket to which the initiating UDP packets were sent. This means that when an inside host sends UDP to some outside socket; other hosts cannot piggyback on this opening in the firewall to send data to the inside host. For example, an asymmetric NAT would keep the mapping: ` -> ` and would redirect all the packets on external port ExtPort to the internal host regardless of the remote IP. Whereas a symmetric NAT would keep the mapping: ` -> ` so only RemoteIP can send packets to the internal host. RemoteIP is the supernode IP in case of n2n, to which the internal host has registered. In n2n, P2P can work monodirectionally if only one of the two peers is behind a symmetric NAT. For example, if A is behind symmetric NAT and B is behind asymmetric NAT - A->B packets are P2P (will have the B public IP as destination) - B->A packets must go through the supernode If both the peers are behind symmetric NAT, then no P2P communication is possible. ## ARP Cache n2n makes use of the host operating system's own ARP cache. Each edge node allocates a random MAC address to itself. This MAC is constant for the life of the edge process. ARP packets are passed around as broadcast ethernet packets over n2n and these packets cause the native ARP cache to be updated. Edge nodes send gratuitous ARP packets on startup. See section on gratuitous ARP below. ## Registration and Peer-to-Peer Communication Setup A and B are edge nodes with public sockets Apub and Bpub; and private network addresses A and B respectively. S is the supernode. A sends {REGISTER,Amac} to S. S registers {Amac->Apub}. B sends {REGISTER,Bmac} to S. S registers {Bmac->Bpub}. Now ping from A to B. A sends broadcast "arp who-has B" to S. S relays the packet to all known edge nodes. B replies "B at Bmac" to supernode which forwards this to A. So now ping A->B is known to be ping Amac(A)->Bmac(B). Note: gratuitous arp also requires discussion. In response to receiving the arp reply, Apub sends {REGISTER,Amac} to Bpub. If Bpub receives the request it sends back {REGISTER_ACK,Amac} and also sends its own {REGISTER,Bmac} request. In response to receiving the "arp who-has", Bpub sends {REGISTER,Bmac} to Apub. Now the OS has received the arp reply and sends ICMP to Bmac(B) via the tunnel on A. A looks up Bmac in the peers list and encapsulates the packet to Bpub or the supernode if the MAC is not found. We assume that between two edge nodes, if Bpub receives a packet from Apub then Apub can receive a packet from Bpub. This is the symmetric NAT case. Note: In the symmetric NAT case, the public socket for a MAC address will be different for direct contact when compared to information from the supernode. When two edge nodes are both behind symmetric NAT they cannot establish direct communication. If A receives {REGISTER,Bmac} from B, A adds {Bmac->Bpub} to its peers list knowing that Bmac is now reachable via that public socket. Similarly if B receives {REGISTER,Amac} from A. The supernode never forwards REGISTER messages because the public socket seen by the supervisor for some edge (eg. A) may be different to the socket seen by another edge due to the actions of symmetric NAT (allocating a new public socket for the new outbound UDP "connection"). ## Edge Resgitration Design Ammendments (starting from 2008-04-10) * Send REGISTER on rx of PACKET or REGISTER only when dest_mac == device MAC (do not send REGISTER on Rx of broadcast packets). * After sending REGISTER add the new peer to pending_peers list; but * Don't send REGISTER to a peer in pending_peers list * Remove old entries from pending_peers at regular intervals * On rx of REGISTER_ACK, move peer from pending_peers to known_peers for direct comms and set last_seen=now * On rx of any packet set last_seen=now in the known_peers entry (if it exists); but do not add a new entry. * If the public socket address for a known_peers entry changes, deleted it and restart registration to the new peer. * Peer sockets provided by the supernode are ignored unless no other entry exists. Direct peer-to-peer sockets are always given more priority as the supernode socket will not be usable for direct contact if the peer is behind symmetric NAT. The pending_peers list concept is to prevent massive registration traffic when supernode relay is in force - this would occur if REGISTER was sent for every incident packet sent via supernode. Periodic REGISTER attempts will still occur; not for every received packet. In the case where the peer cannot be contacted (eg. both peers behind symmetric NAT), then there will still be periodic attempts. Suggest a pending timeout of about 60 sec. A peer is only considered operational for peer-to-peer sending when a REGISTER_ACK is returned. Once operational the peer is kept operational while any direct packet communications are occurring. REGISTER is not required to keep the path open through any firewalls; just some activity in one direction. After an idle period; the peer should be deleted from the known_peers list. We should not try to re-register when this time expires. If there is no data to send then forget the peer. This helps scalability. If a peer wants to be remembered it can send gratuitous ARP traffic which will keep its entry in the known_peers list of any peers which already have the entry. ``` peer = find_by_src_mac( hdr, known_peers ); /* return NULL or entry */ if ( peer ) { peer_last_seen = time(NULL); } else { if ( ! is_broadcast( hdr ) ) /* ignore broadcasts */ { if ( IS_REGISTER_ACK( hdr ) ) { /* move from pending to known_peers */ set_peer_operational( hdr ); } else { /* add to pending and send REGISTER - ignore if in pending. */ try_send_register( hdr ) } } } ``` ### Notes * In testing it was noted that if a symmetric NAT firewall shuts down the UDP association but the known_peers registration is still active, then the peer becomes unreachable until the known_peers registration is deleted. Suggest two ways to mitigate this problem: (a) make the known_peers purge timeout a config parameter; (b) send packets direct and via supernode if the registration is older than eg. 60 sec. ## Gratuitous ARP In addition to the ARP who-has mechanism noted above, two edge nodes can become aware of one another by gratuitous ARP. A gratuitous ARP packet is a broadcast packet sent by a node for no other purpose than to announce its presence and identify its MAC and IP address. Gratuitous ARP packets are to keep ARP caches up to date so contacting the host will be faster after an long idle time. ## man Pages Look at a non-installed man page like this (linux/UNIX): `nroff -man edge.8 | less` ## PACKET message format All message encoding and decoding is contained in wire.c. The PACKET message is of main concern as it is the most frequently transferred as it contains encapsulated ethernet packets. ``` Version 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ! Version=3 ! TTL ! Flags ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4 ! Community : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8 ! ... Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12 ! ... Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16 ! ... Community ... : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 20 ! ... Community ... ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24 ! Source MAC Address : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 28 : ! Destination MAC Address : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 32 : ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 36 ! Socket Flags (v=IPv4) ! Destination UDP Port ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 40 ! Destination IPv4 Address ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44 ! Compress'n ID ! Transform ID ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 48 ! Payload +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` So each n2n PACKET has a 48 byte overhead. For a 1500 byte ethernet packet this is roughly 3%. Socket flags provides support for IPv6. In this case the PACKET message ends as follows: ``` +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 36 ! Socket Flags (v=IPv6) ! Destination UDP Port ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 40 ! Destination IPv6 Address : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44 : : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 48 : : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 52 : ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 56 ! Compress'n ID ! Transform ID ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 60 ! Encapsulated ethernet payload +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` ------- (C) 2008-2010 - Richard Andrews January 2010 - Richard Andrews ntop-n2n-90215bd/doc/ManagementAPI.md000066400000000000000000000206441422132035700172170ustar00rootroot00000000000000# Management API This document is focused on the machine readable API interfaces. Both the edge and the supernode provide a management interface UDP port. These interfaces have some documentation on their non machine readable commands in the respective daemon man pages. Default Ports: - UDP/5644 - edge - UDP/5645 - supernode A Quick start example query: `echo r 1 help | nc -w1 -u 127.0.0.1 5644` ## JSON Query interface A machine readable API is available for both the edge and supernode. It takes a simple text request and replies with JSON formatted data. The request is in simple text so that the daemon does not need to include any complex parser. The replies are all in JSON so that the data is fully machine readable and the schema can be updated as needed - the burden is entirely on the client to handle different replies with different fields. It is expected that any client software will be written in higher level programming languages where this flexibility is easy to provide. Since the API is over UDP, the replies are structured so that each part of the reply is clearly tagged as belonging to one request and there is a clear begin and end marker for the reply. This is expected to support the future possibilities of pipelined and overlapping transactions as well as pub/sub asynchronous event channels. The replies will also handle some small amount of re-ordering of the packets, but that is not an specific goal of the protocol. Note that this API will reply with a relatively large number of UDP packets and that it is not intended for high frequency or high volume data transfer. It was written to use a low amount of memory and to support incremental generation of the reply data. With a small amount of effort, the API is intended to be human readable, but this is intended for debugging. ## Request API The request is a single UDP packet containing one line of text with at least three space separated fields. Any text after the third field is available for the API method to use for additional parameters Fields: - Message Type - Options - Method - Optional Additional Parameters The maximum length of the entire line of text is 80 octets. All request packets should generate a reply. However, this reply may simply be an error. ### Message Type This is a single octet specifying the type: - "r" for a read-only method (or one that does not need change permissions) - "w" for a write method (or one that makes changes) - "s" for a subscribe method to request this socket receive some events To simplify the interface, the reply from both read and write calls to the same method is expected to contain the same data. In the case of a write call, the reply will contain the new state after making the requested change. The subscribe and events message flow works with a different set of messages. ### Options The options field is a colon separated set of options for this request. Only the first subfield (the "tag") is mandatory. The second subfield is a set of flags that describe which optional subfields are present. If there are no additional subfields then the flags can be omitted. SubFields: - Message Tag - Optional Message Flags (defaults to 0) - Optional Authentication Key #### Message Tag Each request provides a tag value. Any non error reply associated with this request will include this tag value, allowing all related messages to be collected within the client. The tag will be truncated if needed by the daemon, but there will be at least 8 octets of space available. Where possible, the error replies will also include this tag, however some errors occur before the tag is parsed. The tag is not interpreted by the daemon, it is simply echoed back in all the replies. It is expected to be a short string that the client knows will be unique amongst all recent, still outstanding or subscription requests on a given socket. One possible client implementation is a number between 0 and 999, incremented for each request and wrapping around to zero when it is greater than 999. #### Message Flags This subfield is a set of bit flags that are hex-encoded and describe any remaining optional subfields. Currently, only one flag is defined. The presence of that flag indicates that an authentication key subfield is also present. Values: - 0 - No additional subfields are present - 1 - One additional field, containing the authentication key #### Authentication Key A simple string password that is provided by the client to authenticate this request. See the Authentication section below for more discussion. #### Example Options value e.g: `102:1:PassWord` ### Example Request string e.g: `r 103:1:PassWord peer` ## Reply API Each UDP packet in the reply is a complete and valid JSON dictionary containing a fragment of information related to the entire reply. Reply packets are generated both in response to requests and whenever an event is published to a subscribed channel. ### Common metadata There are two keys in each dictionary containing metadata. First is the `_tag`, containing the Message Tag from the original request. Second is the `_type` which identifies the expected contents of this packet. ### `_type: error` If an error condition occurs, a packet with a `error` key describing the error will be sent. This usually also indicates that there will be no more substantial data arriving related to this request. e.g: `{"_tag":"107","_type":"error","error":"badauth"}` ### `_type: begin` Before the start of any substantial data packets, a `begin` packet is sent. For consistency checking, the method in the request is echoed back in the `error` key. e.g: `{"_tag":"108","_type":"begin","cmd":"peer"}` For simplicity in decoding, if a `begin` packet is sent, all attempts are made to ensure that a final `end` packet is also sent. ### `_type: end` After the last substantial data packet, a final `end` packet is sent to signal to the client that this reply is finished. e.g: `{"_tag":"108","_type":"end"}` ### `_type: row` The substantial bulk of the data in the reply is contained within one or more `row` packets. The non metadata contents of each `row` packet is defined entirely by the method called and may change from version to version. Each `row` packet contains exactly one complete JSON object. The row replies may be processed incrementally as each row arrives and no batching of multiple packets will be required. e.g: `{"_tag":"108","_type":"row","mode":"p2p","ip4addr":"10.135.98.84","macaddr":"86:56:21:E4:AA:39","sockaddr":"192.168.7.191:41701","desc":"client4","lastseen":1584682200}` ### `_type: subscribed` Signals that the subscription request has been successfully completed. Any future events on the requested channel will be asynchronously sent as `event` packets using the same tag as the subscribe request. ### `_type: unsubscribed` Only one management client can be subscribed to any given event topic, so if another subscribe request arrives, the older client will be sent this message to let them know that they have been replaced. (In the future, this may also be sent as a reply to a explicit unsubscribe request) ### `_type: replacing` If a new subscription request will replace an existing one, this message is sent to the new client to inform them that they have replaced an older connection. ### `_type: event` Asynchronous events will arrive with this message type, using the same tag as the original subscribe request. Just like with the `row` packets, the non metadata contents are entirely defined by the topic and the specific n2n version. ## Subscribe API A client can subscribe to events using a request with the type of "s". Once a subscribe has been successfully completed, any events published on that channel will be forwarded to the client. Only one management client can be subscribed to any given event topic, with newer subscriptions replacing older ones. The special channel "debug" will receive copies of all events published. Note that this is for debugging of events and the packets may not have the same tag as the debug subscription. ## Authentication Some API requests will make global changes to the running daemon and may affect the availability of the n2n networking. Therefore the machine readable API include an authentication component. Currently, the only authentication is a simple password that the client must provide. It defaults to 'n2n' and can manually be set through the command line parameter `--management-password ` – for edge as well as for supernode. ntop-n2n-90215bd/doc/Routing.md000066400000000000000000000234311422132035700162350ustar00rootroot00000000000000# IPv4 Routing (Linux) ## General Remarks Reaching a remote network or tunneling all the internet traffic via n2n are two common tasks which require a proper routing setup. n2n supports routing needs providing options for packet forwarding including broadcasts as well as modifying the routing table. In this context, the `server` is the edge node which provides access to the remote network/internet, whereas the `client` is the connecting edge node. In order to enable routing, the `server` must be configured as follows: 1. Add the `-r` option to the edge options to enable routing 2. Enable packet forwarding with `sudo sysctl -w net.ipv4.ip_forward=1` 3. Enable IP masquerading: `sudo iptables -t nat -A POSTROUTING -j MASQUERADE` On the client side, the easiest way to configure routing is via the `-n` option. For example: - In order to connect to the remote network `192.168.100.0/24`, use `-n 192.168.100.0/24:10.0.0.1` - In order to tunnel all the internet traffic, use `-n 0.0.0.0/0:10.0.0.1` 10.0.0.1 is the IP address of the gateway to use to route the specified network. It should correspond to the IP address of the `server` within n2n. Multiple `-n` options can be specified. As an alternative to the `-n` option, the `ip route` linux command can be manually used. See the [n2n-gateway.sh](scripts/n2n-gateway.sh) script for an example. See also the following description of other use cases and in depth explanation. ## Special Scenarios ### Assumptions - There are two Local Area Networks, namely 10.11.12.0/24 (maybe at **h**ome) and 192.168.1.0/24 (maybe in **o**ffice). - These networks are connected to the internet via routers 10.11.12.1 and 192.168.1.1, respectively. - In each network, there is a computer running a successfully setup n2n node: 10.11.12.5 (**h**ickory) and 192.168.1.6 (**o**scar). They are connected to their networks through a device called _eth0_. Their n2n devices shall be called _n2n0_, and their n2n IP addresses are 10.99.99.50 (**h**ickory) and 10.99.99.60 (**o**scar) in the 10.99.99.0/24 network. - The _iptables_ are flushed. ### Prerequisites - Both, **h**ickory and **o**scar have ip forwarding enabled: `echo 1 > /proc/sys/net/ipv4/ip_forward` or `sysctl -w net.ipv4.ip_forward=1`. To make this setting persistent over reboot, a file containing the line `net.ipv4.ip_forward=1` could be added in /etc/sysctl.d/ – your distro may vary. - To allow n2n to forward packets, both edge nodes need to be started with `-r` option on their command line. All other regular network interfaces usually already allow packet forwarding and thus do not need any further configuration. ### Reach Complete Office Network from n2n Node at Home - To make **h**ickory send all packets with office destination via **o**scar, **h**ickory needs to be made aware of where to route this packets to. On **h**ickory: `ip route add 192.168.1.0/24 via 10.99.99.60 dev n2n0 src 10.11.12.5`. - **o**scar needs to know where to send packets to, too. So, on **o**scar: `ip route add 10.11.12.5 via 10.99.99.50 dev n2n0 src 192.168.1.6`. **o**scar and **h**ickory should now be able to exchange packets by using just their regular (non-n2n) IP addresses 10.11.12.5 and 192.168.1.6. To make the complete office network aware of how packets or answers are sent to **h**ickory, one more step is required: - Packets from any office computer to **h**ickory need to be directed to **o**scar that – thanks to enabled IP forwarding and the routing rule – already knows how to handle this kind of packets. - To handle it in a one-stop-shop, the office router 192.168.1.1 can be configured to direct those packets to **o**scar. Luckily, even most modern small-office-and-home routers allow to add static routing rules via a web interface. A rule like "All packets for host 10.11.12.5 (or network 10.11.12.0/24) need to be sent to another router, namely 192.168.1.5" will do. This is the **recommended** solution. - However, a **less recommended** but working option would be to add static routes to each single of those computers in the office network that shall be able to connect to or be accessed by **h**ickory. On those, e.g. **o**livia with IP address 192.168.1.123: `ip route add 10.11.12.5 via 192.168.1.5 dev eth0 src 192.168.1.123`. - Alternatively, in case the office router does not allow to have added own static routing rules, **o**scar needs to perform NAT for all connections initiated from **h**ickory: `iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE` `iptables -A FORWARD -i eth0 -o n2n0 -m state --state RELATED,ESTABLISHED -j ACCEPT` `iptables -A FORWARD -i n2n0 -o eth0 -j ACCEPT` There is a major drawback with this solution which thus is the **least recommended**: Connections between **h**ickory and the office network will only work if initiated by **h**ickory – not the other way 'round. By the way, in case _iptables_ are messed up, they can be flushed by: `iptables -F` `iptables -X` `iptables -t nat -F` `iptables -t nat -X` `iptables -t mangle -F` `iptables -t mangle -X` `iptables -t raw -F` `iptables -t raw -X` `iptables -t security -F` `iptables -t security -X` `iptables -P INPUT ACCEPT` `iptables -P FORWARD ACCEPT` `iptables -P OUTPUT ACCEPT` ### Reach n2n Node in Office from Whole Home Network This is easy: - Just exchange home and office IP addresses and the computer names in the instructions given above. ### Reach Whole Home Network from Whole Office Network This is not too complicated either. Basically, follow the given example above and apply the following changes: - The instructions used above need to be expanded from **h**ickory's IP 10.11.12.5 to its full network 10.11.12.0/24 in the route commands on **o**scar:, especially: `ip route add 10.11.12.0/24 via 10.99.99.50 dev n2n0 src 192.168.1.6`. - In case of adding a static route to the office network router 192.168.1.1, the home network 10.11.12.0/24 must be specified instead of **h**ickory's more specific IP address 11.11.12.5. Same for the less recommended static routes on other office computers. - Packets from home network's computers to the office network need to be sent through the n2n tunnel. The three alternatives given above can be used just with exchanged office and home IP addresses. One needs to be aware that NAT only (third alternative) on both sides will not allow any connection, i.e. at least on one side static routes need to be added either to the router (best option) or all those computers that shall be able to connect to the other network. ### Route All Internet Traffic from n2n Node at Home through Office Network This scenario could be considered a n2n-tunneled VPN connection which also would work for travelling users on their laptop. All external internet traffic will appear to originate from **o**scar and the office network. - First, one of the setups described above needs to be in place, with the following change: - NAT on **o**scar (see the three _iptables_ commands above) must be enabled. It will not work without because the office router 192.168.1.1 usually denies forwarding to packets not originating from its own network. It could be in addition to the eventually installed static routes for 10.11.12.0/24 in the router 192.168.1.1 or on other office computers – it will not interfere. However, **o**scar definitely needs the route given above: `ip route add 10.11.12.5 via 10.99.99.50 dev n2n0 src 192.168.1.6`. - To have **h**ickory's complete internet traffic going through the n2n tunnel, its default route needs to be changed: `ip route del default` `ip route add default via 10.99.99.60 dev n2n0 src 10.11.12.5` - **h**ickory's home network should still be reachable as usually, _eth0_ and the associated network 10.11.12.0/24 get their very own route. If not, i.e. it was only covered by default route before, it needs to be added: `ip route add 10.11.12.0/24 dev eth0 src 10.11.12.5`. - Unfortunately (unless the supernode is on **h**ickory's local network), n2n supernode becomes unreachable for **h**ickory. To fix it: `ip route add via 10.11.12.1 dev eth0 src 10.11.12.5` The supernode's IP address needs to be known to have this work. However, if the supernode's IP needs to be resolved from some domain name (FQDN), e.g. in case of using dynamic domain name services, a DNS server needs to remain reachable, too. Either the reachable home network router 10.11.12.1 is good enough for that (if it offers DNS) or another route could to be added and **h**ickory's DNS settings might be set accordingly, maybe to Google's 8.8.8.8. If [DNS leaks](https://en.wikipedia.org/wiki/DNS_leak) do not matter, this setup is complete. ### Preventing DNS Leaks Otherwise, there is more to it: Without changes, all future DNS queries go through the home router 10.11.12.1 to the ISP's servers or directly to Google (via the home router 10.11.12.1 along the configured route for 8.8.8.8 and not through the n2n tunnel) while the remaining traffic ships through the n2n tunnel. To prevent such a DNS leak, the supernode's IP address must be determined independently from **h**ickory's DNS configuration, e.g. by digesting `dig +short mysupernode.myfavoritednsservice.com @8.8.8.8`'s output in the n2n-edge's setup script for both, the edge node command line as well as the static route mentioned above. Without further additional work, dynamic address changes remain undetected. A static route to 8.8.8.8 is still required. **h**ickory's regular DNS configuration should query a different DNS server for its regular DNS needs, e.g. 9.9.9.9 or 1.1.1.1 or maybe the office DNS server, maybe 192.168.1.1. This guarantees the regular DNS queries also to get sent through the n2n tunnel. A test for DNS leaks can be found [here](https://www.dnsleaktest.com/). ntop-n2n-90215bd/doc/Scratchpad.md000066400000000000000000000055571422132035700166730ustar00rootroot00000000000000# n2n's Scratchpad ## RPM Packaging ``` bash ./autogen.sh ./configure make cd packages/rpm ./configure rpmbuild -bb ./n2n.spec ``` ## New Features between 2.0.x and 2.1.x - Better ming Windows build support. - Added `-E` flag to allow multicast ethernet traffic. ## Draft changelog between 2.8 and 3.0 (as of September 27, 2021) ### New Features - Federated supernodes to allow multiple supernodes for load balancing and fail-over (`doc/Federation.md`) - Automatic IP address assignment allows edges to draw IP addresses from the supernode (just skip `-a`) - Allowed community names can be restricted by regular expressions (`community.list` file) - Network filter for rules (`-R`) allowing and denying specific traffic to tunnel - Experimental TCP support (`-S2`) lets edges connect to the supernodes via TCP in case firewalls block UDP (not available on Windows yet) - All four supported ciphers offer integrated versions rendering OpenSSL dependency non-mandatory (optionally still available) - MAC and IP address spoofing prevention - Network interface metric can be set by command-line option `-x` (Windows only) - Re-enabled local peer detection by multicast on Windows - Edge identifier (`-I`) helps to identify edges more easily in management port output - Optionally bind edge to one local IP address only (extension to `-p`) - A preferred local socket can be advertised to other edges for better local peer-to-peer connections (`-e`) - Optional edge user and password authentication (`-J`, `-P`, `doc/Authentication.md`) - Optional json format at management port allows for machine-driven handling such as `.html` page generation (`scripts/n2n-httpd`) or script-based evaluation (`scripts/n2n-ctl`) - Completely overhauled build system including GitHub's action runners performing code syntax and formal checks, creating and running test builds, providing binairies and packages as artifacts and running verification tests ### Improvements - Increased edges' resilience to temporary supernode failure - Fixed a compression-related memory leak - Ciphers partly come with platform-specific hardware acceleration - Added a test framework (`tools/test-*.c` and `tests/`) - Clean-up management port output - Polished benchmark tool output - Spun-off the name resolution into a separate thread avoiding lags - Added support for additional environment variables (`N2N_COMMUNITY`, `N2N_PASSWORD`, and `N2N_FEDERATION`) - Implemented new `reload_communities` command to make supernode hot-reload the `-c` provided `community.list` file, issued through management port - Reactivated send out of gratuitous ARP packet on establishing connection - Enhanced documentation (`doc/` folder) including the man pages and command-line help text (`-h` and more detailed `--help`) - Self-monitoring time stamp accuracy for use on systems with less accurate clocks - Fixed man pages' and config files' paths - Code clean-up ntop-n2n-90215bd/doc/Scripts.md000066400000000000000000000064211422132035700162350ustar00rootroot00000000000000# Scripts There are a number of useful scripts included with the distribution. Some of these scripts are only useful during build and development, but other scripts are intended for end users to be able to use. These scripts may be installed with n2n as part of your operating system package. All scripts can be found in the `scripts` directory. Short descriptions of these scripts are below. ## End user scripts ### `n2n-ctl` This python script provides an easy command line interface to the running n2n processes. It uses UDP communications to talk to the Management API. By specifying the right UDP port, it can talk to both the edge and the supernode daemons. Example: - `scripts/n2n-ctl --help` - `scripts/n2n-ctl help` ### `n2n-httpd` This python script is a simple http gateway to the running edge. It provides a proxy for REST-like HTTP requests to talk to the Management API. By default it runs on port 8080. It also provides a simple HTML page showing some edge information, which when run with default settings can be seen at http://localhost:8080/ (Also a http://localhost:8080/supernode.html page for the supernode) Example: - `scripts/n2n-httpd --help` - `scripts/n2n-httpd 8087` ## Build and Development scripts ### `hack_fakeautoconf.sh` This shell script is used during development to help build on Windows systems. An example of how to use it is shown in the [Building document](Building.md) ### `indent.sh` This shell script is a wrapper for the `uncrustify` C code style checker which checks or applies a set of rules to the code. It is used during the automated lint checks. ### `n2n-gateway.sh` A sample script to route all the host traffic towards a remote gateway, which is reachable via the n2n virtual interface. ### `version.sh` This script is used to determine the current version number during the build process. It looks at both the VERSION file and the GIT tags and outputs the version number to use. ## Monitoring and statistics ### `munin/n2n_` This is a simple monitoring script that can be used with the munin-node system to monitor the n2n daemons. This is a fully autoconfigurable wildcard munin plugin, but to get a quick sample: get a list of suggested plugin names: ``` munin/n2n_ suggest ``` Enable some of those names: ``` ln -s /usr/share/munin/plugins/n2n_ /etc/munin/plugins/n2n_supernode_pkts ln -s /usr/share/munin/plugins/n2n_ /etc/munin/plugins/n2n_supernode_counts ``` Manually test fetching and config: ``` /etc/munin/plugins/n2n_supernode_pkts /etc/munin/plugins/n2n_supernode_pkts config ``` ## Testing scripts ### `test_harness.sh` This shell script is used to run automated tests during development. It is run with a testlist filename - pointing at a file containing the list of tests to run. Each test needs a file containing the expected output `${TESTNAME}.expected` which is expected to exist in the same directory as the testlist (this dir is referred to as `${listdir}` below). Each test is a program, searched for in several locations, including the `${listdir}/../scripts` dir. Each test is run with its output being sent to `*.out` files in the `listdir` and compared with the expected output. ### `scripts/test_integration_supernode.sh` This starts a supernode and runs an integration test on the Json API using the `n2n-ctl` command. ntop-n2n-90215bd/doc/TapConfiguration.md000066400000000000000000000227041422132035700200640ustar00rootroot00000000000000# TAP Device Configuration n2n provides its service through a TAP device which is the virtual ethernet device seen by the computer and user. As a prerequisite, it requires the appropriate TAP driver to be installed. Most Linux systems come with it. If not loaded, `sudo modprobe tap` will do. For MacOS and Windows there are specific instructions; please see the [Building](./Building.md) document. ## Device Name If the OS specific driver allows **naming** the virtual Ethernet device created by n2n, the `-d ` command-line option can be used to give a name, e.g. `-d n2n0`. This device name makes the virtual ethernet device easily accessible to all `ip` command activity, `iptables`, `tcpdump` and any other of your preferred network tools. It defaults to `edge0` if not provided through `-d`. One exception applies to Windows: As the installed TAP driver(s) come with fixed names, `-d ` **selects** the appropriate device by name out of the present ones. This is only required if more than one TAP devices are present. To help with it, `edge --help` lists the available TAP adapters at the bottom of its output (Windows only). ## MAC Even virtual ethernet devices have a MAC address. As in real networks, it should be unique as it is used to identify the different participants and transport packets accordingly. The MAC address can optionally be specified by using the `-m ` command line parameter, e.g. `-m 01:02:03:04:05:06`. If omitted, n2n tries to assign a random MAC address. ## IP Address n2n supports several ways to assign an IPv4 address to the virtual ethernet device. Support for IPv6 addresses relies on OS support. ### Manually Assigned IP Address The command line parameter `-a ` assigns a static IP address, e.g. `-a static:192.168.8.5` to the device. The optional `static` keyword (and the delimiting colon) can be omitted, so `-a 192.168.8.5` works as well. The netmask in CIDR notation can optionally be appended to the address, e.g. `-a 192.168.8.5/24` for netmask `255.255.255.0` which also is the default should the netmask not be provided. ### Auto IP Address If `-a` is omitted, the supernode assigns an IP address to the node. This feature uses different IP address pools on a per-community basis. So, all edges of the same community will find themselves in the same sub-network. By default, `/24`-sized IP address sub-network pools from the upper half of the `10.0.0.0` class A network will be used, that is from `10.128.0.0/24` … `10.255.255.0/24`. The supernode can be configured to assign addresses from a different network range: `-a 10.0.0.0-10.255.0.0/16` would the supernode make use of the complete `10.0.0.0` class A range but handle `/16`-sized sub-networks. Also, named communities could be pre-assigned certain sub-networks, please see the explanatory comments in the `community.list` file. ### DHCP If an edge of the community runs a DHCP server, the others could draw their IP addresses from there. It requires the new edges to start-up with the `-r -a dhcp:0.0.0.0` parameters (literally). More details can be found [at this discussion](https://github.com/ntop/n2n/issues/629). ### IPv6 n2n supports the carriage of IPv6 packets within the n2n tunnel. n2n does not yet use IPv6 for transport between edges and supernodes. To make IPv6 carriage work you need to manually add IPv6 addresses to the TAP interfaces at each end. There is currently no way to specify an IPv6 address on the edge command line. For example, under Linux on hostA: `[hostA] $ /sbin/ip -6 addr add fc00:abcd:1234::7/48 dev n2n0` on hostB: `[hostB] $ /sbin/ip -6 addr add fc00:abcd:1234::6/48 dev n2n0` You may find it useful to make use of `tunctl` from the uml-utilities package. `tunctl` allows you to bring up a TAP interface and configure addressing prior to starting the edge. It also allows the edge to be restarted without the interface closing (which would normally affect routing tables). Once the IPv6 addresses are configured and edge is started, IPv6 neighbor discovery packets flow (get broadcast) and IPv6 entities self-arrange. Test your IPv6 setup with `ping6` - the IPv6 ping command. ## MTU The MTU of the VPN interface is set to a lower value (rather than the standard value of 1500 bytes) to avoid excessive fragmentation of the datagram sent over the internet. This is required because n2n adds additional headers to the packets received from the VPN interface. The size of the final frame sent through the internet interface must have a size lower or equal to the internet interface MTU (usually 1500 bytes). As a fragmentation example, suppose that a 3000 byte TCP segment should be sent through the VPN. If the VPN interface MTU is set to 1500, the packet will be split into two fragments of 1500 bytes each. However, n2n will add its headers to each fragment, so each fragment becomes a 1540 byte packet. The internet interface MTU of 1500 bytes will fragment each packet again in two further fragments, e.g. 1500 + 50 bytes, so a total of 4 fragments will be sent over the internet. On the other hand, if the VPN interface MTU was set to 1460 bytes, it would result in only 3 fragments sent as the initial segment of 3000 bytes would be split in 1460 + 1460 + 80 bytes without further fragmentation. IP packet fragmentation in general is something to avoid, as described in http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-87-3.pdf. If possible, the fragmentation should be moved to the TCP layer by a proper MSS value. This can be forced by mangling the packet MSS, which is called "MSS clamping" (currently not implemented in n2n). See https://github.com/gsliepen/tinc/blob/228a03aaa707a5fcced9dd5148a4bdb7e5ef025b/src/route.c#L386. The exact value to use as a clamp value, however, depends on the PMTU, which is the minimum MTU of the path between two hosts. Knowing the PMTU is also useful for a sender in order to avoid fragmentation at IP level. Trying to find the highest non-fragmenting MTU possible is useful since it allows to maximize bandwidth. ### PMTU Discovery Failures Most operating systems try to periodically discover the PMTU by using a PMTU discovery algorithm. This involves setting the DF (don't fragment) flag on the IP packets. When a large IP packet exceeds the MTU of a router in the path, an "ICMP Fragmentation Needed" message should be received, which will help the OS along to tune the size of the next IP packets. However, some routers do not report such ICMP message, which results in packets being silently dropped. The `tracepath` tool can be used to detect the PMTU. The main problem with this situation is that the actual PMTU is unknown, so an automatic solution is not applicable. The user must manually specify a lower MTU for the VPN interface in order to solve the issue. ### n2n and MTU n2n shall work by default in different environments. For this reason, the following solution has been provided: - PMTU discovery is disabled if possible (via the IP_MTU_DISCOVER socket option). This avoids silently dropping an oversized packet due to the DF flag; however, it possibly increments fragmentation on the path. - As explained above, a lower MTU is set on the VPN interface, thus removing excessive fragmentation on the sender. - A value of 1290 bytes is used instead of 1500 bytes as reference value for the internet interface MTU. This essentially avoids fragmentation if the PMTU is greater or equal than 1400 bytes. This is a conservative solution which should make n2n work by default. The user can manually specify the MTU (`-M `) and re-enable PMTU discovery (`-D`) via the command-line interface options. ## Interface Metric and Broadcasts On Windows, broadcasts are sent out to the network interface with the lowest metric only. This usually is the WAN interface with its default metric of `25`. The `-x ` option could be used to configure the TAP with a lower interface metric and hence facilitate service and online game server detection over n2n. Linux and others do not require this feature as broadcasts are sent to all network interfaces by default, also to the virtual ones. ## Multicast n2n does not transmit multicast packets by default. It can be enabled by edge's `-E` command-line parameter. ## Egde Description To keep edge's and supernode's management port output well arranged and understandable, each edge can have a plain text description fed to the edge by the optional `-I ` command-line parameter. If not provided, n2n uses the hostname by default. A description field's hash value is used to choose an auto IP address. So, just be aware that changing the hostname can lead to assigning a different auto IP address on next edge start-up – if auto IP address is used. ## Routing n2n supports routing the traffic through its network. `-r` enables an edge to accept packets at its TAP interface not originating from the local IP address or not destined to the local IP address. As there is more to routing than just this one command-line option, please refer to the dedicated [Routing](Routing.md) document explaining it all in detail. ## Traffic Filter Setting up the integrated traffic filter permits to define exactly the kind of allowed traffic or deny other on edge's TAP interface. It helps to keep unwanted traffic out of the n2n network for bandwidth and security reasons. The traffic filter is disabled by default and gets activated by providing as many `-R `-rules as required through edge's command-line. Specifics are written down in the [Traffic Restrictions](TrafficRestricitons.md) documentation. ntop-n2n-90215bd/doc/TrafficRestrictions.md000066400000000000000000000044131422132035700205740ustar00rootroot00000000000000# Traffic Restrictions It is possible to drop or accept specific packet transmit over edge network interface by rules. Rules can be specify by (`-R rule_str`) multiple times. ## Rule String Format rule_str format: `src_ip/len:[b_port,e_port],dst_ip/len:[s_port,e_port],TCP+/-,UDP+/-,ICMP+/-` `ip/len` indicate a cidr block, len can be ignore, means single ip (not cidr block) will be use in filter rule. `+`,`-` 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. 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. examples: `192.168.1.5/32:[0,65535],192.168.0.0/24:[8081,65535],TCP-,UDP-,ICMP+` `192.168.1.5:[0,65535],192.168.0.0/24:8000,ICMP+` `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. ## Multiple Rules `-R rule_str` can be used multiple times to add multiple rules. Each `-R rule_str` add one rule. for example: `edge -c xxxx -k xxxx -a 192.168.100.5 -l xxx.xxx.xxx.xxx:1234 -r -R 192.168.1.5/32:[0,65535],192.168.0.0/24:[8081,65535],TCP-,UDP-,ICMP+ -R 192.168.1.5:[0,65535],192.168.0.0/24:8000,ICMP+ -R 192.168.1.5,192.168.0.7,TCP-` ## Matching Rules Priority 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. 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. ## Blocklist/Allowlist mode Packets that cannot match any rule will be accepted by default. Users can add rules to block traffics. 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. for example, `-R 0.0.0.0/0,0.0.0.0/0,TCP-,UDP-,ICMP- -R 192.168.100.0/24,192.168.100.0/24,ICMP+` dropped all traffic, except ICMP traffics inside `192.168.100.0/24`. More complex behavior can be set with the feature of `Matching Rules Priority`. ntop-n2n-90215bd/edge.8000066400000000000000000000266641422132035700145270ustar00rootroot00000000000000.TH edge 8 "18 Jul 2021" "version 3" "SUPERUSER COMMANDS" .SH NAME edge \- n2n edge node daemon .SH SYNOPSIS .B edge .br .B edge \-c \-l [further options]... .SH DESCRIPTION N2N is a peer-to-peer VPN system. Edge is the edge node daemon for n2n which creates a TAP interface to expose the n2n virtual LAN. On startup n2n creates the TAP interface and configures it then registers with the supernode so it can begin to find other nodes in the community. .PP The config file is similar to the command line, with one option per line. Lines starting with a "#" are ignored. An equal sign ('=') should be used between key and value. Example: -p=7777 .SH OPTIONS FOR THE UNDERLYING NETWORK CONNECTION .TP \fB\-c \fR<\fIcommunity\fR>, \fB\-\-community\fR=<\fIcommunity\fR> sets the n2n community name (see also N2N_COMMUNITY in ENVIRONMENT). All edges within the same community appear on the same LAN (layer 2 network segment). Community name is 16 bytes in length. A name smaller than this is padded with 0x00 bytes and a name longer than this is truncated to take the first 16 bytes. .TP \fB\-l \fR<\fIhost:port\fR>, \fB\-\-supernode-list\fR=<\fIhost:port\fR> sets the n2n supernode IP address and port to register to. Multiple supernodes can be specified. .TP \fB\-p \fR[<\fIlocal_ip_address\fR>:]<\fIlocal_port\fR> binds edge to the given UDP port. Useful for keeping the same external socket across restarts of edge. This allows peer edges which know the edge socket to continue p2p operation without going back to the supernode. Also, home router's port forwarding feature can refer to that fixed port. Optionally, the edge can bind to the provided local ip address only. This is useful in case restriction to a certain LAN or WiFi interface is desired. By default, the edge binds to any interface. .TP \fB\-T \fR<\fItos\fR> TOS for packets, e.g. 0x48 for SSH like priority .TP \fB\-D\fR enable PMTU discovery, it can reduce fragmentation but causes connections to stall if not properly supported .TP \fB\-e \fR<\fIlocal_ip_address\fR> advertises the provided local IP address as preferred, useful if multicast peer detection is not available, e.g. disabled on routers. \fB\-e auto\fR tries auto-detection of local IP address. .TP \fB\-S1\fR ... \fB\-S2\fR do not connect p2p, always use the supernode, \-S1 = via UDP, \-S2 = via TCP .TP \fB\-i \fR<\fIreg_interval\fR> Supernode registration interval. It specifies the interval in seconds between consecutive REGISTER_SUPER packets and it's used to keep NAT hole open via the UDP NAT hole punching technique. This only works for asymmetric NATs and allows for P2P communication. .TP \fB\-L \fR<\fIreg_ttl\fR> set the TTL for the hole punching packet. This is an advanced flag to make sure that the registration packet is dropped immediately when it goes out of local nat so that it will not trigger some firewall behavior on target peer. Actually, the registration packet is only expected to make local nat UDP hole and is not expected to reach the target peer, see https://tools.ietf.org/html/rfc5389. To achieve this, the flag should be set as nat level + 1. For example, if we have 2 layer nat in local, we should set -L 3. Usually we know exactly how much nat layers in local. If we are not sure how much nat layers in local, we can use traceroute on Linux to check. The following example shows a local single layer nat because on second jump it shows a public ip address. In this case it should set -L 2. $ /usr/sbin/traceroute -w1 8.8.8.8 .br traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets 1 192.168.3.1 (192.168.3.1) 0.464 ms 0.587 ms 0.719 ms 2 112.65.17.217 (112.65.17.217) 5.269 ms 7.031 ms 8.666 ms But this method does not always work due to various local network device policy. .TP \fB\-k \fR<\fIkey\fR> encryption key (ASCII) - also N2N_KEY= \-k sets the encryption key from ASCII text (see also N2N_KEY in ENVIRONMENT). All edges communicating must use the same key and community name. If -k not specified then edge uses cleartext mode (no encryption). .TP \fB\-A1\fR disable payload encryption, do not use with key, defaults to AES then .TP \fB\-A2\fR ... \fB\-A5\fR choose a cipher for payload encryption, requires a key, \-A2 = Twofish, \-A3 = AES (default if key provided), \-A4 = ChaCha20, \-A5 = Speck-CTR .TP \fB\-H\fR use header encryption, supernode needs fixed community .TP \fB\-z1\fR ... \fB\-z2\fR compress outgoing data packets, -z1 = lzo1x, disabled by default .TP \fB\-\-select-rtt\fR select supernode by round trip time if several to choose from (federation), defaults to load-based selection strategy if not provided. .TP \fB\-\-select-mac\fR select supernode by MAC address if several to choose from (federation), lowest MAC address first. .TP \fB\-\-no-port-forwarding\fR disables the default behavior of trying to have the edge's port forwarded through a router eventually supporting it (only if compiled with miniupnp and/or natpmp library support). .SH TAP DEVICE AND OVERLAY NETWORK CONFIGURATION .TP \fB\-a \fR[\fImode\fR]<\fIip\fR>[\fI/n\fR] interface address and optional CIDR subnet, default '/24', mode = [static|dhcp]:, for DHCP use '\-r -a dhcp:0.0.0.0', edge draws IP address from supernode if no '\-a ...' given .TP \fB\-m \fR<\fImac\fR> start the TAP interface with the given MAC address. This is highly recommended as it means the same address will be used if edge stops and restarts. If this is not done, the ARP caches of all peers will be wrong and packets will not flow to this edge until the next ARP refresh. e.g. '\-m 10:20:30:40:50:60', by default a random MAC address is used. .TP \fB\-d \fR<\fIdevice\fR>, \fB\-\-device\fR=<\fIdevice\fR> TAP device name .TP \fB\-M \fR<\fImtu\fR> specify n2n MTU of TAP interface, default 1290 .TP \fB\-r\fR enable IP packet forwarding/routing through the n2n virtual LAN. Without this option, IP packets arriving over n2n are dropped if not for the -a (or DHCP assigned) IP address of the edge interface. .TP \fB\-E\fR accept packets destined for multicast ethernet MAC addresses. These addresses are used in multicast ethernet and IPv6 neighbour discovery. If this option is not present these multicast packets are discarded as most users do not need or understand them. .TP \fB\-I \fR<\fIdescription\fR> annotate the edge's description used for easier identification in management port output or username .TP \fB\-J \fR<\fIpassword\fR> password for user-password edge authentication (see also N2N_PASSWORD in ENVIRONMENT) .TP \fB\-P \fR<\fIpublic key\fR> federation public key for user-password authentication .TP \fB\-R \fR<\fIrule_str\fR> Add rule to drop or accept specific packet transmit over edge network interface. -R rule_str can be used multiple times to add multiple rules. Each -R rule_str add one rule. rule_str format:"src_ip/len:[b_port,e_port],dst_ip/len:[s_port,e_port],TCP+/-,UDP+/-,ICMP+/-". ip/len indicate a cidr block, len can be ignore, means single ip(not cidr block) will be use in filter rule. +,- 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. 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. 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. Packets that cannot match any rule will be accepted by default. Users can add rules to block traffics. 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. for example : `-R 0.0.0.0/0,0.0.0.0/0,TCP-,UDP-,ICMP- -R 192.168.100.0/24,192.168.100.0/24,ICMP+`, .TP \fB\-x \fR<\fImetric\fR> set TAP interface metric, defaults to 0 (auto), e.g. set to 1 for better multiplayer game detection. .br (Windows only) .SH LOCAL OPTIONS .TP \fB\-f\fR do not fork and run as a daemon, rather run in foreground .TP \fB\-t \fR<\fIport\fR> binds the edge management system to the given UDP port. Default 5644. Use this if you need to run multiple instance of edge; or something is bound to that port. .TP \fB\-\-management-password \fR<\fIpassword\fR> sets the password for access to JSON API at the management port, defaults to 'n2n'. The password has to be provided when using 'scripts/n2n-ctl', 'scripts/n2n-httpd' or for any other relevant access to JSON API at the management port. .TP \fB\-v\fR, \fB\-\-verbose\fR make more verbose, repeat as required .TP \fB\-n \fR<\fIcidr:gateway\fR> route an IPv4 network via the gateway, use 0.0.0.0/0 for the default gateway, can be set multiple times .TP \fB\-u \fR<\fIUID\fR>, \fB\-\-euid\fR=<\fIUID\fR> numeric user ID to use when privileges are dropped .TP \fB\-g \fR<\fIGID\fR>, \fB\-\-egid\fR=<\fIGID\fR> numeric group ID to use when privileges are dropped .TP \fb\-h\fr write usage then exit. .TP \fb\--help\fr shows detailed parameter description .SH ENVIRONMENT .TP .B N2N_KEY set the encryption key so it is not visible at the command line .TP .B N2N_COMMUNITY set the community name so it is not visible at the command line .TP .B N2N_PASSWORD set the password for user-password authentication so it is not visible at the command line .SH EXAMPLES .TP .B edge \-d n2n0 \-c mynetwork \-k encryptme \-u 99 \-g 99 \-m DE:AD:BE:EF:01:23 \-a 192.168.254.7 \-p 50001 \-l 123.121.120.119:7654 Start edge with TAP device n2n0 on community "mynetwork" with community supernode at 123.121.120.119 UDP port 7654 and bind the locally used UDP port to 50001. Use "encryptme" as the single permanent shared encryption key. Assign MAC address DE:AD:BE:EF:01:23 to the n2n interface and drop to user=99 and group=99 after the TAP device is successfully configured. .PP Add the -f option to stop edge running as a daemon. .PP Somewhere else setup another edge with similar parameters, eg. .B edge \-d n2n0 \-c mynetwork \-k encryptme \-u 99 \-g 99 \-m DE:AD:BE:EF:01:21 \-a 192.168.254.5 \-p 50001 \-l 123.121.120.119:7654 .PP Now you can ping from 192.168.254.5 to 192.168.254.7. .PP The MAC address (-m ) and virtual IP address (-a ) must be different on all edges in the same community. .SH CLEARTEXT MODE If .B -k is not specified then edge uses cleartext mode. In cleartext mode there is no transform of the packet data it is simply encrypted. This is useful for debugging n2n as packet contents can be seen clearly. To prevent accidental exposure of data, edge only enters cleartext mode when no keying parameters are specified. In the case where keying parameters are specified but no valid keys can be determined, edge exits with an error at startup. If all keys become invalid while running, edge continues to encode using the last key that was valid. .SH MANAGEMENT INTERFACE Edge provides a very simple management system on UDP port 5644. Send a newline to receive a status output. Send 'stop' to cause edge to exit cleanly. .TP .B echo | nc -w1 -u 127.0.0.1 5644 Shows the current statistics of a running edge. .SH EXIT STATUS edge is a daemon and any exit is an error. .SH AUTHORS .TP Richard Andrews andrews (at) ntop.org - n2n-1 maintainer and main author of n2n-2 .TP Luca Deri deri (at) ntop.org - original author of n2n .TP Don Bindner (--) - significant contributions to n2n-1 .SH SEE ALSO ifconfig(8) supernode(1) tunctl(8) n2n(7) .br the documentation contained in the source code .br the extensive documentation found in n2n's \fBdoc/\fR folder ntop-n2n-90215bd/include/000077500000000000000000000000001422132035700151375ustar00rootroot00000000000000ntop-n2n-90215bd/include/aes.h000066400000000000000000000057341422132035700160710ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" // HAVE_OPENSSL_1_1, traceEvent ... #ifndef AES_H #define AES_H #include #include #include "portable_endian.h" #define AES_BLOCK_SIZE 16 #define AES_IV_SIZE (AES_BLOCK_SIZE) #define AES256_KEY_BYTES (256/8) #define AES192_KEY_BYTES (192/8) #define AES128_KEY_BYTES (128/8) #if defined (HAVE_OPENSSL_1_1) // openSSL 1.1 --------------------------------------------------------------------- #include #include #include typedef struct aes_context_t { EVP_CIPHER_CTX *enc_ctx; /* openssl's reusable evp_* en/de-cryption context */ EVP_CIPHER_CTX *dec_ctx; /* openssl's reusable evp_* en/de-cryption context */ const EVP_CIPHER *cipher; /* cipher to use: e.g. EVP_aes_128_cbc */ uint8_t key[AES256_KEY_BYTES]; /* the pure key data for payload encryption & decryption */ AES_KEY ecb_dec_key; /* one step ecb decryption key */ } aes_context_t; #elif defined (__AES__) && defined (__SSE2__) // Intel's AES-NI --------------------------------------------------- #include typedef struct aes_context_t { __m128i rk_enc[15]; __m128i rk_dec[15]; int Nr; } aes_context_t; #else // plain C -------------------------------------------------------------------------------------------------- typedef struct aes_context_t { uint32_t enc_rk[60]; // round keys for encryption uint32_t dec_rk[60]; // round keys for decryption int Nr; // number of rounds } aes_context_t; #endif // --------------------------------------------------------------------------------------------------------- int aes_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, aes_context_t *ctx); int aes_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, aes_context_t *ctx); int aes_ecb_decrypt (unsigned char *out, const unsigned char *in, aes_context_t *ctx); int aes_init (const unsigned char *key, size_t key_size, aes_context_t **ctx); int aes_deinit (aes_context_t *ctx); #endif // AES_H ntop-n2n-90215bd/include/auth.h000066400000000000000000000025501422132035700162530ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #include "n2n.h" #ifndef AUTH_H #define AUTH_H int bin_to_ascii (char *out, uint8_t *in, size_t in_len); int ascii_to_bin (uint8_t *out, char *in); int generate_private_key (n2n_private_public_key_t key, char *in); int generate_public_key (n2n_private_public_key_t pub, n2n_private_public_key_t prv); int generate_shared_secret (n2n_private_public_key_t shared, n2n_private_public_key_t prv, n2n_private_public_key_t pub); int bind_private_key_to_username (n2n_private_public_key_t prv, char *username); int calculate_dynamic_key (uint8_t out_key[N2N_AUTH_CHALLENGE_SIZE], uint32_t key_time, n2n_community_t comm, n2n_community_t fed); #endif ntop-n2n-90215bd/include/cc20.h000066400000000000000000000044131422132035700160410ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #ifndef CC20_H #define CC20_H #include #include "n2n.h" // HAVE_OPENSSL_1_1, traceEvent ... #define CC20_IV_SIZE 16 #define CC20_KEY_BYTES (256/8) #ifdef HAVE_OPENSSL_1_1 // openSSL 1.1 ---------------------------------------------------------------------------- #include #include typedef struct cc20_context_t { EVP_CIPHER_CTX *ctx; /* openssl's reusable evp_* en/de-cryption context */ const EVP_CIPHER *cipher; /* cipher to use: e.g. EVP_chacha20() */ uint8_t key[CC20_KEY_BYTES]; /* the pure key data for payload encryption & decryption */ } cc20_context_t; #elif defined (__SSE2__) // SSE2 --------------------------------------------------------------------------------- #include typedef struct cc20_context { uint32_t keystream32[16]; uint8_t key[CC20_KEY_BYTES]; } cc20_context_t; #else // plain C -------------------------------------------------------------------------------------------------- typedef struct cc20_context { uint32_t keystream32[16]; uint32_t state[16]; uint8_t key[CC20_KEY_BYTES]; } cc20_context_t; #endif // openSSL 1.1, plain C ------------------------------------------------------------------------------------ int cc20_crypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, cc20_context_t *ctx); int cc20_init (const unsigned char *key, cc20_context_t **ctx); int cc20_deinit (cc20_context_t *ctx); #endif // CC20_H ntop-n2n-90215bd/include/curve25519.h000066400000000000000000000014261422132035700170450ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ void curve25519 (unsigned char *q, const unsigned char *n, const unsigned char *p); ntop-n2n-90215bd/include/edge_utils_win32.h000066400000000000000000000030521422132035700204560ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #ifndef _EDGE_UTILS_WIN32_H_ #define _EDGE_UTILS_WIN32_H_ #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include #include #include #include /* Multicast peers discovery disabled due to https://github.com/ntop/n2n/issues/65 */ /* Currently, multicast is performed by specifying the default routing network adapter. * If the solution is determined to be stable and effective, * all macro definitions "SKIP_MULTICAST_PEERS_DISCOVERY" will be completely deleted in the future. */ //#define SKIP_MULTICAST_PEERS_DISCOVERY // TODO: this struct is pretty empty now, collapse it to just n2n_edge_t ? struct tunread_arg { n2n_edge_t *eee; }; extern HANDLE startTunReadThread (struct tunread_arg *arg); int get_best_interface_ip (n2n_edge_t * eee, dec_ip_str_t ip_addr); #endif /* WIN32 */ #endif /* _EDGE_UTILS_WIN32_H_ */ ntop-n2n-90215bd/include/header_encryption.h000066400000000000000000000030421422132035700210110ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ int packet_header_decrypt (uint8_t packet[], uint16_t packet_len, char *community_name, he_context_t *ctx, he_context_t *ctx_iv, uint64_t *stamp); int packet_header_encrypt (uint8_t packet[], uint16_t header_len, uint16_t packet_len, he_context_t *ctx, he_context_t *ctx_iv, uint64_t stamp); void packet_header_setup_key (const char *community_name, he_context_t **ctx_static, he_context_t **ctx_dynamic, he_context_t **ctx_iv_static, he_context_t **ctx_iv_dynamic); void packet_header_change_dynamic_key (uint8_t *key_dynamic, he_context_t **ctx_dynamic, he_context_t **ctx_iv_dynamic); ntop-n2n-90215bd/include/hexdump.h000066400000000000000000000001711422132035700167610ustar00rootroot00000000000000#ifndef HEXDUMP_H #define HEXDUMP_H void fhexdump(unsigned int display_addr, void *in, int size, FILE *stream); #endif ntop-n2n-90215bd/include/lzoconf.h000066400000000000000000000405071422132035700167700ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* lzoconf.h -- configuration of the LZO data compression library This file is part of the LZO real-time data compression library. Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ #ifndef __LZOCONF_H_INCLUDED #define __LZOCONF_H_INCLUDED 1 #define LZO_VERSION 0x20a0 /* 2.10 */ #define LZO_VERSION_STRING "2.10" #define LZO_VERSION_DATE "Mar 01 2017" /* internal Autoconf configuration file - only used when building LZO */ #if defined(LZO_HAVE_CONFIG_H) # include #endif #include #include /*********************************************************************** // LZO requires a conforming ************************************************************************/ #if !defined(CHAR_BIT) || (CHAR_BIT != 8) # error "invalid CHAR_BIT" #endif #if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) # error "check your compiler installation" #endif #if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) # error "your limits.h macros are broken" #endif /* get OS and architecture defines */ #ifndef __LZODEFS_H_INCLUDED #include #endif #ifdef __cplusplus extern "C" { #endif /*********************************************************************** // some core defines ************************************************************************/ /* memory checkers */ #if !defined(__LZO_CHECKER) # if defined(__BOUNDS_CHECKING_ON) # define __LZO_CHECKER 1 # elif defined(__CHECKER__) # define __LZO_CHECKER 1 # elif defined(__INSURE__) # define __LZO_CHECKER 1 # elif defined(__PURIFY__) # define __LZO_CHECKER 1 # endif #endif /*********************************************************************** // integral and pointer types ************************************************************************/ /* lzo_uint must match size_t */ #if !defined(LZO_UINT_MAX) # if (LZO_ABI_LLP64) # if (LZO_OS_WIN64) typedef unsigned __int64 lzo_uint; typedef __int64 lzo_int; # define LZO_TYPEOF_LZO_INT LZO_TYPEOF___INT64 # else typedef lzo_ullong_t lzo_uint; typedef lzo_llong_t lzo_int; # define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG_LONG # endif # define LZO_SIZEOF_LZO_INT 8 # define LZO_UINT_MAX 0xffffffffffffffffull # define LZO_INT_MAX 9223372036854775807LL # define LZO_INT_MIN (-1LL - LZO_INT_MAX) # elif (LZO_ABI_IP32L64) /* MIPS R5900 */ typedef unsigned int lzo_uint; typedef int lzo_int; # define LZO_SIZEOF_LZO_INT LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INT LZO_TYPEOF_INT # define LZO_UINT_MAX UINT_MAX # define LZO_INT_MAX INT_MAX # define LZO_INT_MIN INT_MIN # elif (ULONG_MAX >= LZO_0xffffffffL) typedef unsigned long lzo_uint; typedef long lzo_int; # define LZO_SIZEOF_LZO_INT LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG # define LZO_UINT_MAX ULONG_MAX # define LZO_INT_MAX LONG_MAX # define LZO_INT_MIN LONG_MIN # else # error "lzo_uint" # endif #endif /* The larger type of lzo_uint and lzo_uint32_t. */ #if (LZO_SIZEOF_LZO_INT >= 4) # define lzo_xint lzo_uint #else # define lzo_xint lzo_uint32_t #endif typedef int lzo_bool; /* sanity checks */ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int) == LZO_SIZEOF_LZO_INT) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_INT) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t)) #ifndef __LZO_MMODEL #define __LZO_MMODEL /*empty*/ #endif /* no typedef here because of const-pointer issues */ #define lzo_bytep unsigned char __LZO_MMODEL * #define lzo_charp char __LZO_MMODEL * #define lzo_voidp void __LZO_MMODEL * #define lzo_shortp short __LZO_MMODEL * #define lzo_ushortp unsigned short __LZO_MMODEL * #define lzo_intp lzo_int __LZO_MMODEL * #define lzo_uintp lzo_uint __LZO_MMODEL * #define lzo_xintp lzo_xint __LZO_MMODEL * #define lzo_voidpp lzo_voidp __LZO_MMODEL * #define lzo_bytepp lzo_bytep __LZO_MMODEL * #define lzo_int8_tp lzo_int8_t __LZO_MMODEL * #define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL * #define lzo_int16_tp lzo_int16_t __LZO_MMODEL * #define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL * #define lzo_int32_tp lzo_int32_t __LZO_MMODEL * #define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL * #if defined(lzo_int64_t) #define lzo_int64_tp lzo_int64_t __LZO_MMODEL * #define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL * #endif /* Older LZO versions used to support ancient systems and memory models * such as 16-bit MSDOS with __huge pointers or Cray PVP, but these * obsolete configurations are not supported any longer. */ #if defined(__LZO_MMODEL_HUGE) #error "__LZO_MMODEL_HUGE memory model is unsupported" #endif #if (LZO_MM_PVP) #error "LZO_MM_PVP memory model is unsupported" #endif #if (LZO_SIZEOF_INT < 4) #error "LZO_SIZEOF_INT < 4 is unsupported" #endif #if (__LZO_UINTPTR_T_IS_POINTER) #error "__LZO_UINTPTR_T_IS_POINTER is unsupported" #endif LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4) /* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should * work but have not received much testing lately, so be strict here. */ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep)) /*********************************************************************** // function types ************************************************************************/ /* name mangling */ #if !defined(__LZO_EXTERN_C) # ifdef __cplusplus # define __LZO_EXTERN_C extern "C" # else # define __LZO_EXTERN_C extern # endif #endif /* calling convention */ #if !defined(__LZO_CDECL) # define __LZO_CDECL __lzo_cdecl #endif /* DLL export information */ #if !defined(__LZO_EXPORT1) # define __LZO_EXPORT1 /*empty*/ #endif #if !defined(__LZO_EXPORT2) # define __LZO_EXPORT2 /*empty*/ #endif /* __cdecl calling convention for public C and assembly functions */ #if !defined(LZO_PUBLIC) # define LZO_PUBLIC(r) __LZO_EXPORT1 r __LZO_EXPORT2 __LZO_CDECL #endif #if !defined(LZO_EXTERN) # define LZO_EXTERN(r) __LZO_EXTERN_C LZO_PUBLIC(r) #endif #if !defined(LZO_PRIVATE) # define LZO_PRIVATE(r) static r __LZO_CDECL #endif /* function types */ typedef int (__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem ); typedef int (__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem ); typedef int (__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem ); typedef int (__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem, const lzo_bytep dict, lzo_uint dict_len ); typedef int (__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem, const lzo_bytep dict, lzo_uint dict_len ); /* Callback interface. Currently only the progress indicator ("nprogress") * is used, but this may change in a future release. */ struct lzo_callback_t; typedef struct lzo_callback_t lzo_callback_t; #define lzo_callback_p lzo_callback_t __LZO_MMODEL * /* malloc & free function types */ typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) (lzo_callback_p self, lzo_uint items, lzo_uint size); typedef void (__LZO_CDECL *lzo_free_func_t) (lzo_callback_p self, lzo_voidp ptr); /* a progress indicator callback function */ typedef void (__LZO_CDECL *lzo_progress_func_t) (lzo_callback_p, lzo_uint, lzo_uint, int); struct lzo_callback_t { /* custom allocators (set to 0 to disable) */ lzo_alloc_func_t nalloc; /* [not used right now] */ lzo_free_func_t nfree; /* [not used right now] */ /* a progress indicator callback function (set to 0 to disable) */ lzo_progress_func_t nprogress; /* INFO: the first parameter "self" of the nalloc/nfree/nprogress * callbacks points back to this struct, so you are free to store * some extra info in the following variables. */ lzo_voidp user1; lzo_xint user2; lzo_xint user3; }; /*********************************************************************** // error codes and prototypes ************************************************************************/ /* Error codes for the compression/decompression functions. Negative * values are errors, positive values will be used for special but * normal events. */ #define LZO_E_OK 0 #define LZO_E_ERROR (-1) #define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */ #define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ #define LZO_E_INPUT_OVERRUN (-4) #define LZO_E_OUTPUT_OVERRUN (-5) #define LZO_E_LOOKBEHIND_OVERRUN (-6) #define LZO_E_EOF_NOT_FOUND (-7) #define LZO_E_INPUT_NOT_CONSUMED (-8) #define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ #define LZO_E_INVALID_ARGUMENT (-10) #define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */ #define LZO_E_OUTPUT_NOT_CONSUMED (-12) #define LZO_E_INTERNAL_ERROR (-99) #ifndef lzo_sizeof_dict_t # define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) #endif /* lzo_init() should be the first function you call. * Check the return code ! * * lzo_init() is a macro to allow checking that the library and the * compiler's view of various types are consistent. */ #define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ (int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ (int)sizeof(lzo_callback_t)) LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); /* version functions (useful for shared libraries) */ LZO_EXTERN(unsigned) lzo_version(void); LZO_EXTERN(const char *) lzo_version_string(void); LZO_EXTERN(const char *) lzo_version_date(void); LZO_EXTERN(const lzo_charp) _lzo_version_string(void); LZO_EXTERN(const lzo_charp) _lzo_version_date(void); /* string functions */ LZO_EXTERN(int) lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len); LZO_EXTERN(lzo_voidp) lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len); LZO_EXTERN(lzo_voidp) lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len); LZO_EXTERN(lzo_voidp) lzo_memset(lzo_voidp buf, int c, lzo_uint len); /* checksum functions */ LZO_EXTERN(lzo_uint32_t) lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); LZO_EXTERN(lzo_uint32_t) lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); LZO_EXTERN(const lzo_uint32_tp) lzo_get_crc32_table(void); /* misc. */ LZO_EXTERN(int) _lzo_config_check(void); typedef union { lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04; void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09; #if defined(lzo_int64_t) lzo_uint64_t a10; #endif } lzo_align_t; /* align a char pointer on a boundary that is a multiple of 'size' */ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); #define LZO_PTR_ALIGN_UP(p,size) \ ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size))) /*********************************************************************** // deprecated macros - only for backward compatibility ************************************************************************/ /* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */ #define lzo_byte unsigned char /* deprecated type names */ #define lzo_int32 lzo_int32_t #define lzo_uint32 lzo_uint32_t #define lzo_int32p lzo_int32_t __LZO_MMODEL * #define lzo_uint32p lzo_uint32_t __LZO_MMODEL * #define LZO_INT32_MAX LZO_INT32_C(2147483647) #define LZO_UINT32_MAX LZO_UINT32_C(4294967295) #if defined(lzo_int64_t) #define lzo_int64 lzo_int64_t #define lzo_uint64 lzo_uint64_t #define lzo_int64p lzo_int64_t __LZO_MMODEL * #define lzo_uint64p lzo_uint64_t __LZO_MMODEL * #define LZO_INT64_MAX LZO_INT64_C(9223372036854775807) #define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615) #endif /* deprecated types */ typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u; typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u; /* deprecated defines */ #if !defined(LZO_SIZEOF_LZO_UINT) # define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LZO_INT #endif #if defined(LZO_CFG_COMPAT) #define __LZOCONF_H 1 #if defined(LZO_ARCH_I086) # define __LZO_i386 1 #elif defined(LZO_ARCH_I386) # define __LZO_i386 1 #endif #if defined(LZO_OS_DOS16) # define __LZO_DOS 1 # define __LZO_DOS16 1 #elif defined(LZO_OS_DOS32) # define __LZO_DOS 1 #elif defined(LZO_OS_WIN16) # define __LZO_WIN 1 # define __LZO_WIN16 1 #elif defined(LZO_OS_WIN32) # define __LZO_WIN 1 #endif #define __LZO_CMODEL /*empty*/ #define __LZO_DMODEL /*empty*/ #define __LZO_ENTRY __LZO_CDECL #define LZO_EXTERN_CDECL LZO_EXTERN #define LZO_ALIGN LZO_PTR_ALIGN_UP #define lzo_compress_asm_t lzo_compress_t #define lzo_decompress_asm_t lzo_decompress_t #endif /* LZO_CFG_COMPAT */ #ifdef __cplusplus } /* extern "C" */ #endif #endif /* already included */ /* vim:set ts=4 sw=4 et: */ ntop-n2n-90215bd/include/lzodefs.h000066400000000000000000003717711422132035700167760ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* lzodefs.h -- architecture, OS and compiler specific defines This file is part of the LZO real-time data compression library. Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ #ifndef __LZODEFS_H_INCLUDED #define __LZODEFS_H_INCLUDED 1 #if defined(__CYGWIN32__) && !defined(__CYGWIN__) # define __CYGWIN__ __CYGWIN32__ #endif #if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) # define _ALL_SOURCE 1 #endif #if defined(__mips__) && defined(__R5900__) # if !defined(__LONG_MAX__) # define __LONG_MAX__ 9223372036854775807L # endif #endif #if 0 #elif !defined(__LZO_LANG_OVERRIDE) #if (defined(__clang__) || defined(__GNUC__)) && defined(__ASSEMBLER__) # if (__ASSEMBLER__+0) <= 0 # error "__ASSEMBLER__" # else # define LZO_LANG_ASSEMBLER 1 # endif #elif defined(__cplusplus) # if (__cplusplus+0) <= 0 # error "__cplusplus" # elif (__cplusplus < 199711L) # define LZO_LANG_CXX 1 # elif defined(_MSC_VER) && defined(_MSVC_LANG) && (_MSVC_LANG+0 >= 201402L) && 1 # define LZO_LANG_CXX _MSVC_LANG # else # define LZO_LANG_CXX __cplusplus # endif # define LZO_LANG_CPLUSPLUS LZO_LANG_CXX #else # if defined(__STDC_VERSION__) && (__STDC_VERSION__+0 >= 199409L) # define LZO_LANG_C __STDC_VERSION__ # else # define LZO_LANG_C 1 # endif #endif #endif #if !defined(LZO_CFG_NO_DISABLE_WUNDEF) #if defined(__ARMCC_VERSION) # pragma diag_suppress 193 #elif defined(__clang__) && defined(__clang_minor__) # pragma clang diagnostic ignored "-Wundef" #elif defined(__INTEL_COMPILER) # pragma warning(disable: 193) #elif defined(__KEIL__) && defined(__C166__) # pragma warning disable = 322 #elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) # if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) # pragma GCC diagnostic ignored "-Wundef" # endif #elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) # if ((_MSC_VER-0) >= 1300) # pragma warning(disable: 4668) # endif #endif #endif #if 0 && defined(__POCC__) && defined(_WIN32) # if (__POCC__ >= 400) # pragma warn(disable: 2216) # endif #endif #if 0 && defined(__WATCOMC__) # if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) # pragma warning 203 9 # endif #endif #if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) # pragma option -h #endif #if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) #ifndef _CRT_NONSTDC_NO_DEPRECATE #define _CRT_NONSTDC_NO_DEPRECATE 1 #endif #ifndef _CRT_NONSTDC_NO_WARNINGS #define _CRT_NONSTDC_NO_WARNINGS 1 #endif #ifndef _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE 1 #endif #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS 1 #endif #endif #if 0 #define LZO_0xffffUL 0xfffful #define LZO_0xffffffffUL 0xfffffffful #else #define LZO_0xffffUL 65535ul #define LZO_0xffffffffUL 4294967295ul #endif #define LZO_0xffffL LZO_0xffffUL #define LZO_0xffffffffL LZO_0xffffffffUL #if (LZO_0xffffL == LZO_0xffffffffL) # error "your preprocessor is broken 1" #endif #if (16ul * 16384ul != 262144ul) # error "your preprocessor is broken 2" #endif #if 0 #if (32767 >= 4294967295ul) # error "your preprocessor is broken 3" #endif #if (65535u >= 4294967295ul) # error "your preprocessor is broken 4" #endif #endif #if defined(__COUNTER__) # ifndef LZO_CFG_USE_COUNTER # define LZO_CFG_USE_COUNTER 1 # endif #else # undef LZO_CFG_USE_COUNTER #endif #if (UINT_MAX == LZO_0xffffL) #if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) # if !defined(MSDOS) # define MSDOS 1 # endif # if !defined(_MSDOS) # define _MSDOS 1 # endif #elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) # if (__VERSION == 520) && (MB_LEN_MAX == 1) # if !defined(__AZTEC_C__) # define __AZTEC_C__ __VERSION # endif # if !defined(__DOS__) # define __DOS__ 1 # endif # endif #endif #endif #if (UINT_MAX == LZO_0xffffL) #if defined(_MSC_VER) && defined(M_I86HM) # define ptrdiff_t long # define _PTRDIFF_T_DEFINED 1 #endif #endif #if (UINT_MAX == LZO_0xffffL) # undef __LZO_RENAME_A # undef __LZO_RENAME_B # if defined(__AZTEC_C__) && defined(__DOS__) # define __LZO_RENAME_A 1 # elif defined(_MSC_VER) && defined(MSDOS) # if (_MSC_VER < 600) # define __LZO_RENAME_A 1 # elif (_MSC_VER < 700) # define __LZO_RENAME_B 1 # endif # elif defined(__TSC__) && defined(__OS2__) # define __LZO_RENAME_A 1 # elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) # define __LZO_RENAME_A 1 # elif defined(__PACIFIC__) && defined(DOS) # if !defined(__far) # define __far far # endif # if !defined(__near) # define __near near # endif # endif # if defined(__LZO_RENAME_A) # if !defined(__cdecl) # define __cdecl cdecl # endif # if !defined(__far) # define __far far # endif # if !defined(__huge) # define __huge huge # endif # if !defined(__near) # define __near near # endif # if !defined(__pascal) # define __pascal pascal # endif # if !defined(__huge) # define __huge huge # endif # elif defined(__LZO_RENAME_B) # if !defined(__cdecl) # define __cdecl _cdecl # endif # if !defined(__far) # define __far _far # endif # if !defined(__huge) # define __huge _huge # endif # if !defined(__near) # define __near _near # endif # if !defined(__pascal) # define __pascal _pascal # endif # elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) # if !defined(__cdecl) # define __cdecl cdecl # endif # if !defined(__pascal) # define __pascal pascal # endif # endif # undef __LZO_RENAME_A # undef __LZO_RENAME_B #endif #if (UINT_MAX == LZO_0xffffL) #if defined(__AZTEC_C__) && defined(__DOS__) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 #elif defined(_MSC_VER) && defined(MSDOS) # if (_MSC_VER < 600) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 # endif # if (_MSC_VER < 700) # define LZO_BROKEN_INTEGRAL_PROMOTION 1 # define LZO_BROKEN_SIZEOF 1 # endif #elif defined(__PACIFIC__) && defined(DOS) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 #elif defined(__TURBOC__) && defined(__MSDOS__) # if (__TURBOC__ < 0x0150) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 # define LZO_BROKEN_INTEGRAL_PROMOTION 1 # endif # if (__TURBOC__ < 0x0200) # define LZO_BROKEN_SIZEOF 1 # endif # if (__TURBOC__ < 0x0400) && defined(__cplusplus) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # endif #elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # define LZO_BROKEN_SIZEOF 1 #endif #endif #if defined(__WATCOMC__) && (__WATCOMC__ < 900) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 #endif #if defined(_CRAY) && defined(_CRAY1) # define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 #endif #define LZO_PP_STRINGIZE(x) #x #define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) #define LZO_PP_CONCAT0() /*empty*/ #define LZO_PP_CONCAT1(a) a #define LZO_PP_CONCAT2(a,b) a ## b #define LZO_PP_CONCAT3(a,b,c) a ## b ## c #define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e #define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f #define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() #define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) #define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) #define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) #define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) #define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) #define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) #define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) #define LZO_PP_EMPTY /*empty*/ #define LZO_PP_EMPTY0() /*empty*/ #define LZO_PP_EMPTY1(a) /*empty*/ #define LZO_PP_EMPTY2(a,b) /*empty*/ #define LZO_PP_EMPTY3(a,b,c) /*empty*/ #define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ #define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ #define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ #define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ #if 1 #define LZO_CPP_STRINGIZE(x) #x #define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) #define LZO_CPP_CONCAT2(a,b) a ## b #define LZO_CPP_CONCAT3(a,b,c) a ## b ## c #define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e #define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f #define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) #define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) #define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) #define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) #define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) #define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) #endif #define __LZO_MASK_GEN(o,b) (((((o) << ((b)-((b)!=0))) - (o)) << 1) + (o)*((b)!=0)) #if 1 && defined(__cplusplus) # if !defined(__STDC_CONSTANT_MACROS) # define __STDC_CONSTANT_MACROS 1 # endif # if !defined(__STDC_LIMIT_MACROS) # define __STDC_LIMIT_MACROS 1 # endif #endif #if defined(__cplusplus) # define LZO_EXTERN_C extern "C" # define LZO_EXTERN_C_BEGIN extern "C" { # define LZO_EXTERN_C_END } #else # define LZO_EXTERN_C extern # define LZO_EXTERN_C_BEGIN /*empty*/ # define LZO_EXTERN_C_END /*empty*/ #endif #if !defined(__LZO_OS_OVERRIDE) #if (LZO_OS_FREESTANDING) # define LZO_INFO_OS "freestanding" #elif (LZO_OS_EMBEDDED) # define LZO_INFO_OS "embedded" #elif 1 && defined(__IAR_SYSTEMS_ICC__) # define LZO_OS_EMBEDDED 1 # define LZO_INFO_OS "embedded" #elif defined(__CYGWIN__) && defined(__GNUC__) # define LZO_OS_CYGWIN 1 # define LZO_INFO_OS "cygwin" #elif defined(__EMX__) && defined(__GNUC__) # define LZO_OS_EMX 1 # define LZO_INFO_OS "emx" #elif defined(__BEOS__) # define LZO_OS_BEOS 1 # define LZO_INFO_OS "beos" #elif defined(__Lynx__) # define LZO_OS_LYNXOS 1 # define LZO_INFO_OS "lynxos" #elif defined(__OS400__) # define LZO_OS_OS400 1 # define LZO_INFO_OS "os400" #elif defined(__QNX__) # define LZO_OS_QNX 1 # define LZO_INFO_OS "qnx" #elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" #elif defined(__BORLANDC__) && defined(__DPMI16__) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" #elif defined(__ZTC__) && defined(DOS386) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" #elif defined(__OS2__) || defined(__OS2V2__) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_OS216 1 # define LZO_INFO_OS "os216" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_OS2 1 # define LZO_INFO_OS "os2" # else # error "check your limits.h header" # endif #elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) # define LZO_OS_WIN64 1 # define LZO_INFO_OS "win64" #elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" #elif defined(__MWERKS__) && defined(__INTEL__) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" #elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_WIN16 1 # define LZO_INFO_OS "win16" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" # else # error "check your limits.h header" # endif #elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" # else # error "check your limits.h header" # endif #elif defined(__WATCOMC__) # if defined(__NT__) && (UINT_MAX == LZO_0xffffL) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" # elif defined(__NT__) && (__WATCOMC__ < 1100) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" # elif defined(__linux__) || defined(__LINUX__) # define LZO_OS_POSIX 1 # define LZO_INFO_OS "posix" # else # error "please specify a target using the -bt compiler option" # endif #elif defined(__palmos__) # define LZO_OS_PALMOS 1 # define LZO_INFO_OS "palmos" #elif defined(__TOS__) || defined(__atarist__) # define LZO_OS_TOS 1 # define LZO_INFO_OS "tos" #elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__) # define LZO_OS_MACCLASSIC 1 # define LZO_INFO_OS "macclassic" #elif defined(__VMS) # define LZO_OS_VMS 1 # define LZO_INFO_OS "vms" #elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PS2 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "ps2" #elif defined(__mips__) && defined(__psp__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PSP 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "psp" #else # define LZO_OS_POSIX 1 # define LZO_INFO_OS "posix" #endif #if (LZO_OS_POSIX) # if defined(_AIX) || defined(__AIX__) || defined(__aix__) # define LZO_OS_POSIX_AIX 1 # define LZO_INFO_OS_POSIX "aix" # elif defined(__FreeBSD__) # define LZO_OS_POSIX_FREEBSD 1 # define LZO_INFO_OS_POSIX "freebsd" # elif defined(__hpux__) || defined(__hpux) # define LZO_OS_POSIX_HPUX 1 # define LZO_INFO_OS_POSIX "hpux" # elif defined(__INTERIX) # define LZO_OS_POSIX_INTERIX 1 # define LZO_INFO_OS_POSIX "interix" # elif defined(__IRIX__) || defined(__irix__) # define LZO_OS_POSIX_IRIX 1 # define LZO_INFO_OS_POSIX "irix" # elif defined(__linux__) || defined(__linux) || defined(__LINUX__) # define LZO_OS_POSIX_LINUX 1 # define LZO_INFO_OS_POSIX "linux" # elif defined(__APPLE__) && defined(__MACH__) # if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) # define LZO_OS_POSIX_DARWIN 1040 # define LZO_INFO_OS_POSIX "darwin_iphone" # elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) # define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ # define LZO_INFO_OS_POSIX "darwin" # else # define LZO_OS_POSIX_DARWIN 1 # define LZO_INFO_OS_POSIX "darwin" # endif # define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN # elif defined(__minix__) || defined(__minix) # define LZO_OS_POSIX_MINIX 1 # define LZO_INFO_OS_POSIX "minix" # elif defined(__NetBSD__) # define LZO_OS_POSIX_NETBSD 1 # define LZO_INFO_OS_POSIX "netbsd" # elif defined(__OpenBSD__) # define LZO_OS_POSIX_OPENBSD 1 # define LZO_INFO_OS_POSIX "openbsd" # elif defined(__osf__) # define LZO_OS_POSIX_OSF 1 # define LZO_INFO_OS_POSIX "osf" # elif defined(__solaris__) || defined(__sun) # if defined(__SVR4) || defined(__svr4__) # define LZO_OS_POSIX_SOLARIS 1 # define LZO_INFO_OS_POSIX "solaris" # else # define LZO_OS_POSIX_SUNOS 1 # define LZO_INFO_OS_POSIX "sunos" # endif # elif defined(__ultrix__) || defined(__ultrix) # define LZO_OS_POSIX_ULTRIX 1 # define LZO_INFO_OS_POSIX "ultrix" # elif defined(_UNICOS) # define LZO_OS_POSIX_UNICOS 1 # define LZO_INFO_OS_POSIX "unicos" # else # define LZO_OS_POSIX_UNKNOWN 1 # define LZO_INFO_OS_POSIX "unknown" # endif #endif #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (UINT_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) # define LZO_CC_CILLY 1 # define LZO_INFO_CC "Cilly" # if defined(__CILLY__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) # else # define LZO_INFO_CCVER "unknown" # endif #elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) # define LZO_CC_SDCC 1 # define LZO_INFO_CC "sdcc" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) #elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) # define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) # define LZO_INFO_CC "Pathscale C" # define LZO_INFO_CCVER __PATHSCALE__ # if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) # define LZO_CC_INTELC __INTEL_COMPILER # define LZO_INFO_CC "Intel C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_INTELC_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__POCC__) && defined(_WIN32) # define LZO_CC_PELLESC 1 # define LZO_INFO_CC "Pelles C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) #elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) # define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else # define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_ARMCC __ARMCC_VERSION # define LZO_INFO_CC "ARM C Compiler" # define LZO_INFO_CCVER __VERSION__ #elif defined(__clang__) && defined(__c2__) && defined(__c2_version__) && defined(_MSC_VER) # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # define LZO_CC_CLANG_C2 _MSC_VER # define LZO_CC_CLANG_VENDOR_MICROSOFT 1 # define LZO_INFO_CC "clang/c2" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__c2_version__) #elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) # if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # else # define LZO_CC_CLANG 0x010000L # endif # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_CLANG_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif # if defined(__APPLE_CC__) # define LZO_CC_CLANG_VENDOR_APPLE 1 # define LZO_INFO_CC "clang/apple" # else # define LZO_CC_CLANG_VENDOR_LLVM 1 # define LZO_INFO_CC "clang" # endif # if defined(__clang_version__) # define LZO_INFO_CCVER __clang_version__ # else # define LZO_INFO_CCVER __VERSION__ # endif #elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_LLVM LZO_CC_LLVM_GNUC # define LZO_INFO_CC "llvm-gcc" # define LZO_INFO_CCVER __VERSION__ #elif defined(__ACK__) && defined(_ACK) # define LZO_CC_ACK 1 # define LZO_INFO_CC "Amsterdam Compiler Kit C" # define LZO_INFO_CCVER "unknown" #elif defined(__ARMCC_VERSION) && !defined(__GNUC__) # define LZO_CC_ARMCC __ARMCC_VERSION # define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION # define LZO_INFO_CC "ARM C Compiler" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) #elif defined(__AZTEC_C__) # define LZO_CC_AZTECC 1 # define LZO_INFO_CC "Aztec C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) #elif defined(__CODEGEARC__) # define LZO_CC_CODEGEARC 1 # define LZO_INFO_CC "CodeGear C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) #elif defined(__BORLANDC__) # define LZO_CC_BORLANDC 1 # define LZO_INFO_CC "Borland C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) #elif defined(_CRAYC) && defined(_RELEASE) # define LZO_CC_CRAYC 1 # define LZO_INFO_CC "Cray C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) #elif defined(__DMC__) && defined(__SC__) # define LZO_CC_DMC 1 # define LZO_INFO_CC "Digital Mars C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) #elif defined(__DECC) # define LZO_CC_DECC 1 # define LZO_INFO_CC "DEC C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) #elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) # define LZO_CC_GHS 1 # define LZO_INFO_CC "Green Hills C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_GHS_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__HIGHC__) # define LZO_CC_HIGHC 1 # define LZO_INFO_CC "MetaWare High C" # define LZO_INFO_CCVER "unknown" #elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) # define LZO_CC_HPACC __HP_aCC # define LZO_INFO_CC "HP aCC" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) #elif defined(__IAR_SYSTEMS_ICC__) # define LZO_CC_IARC 1 # define LZO_INFO_CC "IAR C" # if defined(__VER__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) # else # define LZO_INFO_CCVER "unknown" # endif #elif defined(__IBMC__) && ((__IBMC__-0) > 0) # define LZO_CC_IBMC __IBMC__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) #elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) # define LZO_CC_IBMC __IBMCPP__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) #elif defined(__KEIL__) && defined(__C166__) # define LZO_CC_KEILC 1 # define LZO_INFO_CC "Keil C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) #elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) # define LZO_CC_LCCWIN32 1 # define LZO_INFO_CC "lcc-win32" # define LZO_INFO_CCVER "unknown" #elif defined(__LCC__) # define LZO_CC_LCC 1 # define LZO_INFO_CC "lcc" # if defined(__LCC_VERSION__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) # else # define LZO_INFO_CCVER "unknown" # endif #elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) # define LZO_CC_MWERKS __MWERKS__ # define LZO_INFO_CC "Metrowerks C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) #elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) # define LZO_CC_NDPC 1 # define LZO_INFO_CC "Microway NDP C" # define LZO_INFO_CCVER "unknown" #elif defined(__PACIFIC__) # define LZO_CC_PACIFICC 1 # define LZO_INFO_CC "Pacific C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) #elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) # if defined(__PGIC_PATCHLEVEL__) # define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) # else # define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" # endif # define LZO_INFO_CC "Portland Group PGI C" #elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) # define LZO_CC_PGI 1 # define LZO_INFO_CC "Portland Group PGI C" # define LZO_INFO_CCVER "unknown" #elif defined(__PUREC__) && defined(__TOS__) # define LZO_CC_PUREC 1 # define LZO_INFO_CC "Pure C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) #elif defined(__SC__) && defined(__ZTC__) # define LZO_CC_SYMANTECC 1 # define LZO_INFO_CC "Symantec C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) #elif defined(__SUNPRO_C) # define LZO_INFO_CC "SunPro C" # if ((__SUNPRO_C-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_C # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) # else # define LZO_CC_SUNPROC 1 # define LZO_INFO_CCVER "unknown" # endif #elif defined(__SUNPRO_CC) # define LZO_INFO_CC "SunPro C" # if ((__SUNPRO_CC-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_CC # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) # else # define LZO_CC_SUNPROC 1 # define LZO_INFO_CCVER "unknown" # endif #elif defined(__TINYC__) # define LZO_CC_TINYC 1 # define LZO_INFO_CC "Tiny C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) #elif defined(__TSC__) # define LZO_CC_TOPSPEEDC 1 # define LZO_INFO_CC "TopSpeed C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) #elif defined(__WATCOMC__) # define LZO_CC_WATCOMC 1 # define LZO_INFO_CC "Watcom C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) #elif defined(__TURBOC__) # define LZO_CC_TURBOC 1 # define LZO_INFO_CC "Turbo C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) #elif defined(__ZTC__) # define LZO_CC_ZORTECHC 1 # define LZO_INFO_CC "Zortech C" # if ((__ZTC__-0) == 0x310) # define LZO_INFO_CCVER "0x310" # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) # endif #elif defined(__GNUC__) && defined(__VERSION__) # if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) # define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # elif defined(__GNUC_MINOR__) # define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # else # define LZO_CC_GNUC (__GNUC__ * 0x10000L) # endif # define LZO_INFO_CC "gcc" # define LZO_INFO_CCVER __VERSION__ #elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_MSC _MSC_VER # define LZO_INFO_CC "Microsoft C" # if defined(_MSC_FULL_VER) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) # endif #else # define LZO_CC_UNKNOWN 1 # define LZO_INFO_CC "unknown" # define LZO_INFO_CCVER "unknown" #endif #if (LZO_CC_GNUC) && defined(__OPEN64__) # if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) # define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) # define LZO_CC_OPEN64_GNUC LZO_CC_GNUC # endif #endif #if (LZO_CC_GNUC) && defined(__PCC__) # if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) # define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) # define LZO_CC_PCC_GNUC LZO_CC_GNUC # endif #endif #if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) # error "LZO_CC_MSC: _MSC_FULL_VER is not defined" #endif #if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) # if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) # if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) # define LZO_ARCH_CRAY_MPP 1 # elif defined(_CRAY1) # define LZO_ARCH_CRAY_PVP 1 # endif # endif #endif #if !defined(__LZO_ARCH_OVERRIDE) #if (LZO_ARCH_GENERIC) # define LZO_INFO_ARCH "generic" #elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086 1 # define LZO_INFO_ARCH "i086" #elif defined(__aarch64__) || defined(_M_ARM64) # define LZO_ARCH_ARM64 1 # define LZO_INFO_ARCH "arm64" #elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" #elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" #elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) # define LZO_ARCH_AMD64 1 # define LZO_INFO_ARCH "amd64" #elif defined(__arm__) || defined(_M_ARM) # define LZO_ARCH_ARM 1 # define LZO_INFO_ARCH "arm" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) # define LZO_ARCH_ARM 1 # define LZO_INFO_ARCH "arm" #elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) # define LZO_ARCH_AVR 1 # define LZO_INFO_ARCH "avr" #elif defined(__avr32__) || defined(__AVR32__) # define LZO_ARCH_AVR32 1 # define LZO_INFO_ARCH "avr32" #elif defined(__bfin__) # define LZO_ARCH_BLACKFIN 1 # define LZO_INFO_ARCH "blackfin" #elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) # define LZO_ARCH_C166 1 # define LZO_INFO_ARCH "c166" #elif defined(__cris__) # define LZO_ARCH_CRIS 1 # define LZO_INFO_ARCH "cris" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) # define LZO_ARCH_EZ80 1 # define LZO_INFO_ARCH "ez80" #elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) # define LZO_ARCH_H8300 1 # define LZO_INFO_ARCH "h8300" #elif defined(__hppa__) || defined(__hppa) # define LZO_ARCH_HPPA 1 # define LZO_INFO_ARCH "hppa" #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif (LZO_CC_ZORTECHC && defined(__I86__)) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) # define LZO_ARCH_IA64 1 # define LZO_INFO_ARCH "ia64" #elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) # define LZO_ARCH_M16C 1 # define LZO_INFO_ARCH "m16c" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) # define LZO_ARCH_M16C 1 # define LZO_INFO_ARCH "m16c" #elif defined(__m32r__) # define LZO_ARCH_M32R 1 # define LZO_INFO_ARCH "m32r" #elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) # define LZO_ARCH_M68K 1 # define LZO_INFO_ARCH "m68k" #elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) # define LZO_ARCH_MCS251 1 # define LZO_INFO_ARCH "mcs251" #elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) # define LZO_ARCH_MCS51 1 # define LZO_INFO_ARCH "mcs51" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) # define LZO_ARCH_MCS51 1 # define LZO_INFO_ARCH "mcs51" #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) # define LZO_ARCH_MIPS 1 # define LZO_INFO_ARCH "mips" #elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) # define LZO_ARCH_MSP430 1 # define LZO_INFO_ARCH "msp430" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) # define LZO_ARCH_MSP430 1 # define LZO_INFO_ARCH "msp430" #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__powerpc64__) || defined(__powerpc64) || defined(__ppc64__) || defined(__PPC64__) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__powerpc64le__) || defined(__powerpc64le) || defined(__ppc64le__) || defined(__PPC64LE__) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__riscv) # define LZO_ARCH_RISCV 1 # define LZO_INFO_ARCH "riscv" #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) # define LZO_ARCH_S390 1 # define LZO_INFO_ARCH "s390" #elif defined(__sh__) || defined(_M_SH) # define LZO_ARCH_SH 1 # define LZO_INFO_ARCH "sh" #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) # define LZO_ARCH_SPARC 1 # define LZO_INFO_ARCH "sparc" #elif defined(__SPU__) # define LZO_ARCH_SPU 1 # define LZO_INFO_ARCH "spu" #elif (UINT_MAX == LZO_0xffffL) && defined(__z80) # define LZO_ARCH_Z80 1 # define LZO_INFO_ARCH "z80" #elif (LZO_ARCH_CRAY_PVP) # if defined(_CRAYSV1) # define LZO_ARCH_CRAY_SV1 1 # define LZO_INFO_ARCH "cray_sv1" # elif (_ADDR64) # define LZO_ARCH_CRAY_T90 1 # define LZO_INFO_ARCH "cray_t90" # elif (_ADDR32) # define LZO_ARCH_CRAY_YMP 1 # define LZO_INFO_ARCH "cray_ymp" # else # define LZO_ARCH_CRAY_XMP 1 # define LZO_INFO_ARCH "cray_xmp" # endif #else # define LZO_ARCH_UNKNOWN 1 # define LZO_INFO_ARCH "unknown" #endif #endif #if !defined(LZO_ARCH_ARM_THUMB2) #if (LZO_ARCH_ARM) # if defined(__thumb__) || defined(__thumb) || defined(_M_THUMB) # if defined(__thumb2__) # define LZO_ARCH_ARM_THUMB2 1 # elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4) # define LZO_ARCH_ARM_THUMB2 1 # elif 1 && defined(_MSC_VER) && defined(_M_THUMB) && ((_M_THUMB)+0 >= 7) # define LZO_ARCH_ARM_THUMB2 1 # endif # endif #endif #endif #if (LZO_ARCH_ARM_THUMB2) # undef LZO_INFO_ARCH # define LZO_INFO_ARCH "arm_thumb2" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) # error "FIXME - missing define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) # error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) # error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" #endif #if (LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && defined(BLX286)) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) # define LZO_ARCH_I086PM 1 #endif #if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) # define LZO_ARCH_X64 1 #elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_AMD64 1 #endif #if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) # define LZO_ARCH_AARCH64 1 #elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_ARM64 1 #endif #if (LZO_ARCH_I386 && !LZO_ARCH_X86) # define LZO_ARCH_X86 1 #elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_I386 1 #endif #if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086PM && !LZO_ARCH_I086) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086) # if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_I386) # if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) # error "unexpected configuration - check your compiler defines" # endif # if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_AMD64 || LZO_ARCH_I386) # if !defined(LZO_TARGET_FEATURE_SSE2) # if defined(__SSE2__) # define LZO_TARGET_FEATURE_SSE2 1 # elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) # define LZO_TARGET_FEATURE_SSE2 1 # elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64) # define LZO_TARGET_FEATURE_SSE2 1 # endif # endif # if !defined(LZO_TARGET_FEATURE_SSSE3) # if (LZO_TARGET_FEATURE_SSE2) # if defined(__SSSE3__) # define LZO_TARGET_FEATURE_SSSE3 1 # elif defined(_MSC_VER) && defined(__AVX__) # define LZO_TARGET_FEATURE_SSSE3 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_SSE4_2) # if (LZO_TARGET_FEATURE_SSSE3) # if defined(__SSE4_2__) # define LZO_TARGET_FEATURE_SSE4_2 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_AVX) # if (LZO_TARGET_FEATURE_SSSE3) # if defined(__AVX__) # define LZO_TARGET_FEATURE_AVX 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_AVX2) # if (LZO_TARGET_FEATURE_AVX) # if defined(__AVX2__) # define LZO_TARGET_FEATURE_AVX2 1 # endif # endif # endif #endif #if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM) # if !defined(LZO_TARGET_FEATURE_NEON) # if defined(__ARM_NEON) && ((__ARM_NEON)+0) # define LZO_TARGET_FEATURE_NEON 1 # elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0) # define LZO_TARGET_FEATURE_NEON 1 # elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0) # define LZO_TARGET_FEATURE_NEON 1 # endif # endif #elif (LZO_ARCH_ARM64) # if !defined(LZO_TARGET_FEATURE_NEON) # if 1 # define LZO_TARGET_FEATURE_NEON 1 # endif # endif #endif #if 0 #elif !defined(__LZO_MM_OVERRIDE) #if (LZO_ARCH_I086) #if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" #endif #if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) # define LZO_MM_TINY 1 #elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) # define LZO_MM_HUGE 1 #elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) # define LZO_MM_SMALL 1 #elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) # define LZO_MM_MEDIUM 1 #elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) # define LZO_MM_COMPACT 1 #elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) # define LZO_MM_LARGE 1 #elif (LZO_CC_AZTECC) # if defined(_LARGE_CODE) && defined(_LARGE_DATA) # define LZO_MM_LARGE 1 # elif defined(_LARGE_CODE) # define LZO_MM_MEDIUM 1 # elif defined(_LARGE_DATA) # define LZO_MM_COMPACT 1 # else # define LZO_MM_SMALL 1 # endif #elif (LZO_CC_ZORTECHC && defined(__VCM__)) # define LZO_MM_LARGE 1 #else # error "unknown LZO_ARCH_I086 memory model" #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) #define LZO_HAVE_MM_HUGE_PTR 1 #define LZO_HAVE_MM_HUGE_ARRAY 1 #if (LZO_MM_TINY) # undef LZO_HAVE_MM_HUGE_ARRAY #endif #if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) # undef LZO_HAVE_MM_HUGE_PTR # undef LZO_HAVE_MM_HUGE_ARRAY #elif (LZO_CC_DMC || LZO_CC_SYMANTECC) # undef LZO_HAVE_MM_HUGE_ARRAY #elif (LZO_CC_MSC && defined(_QC)) # undef LZO_HAVE_MM_HUGE_ARRAY # if (_MSC_VER < 600) # undef LZO_HAVE_MM_HUGE_PTR # endif #elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) # undef LZO_HAVE_MM_HUGE_ARRAY #endif #if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) # if (LZO_OS_DOS16) # error "unexpected configuration - check your compiler defines" # elif (LZO_CC_ZORTECHC) # else # error "unexpected configuration - check your compiler defines" # endif #endif #if defined(__cplusplus) extern "C" { #endif #if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) # define LZO_MM_AHSHIFT 12 #elif (LZO_CC_WATCOMC) extern unsigned char _HShift; # define LZO_MM_AHSHIFT ((unsigned) _HShift) #else # error "FIXME - implement LZO_MM_AHSHIFT" #endif #if defined(__cplusplus) } #endif #endif #elif (LZO_ARCH_C166) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_C166 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_C166 __MODEL__" #endif #elif (LZO_ARCH_MCS251) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_MCS251 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_MCS251 __MODEL__" #endif #elif (LZO_ARCH_MCS51) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_MCS51 __MODEL__" #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_MCS51 __MODEL__" #endif #elif (LZO_ARCH_CRAY_PVP) # define LZO_MM_PVP 1 #else # define LZO_MM_FLAT 1 #endif #if (LZO_MM_COMPACT) # define LZO_INFO_MM "compact" #elif (LZO_MM_FLAT) # define LZO_INFO_MM "flat" #elif (LZO_MM_HUGE) # define LZO_INFO_MM "huge" #elif (LZO_MM_LARGE) # define LZO_INFO_MM "large" #elif (LZO_MM_MEDIUM) # define LZO_INFO_MM "medium" #elif (LZO_MM_PVP) # define LZO_INFO_MM "pvp" #elif (LZO_MM_SMALL) # define LZO_INFO_MM "small" #elif (LZO_MM_TINY) # define LZO_INFO_MM "tiny" #else # error "unknown memory model" #endif #endif #if !defined(__lzo_gnuc_extension__) #if (LZO_CC_GNUC >= 0x020800ul) # define __lzo_gnuc_extension__ __extension__ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_gnuc_extension__ __extension__ #elif (LZO_CC_IBMC >= 600) # define __lzo_gnuc_extension__ __extension__ #endif #endif #if !defined(__lzo_gnuc_extension__) # define __lzo_gnuc_extension__ /*empty*/ #endif #if !defined(lzo_has_builtin) #if (LZO_CC_CLANG) && defined(__has_builtin) # define lzo_has_builtin __has_builtin #endif #endif #if !defined(lzo_has_builtin) # define lzo_has_builtin(x) 0 #endif #if !defined(lzo_has_attribute) #if (LZO_CC_CLANG) && defined(__has_attribute) # define lzo_has_attribute __has_attribute #endif #endif #if !defined(lzo_has_attribute) # define lzo_has_attribute(x) 0 #endif #if !defined(lzo_has_declspec_attribute) #if (LZO_CC_CLANG) && defined(__has_declspec_attribute) # define lzo_has_declspec_attribute __has_declspec_attribute #endif #endif #if !defined(lzo_has_declspec_attribute) # define lzo_has_declspec_attribute(x) 0 #endif #if !defined(lzo_has_feature) #if (LZO_CC_CLANG) && defined(__has_feature) # define lzo_has_feature __has_feature #endif #endif #if !defined(lzo_has_feature) # define lzo_has_feature(x) 0 #endif #if !defined(lzo_has_extension) #if (LZO_CC_CLANG) && defined(__has_extension) # define lzo_has_extension __has_extension #elif (LZO_CC_CLANG) && defined(__has_feature) # define lzo_has_extension __has_feature #endif #endif #if !defined(lzo_has_extension) # define lzo_has_extension(x) 0 #endif #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 # elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 # else # define LZO_CFG_USE_NEW_STYLE_CASTS 1 # endif #endif #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 #endif #if !defined(__cplusplus) # if defined(LZO_CFG_USE_NEW_STYLE_CASTS) # undef LZO_CFG_USE_NEW_STYLE_CASTS # endif # define LZO_CFG_USE_NEW_STYLE_CASTS 0 #endif #if !defined(LZO_REINTERPRET_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast (e)) # endif #endif #if !defined(LZO_REINTERPRET_CAST) # define LZO_REINTERPRET_CAST(t,e) ((t) (e)) #endif #if !defined(LZO_STATIC_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_STATIC_CAST(t,e) (static_cast (e)) # endif #endif #if !defined(LZO_STATIC_CAST) # define LZO_STATIC_CAST(t,e) ((t) (e)) #endif #if !defined(LZO_STATIC_CAST2) # define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) #endif #if !defined(LZO_UNCONST_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNCONST_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNCONST_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) # endif #endif #if !defined(LZO_UNCONST_CAST) # define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) #endif #if !defined(LZO_UNCONST_VOLATILE_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) # endif #endif #if !defined(LZO_UNCONST_VOLATILE_CAST) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) #endif #if !defined(LZO_UNVOLATILE_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNVOLATILE_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) # endif #endif #if !defined(LZO_UNVOLATILE_CAST) # define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) #endif #if !defined(LZO_UNVOLATILE_CONST_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) # endif #endif #if !defined(LZO_UNVOLATILE_CONST_CAST) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) #endif #if !defined(LZO_PCAST) # if (LZO_HAVE_MM_HUGE_PTR) # define LZO_PCAST(t,e) ((t) (e)) # endif #endif #if !defined(LZO_PCAST) # define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) #endif #if !defined(LZO_CCAST) # if (LZO_HAVE_MM_HUGE_PTR) # define LZO_CCAST(t,e) ((t) (e)) # endif #endif #if !defined(LZO_CCAST) # define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) #endif #if !defined(LZO_ICONV) # define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(LZO_ICAST) # define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(LZO_ITRUNC) # define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(__lzo_cte) # if (LZO_CC_MSC || LZO_CC_WATCOMC) # define __lzo_cte(e) ((void)0,(e)) # elif 1 # define __lzo_cte(e) ((void)0,(e)) # endif #endif #if !defined(__lzo_cte) # define __lzo_cte(e) (e) #endif #if !defined(LZO_BLOCK_BEGIN) # define LZO_BLOCK_BEGIN do { # define LZO_BLOCK_END } while __lzo_cte(0) #endif #if !defined(LZO_UNUSED) # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) # define LZO_UNUSED(var) ((void) &var) # elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) # define LZO_UNUSED(var) if (&var) ; else # elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) # define LZO_UNUSED(var) ((void) &var) # elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNUSED(var) ((void) var) # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_UNUSED(var) if (&var) ; else # elif (LZO_CC_KEILC) # define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;} # elif (LZO_CC_PACIFICC) # define LZO_UNUSED(var) ((void) sizeof(var)) # elif (LZO_CC_WATCOMC) && defined(__cplusplus) # define LZO_UNUSED(var) ((void) var) # else # define LZO_UNUSED(var) ((void) &var) # endif #endif #if !defined(LZO_UNUSED_RESULT) # define LZO_UNUSED_RESULT(var) LZO_UNUSED(var) #endif #if !defined(LZO_UNUSED_FUNC) # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) # define LZO_UNUSED_FUNC(func) ((void) func) # elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) # define LZO_UNUSED_FUNC(func) if (func) ; else # elif (LZO_CC_CLANG || LZO_CC_LLVM) # define LZO_UNUSED_FUNC(func) ((void) &func) # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_UNUSED_FUNC(func) if (func) ; else # elif (LZO_CC_MSC) # define LZO_UNUSED_FUNC(func) ((void) &func) # elif (LZO_CC_KEILC || LZO_CC_PELLESC) # define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;} # else # define LZO_UNUSED_FUNC(func) ((void) func) # endif #endif #if !defined(LZO_UNUSED_LABEL) # if (LZO_CC_CLANG >= 0x020800ul) # define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) # elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) # define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l # else # define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l # endif #endif #if !defined(LZO_DEFINE_UNINITIALIZED_VAR) # if 0 # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var # elif 0 && (LZO_CC_GNUC) # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var # else # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init # endif #endif #if !defined(__lzo_inline) #if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) #elif defined(__cplusplus) # define __lzo_inline inline #elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) # define __lzo_inline inline #elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) # define __lzo_inline __inline #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define __lzo_inline __inline__ #elif (LZO_CC_DMC) # define __lzo_inline __inline #elif (LZO_CC_GHS) # define __lzo_inline __inline__ #elif (LZO_CC_IBMC >= 600) # define __lzo_inline __inline__ #elif (LZO_CC_INTELC) # define __lzo_inline __inline #elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) # define __lzo_inline __inline #elif (LZO_CC_MSC && (_MSC_VER >= 900)) # define __lzo_inline __inline #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_inline __inline__ #endif #endif #if defined(__lzo_inline) # ifndef __lzo_HAVE_inline # define __lzo_HAVE_inline 1 # endif #else # define __lzo_inline /*empty*/ #endif #if !defined(__lzo_forceinline) #if (LZO_CC_GNUC >= 0x030200ul) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) # define __lzo_forceinline __forceinline #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) # define __lzo_forceinline __forceinline #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #endif #endif #if defined(__lzo_forceinline) # ifndef __lzo_HAVE_forceinline # define __lzo_HAVE_forceinline 1 # endif #else # define __lzo_forceinline __lzo_inline #endif #if !defined(__lzo_noinline) #if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) # define __lzo_noinline __attribute__((__noinline__,__used__)) #elif (LZO_CC_GNUC >= 0x030200ul) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) # define __lzo_noinline __declspec(noinline) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_noinline __declspec(noinline) #elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) # if defined(__cplusplus) # else # define __lzo_noinline __declspec(noinline) # endif #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_noinline __attribute__((__noinline__)) #endif #endif #if defined(__lzo_noinline) # ifndef __lzo_HAVE_noinline # define __lzo_HAVE_noinline 1 # endif #else # define __lzo_noinline /*empty*/ #endif #if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) # error "unexpected configuration - check your compiler defines" #endif #if !defined(__lzo_static_inline) #if (LZO_CC_IBMC) # define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline #endif #endif #if !defined(__lzo_static_inline) # define __lzo_static_inline static __lzo_inline #endif #if !defined(__lzo_static_forceinline) #if (LZO_CC_IBMC) # define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline #endif #endif #if !defined(__lzo_static_forceinline) # define __lzo_static_forceinline static __lzo_forceinline #endif #if !defined(__lzo_static_noinline) #if (LZO_CC_IBMC) # define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline #endif #endif #if !defined(__lzo_static_noinline) # define __lzo_static_noinline static __lzo_noinline #endif #if !defined(__lzo_c99_extern_inline) #if defined(__GNUC_GNU_INLINE__) # define __lzo_c99_extern_inline __lzo_inline #elif defined(__GNUC_STDC_INLINE__) # define __lzo_c99_extern_inline extern __lzo_inline #elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) # define __lzo_c99_extern_inline extern __lzo_inline #endif #if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) # define __lzo_c99_extern_inline __lzo_inline #endif #endif #if defined(__lzo_c99_extern_inline) # ifndef __lzo_HAVE_c99_extern_inline # define __lzo_HAVE_c99_extern_inline 1 # endif #else # define __lzo_c99_extern_inline /*empty*/ #endif #if !defined(__lzo_may_alias) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_CLANG >= 0x020900ul) # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 # define __lzo_may_alias __attribute__((__may_alias__)) #endif #endif #if defined(__lzo_may_alias) # ifndef __lzo_HAVE_may_alias # define __lzo_HAVE_may_alias 1 # endif #else # define __lzo_may_alias /*empty*/ #endif #if !defined(__lzo_noreturn) #if (LZO_CC_GNUC >= 0x020700ul) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) # define __lzo_noreturn __declspec(noreturn) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) # define __lzo_noreturn __declspec(noreturn) #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_noreturn __attribute__((__noreturn__)) #endif #endif #if defined(__lzo_noreturn) # ifndef __lzo_HAVE_noreturn # define __lzo_HAVE_noreturn 1 # endif #else # define __lzo_noreturn /*empty*/ #endif #if !defined(__lzo_nothrow) #if (LZO_CC_GNUC >= 0x030300ul) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) # define __lzo_nothrow __declspec(nothrow) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) # define __lzo_nothrow __declspec(nothrow) #endif #endif #if defined(__lzo_nothrow) # ifndef __lzo_HAVE_nothrow # define __lzo_HAVE_nothrow 1 # endif #else # define __lzo_nothrow /*empty*/ #endif #if !defined(__lzo_restrict) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_restrict __restrict__ #elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) # define __lzo_restrict __restrict__ #elif (LZO_CC_IBMC >= 1210) # define __lzo_restrict __restrict__ #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) # define __lzo_restrict __restrict__ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) # define __lzo_restrict __restrict__ #elif (LZO_CC_MSC && (_MSC_VER >= 1400)) # define __lzo_restrict __restrict #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_restrict __restrict__ #endif #endif #if defined(__lzo_restrict) # ifndef __lzo_HAVE_restrict # define __lzo_HAVE_restrict 1 # endif #else # define __lzo_restrict /*empty*/ #endif #if !defined(__lzo_alignof) #if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_GHS) && !defined(__cplusplus) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_IBMC >= 600) # define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_alignof(e) __alignof(e) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_alignof(e) __alignof__(e) #endif #endif #if defined(__lzo_alignof) # ifndef __lzo_HAVE_alignof # define __lzo_HAVE_alignof 1 # endif #endif #if !defined(__lzo_struct_packed) #if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) #elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) #elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) # define __lzo_struct_packed(s) struct s { # define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_struct_packed(s) struct s { # define __lzo_struct_packed_end() } __attribute__((__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_IBMC >= 700) # define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { # define __lzo_struct_packed_end() } __attribute__((__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { # define __lzo_struct_packed_end() } __pragma(pack(pop)); #elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) # define __lzo_struct_packed(s) _Packed struct s { # define __lzo_struct_packed_end() }; #endif #endif #if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) # define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) #endif #if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) # define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() #endif #if !defined(__lzo_byte_struct) #if defined(__lzo_struct_packed) # define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() # define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() #elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); # define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); #endif #endif #if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) # define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) #endif #if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) #if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) #elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_CILLY || LZO_CC_PCC) #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_struct_align16(s) struct __declspec(align(16)) s { # define __lzo_struct_align16_end() }; # define __lzo_struct_align32(s) struct __declspec(align(32)) s { # define __lzo_struct_align32_end() }; # define __lzo_struct_align64(s) struct __declspec(align(64)) s { # define __lzo_struct_align64_end() }; #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_struct_align16(s) struct s { # define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); # define __lzo_struct_align32(s) struct s { # define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); # define __lzo_struct_align64(s) struct s { # define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); #endif #endif #if !defined(__lzo_union_um) #if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) #elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) #elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_union_am(s) union s { # define __lzo_union_am_end() } __lzo_may_alias; # define __lzo_union_um(s) union s { # define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_IBMC >= 700) # define __lzo_union_am(s) __lzo_gnuc_extension__ union s { # define __lzo_union_am_end() } __lzo_may_alias; # define __lzo_union_um(s) __lzo_gnuc_extension__ union s { # define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_union_um(s) __pragma(pack(push,1)) union s { # define __lzo_union_um_end() } __pragma(pack(pop)); #elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) # define __lzo_union_um(s) _Packed union s { # define __lzo_union_um_end() }; #endif #endif #if !defined(__lzo_union_am) # define __lzo_union_am(s) union s { # define __lzo_union_am_end() }; #endif #if !defined(__lzo_constructor) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_constructor __attribute__((__constructor__,__used__)) #elif (LZO_CC_GNUC >= 0x020700ul) # define __lzo_constructor __attribute__((__constructor__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_constructor __attribute__((__constructor__,__used__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_constructor __attribute__((__constructor__)) #endif #endif #if defined(__lzo_constructor) # ifndef __lzo_HAVE_constructor # define __lzo_HAVE_constructor 1 # endif #endif #if !defined(__lzo_destructor) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_destructor __attribute__((__destructor__,__used__)) #elif (LZO_CC_GNUC >= 0x020700ul) # define __lzo_destructor __attribute__((__destructor__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_destructor __attribute__((__destructor__,__used__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_destructor __attribute__((__destructor__)) #endif #endif #if defined(__lzo_destructor) # ifndef __lzo_HAVE_destructor # define __lzo_HAVE_destructor 1 # endif #endif #if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) # error "unexpected configuration - check your compiler defines" #endif #if !defined(__lzo_likely) && !defined(__lzo_unlikely) #if (LZO_CC_GNUC >= 0x030200ul) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_IBMC >= 1010) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_CLANG && LZO_CC_CLANG_C2) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #endif #endif #if defined(__lzo_likely) # ifndef __lzo_HAVE_likely # define __lzo_HAVE_likely 1 # endif #else # define __lzo_likely(e) (e) #endif #if defined(__lzo_very_likely) # ifndef __lzo_HAVE_very_likely # define __lzo_HAVE_very_likely 1 # endif #else # define __lzo_very_likely(e) __lzo_likely(e) #endif #if defined(__lzo_unlikely) # ifndef __lzo_HAVE_unlikely # define __lzo_HAVE_unlikely 1 # endif #else # define __lzo_unlikely(e) (e) #endif #if defined(__lzo_very_unlikely) # ifndef __lzo_HAVE_very_unlikely # define __lzo_HAVE_very_unlikely 1 # endif #else # define __lzo_very_unlikely(e) __lzo_unlikely(e) #endif #if !defined(__lzo_loop_forever) # if (LZO_CC_IBMC) # define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END # else # define __lzo_loop_forever() do { ; } while __lzo_cte(1) # endif #endif #if !defined(__lzo_unreachable) #if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable) # define __lzo_unreachable() __builtin_unreachable(); #elif (LZO_CC_GNUC >= 0x040500ul) # define __lzo_unreachable() __builtin_unreachable(); #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 # define __lzo_unreachable() __builtin_unreachable(); #endif #endif #if defined(__lzo_unreachable) # ifndef __lzo_HAVE_unreachable # define __lzo_HAVE_unreachable 1 # endif #else # if 0 # define __lzo_unreachable() ((void)0); # else # define __lzo_unreachable() __lzo_loop_forever(); # endif #endif #if !defined(lzo_unused_funcs_impl) # if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f # elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC) # define lzo_unused_funcs_impl(r,f) static r f # else # define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f # endif #endif #ifndef __LZO_CTA_NAME #if (LZO_CFG_USE_COUNTER) # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) #else # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) #endif #endif #if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) # if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_DMC || LZO_CC_SYMANTECC) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END # else # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END # endif #endif #if !defined(LZO_COMPILE_TIME_ASSERT) # if (LZO_CC_AZTECC) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} # elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul)) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} # elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) # define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} # elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) # define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} # elif (LZO_CC_GNUC >= 0x040700ul) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # else # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} # endif #endif #if (LZO_LANG_ASSEMBLER) # undef LZO_COMPILE_TIME_ASSERT_HEADER # define LZO_COMPILE_TIME_ASSERT_HEADER(e) /*empty*/ #else LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) #if defined(__cplusplus) extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } #endif LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) #endif #if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) # elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) # define __lzo_cdecl __cdecl # define __lzo_cdecl_atexit /*empty*/ # define __lzo_cdecl_main __cdecl # if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) # define __lzo_cdecl_qsort __pascal # elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) # define __lzo_cdecl_qsort _stdcall # else # define __lzo_cdecl_qsort __cdecl # endif # elif (LZO_CC_WATCOMC) # define __lzo_cdecl __cdecl # else # define __lzo_cdecl __cdecl # define __lzo_cdecl_atexit __cdecl # define __lzo_cdecl_main __cdecl # define __lzo_cdecl_qsort __cdecl # endif # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) # elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) # define __lzo_cdecl_sighandler __pascal # elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) # define __lzo_cdecl_sighandler _stdcall # elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) # define __lzo_cdecl_sighandler __clrcall # elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) # if defined(_DLL) # define __lzo_cdecl_sighandler _far _cdecl _loadds # elif defined(_MT) # define __lzo_cdecl_sighandler _far _cdecl # else # define __lzo_cdecl_sighandler _cdecl # endif # else # define __lzo_cdecl_sighandler __cdecl # endif #elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) # define __lzo_cdecl __cdecl #elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) # define __lzo_cdecl cdecl #endif #if !defined(__lzo_cdecl) # define __lzo_cdecl /*empty*/ #endif #if !defined(__lzo_cdecl_atexit) # define __lzo_cdecl_atexit /*empty*/ #endif #if !defined(__lzo_cdecl_main) # define __lzo_cdecl_main /*empty*/ #endif #if !defined(__lzo_cdecl_qsort) # define __lzo_cdecl_qsort /*empty*/ #endif #if !defined(__lzo_cdecl_sighandler) # define __lzo_cdecl_sighandler /*empty*/ #endif #if !defined(__lzo_cdecl_va) # define __lzo_cdecl_va __lzo_cdecl #endif #if !(LZO_CFG_NO_WINDOWS_H) #if !defined(LZO_HAVE_WINDOWS_H) #if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) # if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) # elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))) # elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) # else # define LZO_HAVE_WINDOWS_H 1 # endif #endif #endif #endif #define LZO_SIZEOF_CHAR 1 #ifndef LZO_SIZEOF_SHORT #if defined(SIZEOF_SHORT) # define LZO_SIZEOF_SHORT (SIZEOF_SHORT) #elif defined(__SIZEOF_SHORT__) # define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) #endif #endif #ifndef LZO_SIZEOF_INT #if defined(SIZEOF_INT) # define LZO_SIZEOF_INT (SIZEOF_INT) #elif defined(__SIZEOF_INT__) # define LZO_SIZEOF_INT (__SIZEOF_INT__) #endif #endif #ifndef LZO_SIZEOF_LONG #if defined(SIZEOF_LONG) # define LZO_SIZEOF_LONG (SIZEOF_LONG) #elif defined(__SIZEOF_LONG__) # define LZO_SIZEOF_LONG (__SIZEOF_LONG__) #endif #endif #ifndef LZO_SIZEOF_LONG_LONG #if defined(SIZEOF_LONG_LONG) # define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) #elif defined(__SIZEOF_LONG_LONG__) # define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) #endif #endif #ifndef LZO_SIZEOF___INT16 #if defined(SIZEOF___INT16) # define LZO_SIZEOF___INT16 (SIZEOF___INT16) #endif #endif #ifndef LZO_SIZEOF___INT32 #if defined(SIZEOF___INT32) # define LZO_SIZEOF___INT32 (SIZEOF___INT32) #endif #endif #ifndef LZO_SIZEOF___INT64 #if defined(SIZEOF___INT64) # define LZO_SIZEOF___INT64 (SIZEOF___INT64) #endif #endif #ifndef LZO_SIZEOF_VOID_P #if defined(SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) #elif defined(__SIZEOF_POINTER__) # define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) #endif #endif #ifndef LZO_SIZEOF_SIZE_T #if defined(SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) #elif defined(__SIZEOF_SIZE_T__) # define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) #endif #endif #ifndef LZO_SIZEOF_PTRDIFF_T #if defined(SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) #elif defined(__SIZEOF_PTRDIFF_T__) # define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) #endif #endif #define __LZO_LSR(x,b) (((x)+0ul) >> (b)) #if !defined(LZO_SIZEOF_SHORT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_SHORT 8 # elif (USHRT_MAX == LZO_0xffffL) # define LZO_SIZEOF_SHORT 2 # elif (__LZO_LSR(USHRT_MAX,7) == 1) # define LZO_SIZEOF_SHORT 1 # elif (__LZO_LSR(USHRT_MAX,15) == 1) # define LZO_SIZEOF_SHORT 2 # elif (__LZO_LSR(USHRT_MAX,31) == 1) # define LZO_SIZEOF_SHORT 4 # elif (__LZO_LSR(USHRT_MAX,63) == 1) # define LZO_SIZEOF_SHORT 8 # elif (__LZO_LSR(USHRT_MAX,127) == 1) # define LZO_SIZEOF_SHORT 16 # else # error "LZO_SIZEOF_SHORT" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) #if !defined(LZO_SIZEOF_INT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_INT 8 # elif (UINT_MAX == LZO_0xffffL) # define LZO_SIZEOF_INT 2 # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_INT 4 # elif (__LZO_LSR(UINT_MAX,7) == 1) # define LZO_SIZEOF_INT 1 # elif (__LZO_LSR(UINT_MAX,15) == 1) # define LZO_SIZEOF_INT 2 # elif (__LZO_LSR(UINT_MAX,31) == 1) # define LZO_SIZEOF_INT 4 # elif (__LZO_LSR(UINT_MAX,63) == 1) # define LZO_SIZEOF_INT 8 # elif (__LZO_LSR(UINT_MAX,127) == 1) # define LZO_SIZEOF_INT 16 # else # error "LZO_SIZEOF_INT" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) #if !defined(LZO_SIZEOF_LONG) # if (ULONG_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_LONG 4 # elif (__LZO_LSR(ULONG_MAX,7) == 1) # define LZO_SIZEOF_LONG 1 # elif (__LZO_LSR(ULONG_MAX,15) == 1) # define LZO_SIZEOF_LONG 2 # elif (__LZO_LSR(ULONG_MAX,31) == 1) # define LZO_SIZEOF_LONG 4 # elif (__LZO_LSR(ULONG_MAX,39) == 1) # define LZO_SIZEOF_LONG 5 # elif (__LZO_LSR(ULONG_MAX,63) == 1) # define LZO_SIZEOF_LONG 8 # elif (__LZO_LSR(ULONG_MAX,127) == 1) # define LZO_SIZEOF_LONG 16 # else # error "LZO_SIZEOF_LONG" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) # if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) # if (LZO_CC_GNUC >= 0x030300ul) # if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) # define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG # elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) # define LZO_SIZEOF_LONG_LONG 4 # endif # endif # endif #endif #endif #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) #if (LZO_ARCH_I086 && LZO_CC_DMC) #elif (LZO_CC_CILLY) && defined(__GNUC__) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_SIZEOF_LONG_LONG 8 #elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_OS_WIN64 || defined(_WIN64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_DMC)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) # define LZO_SIZEOF___INT64 8 #elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) # define LZO_SIZEOF___INT64 8 #elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) # define LZO_SIZEOF_LONG_LONG 8 #elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) #elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define LZO_SIZEOF_LONG_LONG 8 #endif #endif #endif #if defined(__cplusplus) && (LZO_CC_GNUC) # if (LZO_CC_GNUC < 0x020800ul) # undef LZO_SIZEOF_LONG_LONG # endif #endif #if (LZO_CFG_NO_LONG_LONG) # undef LZO_SIZEOF_LONG_LONG #elif defined(__NO_LONG_LONG) # undef LZO_SIZEOF_LONG_LONG #elif defined(_NO_LONGLONG) # undef LZO_SIZEOF_LONG_LONG #endif #if !defined(LZO_WORDSIZE) #if (LZO_ARCH_ALPHA) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_AMD64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_ARM64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_AVR) # define LZO_WORDSIZE 1 #elif (LZO_ARCH_H8300) # if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) # define LZO_WORDSIZE 4 # else # define LZO_WORDSIZE 2 # endif #elif (LZO_ARCH_I086) # define LZO_WORDSIZE 2 #elif (LZO_ARCH_IA64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_M16C) # define LZO_WORDSIZE 2 #elif (LZO_ARCH_SPU) # define LZO_WORDSIZE 4 #elif (LZO_ARCH_Z80) # define LZO_WORDSIZE 1 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) # define LZO_WORDSIZE 8 #elif (LZO_OS_OS400 || defined(__OS400__)) # define LZO_WORDSIZE 8 #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_WORDSIZE 8 #endif #endif #if !defined(LZO_SIZEOF_VOID_P) #if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) # define LZO_SIZEOF_VOID_P 4 #elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) # define LZO_SIZEOF_VOID_P 8 #elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) # define LZO_SIZEOF_VOID_P 8 #elif defined(__LP64__) || defined(__LP64) || defined(_LP64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) # define LZO_SIZEOF_VOID_P 8 #elif (LZO_ARCH_AVR) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_H8300) # if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 4) # if defined(__NORMAL_MODE__) # define LZO_SIZEOF_VOID_P 2 # else # define LZO_SIZEOF_VOID_P 4 # endif # else LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 2) # define LZO_SIZEOF_VOID_P 2 # endif # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT # endif #elif (LZO_ARCH_I086) # if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) # define LZO_SIZEOF_VOID_P 2 # elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) # define LZO_SIZEOF_VOID_P 4 # else # error "invalid LZO_ARCH_I086 memory model" # endif #elif (LZO_ARCH_M16C) # if defined(__m32c_cpu__) || defined(__m32cm_cpu__) # define LZO_SIZEOF_VOID_P 4 # else # define LZO_SIZEOF_VOID_P 2 # endif #elif (LZO_ARCH_SPU) # define LZO_SIZEOF_VOID_P 4 #elif (LZO_ARCH_Z80) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) # define LZO_SIZEOF_VOID_P 4 #elif (LZO_OS_OS400 || defined(__OS400__)) # if defined(__LLP64_IFC__) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG # else # define LZO_SIZEOF_VOID_P 16 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG # endif #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG #endif #endif #if !defined(LZO_SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) #if !defined(LZO_SIZEOF_SIZE_T) #if (LZO_ARCH_I086 || LZO_ARCH_M16C) # define LZO_SIZEOF_SIZE_T 2 #endif #endif #if !defined(LZO_SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P #endif #if defined(offsetof) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) #if (LZO_ARCH_I086) # if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P # elif (LZO_MM_COMPACT || LZO_MM_LARGE) # if (LZO_CC_BORLANDC || LZO_CC_TURBOC) # define LZO_SIZEOF_PTRDIFF_T 4 # else # define LZO_SIZEOF_PTRDIFF_T 2 # endif # else # error "invalid LZO_ARCH_I086 memory model" # endif #endif #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T #endif #if defined(offsetof) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) #endif #if !defined(LZO_WORDSIZE) # define LZO_WORDSIZE LZO_SIZEOF_VOID_P #endif #if (LZO_ABI_NEUTRAL_ENDIAN) # undef LZO_ABI_BIG_ENDIAN # undef LZO_ABI_LITTLE_ENDIAN #elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) #if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) # define LZO_ABI_BIG_ENDIAN 1 #elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430 || LZO_ARCH_RISCV) # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) # if (__LITTLE_ENDIAN__ == 1) # define LZO_ABI_LITTLE_ENDIAN 1 # else # define LZO_ABI_BIG_ENDIAN 1 # endif #elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(_MSC_VER) && defined(_WIN32) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) # if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) # error "unexpected configuration - check your compiler defines" # elif defined(__BIG_ENDIAN) # define LZO_ABI_BIG_ENDIAN 1 # else # define LZO_ABI_LITTLE_ENDIAN 1 # endif # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(_MSC_VER) && defined(_WIN32) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) # define LZO_ABI_LITTLE_ENDIAN 1 #endif #endif #if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ABI_BIG_ENDIAN) # define LZO_INFO_ABI_ENDIAN "be" #elif (LZO_ABI_LITTLE_ENDIAN) # define LZO_INFO_ABI_ENDIAN "le" #elif (LZO_ABI_NEUTRAL_ENDIAN) # define LZO_INFO_ABI_ENDIAN "neutral" #endif #if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_I8LP16 1 # define LZO_INFO_ABI_PM "i8lp16" #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_ILP16 1 # define LZO_INFO_ABI_PM "ilp16" #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_LP32 1 # define LZO_INFO_ABI_PM "lp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_ILP32 1 # define LZO_INFO_ABI_PM "ilp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) # define LZO_ABI_LLP64 1 # define LZO_INFO_ABI_PM "llp64" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) # define LZO_ABI_LP64 1 # define LZO_INFO_ABI_PM "lp64" #elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) # define LZO_ABI_ILP64 1 # define LZO_INFO_ABI_PM "ilp64" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_IP32L64 1 # define LZO_INFO_ABI_PM "ip32l64" #endif #if (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_VOID_P == 4 && LZO_WORDSIZE == 8) # define LZO_ABI_IP32W64 1 # ifndef LZO_INFO_ABI_PM # define LZO_INFO_ABI_PM "ip32w64" # endif #endif #if 0 #elif !defined(__LZO_LIBC_OVERRIDE) #if (LZO_LIBC_NAKED) # define LZO_INFO_LIBC "naked" #elif (LZO_LIBC_FREESTANDING) # define LZO_INFO_LIBC "freestanding" #elif (LZO_LIBC_MOSTLY_FREESTANDING) # define LZO_INFO_LIBC "mfreestanding" #elif (LZO_LIBC_ISOC90) # define LZO_INFO_LIBC "isoc90" #elif (LZO_LIBC_ISOC99) # define LZO_INFO_LIBC "isoc99" #elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) # define LZO_LIBC_ISOC90 1 # define LZO_INFO_LIBC "isoc90" #elif defined(__dietlibc__) # define LZO_LIBC_DIETLIBC 1 # define LZO_INFO_LIBC "dietlibc" #elif defined(_NEWLIB_VERSION) # define LZO_LIBC_NEWLIB 1 # define LZO_INFO_LIBC "newlib" #elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) # if defined(__UCLIBC_SUBLEVEL__) # define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) # else # define LZO_LIBC_UCLIBC 0x00090bL # endif # define LZO_INFO_LIBC "uc" "libc" #elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) # define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) # define LZO_INFO_LIBC "glibc" #elif (LZO_CC_MWERKS) && defined(__MSL__) # define LZO_LIBC_MSL __MSL__ # define LZO_INFO_LIBC "msl" #elif 1 && defined(__IAR_SYSTEMS_ICC__) # define LZO_LIBC_ISOC90 1 # define LZO_INFO_LIBC "isoc90" #else # define LZO_LIBC_DEFAULT 1 # define LZO_INFO_LIBC "default" #endif #endif #if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) # define LZO_ASM_SYNTAX_MSC 1 #elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) #elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) #elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) # define LZO_ASM_SYNTAX_GNUC 1 #elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) # define LZO_ASM_SYNTAX_GNUC 1 #elif (LZO_CC_GNUC) # define LZO_ASM_SYNTAX_GNUC 1 #endif #if (LZO_ASM_SYNTAX_GNUC) #if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) # define __LZO_ASM_CLOBBER "ax" # define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) # define __LZO_ASM_CLOBBER "memory" # define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #else # define __LZO_ASM_CLOBBER "cc", "memory" # define __LZO_ASM_CLOBBER_LIST_CC : "cc" # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #endif #endif #if (LZO_ARCH_ALPHA) # define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_AMD64) # define LZO_OPT_AVOID_INT_INDEX 1 # define LZO_OPT_AVOID_UINT_INDEX 1 # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif #elif (LZO_ARCH_ARM) # if defined(__ARM_FEATURE_UNALIGNED) # if ((__ARM_FEATURE_UNALIGNED)+0) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif # elif 1 && (LZO_ARCH_ARM_THUMB2) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__ARM_ARCH) && ((__ARM_ARCH)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R)) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(_MSC_VER) && defined(_M_ARM) && ((_M_ARM)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif #elif (LZO_ARCH_ARM64) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif #elif (LZO_ARCH_CRIS) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif #elif (LZO_ARCH_I386) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif #elif (LZO_ARCH_IA64) # define LZO_OPT_AVOID_INT_INDEX 1 # define LZO_OPT_AVOID_UINT_INDEX 1 # define LZO_OPT_PREFER_POSTINC 1 #elif (LZO_ARCH_M68K) # define LZO_OPT_PREFER_POSTINC 1 # define LZO_OPT_PREFER_PREDEC 1 # if defined(__mc68020__) && !defined(__mcoldfire__) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif #elif (LZO_ARCH_MIPS) # define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_POWERPC) # define LZO_OPT_PREFER_PREINC 1 # define LZO_OPT_PREFER_PREDEC 1 # if (LZO_ABI_BIG_ENDIAN) || (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif # endif #elif (LZO_ARCH_RISCV) # define LZO_OPT_AVOID_UINT_INDEX 1 # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif #elif (LZO_ARCH_S390) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif #elif (LZO_ARCH_SH) # define LZO_OPT_PREFER_POSTINC 1 # define LZO_OPT_PREFER_PREDEC 1 #endif #ifndef LZO_CFG_NO_INLINE_ASM #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_INLINE_ASM 1 #elif (LZO_CC_LLVM) # define LZO_CFG_NO_INLINE_ASM 1 #endif #endif #if (LZO_CFG_NO_INLINE_ASM) # undef LZO_ASM_SYNTAX_MSC # undef LZO_ASM_SYNTAX_GNUC # undef __LZO_ASM_CLOBBER # undef __LZO_ASM_CLOBBER_LIST_CC # undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY # undef __LZO_ASM_CLOBBER_LIST_EMPTY #endif #ifndef LZO_CFG_NO_UNALIGNED #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_UNALIGNED 1 #endif #endif #if (LZO_CFG_NO_UNALIGNED) # undef LZO_OPT_UNALIGNED16 # undef LZO_OPT_UNALIGNED32 # undef LZO_OPT_UNALIGNED64 #endif #if defined(__LZO_INFOSTR_MM) #elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) # define __LZO_INFOSTR_MM "" #elif defined(LZO_INFO_MM) # define __LZO_INFOSTR_MM "." LZO_INFO_MM #else # define __LZO_INFOSTR_MM "" #endif #if defined(__LZO_INFOSTR_PM) #elif defined(LZO_INFO_ABI_PM) # define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM #else # define __LZO_INFOSTR_PM "" #endif #if defined(__LZO_INFOSTR_ENDIAN) #elif defined(LZO_INFO_ABI_ENDIAN) # define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN #else # define __LZO_INFOSTR_ENDIAN "" #endif #if defined(__LZO_INFOSTR_OSNAME) #elif defined(LZO_INFO_OS_CONSOLE) # define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE #elif defined(LZO_INFO_OS_POSIX) # define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX #else # define __LZO_INFOSTR_OSNAME LZO_INFO_OS #endif #if defined(__LZO_INFOSTR_LIBC) #elif defined(LZO_INFO_LIBC) # define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC #else # define __LZO_INFOSTR_LIBC "" #endif #if defined(__LZO_INFOSTR_CCVER) #elif defined(LZO_INFO_CCVER) # define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER #else # define __LZO_INFOSTR_CCVER "" #endif #define LZO_INFO_STRING \ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER #if !(LZO_CFG_SKIP_LZO_TYPES) #if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) # error "missing defines for sizes" #endif #if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) # error "missing defines for sizes" #endif #define LZO_TYPEOF_CHAR 1u #define LZO_TYPEOF_SHORT 2u #define LZO_TYPEOF_INT 3u #define LZO_TYPEOF_LONG 4u #define LZO_TYPEOF_LONG_LONG 5u #define LZO_TYPEOF___INT8 17u #define LZO_TYPEOF___INT16 18u #define LZO_TYPEOF___INT32 19u #define LZO_TYPEOF___INT64 20u #define LZO_TYPEOF___INT128 21u #define LZO_TYPEOF___INT256 22u #define LZO_TYPEOF___MODE_QI 33u #define LZO_TYPEOF___MODE_HI 34u #define LZO_TYPEOF___MODE_SI 35u #define LZO_TYPEOF___MODE_DI 36u #define LZO_TYPEOF___MODE_TI 37u #define LZO_TYPEOF_CHAR_P 129u #if !defined(lzo_llong_t) #if (LZO_SIZEOF_LONG_LONG+0 > 0) # if !(LZO_LANG_ASSEMBLER) __lzo_gnuc_extension__ typedef long long lzo_llong_t__; __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; # endif # define lzo_llong_t lzo_llong_t__ # define lzo_ullong_t lzo_ullong_t__ #endif #endif #if !defined(lzo_int16e_t) #if (LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) && (LZO_SIZEOF_SHORT != 2) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T #endif #if (LZO_SIZEOF_LONG == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) # define lzo_int16e_t long # define lzo_uint16e_t unsigned long # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_INT == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) # define lzo_int16e_t int # define lzo_uint16e_t unsigned int # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == 2) # define lzo_int16e_t short int # define lzo_uint16e_t unsigned short int # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT #elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); # endif # define lzo_int16e_t lzo_int16e_hi_t__ # define lzo_uint16e_t lzo_uint16e_hi_t__ # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI #elif (LZO_SIZEOF___INT16 == 2) # define lzo_int16e_t __int16 # define lzo_uint16e_t unsigned __int16 # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16 #else #endif #endif #if defined(lzo_int16e_t) # define LZO_SIZEOF_LZO_INT16E_T 2 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) #endif #if !defined(lzo_int32e_t) #if (LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) && (LZO_SIZEOF_INT != 4) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T #endif #if (LZO_SIZEOF_LONG == 4) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) # define lzo_int32e_t long int # define lzo_uint32e_t unsigned long int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_INT == 4) # define lzo_int32e_t int # define lzo_uint32e_t unsigned int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == 4) # define lzo_int32e_t short int # define lzo_uint32e_t unsigned short int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT #elif (LZO_SIZEOF_LONG_LONG == 4) # define lzo_int32e_t lzo_llong_t # define lzo_uint32e_t lzo_ullong_t # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); # endif # define lzo_int32e_t lzo_int32e_si_t__ # define lzo_uint32e_t lzo_uint32e_si_t__ # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); # endif # define lzo_int32e_t lzo_int32e_si_t__ # define lzo_uint32e_t lzo_uint32e_si_t__ # define LZO_INT32_C(c) (c##LL) # define LZO_UINT32_C(c) (c##ULL) # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI #elif (LZO_SIZEOF___INT32 == 4) # define lzo_int32e_t __int32 # define lzo_uint32e_t unsigned __int32 # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32 #else #endif #endif #if defined(lzo_int32e_t) # define LZO_SIZEOF_LZO_INT32E_T 4 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) #endif #if !defined(lzo_int64e_t) #if (LZO_SIZEOF___INT64 == 8) # if (LZO_CC_BORLANDC) && !defined(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T) # define LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T LZO_TYPEOF___INT64 # endif #endif #if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && (LZO_SIZEOF_LONG_LONG != 8) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T #endif #if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) && (LZO_SIZEOF___INT64 != 8) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T #endif #if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_int64e_t int # define lzo_uint64e_t unsigned int # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) # define lzo_int64e_t long int # define lzo_uint64e_t unsigned long int # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) # define lzo_int64e_t lzo_llong_t # define lzo_uint64e_t lzo_ullong_t # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG # if (LZO_CC_BORLANDC) # define LZO_INT64_C(c) ((c) + 0ll) # define LZO_UINT64_C(c) ((c) + 0ull) # elif 0 # define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) # define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) # else # define LZO_INT64_C(c) (c##LL) # define LZO_UINT64_C(c) (c##ULL) # endif #elif (LZO_SIZEOF___INT64 == 8) # define lzo_int64e_t __int64 # define lzo_uint64e_t unsigned __int64 # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64 # if (LZO_CC_BORLANDC) # define LZO_INT64_C(c) ((c) + 0i64) # define LZO_UINT64_C(c) ((c) + 0ui64) # else # define LZO_INT64_C(c) (c##i64) # define LZO_UINT64_C(c) (c##ui64) # endif #else #endif #endif #if defined(lzo_int64e_t) # define LZO_SIZEOF_LZO_INT64E_T 8 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) #endif #if !defined(lzo_int32l_t) #if defined(lzo_int32e_t) # define lzo_int32l_t lzo_int32e_t # define lzo_uint32l_t lzo_uint32e_t # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T # define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T #elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_int32l_t int # define lzo_uint32l_t unsigned int # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT #elif (LZO_SIZEOF_LONG >= 4) # define lzo_int32l_t long int # define lzo_uint32l_t unsigned long int # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG #else # error "lzo_int32l_t" #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) #endif #if !defined(lzo_int64l_t) #if defined(lzo_int64e_t) # define lzo_int64l_t lzo_int64e_t # define lzo_uint64l_t lzo_uint64e_t # define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T # define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T #else #endif #endif #if defined(lzo_int64l_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) #endif #if !defined(lzo_int32f_t) #if (LZO_SIZEOF_SIZE_T >= 8) # define lzo_int32f_t lzo_int64l_t # define lzo_uint32f_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T #else # define lzo_int32f_t lzo_int32l_t # define lzo_uint32f_t lzo_uint32l_t # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T # define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) #endif #if !defined(lzo_int64f_t) #if defined(lzo_int64l_t) # define lzo_int64f_t lzo_int64l_t # define lzo_uint64f_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T #else #endif #endif #if defined(lzo_int64f_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) #endif #if !defined(lzo_intptr_t) #if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) # define __LZO_INTPTR_T_IS_POINTER 1 # if !(LZO_LANG_ASSEMBLER) typedef char * lzo_intptr_t; typedef char * lzo_uintptr_t; # endif # define lzo_intptr_t lzo_intptr_t # define lzo_uintptr_t lzo_uintptr_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P #elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) # if !(LZO_LANG_ASSEMBLER) typedef __w64 int lzo_intptr_t; typedef __w64 unsigned int lzo_uintptr_t; # endif # define lzo_intptr_t lzo_intptr_t # define lzo_uintptr_t lzo_uintptr_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) # define lzo_intptr_t short # define lzo_uintptr_t unsigned short # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT #elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_intptr_t int # define lzo_uintptr_t unsigned int # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) # define lzo_intptr_t long # define lzo_uintptr_t unsigned long # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) # define lzo_intptr_t lzo_int64l_t # define lzo_uintptr_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T #else # error "lzo_intptr_t" #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) #endif #if !defined(lzo_word_t) #if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) #if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) # define lzo_word_t lzo_uintptr_t # define lzo_sword_t lzo_intptr_t # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T #elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) # define lzo_word_t unsigned long # define lzo_sword_t long # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG #elif (LZO_WORDSIZE == LZO_SIZEOF_INT) # define lzo_word_t unsigned int # define lzo_sword_t int # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT #elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) # define lzo_word_t unsigned short # define lzo_sword_t short # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT #elif (LZO_WORDSIZE == 1) # define lzo_word_t unsigned char # define lzo_sword_t signed char # define LZO_SIZEOF_LZO_WORD_T 1 # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR #elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) # define lzo_word_t lzo_uint64l_t # define lzo_sword_t lzo_int64l_t # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T #elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) #if 0 # if !(LZO_LANG_ASSEMBLER) typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); # endif # define lzo_word_t lzo_word_t # define lzo_sword_t lzo_sword_t # define LZO_SIZEOF_LZO_WORD_T 16 # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI #endif #else # error "lzo_word_t" #endif #endif #endif #if 1 && defined(lzo_word_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) #endif #if 1 #define lzo_int8_t signed char #define lzo_uint8_t unsigned char #define LZO_SIZEOF_LZO_INT8_T 1 #define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) #endif #if defined(lzo_int16e_t) #define lzo_int16_t lzo_int16e_t #define lzo_uint16_t lzo_uint16e_t #define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T #define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) #endif #if defined(lzo_int32e_t) #define lzo_int32_t lzo_int32e_t #define lzo_uint32_t lzo_uint32e_t #define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T #define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) #endif #if defined(lzo_int64e_t) #define lzo_int64_t lzo_int64e_t #define lzo_uint64_t lzo_uint64e_t #define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T #define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) #endif #if 1 #define lzo_int_least32_t lzo_int32l_t #define lzo_uint_least32_t lzo_uint32l_t #define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T #define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) #endif #if defined(lzo_int64l_t) #define lzo_int_least64_t lzo_int64l_t #define lzo_uint_least64_t lzo_uint64l_t #define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T #define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) #endif #if 1 #define lzo_int_fast32_t lzo_int32f_t #define lzo_uint_fast32_t lzo_uint32f_t #define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T #define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) #endif #if defined(lzo_int64f_t) #define lzo_int_fast64_t lzo_int64f_t #define lzo_uint_fast64_t lzo_uint64f_t #define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T #define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) #endif #if !defined(LZO_INT16_C) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) # define LZO_INT16_C(c) ((c) + 0) # define LZO_UINT16_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) # define LZO_INT16_C(c) ((c) + 0L) # define LZO_UINT16_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 2) # define LZO_INT16_C(c) (c) # define LZO_UINT16_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 2) # define LZO_INT16_C(c) (c##L) # define LZO_UINT16_C(c) (c##UL) # else # error "LZO_INT16_C" # endif #endif #if !defined(LZO_INT32_C) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) # define LZO_INT32_C(c) ((c) + 0) # define LZO_UINT32_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) # define LZO_INT32_C(c) ((c) + 0L) # define LZO_UINT32_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 4) # define LZO_INT32_C(c) (c) # define LZO_UINT32_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 4) # define LZO_INT32_C(c) (c##L) # define LZO_UINT32_C(c) (c##UL) # elif (LZO_SIZEOF_LONG_LONG >= 4) # define LZO_INT32_C(c) (c##LL) # define LZO_UINT32_C(c) (c##ULL) # else # error "LZO_INT32_C" # endif #endif #if !defined(LZO_INT64_C) && defined(lzo_int64l_t) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) # define LZO_INT64_C(c) ((c) + 0) # define LZO_UINT64_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) # define LZO_INT64_C(c) ((c) + 0L) # define LZO_UINT64_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 8) # define LZO_INT64_C(c) (c) # define LZO_UINT64_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 8) # define LZO_INT64_C(c) (c##L) # define LZO_UINT64_C(c) (c##UL) # else # error "LZO_INT64_C" # endif #endif #endif #endif /* already included */ /* vim:set ts=4 sw=4 et: */ ntop-n2n-90215bd/include/minilzo.h000066400000000000000000000073221422132035700167750ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* minilzo.h -- mini subset of the LZO real-time data compression library This file is part of the LZO real-time data compression library. Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ /* * NOTE: * the full LZO package can be found at * http://www.oberhumer.com/opensource/lzo/ */ #ifndef __MINILZO_H_INCLUDED #define __MINILZO_H_INCLUDED 1 #define MINILZO_VERSION 0x20a0 /* 2.10 */ #if defined(__LZOCONF_H_INCLUDED) # error "you cannot use both LZO and miniLZO" #endif /* internal Autoconf configuration file - only used when building miniLZO */ #ifdef MINILZO_HAVE_CONFIG_H # include #endif #include #include #ifndef __LZODEFS_H_INCLUDED #include "lzodefs.h" #endif #undef LZO_HAVE_CONFIG_H #include "lzoconf.h" #if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) # error "version mismatch in header files" #endif #ifdef __cplusplus extern "C" { #endif /*********************************************************************** // ************************************************************************/ /* Memory required for the wrkmem parameter. * When the required size is 0, you can also pass a NULL pointer. */ #define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS #define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (16384L * lzo_sizeof_dict_t)) #define LZO1X_MEM_DECOMPRESS (0) /* compression */ LZO_EXTERN(int) lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem ); /* decompression */ LZO_EXTERN(int) lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem /* NOT USED */ ); /* safe decompression with overrun testing */ LZO_EXTERN(int) lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem /* NOT USED */ ); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* already included */ /* vim:set ts=4 sw=4 et: */ ntop-n2n-90215bd/include/n2n.h000066400000000000000000000221771422132035700160160ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #ifndef _N2N_H_ #define _N2N_H_ /* tunctl -t tun0 tunctl -t tun1 ifconfig tun0 1.2.3.4 up ifconfig tun1 1.2.3.5 up ./edge -d tun0 -l 2000 -r 127.0.0.1:3000 -c hello ./edge -d tun1 -l 3000 -r 127.0.0.1:2000 -c hello tunctl -u UID -t tunX */ #define SN_MANUAL_MAC /* allows supernode MAC address to be set manually */ #define N2N_HAVE_DAEMON /* needs to be defined before it gets undefined */ #define N2N_HAVE_TCP /* needs to be defined before it gets undefined */ /* #define N2N_CAN_NAME_IFACE */ /* Moved here to define _CRT_SECURE_NO_WARNINGS before all the including takes place */ #ifdef WIN32 #ifndef CMAKE_BUILD #include "config.h" /* Visual C++ */ #else #include "winconfig.h" #endif #define N2N_CAN_NAME_IFACE 1 #undef N2N_HAVE_DAEMON #undef N2N_HAVE_TCP /* as explained on https://github.com/ntop/n2n/pull/627#issuecomment-782093706 */ #undef N2N_HAVE_SETUID #else #ifndef CMAKE_BUILD #include "config.h" #endif #endif #define PACKAGE_BUILDDATE (__DATE__ " " __TIME__) #include #include #include #ifndef WIN32 #include #endif #ifndef _MSC_VER #include #endif /* #ifndef _MSC_VER */ #include #include #include #include #include #ifndef WIN32 #include #include #include #include #include #ifdef __linux__ #define N2N_CAN_NAME_IFACE 1 #include #include #include #include #include #include #include #include #endif /* #ifdef __linux__ */ #ifdef __FreeBSD__ #include #endif /* #ifdef __FreeBSD__ */ #include #include #ifdef HAVE_ZSTD #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #if defined (HAVE_OPENSSL_1_1) #include #include #endif #define closesocket(a) close(a) #endif /* #ifndef WIN32 */ #include "minilzo.h" #include #include #include #include "lzoconf.h" #include "uthash.h" #include "n2n_define.h" #include "n2n_typedefs.h" #ifdef WIN32 #include /* for tcp */ #define SHUT_RDWR SD_BOTH /* for tcp */ #include "wintap.h" #include #else #include #endif /* #ifdef WIN32 */ #include "n2n_wire.h" #include "random_numbers.h" #include "pearson.h" #include "portable_endian.h" #include "aes.h" #include "cc20.h" #include "speck.h" #include "curve25519.h" #include "n2n_regex.h" #include "sn_selection.h" #include "network_traffic_filter.h" #include "auth.h" #if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP) #include "n2n_port_mapping.h" #endif // HAVE_MINIUPNP || HAVE_NATPMP /* ************************************** */ #include "header_encryption.h" #include "tf.h" #ifndef TRACE_ERROR #define TRACE_ERROR 0, __FILE__, __LINE__ #define TRACE_WARNING 1, __FILE__, __LINE__ #define TRACE_NORMAL 2, __FILE__, __LINE__ #define TRACE_INFO 3, __FILE__, __LINE__ #define TRACE_DEBUG 4, __FILE__, __LINE__ #endif /* ************************************** */ /* Transop Init Functions */ int n2n_transop_null_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); int n2n_transop_tf_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); int n2n_transop_aes_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); int n2n_transop_cc20_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); int n2n_transop_speck_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); int n2n_transop_lzo_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); #ifdef HAVE_ZSTD int n2n_transop_zstd_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); #endif /* Log */ void setTraceLevel (int level); void setUseSyslog (int use_syslog); void setTraceFile (FILE *f); int getTraceLevel (); void closeTraceFile (); void traceEvent (int eventTraceLevel, char* file, int line, char * format, ...); /* Tuntap API */ int tuntap_open (struct tuntap_dev *device, char *dev, const char *address_mode, char *device_ip, char *device_mask, const char * device_mac, int mtu #ifdef WIN32 , int metric #endif ); int tuntap_read (struct tuntap_dev *tuntap, unsigned char *buf, int len); int tuntap_write (struct tuntap_dev *tuntap, unsigned char *buf, int len); void tuntap_close (struct tuntap_dev *tuntap); void tuntap_get_address (struct tuntap_dev *tuntap); /* Utils */ char* intoa (uint32_t addr, char* buf, uint16_t buf_len); uint32_t bitlen2mask (uint8_t bitlen); uint8_t mask2bitlen (uint32_t mask); char* macaddr_str (macstr_t buf, const n2n_mac_t mac); int str2mac (uint8_t * outmac /* 6 bytes */, const char * s); int supernode2sock (n2n_sock_t * sn, const n2n_sn_name_t addrIn); uint8_t is_multi_broadcast (const n2n_mac_t dest_mac); uint8_t is_broadcast (const n2n_mac_t dest_mac); uint8_t is_null_mac (const n2n_mac_t dest_mac); char* msg_type2str (uint16_t msg_type); void hexdump (const uint8_t * buf, size_t len); void print_n2n_version (); int is_empty_ip_address (const n2n_sock_t * sock); void print_edge_stats (const n2n_edge_t *eee); int memrnd (uint8_t *address, size_t len); int memxor (uint8_t *destination, const uint8_t *source, size_t len); /* Sockets */ char* sock_to_cstr (n2n_sock_str_t out, const n2n_sock_t * sock); char * ip_subnet_to_str (dec_ip_bit_str_t buf, const n2n_ip_subnet_t *ipaddr); SOCKET open_socket (int local_port, in_addr_t address, int type); int sock_equal (const n2n_sock_t * a, const n2n_sock_t * b); /* Header encryption */ uint64_t time_stamp (void); uint64_t initial_time_stamp (void); int time_stamp_verify_and_update (uint64_t stamp, uint64_t * previous_stamp, int allow_jitter); /* Operations on peer_info lists. */ size_t purge_peer_list (struct peer_info ** peer_list, SOCKET socket_not_to_close, n2n_tcp_connection_t **tcp_connections, time_t purge_before); size_t clear_peer_list (struct peer_info ** peer_list); size_t purge_expired_nodes (struct peer_info **peer_list, SOCKET socket_not_to_close, n2n_tcp_connection_t **tcp_connections, time_t *p_last_purge, int frequency, int timeout); /* Edge conf */ void edge_init_conf_defaults (n2n_edge_conf_t *conf); int edge_verify_conf (const n2n_edge_conf_t *conf); int edge_conf_add_supernode (n2n_edge_conf_t *conf, const char *ip_and_port); const n2n_edge_conf_t* edge_get_conf (const n2n_edge_t *eee); void edge_term_conf (n2n_edge_conf_t *conf); /* Public functions */ n2n_edge_t* edge_init (const n2n_edge_conf_t *conf, int *rv); void update_supernode_reg (n2n_edge_t * eee, time_t nowTime); void readFromIPSocket (n2n_edge_t * eee, int in_sock); void edge_term (n2n_edge_t *eee); void edge_set_callbacks (n2n_edge_t *eee, const n2n_edge_callbacks_t *callbacks); void edge_set_userdata (n2n_edge_t *eee, void *user_data); void* edge_get_userdata (n2n_edge_t *eee); void edge_send_packet2net (n2n_edge_t *eee, uint8_t *tap_pkt, size_t len); void edge_read_from_tap (n2n_edge_t *eee); int edge_get_n2n_socket (n2n_edge_t *eee); int edge_get_management_socket (n2n_edge_t *eee); int run_edge_loop (n2n_edge_t *eee); int quick_edge_init (char *device_name, char *community_name, char *encrypt_key, char *device_mac, char *local_ip_address, char *supernode_ip_address_port, int *keep_on_running); int comm_init (struct sn_community *comm, char *cmn); int sn_init_defaults (n2n_sn_t *sss); void sn_init (n2n_sn_t *sss); void sn_term (n2n_sn_t *sss); int supernode2sock (n2n_sock_t * sn, const n2n_sn_name_t addrIn); struct peer_info* add_sn_to_list_by_mac_or_sock (struct peer_info **sn_list, n2n_sock_t *sock, const n2n_mac_t mac, int *skip_add); int run_sn_loop (n2n_sn_t *sss); int assign_one_ip_subnet (n2n_sn_t *sss, struct sn_community *comm); const char* compression_str (uint8_t cmpr); const char* transop_str (enum n2n_transform tr); void readFromMgmtSocket (n2n_edge_t *eee); void mgmt_event_post (enum n2n_event_topic topic, int data0, void *data1); #endif /* _N2N_H_ */ ntop-n2n-90215bd/include/n2n_define.h000066400000000000000000000235441422132035700173270ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* N2N packet header indicators. */ #define MSG_TYPE_REGISTER 1 #define MSG_TYPE_DEREGISTER 2 #define MSG_TYPE_PACKET 3 #define MSG_TYPE_REGISTER_ACK 4 #define MSG_TYPE_REGISTER_SUPER 5 #define MSG_TYPE_UNREGISTER_SUPER 6 #define MSG_TYPE_REGISTER_SUPER_ACK 7 #define MSG_TYPE_REGISTER_SUPER_NAK 8 #define MSG_TYPE_FEDERATION 9 #define MSG_TYPE_PEER_INFO 10 #define MSG_TYPE_QUERY_PEER 11 #define MSG_TYPE_MAX_TYPE 11 #define MSG_TYPE_RE_REGISTER_SUPER 12 /* Max available space to add supernodes' informations (sockets and MACs) in REGISTER_SUPER_ACK * Field sizes of REGISTER_SUPER_ACK as used in encode/decode fucntions in src/wire.c */ #define REG_SUPER_ACK_PAYLOAD_SPACE (DEFAULT_MTU - (sizeof(n2n_common_t) + sizeof(n2n_REGISTER_SUPER_ACK_t))) /* Space needed to store socket and MAC address of a supernode */ #define REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE (sizeof(n2n_REGISTER_SUPER_ACK_payload_t)) #define BOOTSTRAP_TIMEOUT 3 #define PURGE_REGISTRATION_FREQUENCY 30 #define RE_REG_AND_PURGE_FREQUENCY 10 #define REGISTRATION_TIMEOUT 60 #define SOCKET_TIMEOUT_INTERVAL_SECS 10 #define REGISTER_SUPER_INTERVAL_DFL 20 /* sec, usually UDP NAT entries in a firewall expire after 30 seconds */ #define SWEEP_TIME 30 /* sec, indicates the value after which we have to sort the hash list of supernodes in edges * and when we send out packets to query selection-relevant informations from supernodes. */ #define NUMBER_SN_PINGS_INITIAL 15 /* number of supernodes to concurrently ping during bootstrap and immediately afterwards */ #define NUMBER_SN_PINGS_REGULAR 5 /* number of supernodes to concurrently ping during regular edge operation */ /* Timeouts used in re_register_and_purge_supernodes. LAST_SEEN_SN_ACTIVE and LAST_SEEN_SN_INACTIVE * values should be at least 3*SOCKET_TIMEOUT_INTERVAL_SECS apart. */ #define LAST_SEEN_SN_ACTIVE 20 /* sec, indicates supernodes that are proven to be active */ #define LAST_SEEN_SN_INACTIVE 90 /* sec, indicates supernodes that are proven to be inactive: they will be purged */ #define LAST_SEEN_SN_NEW (LAST_SEEN_SN_INACTIVE - 3 * RE_REG_AND_PURGE_FREQUENCY) /* sec, indicates supernodes with unsure status, must be tested to check if they are active */ #define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ #define TRANSOP_TICK_INTERVAL (10) /* sec */ #define SORT_COMMUNITIES_INTERVAL 90 /* sec. until supernode sorts communities' hash list again */ #define AF_INVALID -1 /* to mark a socket invalid by an invalid address family (do not use AF_UNSPEC, it could turn into auto-detect) */ #define N2N_RESOLVE_INTERVAL 300 /* seconds until edge and supernode try to resolve supernode names again */ #define N2N_RESOLVE_CHECK_INTERVAL 30 /* seconds until main loop checking in on changes from resolver thread */ #define ETH_FRAMESIZE 14 #define IP4_SRCOFFSET 12 #define IP4_DSTOFFSET 16 #define IP4_MIN_SIZE 20 #define UDP_SIZE 8 /* parameters for replay protection */ #define TIME_STAMP_FRAME 0x0000001000000000LL /* clocks of different computers are allowed +/- 16 seconds to be off */ #define TIME_STAMP_JITTER 0x0000000027100000LL /* we allow a packet to arrive 160 ms (== 0x27100 us) before another * set to 0x0000000000000000LL if increasing (or equal) time stamps allowed only */ #define TIME_STAMP_ALLOW_JITTER 1 /* constant for allowing or... */ #define TIME_STAMP_NO_JITTER 0 /* not allowing jitter to be considered */ /* N2N compression indicators. */ /* Compression is disabled by default for outgoing packets if no cli * option is given. All edges are built with decompression support so * they are able to understand each other (this applies to lzo only). */ #define N2N_COMPRESSION_ID_INVALID 0 #define N2N_COMPRESSION_ID_NONE 1 /* default, see edge_init_conf_defaults(...) in edge_utils.c */ #define N2N_COMPRESSION_ID_LZO 2 /* set if '-z1' or '-z' cli option is present, see setOption(...) in edge.c */ #define N2N_COMPRESSION_ID_ZSTD 3 /* set if '-z2' cli option is present, available only if compiled with zstd lib */ #define ZSTD_COMPRESSION_LEVEL 7 /* 1 (faster) ... 22 (more compression) */ /* Federation name and indicators */ #define FEDERATION_NAME "*Federation" enum federation {IS_NO_FEDERATION = 0,IS_FEDERATION = 1}; /* (un)purgeable community indicator (supernode) */ #define COMMUNITY_UNPURGEABLE 0 #define COMMUNITY_PURGEABLE 1 /* (un)purgeable supernode indicator */ enum sn_purge {SN_PURGEABLE = 0, SN_UNPURGEABLE = 1}; /* Header encryption indicators */ #define HEADER_ENCRYPTION_UNKNOWN 0 #define HEADER_ENCRYPTION_NONE 1 #define HEADER_ENCRYPTION_ENABLED 2 /* REGISTER_SUPER_ACK packet hash length with user/pw auth, up to 16 bytes */ #define N2N_REG_SUP_HASH_CHECK_LEN 16 #define DEFAULT_MTU 1290 #define HASH_ADD_PEER(head,add) \ HASH_ADD(hh,head,mac_addr,sizeof(n2n_mac_t),add) #define HASH_FIND_PEER(head,mac,out) \ HASH_FIND(hh,head,mac,sizeof(n2n_mac_t),out) #define N2N_EDGE_SN_HOST_SIZE 48 #define N2N_EDGE_SUP_ATTEMPTS 3 /* Number of failed attmpts before moving on to next supernode. */ #define N2N_PATHNAME_MAXLEN 256 #define N2N_EDGE_MGMT_PORT 5644 #define N2N_SN_MGMT_PORT 5645 enum n2n_event_topic { N2N_EVENT_DEBUG = 0, N2N_EVENT_TEST = 1, N2N_EVENT_PEER = 2, }; #define N2N_EVENT_PEER_PURGE 1 #define N2N_EVENT_PEER_CLEAR 2 #define N2N_EVENT_PEER_DEL_P2P 3 #define N2N_EVENT_PEER_ADD_P2P 4 #define N2N_MGMT_PASSWORD "n2n" /* default password for management port access (so far, json only) */ #define N2N_TCP_BACKLOG_QUEUE_SIZE 3 /* number of concurrently pending connections to be accepted */ /* NOT the number of max. TCP connections */ #define N2N_CLOSE_SOCKET_COUNTER_MAX 15 /* number of times of edge's reconnects to supernode after */ /* which the socket explicitly is closed before reopening */ /* flag used in add_sn_to_list_by_mac_or_sock */ enum skip_add {SN_ADD = 0, SN_ADD_SKIP = 1, SN_ADD_ADDED = 2}; #define N2N_NETMASK_STR_SIZE 16 /* dotted decimal 12 numbers + 3 dots */ #define N2N_MACNAMSIZ 18 /* AA:BB:CC:DD:EE:FF + NULL*/ #define N2N_IF_MODE_SIZE 16 /* static | dhcp */ #define N2N_EDGE_DEFAULT_DEV_NAME "edge0" #define N2N_EDGE_DEFAULT_NETMASK "255.255.255.0" /* default netmask for edge ip address... */ #define N2N_EDGE_DEFAULT_CIDR_NM 24 /* ... also in cidr format */ #define N2N_SN_LPORT_DEFAULT 7654 #define N2N_SN_PKTBUF_SIZE 2048 /* The way TUNTAP allocated IP. */ #define TUNTAP_IP_MODE_SN_ASSIGN 0 #define TUNTAP_IP_MODE_STATIC 1 #define TUNTAP_IP_MODE_DHCP 2 /* Default network segment of the auto ip address service provided by sn. */ #define N2N_SN_MIN_AUTO_IP_NET_DEFAULT "10.128.0.0" #define N2N_SN_MAX_AUTO_IP_NET_DEFAULT "10.255.255.0" #define N2N_SN_AUTO_IP_NET_BIT_DEFAULT 24 /* ************************************** */ #define SUPERNODE_IP "127.0.0.1" #define SUPERNODE_PORT 1234 /* ************************************** */ #define N2N_PKT_VERSION 3 #define N2N_DEFAULT_TTL 2 /* can be forwarded twice at most */ #define N2N_COMMUNITY_SIZE 20 #define N2N_PRIVATE_PUBLIC_KEY_SIZE 32 #define N2N_USER_KEY_LINE_STARTER '*' #define N2N_MAC_SIZE 6 #define N2N_NO_REG_COOKIE 0x00000000 #define N2N_FORWARDED_REG_COOKIE 0x00001000 #define N2N_PORT_REG_COOKIE 0x00004000 #define N2N_REGULAR_REG_COOKIE 0x00010000 #define N2N_MCAST_REG_COOKIE 0x00400000 #define N2N_LOCAL_REG_COOKIE 0x01000000 #define N2N_DESC_SIZE 16 #define N2N_PKT_BUF_SIZE 2048 #define N2N_SOCKBUF_SIZE 64 /* string representation of INET or INET6 sockets */ #define N2N_MULTICAST_PORT 1968 #define N2N_MULTICAST_GROUP "224.0.0.68" #ifdef WIN32 #define N2N_IFNAMSIZ 64 #else #define N2N_IFNAMSIZ 16 /* 15 chars * NULL */ #endif #ifdef _MSC_VER #define N2N_THREAD_RETURN_DATATYPE DWORD WINAPI #define N2N_THREAD_PARAMETER_DATATYPE LPVOID #else #define N2N_THREAD_RETURN_DATATYPE void* #define N2N_THREAD_PARAMETER_DATATYPE void* #endif #define SN_SELECTION_CRITERION_DATA_TYPE uint64_t #define SN_SELECTION_CRITERION_BUF_SIZE 16 #define N2N_TRANSFORM_ID_USER_START 64 #define N2N_TRANSFORM_ID_MAX 65535 #ifndef max #define max(a, b) (((a) < (b)) ? (b) : (a)) #endif #ifndef min #define min(a, b) (((a) >(b)) ? (b) : (a)) #endif ntop-n2n-90215bd/include/n2n_port_mapping.h000066400000000000000000000026361422132035700205730ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #ifndef _N2N_PORT_MAPPING_H_ #define _N2N_PORT_MAPPING_H_ #ifdef HAVE_PORT_FORWARDING #include #ifdef HAVE_MINIUPNP #ifdef CMAKE_BUILD // CMAKE uses static linked lib as submodule which requires different includes than // the dynamically linked, intalled library in case of plain make #include #include #include #else #include #include #include #endif // CMAKE_BUILD #endif // HAVE_MINIUPNP #ifdef HAVE_NATPMP #include "natpmp.h" #endif // HAVE_NATPMP void n2n_chg_port_mapping (struct n2n_edge *eee, const uint16_t port); #endif // HAVE_PORT_FORWARDING #endif // _N2N_PORT_MAPPING_H_ ntop-n2n-90215bd/include/n2n_regex.h000066400000000000000000000044241422132035700172030ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // taken from https://github.com/kokke/tiny-regex-c // under Unlicense as of August 4, 2020 /* * * Mini regex-module inspired by Rob Pike's regex code described in: * * http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html * * * * Supports: * --------- * '.' Dot, matches any character * '^' Start anchor, matches beginning of string * '$' End anchor, matches end of string * '*' Asterisk, match zero or more (greedy) * '+' Plus, match one or more (greedy) * '?' Question, match zero or one (non-greedy) * '[abc]' Character class, match if one of {'a', 'b', 'c'} * '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} -- NOTE: feature is currently broken! * '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z } * '\s' Whitespace, \t \f \r \n \v and spaces * '\S' Non-whitespace * '\w' Alphanumeric, [a-zA-Z0-9_] * '\W' Non-alphanumeric * '\d' Digits, [0-9] * '\D' Non-digits * * */ #ifndef _N2N_REGEX_ #define _N2N_REGEX_ #ifdef __cplusplus extern "C" { #endif #include /* Compile regex string pattern to a regex_t-array. */ re_t re_compile (const char* pattern); /* Find matches of the compiled pattern inside text. */ int re_matchp (re_t pattern, const char* text, int* matchlenght); /* Find matches of the txt pattern inside text (will compile automatically first). */ int re_match (const char* pattern, const char* text, int* matchlenght); #ifdef __cplusplus } #endif #endif ntop-n2n-90215bd/include/n2n_typedefs.h000066400000000000000000001077541422132035700177260ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #ifndef _N2N_TYPEDEFS_H_ #define _N2N_TYPEDEFS_H_ typedef uint8_t n2n_community_t[N2N_COMMUNITY_SIZE]; typedef uint8_t n2n_private_public_key_t[N2N_PRIVATE_PUBLIC_KEY_SIZE]; typedef uint8_t n2n_mac_t[N2N_MAC_SIZE]; typedef uint32_t n2n_cookie_t; typedef uint8_t n2n_desc_t[N2N_DESC_SIZE]; typedef char n2n_sock_str_t[N2N_SOCKBUF_SIZE]; /* tracing string buffer */ #if defined(_MSC_VER) || defined(__MINGW32__) #include "getopt.h" /* Other Win environments are expected to support stdint.h */ /* stdint.h typedefs (C99) (not present in Visual Studio) */ typedef unsigned int uint32_t; typedef unsigned short uint16_t; typedef unsigned char uint8_t; /* sys/types.h typedefs (not present in Visual Studio) */ typedef unsigned int u_int32_t; typedef unsigned short u_int16_t; typedef unsigned char u_int8_t; #ifndef __MINGW32__ typedef int ssize_t; #endif typedef unsigned long in_addr_t; #include "n2n_win32.h" #endif /* #if defined(_MSC_VER) || defined(__MINGW32__) */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #endif #ifdef __OpenBSD__ #include #define __BYTE_ORDER BYTE_ORDER #if BYTE_ORDER == LITTLE_ENDIAN #ifndef __LITTLE_ENDIAN__ #define __LITTLE_ENDIAN__ #endif /* __LITTLE_ENDIAN__ */ #else #define __BIG_ENDIAN__ #endif/* BYTE_ORDER */ #endif/* __OPENBSD__ */ #if __BYTE_ORDER == __LITTLE_ENDIAN #ifndef __LITTLE_ENDIAN__ #define __LITTLE_ENDIAN__ #endif #else #ifndef __BIG_ENDIAN__ #define __BIG_ENDIAN__ #endif #endif #ifdef WIN32 #ifndef __LITTLE_ENDIAN__ #define __LITTLE_ENDIAN__ 1 #endif #endif #if !(defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__)) #if defined(__mips__) #undef __LITTLE_ENDIAN__ #undef __LITTLE_ENDIAN #define __BIG_ENDIAN__ #endif /* Everything else */ #if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)) #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define __LITTLE_ENDIAN__ #else #define __BIG_ENDIAN__ #endif #endif #endif /* *************************************** */ #ifdef __GNUC__ #define PACK_STRUCT __attribute__((__packed__)) #else #define PACK_STRUCT #endif #if defined(_MSC_VER) || defined(__MINGW32__) #pragma pack(push,1) #endif // those are definitely not typedefs (with a view to the filename) but neither are they defines static const n2n_mac_t broadcast_mac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const n2n_mac_t multicast_mac = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; /* First 3 bytes are meaningful */ static const n2n_mac_t ipv6_multicast_mac = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; /* First 2 bytes are meaningful */ static const n2n_mac_t null_mac = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #define ETH_ADDR_LEN 6 struct ether_hdr { uint8_t dhost[ETH_ADDR_LEN]; uint8_t shost[ETH_ADDR_LEN]; uint16_t type; /* higher layer protocol encapsulated */ } PACK_STRUCT; typedef struct ether_hdr ether_hdr_t; struct n2n_iphdr { #if defined(__LITTLE_ENDIAN__) u_int8_t ihl:4, version:4; #elif defined(__BIG_ENDIAN__) u_int8_t version:4, ihl:4; #else # error "Byte order must be defined" #endif u_int8_t tos; u_int16_t tot_len; u_int16_t id; u_int16_t frag_off; u_int8_t ttl; u_int8_t protocol; u_int16_t check; u_int32_t saddr; u_int32_t daddr; } PACK_STRUCT; struct n2n_tcphdr { u_int16_t source; u_int16_t dest; u_int32_t seq; u_int32_t ack_seq; #if defined(__LITTLE_ENDIAN__) u_int16_t res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; #elif defined(__BIG_ENDIAN__) u_int16_t doff:4, res1:4, cwr:1, ece:1, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1; #else # error "Byte order must be defined" #endif u_int16_t window; u_int16_t check; u_int16_t urg_ptr; } PACK_STRUCT; struct n2n_udphdr { u_int16_t source; u_int16_t dest; u_int16_t len; u_int16_t check; } PACK_STRUCT; #if defined(_MSC_VER) || defined(__MINGW32__) #pragma pack(pop) #endif typedef struct port_range { uint16_t start_port; // range contain 'start_port' self uint16_t end_port; // range contain 'end_port' self } port_range_t; typedef struct filter_rule_key { in_addr_t src_net_cidr; uint8_t src_net_bit_len; port_range_t src_port_range; in_addr_t dst_net_cidr; uint8_t dst_net_bit_len; port_range_t dst_port_range; uint8_t bool_tcp_configured; uint8_t bool_udp_configured; uint8_t bool_icmp_configured; } filter_rule_key_t; typedef struct filter_rule { filter_rule_key_t key; uint8_t bool_accept_icmp; uint8_t bool_accept_udp; uint8_t bool_accept_tcp; UT_hash_handle hh; /* makes this structure hashable */ } filter_rule_t; #ifndef WIN32 typedef struct tuntap_dev { int fd; int if_idx; n2n_mac_t mac_addr; uint32_t ip_addr; uint32_t device_mask; uint16_t mtu; char dev_name[N2N_IFNAMSIZ]; } tuntap_dev; #define SOCKET int #endif /* #ifndef WIN32 */ /** Uncomment this to enable the MTU check, then try to ssh to generate a fragmented packet. */ /** NOTE: see doc/MTU.md for an explanation on the 1400 value */ //#define MTU_ASSERT_VALUE 1400 /** Common type used to hold stringified IP addresses. */ typedef char ipstr_t[32]; /** Common type used to hold stringified MAC addresses. */ #define N2N_MACSTR_SIZE 32 typedef char macstr_t[N2N_MACSTR_SIZE]; typedef char dec_ip_str_t[N2N_NETMASK_STR_SIZE]; typedef char dec_ip_bit_str_t[N2N_NETMASK_STR_SIZE + 4]; typedef struct speck_context_t he_context_t; typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; typedef enum n2n_pc { n2n_ping = 0, /* Not used */ n2n_register = 1, /* Register edge to edge */ n2n_deregister = 2, /* Deregister this edge */ n2n_packet = 3, /* PACKET data content */ n2n_register_ack = 4, /* ACK of a registration from edge to edge */ n2n_register_super = 5, /* Register edge to supernode */ n2n_unregister_super = 6, /* Deregister edge from supernode */ n2n_register_super_ack = 7, /* ACK from supernode to edge */ n2n_register_super_nak = 8, /* NAK from supernode to edge - registration refused */ n2n_federation = 9, /* Not used by edge */ n2n_peer_info = 10, /* Send info on a peer from sn to edge */ n2n_query_peer = 11, /* ask supernode for info on a peer */ n2n_re_register_super = 12 /* ask edge to re-register with supernode */ } n2n_pc_t; #define N2N_FLAGS_OPTIONS 0x0080 #define N2N_FLAGS_SOCKET 0x0040 #define N2N_FLAGS_FROM_SUPERNODE 0x0020 /* The bits in flag that are the packet type */ #define N2N_FLAGS_TYPE_MASK 0x001f /* 0 - 31 */ #define N2N_FLAGS_BITS_MASK 0xffe0 #define IPV4_SIZE 4 #define IPV6_SIZE 16 #define N2N_AUTH_MAX_TOKEN_SIZE 48 /* max token size in bytes */ #define N2N_AUTH_CHALLENGE_SIZE 16 /* challenge always is of same size as dynamic key */ #define N2N_AUTH_ID_TOKEN_SIZE 16 #define N2N_AUTH_PW_TOKEN_SIZE (N2N_PRIVATE_PUBLIC_KEY_SIZE + N2N_AUTH_CHALLENGE_SIZE) #define N2N_EUNKNOWN -1 #define N2N_ENOTIMPL -2 #define N2N_EINVAL -3 #define N2N_ENOSPACE -4 #define N2N_VERSION_STRING_SIZE 20 typedef char n2n_version_t[N2N_VERSION_STRING_SIZE]; #define SN_SELECTION_STRATEGY_LOAD 1 #define SN_SELECTION_STRATEGY_RTT 2 #define SN_SELECTION_STRATEGY_MAC 3 typedef struct n2n_ip_subnet { uint32_t net_addr; /* Host order IP address. */ uint8_t net_bitlen; /* Subnet prefix. */ } n2n_ip_subnet_t; typedef struct n2n_sock { uint8_t family; /* AF_INET or AF_INET6; or 0 if invalid */ uint16_t port; /* host order */ union { uint8_t v6[IPV6_SIZE]; /* byte sequence */ uint8_t v4[IPV4_SIZE]; /* byte sequence */ } addr; } n2n_sock_t; typedef enum { n2n_auth_none = 0, n2n_auth_simple_id = 1, n2n_auth_user_password = 2 } n2n_auth_scheme_t; typedef enum { update_edge_no_change = 0, update_edge_sock_change = 1, update_edge_new_sn = 2, update_edge_auth_fail = -1 } update_edge_ret_value_t; typedef struct n2n_auth { uint16_t scheme; /* What kind of auth */ uint16_t token_size; /* Size of auth token */ uint8_t token[N2N_AUTH_MAX_TOKEN_SIZE]; /* Auth data interpreted based on scheme */ } n2n_auth_t; typedef struct n2n_common { /* NOTE: wire representation is different! */ /* int version; */ uint8_t ttl; uint8_t pc; uint16_t flags; n2n_community_t community; } n2n_common_t; typedef struct n2n_REGISTER { n2n_cookie_t cookie; /**< Link REGISTER and REGISTER_ACK */ n2n_mac_t srcMac; /**< MAC of registering party */ n2n_mac_t dstMac; /**< MAC of target edge */ n2n_sock_t sock; /**< Supernode's view of edge socket OR edge's preferred local socket */ n2n_ip_subnet_t dev_addr; /**< IP address of the tuntap adapter. */ n2n_desc_t dev_desc; /**< Hint description correlated with the edge */ } n2n_REGISTER_t; typedef struct n2n_REGISTER_ACK { n2n_cookie_t cookie; /**< Return cookie from REGISTER */ n2n_mac_t srcMac; /**< MAC of acknowledging party (supernode or edge) */ n2n_mac_t dstMac; /**< Reflected MAC of registering edge from REGISTER */ n2n_sock_t sock; /**< Supernode's view of edge socket (IP Addr, port) */ } n2n_REGISTER_ACK_t; typedef struct n2n_PACKET { n2n_mac_t srcMac; n2n_mac_t dstMac; n2n_sock_t sock; uint8_t transform; uint8_t compression; } n2n_PACKET_t; /* Linked with n2n_register_super in n2n_pc_t. Only from edge to supernode. */ typedef struct n2n_REGISTER_SUPER { n2n_cookie_t cookie; /**< Link REGISTER_SUPER and REGISTER_SUPER_ACK */ n2n_mac_t edgeMac; /**< MAC to register with edge sending socket */ n2n_sock_t sock; /**< Sending socket associated with edgeMac */ n2n_ip_subnet_t dev_addr; /**< IP address of the tuntap adapter. */ n2n_desc_t dev_desc; /**< Hint description correlated with the edge */ n2n_auth_t auth; /**< Authentication scheme and tokens */ uint32_t key_time; /**< key time for dynamic key, used between federatred supernodes only */ } n2n_REGISTER_SUPER_t; /* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ typedef struct n2n_REGISTER_SUPER_ACK { n2n_cookie_t cookie; /**< Return cookie from REGISTER_SUPER */ n2n_mac_t srcMac; /**< MAC of answering supernode */ n2n_ip_subnet_t dev_addr; /**< Assign an IP address to the tuntap adapter of edge. */ uint16_t lifetime; /**< How long the registration will live */ n2n_sock_t sock; /**< Sending sockets associated with edge */ n2n_auth_t auth; /**< Authentication scheme and tokens */ /** The packet format provides additional supernode definitions here. * uint8_t count, then for each count there is one * n2n_sock_t. */ uint8_t num_sn; /**< Number of supernodes that were send * even if we cannot store them all. */ uint32_t key_time; /**< key time for dynamic key, used between federatred supernodes only */ } n2n_REGISTER_SUPER_ACK_t; /* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ typedef struct n2n_REGISTER_SUPER_NAK { n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ n2n_mac_t srcMac; n2n_auth_t auth; /* Authentication scheme and tokens */ } n2n_REGISTER_SUPER_NAK_t; /* REGISTER_SUPER_ACK may contain extra payload (their number given by num_sn) * of following type describing a(nother) supernode */ typedef struct n2n_REGISTER_SUPER_ACK_payload { n2n_sock_t sock; /**< socket of supernode */ n2n_mac_t mac; /**< MAC of supernode */ } n2n_REGISTER_SUPER_ACK_payload_t; /* Linked with n2n_unregister_super in n2n_pc_t. */ typedef struct n2n_UNREGISTER_SUPER { n2n_auth_t auth; n2n_mac_t srcMac; } n2n_UNREGISTER_SUPER_t; typedef struct n2n_PEER_INFO { uint16_t aflags; n2n_mac_t srcMac; n2n_mac_t mac; n2n_sock_t sock; n2n_sock_t preferred_sock; uint32_t load; n2n_version_t version; time_t uptime; } n2n_PEER_INFO_t; typedef struct n2n_QUERY_PEER { uint16_t aflags; n2n_mac_t srcMac; n2n_sock_t sock; n2n_mac_t targetMac; } n2n_QUERY_PEER_t; typedef struct n2n_buf n2n_buf_t; struct peer_info { n2n_mac_t mac_addr; n2n_ip_subnet_t dev_addr; n2n_desc_t dev_desc; n2n_sock_t sock; SOCKET socket_fd; n2n_sock_t preferred_sock; n2n_cookie_t last_cookie; n2n_auth_t auth; int timeout; uint8_t purgeable; time_t last_seen; time_t last_p2p; time_t last_sent_query; SN_SELECTION_CRITERION_DATA_TYPE selection_criterion; uint64_t last_valid_time_stamp; char *ip_addr; uint8_t local; time_t uptime; n2n_version_t version; UT_hash_handle hh; /* makes this structure hashable */ }; typedef struct peer_info peer_info_t; typedef struct n2n_route { in_addr_t net_addr; uint8_t net_bitlen; in_addr_t gateway; } n2n_route_t; typedef struct n2n_edge n2n_edge_t; /* *************************************************** */ typedef enum { N2N_ACCEPT = 0, N2N_DROP = 1 } n2n_verdict; /* *************************************************** */ typedef enum { FPP_UNKNOWN = 0, FPP_ARP = 1, FPP_TCP = 2, FPP_UDP = 3, FPP_ICMP = 4, FPP_IGMP = 5 } filter_packet_proto; typedef struct packet_address_proto_info { in_addr_t src_ip; uint16_t src_port; in_addr_t dst_ip; uint16_t dst_port; filter_packet_proto proto; }packet_address_proto_info_t; typedef struct filter_rule_pair_cache { packet_address_proto_info_t key; uint8_t bool_allow_traffic; uint32_t active_count; UT_hash_handle hh; /* makes this structure hashable */ } filter_rule_pair_cache_t; struct network_traffic_filter; typedef struct network_traffic_filter network_traffic_filter_t; struct network_traffic_filter { n2n_verdict (*filter_packet_from_peer)(network_traffic_filter_t* filter, n2n_edge_t *eee, const n2n_sock_t *peer, uint8_t *payload, uint16_t payload_size); n2n_verdict (*filter_packet_from_tap)(network_traffic_filter_t* filter, n2n_edge_t *eee, uint8_t *payload, uint16_t payload_size); filter_rule_t *rules; filter_rule_pair_cache_t *connections_rule_cache; uint32_t work_count_scene_last_clear; }; /* *************************************************** */ /* Callbacks allow external programs to attach functions in response to * N2N events. */ typedef struct n2n_edge_callbacks { /* The supernode registration has been updated */ void (*sn_registration_updated)(n2n_edge_t *eee, time_t now, const n2n_sock_t *sn); /* A packet has been received from a peer. N2N_DROP can be returned to * drop the packet. The packet payload can be modified. This only allows * the packet size to be reduced */ n2n_verdict (*packet_from_peer)(n2n_edge_t *eee, const n2n_sock_t *peer, uint8_t *payload, uint16_t *payload_size); /* A packet has been received from the TAP interface. N2N_DROP can be * returned to drop the packet. The packet payload can be modified. * This only allows the packet size to be reduced */ n2n_verdict (*packet_from_tap)(n2n_edge_t *eee, uint8_t *payload, uint16_t *payload_size); /* Called whenever the IP address of the TAP interface changes. */ void (*ip_address_changed)(n2n_edge_t *eee, uint32_t old_ip, uint32_t new_ip); /* Called periodically in the main loop. */ void (*main_loop_period)(n2n_edge_t *eee, time_t now); /* Called when a new socket to supernode is created. */ void (*sock_opened)(n2n_edge_t *eee); } n2n_edge_callbacks_t; typedef struct n2n_tuntap_priv_config { char tuntap_dev_name[N2N_IFNAMSIZ]; char ip_mode[N2N_IF_MODE_SIZE]; dec_ip_str_t ip_addr; dec_ip_str_t netmask; char device_mac[N2N_MACNAMSIZ]; int mtu; int metric; uint8_t daemon; #ifndef WIN32 uid_t userid; gid_t groupid; #endif } n2n_tuntap_priv_config_t; /* *************************************************** */ typedef enum n2n_transform { N2N_TRANSFORM_ID_INVAL = 0, N2N_TRANSFORM_ID_NULL = 1, N2N_TRANSFORM_ID_TWOFISH = 2, N2N_TRANSFORM_ID_AES = 3, N2N_TRANSFORM_ID_CHACHA20 = 4, N2N_TRANSFORM_ID_SPECK = 5, } n2n_transform_t; struct n2n_trans_op; /* Circular definition */ typedef int (*n2n_transdeinit_f)(struct n2n_trans_op * arg); typedef void (*n2n_transtick_f)(struct n2n_trans_op * arg, time_t now); typedef int (*n2n_transform_f)(struct n2n_trans_op * arg, uint8_t * outbuf, size_t out_len, const uint8_t * inbuf, size_t in_len, const n2n_mac_t peer_mac); /** Holds the info associated with a data transform plugin. * * When a packet arrives the transform ID is extracted. This defines the code * to use to decode the packet content. The transform code then decodes the * packet and consults its internal key lookup. */ typedef struct n2n_trans_op { void * priv; /* opaque data. Key schedule goes here. */ uint8_t no_encryption; /* 1 if this transop does not perform encryption */ n2n_transform_t transform_id; size_t tx_cnt; size_t rx_cnt; n2n_transdeinit_f deinit; /* destructor function */ n2n_transtick_f tick; /* periodic maintenance */ n2n_transform_f fwd; /* encode a payload */ n2n_transform_f rev; /* decode a payload */ } n2n_trans_op_t; /* *************************************************** */ typedef struct n2n_resolve_ip_sock { char *org_ip; /* pointer to original ip/named address string (used read only) */ n2n_sock_t sock; /* resolved socket */ n2n_sock_t *org_sock; /* pointer to original socket where 'sock' gets copied to from time to time */ int error_code; /* result of last resolution attempt */ UT_hash_handle hh; /* makes this structure hashable */ } n2n_resolve_ip_sock_t; // structure to hold resolver thread's parameters typedef struct n2n_resolve_parameter { n2n_resolve_ip_sock_t *list; /* pointer to list of to be resolved nodes */ uint8_t changed; /* indicates a change */ #ifdef HAVE_PTHREAD pthread_t id; /* thread id */ pthread_mutex_t access; /* mutex for shared access */ #endif uint8_t request; /* flags main thread's need for intermediate resolution */ time_t check_interval;/* interval to checik resolover results */ time_t last_checked; /* last time the resolver results were cheked */ time_t last_resolved; /* last time the resolver completed */ } n2n_resolve_parameter_t; /* *************************************************** */ // structure to hold port mapping thread's parameters typedef struct n2n_port_map_parameter { #ifdef HAVE_PTHREAD pthread_t id; /* thread id */ pthread_mutex_t access; /* mutex for shared access */ #endif uint16_t mgmt_port; uint16_t mapped_port; uint16_t new_port; /* REVISIT: remove with management port subscriptions */ } n2n_port_map_parameter_t; /* *************************************************** */ typedef struct n2n_edge_conf { struct peer_info *supernodes; /**< List of supernodes */ n2n_route_t *routes; /**< Networks to route through n2n */ n2n_community_t community_name; /**< The community. 16 full octets. */ n2n_desc_t dev_desc; /**< The device description (hint) */ n2n_private_public_key_t *public_key; /**< edge's public key (for user/password based authentication) */ n2n_private_public_key_t *shared_secret; /**< shared secret derived from federation public key, username and password */ he_context_t *shared_secret_ctx; /**< context holding the roundkeys derived from shared secret */ n2n_private_public_key_t *federation_public_key; /**< federation public key provided by command line */ uint8_t header_encryption; /**< Header encryption indicator. */ he_context_t *header_encryption_ctx_static; /**< Header encryption cipher context. */ he_context_t *header_encryption_ctx_dynamic; /**< Header encryption cipher context. */ he_context_t *header_iv_ctx_static; /**< Header IV ecnryption cipher context, REMOVE as soon as separate fileds for checksum and replay protection available */ he_context_t *header_iv_ctx_dynamic; /**< Header IV ecnryption cipher context, REMOVE as soon as separate fileds for checksum and replay protection available */ n2n_transform_t transop_id; /**< The transop to use. */ uint8_t compression; /**< Compress outgoing data packets before encryption */ uint16_t num_routes; /**< Number of routes in routes */ uint8_t tuntap_ip_mode; /**< Interface IP address allocated mode, eg. DHCP. */ uint8_t allow_routing; /**< Accept packet no to interface address. */ uint8_t drop_multicast; /**< Multicast ethernet addresses. */ uint8_t disable_pmtu_discovery; /**< Disable the Path MTU discovery. */ uint8_t allow_p2p; /**< Allow P2P connection */ uint8_t sn_num; /**< Number of supernode addresses defined. */ uint8_t tos; /** TOS for sent packets */ char *encrypt_key; int register_interval; /**< Interval for supernode registration, also used for UDP NAT hole punching. */ int register_ttl; /**< TTL for registration packet when UDP NAT hole punching through supernode. */ in_addr_t bind_address; /**< The address to bind to if provided (-b) */ n2n_sock_t preferred_sock; /**< propagated local sock for better p2p in LAN (-e) */ uint8_t preferred_sock_auto; /**< indicates desired auto detect for preferred sock */ int local_port; int mgmt_port; uint8_t connect_tcp; /** connection to supernode 0 = UDP; 1 = TCP */ n2n_auth_t auth; filter_rule_t *network_traffic_filter_rules; int metric; /**< Network interface metric (Windows only). */ uint8_t sn_selection_strategy; /**< encodes currently chosen supernode selection strategy. */ uint8_t number_max_sn_pings; /**< Number of maximum concurrently allowed supernode pings. */ uint64_t mgmt_password_hash; /**< contains hash of managament port password. */ uint8_t port_forwarding; /**< indicates if port forwarding UPNP/PMP is enabled */ } n2n_edge_conf_t; struct n2n_edge_stats { uint32_t tx_p2p; uint32_t rx_p2p; uint32_t tx_sup; uint32_t rx_sup; uint32_t tx_sup_broadcast; uint32_t rx_sup_broadcast; }; struct n2n_edge { n2n_edge_conf_t conf; /* Status */ int *keep_running; /**< Pointer to edge loop stop/go flag */ struct peer_info *curr_sn; /**< Currently active supernode. */ uint8_t sn_wait; /**< Whether we are waiting for a supernode response. */ uint8_t sn_pong; /**< Whether we have seen a PONG since last time reset. */ size_t sup_attempts; /**< Number of remaining attempts to this supernode. */ tuntap_dev device; /**< All about the TUNTAP device */ n2n_trans_op_t transop; /**< The transop to use when encoding */ n2n_trans_op_t transop_lzo; /**< The transop for LZO compression */ #ifdef HAVE_ZSTD n2n_trans_op_t transop_zstd; /**< The transop for ZSTD compression */ #endif n2n_route_t *sn_route_to_clean; /**< Supernode route to clean */ n2n_edge_callbacks_t cb; /**< API callbacks */ void *user_data; /**< Can hold user data */ SN_SELECTION_CRITERION_DATA_TYPE sn_selection_criterion_common_data; /* Sockets */ /* supernode socket is in eee->curr_sn->sock (of type n2n_sock_t) */ int sock; int close_socket_counter; /**< counter for close-event before re-opening */ int udp_mgmt_sock; /**< socket for status info. */ #ifndef SKIP_MULTICAST_PEERS_DISCOVERY n2n_sock_t multicast_peer; /**< Multicast peer group (for local edges) */ int udp_multicast_sock; /**< socket for local multicast registrations. */ int multicast_joined; /**< 1 if the group has been joined.*/ #endif /* Peers */ struct peer_info * known_peers; /**< Edges we are connected to. */ struct peer_info * pending_peers; /**< Edges we have tried to register with. */ /* Timers */ time_t last_register_req; /**< Check if time to re-register with super*/ time_t last_p2p; /**< Last time p2p traffic was received. */ time_t last_sup; /**< Last time a packet arrived from supernode. */ time_t last_sweep; /**< Last time a sweep was performed. */ time_t start_time; /**< For calculating uptime */ struct n2n_edge_stats stats; /**< Statistics */ n2n_resolve_parameter_t *resolve_parameter; /**< Pointer to name resolver's parameter block */ uint8_t resolution_request; /**< Flag an immediate DNS resolution request */ n2n_port_map_parameter_t *port_map_parameter; /**< Pointer to port mapping thread's parameter block */ n2n_tuntap_priv_config_t tuntap_priv_conf; /**< Tuntap config */ network_traffic_filter_t *network_traffic_filter; }; typedef struct sn_stats { size_t errors; /* Number of errors encountered. */ size_t reg_super; /* Number of REGISTER_SUPER requests received. */ size_t reg_super_nak; /* Number of REGISTER_SUPER requests declined. */ size_t fwd; /* Number of messages forwarded. */ size_t broadcast; /* Number of messages broadcast to a community. */ time_t last_fwd; /* Time when last message was forwarded. */ time_t last_reg_super; /* Time when last REGISTER_SUPER was received. */ } sn_stats_t; typedef struct node_supernode_association { n2n_mac_t mac; /* mac address of an edge */ const struct sockaddr_in sock; /* network order socket of that edge's supernode */ time_t last_seen; /* time mark to keep track of purging requirements */ UT_hash_handle hh; /* makes this structure hashable */ } node_supernode_association_t; typedef struct sn_user { n2n_private_public_key_t public_key; n2n_private_public_key_t shared_secret; he_context_t *shared_secret_ctx; n2n_desc_t name; UT_hash_handle hh; } sn_user_t; struct sn_community { char community[N2N_COMMUNITY_SIZE]; uint8_t is_federation; /* if not-zero, then the current community is the federation of supernodes */ uint8_t purgeable; /* indicates purgeable community (fixed-name, predetermined (-c parameter) communties usually are unpurgeable) */ uint8_t header_encryption; /* Header encryption indicator. */ he_context_t *header_encryption_ctx_static; /* Header encryption cipher context. */ he_context_t *header_encryption_ctx_dynamic; /* Header encryption cipher context. */ he_context_t *header_iv_ctx_static; /* Header IV encryption cipher context, REMOVE as soon as separate fields for checksum and replay protection available */ he_context_t *header_iv_ctx_dynamic; /* Header IV encryption cipher context, REMOVE as soon as separate fields for checksum and replay protection available */ uint8_t dynamic_key[N2N_AUTH_CHALLENGE_SIZE]; /* dynamic key */ struct peer_info *edges; /* Link list of registered edges. */ node_supernode_association_t *assoc; /* list of other edges from this community and their supernodes */ sn_user_t *allowed_users; /* list of allowed users */ int64_t number_enc_packets; /* Number of encrypted packets handled so far, required for sorting from time to time */ n2n_ip_subnet_t auto_ip_net; /* Address range of auto ip address service. */ UT_hash_handle hh; /* makes this structure hashable */ }; /* Typedef'd pointer to get abstract datatype. */ typedef struct regex_t* re_t; struct sn_community_regular_expression { re_t rule; /* compiles regular expression */ UT_hash_handle hh; /* makes this structure hashable */ }; typedef struct n2n_tcp_connection { int socket_fd; /* file descriptor for tcp socket */ struct sockaddr sock; /* network order socket */ uint16_t expected; /* number of bytes expected to be read */ uint16_t position; /* current position in the buffer */ uint8_t buffer[N2N_PKT_BUF_SIZE + sizeof(uint16_t)]; /* buffer for data collected from tcp socket incl. prepended length */ uint8_t inactive; /* connection not be handled if set, already closed and to be deleted soon */ UT_hash_handle hh; /* makes this structure hashable */ } n2n_tcp_connection_t; typedef struct n2n_sn { int *keep_running; /* Pointer to sn loop stop/go flag */ time_t start_time; /* Used to measure uptime. */ n2n_version_t version; /* version string sent to edges along with PEER_INFO a.k.a. PONG */ sn_stats_t stats; int daemon; /* If non-zero then daemonise. */ n2n_mac_t mac_addr; uint16_t lport; /* Local UDP port to bind to. */ uint16_t mport; /* Management UDP port to bind to. */ int sock; /* Main socket for UDP traffic with edges. */ int tcp_sock; /* auxiliary socket for optional TCP connections */ n2n_tcp_connection_t *tcp_connections;/* list of established TCP connections */ int mgmt_sock; /* management socket. */ n2n_ip_subnet_t min_auto_ip_net; /* Address range of auto_ip service. */ n2n_ip_subnet_t max_auto_ip_net; /* Address range of auto_ip service. */ #ifndef WIN32 uid_t userid; gid_t groupid; #endif int lock_communities; /* If true, only loaded and matching communities can be used. */ char *community_file; struct sn_community *communities; struct sn_community_regular_expression *rules; struct sn_community *federation; n2n_private_public_key_t private_key; /* private federation key derived from federation name */ n2n_auth_t auth; uint32_t dynamic_key_time; /* UTC time of last dynamic key generation (second accuracy) */ uint8_t override_spoofing_protection; /* set if overriding MAC/IP spoofing protection (cli option '-M') */ n2n_resolve_parameter_t *resolve_parameter;/*Pointer to name resolver's parameter block */ uint64_t mgmt_password_hash;/* contains hash of managament port password */ } n2n_sn_t; /* *************************************************** */ #endif /* _N2N_TYPEDEFS_H_ */ ntop-n2n-90215bd/include/n2n_wire.h000066400000000000000000000170731422132035700170430ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #if !defined( N2N_WIRE_H_ ) #define N2N_WIRE_H_ #include #ifndef _MSC_VER /* Not included in Visual Studio 2008 */ #include #endif #if defined(WIN32) #include "n2n_win32.h" #else /* #if defined(WIN32) */ #include #include /* AF_INET and AF_INET6 */ #endif /* #if defined(WIN32) */ #include "sn_selection.h" int encode_uint8 (uint8_t * base, size_t * idx, const uint8_t v); int decode_uint8 (uint8_t * out, const uint8_t * base, size_t * rem, size_t * idx); int encode_uint16 (uint8_t * base, size_t * idx, const uint16_t v); int decode_uint16 (uint16_t * out, const uint8_t * base, size_t * rem, size_t * idx); int encode_uint32 (uint8_t * base, size_t * idx, const uint32_t v); int decode_uint32 (uint32_t * out, const uint8_t * base, size_t * rem, size_t * idx); int encode_uint64 (uint8_t * base, size_t * idx, const uint64_t v); int decode_uint64 (uint64_t * out, const uint8_t * base, size_t * rem, size_t * idx); int encode_buf (uint8_t * base, size_t * idx, const void * p, size_t s); int decode_buf (uint8_t * out, size_t bufsize, const uint8_t * base, size_t * rem, size_t * idx); int encode_mac (uint8_t * base, size_t * idx, const n2n_mac_t m); int decode_mac (n2n_mac_t out, const uint8_t * base, size_t * rem, size_t * idx); int encode_cookie (uint8_t * base, size_t * idx, const n2n_cookie_t c); int decode_cookie (n2n_cookie_t * out, const uint8_t * base, size_t * rem, size_t * idx); int encode_common (uint8_t * base, size_t * idx, const n2n_common_t * common); int decode_common (n2n_common_t * out, const uint8_t * base, size_t * rem, size_t * idx); int encode_sock (uint8_t * base, size_t * idx, const n2n_sock_t * sock); int decode_sock (n2n_sock_t * sock, const uint8_t * base, size_t * rem, size_t * idx); int encode_REGISTER (uint8_t * base, size_t * idx, const n2n_common_t * common, const n2n_REGISTER_t * reg); int decode_REGISTER (n2n_REGISTER_t * pkt, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx); int encode_REGISTER_SUPER (uint8_t * base, size_t * idx, const n2n_common_t * common, const n2n_REGISTER_SUPER_t * reg); int decode_REGISTER_SUPER (n2n_REGISTER_SUPER_t * pkt, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx); int encode_UNREGISTER_SUPER (uint8_t *base, size_t *idx, const n2n_common_t *common, const n2n_UNREGISTER_SUPER_t *unreg); int decode_UNREGISTER_SUPER (n2n_UNREGISTER_SUPER_t *unreg, const n2n_common_t *cmn, /* info on how to interpret it */ const uint8_t *base, size_t *rem, size_t *idx); int encode_REGISTER_ACK (uint8_t * base, size_t * idx, const n2n_common_t * common, const n2n_REGISTER_ACK_t * reg); int decode_REGISTER_ACK (n2n_REGISTER_ACK_t * pkt, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx); int encode_REGISTER_SUPER_ACK (uint8_t * base, size_t * idx, const n2n_common_t * cmn, const n2n_REGISTER_SUPER_ACK_t * reg, uint8_t * tmpbuf); int decode_REGISTER_SUPER_ACK (n2n_REGISTER_SUPER_ACK_t * reg, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx, uint8_t * tmpbuf); int encode_REGISTER_SUPER_NAK (uint8_t * base, size_t * idx, const n2n_common_t * cmn, const n2n_REGISTER_SUPER_NAK_t * nak); int decode_REGISTER_SUPER_NAK (n2n_REGISTER_SUPER_NAK_t * nak, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx); int fill_sockaddr (struct sockaddr * addr, size_t addrlen, const n2n_sock_t * sock); int encode_PACKET (uint8_t * base, size_t * idx, const n2n_common_t * common, const n2n_PACKET_t * pkt); int decode_PACKET (n2n_PACKET_t * pkt, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx); int encode_PEER_INFO (uint8_t * base, size_t * idx, const n2n_common_t * common, const n2n_PEER_INFO_t * pkt); int decode_PEER_INFO (n2n_PEER_INFO_t * pkt, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx); int encode_QUERY_PEER (uint8_t * base, size_t * idx, const n2n_common_t * common, const n2n_QUERY_PEER_t * pkt); int decode_QUERY_PEER (n2n_QUERY_PEER_t * pkt, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx); #endif /* #if !defined( N2N_WIRE_H_ ) */ ntop-n2n-90215bd/include/network_traffic_filter.h000066400000000000000000000024301422132035700220430ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // // Zhou Bin // #ifndef N2N_NETWORK_TRAFFIC_FILTER_H #define N2N_NETWORK_TRAFFIC_FILTER_H #include "n2n_typedefs.h" network_traffic_filter_t* create_network_traffic_filter (); void destroy_network_traffic_filter (network_traffic_filter_t* filter); void network_traffic_filter_add_rule (network_traffic_filter_t* filter, filter_rule_t* rules); //rule_str format: src_ip/len:[b_port,e_port],dst_ip/len:[s_port,e_port],TCP+/-,UDP+/-,ICMP+/- uint8_t process_traffic_filter_rule_str (const char* rule_str, filter_rule_t* rule_struct); #endif //N2N_NETWORK_TRAFFIC_FILTER_H ntop-n2n-90215bd/include/pearson.h000066400000000000000000000021421422132035700167560ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include #include #include "portable_endian.h" void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len); void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len); uint64_t pearson_hash_64 (const uint8_t *in, size_t len); uint32_t pearson_hash_32 (const uint8_t *in, size_t len); uint16_t pearson_hash_16 (const uint8_t *in, size_t len); void pearson_hash_init (); ntop-n2n-90215bd/include/portable_endian.h000066400000000000000000000205771422132035700204510ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // taken from // https://raw.githubusercontent.com/pyca/bcrypt/master/src/_csrc/portable_endian.h // as of June 11, 2020 // "License": Public Domain // I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like. // In case there are jurisdictions that don't support putting things in the public domain you can also consider it to // be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it // an example on how to get the endian conversion functions on different platforms. #ifndef PORTABLE_ENDIAN_H__ #define PORTABLE_ENDIAN_H__ #if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) # define __WINDOWS__ #endif #if defined(__linux__) || defined(__CYGWIN__) /* Define necessary macros for the header to expose all fields. */ # if !defined(_BSD_SOURCE) # define _BSD_SOURCE # endif # if !defined(__USE_BSD) # define __USE_BSD # endif # if !defined(_DEFAULT_SOURCE) # define _DEFAULT_SOURCE # endif # include # include /* See http://linux.die.net/man/3/endian */ # if defined(htobe16) && defined(htole16) && defined(be16toh) && defined(le16toh) && defined(htobe32) && defined(htole32) && defined(be32toh) && defined(htole32) && defined(htobe64) && defined(htole64) && defined(htobe64) && defined(be64toh) && defined(htole64) && defined(le64toh) /* Do nothing. The macros we need already exist. */ # elif !defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 9))) # include # if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) # define htobe16(x) htons(x) # define htole16(x) (x) # define be16toh(x) ntohs(x) # define le16toh(x) (x) # define htobe32(x) htonl(x) # define htole32(x) (x) # define be32toh(x) ntohl(x) # define le32toh(x) (x) # define htobe64(x) (((uint64_t)htonl(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)htonl(((uint32_t)(x)))) << 32)) # define htole64(x) (x) # define be64toh(x) (((uint64_t)ntohl(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)ntohl(((uint32_t)(x)))) << 32)) # define le64toh(x) (x) # elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) # define htobe16(x) (x) # define htole16(x) (((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) # define be16toh(x) (x) # define le16toh(x) (((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) # define htobe32(x) (x) # define htole32(x) (((uint32_t)htole16(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)htole16(((uint16_t)(x)))) << 16)) # define be32toh(x) (x) # define le32toh(x) (((uint32_t)le16toh(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)le16toh(((uint16_t)(x)))) << 16)) # define htobe64(x) (x) # define htole64(x) (((uint64_t)htole32(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)htole32(((uint32_t)(x)))) << 32)) # define be64toh(x) (x) # define le64toh(x) (((uint64_t)le32toh(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)le32toh(((uint32_t)(x)))) << 32)) # else # error Byte Order not supported or not defined. # endif # endif #elif defined(__APPLE__) # include # define htobe16(x) OSSwapHostToBigInt16(x) # define htole16(x) OSSwapHostToLittleInt16(x) # define be16toh(x) OSSwapBigToHostInt16(x) # define le16toh(x) OSSwapLittleToHostInt16(x) # define htobe32(x) OSSwapHostToBigInt32(x) # define htole32(x) OSSwapHostToLittleInt32(x) # define be32toh(x) OSSwapBigToHostInt32(x) # define le32toh(x) OSSwapLittleToHostInt32(x) # define htobe64(x) OSSwapHostToBigInt64(x) # define htole64(x) OSSwapHostToLittleInt64(x) # define be64toh(x) OSSwapBigToHostInt64(x) # define le64toh(x) OSSwapLittleToHostInt64(x) # define __BYTE_ORDER BYTE_ORDER # define __BIG_ENDIAN BIG_ENDIAN # define __LITTLE_ENDIAN LITTLE_ENDIAN # define __PDP_ENDIAN PDP_ENDIAN #elif defined(__OpenBSD__) # include #elif defined(__HAIKU__) # include #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) # include # if !defined(be16toh) # define be16toh(x) betoh16(x) # define le16toh(x) letoh16(x) # endif # if !defined(be32toh) # define be32toh(x) betoh32(x) # define le32toh(x) letoh32(x) # endif # if !defined(be64toh) # define be64toh(x) betoh64(x) # define le64toh(x) letoh64(x) # endif #elif defined(__WINDOWS__) # if BYTE_ORDER == LITTLE_ENDIAN # define htobe16(x) _byteswap_ushort(x) # define htole16(x) (x) # define be16toh(x) _byteswap_ushort(x) # define le16toh(x) (x) # define htobe32(x) _byteswap_ulong(x) # define htole32(x) (x) # define be32toh(x) _byteswap_ulong(x) # define le32toh(x) (x) # define htobe64(x) (((uint64_t)htobe32(((uint32_t)(((uint64_t)(x)) >> 32))) & 0x00000000FFFFFFFFULL) | (((uint64_t)htobe32(((uint32_t)(x)))) << 32)) # define be64toh(x) (((uint64_t)be32toh(((uint32_t)(((uint64_t)(x)) >> 32))) & 0x00000000FFFFFFFFULL) | (((uint64_t)be32toh(((uint32_t)(x)))) << 32)) # define htole64(x) (x) # define le64toh(x) (x) # elif BYTE_ORDER == BIG_ENDIAN /* that would be xbox 360 */ # define htobe16(x) (x) # define htole16(x) __builtin_bswap16(x) # define be16toh(x) (x) # define le16toh(x) __builtin_bswap16(x) # define htobe32(x) (x) # define htole32(x) __builtin_bswap32(x) # define be32toh(x) (x) # define le32toh(x) __builtin_bswap32(x) # define htobe64(x) (x) # define htole64(x) __builtin_bswap64(x) # define be64toh(x) (x) # define le64toh(x) __builtin_bswap64(x) # else # error byte order not supported # endif # define __BYTE_ORDER BYTE_ORDER # define __BIG_ENDIAN BIG_ENDIAN # define __LITTLE_ENDIAN LITTLE_ENDIAN # define __PDP_ENDIAN PDP_ENDIAN #elif defined(__sun) # include # define htobe16(x) BE_16(x) # define htole16(x) LE_16(x) # define be16toh(x) BE_16(x) # define le16toh(x) LE_16(x) # define htobe32(x) BE_32(x) # define htole32(x) LE_32(x) # define be32toh(x) BE_32(x) # define le32toh(x) LE_32(x) # define htobe64(x) BE_64(x) # define htole64(x) LE_64(x) # define be64toh(x) BE_64(x) # define le64toh(x) LE_64(x) #elif defined _AIX /* AIX is always big endian */ # define be64toh(x) (x) # define be32toh(x) (x) # define be16toh(x) (x) # define le32toh(x) \ ((((x) & 0xff) << 24) | \ (((x) & 0xff00) << 8) | \ (((x) & 0xff0000) >> 8) | \ (((x) & 0xff000000) >> 24)) # define le64toh(x) \ ((((x) & 0x00000000000000ffL) << 56) | \ (((x) & 0x000000000000ff00L) << 40) | \ (((x) & 0x0000000000ff0000L) << 24) | \ (((x) & 0x00000000ff000000L) << 8) | \ (((x) & 0x000000ff00000000L) >> 8) | \ (((x) & 0x0000ff0000000000L) >> 24) | \ (((x) & 0x00ff000000000000L) >> 40) | \ (((x) & 0xff00000000000000L) >> 56)) # ifndef htobe64 # define htobe64(x) be64toh(x) # endif # ifndef htobe32 # define htobe32(x) be32toh(x) # endif # ifndef htobe16 # define htobe16(x) be16toh(x) # endif #else # error platform not supported #endif #endif ntop-n2n-90215bd/include/random_numbers.h000066400000000000000000000032171422132035700203260ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #ifndef RND_H #define RND_H #include #include #include /* time, clock */ #include "n2n.h" /* traceEvent */ // syscall and inquiring random number from hardware generators might fail, so we will retry #define RND_RETRIES 1000 #if defined (__linux__) #include /* syscall, SYS_getrandom */ #ifdef SYS_getrandom #define GRND_NONBLOCK 1 #include /* errno, EAGAIN */ #endif #endif #if defined (__RDRND__) || defined (__RDSEED__) #include /* _rdrand64_step, rdseed4_step */ #endif #if defined (WIN32) #include // HCTYPTPROV, Crypt*-functions #endif typedef struct rn_generator_state_t { uint64_t a, b; } rn_generator_state_t; typedef struct splitmix64_state_t { uint64_t s; } splitmix64_state_t; int n2n_srand (uint64_t seed); uint64_t n2n_rand (void); uint64_t n2n_seed (void); uint32_t n2n_rand_sqr (uint32_t max_n); #endif // RND_H ntop-n2n-90215bd/include/sn_selection.h000066400000000000000000000034451422132035700200030ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #ifndef _SN_SELECTION_ #define _SN_SELECTION_ typedef char selection_criterion_str_t[SN_SELECTION_CRITERION_BUF_SIZE]; #include "n2n.h" /* selection criterion's functions */ int sn_selection_criterion_init (peer_info_t *peer); int sn_selection_criterion_default (SN_SELECTION_CRITERION_DATA_TYPE *selection_criterion); int sn_selection_criterion_bad (SN_SELECTION_CRITERION_DATA_TYPE *selection_criterion); int sn_selection_criterion_good (SN_SELECTION_CRITERION_DATA_TYPE *selection_criterion); int sn_selection_criterion_calculate (n2n_edge_t *eee, peer_info_t *peer, SN_SELECTION_CRITERION_DATA_TYPE *data); /* common data's functions */ int sn_selection_criterion_common_data_default (n2n_edge_t *eee); /* sorting function */ int sn_selection_sort (peer_info_t **peer_list); /* gathering data function */ SN_SELECTION_CRITERION_DATA_TYPE sn_selection_criterion_gather_data (n2n_sn_t *sss); /* management port output function */ extern char * sn_selection_criterion_str (n2n_edge_t *eee, selection_criterion_str_t out, peer_info_t *peer); #endif /* _SN_SELECTION_ */ ntop-n2n-90215bd/include/speck.h000066400000000000000000000072101422132035700164150ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // cipher SPECK -- 128 bit block size -- 128 and 256 bit key size -- CTR mode // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ #ifndef SPECK_H #define SPECK_H #include #include #include "portable_endian.h" #define u32 uint32_t #define u64 uint64_t #define N2N_SPECK_IVEC_SIZE 16 #define SPECK_KEY_BYTES (256/8) #if defined (__AVX512F__) // AVX512 support ----------------------------------------------------------------------- #include #include /* memcpy() */ #define u512 __m512i #define SPECK_ALIGNED_CTX 64 typedef struct { u512 rk[34]; u64 key[34]; u32 keysize; } speck_context_t; #elif defined (__AVX2__) // AVX2 support -------------------------------------------------------------------------- #include #define u256 __m256i #define SPECK_ALIGNED_CTX 32 typedef struct { u256 rk[34]; u64 key[34]; u32 keysize; } speck_context_t; #elif defined (__SSE2__) // SSE support --------------------------------------------------------------------------- #include #define u128 __m128i #define SPECK_ALIGNED_CTX 16 #define SPECK_CTX_BYVAL 1 typedef struct { u128 rk[34]; u64 key[34]; u32 keysize; } speck_context_t; #elif defined (__ARM_NEON) && defined (SPECK_ARM_NEON) // NEON support --------------------------------------- #include #define u128 uint64x2_t typedef struct { u128 rk[34]; u64 key[34]; u32 keysize; } speck_context_t; #else // plain C -------------------------------------------------------------------------------------------------- typedef struct { u64 key[34]; u32 keysize; } speck_context_t; #endif // --------------------------------------------------------------------------------------------------------- int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *n, speck_context_t *ctx); int speck_init (speck_context_t **ctx, const unsigned char *k, int keysize); int speck_deinit (speck_context_t *ctx); // ---------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------- // cipher SPECK -- 128 bit block size -- 128 bit key size -- ECB mode // follows endianess rules as used in official implementation guide and NOT as in original 2013 cipher presentation // used for IV in header encryption (one block) and challenge encryption (user/password) // for now: just plain C -- probably no need for AVX, SSE, NEON int speck_128_decrypt (unsigned char *inout, speck_context_t *ctx); int speck_128_encrypt (unsigned char *inout, speck_context_t *ctx); #endif // SPECK_H ntop-n2n-90215bd/include/tf.h000066400000000000000000000055731422132035700157330ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // taken (and modified) from github/fudanchii/twofish as of August 2020 // which itself is a modified copy of Andrew T. Csillag's implementation // published on github/drewcsillag/twofish /** * The MIT License (MIT) * * Copyright (c) 2015 Andrew T. Csillag * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef TF_H #define TF_H #include #include #include #include "portable_endian.h" #define TF_BLOCK_SIZE 16 #define TF_IV_SIZE (TF_BLOCK_SIZE) typedef struct tf_context_t { int N; uint32_t K[40]; uint32_t QF[4][256]; } tf_context_t; int tf_ecb_decrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx); int tf_ecb_encrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx); int tf_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, tf_context_t *ctx); int tf_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, tf_context_t *ctx); int tf_init (const unsigned char *key, size_t key_size, tf_context_t **ctx); int tf_deinit (tf_context_t *ctx); #endif // TF_H ntop-n2n-90215bd/include/uthash.h000066400000000000000000002330571422132035700166160ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* Copyright (c) 2003-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UTHASH_H #define UTHASH_H #define UTHASH_VERSION 2.1.0 #include /* memcmp, memset, strlen */ #include /* ptrdiff_t */ #include /* exit */ /* These macros use decltype or the earlier __typeof GNU extension. As decltype is only available in newer compilers (VS2010 or gcc 4.3+ when compiling c++ source) this code uses whatever method is needed or, for VS2008 where neither is available, uses casting workarounds. */ #if !defined(DECLTYPE) && !defined(NO_DECLTYPE) #if defined(_MSC_VER) /* MS compiler */ #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ #define DECLTYPE(x) (decltype(x)) #else /* VS2008 or older (or VS2010 in C mode) */ #define NO_DECLTYPE #endif #elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) #define NO_DECLTYPE #else /* GNU, Sun and other compilers */ #define DECLTYPE(x) (__typeof(x)) #endif #endif #ifdef NO_DECLTYPE #define DECLTYPE(x) #define DECLTYPE_ASSIGN(dst,src) \ do { \ char **_da_dst = (char**)(&(dst)); \ *_da_dst = (char*)(src); \ } while (0) #else #define DECLTYPE_ASSIGN(dst,src) \ do { \ (dst) = DECLTYPE(dst)(src); \ } while (0) #endif /* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ #if defined(_WIN32) #if defined(_MSC_VER) && _MSC_VER >= 1600 #include #elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__) #include #else typedef unsigned int uint32_t; typedef unsigned char uint8_t; #endif #elif defined(__GNUC__) && !defined(__VXWORKS__) #include #else typedef unsigned int uint32_t; typedef unsigned char uint8_t; #endif #ifndef uthash_malloc #define uthash_malloc(sz) malloc(sz) /* malloc fcn */ #endif #ifndef uthash_free #define uthash_free(ptr,sz) free(ptr) /* free fcn */ #endif #ifndef uthash_bzero #define uthash_bzero(a,n) memset(a,'\0',n) #endif #ifndef uthash_strlen #define uthash_strlen(s) strlen(s) #endif #ifdef uthash_memcmp /* This warning will not catch programs that define uthash_memcmp AFTER including uthash.h. */ #warning "uthash_memcmp is deprecated; please use HASH_KEYCMP instead" #else #define uthash_memcmp(a,b,n) memcmp(a,b,n) #endif #ifndef HASH_KEYCMP #define HASH_KEYCMP(a,b,n) uthash_memcmp(a,b,n) #endif #ifndef uthash_noexpand_fyi #define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ #endif #ifndef uthash_expand_fyi #define uthash_expand_fyi(tbl) /* can be defined to log expands */ #endif #ifndef HASH_NONFATAL_OOM #define HASH_NONFATAL_OOM 0 #endif #if HASH_NONFATAL_OOM /* malloc failures can be recovered from */ #ifndef uthash_nonfatal_oom #define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */ #endif #define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0) #define IF_HASH_NONFATAL_OOM(x) x #else /* malloc failures result in lost memory, hash tables are unusable */ #ifndef uthash_fatal #define uthash_fatal(msg) exit(-1) /* fatal OOM error */ #endif #define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory") #define IF_HASH_NONFATAL_OOM(x) #endif /* initial number of buckets */ #define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ #define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ #define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ /* calculate the element whose hash handle address is hhp */ #define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) /* calculate the hash handle from element address elp */ #define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho))) #define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ do { \ struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ unsigned _hd_bkt; \ HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ (head)->hh.tbl->buckets[_hd_bkt].count++; \ _hd_hh_item->hh_next = NULL; \ _hd_hh_item->hh_prev = NULL; \ } while (0) #define HASH_VALUE(keyptr,keylen,hashv) \ do { \ HASH_FCN(keyptr, keylen, hashv); \ } while (0) #define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ do { \ (out) = NULL; \ if (head) { \ unsigned _hf_bkt; \ HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ } \ } \ } while (0) #define HASH_FIND(hh,head,keyptr,keylen,out) \ do { \ (out) = NULL; \ if (head) { \ unsigned _hf_hashv; \ HASH_VALUE(keyptr, keylen, _hf_hashv); \ HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ } \ } while (0) #ifdef HASH_BLOOM #define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) #define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) #define HASH_BLOOM_MAKE(tbl,oomed) \ do { \ (tbl)->bloom_nbits = HASH_BLOOM; \ (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ if (!(tbl)->bloom_bv) { \ HASH_RECORD_OOM(oomed); \ } else { \ uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ } \ } while (0) #define HASH_BLOOM_FREE(tbl) \ do { \ uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ } while (0) #define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) #define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) #define HASH_BLOOM_ADD(tbl,hashv) \ HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) #define HASH_BLOOM_TEST(tbl,hashv) \ HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) #else #define HASH_BLOOM_MAKE(tbl,oomed) #define HASH_BLOOM_FREE(tbl) #define HASH_BLOOM_ADD(tbl,hashv) #define HASH_BLOOM_TEST(tbl,hashv) (1) #define HASH_BLOOM_BYTELEN 0U #endif #define HASH_MAKE_TABLE(hh,head,oomed) \ do { \ (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \ if (!(head)->hh.tbl) { \ HASH_RECORD_OOM(oomed); \ } else { \ uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ (head)->hh.tbl->tail = &((head)->hh); \ (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ (head)->hh.tbl->signature = HASH_SIGNATURE; \ if (!(head)->hh.tbl->buckets) { \ HASH_RECORD_OOM(oomed); \ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ } else { \ uthash_bzero((head)->hh.tbl->buckets, \ HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ IF_HASH_NONFATAL_OOM( \ if (oomed) { \ uthash_free((head)->hh.tbl->buckets, \ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ } \ ) \ } \ } \ } while (0) #define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ do { \ (replaced) = NULL; \ HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ if (replaced) { \ HASH_DELETE(hh, head, replaced); \ } \ HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ } while (0) #define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ do { \ (replaced) = NULL; \ HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ if (replaced) { \ HASH_DELETE(hh, head, replaced); \ } \ HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ } while (0) #define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ do { \ unsigned _hr_hashv; \ HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ } while (0) #define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ do { \ unsigned _hr_hashv; \ HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ } while (0) #define HASH_APPEND_LIST(hh, head, add) \ do { \ (add)->hh.next = NULL; \ (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ (head)->hh.tbl->tail->next = (add); \ (head)->hh.tbl->tail = &((add)->hh); \ } while (0) #define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ do { \ do { \ if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ break; \ } \ } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ } while (0) #ifdef NO_DECLTYPE #undef HASH_AKBI_INNER_LOOP #define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ do { \ char *_hs_saved_head = (char*)(head); \ do { \ DECLTYPE_ASSIGN(head, _hs_iter); \ if (cmpfcn(head, add) > 0) { \ DECLTYPE_ASSIGN(head, _hs_saved_head); \ break; \ } \ DECLTYPE_ASSIGN(head, _hs_saved_head); \ } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ } while (0) #endif #if HASH_NONFATAL_OOM #define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ do { \ if (!(oomed)) { \ unsigned _ha_bkt; \ (head)->hh.tbl->num_items++; \ HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ if (oomed) { \ HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ HASH_DELETE_HH(hh, head, &(add)->hh); \ (add)->hh.tbl = NULL; \ uthash_nonfatal_oom(add); \ } else { \ HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ } \ } else { \ (add)->hh.tbl = NULL; \ uthash_nonfatal_oom(add); \ } \ } while (0) #else #define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ do { \ unsigned _ha_bkt; \ (head)->hh.tbl->num_items++; \ HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ } while (0) #endif #define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ do { \ IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ (add)->hh.hashv = (hashval); \ (add)->hh.key = (char*) (keyptr); \ (add)->hh.keylen = (unsigned) (keylen_in); \ if (!(head)) { \ (add)->hh.next = NULL; \ (add)->hh.prev = NULL; \ HASH_MAKE_TABLE(hh, add, _ha_oomed); \ IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ (head) = (add); \ IF_HASH_NONFATAL_OOM( } ) \ } else { \ void *_hs_iter = (head); \ (add)->hh.tbl = (head)->hh.tbl; \ HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ if (_hs_iter) { \ (add)->hh.next = _hs_iter; \ if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ } else { \ (head) = (add); \ } \ HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ } else { \ HASH_APPEND_LIST(hh, head, add); \ } \ } \ HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ } while (0) #define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ do { \ unsigned _hs_hashv; \ HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ } while (0) #define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) #define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) #define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ do { \ IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ (add)->hh.hashv = (hashval); \ (add)->hh.key = (char*) (keyptr); \ (add)->hh.keylen = (unsigned) (keylen_in); \ if (!(head)) { \ (add)->hh.next = NULL; \ (add)->hh.prev = NULL; \ HASH_MAKE_TABLE(hh, add, _ha_oomed); \ IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ (head) = (add); \ IF_HASH_NONFATAL_OOM( } ) \ } else { \ (add)->hh.tbl = (head)->hh.tbl; \ HASH_APPEND_LIST(hh, head, add); \ } \ HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ } while (0) #define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ do { \ unsigned _ha_hashv; \ HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ } while (0) #define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) #define HASH_ADD(hh,head,fieldname,keylen_in,add) \ HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) #define HASH_TO_BKT(hashv,num_bkts,bkt) \ do { \ bkt = ((hashv) & ((num_bkts) - 1U)); \ } while (0) /* delete "delptr" from the hash table. * "the usual" patch-up process for the app-order doubly-linked-list. * The use of _hd_hh_del below deserves special explanation. * These used to be expressed using (delptr) but that led to a bug * if someone used the same symbol for the head and deletee, like * HASH_DELETE(hh,users,users); * We want that to work, but by changing the head (users) below * we were forfeiting our ability to further refer to the deletee (users) * in the patch-up process. Solution: use scratch space to * copy the deletee pointer, then the latter references are via that * scratch pointer rather than through the repointed (users) symbol. */ #define HASH_DELETE(hh,head,delptr) \ HASH_DELETE_HH(hh, head, &(delptr)->hh) #define HASH_DELETE_HH(hh,head,delptrhh) \ do { \ struct UT_hash_handle *_hd_hh_del = (delptrhh); \ if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ HASH_BLOOM_FREE((head)->hh.tbl); \ uthash_free((head)->hh.tbl->buckets, \ (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ (head) = NULL; \ } else { \ unsigned _hd_bkt; \ if (_hd_hh_del == (head)->hh.tbl->tail) { \ (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ } \ if (_hd_hh_del->prev != NULL) { \ HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ } else { \ DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ } \ if (_hd_hh_del->next != NULL) { \ HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ } \ HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ (head)->hh.tbl->num_items--; \ } \ HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ } while (0) /* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ #define HASH_FIND_STR(head,findstr,out) \ do { \ unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ } while (0) #define HASH_ADD_STR(head,strfield,add) \ do { \ unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \ HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ } while (0) #define HASH_REPLACE_STR(head,strfield,add,replaced) \ do { \ unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \ HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ } while (0) #define HASH_FIND_INT(head,findint,out) \ HASH_FIND(hh,head,findint,sizeof(int),out) #define HASH_ADD_INT(head,intfield,add) \ HASH_ADD(hh,head,intfield,sizeof(int),add) #define HASH_REPLACE_INT(head,intfield,add,replaced) \ HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) #define HASH_FIND_PTR(head,findptr,out) \ HASH_FIND(hh,head,findptr,sizeof(void *),out) #define HASH_ADD_PTR(head,ptrfield,add) \ HASH_ADD(hh,head,ptrfield,sizeof(void *),add) #define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) #define HASH_DEL(head,delptr) \ HASH_DELETE(hh,head,delptr) /* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. */ #ifdef HASH_DEBUG #define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) #define HASH_FSCK(hh,head,where) \ do { \ struct UT_hash_handle *_thh; \ if (head) { \ unsigned _bkt_i; \ unsigned _count = 0; \ char *_prev; \ for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ unsigned _bkt_count = 0; \ _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ _prev = NULL; \ while (_thh) { \ if (_prev != (char*)(_thh->hh_prev)) { \ HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ (where), (void*)_thh->hh_prev, (void*)_prev); \ } \ _bkt_count++; \ _prev = (char*)(_thh); \ _thh = _thh->hh_next; \ } \ _count += _bkt_count; \ if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ } \ } \ if (_count != (head)->hh.tbl->num_items) { \ HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ (where), (head)->hh.tbl->num_items, _count); \ } \ _count = 0; \ _prev = NULL; \ _thh = &(head)->hh; \ while (_thh) { \ _count++; \ if (_prev != (char*)_thh->prev) { \ HASH_OOPS("%s: invalid prev %p, actual %p\n", \ (where), (void*)_thh->prev, (void*)_prev); \ } \ _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ } \ if (_count != (head)->hh.tbl->num_items) { \ HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ (where), (head)->hh.tbl->num_items, _count); \ } \ } \ } while (0) #else #define HASH_FSCK(hh,head,where) #endif /* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to * the descriptor to which this macro is defined for tuning the hash function. * The app can #include to get the prototype for write(2). */ #ifdef HASH_EMIT_KEYS #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ do { \ unsigned _klen = fieldlen; \ write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ } while (0) #else #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) #endif /* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ #ifdef HASH_FUNCTION #define HASH_FCN HASH_FUNCTION #else #define HASH_FCN HASH_JEN #endif /* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ #define HASH_BER(key,keylen,hashv) \ do { \ unsigned _hb_keylen = (unsigned)keylen; \ const unsigned char *_hb_key = (const unsigned char*)(key); \ (hashv) = 0; \ while (_hb_keylen-- != 0U) { \ (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ } \ } while (0) /* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ #define HASH_SAX(key,keylen,hashv) \ do { \ unsigned _sx_i; \ const unsigned char *_hs_key = (const unsigned char*)(key); \ hashv = 0; \ for (_sx_i=0; _sx_i < keylen; _sx_i++) { \ hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ } \ } while (0) /* FNV-1a variation */ #define HASH_FNV(key,keylen,hashv) \ do { \ unsigned _fn_i; \ const unsigned char *_hf_key = (const unsigned char*)(key); \ (hashv) = 2166136261U; \ for (_fn_i=0; _fn_i < keylen; _fn_i++) { \ hashv = hashv ^ _hf_key[_fn_i]; \ hashv = hashv * 16777619U; \ } \ } while (0) #define HASH_OAT(key,keylen,hashv) \ do { \ unsigned _ho_i; \ const unsigned char *_ho_key=(const unsigned char*)(key); \ hashv = 0; \ for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ hashv += _ho_key[_ho_i]; \ hashv += (hashv << 10); \ hashv ^= (hashv >> 6); \ } \ hashv += (hashv << 3); \ hashv ^= (hashv >> 11); \ hashv += (hashv << 15); \ } while (0) #define HASH_JEN_MIX(a,b,c) \ do { \ a -= b; a -= c; a ^= ( c >> 13 ); \ b -= c; b -= a; b ^= ( a << 8 ); \ c -= a; c -= b; c ^= ( b >> 13 ); \ a -= b; a -= c; a ^= ( c >> 12 ); \ b -= c; b -= a; b ^= ( a << 16 ); \ c -= a; c -= b; c ^= ( b >> 5 ); \ a -= b; a -= c; a ^= ( c >> 3 ); \ b -= c; b -= a; b ^= ( a << 10 ); \ c -= a; c -= b; c ^= ( b >> 15 ); \ } while (0) #define HASH_JEN(key,keylen,hashv) \ do { \ unsigned _hj_i,_hj_j,_hj_k; \ unsigned const char *_hj_key=(unsigned const char*)(key); \ hashv = 0xfeedbeefu; \ _hj_i = _hj_j = 0x9e3779b9u; \ _hj_k = (unsigned)(keylen); \ while (_hj_k >= 12U) { \ _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + ( (unsigned)_hj_key[2] << 16 ) \ + ( (unsigned)_hj_key[3] << 24 ) ); \ _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + ( (unsigned)_hj_key[6] << 16 ) \ + ( (unsigned)_hj_key[7] << 24 ) ); \ hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + ( (unsigned)_hj_key[10] << 16 ) \ + ( (unsigned)_hj_key[11] << 24 ) ); \ \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ \ _hj_key += 12; \ _hj_k -= 12U; \ } \ hashv += (unsigned)(keylen); \ switch ( _hj_k ) { \ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ case 1: _hj_i += _hj_key[0]; \ } \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ } while (0) /* The Paul Hsieh hash function */ #undef get16bits #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) #define get16bits(d) (*((const uint16_t *) (d))) #endif #if !defined (get16bits) #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ +(uint32_t)(((const uint8_t *)(d))[0]) ) #endif #define HASH_SFH(key,keylen,hashv) \ do { \ unsigned const char *_sfh_key=(unsigned const char*)(key); \ uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ \ unsigned _sfh_rem = _sfh_len & 3U; \ _sfh_len >>= 2; \ hashv = 0xcafebabeu; \ \ /* Main loop */ \ for (;_sfh_len > 0U; _sfh_len--) { \ hashv += get16bits (_sfh_key); \ _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ hashv = (hashv << 16) ^ _sfh_tmp; \ _sfh_key += 2U*sizeof (uint16_t); \ hashv += hashv >> 11; \ } \ \ /* Handle end cases */ \ switch (_sfh_rem) { \ case 3: hashv += get16bits (_sfh_key); \ hashv ^= hashv << 16; \ hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ hashv += hashv >> 11; \ break; \ case 2: hashv += get16bits (_sfh_key); \ hashv ^= hashv << 11; \ hashv += hashv >> 17; \ break; \ case 1: hashv += *_sfh_key; \ hashv ^= hashv << 10; \ hashv += hashv >> 1; \ } \ \ /* Force "avalanching" of final 127 bits */ \ hashv ^= hashv << 3; \ hashv += hashv >> 5; \ hashv ^= hashv << 4; \ hashv += hashv >> 17; \ hashv ^= hashv << 25; \ hashv += hashv >> 6; \ } while (0) #ifdef HASH_USING_NO_STRICT_ALIASING /* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. * MurmurHash uses the faster approach only on CPU's where we know it's safe. * * Note the preprocessor built-in defines can be emitted using: * * gcc -m64 -dM -E - < /dev/null (on gcc) * cc -## a.c (where a.c is a simple test file) (Sun Studio) */ #if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) #define MUR_GETBLOCK(p,i) p[i] #else /* non intel */ #define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL) #define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL) #define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) #define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) #define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) #if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) #define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) #define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) #define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) #else /* assume little endian non-intel */ #define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) #define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) #define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) #endif #define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ MUR_ONE_THREE(p)))) #endif #define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) #define MUR_FMIX(_h) \ do { \ _h ^= _h >> 16; \ _h *= 0x85ebca6bu; \ _h ^= _h >> 13; \ _h *= 0xc2b2ae35u; \ _h ^= _h >> 16; \ } while (0) #define HASH_MUR(key,keylen,hashv) \ do { \ const uint8_t *_mur_data = (const uint8_t*)(key); \ const int _mur_nblocks = (int)(keylen) / 4; \ uint32_t _mur_h1 = 0xf88D5353u; \ uint32_t _mur_c1 = 0xcc9e2d51u; \ uint32_t _mur_c2 = 0x1b873593u; \ uint32_t _mur_k1 = 0; \ const uint8_t *_mur_tail; \ const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \ int _mur_i; \ for (_mur_i = -_mur_nblocks; _mur_i != 0; _mur_i++) { \ _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ _mur_k1 *= _mur_c1; \ _mur_k1 = MUR_ROTL32(_mur_k1,15); \ _mur_k1 *= _mur_c2; \ \ _mur_h1 ^= _mur_k1; \ _mur_h1 = MUR_ROTL32(_mur_h1,13); \ _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \ } \ _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \ _mur_k1=0; \ switch ((keylen) & 3U) { \ case 0: break; \ case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \ case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \ case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \ _mur_k1 *= _mur_c1; \ _mur_k1 = MUR_ROTL32(_mur_k1,15); \ _mur_k1 *= _mur_c2; \ _mur_h1 ^= _mur_k1; \ } \ _mur_h1 ^= (uint32_t)(keylen); \ MUR_FMIX(_mur_h1); \ hashv = _mur_h1; \ } while (0) #endif /* HASH_USING_NO_STRICT_ALIASING */ /* iterate over items in a known bucket to find desired item */ #define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ do { \ if ((head).hh_head != NULL) { \ DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ } else { \ (out) = NULL; \ } \ while ((out) != NULL) { \ if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \ break; \ } \ } \ if ((out)->hh.hh_next != NULL) { \ DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ } else { \ (out) = NULL; \ } \ } \ } while (0) /* add an item to a bucket */ #define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \ do { \ UT_hash_bucket *_ha_head = &(head); \ _ha_head->count++; \ (addhh)->hh_next = _ha_head->hh_head; \ (addhh)->hh_prev = NULL; \ if (_ha_head->hh_head != NULL) { \ _ha_head->hh_head->hh_prev = (addhh); \ } \ _ha_head->hh_head = (addhh); \ if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ && !(addhh)->tbl->noexpand) { \ HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \ IF_HASH_NONFATAL_OOM( \ if (oomed) { \ HASH_DEL_IN_BKT(head,addhh); \ } \ ) \ } \ } while (0) /* remove an item from a given bucket */ #define HASH_DEL_IN_BKT(head,delhh) \ do { \ UT_hash_bucket *_hd_head = &(head); \ _hd_head->count--; \ if (_hd_head->hh_head == (delhh)) { \ _hd_head->hh_head = (delhh)->hh_next; \ } \ if ((delhh)->hh_prev) { \ (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ } \ if ((delhh)->hh_next) { \ (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ } \ } while (0) /* Bucket expansion has the effect of doubling the number of buckets * and redistributing the items into the new buckets. Ideally the * items will distribute more or less evenly into the new buckets * (the extent to which this is true is a measure of the quality of * the hash function as it applies to the key domain). * * With the items distributed into more buckets, the chain length * (item count) in each bucket is reduced. Thus by expanding buckets * the hash keeps a bound on the chain length. This bounded chain * length is the essence of how a hash provides constant time lookup. * * The calculation of tbl->ideal_chain_maxlen below deserves some * explanation. First, keep in mind that we're calculating the ideal * maximum chain length based on the *new* (doubled) bucket count. * In fractions this is just n/b (n=number of items,b=new num buckets). * Since the ideal chain length is an integer, we want to calculate * ceil(n/b). We don't depend on floating point arithmetic in this * hash, so to calculate ceil(n/b) with integers we could write * * ceil(n/b) = (n/b) + ((n%b)?1:0) * * and in fact a previous version of this hash did just that. * But now we have improved things a bit by recognizing that b is * always a power of two. We keep its base 2 log handy (call it lb), * so now we can write this with a bit shift and logical AND: * * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) * */ #define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \ do { \ unsigned _he_bkt; \ unsigned _he_bkt_i; \ struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ if (!_he_new_buckets) { \ HASH_RECORD_OOM(oomed); \ } else { \ uthash_bzero(_he_new_buckets, \ 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ (tbl)->ideal_chain_maxlen = \ ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \ ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ (tbl)->nonideal_items = 0; \ for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \ while (_he_thh != NULL) { \ _he_hh_nxt = _he_thh->hh_next; \ HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ _he_newbkt = &(_he_new_buckets[_he_bkt]); \ if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ (tbl)->nonideal_items++; \ if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ _he_newbkt->expand_mult++; \ } \ } \ _he_thh->hh_prev = NULL; \ _he_thh->hh_next = _he_newbkt->hh_head; \ if (_he_newbkt->hh_head != NULL) { \ _he_newbkt->hh_head->hh_prev = _he_thh; \ } \ _he_newbkt->hh_head = _he_thh; \ _he_thh = _he_hh_nxt; \ } \ } \ uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ (tbl)->num_buckets *= 2U; \ (tbl)->log2_num_buckets++; \ (tbl)->buckets = _he_new_buckets; \ (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \ ((tbl)->ineff_expands+1U) : 0U; \ if ((tbl)->ineff_expands > 1U) { \ (tbl)->noexpand = 1; \ uthash_noexpand_fyi(tbl); \ } \ uthash_expand_fyi(tbl); \ } \ } while (0) /* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ /* Note that HASH_SORT assumes the hash handle name to be hh. * HASH_SRT was added to allow the hash handle name to be passed in. */ #define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) #define HASH_SRT(hh,head,cmpfcn) \ do { \ unsigned _hs_i; \ unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ if (head != NULL) { \ _hs_insize = 1; \ _hs_looping = 1; \ _hs_list = &((head)->hh); \ while (_hs_looping != 0U) { \ _hs_p = _hs_list; \ _hs_list = NULL; \ _hs_tail = NULL; \ _hs_nmerges = 0; \ while (_hs_p != NULL) { \ _hs_nmerges++; \ _hs_q = _hs_p; \ _hs_psize = 0; \ for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ _hs_psize++; \ _hs_q = ((_hs_q->next != NULL) ? \ HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ if (_hs_q == NULL) { \ break; \ } \ } \ _hs_qsize = _hs_insize; \ while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ if (_hs_psize == 0U) { \ _hs_e = _hs_q; \ _hs_q = ((_hs_q->next != NULL) ? \ HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ _hs_qsize--; \ } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ _hs_e = _hs_p; \ if (_hs_p != NULL) { \ _hs_p = ((_hs_p->next != NULL) ? \ HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ } \ _hs_psize--; \ } else if ((cmpfcn( \ DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \ )) <= 0) { \ _hs_e = _hs_p; \ if (_hs_p != NULL) { \ _hs_p = ((_hs_p->next != NULL) ? \ HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ } \ _hs_psize--; \ } else { \ _hs_e = _hs_q; \ _hs_q = ((_hs_q->next != NULL) ? \ HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ _hs_qsize--; \ } \ if ( _hs_tail != NULL ) { \ _hs_tail->next = ((_hs_e != NULL) ? \ ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ } else { \ _hs_list = _hs_e; \ } \ if (_hs_e != NULL) { \ _hs_e->prev = ((_hs_tail != NULL) ? \ ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ } \ _hs_tail = _hs_e; \ } \ _hs_p = _hs_q; \ } \ if (_hs_tail != NULL) { \ _hs_tail->next = NULL; \ } \ if (_hs_nmerges <= 1U) { \ _hs_looping = 0; \ (head)->hh.tbl->tail = _hs_tail; \ DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ } \ _hs_insize *= 2U; \ } \ HASH_FSCK(hh, head, "HASH_SRT"); \ } \ } while (0) /* This function selects items from one hash into another hash. * The end result is that the selected items have dual presence * in both hashes. There is no copy of the items made; rather * they are added into the new hash through a secondary hash * hash handle that must be present in the structure. */ #define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ do { \ unsigned _src_bkt, _dst_bkt; \ void *_last_elt = NULL, *_elt; \ UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ if ((src) != NULL) { \ for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ _src_hh != NULL; \ _src_hh = _src_hh->hh_next) { \ _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ if (cond(_elt)) { \ IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ _dst_hh->key = _src_hh->key; \ _dst_hh->keylen = _src_hh->keylen; \ _dst_hh->hashv = _src_hh->hashv; \ _dst_hh->prev = _last_elt; \ _dst_hh->next = NULL; \ if (_last_elt_hh != NULL) { \ _last_elt_hh->next = _elt; \ } \ if ((dst) == NULL) { \ DECLTYPE_ASSIGN(dst, _elt); \ HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ IF_HASH_NONFATAL_OOM( \ if (_hs_oomed) { \ uthash_nonfatal_oom(_elt); \ (dst) = NULL; \ continue; \ } \ ) \ } else { \ _dst_hh->tbl = (dst)->hh_dst.tbl; \ } \ HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ (dst)->hh_dst.tbl->num_items++; \ IF_HASH_NONFATAL_OOM( \ if (_hs_oomed) { \ HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ _dst_hh->tbl = NULL; \ uthash_nonfatal_oom(_elt); \ continue; \ } \ ) \ HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ _last_elt = _elt; \ _last_elt_hh = _dst_hh; \ } \ } \ } \ } \ HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ } while (0) #define HASH_CLEAR(hh,head) \ do { \ if ((head) != NULL) { \ HASH_BLOOM_FREE((head)->hh.tbl); \ uthash_free((head)->hh.tbl->buckets, \ (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ (head) = NULL; \ } \ } while (0) #define HASH_OVERHEAD(hh,head) \ (((head) != NULL) ? ( \ (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ sizeof(UT_hash_table) + \ (HASH_BLOOM_BYTELEN))) : 0U) #ifdef NO_DECLTYPE #define HASH_ITER(hh,head,el,tmp) \ for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) #else #define HASH_ITER(hh,head,el,tmp) \ for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) #endif /* obtain a count of items in the hash */ #define HASH_COUNT(head) HASH_CNT(hh,head) #define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) typedef struct UT_hash_bucket { struct UT_hash_handle *hh_head; unsigned count; /* expand_mult is normally set to 0. In this situation, the max chain length * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If * the bucket's chain exceeds this length, bucket expansion is triggered). * However, setting expand_mult to a non-zero value delays bucket expansion * (that would be triggered by additions to this particular bucket) * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. * (The multiplier is simply expand_mult+1). The whole idea of this * multiplier is to reduce bucket expansions, since they are expensive, in * situations where we know that a particular bucket tends to be overused. * It is better to let its chain length grow to a longer yet-still-bounded * value, than to do an O(n) bucket expansion too often. */ unsigned expand_mult; } UT_hash_bucket; /* random signature used only to find hash tables in external analysis */ #define HASH_SIGNATURE 0xa0111fe1u #define HASH_BLOOM_SIGNATURE 0xb12220f2u typedef struct UT_hash_table { UT_hash_bucket *buckets; unsigned num_buckets, log2_num_buckets; unsigned num_items; struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ /* in an ideal situation (all buckets used equally), no bucket would have * more than ceil(#items/#buckets) items. that's the ideal chain length. */ unsigned ideal_chain_maxlen; /* nonideal_items is the number of items in the hash whose chain position * exceeds the ideal chain maxlen. these items pay the penalty for an uneven * hash distribution; reaching them in a chain traversal takes >ideal steps */ unsigned nonideal_items; /* ineffective expands occur when a bucket doubling was performed, but * afterward, more than half the items in the hash had nonideal chain * positions. If this happens on two consecutive expansions we inhibit any * further expansion, as it's not helping; this happens when the hash * function isn't a good fit for the key domain. When expansion is inhibited * the hash will still work, albeit no longer in constant time. */ unsigned ineff_expands, noexpand; uint32_t signature; /* used only to find hash tables in external analysis */ #ifdef HASH_BLOOM uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ uint8_t *bloom_bv; uint8_t bloom_nbits; #endif } UT_hash_table; typedef struct UT_hash_handle { struct UT_hash_table *tbl; void *prev; /* prev element in app order */ void *next; /* next element in app order */ struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ struct UT_hash_handle *hh_next; /* next hh in bucket order */ void *key; /* ptr to enclosing struct's key */ unsigned keylen; /* enclosing struct's key len */ unsigned hashv; /* result of hash-fcn(key) */ } UT_hash_handle; #endif /* UTHASH_H */ ntop-n2n-90215bd/legacy/000077500000000000000000000000001422132035700147605ustar00rootroot00000000000000ntop-n2n-90215bd/legacy/README.md000066400000000000000000000027151422132035700162440ustar00rootroot00000000000000# Removed Features This folder contains a list N2N legacy features which have been dropped due to maintainance cost versus effective use and benefits. Multiple Transops ----------------- N2N used to initialize all the available transops and use the "tick" function of the transops to decide which transop to use before sending a packet. This however has the following problems: - It only works with the keyfile, whereas with normal encryption we inizialize and keep structures that we don't need. - It is unfeasable as an edge node is required to implement all the transops in order to properly talk with other edge nodes (via keyfile). - It rises the complexity of the code. - It is not clear which transop will be used. - Mixing multiple encyptions together is not necessarily a good idea to improve security as a vulnerability in at least one encryption method will leak some information. Keyfile and Key Rotation ------------------------ The keyfile mechanism allowed N2N users to specify a keyfile to be used to periodically rotate keys and encryption methods. However, it has the following problems: - This feature is obscure for most of the users and poorly documented. - It is tightly integrated in the core whereas it is used by only a few people (if any). In conclusion the main problem is the complexity that it adds to the code. In a possible future rework this could be integrated as an extention (e.g. a specific trasop) without rising the core complexity. ntop-n2n-90215bd/legacy/edge_keyschedule.c000066400000000000000000000062101422132035700204140ustar00rootroot00000000000000typedef struct n2n_tostat { uint8_t can_tx; /* Does this transop have a valid SA for encoding. */ n2n_cipherspec_t tx_spec; /* If can_tx, the spec used to encode. */ } n2n_tostat_t; typedef uint32_t n2n_sa_t; /* security association number */ typedef int (*n2n_transaddspec_f)( struct n2n_trans_op * arg, const n2n_cipherspec_t * cspec ); typedef n2n_tostat_t (*n2n_transtick_f)( struct n2n_trans_op * arg, time_t now ); /** Read in a key-schedule file, parse the lines and pass each line to the * appropriate trans_op for parsing of key-data and adding key-schedule * entries. The lookup table of time->trans_op is constructed such that * encoding can be passed to the correct trans_op. The trans_op internal table * will then determine the best SA for that trans_op from the key schedule to * use for encoding. */ static int edge_init_keyschedule(n2n_edge_t *eee) { #define N2N_NUM_CIPHERSPECS 32 int retval = -1; ssize_t numSpecs=0; n2n_cipherspec_t specs[N2N_NUM_CIPHERSPECS]; size_t i; time_t now = time(NULL); numSpecs = n2n_read_keyfile(specs, N2N_NUM_CIPHERSPECS, eee->conf.keyschedule); if(numSpecs > 0) { traceEvent(TRACE_NORMAL, "keyfile = %s read -> %d specs.\n", optarg, (signed int)numSpecs); for (i=0; i < (size_t)numSpecs; ++i) { n2n_transform_t idx = (n2n_transform_t) specs[i].t; if(idx != eee->transop.transform_id) { traceEvent(TRACE_ERROR, "changing transop in keyschedule is not supported"); retval = -1; } if(eee->transop.addspec != NULL) retval = eee->transop.addspec(&eee->transop, &(specs[i])); if (0 != retval) { traceEvent(TRACE_ERROR, "keyschedule failed to add spec[%u] to transop[%d].\n", (unsigned int)i, idx); return retval; } } n2n_tick_transop(eee, now); } else traceEvent(TRACE_ERROR, "Failed to process '%s'", eee->conf.keyschedule); return retval; } #if 0 if(recvlen >= 6) { if(0 == memcmp(udp_buf, "reload", 6)) { if(strlen(eee->conf.keyschedule) > 0) { if(edge_init_keyschedule(eee) == 0) { msg_len=0; msg_len += snprintf((char *)(udp_buf+msg_len), (N2N_PKT_BUF_SIZE-msg_len), "> OK\n"); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, (struct sockaddr *)&sender_sock, sizeof(struct sockaddr_in)); } return; } } } #endif #if 0 case'K': { if(conf->encrypt_key) { traceEvent(TRACE_ERROR, "Error: -K and -k options are mutually exclusive"); exit(1); } else { strncpy(conf->keyschedule, optargument, N2N_PATHNAME_MAXLEN-1); /* strncpy does not add NULL if the source has no NULL. */ conf->keyschedule[N2N_PATHNAME_MAXLEN-1] = 0; traceEvent(TRACE_NORMAL, "keyfile = '%s'\n", conf->keyschedule); } break; } #endif #if 0 printf("-K | Specify a key schedule file to load. Not with -k.\n"); #endif ntop-n2n-90215bd/legacy/gen_keyfile.py000077500000000000000000000020301422132035700176110ustar00rootroot00000000000000#!/usr/bin/env python # (c) 2009 Richard Andrews # Program to generate a n2n_edge key schedule file for twofish keys # Each key line consists of the following element # # # where , are UNIX time_t values of key valid period # is the transform ID (=2 for twofish) # is twofish-specific data as follows # _ import os import sys import time import random NUM_KEYS=30 KEY_LIFE=300 KEY_LEN=16 now=time.time() start_sa=random.randint( 0, 0xffffffff ) random.seed(now) # note now is a floating point time value def rand_key(): key=str() for i in range(0,KEY_LEN): key += "%02x"%( random.randint( 0, 255) ) return key for i in range(0,NUM_KEYS): from_time = now + (KEY_LIFE * (i-1) ) until_time = now + (KEY_LIFE * (i+1) ) key = rand_key() sa_idx = start_sa + i transform_id = random.randint( 2, 3 ) sys.stdout.write("%d %d %d %d_%s\n"%(from_time, until_time, transform_id,sa_idx, key) ) ntop-n2n-90215bd/legacy/n2n_keyfile.c000066400000000000000000000130401422132035700173270ustar00rootroot00000000000000/** * (C) 2007-18 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #include "n2n_keyfile.h" #include #include #include #include #ifdef WIN32 char *strsep( char **ppsz_string, const char *psz_delimiters ) { char *p; char *psz_string = *ppsz_string; if( !psz_string ) return NULL; p = strpbrk( psz_string, psz_delimiters ); if( !p ) { *ppsz_string = NULL; return psz_string; } *p++ = '\0'; *ppsz_string = p; return psz_string; } #endif /* Parse hex nibbles in ascii until a non-nibble character is found. Nibble * characters are 0-9, a-f and A-F. * * Return number of bytes parsed into keyBuf or a negative error code. */ ssize_t n2n_parse_hex( uint8_t * keyBuf, size_t keyLen, const char * textKey, size_t textLen) { ssize_t retval=0; uint8_t * pout=keyBuf; size_t octet=0; const char * textEnd; const char * pbeg; textEnd = textKey+textLen; pbeg=textKey; while ( ( pbeg + 1 < textEnd ) && ( retval < (ssize_t)keyLen ) ) { if ( 1 != sscanf( pbeg, "%02x", (unsigned int*)&octet ) ) { retval=-1; break; } *pout = (octet & 0xff); ++pout; ++retval; pbeg += 2; } return retval; } static int parseKeyLine( n2n_cipherspec_t * spec, const char * linein ) { /* parameters are separated by whitespace */ char line[N2N_KEYFILE_LINESIZE]; char * lp=line; const char * token; strncpy( line, linein, N2N_KEYFILE_LINESIZE ); memset( spec, 0, sizeof( n2n_cipherspec_t ) ); /* decode valid_from time */ token = strsep( &lp, DELIMITERS ); if ( !token ) { goto error; } spec->valid_from = atol(token); /* decode valid_until time */ token = strsep( &lp, DELIMITERS ); if ( !token ) { goto error; } spec->valid_until = atol(token); /* decode the transform number */ token = strsep( &lp, DELIMITERS ); if ( !token ) { goto error; } spec->t = atoi(token); /* The reset if opaque key data */ token = strsep( &lp, DELIMITERS ); if ( !token ) { goto error; } strncpy( (char *)spec->opaque, token, N2N_MAX_KEYSIZE ); spec->opaque_size=strlen( (char *)spec->opaque); return 0; error: return -1; } #define SEP "/" int validCipherSpec( const n2n_cipherspec_t * k, time_t now ) { if ( k->valid_until < k->valid_from ) { goto bad; } if ( k->valid_from > now ) { goto bad; } if ( k->valid_until < now ) { goto bad; } return 0; bad: return -1; } /* Read key control file and return the number of specs stored or a negative * error code. * * As the specs are read in the from and until time values are compared to * present time. Only those keys which are valid are stored. */ int n2n_read_keyfile( n2n_cipherspec_t * specs, /* fill out this array of cipherspecs */ size_t numspecs, /* number of slots in the array. */ const char * ctrlfile_path ) /* path to control file */ { /* Each line contains one cipherspec. */ int retval=0; FILE * fp=NULL; size_t idx=0; time_t now = time(NULL); traceEvent( TRACE_DEBUG, "Reading '%s'\n", ctrlfile_path ); fp = fopen( ctrlfile_path, "r" ); if ( fp ) { /* Read the file a line a time with fgets. */ char line[N2N_KEYFILE_LINESIZE]; size_t lineNum=0; while ( idx < numspecs ) { n2n_cipherspec_t * k = &(specs[idx]); fgets( line, N2N_KEYFILE_LINESIZE, fp ); ++lineNum; if ( strlen(line) > 1 ) { if ( 0 == parseKeyLine( k, line ) ) { if ( k->valid_until > now ) { traceEvent( TRACE_INFO, " --> [%u] from %lu, until %lu, transform=%hu, data=%s\n", idx, k->valid_from, k->valid_until, k->t, k->opaque ); ++retval; ++idx; } else { traceEvent( TRACE_INFO, " --X [%u] from %lu, until %lu, transform=%hu, data=%s\n", idx, k->valid_from, k->valid_until, k->t, k->opaque ); } } else { traceEvent( TRACE_WARNING, "Failed to decode line %u\n", lineNum ); } } if ( feof(fp) ) { break; } line[0]=0; /* this line has been consumed */ } fclose( fp); fp=NULL; } else { traceEvent( TRACE_ERROR, "Failed to open '%s'\n", ctrlfile_path ); retval = -1; } return retval; } ntop-n2n-90215bd/legacy/n2n_keyfile.h000066400000000000000000000113111422132035700173330ustar00rootroot00000000000000/** * (C) 2007-18 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /** Key files * * Edge implements a very simple interface for getting instructions about * rolling keys. * * Key definitions are written as individual files in /.key. The * format of each key is a single line of hex nibbles as follows: * * 0102030405060708090a0b0c0d0e0f * * Any external key exchange mechanism can receive the key data write it into * the keyfiles. * * To control which keys are active at what times the key control file is * used. This is a single file which is periodically reread. It contains key * definitions in chronological order with one line per key definition as * follows: * * * * edge reads the key control file periodically to get updates in policy. edge * holds a number of keys in memory. Data can be decoded if it was encoded by * any of the keys still in memory. By having at least 2 keys in memory it * allows for clock skew and transmission delay when encoder and decoder roll * keys at slightly different times. The amount of overlap in the valid time * ranges provides the tolerance to timing skews in the system. * * The keys have the same level of secrecy as any other user file. Existing * UNIX permission systems can be used to provide access controls. * */ /** How Edge Uses The Key Schedule * * Edge provides state space for a number of transform algorithms. Each * transform uses its state space to store the SA information for its keys as * found in the key file. When a packet is received the transform ID is in * plain text. The packets is then sent to that transform for decoding. Each * transform can store its SA numbers differently (or not at all). The * transform code then finds the SA number, then finds the cipher (with key) in * the state space and uses this to decode the packet. * * To support this, as edge reads each key line, it passes it to the * appropriate transform to parse the line and store the SA information in its * state space. * * When encoding a packet, edge has several transforms and potentially valid * SAs to choose from. To keep track of which one to use for encoding edge does * its own book-keeping as each key line is passed to the transform code: it * stores a lookup of valid_from -> transform. When encoding a packet it then * just calls the transform with the best valid_from in the table. The * transform's own state space has all the SAs for its keys and the best of * those is chosen. */ #if !defined( N2N_KEYFILE_H_ ) #define N2N_KEYFILE_H_ #include "n2n_wire.h" #include #define N2N_MAX_KEYSIZE 256 /* bytes */ #define N2N_MAX_NUM_CIPHERSPECS 8 #define N2N_KEYPATH_SIZE 256 #define N2N_KEYFILE_LINESIZE 256 /** This structure stores an encryption cipher spec. */ struct n2n_cipherspec { n2n_transform_t t; /* N2N_TRANSFORM_ID_xxx for this spec. */ time_t valid_from; /* Start using the key at this time. */ time_t valid_until; /* Key is valid if time < valid_until. */ uint16_t opaque_size; /* Size in bytes of key. */ uint8_t opaque[N2N_MAX_KEYSIZE];/* Key matter. */ }; typedef struct n2n_cipherspec n2n_cipherspec_t; static const char * const DELIMITERS=" \t\n\r"; /** @return number of cipherspec items filled. */ int n2n_read_keyfile( n2n_cipherspec_t * specs, /* fill out this array of cipherspecs */ size_t numspecs, /* number of slots in the array. */ const char * ctrlfile_path ); /* path to control file */ int validCipherSpec( const n2n_cipherspec_t * k, time_t now ); ssize_t n2n_parse_hex( uint8_t * keyBuf, size_t keyMax, const char * textKey, size_t textLen ); /*----------------------------------------------------------------------------*/ #endif /* #if !defined( N2N_KEYFILE_H_ ) */ ntop-n2n-90215bd/legacy/transform_aes.c000066400000000000000000000550661422132035700200030ustar00rootroot00000000000000/** * (C) 2007-18 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #include "n2n_transforms.h" #if defined(N2N_HAVE_AES) #include "openssl/aes.h" #include "openssl/sha.h" #ifndef _MSC_VER /* Not included in Visual Studio 2008 */ #include /* index() */ #endif #define N2N_AES_NUM_SA 32 /* space for SAa */ #define N2N_AES_TRANSFORM_VERSION 1 /* version of the transform encoding */ #define N2N_AES_IVEC_SIZE 32 /* Enough space for biggest AES ivec */ #define AES256_KEY_BYTES (256/8) #define AES192_KEY_BYTES (192/8) #define AES128_KEY_BYTES (128/8) typedef unsigned char n2n_aes_ivec_t[N2N_AES_IVEC_SIZE]; struct sa_aes { n2n_cipherspec_t spec; /* cipher spec parameters */ n2n_sa_t sa_id; /* security association index */ AES_KEY enc_key; /* tx key */ AES_KEY dec_key; /* tx key */ AES_KEY iv_enc_key; /* key used to encrypt the IV */ uint8_t iv_ext_val[AES128_KEY_BYTES]; /* key used to extend the random IV seed to full block size */ }; typedef struct sa_aes sa_aes_t; /** Aes transform state data. * * With a key-schedule in place this will be populated with a number of * SAs. Each SA has a lifetime and some opque data. The opaque data for aes * consists of the SA number and key material. * */ struct transop_aes { ssize_t tx_sa; size_t num_sa; sa_aes_t sa[N2N_AES_NUM_SA]; u_int8_t psk_mode; }; typedef struct transop_aes transop_aes_t; static ssize_t aes_find_sa( const transop_aes_t * priv, const n2n_sa_t req_id ); static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_size, size_t sa_num); static int transop_deinit_aes( n2n_trans_op_t * arg ) { transop_aes_t * priv = (transop_aes_t *)arg->priv; size_t i; if ( priv ) { /* Memory was previously allocated */ for (i=0; isa[i]); sa->sa_id=0; } priv->num_sa=0; priv->tx_sa=-1; free(priv); } arg->priv=NULL; /* return to fully uninitialised state */ return 0; } static size_t aes_choose_tx_sa( transop_aes_t * priv, const u_int8_t * peer_mac ) { return priv->tx_sa; /* set in tick */ } static ssize_t aes_choose_rx_sa( transop_aes_t * priv, const u_int8_t * peer_mac, ssize_t sa_rx) { if(!priv->psk_mode) return aes_find_sa(priv, sa_rx); else /* NOTE the sa_rx of the packet is ignored in this case */ return 0; } /* AES plaintext preamble */ #define TRANSOP_AES_VER_SIZE 1 /* Support minor variants in encoding in one module. */ #define TRANSOP_AES_SA_SIZE 4 #define TRANSOP_AES_IV_SEED_SIZE 8 #define TRANSOP_AES_PREAMBLE_SIZE (TRANSOP_AES_VER_SIZE + TRANSOP_AES_SA_SIZE + TRANSOP_AES_IV_SEED_SIZE) /* AES ciphertext preamble */ #define TRANSOP_AES_NONCE_SIZE 4 /* Return the best acceptable AES key size (in bytes) given an input keysize. * * The value returned will be one of AES128_KEY_BYTES, AES192_KEY_BYTES or * AES256_KEY_BYTES. */ static size_t aes_best_keysize(size_t numBytes) { if (numBytes >= AES256_KEY_BYTES ) { return AES256_KEY_BYTES; } else if (numBytes >= AES192_KEY_BYTES) { return AES192_KEY_BYTES; } else { return AES128_KEY_BYTES; } } static void set_aes_cbc_iv(sa_aes_t *sa, n2n_aes_ivec_t ivec, uint64_t iv_seed) { uint8_t iv_full[AES_BLOCK_SIZE]; /* Extend the seed to full block size via the fixed ext value */ memcpy(iv_full, sa->iv_ext_val, sizeof(iv_seed)); // note: only 64bits used of 128 available memcpy(iv_full + sizeof(iv_seed), &iv_seed, sizeof(iv_seed)); /* Encrypt the IV with secret key to make it unpredictable. * As discussed in https://github.com/ntop/n2n/issues/72, it's important to * have an unpredictable IV since the initial part of the packet plaintext * can be easily reconstructed from plaintext headers and used by an attacker * to perform differential analysis. */ AES_ecb_encrypt(iv_full, ivec, &sa->iv_enc_key, AES_ENCRYPT); } /** The aes packet format consists of: * * - a 8-bit aes encoding version in clear text * - a 32-bit SA number in clear text * - a 64-bit random IV seed * - ciphertext encrypted from a 32-bit nonce followed by the payload. * * [V|SSSS|II|nnnnDDDDDDDDDDDDDDDDDDDDD] * |<------ encrypted ------>| */ static int transop_encode_aes( n2n_trans_op_t * arg, uint8_t * outbuf, size_t out_len, const uint8_t * inbuf, size_t in_len, const uint8_t * peer_mac) { int len2=-1; transop_aes_t * priv = (transop_aes_t *)arg->priv; uint8_t assembly[N2N_PKT_BUF_SIZE] = {0}; uint32_t * pnonce; if ( (in_len + TRANSOP_AES_NONCE_SIZE) <= N2N_PKT_BUF_SIZE ) { if ( (in_len + TRANSOP_AES_NONCE_SIZE + TRANSOP_AES_PREAMBLE_SIZE) <= out_len ) { int len=-1; size_t idx=0; sa_aes_t * sa; size_t tx_sa_num = 0; uint64_t iv_seed = 0; uint8_t padding = 0; n2n_aes_ivec_t enc_ivec = {0}; /* The transmit sa is periodically updated */ tx_sa_num = aes_choose_tx_sa( priv, peer_mac ); sa = &(priv->sa[tx_sa_num]); /* Proper Tx SA index */ traceEvent( TRACE_DEBUG, "encode_aes %lu with SA %lu.", in_len, sa->sa_id ); /* Encode the aes format version. */ encode_uint8( outbuf, &idx, N2N_AES_TRANSFORM_VERSION ); /* Encode the security association (SA) number */ encode_uint32( outbuf, &idx, sa->sa_id ); /* Generate and encode the IV seed. * Using two calls to rand() because RAND_MAX is usually < 64bit * (e.g. linux) and sometimes < 32bit (e.g. Windows). */ ((uint32_t*)&iv_seed)[0] = rand(); ((uint32_t*)&iv_seed)[1] = rand(); encode_buf(outbuf, &idx, &iv_seed, sizeof(iv_seed)); /* Encrypt the assembly contents and write the ciphertext after the SA. */ len = in_len + TRANSOP_AES_NONCE_SIZE; /* The assembly buffer is a source for encrypting data. The nonce is * written in first followed by the packet payload. The whole * contents of assembly are encrypted. */ pnonce = (uint32_t *)assembly; *pnonce = rand(); memcpy( assembly + TRANSOP_AES_NONCE_SIZE, inbuf, in_len ); /* Need at least one encrypted byte at the end for the padding. */ len2 = ( (len / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; /* Round up to next whole AES adding at least one byte. */ padding = (len2-len); assembly[len2 - 1] = padding; traceEvent( TRACE_DEBUG, "padding = %u, seed = %016lx", padding, iv_seed ); set_aes_cbc_iv(sa, enc_ivec, iv_seed); AES_cbc_encrypt( assembly, /* source */ outbuf + TRANSOP_AES_PREAMBLE_SIZE, /* dest */ len2, /* enc size */ &(sa->enc_key), enc_ivec, AES_ENCRYPT ); len2 += TRANSOP_AES_PREAMBLE_SIZE; /* size of data carried in UDP. */ } else { traceEvent( TRACE_ERROR, "encode_aes outbuf too small." ); } } else { traceEvent( TRACE_ERROR, "encode_aes inbuf too big to encrypt." ); } return len2; } /* Search through the array of SAs to find the one with the required ID. * * @return array index where found or -1 if not found */ static ssize_t aes_find_sa( const transop_aes_t * priv, const n2n_sa_t req_id ) { size_t i; for (i=0; i < priv->num_sa; ++i) { const sa_aes_t * sa=NULL; sa = &(priv->sa[i]); if (req_id == sa->sa_id) { return i; } } return -1; } /* See transop_encode_aes for packet format */ static int transop_decode_aes( n2n_trans_op_t * arg, uint8_t * outbuf, size_t out_len, const uint8_t * inbuf, size_t in_len, const uint8_t * peer_mac) { int len=0; transop_aes_t * priv = (transop_aes_t *)arg->priv; uint8_t assembly[N2N_PKT_BUF_SIZE]; if ( ( (in_len - TRANSOP_AES_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE ) /* Cipher text fits in assembly */ && (in_len >= (TRANSOP_AES_PREAMBLE_SIZE + TRANSOP_AES_NONCE_SIZE) ) /* Has at least version, SA, iv seed and nonce */ ) { n2n_sa_t sa_rx; ssize_t sa_idx=-1; size_t rem=in_len; size_t idx=0; uint8_t aes_enc_ver=0; uint64_t iv_seed=0; /* Get the encoding version to make sure it is supported */ decode_uint8( &aes_enc_ver, inbuf, &rem, &idx ); if ( N2N_AES_TRANSFORM_VERSION == aes_enc_ver ) { /* Get the SA number and make sure we are decrypting with the right one. */ decode_uint32( &sa_rx, inbuf, &rem, &idx ); sa_idx = aes_choose_rx_sa(priv, peer_mac, sa_rx); if ( sa_idx >= 0 ) { sa_aes_t * sa = &(priv->sa[sa_idx]); /* Get the IV seed */ decode_buf((uint8_t *)&iv_seed, sizeof(iv_seed), inbuf, &rem, &idx); traceEvent( TRACE_DEBUG, "decode_aes %lu with SA %lu and seed %016lx", in_len, sa->sa_id, iv_seed ); len = (in_len - TRANSOP_AES_PREAMBLE_SIZE); if ( 0 == (len % AES_BLOCK_SIZE ) ) { uint8_t padding; n2n_aes_ivec_t dec_ivec = {0}; set_aes_cbc_iv(sa, dec_ivec, iv_seed); AES_cbc_encrypt( (inbuf + TRANSOP_AES_PREAMBLE_SIZE), assembly, /* destination */ len, &(sa->dec_key), dec_ivec, AES_DECRYPT ); /* last byte is how much was padding: max value should be * AES_BLOCKSIZE-1 */ padding = assembly[ len-1 ] & 0xff; if ( len >= (padding + TRANSOP_AES_NONCE_SIZE)) { /* strictly speaking for this to be an ethernet packet * it is going to need to be even bigger; but this is * enough to prevent segfaults. */ traceEvent( TRACE_DEBUG, "padding = %u", padding ); len -= padding; len -= TRANSOP_AES_NONCE_SIZE; /* size of ethernet packet */ /* Step over 4-byte random nonce value */ memcpy( outbuf, assembly + TRANSOP_AES_NONCE_SIZE, len ); } else { traceEvent( TRACE_WARNING, "UDP payload decryption failed." ); } } else { traceEvent( TRACE_WARNING, "Encrypted length %d is not a multiple of AES_BLOCK_SIZE (%d)", len, AES_BLOCK_SIZE ); len = 0; } } else { /* Wrong security association; drop the packet as it is undecodable. */ traceEvent( TRACE_ERROR, "decode_aes SA number %lu not found.", sa_rx ); /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ } } else { /* Wrong security association; drop the packet as it is undecodable. */ traceEvent( TRACE_ERROR, "decode_aes unsupported aes version %u.", aes_enc_ver ); /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ } } else { traceEvent( TRACE_ERROR, "decode_aes inbuf wrong size (%ul) to decrypt.", in_len ); } return len; } struct sha512_keybuf { uint8_t enc_dec_key[AES256_KEY_BYTES]; /* The key to use for AES CBC encryption/decryption */ uint8_t iv_enc_key[AES128_KEY_BYTES]; /* The key to use to encrypt the IV with AES ECB */ uint8_t iv_ext_val[AES128_KEY_BYTES]; /* A value to extend the IV seed */ }; /* size: SHA512_DIGEST_LENGTH */ /* NOTE: the caller should adjust priv->num_sa accordingly */ static int setup_aes_key(transop_aes_t *priv, const uint8_t *key, ssize_t key_size, size_t sa_num) { sa_aes_t * sa = &(priv->sa[sa_num]); size_t aes_keysize_bytes; size_t aes_keysize_bits; struct sha512_keybuf keybuf; /* Clear out any old possibly longer key matter. */ memset( &(sa->enc_key), 0, sizeof(sa->enc_key) ); memset( &(sa->dec_key), 0, sizeof(sa->dec_key) ); memset( &(sa->iv_enc_key), 0, sizeof(sa->iv_enc_key) ); memset( &(sa->iv_ext_val), 0, sizeof(sa->iv_ext_val) ); /* We still use aes_best_keysize (even not necessary since we hash the key * into the 256bits enc_dec_key) to let the users choose the degree of encryption. * Long keys will pick AES192 or AES256 with more robust but expensive encryption. */ aes_keysize_bytes = aes_best_keysize(key_size); aes_keysize_bits = 8 * aes_keysize_bytes; /* Hash the main key to generate subkeys */ SHA512(key, key_size, (u_char*)&keybuf); /* setup of enc_key/dec_key, used for the CBC encryption */ AES_set_encrypt_key(keybuf.enc_dec_key, aes_keysize_bits, &(sa->enc_key)); AES_set_decrypt_key(keybuf.enc_dec_key, aes_keysize_bits, &(sa->dec_key)); /* setup of iv_enc_key and iv_ext_val, used for generating the CBC IV */ AES_set_encrypt_key(keybuf.iv_enc_key, sizeof(keybuf.iv_enc_key) * 8, &(sa->iv_enc_key)); memcpy(sa->iv_ext_val, keybuf.iv_ext_val, sizeof(keybuf.iv_ext_val)); traceEvent( TRACE_DEBUG, "transop_addspec_aes sa_id=%u, %u bits key=%s.\n", priv->sa[sa_num].sa_id, aes_keysize_bits, key); return(0); } /* * priv: pointer to transform state * keybuf: buffer holding the key * pstat: length of keybuf */ static void add_aes_key(transop_aes_t *priv, uint8_t *keybuf, ssize_t pstat) { setup_aes_key(priv, keybuf, pstat, priv->num_sa); ++(priv->num_sa); } static int transop_addspec_aes( n2n_trans_op_t * arg, const n2n_cipherspec_t * cspec ) { int retval = 1; ssize_t pstat=-1; transop_aes_t * priv = (transop_aes_t *)arg->priv; uint8_t keybuf[N2N_MAX_KEYSIZE]; if ( priv->num_sa < N2N_AES_NUM_SA ) { const char * op = (const char *)cspec->opaque; const char * sep = index( op, '_' ); if ( sep ) { char tmp[256]; size_t s; s = sep - op; memcpy( tmp, cspec->opaque, s ); tmp[s]=0; s = strlen(sep+1); /* sep is the _ which might be immediately followed by NULL */ priv->sa[priv->num_sa].spec = *cspec; priv->sa[priv->num_sa].sa_id = strtoul(tmp, NULL, 10); memset( keybuf, 0, N2N_MAX_KEYSIZE ); pstat = n2n_parse_hex( keybuf, N2N_MAX_KEYSIZE, sep+1, s ); if ( pstat > 0 ) { add_aes_key(priv, keybuf, pstat); retval = 0; } } else { traceEvent( TRACE_ERROR, "transop_addspec_aes : bad key data - missing '_'.\n"); } } else { traceEvent( TRACE_ERROR, "transop_addspec_aes : full.\n"); } return retval; } static n2n_tostat_t transop_tick_aes( n2n_trans_op_t * arg, time_t now ) { transop_aes_t * priv = (transop_aes_t *)arg->priv; size_t i; int found=0; n2n_tostat_t r; memset( &r, 0, sizeof(r) ); traceEvent( TRACE_DEBUG, "transop_aes tick num_sa=%u now=%lu", priv->num_sa, now ); for ( i=0; i < priv->num_sa; ++i ) { if ( 0 == validCipherSpec( &(priv->sa[i].spec), now ) ) { time_t remaining = priv->sa[i].spec.valid_until - now; traceEvent( TRACE_INFO, "transop_aes choosing tx_sa=%u (valid for %lu sec)", priv->sa[i].sa_id, remaining ); priv->tx_sa=i; found=1; break; } else { traceEvent( TRACE_DEBUG, "transop_aes tick rejecting sa=%u %lu -> %lu", priv->sa[i].sa_id, priv->sa[i].spec.valid_from, priv->sa[i].spec.valid_until ); } } if ( 0==found) { traceEvent( TRACE_INFO, "transop_aes no keys are currently valid. Keeping tx_sa=%u", priv->tx_sa ); } else { r.can_tx = 1; r.tx_spec.t = N2N_TRANSFORM_ID_AESCBC; r.tx_spec = priv->sa[priv->tx_sa].spec; } return r; } static n2n_tostat_t transop_tick_aes_psk(n2n_trans_op_t * arg, time_t now) { transop_aes_t * priv = (transop_aes_t *)arg->priv; n2n_tostat_t r; memset(&r, 0, sizeof(r)); // Always tx r.can_tx = 1; r.tx_spec.t = N2N_TRANSFORM_ID_AESCBC; r.tx_spec = priv->sa[priv->tx_sa].spec; return r; } int transop_aes_init( n2n_trans_op_t * ttt ) { int retval = 1; transop_aes_t * priv = NULL; if ( ttt->priv ) { transop_deinit_aes( ttt ); } memset( ttt, 0, sizeof( n2n_trans_op_t ) ); priv = (transop_aes_t *) calloc(1, sizeof(transop_aes_t)); if ( NULL != priv ) { size_t i; sa_aes_t * sa=NULL; /* install the private structure. */ ttt->priv = priv; priv->num_sa=0; priv->tx_sa=0; /* We will use this sa index for encoding. */ priv->psk_mode = 0; ttt->transform_id = N2N_TRANSFORM_ID_AESCBC; ttt->addspec = transop_addspec_aes; ttt->tick = transop_tick_aes; /* chooses a new tx_sa */ ttt->deinit = transop_deinit_aes; ttt->fwd = transop_encode_aes; ttt->rev = transop_decode_aes; for(i=0; isa[i]); sa->sa_id=0; memset( &(sa->spec), 0, sizeof(n2n_cipherspec_t) ); memset( &(sa->enc_key), 0, sizeof(sa->enc_key) ); memset( &(sa->dec_key), 0, sizeof(sa->dec_key) ); memset( &(sa->iv_enc_key), 0, sizeof(sa->iv_enc_key) ); memset( &(sa->iv_ext_val), 0, sizeof(sa->iv_ext_val) ); } retval = 0; } else { memset( ttt, 0, sizeof(n2n_trans_op_t) ); traceEvent( TRACE_ERROR, "Failed to allocate priv for aes" ); } return retval; } /* Setup AES in pre-shared key mode */ int transop_aes_setup_psk(n2n_trans_op_t *ttt, n2n_sa_t sa_num, uint8_t *encrypt_pwd, uint32_t encrypt_pwd_len) { int retval = 1; transop_aes_t *priv = (transop_aes_t *)ttt->priv; if(ttt->priv) { /* Replace the tick function with the PSK version of it */ ttt->tick = transop_tick_aes_psk; priv->psk_mode = 1; priv->num_sa=0; priv->tx_sa=0; /* Setup the key to use for encryption/decryption */ add_aes_key(priv, encrypt_pwd, encrypt_pwd_len); retval = 0; } else traceEvent(TRACE_ERROR, "AES priv is not allocated"); return retval; } #else /* #if defined(N2N_HAVE_AES) */ struct transop_aes { ssize_t tx_sa; }; typedef struct transop_aes transop_aes_t; static int transop_deinit_aes( n2n_trans_op_t * arg ) { transop_aes_t * priv = (transop_aes_t *)arg->priv; if ( priv ) { free(priv); } arg->priv=NULL; /* return to fully uninitialised state */ return 0; } static int transop_encode_aes( n2n_trans_op_t * arg, uint8_t * outbuf, size_t out_len, const uint8_t * inbuf, size_t in_len ) { return -1; } static int transop_decode_aes( n2n_trans_op_t * arg, uint8_t * outbuf, size_t out_len, const uint8_t * inbuf, size_t in_len ) { return -1; } static int transop_addspec_aes( n2n_trans_op_t * arg, const n2n_cipherspec_t * cspec ) { traceEvent( TRACE_DEBUG, "transop_addspec_aes AES not built into edge.\n"); return -1; } static n2n_tostat_t transop_tick_aes( n2n_trans_op_t * arg, time_t now ) { n2n_tostat_t r; memset( &r, 0, sizeof(r) ); return r; } int transop_aes_init( n2n_trans_op_t * ttt ) { int retval = 1; transop_aes_t * priv = NULL; if ( ttt->priv ) { transop_deinit_aes( ttt ); } memset( ttt, 0, sizeof( n2n_trans_op_t ) ); priv = (transop_aes_t *) malloc( sizeof(transop_aes_t) ); if ( NULL != priv ) { /* install the private structure. */ ttt->priv = priv; priv->tx_sa=0; /* We will use this sa index for encoding. */ ttt->transform_id = N2N_TRANSFORM_ID_AESCBC; ttt->addspec = transop_addspec_aes; ttt->tick = transop_tick_aes; /* chooses a new tx_sa */ ttt->deinit = transop_deinit_aes; ttt->fwd = transop_encode_aes; ttt->rev = transop_decode_aes; retval = 0; } else { memset( ttt, 0, sizeof(n2n_trans_op_t) ); traceEvent( TRACE_ERROR, "Failed to allocate priv for aes" ); } return retval; } int transop_aes_setup_psk(n2n_trans_op_t *ttt, n2n_sa_t sa_num, uint8_t *encrypt_pwd, uint32_t encrypt_pwd_len) { return 0; } #endif /* #if defined(N2N_HAVE_AES) */ ntop-n2n-90215bd/legacy/transform_tf.c000066400000000000000000000315201422132035700176310ustar00rootroot00000000000000/** * (C) 2007-18 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #include "n2n_transforms.h" #include "twofish.h" #ifndef _MSC_VER /* Not included in Visual Studio 2008 */ #include /* index() */ #endif #define N2N_TWOFISH_NUM_SA 32 /* space for SAa */ #define N2N_TWOFISH_TRANSFORM_VERSION 1 /* version of the transform encoding */ struct sa_twofish { n2n_cipherspec_t spec; /* cipher spec parameters */ n2n_sa_t sa_id; /* security association index */ TWOFISH * enc_tf; /* tx state */ TWOFISH * dec_tf; /* rx state */ }; typedef struct sa_twofish sa_twofish_t; /** Twofish transform state data. * * With a key-schedule in place this will be populated with a number of * SAs. Each SA has a lifetime and some opque data. The opaque data for twofish * consists of the SA number and key material. * */ struct transop_tf { ssize_t tx_sa; size_t num_sa; sa_twofish_t sa[N2N_TWOFISH_NUM_SA]; }; typedef struct transop_tf transop_tf_t; static int transop_deinit_twofish( n2n_trans_op_t * arg ) { transop_tf_t * priv = (transop_tf_t *)arg->priv; size_t i; if ( priv ) { /* Memory was previously allocated */ for (i=0; isa[i]); TwoFishDestroy(sa->enc_tf); /* deallocate TWOFISH */ sa->enc_tf=NULL; TwoFishDestroy(sa->dec_tf); /* deallocate TWOFISH */ sa->dec_tf=NULL; sa->sa_id=0; } priv->num_sa=0; priv->tx_sa=-1; free(priv); } arg->priv=NULL; /* return to fully uninitialised state */ return 0; } static size_t tf_choose_tx_sa( transop_tf_t * priv ) { return priv->tx_sa; /* set in tick */ } #define TRANSOP_TF_VER_SIZE 1 /* Support minor variants in encoding in one module. */ #define TRANSOP_TF_NONCE_SIZE 4 #define TRANSOP_TF_SA_SIZE 4 /** The twofish packet format consists of: * * - a 8-bit twofish encoding version in clear text * - a 32-bit SA number in clear text * - ciphertext encrypted from a 32-bit nonce followed by the payload. * * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] * |<------ encrypted ------>| */ static int transop_encode_twofish( n2n_trans_op_t * arg, uint8_t * outbuf, size_t out_len, const uint8_t * inbuf, size_t in_len, const uint8_t * peer_mac) { int len=-1; transop_tf_t * priv = (transop_tf_t *)arg->priv; uint8_t assembly[N2N_PKT_BUF_SIZE]; uint32_t * pnonce; if ( (in_len + TRANSOP_TF_NONCE_SIZE) <= N2N_PKT_BUF_SIZE ) { if ( (in_len + TRANSOP_TF_NONCE_SIZE + TRANSOP_TF_SA_SIZE + TRANSOP_TF_VER_SIZE) <= out_len ) { size_t idx=0; sa_twofish_t * sa; size_t tx_sa_num = 0; /* The transmit sa is periodically updated */ tx_sa_num = tf_choose_tx_sa( priv ); sa = &(priv->sa[tx_sa_num]); /* Proper Tx SA index */ traceEvent( TRACE_DEBUG, "encode_twofish %lu with SA %lu.", in_len, sa->sa_id ); /* Encode the twofish format version. */ encode_uint8( outbuf, &idx, N2N_TWOFISH_TRANSFORM_VERSION ); /* Encode the security association (SA) number */ encode_uint32( outbuf, &idx, sa->sa_id ); /* The assembly buffer is a source for encrypting data. The nonce is * written in first followed by the packet payload. The whole * contents of assembly are encrypted. */ pnonce = (uint32_t *)assembly; *pnonce = rand(); memcpy( assembly + TRANSOP_TF_NONCE_SIZE, inbuf, in_len ); /* Encrypt the assembly contents and write the ciphertext after the SA. */ len = TwoFishEncryptRaw( assembly, /* source */ outbuf + TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE, in_len + TRANSOP_TF_NONCE_SIZE, /* enc size */ sa->enc_tf); if ( len > 0 ) { len += TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE; /* size of data carried in UDP. */ } else { traceEvent( TRACE_ERROR, "encode_twofish encryption failed." ); } } else { traceEvent( TRACE_ERROR, "encode_twofish outbuf too small." ); } } else { traceEvent( TRACE_ERROR, "encode_twofish inbuf too big to encrypt." ); } return len; } /* Search through the array of SAs to find the one with the required ID. * * @return array index where found or -1 if not found */ static ssize_t twofish_find_sa( const transop_tf_t * priv, const n2n_sa_t req_id ) { size_t i; for (i=0; i < priv->num_sa; ++i) { const sa_twofish_t * sa=NULL; sa = &(priv->sa[i]); if (req_id == sa->sa_id) { return i; } } return -1; } /** The twofish packet format consists of: * * - a 8-bit twofish encoding version in clear text * - a 32-bit SA number in clear text * - ciphertext encrypted from a 32-bit nonce followed by the payload. * * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD] * |<------ encrypted ------>| */ static int transop_decode_twofish( n2n_trans_op_t * arg, uint8_t * outbuf, size_t out_len, const uint8_t * inbuf, size_t in_len, const uint8_t * peer_mac) { int len=0; transop_tf_t * priv = (transop_tf_t *)arg->priv; uint8_t assembly[N2N_PKT_BUF_SIZE]; if ( ( (in_len - (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE)) <= N2N_PKT_BUF_SIZE ) /* Cipher text fits in assembly */ && (in_len >= (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE + TRANSOP_TF_NONCE_SIZE) ) /* Has at least version, SA and nonce */ ) { n2n_sa_t sa_rx; ssize_t sa_idx=-1; size_t rem=in_len; size_t idx=0; uint8_t tf_enc_ver=0; /* Get the encoding version to make sure it is supported */ decode_uint8( &tf_enc_ver, inbuf, &rem, &idx ); if ( N2N_TWOFISH_TRANSFORM_VERSION == tf_enc_ver ) { /* Get the SA number and make sure we are decrypting with the right one. */ decode_uint32( &sa_rx, inbuf, &rem, &idx ); sa_idx = twofish_find_sa(priv, sa_rx); if ( sa_idx >= 0 ) { sa_twofish_t * sa = &(priv->sa[sa_idx]); traceEvent( TRACE_DEBUG, "decode_twofish %lu with SA %lu.", in_len, sa_rx, sa->sa_id ); len = TwoFishDecryptRaw( (void *)(inbuf + TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE), assembly, /* destination */ (in_len - (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE)), sa->dec_tf); if ( len > 0 ) { /* Step over 4-byte random nonce value */ len -= TRANSOP_TF_NONCE_SIZE; /* size of ethernet packet */ memcpy( outbuf, assembly + TRANSOP_TF_NONCE_SIZE, len ); } else { traceEvent( TRACE_ERROR, "decode_twofish decryption failed." ); } } else { /* Wrong security association; drop the packet as it is undecodable. */ traceEvent( TRACE_ERROR, "decode_twofish SA number %lu not found.", sa_rx ); /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ } } else { /* Wrong security association; drop the packet as it is undecodable. */ traceEvent( TRACE_ERROR, "decode_twofish unsupported twofish version %u.", tf_enc_ver ); /* REVISIT: should be able to load a new SA at this point to complete the decoding. */ } } else { traceEvent( TRACE_ERROR, "decode_twofish inbuf wrong size (%ul) to decrypt.", in_len ); } return len; } static int transop_addspec_twofish( n2n_trans_op_t * arg, const n2n_cipherspec_t * cspec ) { int retval = 1; ssize_t pstat=-1; transop_tf_t * priv = (transop_tf_t *)arg->priv; uint8_t keybuf[N2N_MAX_KEYSIZE]; if ( priv->num_sa < N2N_TWOFISH_NUM_SA ) { const char * op = (const char *)cspec->opaque; #ifdef __ANDROID_NDK__ const char *sep = strchr(op, '_'); #else const char * sep = index( op, '_' ); #endif // __ANDROID_NDK__ if ( sep ) { char tmp[256]; size_t s; s = sep - op; memcpy( tmp, cspec->opaque, s ); tmp[s]=0; s = strlen(sep+1); /* sep is the _ which might be immediately followed by NULL */ priv->sa[priv->num_sa].spec = *cspec; priv->sa[priv->num_sa].sa_id = strtoul(tmp, NULL, 10); pstat = n2n_parse_hex( keybuf, N2N_MAX_KEYSIZE, sep+1, s ); if ( pstat > 0 ) { priv->sa[priv->num_sa].enc_tf = TwoFishInit( keybuf, pstat); priv->sa[priv->num_sa].dec_tf = TwoFishInit( keybuf, pstat); traceEvent( TRACE_DEBUG, "transop_addspec_twofish sa_id=%u data=%s.\n", priv->sa[priv->num_sa].sa_id, sep+1); ++(priv->num_sa); retval = 0; } } else { traceEvent( TRACE_ERROR, "transop_addspec_twofish : bad key data - missing '_'.\n"); } } else { traceEvent( TRACE_ERROR, "transop_addspec_twofish : full.\n"); } return retval; } static n2n_tostat_t transop_tick_twofish( n2n_trans_op_t * arg, time_t now ) { transop_tf_t * priv = (transop_tf_t *)arg->priv; size_t i; int found=0; n2n_tostat_t r; memset( &r, 0, sizeof(r) ); traceEvent( TRACE_DEBUG, "transop_tf tick num_sa=%u", priv->num_sa ); for ( i=0; i < priv->num_sa; ++i ) { if ( 0 == validCipherSpec( &(priv->sa[i].spec), now ) ) { time_t remaining = priv->sa[i].spec.valid_until - now; traceEvent( TRACE_INFO, "transop_tf choosing tx_sa=%u (valid for %lu sec)", priv->sa[i].sa_id, remaining ); priv->tx_sa=i; found=1; break; } else { traceEvent( TRACE_DEBUG, "transop_tf tick rejecting sa=%u %lu -> %lu", priv->sa[i].sa_id, priv->sa[i].spec.valid_from, priv->sa[i].spec.valid_until ); } } if ( 0==found) { traceEvent( TRACE_INFO, "transop_tf no keys are currently valid. Keeping tx_sa=%u", priv->tx_sa ); } else { r.can_tx = 1; r.tx_spec.t = N2N_TRANSFORM_ID_TWOFISH; r.tx_spec = priv->sa[priv->tx_sa].spec; } return r; } int transop_twofish_setup_psk( n2n_trans_op_t * ttt, n2n_sa_t sa_num, uint8_t * encrypt_pwd, uint32_t encrypt_pwd_len ) { int retval = 1; transop_tf_t * priv = (transop_tf_t *)ttt->priv; if(priv) { sa_twofish_t *sa; priv->num_sa=1; /* There is one SA in the array. */ priv->tx_sa=0; sa = &(priv->sa[priv->tx_sa]); sa->sa_id=sa_num; sa->spec.valid_until = 0x7fffffff; /* This is a preshared key setup. Both Tx and Rx are using the same security association. */ sa->enc_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); sa->dec_tf = TwoFishInit(encrypt_pwd, encrypt_pwd_len); if ( (sa->enc_tf) && (sa->dec_tf) ) retval = 0; else traceEvent( TRACE_ERROR, "transop_twofish_setup_psk" ); } else traceEvent( TRACE_ERROR, "twofish priv is not allocated" ); return retval; } int transop_twofish_init( n2n_trans_op_t * ttt ) { int retval = 1; transop_tf_t * priv = NULL; if ( ttt->priv ) { transop_deinit_twofish( ttt ); } memset( ttt, 0, sizeof( n2n_trans_op_t ) ); priv = (transop_tf_t *) malloc( sizeof(transop_tf_t) ); if ( NULL != priv ) { size_t i; sa_twofish_t * sa=NULL; /* install the private structure. */ ttt->priv = priv; priv->num_sa=0; priv->tx_sa=0; /* We will use this sa index for encoding. */ ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH; ttt->addspec = transop_addspec_twofish; ttt->tick = transop_tick_twofish; /* chooses a new tx_sa */ ttt->deinit = transop_deinit_twofish; ttt->fwd = transop_encode_twofish; ttt->rev = transop_decode_twofish; for(i=0; isa[i]); sa->sa_id=0; memset( &(sa->spec), 0, sizeof(n2n_cipherspec_t) ); sa->enc_tf=NULL; sa->dec_tf=NULL; } retval = 0; } else { memset( ttt, 0, sizeof(n2n_trans_op_t) ); traceEvent( TRACE_ERROR, "Failed to allocate priv for twofish" ); } return retval; } ntop-n2n-90215bd/n2n.7000066400000000000000000000130541422132035700143040ustar00rootroot00000000000000.TH "n2n_v3" 7 "Sep 27, 2021" "version 3" "Background" .SH NAME n2n version 3 \- version 3 of the n2n decentralised peer-to-peer network overlay VPN. .SH DESCRIPTION n2n is a peer-to-peer network overlay or VPN system that provides layer 2 over layer 3 encapsulation with data transform capabilities such as encryption and compression. This guide also discusses the differences of version 3 of n2n from version 2. .SH PROTOCOLS n2n-3 basically uses the same set of messages to communicate with edges and supernodes. However, due to slight packet format changes, the n2n-3 messages are not compatible with n2n-2. There is no backward compatibility for n2n-2. .SH ENCRYPTION n2n-3 offers four different ciphers for payload encryption as well as optional header encryption. Earlier versions of n2n-2 provided a mechanism using a key schedule which has been removed in n2n-3. A basic user authentication scheme relying on asymmetric cryptography has been added to n2n-3. n2n-3 provides the following ciphers to chose from for payload encryption; more can be added as required: .TP .B (1) NULL Data is encapsulated unchanged. Useful for testing and high-performance, low sensitivity applications. .TP .B (2) TF-CTS Twofish AES candidate in CTS mode. .TP .B (3) AES-CTS AES in CTS mode with up to 256-bit key. .TP .B (4) CHACHA20 ChaCha20, a well known stream cipher developped by Daniel J. Bernstein. .TP .B (5) SPECK-CTR A fast block cipher developped by the NSA used as stream cipher in CTR mode. .TP Full Header Encyption The optional full header encryption also encrypts packets' header which include some administrative data. In addition, it adds replay protection. .TP User Password Authentication n2n-3 implements an optional user-password authentication scheme. A key generator assists in generating user's public keys to be stored at the supernode side. .SH COPMPRESSION LZO for payload compression is an always available option at n2n-3. If compiled with zstdlib support, ZSTD is at optional service as well. .SH EXTENSIBILITY n2n-3 decouples the data transform system from the core of the edge operation. This allows for easier addition of new data transform operations. n2n-3 reserves some standard transform identifiers (such as TwoFish encryption) but allocates transform identifiers for user-defined transforms. This allows anyone to add to n2n new private transforms without breaking compatibility with the standard offering. .SH FEDERATED SUPERNODES n2n-3 incorporates the capability of multiple supernodes to be federated. Federation acts transparently and balances the workload evenly among the federated supernodes. Supernodes keep track of edges connected to different supernodes and forward packets as required. This feature naturally supports fail-over and this increases redundancy and resilience. .P Information on additional supernodes is propagated to all edges. In addition, the n2n-3 edge implementation allows multiple supernodes to be specified on the command line. Edges monitor the current supernode for responses to REGISTER_SUPER as well as PING messages. After three responses from current supernode are missed or when a better supernode in terms of significant lower workload is found, the edge tries to connect to another supernode. It cycles through the list f supernodes which over and over again is sorted according to reported workload. .SH MANAGEMENT CONSOLE Edge and supernode in n2n-3 provide a UDP-based management console. Both listen on the localhost address 127.0.0.1. Commands can be sent to the programs by sending to the UDP socket. Responses are returned to the socket from which commands were issued. This only works from the computer on which the programs are running. Statistics can be retrieved and commands issued. The netcat utility is all that is required; but more sophisticated tools could be built on the interface. .SH SUPERNODE AUTHENTICATION The supernode federation name serves as private key shared between the supernodes only. The corresponding public key can be provided to the edges. .SH MESSAGE SUMMARY The following message types work within n2n-3. .TP REGISTER_SUPER Sent from an edge to its local supernode to register its MAC with the community. Also, federated supernodes use this packet format to register to each other. .TP REGISTER_SUPER_ACK Sent from a supernode to an edge to confirm registration. This also carries the definition of the edge socket as seen at the supernode so NAT can be detected and described. Furthermore, it carries information about additional federated supernodes. .TP REGISTER_SUPER_NAK Supernode refusing to register an edge. .TP PACKET Encapsulated ethernet packets sent between edges. Supernodes forward or broadcast these and edges send them direct in peer-to-peer mode. .TP REGISTER A peer-to-peer mode registration request from one edge to another. Supernodes forward these to facilitate NAT crossing introductions. .TP REGISTER_ACK Complete peer-to-peer mode setup between two edges. These messages need to travel direct between edges. .TP QUERY_PEER Queries a supernode about another edge, especially its public socket in case of no peer-to-peer communication can be established. Additionally, it serves as PING to query supernodes about themselves. .TP PEER_INFO Answers the QUERY_PEER; it also covers the special case of the PING query, internally called PONG. .SH AUTHORS .TP Richard Andrews andrews (at) ntop.org - main author of n2n-2 .TP Luca Deri deri (at) ntop.org - code inherited from n2n-1 .SH SEE ALSO ifconfig(8) edge(8) supernode(1) .br the documentation contained in the source code .br the extensive documentation found in n2n's \fBdoc/\fR folder ntop-n2n-90215bd/packages/000077500000000000000000000000001422132035700152725ustar00rootroot00000000000000ntop-n2n-90215bd/packages/centos000077700000000000000000000000001422132035700172242rpmustar00rootroot00000000000000ntop-n2n-90215bd/packages/debian/000077500000000000000000000000001422132035700165145ustar00rootroot00000000000000ntop-n2n-90215bd/packages/debian/Makefile.in000066400000000000000000000024101422132035700205560ustar00rootroot00000000000000# # Change it according to your setup # N2N_HOME=$(PWD)/../.. N2N_BUILD=${N2N_HOME}/packages/debian/n2n all: clean pkg pkg: make -C ../../ if test -e "${N2N_BUILD}"; then /bin/rm -fr ${N2N_BUILD}; fi mkdir -p ${N2N_BUILD}/usr/sbin ${N2N_BUILD}/usr/share/man/man1 ${N2N_BUILD}/usr/share/man/man7 ${N2N_BUILD}/usr/share/man/man8 mkdir -p ${N2N_BUILD}/usr/share/doc/n2n/examples install -m755 ../../supernode ${N2N_BUILD}/usr/sbin/ install -m755 ../../edge ${N2N_BUILD}/usr/sbin/ install -m644 ../../edge.8.gz ${N2N_BUILD}/usr/share/man/man8/ install -m644 ../../supernode.1.gz ${N2N_BUILD}/usr/share/man/man1/ install -m644 ../../n2n.7.gz ${N2N_BUILD}/usr/share/man/man7/ install -m644 ../../community.list ${N2N_BUILD}/usr/share/doc/n2n/examples/ install -m644 ../../doc/*.md ${N2N_BUILD}/usr/share/doc/n2n/ @/bin/rm -f ../n2n*.deb dpkg-buildpackage -rfakeroot -d -us -uc -a@EXTN@ -dpkg-sig --sign builder -k D1EB60BE ../n2n_*deb @\rm -f ../n2n_*dsc ../n2n_*.gz ../n2n_*changes @/bin/mv ../n2n_*deb . @echo @echo "Package built." @/bin/ls n2n_*deb @echo "-------------------------------" -dpkg -I n2n_*deb -dpkg --contents n2n_*deb @echo "-------------------------------" distclean: echo "dummy distclean" install: echo "dummy install" clean: rm -rf *~ *deb ntop-n2n-90215bd/packages/debian/README000066400000000000000000000013671422132035700174030ustar00rootroot00000000000000Prerequisites ------------- apt-get install debhelper fakeroot dpkg-sig EdgeOS ------ We need to replace BusyBox-implemented commands using full-fledged commands by doing (see http://community.ubnt.com/t5/EdgeMAX/ubnt-debian-package-conflict/m-p/421325) curl -O http://ftp.us.debian.org/debian/pool/main/c/coreutils/coreutils_8.5-1_mips.deb dpkg -i --force-all coreutils_8.5-1_mips.deb curl -O http://ftp.us.debian.org/debian/pool/main/t/tar/tar_1.23-3_mips.deb dpkg -i --force-all tar_1.23-3_mips.deb wget http://ftp.us.debian.org/debian/pool/main/f/findutils/findutils_4.4.2-4_mips.deb dpkg -i --force-all findutils_4.4.2-4_mips.deb wget http://ftp.us.debian.org/debian/pool/main/g/gzip/gzip_1.5-1.1_mips.deb dpkg -i --force-all gzip_1.5-1.1_mips.deb ntop-n2n-90215bd/packages/debian/configure000077500000000000000000002503311422132035700204270ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for Makefile.in 1.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Makefile.in' PACKAGE_TARNAME='makefile-in' PACKAGE_VERSION='1.0' PACKAGE_STRING='Makefile.in 1.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS EXTRA_DEP DATE EXTN N2N_VERSION APP target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_edgex ' ac_precious_vars='build_alias host_alias target_alias' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures Makefile.in 1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/makefile-in] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Makefile.in 1.0:";; esac cat <<\_ACEOF Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-edgex Build for Ubiquity-X Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF Makefile.in configure 1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Makefile.in $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Check whether --with-edgex was given. if test "${with_edgex+set}" = set; then : withval=$with_edgex; fi # NOTE: this file is not actually used. You need to edit configure as well! N2N_VERSION=$(../../scripts/version.sh) DEBIAN_VERSION=`cat /etc/debian_version | grep "^8" | wc -l` EXTRA_DEP="" if test $DEBIAN_VERSION = "0"; then EXTRA_DEP=", libzstd1" fi if test "${EXTN+set}" != set; then MACHINE=`uname -m` SHORT_MACHINE=`echo $MACHINE | cut -b1-3` if test $MACHINE = "x86_64"; then EXTN="amd64" else if test $SHORT_MACHINE = "aar"; then EXTN="arm64" else if test $SHORT_MACHINE = "arm"; then EXTN="armhf" else if test $SHORT_MACHINE = "mip"; then EXTN="mips" else EXTN="i386" fi fi fi fi fi if test "${with_edgex+set}" = set; then EXTN="mipsel" fi APP=n2n DATE=`date -R` ac_config_files="$ac_config_files debian/changelog" ac_config_files="$ac_config_files debian/files" ac_config_files="$ac_config_files debian/control" ac_config_files="$ac_config_files debian/rules" ac_config_files="$ac_config_files ../etc/systemd/system/edge.service" ac_config_files="$ac_config_files ../etc/systemd/system/edge@.service" ac_config_files="$ac_config_files ../etc/systemd/system/edge-ntopng@.service" ac_config_files="$ac_config_files ../etc/systemd/system/supernode.service" ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by Makefile.in $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ Makefile.in config.status 1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "debian/changelog") CONFIG_FILES="$CONFIG_FILES debian/changelog" ;; "debian/files") CONFIG_FILES="$CONFIG_FILES debian/files" ;; "debian/control") CONFIG_FILES="$CONFIG_FILES debian/control" ;; "debian/rules") CONFIG_FILES="$CONFIG_FILES debian/rules" ;; "../etc/systemd/system/edge.service") CONFIG_FILES="$CONFIG_FILES ../etc/systemd/system/edge.service" ;; "../etc/systemd/system/edge@.service") CONFIG_FILES="$CONFIG_FILES ../etc/systemd/system/edge@.service" ;; "../etc/systemd/system/edge-ntopng@.service") CONFIG_FILES="$CONFIG_FILES ../etc/systemd/system/edge-ntopng@.service" ;; "../etc/systemd/system/supernode.service") CONFIG_FILES="$CONFIG_FILES ../etc/systemd/system/supernode.service" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ntop-n2n-90215bd/packages/debian/configure.in000066400000000000000000000025741422132035700210350ustar00rootroot00000000000000AC_INIT([Makefile.in], 1.0) AC_ARG_WITH(edgex, [ --with-edgex Build for Ubiquity-X]) # NOTE: this file is not actually used. You need to edit configure as well! N2N_VERSION=$(../../scripts/version.sh) DEBIAN_VERSION=`cat /etc/debian_version | grep "^8" | wc -l` EXTRA_DEP="" if test $DEBIAN_VERSION = "0"; then EXTRA_DEP=", libzstd1" fi if test "${EXTN+set}" != set; then MACHINE=`uname -m` SHORT_MACHINE=`echo $MACHINE | cut -b1-3` if test $MACHINE = "x86_64"; then EXTN="amd64" else if test $SHORT_MACHINE = "aar"; then EXTN="arm64" else if test $SHORT_MACHINE = "arm"; then EXTN="armhf" else if test $SHORT_MACHINE = "mip"; then EXTN="mips" else EXTN="i386" fi fi fi fi fi if test "${with_edgex+set}" = set; then EXTN="mipsel" fi APP=n2n DATE=`date -R` AC_SUBST(APP) AC_SUBST(N2N_VERSION) AC_SUBST(EXTN) AC_SUBST(DATE) AC_SUBST(EXTRA_DEP) AC_CONFIG_FILES(debian/changelog) AC_CONFIG_FILES(debian/files) AC_CONFIG_FILES(debian/control) AC_CONFIG_FILES(debian/rules) AC_CONFIG_FILES(../etc/systemd/system/edge.service) AC_CONFIG_FILES(../etc/systemd/system/edge@.service) AC_CONFIG_FILES(../etc/systemd/system/edge-ntopng@.service) AC_CONFIG_FILES(../etc/systemd/system/supernode.service) AC_CONFIG_FILES(Makefile) AC_OUTPUT ntop-n2n-90215bd/packages/debian/debian/000077500000000000000000000000001422132035700177365ustar00rootroot00000000000000ntop-n2n-90215bd/packages/debian/debian/COPYRIGHT000066400000000000000000001045131422132035700212350ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ntop-n2n-90215bd/packages/debian/debian/README000066400000000000000000000001611422132035700206140ustar00rootroot00000000000000This directory contains the files needed to build the package named 'n2n' for the Debian GNU/Linux distribution. ntop-n2n-90215bd/packages/debian/debian/changelog.in000066400000000000000000000001541422132035700222150ustar00rootroot00000000000000@APP@ (@N2N_VERSION@) table; urgency=high * Last packaged version -- Luca Deri @DATE@ ntop-n2n-90215bd/packages/debian/debian/compat000066400000000000000000000000021422132035700211340ustar00rootroot000000000000009 ntop-n2n-90215bd/packages/debian/debian/conffiles000066400000000000000000000000711422132035700216270ustar00rootroot00000000000000/etc/n2n/edge.conf.sample /etc/n2n/supernode.conf.sample ntop-n2n-90215bd/packages/debian/debian/control.in000066400000000000000000000020071422132035700217450ustar00rootroot00000000000000Source: n2n Section: net Priority: extra Maintainer: Luca Deri Standards-Version: 4.6.0 Build-Depends: Package: n2n Architecture: @EXTN@ Suggests: uml-utilities Depends: ${shlibs:Depends}, ${misc:Depends} @EXTRA_DEP@ Conflicts: n2n (<< 2.1.0-1) Replaces: n2n (<< 2.1.0-1) Description: a layer-two peer-to-peer virtual private network (VPN) n2n is a layer-two peer-to-peer virtual private network (VPN) which allows users to exploit features typical of P2P applications at network instead of application level. This means that users can gain native IP visibility (e.g. two PCs belonging to the same n2n network can ping each other) and be reachable with the same network IP address regardless of the network where they currently belong. In a nutshell, as OpenVPN moved SSL from application (e.g. used to implement the https protocol) to network protocol, n2n moves P2P from application to network level. . Edge is the edge node daemon for n2n which creates a TAP interface to expose the n2n virtual LAN. ntop-n2n-90215bd/packages/debian/debian/dirs000066400000000000000000000000401422132035700206140ustar00rootroot00000000000000usr/sbin etc/systemd etc/init.d ntop-n2n-90215bd/packages/debian/debian/docs000066400000000000000000000000071422132035700206060ustar00rootroot00000000000000README ntop-n2n-90215bd/packages/debian/debian/files.in000066400000000000000000000000531422132035700213660ustar00rootroot00000000000000n2n_@N2N_VERSION@_@EXTN@.deb free optional ntop-n2n-90215bd/packages/debian/debian/n2n.substvars000066400000000000000000000000761422132035700224140ustar00rootroot00000000000000misc:Depends=debconf (>= 0.5) | debconf-2.0 misc:Pre-Depends= ntop-n2n-90215bd/packages/debian/debian/postinst000077500000000000000000000021541422132035700215510ustar00rootroot00000000000000#!/bin/sh -e case "$1" in configure) # continue below ;; abort-upgrade|abort-remove|abort-deconfigure) exit 0 ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 0 ;; esac umask 022 if ! grep -q n2n /etc/group; then echo 'Creating n2n group' /usr/sbin/groupadd -r n2n fi if ! /usr/bin/id -u n2n > /dev/null 2>&1; then echo "Creating n2n user..." /usr/sbin/useradd -M -N -g n2n -r -s /bin/false n2n fi echo "Rebuilding ld cache..." /sbin/ldconfig if [ -f /.dockerenv ]; then exit 0; fi # Start service after upgrade/install systemctl daemon-reload systemctl reset-failed # Enable edge if systemctl -q is-active edge; then # only restart edge if it's already running echo "Restarting n2n edge..." deb-systemd-invoke restart edge fi # Restart specific services if already running deb-systemd-invoke restart 'edge@*.service' 'edge-ntopng@*.service' # Enable supernode if systemctl -q is-active supernode; then # only restart supernode if it's already running echo "Restarting n2n supernode..." deb-systemd-invoke restart supernode fi exit 0 ntop-n2n-90215bd/packages/debian/debian/postrm000066400000000000000000000001111422132035700211760ustar00rootroot00000000000000#!/bin/sh -e set -e #case "$1" in # purge|remove) # # ;; #esac exit 0 ntop-n2n-90215bd/packages/debian/debian/preinst000066400000000000000000000010471422132035700213470ustar00rootroot00000000000000#! /bin/sh # preinst script for n2n # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `install' # * `install' # * `upgrade' # * `abort-upgrade' case "$1" in install|upgrade) ;; abort-upgrade) ;; *) echo "preinst called with unknown argument \`$1'" >&2 exit 0 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. exit 0 ntop-n2n-90215bd/packages/debian/debian/prerm000077500000000000000000000006571422132035700210210ustar00rootroot00000000000000#!/bin/sh set -e if [ -f /.dockerenv ]; then exit 0; fi . /usr/share/debconf/confmodule if [ "$1" = "remove" ]; then deb-systemd-invoke stop edge.service 'edge@*.service' 'edge-ntopng@*.service' deb-systemd-invoke disable edge.service 'edge@*.service' 'edge-ntopng@*.service' deb-systemd-invoke stop supernode.service deb-systemd-invoke disable supernode.service systemctl daemon-reload systemctl reset-failed fi exit 0 ntop-n2n-90215bd/packages/debian/debian/rules.in000077500000000000000000000021461422132035700214260ustar00rootroot00000000000000#!/usr/bin/make -f # Uncomment this to turn on verbose mode. # export DH_VERBOSE=1 # # debian/compat # We should use at least compatibility version 5 # but this requires the whole building process # to be remade and this is something we leave # to when we will have more time # http://www.tin.org/bin/man.cgi?section=7&topic=debhelper # package=@APP@ build: build-stamp build-stamp: dh_testdir clean: dh_testdir dh_testroot dh_clean install: build dh_testdir dh_testroot dh_prep dh_installdirs # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install dh_testdir dh_testroot dh_prep dh_installdirs dh_installinit dh_installdebconf dh_installman dh_strip dh_compress dh_fixperms dh_installdeb cp -r n2n debian cp -r ../etc debian/n2n find debian/n2n -name "*.in" -exec /bin/rm {} ';' find debian/n2n -name "*~" -exec /bin/rm {} ';' dh_link dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install ntop-n2n-90215bd/packages/debian/debian/templates000066400000000000000000000005421422132035700216600ustar00rootroot00000000000000Template: n2n/license_expired_continue_installation Type: boolean Default: true Description: Do you want to continue with the installation? License found is not valid for the new package that is going to be installed. . Renew the maintenance to get a valid license for the new package or cancel the installation to continue using the current package. ntop-n2n-90215bd/packages/etc/000077500000000000000000000000001422132035700160455ustar00rootroot00000000000000ntop-n2n-90215bd/packages/etc/n2n/000077500000000000000000000000001422132035700165425ustar00rootroot00000000000000ntop-n2n-90215bd/packages/etc/n2n/edge.conf.sample000066400000000000000000000020251422132035700215740ustar00rootroot00000000000000# # The configuration file is similar to the command line, with one option per line. An equal # sign '=' should be used between key and value. Example: -c=mynetwork or --community=mynetwork # This file contains a basic configuration example, please refer to the help (-h) for the full # list of available options. # # -d|--tun-device # Specifies the name of the TUN interface. # -d=n2n0 # # -c|--community # Specifies the n2n community name the edge belongs to. # -c=mynetwork # # -k # Sets the encryption key (ASCII). The environment variable N2N_KEY= can also be used. # -k=mypassword # # -m # Specified the MAC address for the TAP interface (random otherwise). # # -m=DE:AD:BE:EF:99:99 # # -a # Sets the interface address. For DHCP use '-r -a dhcp:0.0.0.0'. # -a=1.2.3.4 # # -p # Sets the local UDP port to a fixed port. # -p=50001 # # -l|--supernode-list # Specifies the supernode IP and port. # -l=7.8.9.0:7777 # ntop-n2n-90215bd/packages/etc/n2n/supernode.conf.sample000066400000000000000000000007621422132035700227020ustar00rootroot00000000000000# # The configuration file is similar to the command line, with one option per line. An equal # sign '=' should be used between key and value. Example: -p=7777 # This file contains a basic configuration example, please refer to the help (-h) for the full # list of available options. # # -p # Sets the UDP listening port. # -p=7777 # # -c # Optionally specifies the allowed communities as listed in community.list file. # # -c=community.list ntop-n2n-90215bd/packages/etc/systemd/000077500000000000000000000000001422132035700175355ustar00rootroot00000000000000ntop-n2n-90215bd/packages/etc/systemd/system/000077500000000000000000000000001422132035700210615ustar00rootroot00000000000000ntop-n2n-90215bd/packages/etc/systemd/system/edge-ntopng@.service.in000066400000000000000000000004521422132035700253600ustar00rootroot00000000000000[Unit] Description=n2n edge process, on %I After=network-online.target syslog.target Wants=network-online.target BindsTo=ntopng.service [Service] Type=simple ExecStartPre= ExecStart=/usr/sbin/edge /etc/n2n/edge-%i.conf -f Restart=on-abnormal RestartSec=5 [Install] WantedBy=ntopng.service Alias= ntop-n2n-90215bd/packages/etc/systemd/system/edge.service.in000066400000000000000000000004271422132035700237570ustar00rootroot00000000000000[Unit] Description=n2n edge process After=network-online.target syslog.target nfw.target Wants=network-online.target [Service] Type=simple ExecStartPre= ExecStart=/usr/sbin/edge /etc/n2n/edge.conf -f Restart=on-abnormal RestartSec=5 [Install] WantedBy=multi-user.target Alias= ntop-n2n-90215bd/packages/etc/systemd/system/edge@.service.in000066400000000000000000000004411422132035700240530ustar00rootroot00000000000000[Unit] Description=n2n edge process, on %I After=network-online.target syslog.target nfw.target Wants=network-online.target [Service] Type=simple ExecStartPre= ExecStart=/usr/sbin/edge /etc/n2n/edge-%i.conf -f Restart=on-abnormal RestartSec=5 [Install] WantedBy=multi-user.target Alias= ntop-n2n-90215bd/packages/etc/systemd/system/supernode.service.in000066400000000000000000000004401422132035700250520ustar00rootroot00000000000000[Unit] Description=n2n supernode process After=network-online.target syslog.target Wants=network-online.target [Service] Type=simple User=n2n Group=n2n ExecStart=/usr/sbin/supernode /etc/n2n/supernode.conf -f Restart=on-abnormal RestartSec=5 [Install] WantedBy=multi-user.target Alias= ntop-n2n-90215bd/packages/openwrt/000077500000000000000000000000001422132035700167705ustar00rootroot00000000000000ntop-n2n-90215bd/packages/openwrt/Makefile000066400000000000000000000046061422132035700204360ustar00rootroot00000000000000# # Copyright (C) 2021 - ntop.org and contributors # include $(TOPDIR)/rules.mk PKG_NAME:=n2n PKG_VERSION:=HEAD PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz # These are defaults for compiling without any environmental overrides # (eg, the github action calculates the correct overrides for each build) PKG_SOURCE_URL:=https://github.com/ntop/n2n PKG_SOURCE_VERSION:=dev PKG_MIRROR_HASH:=skip # Apply overrides from the build environment ifdef N2N_PKG_SOURCE_URL PKG_SOURCE_URL:=$(N2N_PKG_SOURCE_URL) endif ifdef N2N_PKG_SOURCE_VERSION PKG_SOURCE_VERSION:=$(N2N_PKG_SOURCE_VERSION) endif ifdef N2N_PKG_VERSION PKG_VERSION:=$(N2N_PKG_VERSION) endif PKG_MAINTAINER:=Emanuele Faranda PKG_LICENSE:=GPL3 # autogen fix PKG_FIXUP:=autoreconf include $(INCLUDE_DIR)/package.mk define Package/n2n/Default SECTION:=net CATEGORY:=Network TITLE:=N2N Peer-to-peer VPN URL:=http://www.ntop.org/n2n SUBMENU:=VPN DEPENDS+=+libcap endef define Package/n2n-edge $(call Package/n2n/Default) TITLE+= client (edge node) DEPENDS+=+kmod-tun endef define Package/n2n-supernode $(call Package/n2n/Default) TITLE+= server (supernode) endef define Package/n2n-edge/description The client node for the N2N infrastructure endef define Package/n2n-supernode/description The supernode for the N2N infrastructure endef define Build/Configure ( cd $(PKG_BUILD_DIR); \ ./autogen.sh; \ ./configure ) endef define Package/n2n-edge/conffiles /etc/n2n/edge.conf endef define Package/n2n-edge/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/edge $(1)/usr/bin/ $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) $(PKG_BUILD_DIR)/packages/openwrt/etc/init.d/edge $(1)/etc/init.d/edge $(INSTALL_DIR) $(1)/etc/n2n $(INSTALL_CONF) $(PKG_BUILD_DIR)/packages/etc/n2n/edge.conf.sample $(1)/etc/n2n/edge.conf endef define Package/n2n-supernode/conffiles /etc/n2n/supernode.conf endef define Package/n2n-supernode/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/supernode $(1)/usr/bin/ $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) $(PKG_BUILD_DIR)/packages/openwrt/etc/init.d/supernode $(1)/etc/init.d/supernode $(INSTALL_DIR) $(1)/etc/n2n $(INSTALL_CONF) $(PKG_BUILD_DIR)/packages/etc/n2n/supernode.conf.sample $(1)/etc/n2n/supernode.conf endef $(eval $(call BuildPackage,n2n-edge)) $(eval $(call BuildPackage,n2n-supernode)) ntop-n2n-90215bd/packages/openwrt/README.md000066400000000000000000000043471422132035700202570ustar00rootroot00000000000000## Prerequisites This instructions explain how to build an OpenWRT .ipk package for n2n. You will either need to build a full OpenWRT buildchain (See the github action for building openwrt.yml for some example steps) or have a working cross-compiling build environment for the OpenWRT version installed into your device. ### Downloading a cross-compiling build environment This usually comes down to the following steps: 1. Download and extract the SDK toolchain for your device. The toolchain must match the *exact* OpenWRT version installed in your device. Toolchain for official OpenWRT images can be downloaded from https://downloads.openwrt.org 2. Build the toolchain: run `make menuconfig`, save the configuration, then run `make` to build the cross compiling tools 3. Download the feeds with `./scripts/feeds update -a` ## Compilation These instructions are for building the current checked out version of the n2n source (The generally used OpenWRT alternative is to download a tar.gz file of a specific n2n version, but that is not as suitable for development or local builds) You need both the openwrt repository and the n2n repository checked out for this. In these instructions, we assume that `openwrt` is the directory where your openwrt checkout is located and `n2n` is the directory for the n2n repository. ``` git clone https://github.com/ntop/n2n n2n N2N_PKG_VERSION=$(n2n/scripts/version.sh) export N2N_PKG_VERSION cp -r n2n/packages/openwrt openwrt/package/n2n cd openwrt make menuconfig # select Network -> VPN -> n2n-edge and n2n-supernode make package/n2n/clean V=s make package/n2n/prepare USE_SOURCE_DIR=../n2n V=s make package/n2n/compile V=s ``` If everything went fine, two ipk will be generated, one for the n2n-edge and the other for n2n-supernode. They can be found with `find . -name "n2n*.ipk"`, copied to the target device, and installed with `opkg install`. The github action described in `.github/workflows/openwrt.yml` implements an automated version of the above steps. ## Configuration The edge node can be started with `/etc/init.d/edge start`. Its configuration file is `/etc/n2n/edge.conf`. The supernode can be started with `/etc/init.d/supernode start`. Its configuration file is `/etc/n2n/supernode.conf`. ntop-n2n-90215bd/packages/openwrt/etc/000077500000000000000000000000001422132035700175435ustar00rootroot00000000000000ntop-n2n-90215bd/packages/openwrt/etc/init.d/000077500000000000000000000000001422132035700207305ustar00rootroot00000000000000ntop-n2n-90215bd/packages/openwrt/etc/init.d/edge000066400000000000000000000005571422132035700215660ustar00rootroot00000000000000#!/bin/sh /etc/rc.common START=90 STOP=10 USE_PROCD=1 PROG=/usr/bin/edge CONFIGFILE=/etc/n2n/edge.conf start_service() { procd_open_instance procd_set_param command $PROG $CONFIGFILE procd_set_param file $CONFIGFILE procd_set_param respawn procd_close_instance } stop_service() { service_stop $PROG } service_triggers() { procd_add_reload_trigger "edge" } ntop-n2n-90215bd/packages/openwrt/etc/init.d/supernode000066400000000000000000000005761422132035700226670ustar00rootroot00000000000000#!/bin/sh /etc/rc.common START=90 STOP=10 USE_PROCD=1 PROG=/usr/bin/supernode CONFIGFILE=/etc/n2n/supernode.conf start_service() { procd_open_instance procd_set_param command $PROG $CONFIGFILE procd_set_param file $CONFIGFILE procd_set_param respawn procd_close_instance } stop_service() { service_stop $PROG } service_triggers() { procd_add_reload_trigger "supernode" } ntop-n2n-90215bd/packages/rpm/000077500000000000000000000000001422132035700160705ustar00rootroot00000000000000ntop-n2n-90215bd/packages/rpm/Makefile.in000066400000000000000000000010501422132035700201310ustar00rootroot00000000000000# # Change it according to your setup # N2N_HOME=$(PWD)/../.. N2N_BUILD=${N2N_HOME}/packages/debian/n2n PLATFORM=@MACHINE@ RPM_PKG=n2n-@N2N_VERSION_RPM@-1.$(PLATFORM).rpm all: clean pkg pkg: rpmbuild -bb ./n2n.spec -@@RPM_SIGN_CMD@ $(HOME)/rpmbuild/RPMS/$(PLATFORM)/$(RPM_PKG) @echo "" @echo "Package contents:" @rpm -qpl $(HOME)/rpmbuild/RPMS/$(PLATFORM)/$(RPM_PKG) @echo "The package is now available in $(HOME)/rpmbuild/RPMS/$(PLATFORM)/$(RPM_PKG)" distclean: echo "dummy distclean" install: echo "dummy install" clean: rm -rf *~ *rpm ntop-n2n-90215bd/packages/rpm/configure000077500000000000000000002471701422132035700200120ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for Makefile.in 1.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Makefile.in' PACKAGE_TARNAME='makefile-in' PACKAGE_VERSION='1.0' PACKAGE_STRING='Makefile.in 1.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS RPM_SIGN_CMD DATE EXTN N2N_VERSION_RPM MACHINE APP target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures Makefile.in 1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/makefile-in] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Makefile.in 1.0:";; esac cat <<\_ACEOF Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF Makefile.in configure 1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Makefile.in $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # NOTE: this file is not actually used. You need to edit configure as well! N2N_VERSION_RPM=$(../../scripts/version.sh |tr - _) MACHINE=`uname -m` SHORT_MACHINE=`uname -m | cut -b1-3` if test $MACHINE = "x86_64"; then EXTN="amd64" else if test $SHORT_MACHINE = "aar"; then EXTN="arm64" EXTRA_DEPS="" else if test $SHORT_MACHINE = "arm"; then EXTN="armhf" EXTRA_DEPS="" else if test $SHORT_MACHINE = "mip"; then EXTN="mips" EXTRA_DEPS="" else EXTN="i386" fi fi fi fi APP=n2n DATE=`date -R` CENTOS_RELEASE=`cat /etc/centos-release | cut -d ' ' -f 3|cut -d '.' -f 1` if test $CENTOS_RELEASE = "release"; then CENTOS_RELEASE=`cat /etc/centos-release | cut -d ' ' -f 4|cut -d '.' -f 1` fi RPM_SIGN_CMD="rpm --addsign" if test "$CENTOS_RELEASE" -ne 8; then RPM_SIGN_CMD="./rpm-sign.exp" fi ac_config_files="$ac_config_files n2n.spec" ac_config_files="$ac_config_files ../etc/systemd/system/edge.service" ac_config_files="$ac_config_files ../etc/systemd/system/edge@.service" ac_config_files="$ac_config_files ../etc/systemd/system/edge-ntopng@.service" ac_config_files="$ac_config_files ../etc/systemd/system/supernode.service" ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by Makefile.in $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ Makefile.in config.status 1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "n2n.spec") CONFIG_FILES="$CONFIG_FILES n2n.spec" ;; "../etc/systemd/system/edge.service") CONFIG_FILES="$CONFIG_FILES ../etc/systemd/system/edge.service" ;; "../etc/systemd/system/edge@.service") CONFIG_FILES="$CONFIG_FILES ../etc/systemd/system/edge@.service" ;; "../etc/systemd/system/edge-ntopng@.service") CONFIG_FILES="$CONFIG_FILES ../etc/systemd/system/edge-ntopng@.service" ;; "../etc/systemd/system/supernode.service") CONFIG_FILES="$CONFIG_FILES ../etc/systemd/system/supernode.service" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ntop-n2n-90215bd/packages/rpm/configure.in000066400000000000000000000024421422132035700204030ustar00rootroot00000000000000AC_INIT([Makefile.in], 1.0) # NOTE: this file is not actually used. You need to edit configure as well! N2N_VERSION_RPM=$(../../scripts/version.sh |tr - _) MACHINE=`uname -m` SHORT_MACHINE=`uname -m | cut -b1-3` if test $MACHINE = "x86_64"; then EXTN="amd64" else if test $SHORT_MACHINE = "aar"; then EXTN="arm64" EXTRA_DEPS="" else if test $SHORT_MACHINE = "arm"; then EXTN="armhf" EXTRA_DEPS="" else if test $SHORT_MACHINE = "mip"; then EXTN="mips" EXTRA_DEPS="" else EXTN="i386" fi fi fi fi APP=n2n DATE=`date -R` CENTOS_RELEASE=`cat /etc/centos-release | cut -d ' ' -f 3|cut -d '.' -f 1` if test $CENTOS_RELEASE = "release"; then CENTOS_RELEASE=`cat /etc/centos-release | cut -d ' ' -f 4|cut -d '.' -f 1` fi RPM_SIGN_CMD="rpm --addsign" if test "$CENTOS_RELEASE" -ne 8; then RPM_SIGN_CMD="./rpm-sign.exp" fi AC_SUBST(APP) AC_SUBST(MACHINE) AC_SUBST(N2N_VERSION_RPM) AC_SUBST(EXTN) AC_SUBST(DATE) AC_SUBST(RPM_SIGN_CMD) AC_CONFIG_FILES(n2n.spec) AC_CONFIG_FILES(../etc/systemd/system/edge.service) AC_CONFIG_FILES(../etc/systemd/system/edge@.service) AC_CONFIG_FILES(../etc/systemd/system/edge-ntopng@.service) AC_CONFIG_FILES(../etc/systemd/system/supernode.service) AC_CONFIG_FILES(Makefile) AC_OUTPUT ntop-n2n-90215bd/packages/rpm/n2n.spec.in000066400000000000000000000061141422132035700200500ustar00rootroot00000000000000Summary: n2n peer-to-peer VPN Name: n2n Version: @N2N_VERSION_RPM@ Release: 1 License: GPL Group: Networking/Utilities URL: http://www.ntop.org/ Source: n2n-%{version}.tgz Packager: Luca Deri # Temporary location where the RPM will be built BuildRoot: %{_tmppath}/%{name}-%{version}-root Requires: libzstd # Make sure .build-id is not part of the package %define _build_id_links none %description n2n peer-to-peer VPN %prep %build mkdir -p $RPM_BUILD_ROOT/usr/sbin $RPM_BUILD_ROOT/usr/share/man/man1 $RPM_BUILD_ROOT/usr/share/man/man7 $RPM_BUILD_ROOT/usr/share/man/man8 mkdir -p $RPM_BUILD_ROOT/etc/n2n mkdir -p $RPM_BUILD_ROOT/usr/lib/systemd/system/ cp $HOME/n2n/edge $RPM_BUILD_ROOT/usr/sbin cp $HOME/n2n/supernode $RPM_BUILD_ROOT/usr/sbin cp $HOME/n2n/n2n.7.gz $RPM_BUILD_ROOT/usr/share/man/man7 cp $HOME/n2n/supernode.1.gz $RPM_BUILD_ROOT/usr/share/man/man1 cp $HOME/n2n/edge.8.gz $RPM_BUILD_ROOT/usr/share/man/man8 cp $HOME/n2n/packages/etc/systemd/system/*.service $RPM_BUILD_ROOT/usr/lib/systemd/system/ cp $HOME/n2n/packages/etc/n2n/*.conf.sample $RPM_BUILD_ROOT/etc/n2n find $RPM_BUILD_ROOT -name ".git" | xargs /bin/rm -rf find $RPM_BUILD_ROOT -name ".svn" | xargs /bin/rm -rf find $RPM_BUILD_ROOT -name "*~" | xargs /bin/rm -f # DST=$RPM_BUILD_ROOT/usr/n2n SRC=$RPM_BUILD_DIR/%{name}-%{version} #mkdir -p $DST/conf # Clean out our build directory %clean rm -fr $RPM_BUILD_ROOT %files /usr/sbin/edge /usr/sbin/supernode /usr/share/man/man7/n2n.7.gz /usr/share/man/man1/supernode.1.gz /usr/share/man/man8/edge.8.gz /usr/lib/systemd/system/edge.service /usr/lib/systemd/system/edge@.service /usr/lib/systemd/system/edge-ntopng@.service /usr/lib/systemd/system/supernode.service %config(noreplace) /etc/n2n/supernode.conf.sample %config(noreplace) /etc/n2n/edge.conf.sample # Set the default attributes of all of the files specified to have an # owner and group of root and to inherit the permissions of the file # itself. %defattr(-, root, root) %changelog * Fri Aug 17 2018 Luca Deri 1.0 - Current package version # Execution order: # install: pre -> (copy) -> post # upgrade: pre -> (copy) -> post -> preun (old) -> (delete old) -> postun (old) # un-install: preun -> (delete) -> postun %pre if ! grep -q n2n /etc/group; then echo 'Creating n2n group' /usr/sbin/groupadd -r n2n fi if ! /usr/bin/id -u n2n > /dev/null 2>&1; then echo 'Creating n2n user' /usr/sbin/useradd -M -N -g n2n -r -s /bin/false n2n fi %post if [ -f /bin/systemctl ]; then if [ ! -f /.dockerenv ]; then /bin/systemctl daemon-reload # NOTE: do not enable any services during first installation fi fi %preun if [ -f /bin/systemctl ]; then if [ ! -f /.dockerenv ]; then # possibly remove the installed services %systemd_preun supernode.service edge.service 'edge-ntopng@*.service' 'edge@*.service' fi fi %postun if [ -f /bin/systemctl ]; then if [ ! -f /.dockerenv ]; then # possibly restart the running services %systemd_postun_with_restart supernode.service edge.service 'edge-ntopng@*.service' 'edge@*.service' fi fi ntop-n2n-90215bd/packages/rpm/rpm-sign.exp000077500000000000000000000003161422132035700203450ustar00rootroot00000000000000#!/usr/bin/expect -f ### rpm-sign.exp -- Sign RPMs by sending the passphrase. spawn rpm --addsign {*}$argv expect -exact "Enter pass phrase: " send -- "\r" expect eof ## end of rpm-sign.exp ntop-n2n-90215bd/packages/ubuntu000077700000000000000000000000001422132035700176772debianustar00rootroot00000000000000ntop-n2n-90215bd/scripts/000077500000000000000000000000001422132035700152035ustar00rootroot00000000000000ntop-n2n-90215bd/scripts/README.md000066400000000000000000000006761422132035700164730ustar00rootroot00000000000000This directory contains executables that are not compiled. Some of these may end up installed for use by end users, but many of them are for use during development, builds and tests. Nothing in this directory should need compiling to use and they should be written such that they do not need configuring (e.g: they might probe several directories for their requirements) See the [Scripts Documentation](../docs/Scripts.md) for further details ntop-n2n-90215bd/scripts/cmake_all.sh000077500000000000000000000016611422132035700174560ustar00rootroot00000000000000#!/bin/bash # # Well, cmake might be approximately the same as ./configure && make, but it # never rolls off the fingers as easily # if [ ! -f CMakeLists.txt ]; then echo ERROR: run this script from the TOPDIR exit 1 fi OPTS="" #OPTS+=" -DN2N_OPTION_USE_PTHREAD=ON" #OPTS+=" -DN2N_OPTION_USE_OPENSSL=ON" #OPTS+=" -DN2N_OPTION_USE_CAPLIB=ON" #OPTS+=" -DN2N_OPTION_USE_PCAPLIB=ON" #OPTS+=" -DN2N_OPTION_USE_ZSTD=ON" #OPTS+=" -DN2N_OPTION_USE_PORTMAPPING=ON" #OPTS+=" -DOPENSSL_USE_STATIC_LIBS=true" set -e rm -rf build cmake -E make_directory build cd build # Shell check wants me to use an array in this scenario. Bourne shell # arrays are my line in the sand showing that a script should not be # written in such a horrible language. Since it would be silly to rewrite # a one-page wrapper script in python, we submit that this check is wrong. # shellcheck disable=SC2086 cmake .. $OPTS cmake --build . --config Release ctest ntop-n2n-90215bd/scripts/hack_fakeautoconf.sh000077500000000000000000000007311422132035700211760ustar00rootroot00000000000000#!/bin/sh # # Specifically for windows, where installing autoconf looks suspiciously # like boiling the ocean. sed \ -e "s%@CC@%gcc%g" \ -e "s%@AR@%ar%g" \ -e "s%@CFLAGS@%$CFLAGS%g" \ -e "s%@LDFLAGS@%$LDFLAGS%g" \ -e "s%@N2N_LIBS@%$LDLIBS%g" \ < Makefile.in > Makefile sed \ -e "s%@ADDITIONAL_TOOLS@%%g" \ < tools/Makefile.in > tools/Makefile cat <include/config.h #define PACKAGE_VERSION "FIXME" #define PACKAGE_OSNAME "FIXME" EOF ntop-n2n-90215bd/scripts/indent.sh000077500000000000000000000023421422132035700170240ustar00rootroot00000000000000#!/bin/sh # # Given one or more input source files, run a re-indenter on them. help() { echo "Usage: scripts/indent [-i] [file...]" echo " -i modify file in place with reindent results" echo "" echo "By default, will output a diff and exitcode if changed are needed" echo "If modifying files, no exit code or diff is output" exit 1 } [ -z "$1" ] && help [ "$1" = "-h" ] && help [ "$1" = "--help" ] && help INPLACE=0 if [ "$1" = "-i" ]; then shift INPLACE=1 fi ## indentOneClang() { ## rm -f "$1.indent" ## clang-format "$1" >"$1.indent" ## if [ $? -ne 0 ]; then ## echo "Error while formatting \"$1\"" ## RESULT=1 ## return ## fi ## diff -u "$1" "$1.indent" ## if [ $? -ne 0 ]; then ## RESULT=1 ## fi ## } indentOne() { IFILE="$1" if [ "$INPLACE" -eq 0 ]; then OFILE="$1.indent" rm -f "$OFILE" else OFILE="$1" fi if ! uncrustify -c uncrustify.cfg -f "$IFILE" -o "$OFILE"; then echo "Error while formatting \"$1\"" RESULT=1 return fi if ! diff -u "$IFILE" "$OFILE"; then RESULT=1 fi } RESULT=0 while [ -n "$1" ]; do indentOne "$1" shift done exit $RESULT ntop-n2n-90215bd/scripts/munin/000077500000000000000000000000001422132035700163315ustar00rootroot00000000000000ntop-n2n-90215bd/scripts/munin/n2n_000077500000000000000000000157231422132035700171230ustar00rootroot00000000000000#!/usr/bin/env perl use warnings; use strict; # # Requires # libjson-perl # # Magic Markers # #%# family=auto #%# capabilities=autoconf suggest package JsonUDP; use warnings; use strict; use IO::Socket::INET; use JSON; sub new { my $class = shift; my $port = shift || 5644; my $self = {}; bless($self, $class); $self->{sock} = IO::Socket::INET->new( PeerAddr => '127.0.0.1', PeerPort => $port, Proto => 'udp', ); $self->{json} = JSON->new->utf8->relaxed->pretty->canonical; $self->{tag} = 0; $self->{debug} = 0; return $self; } sub _tx { my $self = shift; my $msgline = shift; return $self->{sock}->send($msgline); } sub _rx { my $self = shift; my $tag = shift; my $db = []; my $error; while(1) { my $jsontxt; $self->{sock}->recv($jsontxt,1024); if ($self->{debug}) { print($jsontxt); } my $msg = $self->{json}->decode($jsontxt); # ignore packets not for us if ($msg->{_tag} ne $tag) { next; } # Save most recent error for return if ($msg->{_type} eq 'error') { $error = $msg; next; } if ($msg->{_type} eq 'end') { if ($error) { # TODO: an error channel return undef; } return $db; } if ($msg->{_type} eq 'row') { delete $msg->{_tag}; delete $msg->{_type}; push @$db, $msg; next; } # Ignore any unknown _type } } sub read { my $self = shift; my $cmdline = shift; my $tag = $self->{tag}++; # TODO: # Add a read cache $self->_tx(sprintf("r %i %s", $tag, $cmdline)); return $self->_rx($tag); } 1; package main; use warnings; use strict; my $config = { edge_pkts => { p2p_tx_pkt => { label => 'Peer to Peer tx rate', type => 'DERIVE', min => 0, }, p2p_rx_pkt => { label => 'Peer to Peer rx rate', type => 'DERIVE', min => 0, }, super_tx_pkt => { label => 'Peer to Supernode tx rate', type => 'DERIVE', min => 0, }, super_rx_pkt => { label => 'Peer to Supernode rx rate', type => 'DERIVE', min => 0, }, super_broadcast_tx_pkt => { label => 'Broadcast to Supernode tx rate', type => 'DERIVE', min => 0, }, super_broadcast_rx_pkt => { label => 'Broadcast to Supernode rx rate', type => 'DERIVE', min => 0, }, transop_tx_pkt => { label => 'Transform tx rate', type => 'DERIVE', min => 0, }, transop_rx_pkt => { label => 'Transform rx rate', type => 'DERIVE', min => 0, }, }, edge_counts => { edges => { label => 'Current known peers', type => 'GAUGE', }, supernodes => { label => 'Current known supernodes', type => 'GAUGE', }, }, supernode_pkts => { errors_tx_pkt => { label => 'Error rate', type => 'DERIVE', min => 0, }, reg_super_rx_pkt => { label => 'Connect rate', type => 'DERIVE', min => 0, }, reg_super_nak => { label => 'Connect error rate', type => 'DERIVE', min => 0, }, forward_tx_pkt => { label => 'Packets forwarded rate', type => 'DERIVE', min => 0, }, broadcast_tx_pkt => { label => 'Broadcast packet rate', type => 'DERIVE', min => 0, }, }, supernode_counts => { edges => { label => 'Current known edges', type => 'GAUGE', }, communities => { label => 'Current known communities', type => 'GAUGE', }, }, }; my $fetchinfo = { edge_pkts => { port => 5644, read => "packetstats", }, edge_counts => { port => 5644, count => [ "edges", "supernodes", ], }, supernode_pkts => { port => 5645, read => "packetstats", }, supernode_counts => { port => 5645, count => [ "edges", "communities", ], }, }; sub do_config { my $rpc = shift; my $name = shift; print("graph_title n2n $name status\n"); print("graph_category network\n"); my @names; while (my ($fieldname, $field) = each(%{$config->{$name}})) { push @names, $fieldname; while (my ($key, $val) = each(%{$field})) { print($fieldname.'.'.$key," ",$val,"\n"); } } # Ensure stable order print("graph_order ", join(' ', sort(@names)), "\n"); } sub do_fetch { my $rpc = shift; my $name = shift; my $db; my $read_table = $fetchinfo->{$name}->{read}; if (defined($read_table)) { $db = $rpc->read($read_table); for my $row (@$db) { my $type = $row->{type}; delete $row->{type}; while (my ($key, $val) = each(%{$row})) { my $metricname = $type."_".$key; print($metricname,".value ",$val,"\n"); } } } my $count_tables = $fetchinfo->{$name}->{count}; if (defined($count_tables)) { for my $table (@{$count_tables}) { $db = $rpc->read($table); print($table,".value ", scalar(@$db), "\n"); } } } sub do_autoconf { # quick check to see if this plugin should be enabled if (`pgrep supernode`) { print("yes\n"); } elsif (`pgrep edge`) { print("yes\n"); } else { print("no - neither edge nor supernode are running\n"); } } sub do_suggest { my $ports = {}; if (`pgrep supernode`) { $ports->{5645}=1; } if (`pgrep edge`) { $ports->{5644}=1; } while (my ($name, $info) = each(%{$fetchinfo})) { my $port = $info->{port}; next if (!defined($port)); # this not a real fetchinfo next if (!defined($ports->{$port})); # not linked to a running daemon print($name,"\n"); } } my $subc = { 'fetch' => \&do_fetch, 'config' => \&do_config, 'autoconf' => \&do_autoconf, 'suggest' => \&do_suggest, }; sub main() { my $name = $ARGV[1] || $0; $name =~ s%^.*/n2n_([^/]+)%$1%; my $port = $fetchinfo->{$name}->{port}; my $rpc = JsonUDP->new($port); my $cmd = $ARGV[0]; if (!defined($cmd)) { $cmd = 'fetch'; } my $func = $subc->{$cmd}; if (!defined($func)) { die("bad sub command"); } return $func->($rpc, $name); } main(); ntop-n2n-90215bd/scripts/n2n-ctl000077500000000000000000000210051422132035700164040ustar00rootroot00000000000000#!/usr/bin/env python3 # Licensed under GPLv3 # # Simple script to query the management interface of a running n2n edge node import argparse import socket import json import collections class JsonUDP(): """encapsulate communication with the edge""" def __init__(self, port): self.address = "127.0.0.1" self.port = port self.tag = 0 self.key = None self.debug = False self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.settimeout(1) def _next_tag(self): tagstr = str(self.tag) self.tag = (self.tag + 1) % 1000 return tagstr def _cmdstr(self, msgtype, cmdline): """Create the full command string to send""" tagstr = self._next_tag() options = [tagstr] if self.key is not None: options += ['1'] # Flags set for auth key field options += [self.key] optionsstr = ':'.join(options) return tagstr, ' '.join((msgtype, optionsstr, cmdline)) def _rx(self, tagstr): """Wait for rx packets""" seen_begin = False while not seen_begin: # TODO: there are no timeouts with any of the recv calls data, _ = self.sock.recvfrom(1024) data = json.loads(data.decode('utf8')) # TODO: We assume the first packet we get will be tagged for us assert(data['_tag'] == tagstr) if data['_type'] == 'error': raise ValueError('Error: {}'.format(data['error'])) if data['_type'] == 'replacing': # a signal that we have evicted an earlier subscribe continue if data['_type'] == 'subscribe': return True if data['_type'] == 'begin': seen_begin = True # Ideally, we would confirm that this is our "begin", but that # would need the cmd passed into this method, and that would # probably require parsing the cmdline passed to us :-( # assert(data['cmd'] == cmd) continue raise ValueError('Unknown data type {} from ' 'edge'.format(data['_type'])) result = list() error = None while True: data, _ = self.sock.recvfrom(1024) data = json.loads(data.decode('utf8')) if data['_tag'] != tagstr: # this packet is not for us, ignore it continue if data['_type'] == 'error': # we still expect an end packet, so save the error error = ValueError('Error: {}'.format(data['error'])) continue if data['_type'] == 'end': if error: raise error return result if data['_type'] != 'row': raise ValueError('Unknown data type {} from ' 'edge'.format(data['_type'])) # remove our boring metadata del data['_tag'] del data['_type'] if self.debug: print(data) result.append(data) def _call(self, msgtype, cmdline): """Perform a rpc call""" tagstr, msgstr = self._cmdstr(msgtype, cmdline) self.sock.sendto(msgstr.encode('utf8'), (self.address, self.port)) return self._rx(tagstr) def read(self, cmdline): return self._call('r', cmdline) def write(self, cmdline): return self._call('w', cmdline) def sub(self, cmdline): return self._call('s', cmdline) def readevent(self): self.sock.settimeout(3600) data, _ = self.sock.recvfrom(1024) data = json.loads(data.decode('utf8')) # assert(data['_tag'] == tagstr) assert(data['_type'] == 'event') del data['_tag'] del data['_type'] return data def str_table(rows, columns, orderby): """Given an array of dicts, do a simple table print""" result = list() widths = collections.defaultdict(lambda: 0) if len(rows) == 0: # No data to show, be sure not to truncate the column headings for col in columns: widths[col] = len(col) else: for row in rows: for col in columns: if col in row: widths[col] = max(widths[col], len(str(row[col]))) for col in columns: if widths[col] == 0: widths[col] = 1 result += "{:{}.{}} ".format(col, widths[col], widths[col]) result += "\n" if orderby is not None: rows = sorted(rows, key=lambda row: row.get(orderby, 0)) for row in rows: for col in columns: if col in row: data = row[col] else: data = '' result += "{:{}} ".format(data, widths[col]) result += "\n" return ''.join(result) def subcmd_show_supernodes(rpc, args): rows = rpc.read('supernodes') columns = [ 'version', 'current', 'macaddr', 'sockaddr', 'uptime', ] return str_table(rows, columns, args.orderby) def subcmd_show_edges(rpc, args): rows = rpc.read('edges') columns = [ 'mode', 'ip4addr', 'macaddr', 'sockaddr', 'desc', ] return str_table(rows, columns, args.orderby) def subcmd_show_help(rpc, args): result = 'Commands with pretty-printed output:\n\n' for name, cmd in subcmds.items(): result += "{:12} {}\n".format(name, cmd['help']) result += "\n" result += "Possble remote commands:\n" result += "(those without a pretty-printer will pass-through)\n\n" rows = rpc.read('help') for row in rows: result += "{:12} {}\n".format(row['cmd'], row['help']) return result subcmds = { 'help': { 'func': subcmd_show_help, 'help': 'Show available commands', }, 'supernodes': { 'func': subcmd_show_supernodes, 'help': 'Show the list of supernodes', }, 'edges': { 'func': subcmd_show_edges, 'help': 'Show the list of edges/peers', }, } def subcmd_default(rpc, args): """Just pass command through to edge""" cmdline = ' '.join([args.cmd] + args.args) if args.write: rows = rpc.write(cmdline) elif args.read: rows = rpc.read(cmdline) elif args.sub: if not rpc.sub(cmdline): raise ValueError('Could not subscribe') while True: event = rpc.readevent() # FIXME: violates layering.. print(json.dumps(event, sort_keys=True, indent=4)) else: raise ValueError('Unknown request type') return json.dumps(rows, sort_keys=True, indent=4) def main(): ap = argparse.ArgumentParser( description='Query the running local n2n edge') ap.add_argument('-t', '--mgmtport', action='store', default=5644, help='Management Port (default=5644)', type=int) ap.add_argument('-k', '--key', action='store', help='Password for mgmt commands') ap.add_argument('-d', '--debug', action='store_true', help='Also show raw internal data') ap.add_argument('--raw', action='store_true', help='Force cmd to avoid any pretty printing') ap.add_argument('--orderby', action='store', help='Hint to a pretty printer on how to sort') group = ap.add_mutually_exclusive_group() group.add_argument('--read', action='store_true', help='Make a read request (default)') group.add_argument('--write', action='store_true', help='Make a write request (only to non pretty' 'printed cmds)') group.add_argument('--sub', action='store_true', help='Make a subscribe request') ap.add_argument('cmd', action='store', help='Command to run (try "help" for list)') ap.add_argument('args', action='store', nargs="*", help='Optional args for the command') args = ap.parse_args() if not args.read and not args.write and not args.sub: args.read = True if args.raw or (args.cmd not in subcmds): func = subcmd_default else: func = subcmds[args.cmd]['func'] rpc = JsonUDP(args.mgmtport) rpc.debug = args.debug rpc.key = args.key try: result = func(rpc, args) except socket.timeout as e: print(e) exit(1) print(result) if __name__ == '__main__': main() ntop-n2n-90215bd/scripts/n2n-gateway.sh000077500000000000000000000042601422132035700177000ustar00rootroot00000000000000#!/bin/bash # # This is a sample script to route all the host traffic towards a remote # gateway, which is reacheable via the n2n virtual interface. # # This assumes the n2n connection is already been established and the # VPN gateway can be pinged by this host. # ####################################################### # CONFIG ####################################################### # The IP address of the gateway through the n2n interface N2N_GATEWAY="192.168.100.1" # The IP address of the supernode as configured in n2n N2N_SUPERNODE="1.2.3.4" # The n2n interface name N2N_INTERFACE="n2n0" # The DNS server to use. Must be a public DNS or a DNS located on the # N2N virtual network, otherwise DNS query information will be leaked # outside the VPN. DNS_SERVER="8.8.8.8" ####################################################### # END CONFIG ####################################################### if [[ $UID -ne 0 ]]; then echo "This script must be run as root" exit 1 fi if ! ip route get $N2N_GATEWAY | grep -q $N2N_INTERFACE ; then echo "Cannot reach the gateway ($N2N_GATEWAY) via $N2N_INTERFACE. Is edge running?" exit 1 fi # Determine the current internet gateway internet_gateway=$(ip route get 8.8.8.8 | head -n1 | awk '{ print $3 }') # Backup the DNS resolver configuration and use the specified server cp /etc/resolv.conf /etc/resolv.conf.my_bak echo "Using DNS server $DNS_SERVER" echo "nameserver $DNS_SERVER" > /etc/resolv.conf # The public IP of the supernode must be reachable via the internet gateway # Whereas all the other traffic will go through the new VPN gateway. ip route add $N2N_SUPERNODE via "$internet_gateway" ip route del default echo "Forwarding traffic via $N2N_GATEWAY" ip route add default via $N2N_GATEWAY function stopService { echo "Deleting custom routes" ip route del default ip route del $N2N_SUPERNODE via "$internet_gateway" echo "Restoring original gateway $internet_gateway" ip route add default via "$internet_gateway" echo "Restoring original DNS" mv /etc/resolv.conf.my_bak /etc/resolv.conf exit 0 } # setup signal handlers trap "stopService" SIGHUP SIGINT SIGTERM # enter wait loop echo "VPN is now up" while :; do sleep 300; done ntop-n2n-90215bd/scripts/n2n-httpd000077500000000000000000000276201422132035700167560ustar00rootroot00000000000000#!/usr/bin/env python3 # Licensed under GPLv3 # # Simple http server to allow user control of n2n edge nodes # # Currently only for demonstration # - needs nicer looking html written # - needs more json interfaces in edge # # Try it out with # http://localhost:8080/ # http://localhost:8080/edge/edges # http://localhost:8080/edge/supernodes import argparse import socket import json import socketserver import http.server import signal import functools import base64 from http import HTTPStatus import os import sys import importlib.machinery import importlib.util def import_filename(modulename, filename): # look in the same dir as this script pathname = os.path.join(os.path.dirname(os.path.abspath(__file__)), filename) loader = importlib.machinery.SourceFileLoader(modulename, pathname) spec = importlib.util.spec_from_loader(modulename, loader) module = importlib.util.module_from_spec(spec) try: loader.exec_module(module) except FileNotFoundError: print("Script {} not found".format(pathname), file=sys.stderr) sys.exit(1) return module # We share the implementation of the RPC class with the n2n-ctl script. We # cannot just import the module as 'n2n-ctl' has a dash in its name :-( JsonUDP = import_filename('n2nctl', 'n2n-ctl').JsonUDP pages = { "/script.js": { "content_type": "text/javascript", "content": """ var verbose=-1; function rows2verbose(id, unused, data) { row0 = data[0] verbose = row0['traceLevel'] let div = document.getElementById(id); div.innerHTML=verbose } function rows2keyvalue(id, keys, data) { let s = "" data.forEach((row) => { keys.forEach((key) => { if (key in row) { s += "
" + key + "" + row[key]; } }); }); s += "
" let div = document.getElementById(id); div.innerHTML=s } function rows2keyvalueall(id, unused, data) { let s = "" data.forEach((row) => { Object.keys(row).forEach((key) => { s += "
" + key + "" + row[key]; }); }); s += "
" let div = document.getElementById(id); div.innerHTML=s } function rows2table(id, columns, data) { let s = "" s += "" columns.forEach((col) => { s += "" columns.forEach((col) => { val = row[col] if (typeof val === "undefined") { val = '' } s += "
" + col }); data.forEach((row) => { s += "
" + val }); }); s += "
" let div = document.getElementById(id); div.innerHTML=s } function do_get(url, id, handler, handler_param) { fetch(url) .then(function (response) { if (!response.ok) { throw new Error('Fetch got ' + response.status) } return response.json(); }) .then(function (data) { handler(id,handler_param,data); // update the timestamp on success let now = Math.round(new Date().getTime() / 1000); let time = document.getElementById('time'); time.innerHTML=now; }) .catch(function (err) { console.log('error: ' + err); }); } function do_post(url, body, id, handler, handler_param) { fetch(url, {method:'POST', body: body}) .then(function (response) { if (!response.ok) { throw new Error('Fetch got ' + response.status) } return response.json(); }) .then(function (data) { handler(id,handler_param,data); }) .catch(function (err) { console.log('error: ' + err); }); } function do_stop(tracelevel) { // FIXME: uses global in script library fetch(nodetype + '/stop', {method:'POST'}) } function setverbose(tracelevel) { if (tracelevel < 0) { tracelevel = 0; } // FIXME: uses global in script library do_post( nodetype + '/verbose', tracelevel, 'verbose', rows2verbose, null ); } function refresh_setup(interval) { var timer = setInterval(refresh_job, interval); } """, }, "/": { "content_type": "text/html; charset=utf-8", "content": """ n2n edge management
Last Updated:
Logging Verbosity:


Edges/Peers:

Supernodes:


""", }, "/supernode.html": { "content_type": "text/html; charset=utf-8", "content": """ n2n supernode management
Last Updated:
Logging Verbosity:

Communities:

Edges/Peers:


""", }, } class SimpleHandler(http.server.BaseHTTPRequestHandler): def __init__(self, rpc, snrpc, *args, **kwargs): self.rpc = rpc self.snrpc = snrpc super().__init__(*args, **kwargs) def log_request(self, code='-', size='-'): # Dont spam the output pass def _simplereply(self, number, message): self.send_response(number) self.end_headers() self.wfile.write(message.encode('utf8')) def _replyjson(self, data): self.send_response(HTTPStatus.OK) self.send_header('Content-type', 'application/json') self.end_headers() self.wfile.write(json.dumps(data).encode('utf8')) def _replyunauth(self): self.send_response(HTTPStatus.UNAUTHORIZED) self.send_header('WWW-Authenticate', 'Basic realm="n2n"') self.end_headers() def _extractauth(self, rpc): # Avoid caching the key inside the object for all clients rpc.key = None header = self.headers.get('Authorization') if header is not None: authtype, encoded = header.split(' ') if authtype == 'Basic': user, key = base64.b64decode(encoded).decode('utf8').split(':') rpc.key = key if rpc.key is None: rpc.key = rpc.defaultkey def _rpc(self, method, cmdline): try: data = method(cmdline) except ValueError as e: if str(e) == "Error: badauth": self._replyunauth() return self._simplereply(HTTPStatus.BAD_REQUEST, 'Bad Command') return except socket.timeout as e: self._simplereply(HTTPStatus.REQUEST_TIMEOUT, str(e)) return self._replyjson(data) return def _rpc_read(self, rpc): self._extractauth(rpc) tail = self.path.split('/') cmd = tail[2] # if reads ever need args, could use more of the tail self._rpc(rpc.read, cmd) def _rpc_write(self, rpc): self._extractauth(rpc) content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length).decode('utf8') tail = self.path.split('/') cmd = tail[2] cmdline = cmd + ' ' + post_data self._rpc(rpc.write, cmdline) def do_GET(self): if self.path.startswith("/edge/"): self._rpc_read(self.rpc) return if self.path.startswith("/supernode/"): self._rpc_read(self.snrpc) return if self.path in pages: page = pages[self.path] self.send_response(HTTPStatus.OK) self.send_header('Content-type', page['content_type']) self.end_headers() self.wfile.write(page['content'].encode('utf8')) return self._simplereply(HTTPStatus.NOT_FOUND, 'Not Found') return def do_POST(self): if self.path.startswith("/edge/"): self._rpc_write(self.rpc) return if self.path.startswith("/supernode/"): self._rpc_write(self.snrpc) return def main(): ap = argparse.ArgumentParser( description='Control the running local n2n edge via http') ap.add_argument('-t', '--mgmtport', action='store', default=5644, help='Management Port (default=5644)', type=int) ap.add_argument('--snmgmtport', action='store', default=5645, help='Supernode Management Port (default=5645)', type=int) ap.add_argument('-k', '--key', action='store', help='Password for mgmt commands') ap.add_argument('-d', '--debug', action='store_true', help='Also show raw internal data') ap.add_argument('port', action='store', default=8080, type=int, nargs='?', help='Serve requests on TCP port (default 8080)') args = ap.parse_args() rpc = JsonUDP(args.mgmtport) rpc.debug = args.debug rpc.defaultkey = args.key snrpc = JsonUDP(args.snmgmtport) snrpc.debug = args.debug snrpc.defaultkey = args.key signal.signal(signal.SIGPIPE, signal.SIG_DFL) socketserver.TCPServer.allow_reuse_address = True handler = functools.partial(SimpleHandler, rpc, snrpc) httpd = socketserver.TCPServer(("", args.port), handler) try: httpd.serve_forever() except KeyboardInterrupt: return if __name__ == '__main__': main() ntop-n2n-90215bd/scripts/test_harness.sh000077500000000000000000000021261422132035700202450ustar00rootroot00000000000000#!/bin/sh # # Run with the name of a test list file. # # This expects to find the tests in the tools dir or scripts dir and the # expected results in the tests dir. # boilerplate so we can support whaky cmake dirs [ -z "$TOPDIR" ] && TOPDIR="." [ -z "$BINDIR" ] && BINDIR="." export TOPDIR export BINDIR if [ -z "$1" ]; then echo need test list filename exit 1 fi TESTLIST="$1" LISTDIR=$(dirname "$TESTLIST") TESTS=$(sed -e "s/#.*//" "$TESTLIST") # Actually run the tests for i in $TESTS; do # Look in several places for the test program if [ -e "$BINDIR/$i" ]; then TEST="$BINDIR/$i" elif [ -e "$BINDIR/tools/$i" ]; then TEST="$BINDIR/tools/$i" elif [ -e "$LISTDIR/../scripts/$i" ]; then TEST="$LISTDIR/../scripts/$i" else echo "Could not find test $i" exit 1 fi if [ ! -e "$LISTDIR/$i.expected" ]; then echo "Could not find testdata $LISTDIR/$i.expected" exit 1 fi echo "$TEST >$LISTDIR/$i.out" set -e "$TEST" >"$LISTDIR/$i.out" cmp "$LISTDIR/$i.expected" "$LISTDIR/$i.out" set +e done ntop-n2n-90215bd/scripts/test_integration_edge.sh000077500000000000000000000021601422132035700221070ustar00rootroot00000000000000#!/bin/sh # # Do some quick tests via the Json API against the edge # AUTH=n2n # boilerplate so we can support whaky cmake dirs [ -z "$TOPDIR" ] && TOPDIR=. [ -z "$BINDIR" ] && BINDIR=. docmd() { echo "###" "$@" echo } # start a supernode docmd ${BINDIR}/supernode -v # Start the edge in the background docmd sudo ${BINDIR}/edge -l localhost:7654 -c test >/dev/null # TODO: # - send edge messages to stderr? docmd ${TOPDIR}/scripts/n2n-ctl communities docmd ${TOPDIR}/scripts/n2n-ctl packetstats docmd ${TOPDIR}/scripts/n2n-ctl edges --raw # TODO: # docmd ${TOPDIR}/scripts/n2n-ctl supernodes --raw # - need fixed mac address # - need to mask out: # - version string # - last_seen timestamp # - uptime docmd ${TOPDIR}/scripts/n2n-ctl verbose docmd ${TOPDIR}/scripts/n2n-ctl --write verbose 1 2>/dev/null echo $? docmd ${TOPDIR}/scripts/n2n-ctl -k $AUTH --write verbose 1 # looks strange, but we are querying the state of the "stop" verb docmd ${TOPDIR}/scripts/n2n-ctl stop # stop them both docmd ${TOPDIR}/scripts/n2n-ctl -k $AUTH --write stop docmd ${TOPDIR}/scripts/n2n-ctl -t 5645 -k $AUTH --write stop ntop-n2n-90215bd/scripts/test_integration_supernode.sh000077500000000000000000000013751422132035700232160ustar00rootroot00000000000000#!/bin/sh # # Do some quick tests via the Json API against the supernode # AUTH=n2n # boilerplate so we can support whaky cmake dirs [ -z "$TOPDIR" ] && TOPDIR=. [ -z "$BINDIR" ] && BINDIR=. docmd() { echo "###" "$@" echo } # start it running in the background docmd ${BINDIR}/supernode -v docmd ${TOPDIR}/scripts/n2n-ctl -t 5645 communities docmd ${TOPDIR}/scripts/n2n-ctl -t 5645 packetstats docmd ${TOPDIR}/scripts/n2n-ctl -t 5645 edges --raw docmd ${TOPDIR}/scripts/n2n-ctl -t 5645 verbose docmd ${TOPDIR}/scripts/n2n-ctl -t 5645 -k $AUTH --write verbose 1 # looks strange, but we are querying the state of the "stop" verb docmd ${TOPDIR}/scripts/n2n-ctl -t 5645 stop # stop it docmd ${TOPDIR}/scripts/n2n-ctl -t 5645 -k $AUTH --write stop ntop-n2n-90215bd/scripts/version.sh000077500000000000000000000023241422132035700172300ustar00rootroot00000000000000#!/bin/sh # # Output the current version number # usage() { echo "Usage: $0 [short|hash]" echo echo "Determine the correct version number for the current build" exit 0 } # We assume this script is in the TOPDIR/scripts directory and use that # to find any other files we need TOPDIR=$(dirname "$0")/.. VER_FILE_SHORT=$(cat "${TOPDIR}/VERSION") if [ -d "$TOPDIR/.git" ]; then # If there is a .git directory in our TOPDIR, then this is assumed to be # real git checkout cd "$TOPDIR" || exit 1 VER_GIT_SHORT=$(git describe --abbrev=0) if [ "$VER_FILE_SHORT" != "$VER_GIT_SHORT" ]; then echo "Error: VERSION file does not match tag version ($VER_FILE_SHORT != $VER_GIT_SHORT)" exit 1 fi VER_SHORT="$VER_GIT_SHORT" VER_HASH=$(git rev-parse --short HEAD) VER=$(git describe --abbrev=7 --dirty) else # If there is no .git directory in our TOPDIR, we fall back on relying on # the VERSION file VER_SHORT="$VER_FILE_SHORT" VER_HASH="HEAD" VER="$VER_FILE_SHORT" fi case "$1" in hash) echo "$VER_HASH" ;; short) echo "$VER_SHORT" ;; "") echo "$VER" ;; *) usage ;; esac ntop-n2n-90215bd/src/000077500000000000000000000000001422132035700143035ustar00rootroot00000000000000ntop-n2n-90215bd/src/aes.c000066400000000000000000002164411422132035700152270ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #if defined (HAVE_OPENSSL_1_1) // openSSL 1.1 --------------------------------------------------------------------- // get any erorr message out of openssl // taken from https://en.wikibooks.org/wiki/OpenSSL/Error_handling static char *openssl_err_as_string (void) { BIO *bio = BIO_new (BIO_s_mem ()); ERR_print_errors (bio); char *buf = NULL; size_t len = BIO_get_mem_data (bio, &buf); char *ret = (char *) calloc (1, 1 + len); if(ret) memcpy (ret, buf, len); BIO_free (bio); return ret; } int aes_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, aes_context_t *ctx) { int evp_len; int evp_ciphertext_len; if(1 == EVP_EncryptInit_ex(ctx->enc_ctx, ctx->cipher, NULL, ctx->key, iv)) { if(1 == EVP_CIPHER_CTX_set_padding(ctx->enc_ctx, 0)) { if(1 == EVP_EncryptUpdate(ctx->enc_ctx, out, &evp_len, in, in_len)) { evp_ciphertext_len = evp_len; if(1 == EVP_EncryptFinal_ex(ctx->enc_ctx, out + evp_len, &evp_len)) { evp_ciphertext_len += evp_len; if(evp_ciphertext_len != in_len) traceEvent(TRACE_ERROR, "aes_cbc_encrypt openssl encryption: encrypted %u bytes where %u were expected", evp_ciphertext_len, in_len); } else traceEvent(TRACE_ERROR, "aes_cbc_encrypt openssl final encryption: %s", openssl_err_as_string()); } else traceEvent(TRACE_ERROR, "aes_cbc_encrypt openssl encrpytion: %s", openssl_err_as_string()); } else traceEvent(TRACE_ERROR, "aes_cbc_encrypt openssl padding setup: %s", openssl_err_as_string()); } else traceEvent(TRACE_ERROR, "aes_cbc_encrypt openssl init: %s", openssl_err_as_string()); EVP_CIPHER_CTX_reset(ctx->enc_ctx); return 0; } int aes_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, aes_context_t *ctx) { int evp_len; int evp_plaintext_len; if(1 == EVP_DecryptInit_ex(ctx->dec_ctx, ctx->cipher, NULL, ctx->key, iv)) { if(1 == EVP_CIPHER_CTX_set_padding(ctx->dec_ctx, 0)) { if(1 == EVP_DecryptUpdate(ctx->dec_ctx, out, &evp_len, in, in_len)) { evp_plaintext_len = evp_len; if(1 == EVP_DecryptFinal_ex(ctx->dec_ctx, out + evp_len, &evp_len)) { evp_plaintext_len += evp_len; if(evp_plaintext_len != in_len) traceEvent(TRACE_ERROR, "aes_cbc_decrypt openssl decryption: decrypted %u bytes where %u were expected", evp_plaintext_len, in_len); } else traceEvent(TRACE_ERROR, "aes_cbc_decrypt openssl final decryption: %s", openssl_err_as_string()); } else traceEvent(TRACE_ERROR, "aes_cbc_decrypt openssl decrpytion: %s", openssl_err_as_string()); } else traceEvent(TRACE_ERROR, "aes_cbc_decrypt openssl padding setup: %s", openssl_err_as_string()); } else traceEvent(TRACE_ERROR, "aes_cbc_decrypt openssl init: %s", openssl_err_as_string()); EVP_CIPHER_CTX_reset(ctx->dec_ctx); return 0; } int aes_ecb_decrypt (unsigned char *out, const unsigned char *in, aes_context_t *ctx) { AES_ecb_encrypt(in, out, &(ctx->ecb_dec_key), AES_DECRYPT); return 0; } int aes_init (const unsigned char *key, size_t key_size, aes_context_t **ctx) { // allocate context... *ctx = (aes_context_t*) calloc(1, sizeof(aes_context_t)); if(!(*ctx)) return -1; // ...and fill her up: // initialize data structures if(!((*ctx)->enc_ctx = EVP_CIPHER_CTX_new())) { traceEvent(TRACE_ERROR, "aes_init openssl's evp_* encryption context creation failed: %s", openssl_err_as_string()); return -1; } if(!((*ctx)->dec_ctx = EVP_CIPHER_CTX_new())) { traceEvent(TRACE_ERROR, "aes_init openssl's evp_* decryption context creation failed: %s", openssl_err_as_string()); return -1; } // check key size and make key size (given in bytes) dependant settings switch(key_size) { case AES128_KEY_BYTES: // 128 bit key size (*ctx)->cipher = EVP_aes_128_cbc(); break; case AES192_KEY_BYTES: // 192 bit key size (*ctx)->cipher = EVP_aes_192_cbc(); break; case AES256_KEY_BYTES: // 256 bit key size (*ctx)->cipher = EVP_aes_256_cbc(); break; default: traceEvent(TRACE_ERROR, "aes_init invalid key size %u\n", key_size); return -1; } // key materiel handling memcpy((*ctx)->key, key, key_size); AES_set_decrypt_key(key, key_size * 8, &((*ctx)->ecb_dec_key)); return 0; } #elif defined (__AES__) && defined (__SSE2__) // Intel's AES-NI --------------------------------------------------- // inspired by https://gist.github.com/acapola/d5b940da024080dfaf5f // furthered by the help of Sebastian Ramacher's implementation found at // https://chromium.googlesource.com/external/github.com/dlitz/pycrypto/+/junk/master/src/AESNI.c // modified along Intel's white paper on AES Instruction Set // https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf static __m128i aes128_keyexpand(__m128i key, __m128i keygened, uint8_t shuf) { key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); // unfortunately, shuffle expects immediate argument, thus the not-so-stylish switch ... // REVISIT: either macrorize this whole function (and perhaps the following one) or // use shuffle_epi8 (which would require SSSE3 instead of SSE2) switch(shuf) { case 0x55: keygened = _mm_shuffle_epi32(keygened, 0x55 ); break; case 0xaa: keygened = _mm_shuffle_epi32(keygened, 0xaa ); break; case 0xff: keygened = _mm_shuffle_epi32(keygened, 0xff ); break; default: break; } return _mm_xor_si128(key, keygened); } static __m128i aes192_keyexpand_2(__m128i key, __m128i key2) { key = _mm_shuffle_epi32(key, 0xff); key2 = _mm_xor_si128(key2, _mm_slli_si128(key2, 4)); return _mm_xor_si128(key, key2); } #define KEYEXP128(K, I) aes128_keyexpand (K, _mm_aeskeygenassist_si128(K, I), 0xff) #define KEYEXP192(K1, K2, I) aes128_keyexpand (K1, _mm_aeskeygenassist_si128(K2, I), 0x55) #define KEYEXP192_2(K1, K2) aes192_keyexpand_2(K1, K2) #define KEYEXP256(K1, K2, I) aes128_keyexpand (K1, _mm_aeskeygenassist_si128(K2, I), 0xff) #define KEYEXP256_2(K1, K2) aes128_keyexpand (K1, _mm_aeskeygenassist_si128(K2, 0x00), 0xaa) // key setup static int aes_internal_key_setup (aes_context_t *ctx, const uint8_t *key, int key_bits) { // number of rounds ctx->Nr = 6 + (key_bits / 32); // encryption keys switch(key_bits) { case 128: { ctx->rk_enc[ 0] = _mm_loadu_si128((const __m128i*)key); ctx->rk_enc[ 1] = KEYEXP128(ctx->rk_enc[0], 0x01); ctx->rk_enc[ 2] = KEYEXP128(ctx->rk_enc[1], 0x02); ctx->rk_enc[ 3] = KEYEXP128(ctx->rk_enc[2], 0x04); ctx->rk_enc[ 4] = KEYEXP128(ctx->rk_enc[3], 0x08); ctx->rk_enc[ 5] = KEYEXP128(ctx->rk_enc[4], 0x10); ctx->rk_enc[ 6] = KEYEXP128(ctx->rk_enc[5], 0x20); ctx->rk_enc[ 7] = KEYEXP128(ctx->rk_enc[6], 0x40); ctx->rk_enc[ 8] = KEYEXP128(ctx->rk_enc[7], 0x80); ctx->rk_enc[ 9] = KEYEXP128(ctx->rk_enc[8], 0x1B); ctx->rk_enc[10] = KEYEXP128(ctx->rk_enc[9], 0x36); break; } case 192: { __m128i temp[2]; ctx->rk_enc[ 0] = _mm_loadu_si128((const __m128i*) key); ctx->rk_enc[ 1] = _mm_loadu_si128((const __m128i*) (key+16)); temp[0] = KEYEXP192(ctx->rk_enc[0], ctx->rk_enc[1], 0x01); temp[1] = KEYEXP192_2(temp[0], ctx->rk_enc[1]); ctx->rk_enc[ 1] = (__m128i)_mm_shuffle_pd((__m128d)ctx->rk_enc[1], (__m128d)temp[0], 0); ctx->rk_enc[ 2] = (__m128i)_mm_shuffle_pd((__m128d)temp[0], (__m128d)temp[1], 1); ctx->rk_enc[ 3] = KEYEXP192(temp[0], temp[1], 0x02); ctx->rk_enc[ 4] = KEYEXP192_2(ctx->rk_enc[3], temp[1]); temp[0] = KEYEXP192(ctx->rk_enc[3], ctx->rk_enc[4], 0x04); temp[1] = KEYEXP192_2(temp[0], ctx->rk_enc[4]); ctx->rk_enc[ 4] = (__m128i)_mm_shuffle_pd((__m128d)ctx->rk_enc[4], (__m128d)temp[0], 0); ctx->rk_enc[ 5] = (__m128i)_mm_shuffle_pd((__m128d)temp[0], (__m128d)temp[1], 1); ctx->rk_enc[ 6] = KEYEXP192(temp[0], temp[1], 0x08); ctx->rk_enc[ 7] = KEYEXP192_2(ctx->rk_enc[6], temp[1]); temp[0] = KEYEXP192(ctx->rk_enc[6], ctx->rk_enc[7], 0x10); temp[1] = KEYEXP192_2(temp[0], ctx->rk_enc[7]); ctx->rk_enc[ 7] = (__m128i)_mm_shuffle_pd((__m128d)ctx->rk_enc[7], (__m128d)temp[0], 0); ctx->rk_enc[ 8] = (__m128i)_mm_shuffle_pd((__m128d)temp[0], (__m128d)temp[1], 1); ctx->rk_enc[ 9] = KEYEXP192(temp[0], temp[1], 0x20); ctx->rk_enc[10] = KEYEXP192_2(ctx->rk_enc[9], temp[1]); temp[0] = KEYEXP192(ctx->rk_enc[9], ctx->rk_enc[10], 0x40); temp[1] = KEYEXP192_2(temp[0], ctx->rk_enc[10]); ctx->rk_enc[10] = (__m128i)_mm_shuffle_pd((__m128d)ctx->rk_enc[10], (__m128d) temp[0], 0); ctx->rk_enc[11] = (__m128i)_mm_shuffle_pd((__m128d)temp[0],(__m128d) temp[1], 1); ctx->rk_enc[12] = KEYEXP192(temp[0], temp[1], 0x80); break; } case 256: { ctx->rk_enc[ 0] = _mm_loadu_si128((const __m128i*) key); ctx->rk_enc[ 1] = _mm_loadu_si128((const __m128i*) (key+16)); ctx->rk_enc[ 2] = KEYEXP256(ctx->rk_enc[0], ctx->rk_enc[1], 0x01); ctx->rk_enc[ 3] = KEYEXP256_2(ctx->rk_enc[1], ctx->rk_enc[2]); ctx->rk_enc[ 4] = KEYEXP256(ctx->rk_enc[2], ctx->rk_enc[3], 0x02); ctx->rk_enc[ 5] = KEYEXP256_2(ctx->rk_enc[3], ctx->rk_enc[4]); ctx->rk_enc[ 6] = KEYEXP256(ctx->rk_enc[4], ctx->rk_enc[5], 0x04); ctx->rk_enc[ 7] = KEYEXP256_2(ctx->rk_enc[5], ctx->rk_enc[6]); ctx->rk_enc[ 8] = KEYEXP256(ctx->rk_enc[6], ctx->rk_enc[7], 0x08); ctx->rk_enc[ 9] = KEYEXP256_2(ctx->rk_enc[7], ctx->rk_enc[8]); ctx->rk_enc[10] = KEYEXP256(ctx->rk_enc[8], ctx->rk_enc[9], 0x10); ctx->rk_enc[11] = KEYEXP256_2(ctx->rk_enc[9], ctx->rk_enc[10]); ctx->rk_enc[12] = KEYEXP256(ctx->rk_enc[10], ctx->rk_enc[11], 0x20); ctx->rk_enc[13] = KEYEXP256_2(ctx->rk_enc[11], ctx->rk_enc[12]); ctx->rk_enc[14] = KEYEXP256(ctx->rk_enc[12], ctx->rk_enc[13], 0x40); break; } } // derive decryption keys for(int i = 1; i < ctx->Nr; ++i) { ctx->rk_dec[ctx->Nr - i] = _mm_aesimc_si128(ctx->rk_enc[i]); } ctx->rk_dec[ 0] = ctx->rk_enc[ctx->Nr]; return ctx->Nr; } static void aes_internal_encrypt (aes_context_t *ctx, const uint8_t pt[16], uint8_t ct[16]) { __m128i tmp = _mm_loadu_si128((__m128i*)pt); tmp = _mm_xor_si128 (tmp, ctx->rk_enc[ 0]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 1]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 2]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 3]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 4]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 5]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 6]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 7]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 8]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 9]); if(ctx->Nr > 10) { tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[10]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[11]); if(ctx->Nr > 12) { tmp = _mm_aesenc_si128(tmp, ctx->rk_enc[12]); tmp = _mm_aesenc_si128(tmp, ctx->rk_enc[13]); } } tmp = _mm_aesenclast_si128 (tmp, ctx->rk_enc[ctx->Nr]); _mm_storeu_si128((__m128i*) ct, tmp); } static void aes_internal_decrypt (aes_context_t *ctx, const uint8_t ct[16], uint8_t pt[16]) { __m128i tmp = _mm_loadu_si128((__m128i*)ct); tmp = _mm_xor_si128 (tmp, ctx->rk_dec[ 0]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 1]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 2]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 3]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 4]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 5]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 6]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 7]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 8]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 9]); if(ctx->Nr > 10) { tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[10]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[11]); if(ctx->Nr > 12) { tmp = _mm_aesdec_si128(tmp, ctx->rk_dec[12]); tmp = _mm_aesdec_si128(tmp, ctx->rk_dec[13]); } } tmp = _mm_aesdeclast_si128 (tmp, ctx->rk_enc[ 0]); _mm_storeu_si128((__m128i*) pt, tmp); } // public API int aes_ecb_decrypt (unsigned char *out, const unsigned char *in, aes_context_t *ctx) { aes_internal_decrypt(ctx, in, out); return AES_BLOCK_SIZE; } // not used int aes_ecb_encrypt (unsigned char *out, const unsigned char *in, aes_context_t *ctx) { aes_internal_encrypt(ctx, in, out); return AES_BLOCK_SIZE; } int aes_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, aes_context_t *ctx) { int n; /* number of blocks */ int ret = (int)in_len & 15; /* remainder */ __m128i ivec = _mm_loadu_si128((__m128i*)iv); for(n = in_len / 16; n != 0; n--) { __m128i tmp = _mm_loadu_si128((__m128i*)in); in += 16; tmp = _mm_xor_si128(tmp, ivec); tmp = _mm_xor_si128 (tmp, ctx->rk_enc[ 0]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 1]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 2]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 3]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 4]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 5]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 6]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 7]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 8]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[ 9]); if(ctx->Nr > 10) { tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[10]); tmp = _mm_aesenc_si128 (tmp, ctx->rk_enc[11]); if(ctx->Nr > 12) { tmp = _mm_aesenc_si128(tmp, ctx->rk_enc[12]); tmp = _mm_aesenc_si128(tmp, ctx->rk_enc[13]); } } tmp = _mm_aesenclast_si128 (tmp, ctx->rk_enc[ctx->Nr]); ivec = tmp; _mm_storeu_si128((__m128i*)out, tmp); out += 16; } return ret; } int aes_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, aes_context_t *ctx) { int n; /* number of blocks */ int ret = (int)in_len & 15; /* remainder */ __m128i ivec = _mm_loadu_si128((__m128i*)iv); // 4 parallel rails of AES decryption to reduce data dependencies in x86's deep pipelines for(n = in_len / 16; n > 3; n -=4) { __m128i tmp1 = _mm_loadu_si128((__m128i*)in); in += 16; __m128i tmp2 = _mm_loadu_si128((__m128i*)in); in += 16; __m128i tmp3 = _mm_loadu_si128((__m128i*)in); in += 16; __m128i tmp4 = _mm_loadu_si128((__m128i*)in); in += 16; __m128i old_in1 = tmp1; __m128i old_in2 = tmp2; __m128i old_in3 = tmp3; __m128i old_in4 = tmp4; tmp1 = _mm_xor_si128 (tmp1, ctx->rk_dec[ 0]); tmp2 = _mm_xor_si128 (tmp2, ctx->rk_dec[ 0]); tmp3 = _mm_xor_si128 (tmp3, ctx->rk_dec[ 0]); tmp4 = _mm_xor_si128 (tmp4, ctx->rk_dec[ 0]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 1]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 1]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[ 1]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[ 1]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 2]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 2]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[ 2]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[ 2]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 3]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 3]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[ 3]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[ 3]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 4]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 4]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[ 4]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[ 4]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 5]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 5]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[ 5]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[ 5]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 6]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 6]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[ 6]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[ 6]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 7]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 7]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[ 7]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[ 7]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 8]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 8]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[ 8]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[ 8]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 9]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 9]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[ 9]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[ 9]); if(ctx->Nr > 10) { tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[10]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[10]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[10]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[10]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[11]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[11]); tmp3 = _mm_aesdec_si128 (tmp3, ctx->rk_dec[11]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[11]); if(ctx->Nr > 12) { tmp1 = _mm_aesdec_si128(tmp1, ctx->rk_dec[12]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[12]); tmp3 = _mm_aesdec_si128(tmp3, ctx->rk_dec[12]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[12]); tmp1 = _mm_aesdec_si128(tmp1, ctx->rk_dec[13]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[13]); tmp3 = _mm_aesdec_si128(tmp3, ctx->rk_dec[13]); tmp4 = _mm_aesdec_si128 (tmp4, ctx->rk_dec[13]); } } tmp1 = _mm_aesdeclast_si128(tmp1, ctx->rk_enc[ 0]); tmp2 = _mm_aesdeclast_si128(tmp2, ctx->rk_enc[ 0]); tmp3 = _mm_aesdeclast_si128(tmp3, ctx->rk_enc[ 0]); tmp4 = _mm_aesdeclast_si128(tmp4, ctx->rk_enc[ 0]); tmp1 = _mm_xor_si128 (tmp1, ivec); tmp2 = _mm_xor_si128 (tmp2, old_in1); tmp3 = _mm_xor_si128 (tmp3, old_in2); tmp4 = _mm_xor_si128 (tmp4, old_in3); ivec = old_in4; _mm_storeu_si128((__m128i*) out, tmp1); out += 16; _mm_storeu_si128((__m128i*) out, tmp2); out += 16; _mm_storeu_si128((__m128i*) out, tmp3); out += 16; _mm_storeu_si128((__m128i*) out, tmp4); out += 16; } // now: less than 4 blocks remaining // if 2 or 3 blocks remaining --> this code handles two of them if(n > 1) { n-= 2; __m128i tmp1 = _mm_loadu_si128((__m128i*)in); in += 16; __m128i tmp2 = _mm_loadu_si128((__m128i*)in); in += 16; __m128i old_in1 = tmp1; __m128i old_in2 = tmp2; tmp1 = _mm_xor_si128 (tmp1, ctx->rk_dec[ 0]); tmp2 = _mm_xor_si128 (tmp2, ctx->rk_dec[ 0]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 1]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 1]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 2]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 2]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 3]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 3]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 4]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 4]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 5]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 5]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 6]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 6]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 7]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 7]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 8]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 8]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[ 9]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[ 9]); if(ctx->Nr > 10) { tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[10]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[10]); tmp1 = _mm_aesdec_si128 (tmp1, ctx->rk_dec[11]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[11]); if(ctx->Nr > 12) { tmp1 = _mm_aesdec_si128(tmp1, ctx->rk_dec[12]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[12]); tmp1 = _mm_aesdec_si128(tmp1, ctx->rk_dec[13]); tmp2 = _mm_aesdec_si128 (tmp2, ctx->rk_dec[13]); } } tmp1 = _mm_aesdeclast_si128 (tmp1, ctx->rk_enc[ 0]); tmp2 = _mm_aesdeclast_si128(tmp2, ctx->rk_enc[ 0]); tmp1 = _mm_xor_si128 (tmp1, ivec); tmp2 = _mm_xor_si128 (tmp2, old_in1); ivec = old_in2; _mm_storeu_si128((__m128i*) out, tmp1); out += 16; _mm_storeu_si128((__m128i*) out, tmp2); out += 16; } // one block remaining if(n) { __m128i tmp = _mm_loadu_si128((__m128i*)in); tmp = _mm_xor_si128 (tmp, ctx->rk_dec[ 0]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 1]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 2]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 3]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 4]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 5]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 6]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 7]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 8]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[ 9]); if(ctx->Nr > 10) { tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[10]); tmp = _mm_aesdec_si128 (tmp, ctx->rk_dec[11]); if(ctx->Nr > 12) { tmp = _mm_aesdec_si128(tmp, ctx->rk_dec[12]); tmp = _mm_aesdec_si128(tmp, ctx->rk_dec[13]); } } tmp = _mm_aesdeclast_si128 (tmp, ctx->rk_enc[ 0]); tmp = _mm_xor_si128 (tmp, ivec); _mm_storeu_si128((__m128i*) out, tmp); } return ret; } int aes_init (const unsigned char *key, size_t key_size, aes_context_t **ctx) { // allocate context... *ctx = (aes_context_t*) calloc(1, sizeof(aes_context_t)); if(!(*ctx)) return -1; // ...and fill her up: // initialize data structures // check key size and make key size (given in bytes) dependant settings switch(key_size) { case AES128_KEY_BYTES: // 128 bit key size break; case AES192_KEY_BYTES: // 192 bit key size break; case AES256_KEY_BYTES: // 256 bit key size break; default: traceEvent(TRACE_ERROR, "aes_init invalid key size %u\n", key_size); return -1; } // key materiel handling aes_internal_key_setup ( *ctx, key, 8 * key_size); return 0; } #else // plain C -------------------------------------------------------------------------- // rijndael-alg-fst.c version 3.0 (December 2000) // optimised ANSI C code for the Rijndael cipher (now AES) // original authors: Vincent Rijmen // Antoon Bosselaers // Paulo Barreto // // was put in the public domain, taken (and modified) from // https://fastcrypto.org/front/misc/rijndael-alg-fst.c // Te0[x] = S [x].[02, 01, 01, 03]; static const uint32_t Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU }; // Te1[x] = S [x].[03, 02, 01, 01]; static const uint32_t Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U }; // Te2[x] = S [x].[01, 03, 02, 01]; static const uint32_t Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U }; // Te3[x] = S [x].[01, 01, 03, 02]; static const uint32_t Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU }; // Te4[x] = S [x].[01, 01, 01, 01]; static const uint32_t Te4[256] = { 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U }; // Td0[x] = Si[x].[0e, 09, 0d, 0b]; static const uint32_t Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U }; // Td1[x] = Si[x].[0b, 0e, 09, 0d]; static const uint32_t Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U }; // Td2[x] = Si[x].[0d, 0b, 0e, 09]; static const uint32_t Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U }; // Td3[x] = Si[x].[09, 0d, 0b, 0e]; static const uint32_t Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U }; // Td4[x] = Si[x].[01, 01, 01, 01]; static const uint32_t Td4[256] = { 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU }; // for 128-bit blocks, Rijndael never uses more than 10 rcon values static const uint32_t rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000 }; #define GETU32(p) (be32toh((*((uint32_t*)(p))))) #define PUTU32(ct, st) { *((uint32_t*)(ct)) = htobe32((st)); } #define b0(x) ((uint8_t)(x)) #define b1(x) ((uint8_t)((x) >> 8)) #define b2(x) ((uint8_t)((x) >> 16)) #define b3(x) ((uint8_t)((x) >> 24)) #define m0(x) ((x) & 0x000000ff) #define m1(x) ((x) & 0x0000ff00) #define m2(x) ((x) & 0x00ff0000) #define m3(x) ((x) & 0xff000000) // expand the cipher key into the encryption key schedule and // return the number of rounds for the given cipher key size static int aes_internal_key_setup_enc (uint32_t rk[/*4*(Nr + 1)*/], const uint8_t cipherKey[], int keyBits) { int i = 0; uint32_t temp; rk[0] = GETU32(cipherKey ); rk[1] = GETU32(cipherKey + 4); rk[2] = GETU32(cipherKey + 8); rk[3] = GETU32(cipherKey + 12); if(keyBits == 128) { for(;;) { temp = rk[3]; rk[4] = rk[0] ^ (Te4[b2(temp)] & 0xff000000) ^ (Te4[b1(temp)] & 0x00ff0000) ^ (Te4[b0(temp)] & 0x0000ff00) ^ (Te4[b3(temp)] & 0x000000ff) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if(++i == 10) { return 10; } rk += 4; } } rk[4] = GETU32(cipherKey + 16); rk[5] = GETU32(cipherKey + 20); if(keyBits == 192) { for(;;) { temp = rk[ 5]; rk[ 6] = rk[ 0] ^ (Te4[b2(temp)] & 0xff000000) ^ (Te4[b1(temp)] & 0x00ff0000) ^ (Te4[b0(temp)] & 0x0000ff00) ^ (Te4[b3(temp)] & 0x000000ff) ^ rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; rk[ 9] = rk[ 3] ^ rk[ 8]; if(++i == 8) { return 12; } rk[10] = rk[ 4] ^ rk[ 9]; rk[11] = rk[ 5] ^ rk[10]; rk += 6; } } rk[6] = GETU32(cipherKey + 24); rk[7] = GETU32(cipherKey + 28); if(keyBits == 256) { for(;;) { temp = rk[ 7]; rk[ 8] = rk[ 0] ^ (Te4[b2(temp)] & 0xff000000) ^ (Te4[b1(temp)] & 0x00ff0000) ^ (Te4[b0(temp)] & 0x0000ff00) ^ (Te4[b3(temp)] & 0x000000ff) ^ rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; rk[11] = rk[ 3] ^ rk[10]; if(++i == 7) { return 14; } temp = rk[11]; rk[12] = rk[ 4] ^ (Te4[b3(temp)] & 0xff000000) ^ (Te4[b2(temp)] & 0x00ff0000) ^ (Te4[b1(temp)] & 0x0000ff00) ^ (Te4[b0(temp)] & 0x000000ff); rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; rk[15] = rk[ 7] ^ rk[14]; rk += 8; } } return 0; } #define INVMIXCOLRK(n) rk[n] = Td0[b0(Te4[b3(rk[n])])] ^ Td1[b0(Te4[b2(rk[n])])] ^ Td2[b0(Te4[b1(rk[n])])] ^ Td3[b0(Te4[b0(rk[n])])] // expand the cipher key into the decryption key schedule and // return the number of rounds for the given cipher key size static int aes_internal_key_setup_dec (uint32_t rk[/*4*(Nr + 1)*/], const uint8_t cipherKey[], int keyBits) { int Nr, i, j; uint32_t temp; // expand the cipher key Nr = aes_internal_key_setup_enc(rk, cipherKey, keyBits); // invert the order of the round keys for(i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } // apply the inverse MixColumn transform to all round keys but the first and the last for(i = 1; i < Nr; i++) { rk += 4; INVMIXCOLRK(0); INVMIXCOLRK(1); INVMIXCOLRK(2); INVMIXCOLRK(3); } return Nr; } #define AES_ENC_ROUND(DST, SRC, round) \ DST##0 = Te0[b3(SRC##0)] ^ Te1[b2(SRC##1)] ^ Te2[b1(SRC##2)] ^ Te3[b0(SRC##3)] ^ rk[4 * round + 0]; \ DST##1 = Te0[b3(SRC##1)] ^ Te1[b2(SRC##2)] ^ Te2[b1(SRC##3)] ^ Te3[b0(SRC##0)] ^ rk[4 * round + 1]; \ DST##2 = Te0[b3(SRC##2)] ^ Te1[b2(SRC##3)] ^ Te2[b1(SRC##0)] ^ Te3[b0(SRC##1)] ^ rk[4 * round + 2]; \ DST##3 = Te0[b3(SRC##3)] ^ Te1[b2(SRC##0)] ^ Te2[b1(SRC##1)] ^ Te3[b0(SRC##2)] ^ rk[4 * round + 3]; static void aes_internal_encrypt (const uint32_t rk[/*4*(Nr + 1)*/], int Nr, const uint8_t pt[16], uint8_t ct[16]) { uint32_t s0, s1, s2, s3, t0, t1, t2, t3; // map byte array block to cipher state and add initial round key s0 = GETU32(pt ) ^ rk[0]; s1 = GETU32(pt + 4) ^ rk[1]; s2 = GETU32(pt + 8) ^ rk[2]; s3 = GETU32(pt + 12) ^ rk[3]; AES_ENC_ROUND(t, s, 1); AES_ENC_ROUND(s, t, 2); AES_ENC_ROUND(t, s, 3); AES_ENC_ROUND(s, t, 4); AES_ENC_ROUND(t, s, 5); AES_ENC_ROUND(s, t, 6); AES_ENC_ROUND(t, s, 7); AES_ENC_ROUND(s, t, 8); AES_ENC_ROUND(t, s, 9); if(Nr > 10) { AES_ENC_ROUND(s, t, 10); AES_ENC_ROUND(t, s, 11); if(Nr > 12) { AES_ENC_ROUND(s, t, 12); AES_ENC_ROUND(t, s, 13); } } rk += Nr << 2; // apply last round and map cipher state to byte array block s0 = m3(Te4[b3(t0)]) ^ m2(Te4[b2(t1)]) ^ m1(Te4[b1(t2)]) ^ m0(Te4[b0(t3)]) ^ rk[0]; PUTU32(ct , s0); s1 = m3(Te4[b3(t1)]) ^ m2(Te4[b2(t2)]) ^ m1(Te4[b1(t3)]) ^ m0(Te4[b0(t0)]) ^ rk[1]; PUTU32(ct + 4, s1); s2 = m3(Te4[b3(t2)]) ^ m2(Te4[b2(t3)]) ^ m1(Te4[b1(t0)]) ^ m0(Te4[b0(t1)]) ^ rk[2]; PUTU32(ct + 8, s2); s3 = m3(Te4[b3(t3)]) ^ m2(Te4[b2(t0)]) ^ m1(Te4[b1(t1)]) ^ m0(Te4[b0(t2)]) ^ rk[3]; PUTU32(ct + 12, s3); } #define AES_DEC_ROUND(DST, SRC, round) \ DST##0 = Td0[b3(SRC##0)] ^ Td1[b2(SRC##3)] ^ Td2[b1(SRC##2)] ^ Td3[b0(SRC##1)] ^ rk[4 * round + 0]; \ DST##1 = Td0[b3(SRC##1)] ^ Td1[b2(SRC##0)] ^ Td2[b1(SRC##3)] ^ Td3[b0(SRC##2)] ^ rk[4 * round + 1]; \ DST##2 = Td0[b3(SRC##2)] ^ Td1[b2(SRC##1)] ^ Td2[b1(SRC##0)] ^ Td3[b0(SRC##3)] ^ rk[4 * round + 2]; \ DST##3 = Td0[b3(SRC##3)] ^ Td1[b2(SRC##2)] ^ Td2[b1(SRC##1)] ^ Td3[b0(SRC##0)] ^ rk[4 * round + 3]; static void aes_internal_decrypt (const uint32_t rk[/*4*(Nr + 1)*/], int Nr, const uint8_t ct[16], uint8_t pt[16]) { uint32_t s0, s1, s2, s3, t0, t1, t2, t3; // map byte array block to cipher state and add initial round key s0 = GETU32(ct ) ^ rk[0]; s1 = GETU32(ct + 4) ^ rk[1]; s2 = GETU32(ct + 8) ^ rk[2]; s3 = GETU32(ct + 12) ^ rk[3]; AES_DEC_ROUND(t, s, 1); AES_DEC_ROUND(s, t, 2); AES_DEC_ROUND(t, s, 3); AES_DEC_ROUND(s, t, 4); AES_DEC_ROUND(t, s, 5); AES_DEC_ROUND(s, t, 6); AES_DEC_ROUND(t, s, 7); AES_DEC_ROUND(s, t, 8); AES_DEC_ROUND(t, s, 9); if(Nr > 10) { AES_DEC_ROUND(s, t, 10); AES_DEC_ROUND(t, s, 11); if(Nr > 12) { AES_DEC_ROUND(s, t, 12); AES_DEC_ROUND(t, s, 13); } } rk += Nr << 2; // apply last round and map cipher state to byte array block s0 = m3(Td4[b3(t0)]) ^ m2(Td4[b2(t3)]) ^ m1(Td4[b1(t2)]) ^ m0(Td4[b0(t1)]) ^ rk[0]; PUTU32(pt , s0); s1 = m3(Td4[b3(t1)]) ^ m2(Td4[b2(t0)]) ^ m1(Td4[b1(t3)]) ^ m0(Td4[b0(t2)]) ^ rk[1]; PUTU32(pt + 4, s1); s2 = m3(Td4[b3(t2)]) ^ m2(Td4[b2(t1)]) ^ m1(Td4[b1(t0)]) ^ m0(Td4[b0(t3)]) ^ rk[2]; PUTU32(pt + 8, s2); s3 = m3(Td4[b3(t3)]) ^ m2(Td4[b2(t2)]) ^ m1(Td4[b1(t1)]) ^ m0(Td4[b0(t0)]) ^ rk[3]; PUTU32(pt + 12, s3); } // public API int aes_ecb_decrypt (unsigned char *out, const unsigned char *in, aes_context_t *ctx) { aes_internal_decrypt(ctx->dec_rk, ctx->Nr, in, out); return AES_BLOCK_SIZE; } // not used int aes_ecb_encrypt (unsigned char *out, const unsigned char *in, aes_context_t *ctx) { aes_internal_encrypt(ctx->enc_rk, ctx->Nr, in, out); return AES_BLOCK_SIZE; } #define fix_xor(target, source) *(uint32_t*)&(target)[0] = *(uint32_t*)&(target)[0] ^ *(uint32_t*)&(source)[0]; *(uint32_t*)&(target)[4] = *(uint32_t*)&(target)[4] ^ *(uint32_t*)&(source)[4]; \ *(uint32_t*)&(target)[8] = *(uint32_t*)&(target)[8] ^ *(uint32_t*)&(source)[8]; *(uint32_t*)&(target)[12] = *(uint32_t*)&(target)[12] ^ *(uint32_t*)&(source)[12]; int aes_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, aes_context_t *ctx) { uint8_t tmp[AES_BLOCK_SIZE]; size_t i; size_t n; memcpy(tmp, iv, AES_BLOCK_SIZE); n = in_len / AES_BLOCK_SIZE; for(i=0; i < n; i++) { fix_xor(tmp, &in[i * AES_BLOCK_SIZE]); aes_internal_encrypt(ctx->enc_rk, ctx->Nr, tmp, tmp); memcpy(&out[i * AES_BLOCK_SIZE], tmp, AES_BLOCK_SIZE); } return n * AES_BLOCK_SIZE; } int aes_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, aes_context_t *ctx) { uint8_t tmp[AES_BLOCK_SIZE]; uint8_t old[AES_BLOCK_SIZE]; size_t i; size_t n; memcpy(tmp, iv, AES_BLOCK_SIZE); n = in_len / AES_BLOCK_SIZE; for(i=0; i < n; i++) { memcpy(old, &in[i * AES_BLOCK_SIZE], AES_BLOCK_SIZE); aes_internal_decrypt(ctx->dec_rk, ctx->Nr, &in[i * AES_BLOCK_SIZE], &out[i * AES_BLOCK_SIZE]); fix_xor(&out[i * AES_BLOCK_SIZE], tmp); memcpy(tmp, old, AES_BLOCK_SIZE); } return n * AES_BLOCK_SIZE; } int aes_init (const unsigned char *key, size_t key_size, aes_context_t **ctx) { // allocate context... *ctx = (aes_context_t*) calloc(1, sizeof(aes_context_t)); if(!(*ctx)) return -1; // ...and fill her up: // initialize data structures // check key size and make key size (given in bytes) dependant settings switch(key_size) { case AES128_KEY_BYTES: // 128 bit key size break; case AES192_KEY_BYTES: // 192 bit key size break; case AES256_KEY_BYTES: // 256 bit key size break; default: traceEvent(TRACE_ERROR, "aes_init invalid key size %u\n", key_size); return -1; } // key materiel handling (*ctx)->Nr = aes_internal_key_setup_enc((*ctx)->enc_rk/*[4*(Nr + 1)]*/, key, 8 * key_size); aes_internal_key_setup_dec((*ctx)->dec_rk/*[4*(Nr + 1)]*/, key, 8 * key_size); return 0; } #endif // openSSL 1.1, AES-NI, plain C ---------------------------------------------------------------------------- int aes_deinit (aes_context_t *ctx) { if(ctx) free(ctx); return 0; } ntop-n2n-90215bd/src/auth.c000066400000000000000000000144241422132035700154150ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #include "auth.h" // mapping six binary bits to printable ascii character static uint8_t b2a[64] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 0 ... 9, A ... F */ 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* G ... V */ 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, /* W ... Z, a ... l */ 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x2b, 0x2d }; /* m ... z, + , - */ // mapping ascii 0x30 ...0x7f back to 6 bit binary, invalids are mapped to 0xff static uint8_t a2b[256] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0x3f, 0xff, 0xff, /* 0x20 ... 0x2f */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0x3e, 0xff, 0x3f, 0xff, /* 0x30 ... 0x3f */ 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* 0x40 ... 0x4f */ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x50 ... 0x5f */ 0xff, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, /* 0x60 ... 0x6f */ 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff }; /* 0x70 ... 0x7f */ int bin_to_ascii (char *out, uint8_t *in, size_t in_len) { // in buffer contains binary data of length in_len // out buffer is already allocated and of size ceiling(in_len * 8 / 6) + 1 // out buffer will be filled with a string including trailing 0x00 size_t bit_count = 0; size_t out_count = 0; uint8_t buf1, buf2; for(bit_count = 0; bit_count < 8 * in_len; bit_count += 6) { buf1 = in[bit_count / 8]; buf1 <<= bit_count % 8; buf2 = ((bit_count + 6) < (8 * in_len)) ? in[bit_count / 8 + 1] : 0; buf2 >>= 8 - (bit_count % 8); buf1 |= buf2; buf1 >>= 2; out[out_count++] = b2a[buf1]; } out[out_count] = 0; return 0; } int ascii_to_bin (uint8_t *out, char *in) { // in buffer contains 0x00-terminated string to be decoded // out buffer will contain decoded binary data // out buffer is already allocated and of size floor(strlen(in) * 6 / 8) size_t in_count, out_count, bit_count; uint16_t buf = 0; bit_count = 0; out_count = 0; for(in_count = 0; in_count < strlen(in); in_count++) { buf <<= 6; int ch = in[in_count]; if((ch > 0x20) && (ch < 0x80)) { if(a2b[ch] != 0xFF) { buf |= a2b[ch - 0x20]; } else { traceEvent(TRACE_NORMAL, "ascii_to_bin encountered the unknown character '%c'", in[in_count]); } } else { traceEvent(TRACE_WARNING, "ascii_to_bin encountered a completely out-of-range character"); } bit_count += 6; if(bit_count / 8) { bit_count -= 8; out[out_count++] = ((uint8_t)(buf >> bit_count)); } } return 0; } int generate_private_key (n2n_private_public_key_t key, char *in) { // hash the 0-terminated string input twice to generate private key pearson_hash_256(key, (uint8_t *)in, strlen(in)); pearson_hash_256(key, key, sizeof(n2n_private_public_key_t)); return 0; } int generate_public_key (n2n_private_public_key_t pub, n2n_private_public_key_t prv) { // generator point '9' on curve static uint8_t gen[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }; curve25519(pub, prv, gen); return 0; } int generate_shared_secret (n2n_private_public_key_t shared, n2n_private_public_key_t prv, n2n_private_public_key_t pub) { curve25519(shared, prv, pub); pearson_hash_256(shared, shared, sizeof(n2n_private_public_key_t)); return 0; } int bind_private_key_to_username (n2n_private_public_key_t prv, char *username) { uint8_t tmp[32]; pearson_hash_256(tmp, (uint8_t *)username, strlen(username)); memxor(prv, tmp, sizeof(n2n_private_public_key_t)); return 0; } // calculate SPECK ( plain = HASH³(time), key = HASH³(comm) ^ HASH³(fed) ) int calculate_dynamic_key (uint8_t out_key[N2N_AUTH_CHALLENGE_SIZE], uint32_t key_time, n2n_community_t comm, n2n_community_t fed) { uint8_t key[N2N_AUTH_CHALLENGE_SIZE]; uint8_t tmp[N2N_AUTH_CHALLENGE_SIZE]; speck_context_t *ctx; // we know that N2N_AUTH_CHALLENGE_SIZE == 16, i.e. 128 bit that can take the hash value pearson_hash_128(key, comm, sizeof(n2n_community_t)); pearson_hash_128(key, key, N2N_AUTH_CHALLENGE_SIZE); pearson_hash_128(key, key, N2N_AUTH_CHALLENGE_SIZE); pearson_hash_128(tmp, fed, sizeof(n2n_community_t)); pearson_hash_128(tmp, tmp, N2N_AUTH_CHALLENGE_SIZE); pearson_hash_128(tmp, tmp, N2N_AUTH_CHALLENGE_SIZE); memxor(key, tmp, N2N_AUTH_CHALLENGE_SIZE); ctx = (speck_context_t*)calloc(1, sizeof(speck_context_t)); speck_init((speck_context_t**)&ctx, key, 128); pearson_hash_128(tmp, (uint8_t*)&key_time, sizeof(key_time)); pearson_hash_128(tmp, tmp, N2N_AUTH_CHALLENGE_SIZE); pearson_hash_128(out_key, tmp, N2N_AUTH_CHALLENGE_SIZE); speck_128_encrypt(out_key, ctx); free(ctx); return 0; } ntop-n2n-90215bd/src/cc20.c000066400000000000000000000357201422132035700152050ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "cc20.h" #if defined (HAVE_OPENSSL_1_1) // openSSL 1.1 --------------------------------------------------------------------- // get any erorr message out of openssl // taken from https://en.wikibooks.org/wiki/OpenSSL/Error_handling static char *openssl_err_as_string (void) { BIO *bio = BIO_new(BIO_s_mem()); ERR_print_errors(bio); char *buf = NULL; size_t len = BIO_get_mem_data(bio, &buf); char *ret = (char *)calloc(1, 1 + len); if(ret) memcpy(ret, buf, len); BIO_free(bio); return ret; } // encryption == decryption int cc20_crypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, cc20_context_t *ctx) { int evp_len; int evp_ciphertext_len; if(1 == EVP_EncryptInit_ex(ctx->ctx, ctx->cipher, NULL, ctx->key, iv)) { if(1 == EVP_CIPHER_CTX_set_padding(ctx->ctx, 0)) { if(1 == EVP_EncryptUpdate(ctx->ctx, out, &evp_len, in, in_len)) { evp_ciphertext_len = evp_len; if(1 == EVP_EncryptFinal_ex(ctx->ctx, out + evp_len, &evp_len)) { evp_ciphertext_len += evp_len; if(evp_ciphertext_len != in_len) traceEvent(TRACE_ERROR, "cc20_crypt openssl encryption: encrypted %u bytes where %u were expected", evp_ciphertext_len, in_len); } else traceEvent(TRACE_ERROR, "cc20_crypt openssl final encryption: %s", openssl_err_as_string()); } else traceEvent(TRACE_ERROR, "cc20_encrypt openssl encrpytion: %s", openssl_err_as_string()); } else traceEvent(TRACE_ERROR, "cc20_encrypt openssl padding setup: %s", openssl_err_as_string()); } else traceEvent(TRACE_ERROR, "cc20_encrypt openssl init: %s", openssl_err_as_string()); EVP_CIPHER_CTX_reset(ctx->ctx); return 0; } #elif defined (__SSE2__) // SSE2 --------------------------------------------------------------------------------- // taken (and heavily modified and enhanced) from // https://github.com/Ginurx/chacha20-c (public domain) #define SL _mm_slli_epi32 #define SR _mm_srli_epi32 #define XOR _mm_xor_si128 #define AND _mm_and_si128 #define ADD _mm_add_epi32 #define ROL(X,r) (XOR(SL(X,r),SR(X,(32-r)))) #define ONE _mm_setr_epi32(1, 0, 0, 0) #define TWO _mm_setr_epi32(2, 0, 0, 0) #if defined (__SSSE3__) // --- SSSE3 #define L8 _mm_set_epi32(0x0e0d0c0fL, 0x0a09080bL, 0x06050407L, 0x02010003L) #define L16 _mm_set_epi32(0x0d0c0f0eL, 0x09080b0aL, 0x05040706L, 0x01000302L) #define ROL8(X) ( _mm_shuffle_epi8(X, L8)) /* SSSE 3 */ #define ROL16(X) ( _mm_shuffle_epi8(X, L16)) /* SSSE 3 */ #else // --- regular SSE2 ---------- #define ROL8(X) ROL(X,8) #define ROL16(X) ROL(X,16) #endif // -------------------------- #define CC20_PERMUTE_ROWS(A,B,C,D) \ B = _mm_shuffle_epi32(B, _MM_SHUFFLE(0, 3, 2, 1)); \ C = _mm_shuffle_epi32(C, _MM_SHUFFLE(1, 0, 3, 2)); \ D = _mm_shuffle_epi32(D, _MM_SHUFFLE(2, 1, 0, 3)) #define CC20_PERMUTE_ROWS_INV(A,B,C,D) \ B = _mm_shuffle_epi32(B, _MM_SHUFFLE(2, 1, 0, 3)); \ C = _mm_shuffle_epi32(C, _MM_SHUFFLE(1, 0, 3, 2)); \ D = _mm_shuffle_epi32(D, _MM_SHUFFLE(0, 3, 2, 1)) #define CC20_ODD_ROUND(A,B,C,D) \ /* odd round */ \ A = ADD(A, B); D = ROL16(XOR(D, A)); \ C = ADD(C, D); B = ROL(XOR(B, C), 12); \ A = ADD(A, B); D = ROL8(XOR(D, A)); \ C = ADD(C, D); B = ROL(XOR(B, C), 7) #define CC20_EVEN_ROUND(A,B,C,D) \ CC20_PERMUTE_ROWS (A, B, C, D); \ CC20_ODD_ROUND (A, B, C, D); \ CC20_PERMUTE_ROWS_INV(A, B, C, D) #define CC20_DOUBLE_ROUND(A,B,C,D) \ CC20_ODD_ROUND (A, B, C, D); \ CC20_EVEN_ROUND(A, B, C, D) #define STOREXOR(O,I,X) \ _mm_storeu_si128((__m128i*)O, \ _mm_xor_si128(_mm_loadu_si128((__m128i*)I), X)); \ I += 16; O += 16 \ int cc20_crypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, cc20_context_t *ctx) { __m128i a, b, c, d, k0, k1, k2, k3, k4, k5, k6, k7; uint8_t *keystream8 = (uint8_t*)ctx->keystream32; const uint8_t *magic_constant = (uint8_t*)"expand 32-byte k"; a = _mm_loadu_si128((__m128i*)magic_constant); b = _mm_loadu_si128((__m128i*)(ctx->key)); c = _mm_loadu_si128( (__m128i*)((ctx->key)+16)); d = _mm_loadu_si128((__m128i*)iv); while(in_len >= 128) { k0 = a; k1 = b; k2 = c; k3 = d; k4 = a; k5 = b; k6 = c; k7 = ADD(d, ONE); // 10 double rounds -- two in parallel to make better use of all 8 SSE registers CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k4, k5, k6, k7); k0 = ADD(k0, a); k1 = ADD(k1, b); k2 = ADD(k2, c); k3 = ADD(k3, d); k4 = ADD(k4, a); k5 = ADD(k5, b); k6 = ADD(k6, c); k7 = ADD(k7, d); k7 = ADD(k7, ONE); STOREXOR(out, in, k0); STOREXOR(out, in, k1); STOREXOR(out, in, k2); STOREXOR(out, in, k3); STOREXOR(out, in, k4); STOREXOR(out, in, k5); STOREXOR(out, in, k6); STOREXOR(out, in, k7); // increment counter, make sure it is and stays little endian in memory d = ADD(d, TWO); in_len -= 128; } if(in_len >= 64) { k0 = a; k1 = b; k2 = c; k3 = d; // 10 double rounds CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); k0 = ADD(k0, a); k1 = ADD(k1, b); k2 = ADD(k2, c); k3 = ADD(k3, d); STOREXOR(out, in, k0); STOREXOR(out, in, k1); STOREXOR(out, in, k2); STOREXOR(out, in, k3); // increment counter, make sure it is and stays little endian in memory d = ADD(d, ONE); in_len -= 64; } if(in_len) { k0 = a; k1 = b; k2 = c; k3 = d; // 10 double rounds CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); CC20_DOUBLE_ROUND(k0, k1, k2, k3); k0 = ADD(k0, a); k1 = ADD(k1, b); k2 = ADD(k2, c); k3 = ADD(k3, d); _mm_storeu_si128((__m128i*)&(ctx->keystream32[ 0]), k0); _mm_storeu_si128((__m128i*)&(ctx->keystream32[ 4]), k1); _mm_storeu_si128((__m128i*)&(ctx->keystream32[ 8]), k2); _mm_storeu_si128((__m128i*)&(ctx->keystream32[12]), k3); // keep in mind that out and in got increased inside the last loop // and point to current position now while(in_len > 0) { in_len--; out[in_len] = in[in_len] ^ keystream8[in_len]; } } return(0); } #else // plain C -------------------------------------------------------------------------------------------------- // taken (and modified) from https://github.com/Ginurx/chacha20-c (public domain) static void cc20_init_block(cc20_context_t *ctx, const uint8_t nonce[]) { const uint8_t *magic_constant = (uint8_t*)"expand 32-byte k"; memcpy(&(ctx->state[ 0]), magic_constant, 16); memcpy(&(ctx->state[ 4]), ctx->key, CC20_KEY_BYTES); memcpy(&(ctx->state[12]), nonce, CC20_IV_SIZE); } #define ROL32(x,r) (((x)<<(r))|((x)>>(32-(r)))) #define CC20_QUARTERROUND(x, a, b, c, d) \ x[a] += x[b]; x[d] = ROL32(x[d] ^ x[a], 16); \ x[c] += x[d]; x[b] = ROL32(x[b] ^ x[c], 12); \ x[a] += x[b]; x[d] = ROL32(x[d] ^ x[a], 8); \ x[c] += x[d]; x[b] = ROL32(x[b] ^ x[c], 7) #define CC20_DOUBLE_ROUND(s) \ /* odd round */ \ CC20_QUARTERROUND(s, 0, 4, 8, 12); \ CC20_QUARTERROUND(s, 1, 5, 9, 13); \ CC20_QUARTERROUND(s, 2, 6, 10, 14); \ CC20_QUARTERROUND(s, 3, 7, 11, 15); \ /* even round */ \ CC20_QUARTERROUND(s, 0, 5, 10, 15); \ CC20_QUARTERROUND(s, 1, 6, 11, 12); \ CC20_QUARTERROUND(s, 2, 7, 8, 13); \ CC20_QUARTERROUND(s, 3, 4, 9, 14) static void cc20_block_next(cc20_context_t *ctx) { uint32_t *counter = ctx->state + 12; ctx->keystream32[ 0] = ctx->state[ 0]; ctx->keystream32[ 1] = ctx->state[ 1]; ctx->keystream32[ 2] = ctx->state[ 2]; ctx->keystream32[ 3] = ctx->state[ 3]; ctx->keystream32[ 4] = ctx->state[ 4]; ctx->keystream32[ 5] = ctx->state[ 5]; ctx->keystream32[ 6] = ctx->state[ 6]; ctx->keystream32[ 7] = ctx->state[ 7]; ctx->keystream32[ 8] = ctx->state[ 8]; ctx->keystream32[ 9] = ctx->state[ 9]; ctx->keystream32[10] = ctx->state[10]; ctx->keystream32[11] = ctx->state[11]; ctx->keystream32[12] = ctx->state[12]; ctx->keystream32[13] = ctx->state[13]; ctx->keystream32[14] = ctx->state[14]; ctx->keystream32[15] = ctx->state[15]; // 10 double rounds CC20_DOUBLE_ROUND(ctx->keystream32); CC20_DOUBLE_ROUND(ctx->keystream32); CC20_DOUBLE_ROUND(ctx->keystream32); CC20_DOUBLE_ROUND(ctx->keystream32); CC20_DOUBLE_ROUND(ctx->keystream32); CC20_DOUBLE_ROUND(ctx->keystream32); CC20_DOUBLE_ROUND(ctx->keystream32); CC20_DOUBLE_ROUND(ctx->keystream32); CC20_DOUBLE_ROUND(ctx->keystream32); CC20_DOUBLE_ROUND(ctx->keystream32); ctx->keystream32[ 0] += ctx->state[ 0]; ctx->keystream32[ 1] += ctx->state[ 1]; ctx->keystream32[ 2] += ctx->state[ 2]; ctx->keystream32[ 3] += ctx->state[ 3]; ctx->keystream32[ 4] += ctx->state[ 4]; ctx->keystream32[ 5] += ctx->state[ 5]; ctx->keystream32[ 6] += ctx->state[ 6]; ctx->keystream32[ 7] += ctx->state[ 7]; ctx->keystream32[ 8] += ctx->state[ 8]; ctx->keystream32[ 9] += ctx->state[ 9]; ctx->keystream32[10] += ctx->state[10]; ctx->keystream32[11] += ctx->state[11]; ctx->keystream32[12] += ctx->state[12]; ctx->keystream32[13] += ctx->state[13]; ctx->keystream32[14] += ctx->state[14]; ctx->keystream32[15] += ctx->state[15]; // increment counter, make sure it is and stays little endian in memory *counter = htole32(le32toh(*counter)+1); } static void cc20_init_context(cc20_context_t *ctx, const uint8_t *nonce) { cc20_init_block(ctx, nonce); } int cc20_crypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, cc20_context_t *ctx) { uint8_t *keystream8 = (uint8_t*)ctx->keystream32; uint32_t * in_p = (uint32_t*)in; uint32_t * out_p = (uint32_t*)out; size_t tmp_len = in_len; cc20_init_context(ctx, iv); while(in_len >= 64) { cc20_block_next(ctx); *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 0]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 1]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 2]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 3]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 4]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 5]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 6]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 7]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 8]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[ 9]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[10]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[11]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[12]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[13]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[14]; in_p++; out_p++; *(uint32_t*)out_p = *(uint32_t*)in_p ^ ctx->keystream32[15]; in_p++; out_p++; in_len -= 64; } if(in_len > 0) { cc20_block_next(ctx); tmp_len -= in_len; while(in_len > 0) { out[tmp_len] = in[tmp_len] ^ keystream8[tmp_len%64]; tmp_len++; in_len--; } } return(0); } #endif // openSSL 1.1, plain C ------------------------------------------------------------------------------------ int cc20_init (const unsigned char *key, cc20_context_t **ctx) { // allocate context... *ctx = (cc20_context_t*)calloc(1, sizeof(cc20_context_t)); if(!(*ctx)) return -1; #if defined (HAVE_OPENSSL_1_1) if(!((*ctx)->ctx = EVP_CIPHER_CTX_new())) { traceEvent(TRACE_ERROR, "cc20_init openssl's evp_* encryption context creation failed: %s", openssl_err_as_string()); return -1; } (*ctx)->cipher = EVP_chacha20(); #endif memcpy((*ctx)->key, key, CC20_KEY_BYTES); return 0; } int cc20_deinit (cc20_context_t *ctx) { #if defined (HAVE_OPENSSL_1_1) if(ctx->ctx) EVP_CIPHER_CTX_free(ctx->ctx); #endif return 0; } ntop-n2n-90215bd/src/curve25519.c000066400000000000000000000205631422132035700162070ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /** * version 20081011 * Matthew Dempsky * Public domain. * Derived from public domain code by D. J. Bernstein. * 20140216 tweak: Mask top bit of point input. * */ static void add (unsigned int out[32], const unsigned int a[32], const unsigned int b[32]) { unsigned int j; unsigned int u; u = 0; for(j = 0; j < 31; ++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; } u += a[31] + b[31]; out[31] = u; } static void sub (unsigned int out[32], const unsigned int a[32], const unsigned int b[32]) { unsigned int j; unsigned int u; u = 218; for(j = 0; j < 31; ++j) { u += a[j] + 65280 - b[j]; out[j] = u & 255; u >>= 8; } u += a[31] - b[31]; out[31] = u; } static void squeeze (unsigned int a[32]) { unsigned int j; unsigned int u; u = 0; for(j = 0; j < 31; ++j) { u += a[j]; a[j] = u & 255; u >>= 8; } u += a[31]; a[31] = u & 127; u = 19 * (u >> 7); for(j = 0; j < 31; ++j) { u += a[j]; a[j] = u & 255; u >>= 8; } u += a[31]; a[31] = u; } static const unsigned int minusp[32] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 }; static void freeze (unsigned int a[32]) { unsigned int aorig[32]; unsigned int j; unsigned int negative; for(j = 0; j < 32; ++j) aorig[j] = a[j]; add(a, a, minusp); negative = -((a[31] >> 7) & 1); for(j = 0; j < 32; ++j) a[j] ^= negative & (aorig[j] ^ a[j]); } static void mult (unsigned int out[32], const unsigned int a[32], const unsigned int b[32]) { unsigned int i; unsigned int j; unsigned int u; for(i = 0; i < 32; ++i) { u = 0; for(j = 0; j <= i; ++j) u += a[j] * b[i - j]; for(j = i + 1; j < 32; ++j) u += 38 * a[j] * b[i + 32 - j]; out[i] = u; } squeeze(out); } static void mult121665 (unsigned int out[32], const unsigned int a[32]) { unsigned int j; unsigned int u; u = 0; for(j = 0; j < 31; ++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; } u += 121665 * a[31]; out[31] = u & 127; u = 19 * (u >> 7); for(j = 0; j < 31; ++j) { u += out[j]; out[j] = u & 255; u >>= 8; } u += out[j]; out[j] = u; } static void square (unsigned int out[32], const unsigned int a[32]) { unsigned int i; unsigned int j; unsigned int u; for(i = 0; i < 32; ++i) { u = 0; for(j = 0; j < i - j; ++j) u += a[j] * a[i - j]; for(j = i + 1; j < i + 32 - j; ++j) u += 38 * a[j] * a[i + 32 - j]; u *= 2; if((i & 1) == 0) { u += a[i / 2] * a[i / 2]; u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; } out[i] = u; } squeeze(out); } static void select (unsigned int p[64], unsigned int q[64], const unsigned int r[64], const unsigned int s[64], unsigned int b) { unsigned int j; unsigned int t; unsigned int bminus1; bminus1 = b - 1; for(j = 0; j < 64; ++j) { t = bminus1 & (r[j] ^ s[j]); p[j] = s[j] ^ t; q[j] = r[j] ^ t; } } static void mainloop (unsigned int work[64], const unsigned char e[32]) { unsigned int xzm1[64]; unsigned int xzm[64]; unsigned int xzmb[64]; unsigned int xzm1b[64]; unsigned int xznb[64]; unsigned int xzn1b[64]; unsigned int a0[64]; unsigned int a1[64]; unsigned int b0[64]; unsigned int b1[64]; unsigned int c1[64]; unsigned int r[32]; unsigned int s[32]; unsigned int t[32]; unsigned int u[32]; unsigned int j; unsigned int b; int pos; for(j = 0; j < 32; ++j) xzm1[j] = work[j]; xzm1[32] = 1; for(j = 33; j < 64; ++j) xzm1[j] = 0; xzm[0] = 1; for(j = 1; j < 64; ++j) xzm[j] = 0; for(pos = 254; pos >= 0; --pos) { b = e[pos / 8] >> (pos & 7); b &= 1; select(xzmb, xzm1b, xzm, xzm1, b); add(a0, xzmb, xzmb + 32); sub(a0 + 32, xzmb, xzmb + 32); add (a1, xzm1b, xzm1b + 32); sub(a1 + 32, xzm1b, xzm1b + 32); square(b0, a0); square(b0 + 32, a0 + 32); mult(b1, a1, a0 + 32); mult(b1 + 32, a1 + 32, a0); add(c1, b1, b1 + 32); sub(c1 + 32, b1, b1 + 32); square(r, c1 + 32); sub(s, b0, b0 + 32); mult121665 (t, s); add(u, t, b0); mult(xznb, b0, b0 + 32); mult(xznb + 32, s, u); square(xzn1b, c1); mult(xzn1b + 32, r, work); select(xzm, xzm1, xznb, xzn1b, b); } for(j = 0; j < 64; ++j) work[j] = xzm[j]; } static void recip (unsigned int out[32], const unsigned int z[32]) { unsigned int z2[32]; unsigned int z9[32]; unsigned int z11[32]; unsigned int z2_5_0[32]; unsigned int z2_10_0[32]; unsigned int z2_20_0[32]; unsigned int z2_50_0[32]; unsigned int z2_100_0[32]; unsigned int t0[32]; unsigned int t1[32]; int i; /* 2 */ square(z2, z); /* 4 */ square(t1, z2); /* 8 */ square(t0, t1); /* 9 */ mult(z9, t0, z); /* 11 */ mult(z11, z9, z2); /* 22 */ square(t0, z11); /* 2^5 - 2^0 = 31 */ mult(z2_5_0, t0, z9); /* 2^6 - 2^1 */ square(t0, z2_5_0); /* 2^7 - 2^2 */ square(t1, t0); /* 2^8 - 2^3 */ square(t0, t1); /* 2^9 - 2^4 */ square(t1, t0); /* 2^10 - 2^5 */ square(t0, t1); /* 2^10 - 2^0 */ mult(z2_10_0, t0, z2_5_0); /* 2^11 - 2^1 */ square(t0, z2_10_0); /* 2^12 - 2^2 */ square(t1, t0); /* 2^20 - 2^10 */ for(i = 2; i < 10; i += 2) { square(t0, t1); square(t1, t0); } /* 2^20 - 2^0 */ mult(z2_20_0, t1, z2_10_0); /* 2^21 - 2^1 */ square(t0, z2_20_0); /* 2^22 - 2^2 */ square(t1, t0); /* 2^40 - 2^20 */ for(i = 2; i < 20; i += 2) { square(t0, t1); square(t1, t0); } /* 2^40 - 2^0 */ mult(t0, t1, z2_20_0); /* 2^41 - 2^1 */ square(t1, t0); /* 2^42 - 2^2 */ square(t0, t1); /* 2^50 - 2^10 */ for(i = 2; i < 10; i += 2) { square(t1, t0); square(t0, t1); } /* 2^50 - 2^0 */ mult(z2_50_0, t0, z2_10_0); /* 2^51 - 2^1 */ square(t0, z2_50_0); /* 2^52 - 2^2 */ square(t1, t0); /* 2^100 - 2^50 */ for(i = 2; i < 50; i += 2) { square(t0, t1); square(t1, t0); } /* 2^100 - 2^0 */ mult(z2_100_0, t1, z2_50_0); /* 2^101 - 2^1 */ square(t1, z2_100_0); /* 2^102 - 2^2 */ square(t0, t1); /* 2^200 - 2^100 */ for(i = 2; i < 100; i += 2) { square(t1, t0); square(t0, t1); } /* 2^200 - 2^0 */ mult(t1, t0, z2_100_0); /* 2^201 - 2^1 */ square(t0, t1); /* 2^202 - 2^2 */ square(t1, t0); /* 2^250 - 2^50 */ for(i = 2; i < 50; i += 2) { square(t0, t1); square(t1, t0); } /* 2^250 - 2^0 */ mult(t0, t1, z2_50_0); /* 2^251 - 2^1 */ square(t1, t0); /* 2^252 - 2^2 */ square(t0, t1); /* 2^253 - 2^3 */ square(t1, t0); /* 2^254 - 2^4 */ square(t0, t1); /* 2^255 - 2^5 */ square(t1, t0); /* 2^255 - 21 */ mult(out, t1, z11); } void curve25519 (unsigned char *q, const unsigned char *n, const unsigned char *p) { unsigned int work[96]; unsigned char e[32]; unsigned int i; for (i = 0; i < 32; ++i) e[i] = n[i]; e[0] &= 248; e[31] &= 127; e[31] |= 64; for (i = 0; i < 32; ++i) work[i] = p[i]; work[31] &= 127; mainloop(work, e); recip(work + 32, work + 32); mult(work + 64, work, work + 32); freeze(work + 64); for(i = 0; i < 32; ++i) q[i] = work[64 + i]; } ntop-n2n-90215bd/src/edge.c000066400000000000000000001447521422132035700153700ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" /* *************************************************** */ /** maximum length of command line arguments */ #define MAX_CMDLINE_BUFFER_LENGTH 4096 /** maximum length of a line in the configuration file */ #define MAX_CONFFILE_LINE_LENGTH 1024 /* ***************************************************** */ #ifdef HAVE_LIBCAP #include #include #include "network_traffic_filter.h" static cap_value_t cap_values[] = { //CAP_NET_RAW, /* Use RAW and PACKET sockets */ CAP_NET_ADMIN /* Needed to performs routes cleanup at exit */ }; int num_cap = sizeof(cap_values)/sizeof(cap_value_t); #endif // forward declaration for use in main() void send_register_super (n2n_edge_t *eee); void send_query_peer (n2n_edge_t *eee, const n2n_mac_t dst_mac); int supernode_connect (n2n_edge_t *eee); int supernode_disconnect (n2n_edge_t *eee); int fetch_and_eventually_process_data (n2n_edge_t *eee, SOCKET sock, uint8_t *pktbuf, uint16_t *expected, uint16_t *position, time_t now); int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, time_t now); int edge_init_routes (n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_routes); /* ***************************************************** */ /** Find the address and IP mode for the tuntap device. * * s is of the form: * * ["static"|"dhcp",":"] (|) [/] * * for example static:192.168.8.5/24 * * Fill the parts of the string into the fileds, ip_mode only if * present. All strings are NULL terminated. * * return 0 on success and -1 on error */ static int scan_address (char * ip_addr, size_t addr_size, char * netmask, size_t netmask_size, char * ip_mode, size_t mode_size, char * s) { int retval = -1; char * start; char * end; int bitlen = N2N_EDGE_DEFAULT_CIDR_NM; if((NULL == s) || (NULL == ip_addr) || (NULL == netmask)) { return -1; } memset(ip_addr, 0, addr_size); memset(netmask, 0, netmask_size); start = s; end = strpbrk(s, ":"); if(end) { // colon is present if(ip_mode) { memset(ip_mode, 0, mode_size); strncpy(ip_mode, start, (size_t)MIN(end - start, mode_size - 1)); } start = end + 1; } else { // colon is not present } // start now points to first address character retval = 0; // we have got an address end = strpbrk(start, "/"); if(!end) // no slash present -- default end end = s + strlen(s); strncpy(ip_addr, start, (size_t)MIN(end - start, addr_size - 1)); // ensure NULL term if(end) { // slash is present // now, handle the sub-network address sscanf(end + 1, "%u", &bitlen); bitlen = htobe32(bitlen2mask(bitlen)); inet_ntop(AF_INET, &bitlen, netmask, netmask_size); } return retval; } /* *************************************************** */ static void help (int level) { if(level == 0) return; /* no help required */ printf("\n"); print_n2n_version(); if(level == 1) /* short help */ { printf(" basic usage: edge (see edge.conf)\n" "\n" " or edge " " -c " "\n " " -l : " "\n " "[-a ] " "\n " #if defined(N2N_CAN_NAME_IFACE) "[-d ] " "\n " #endif "[-k ] " "\n" "\n -h shows a quick reference including all available options" "\n --help gives a detailed parameter description" "\n man files for n2n, edge, and superndode contain in-depth information" "\n\n"); } else if(level == 2) /* quick reference */ { printf(" general usage: edge (see edge.conf)\n" "\n" " or edge " " -c " " -l " "\n " "[-p [:]] " "\n " #ifdef __linux__ "[-T ] " #endif #ifndef __APPLE__ "[-D] " #endif "\n options for under- " "[-i ] " "[-L ] " "\n lying connection " "[-k ] " "[-A] " "[-H] " "[-z] " "\n " "[-e ] [-S]" "\n " "[--select-rtt] " #if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP) "[--no-port-forwarding] " #endif // HAVE_MINIUPNP || HAVE_NATPMP "\n\n tap device and " "[-a [static:|dhcp:][/]] " "\n overlay network " "[-m ] " #if defined(N2N_CAN_NAME_IFACE) "[-d ] " #endif "\n configuration " "[-M ] " "[-r] " "[-E] " "[-I ] " "\n " "[-J ] " "[-P ] " "[-R ] " #ifdef WIN32 "\n " "[-x ] " #endif "\n\n local options " #ifndef WIN32 "[-f] " #endif "[-t ] " "[--management-password ] " "\n " "[-v] " "[-n ] " #ifndef WIN32 "\n " "[-u ] " "[-g ] " #endif "\n\n environment " "N2N_KEY instead of [-k ]" "\n variables " "N2N_COMMUNITY instead of -c " "\n " "N2N_PASSWORD instead of [-J ]" "\n " "\n meaning of the " #ifndef __APPLE__ "[-D] enable PMTU discovery" #endif "\n flag options [-H] enable header encryption" "\n [-r] enable packet forwarding through n2n community" "\n [-E] accept multicast MAC addresses" "\n [--select-rtt] select supernode by round trip time" "\n [--select-mac] select supernode by MAC address" #if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP) "\n [--no-port-forwarding] disable UPnP/PMP port forwarding" #endif // HAVE_MINIUPNP || HAVE_NATPMP #ifndef WIN32 "\n [-f] do not fork but run in foreground" #endif "\n [-v] make more verbose, repeat as required" "\n " "\n -h shows this quick reference including all available options" "\n --help gives a detailed parameter description" "\n man files for n2n, edge, and superndode contain in-depth information" "\n\n"); } else /* long help */ { printf(" general usage: edge (see edge.conf)\n" "\n" " or edge -c -l \n" " [further optional command line parameters]\n\n" ); printf (" OPTIONS FOR THE UNDERLYING NETWORK CONNECTION\n"); printf (" ---------------------------------------------\n\n"); printf(" -c | n2n community name the edge belongs to\n"); printf(" -l | supernode ip address or name, and port\n"); printf(" -p [:] | fixed local UDP port and optionally bind to the\n" " | sepcified local IP address only (any by default)\n"); #ifdef __linux__ printf(" -T | TOS for packets, e.g. 0x48 for SSH like priority\n"); #endif #ifndef __APPLE__ printf(" -D | enable PMTU discovery, it can reduce fragmentation but\n" " | causes connections to stall if not properly supported\n"); #endif printf(" -e | advertises the provided local IP address as preferred,\n" " | useful if multicast peer detection is not available,\n" " | '-e auto' tries IP address auto-detection\n"); printf(" -S1 ... -S2 | do not connect p2p, always use the supernode,\n" " | -S1 = via UDP" #ifdef N2N_HAVE_TCP ", -S2 = via TCP" #endif "\n"); printf(" -i | registration interval, for NAT hole punching (default\n" " | %u seconds)\n", REGISTER_SUPER_INTERVAL_DFL); printf(" -L | TTL for registration packet for NAT hole punching through\n" " | supernode (default 0 for not set)\n"); printf(" -k | encryption key (ASCII) - also N2N_KEY=\n"); printf(" -A1 | disable payload encryption, do not use with key, defaults\n" " | to AES then\n"); printf(" -A2 ... -A5 | choose a cipher for payload encryption, requires a key,\n" " | -A2 = Twofish, -A3 = AES (default if key provided),\n" " | -A4 = ChaCha20, -A5 = Speck-CTR\n"); printf(" -H | use header encryption, supernode needs fixed community\n"); printf(" -z1 ... -z2 | compress outgoing data packets, -z1 = lzo1x,\n" " | " #ifdef HAVE_ZSTD "-z2 = zstd, " #endif "disabled by default\n"); printf("--select-rtt | supernode selection based on round trip time\n" "--select-mac | supernode selection based on MAC address (default:\n" " | by load)\n"); #if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP) printf("--no-port-... | disable UPnP/PMP port forwarding\n" "...forwarding | \n"); #endif // HAVE_MINIUPNP || HAVE_NATPMP printf ("\n"); printf (" TAP DEVICE AND OVERLAY NETWORK CONFIGURATION\n"); printf (" --------------------------------------------\n\n"); printf(" -a [mode][/n] | interface address and optional CIDR subnet, default '/24',\n" " | mode = [static|dhcp]:, for DHCP use '-r -a dhcp:0.0.0.0',\n" " | edge draws IP address from supernode if no '-a ...' given\n"); printf(" -m | fixed MAC address for the TAP interface, e.g.\n" " | '-m 10:20:30:40:50:60', random otherwise\n"); #if defined(N2N_CAN_NAME_IFACE) printf(" -d | TAP device name\n"); #endif printf(" -M | specify n2n MTU of TAP interface, default %d\n", DEFAULT_MTU); printf(" -r | enable packet forwarding through n2n community\n"); printf(" -E | accept multicast MAC addresses, drop by default\n"); printf(" -I | annotate the edge's description used for easier\n" " | identification in management port output or username\n"); printf(" -J | password for user-password edge authentication\n"); printf(" -P | federation public key for user-password authentication\n"); printf(" -R | drop or accept packets by rules, can be set multiple times\n"); printf(" | rule format: 'src_ip/n:[s_port,e_port],...\n" " | |on same| ...dst_ip/n:[s_port,e_port],...\n" " | | line | ...TCP+/-,UDP+/-,ICMP+/-'\n"); #ifdef WIN32 printf(" -x | set TAP interface metric, defaults to 0 (auto),\n" " | e.g. set to 1 for better multiplayer game detection\n"); #endif printf ("\n"); printf (" LOCAL OPTIONS\n"); printf (" -------------\n\n"); #ifndef WIN32 printf(" -f | do not fork and run as a daemon, rather run in foreground\n"); #endif printf(" -t | management UDP port, for multiple edges on a machine,\n" " | defaults to %u\n", N2N_EDGE_MGMT_PORT); printf(" --management_... | management port password, defaults to '%s'\n" " ...password | \n", N2N_MGMT_PASSWORD); printf(" -v | make more verbose, repeat as required\n"); printf(" -n | route an IPv4 network via the gateway, use 0.0.0.0/0 for\n" " | the default gateway, can be set multiple times\n"); #ifndef WIN32 printf(" -u | numeric user ID to use when privileges are dropped\n"); printf(" -g | numeric group ID to use when privileges are dropped\n"); #endif printf ("\n"); printf (" ENVIRONMENT VARIABLES\n"); printf (" ---------------------\n\n"); printf(" N2N_KEY | encryption key (ASCII), not with '-k ...'\n"); printf(" N2N_COMMUNITY | community name (ASCII), overwritten by '-c ...'\n"); printf(" N2N_PASSWORD | password (ASCII) for user-password authentication,\n" " | overwritten by '-J ...'\n"); #ifdef WIN32 printf ("\n"); printf (" AVAILABLE TAP ADAPTERS\n"); printf (" ----------------------\n\n"); win_print_available_adapters(); #endif printf ("\n" "\n -h shows a quick reference including all available options" "\n --help gives this detailed parameter description" "\n man files for n2n, edge, and superndode contain in-depth information" "\n\n"); } exit(0); } /* *************************************************** */ static void setPayloadCompression (n2n_edge_conf_t *conf, int compression) { /* even though 'compression' and 'conf->compression' share the same encoding scheme, * a switch-statement under conditional compilation is used to sort out the * unsupported optarguments */ switch (compression) { case 1: { conf->compression = N2N_COMPRESSION_ID_LZO; break; } #ifdef HAVE_ZSTD case 2: { conf->compression = N2N_COMPRESSION_ID_ZSTD; break; } #endif default: { conf->compression = N2N_COMPRESSION_ID_NONE; // internal comrpession scheme numbering differs from cli counting by one, hence plus one // (internal: 0 == invalid, 1 == none, 2 == lzo, 3 == zstd) traceEvent(TRACE_NORMAL, "the %s compression given by -z_ option is not supported in this version", compression_str(compression + 1)); exit(1); // to make the user aware } } } /* *************************************************** */ static void setPayloadEncryption (n2n_edge_conf_t *conf, int cipher) { /* even though 'cipher' and 'conf->transop_id' share the same encoding scheme, * a switch-statement under conditional compilation is used to sort out the * unsupported ciphers */ switch (cipher) { case 1: { conf->transop_id = N2N_TRANSFORM_ID_NULL; break; } case 2: { conf->transop_id = N2N_TRANSFORM_ID_TWOFISH; break; } case 3: { conf->transop_id = N2N_TRANSFORM_ID_AES; break; } case 4: { conf->transop_id = N2N_TRANSFORM_ID_CHACHA20; break; } case 5: { conf->transop_id = N2N_TRANSFORM_ID_SPECK; break; } default: { conf->transop_id = N2N_TRANSFORM_ID_INVAL; traceEvent(TRACE_NORMAL, "the %s cipher given by -A_ option is not supported in this version", transop_str(cipher)); exit(1); } } } /* *************************************************** */ static int setOption (int optkey, char *optargument, n2n_tuntap_priv_config_t *ec, n2n_edge_conf_t *conf) { /* traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, optargument ? optargument : ""); */ switch(optkey) { case 'a': /* IP address and mode of TUNTAP interface */ { scan_address(ec->ip_addr, N2N_NETMASK_STR_SIZE, ec->netmask, N2N_NETMASK_STR_SIZE, ec->ip_mode, N2N_IF_MODE_SIZE, optargument); break; } case 'c': /* community as a string */ { strncpy((char *)conf->community_name, optargument, N2N_COMMUNITY_SIZE); conf->community_name[N2N_COMMUNITY_SIZE - 1] = '\0'; break; } case 'E': /* multicast ethernet addresses accepted. */ { conf->drop_multicast = 0; traceEvent(TRACE_INFO, "enabling ethernet multicast traffic"); break; } #ifndef WIN32 case 'u': /* unprivileged uid */ { ec->userid = atoi(optargument); break; } case 'g': /* unprivileged uid */ { ec->groupid = atoi(optargument); break; } #endif #ifndef WIN32 case 'f' : /* do not fork as daemon */ { ec->daemon = 0; break; } #endif /* #ifndef WIN32 */ case 'm' : /* TUNTAP MAC address */ { strncpy(ec->device_mac, optargument, N2N_MACNAMSIZ); ec->device_mac[N2N_MACNAMSIZ - 1] = '\0'; break; } case 'M' : /* TUNTAP MTU */ { ec->mtu = atoi(optargument); break; } #ifndef __APPLE__ case 'D' : /* enable PMTU discovery */ { conf->disable_pmtu_discovery = 0; break; } #endif case 'k': /* encrypt key */ { if(conf->encrypt_key) free(conf->encrypt_key); conf->encrypt_key = strdup(optargument); traceEvent(TRACE_DEBUG, "encrypt_key = '%s'\n", conf->encrypt_key); break; } case 'r': /* enable packet routing across n2n endpoints */ { conf->allow_routing = 1; break; } case 'A': { int cipher; if(optargument) { cipher = atoi(optargument); } else { traceEvent(TRACE_WARNING, "the use of the solitary -A switch is deprecated and will not be supported in future versions, " "please use -A3 instead to choose AES cipher for payload encryption"); cipher = N2N_TRANSFORM_ID_AES; // default, if '-A' only } setPayloadEncryption(conf, cipher); break; } case 'H': /* indicate header encryption */ { /* we cannot be sure if this gets parsed before the community name is set. * so, only an indicator is set, action is taken later*/ conf->header_encryption = HEADER_ENCRYPTION_ENABLED; break; } case 'z': { int compression; if(optargument) { compression = atoi(optargument); } else { traceEvent(TRACE_WARNING, "the use of the solitary -z switch is deprecated and will not be supported in future versions, " "please use -z1 instead to choose LZO1X algorithm for payload compression"); compression = 1; // default, if '-z' only, equals -z1 } setPayloadCompression(conf, compression); break; } case 'l': /* supernode-list */ { if(optargument) { if(edge_conf_add_supernode(conf, optargument) != 0) { traceEvent(TRACE_WARNING, "failed to add supernode '%s'", optargument); } } break; } case 'i': /* supernode registration interval */ conf->register_interval = atoi(optargument); break; case 'L': /* supernode registration interval */ conf->register_ttl = atoi(optarg); break; #if defined(N2N_CAN_NAME_IFACE) case 'd': /* TUNTAP name */ { strncpy(ec->tuntap_dev_name, optargument, N2N_IFNAMSIZ); ec->tuntap_dev_name[N2N_IFNAMSIZ - 1] = '\0'; break; } #endif case 'I': /* Device Description (hint) or username */ { strncpy((char *)conf->dev_desc, optargument, N2N_DESC_SIZE); conf->dev_desc[N2N_DESC_SIZE - 1] = '\0'; break; } case 'J': /* password for user-password authentication */ { if(!conf->shared_secret) /* we could already have it from environment variable, see edge_init_conf_defaults() */ conf->shared_secret = calloc(1, sizeof(n2n_private_public_key_t)); if(conf->shared_secret) generate_private_key(*(conf->shared_secret), optargument); // the hash of the username (-I) gets xored into this key later, // we can't be sure to already have it at this point // also, the complete shared secret will be calculated then as we // might still be missing the federation public key as well break; } case 'P': /* federation public key for user-password authentication */ { if(strlen(optargument) < ((N2N_PRIVATE_PUBLIC_KEY_SIZE * 8 + 5)/ 6 + 1)) { conf->federation_public_key = calloc(1, sizeof(n2n_private_public_key_t)); if(conf->federation_public_key) { ascii_to_bin(*(conf->federation_public_key), optargument); } } else { traceEvent(TRACE_WARNING, "public key too long"); return 2; } break; } case 'p': { char* colon = strpbrk(optargument, ":"); if(colon) { /*ip address:port */ *colon = 0; conf->bind_address = ntohl(inet_addr(optargument)); conf->local_port = atoi(++colon); if(conf->bind_address == INADDR_NONE) { traceEvent(TRACE_WARNING, "bad address to bind to, binding to any IP address"); conf->bind_address = INADDR_ANY; } if(conf->local_port == 0) { traceEvent(TRACE_WARNING, "bad local port format, using OS assigned port"); } } else { /* ip address or port only */ char* dot = strpbrk(optargument, "."); if(dot) { /* ip address only */ conf->bind_address = ntohl(inet_addr(optargument)); if(conf->bind_address == INADDR_NONE) { traceEvent(TRACE_WARNING, "bad address to bind to, binding to any IP address"); conf->bind_address = INADDR_ANY; } } else { /* port only */ conf->local_port = atoi(optargument); if(conf->local_port == 0) { traceEvent(TRACE_WARNING, "bad local port format, using OS assigned port"); } } } break; } case 'e': { in_addr_t address_tmp; if(optargument) { if(!strcmp(optargument, "auto")) { address_tmp = INADDR_ANY; conf->preferred_sock_auto = 1; } else { address_tmp = inet_addr(optargument); } memcpy(&(conf->preferred_sock.addr.v4), &(address_tmp), IPV4_SIZE); if(address_tmp == INADDR_NONE) { traceEvent(TRACE_WARNING, "bad address for preferred local socket, skipping"); conf->preferred_sock.family = AF_INVALID; break; } else { conf->preferred_sock.family = AF_INET; // port is set after parsing all cli parameters during supernode_connect() } } break; } case 't': { conf->mgmt_port = atoi(optargument); break; } #ifdef __linux__ case 'T': { if((optargument[0] == '0') && (optargument[1] == 'x')) conf->tos = strtol(&optargument[2], NULL, 16); else conf->tos = atoi(optargument); break; } #endif case 'n': { char cidr_net[64], gateway[64]; n2n_route_t route; if(sscanf(optargument, "%63[^/]/%hhd:%63s", cidr_net, &route.net_bitlen, gateway) != 3) { traceEvent(TRACE_WARNING, "bad cidr/gateway format '%d'", optargument); return 2; } route.net_addr = inet_addr(cidr_net); route.gateway = inet_addr(gateway); if((route.net_bitlen < 0) || (route.net_bitlen > 32)) { traceEvent(TRACE_WARNING, "bad prefix '%d' in '%s'", route.net_bitlen, optargument); return 2; } if(route.net_addr == INADDR_NONE) { traceEvent(TRACE_WARNING, "bad network '%s' in '%s'", cidr_net, optargument); return 2; } if(route.gateway == INADDR_NONE) { traceEvent(TRACE_WARNING, "bad gateway '%s' in '%s'", gateway, optargument); return 2; } traceEvent(TRACE_NORMAL, "adding %s/%d via %s", cidr_net, route.net_bitlen, gateway); conf->routes = realloc(conf->routes, sizeof(struct n2n_route) * (conf->num_routes + 1)); conf->routes[conf->num_routes] = route; conf->num_routes++; break; } case 'S': { int solitude; if(optargument) { solitude = atoi(optargument); } else { traceEvent(TRACE_WARNING, "the use of the solitary -S switch is deprecated and will not be supported in future versions, " "please use -S1 instead to choose supernode-only connection via UDP"); solitude = 1; } // set the level if(solitude >= 1) conf->allow_p2p = 0; #ifdef N2N_HAVE_TCP if(solitude == 2) conf->connect_tcp = 1; #endif break; } case '[': /* round-trip-time-based supernode selection strategy */ { // overwrites the default load-based strategy conf->sn_selection_strategy = SN_SELECTION_STRATEGY_RTT; break; } case ']': /* mac-address-based supernode selection strategy */ { // overwrites the default load-based strategy conf->sn_selection_strategy = SN_SELECTION_STRATEGY_MAC; break; } case '{': /* password for management port */ { conf->mgmt_password_hash = pearson_hash_64((uint8_t*)optargument, strlen(optargument)); break; } case '}': /* disable port forwarding */ { conf->port_forwarding = 0; break; } case 'h': /* quick reference */ { return 2; } case '@': /* long help */ { return 3; } case 'v': /* verbose */ setTraceLevel(getTraceLevel() + 1); break; case 'R': /* network traffic filter */ { filter_rule_t *new_rule = malloc(sizeof(filter_rule_t)); memset(new_rule, 0, sizeof(filter_rule_t)); if(process_traffic_filter_rule_str(optargument, new_rule)) { HASH_ADD(hh, conf->network_traffic_filter_rules, key, sizeof(filter_rule_key_t), new_rule); } else { free(new_rule); traceEvent(TRACE_WARNING, "invalid filter rule: %s", optargument); return 2; } break; } #ifdef WIN32 case 'x': { conf->metric = atoi(optargument); ec->metric = atoi(optargument); break; } #endif default: { traceEvent(TRACE_WARNING, "unknown option -%c", (char)optkey); return 2; } } return 0; } /* *********************************************** */ static const struct option long_options[] = { { "community", required_argument, NULL, 'c' }, { "supernode-list", required_argument, NULL, 'l' }, { "tap-device", required_argument, NULL, 'd' }, { "euid", required_argument, NULL, 'u' }, { "egid", required_argument, NULL, 'g' }, { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, '@' }, /* internal special character '@' to identify long help case */ { "select-rtt", no_argument, NULL, '[' }, /* '[' rtt selection strategy */ { "select-mac", no_argument, NULL, ']' }, /* ']' mac selection strategy */ { "management-password", required_argument, NULL, '{' }, /* '{' management port password */ { "no-port-forwarding", no_argument, NULL, '}' }, /* '}' disable port forwarding */ { NULL, 0, NULL, 0 } }; /* *************************************************** */ /* read command line options */ static int loadFromCLI (int argc, char *argv[], n2n_edge_conf_t *conf, n2n_tuntap_priv_config_t *ec) { u_char c; while ((c = getopt_long(argc, argv, "k:a:c:Eu:g:m:M:s:d:l:p:fvhrt:i:I:J:P:S::DL:z::A::Hn:R:e:" #ifdef __linux__ "T:" #endif #ifdef WIN32 "x:" #endif , long_options, NULL)) != '?') { if(c == 255) break; help(setOption(c, optarg, ec, conf)); } return 0; } /* *************************************************** */ static char *trim (char *s) { char *end; while(isspace(s[0]) || (s[0] == '"') || (s[0] == '\'')) s++; if(s[0] == 0) return s; end = &s[strlen(s) - 1]; while(end > s && (isspace(end[0])|| (end[0] == '"') || (end[0] == '\''))) end--; end[1] = 0; return s; } /* *************************************************** */ /* parse the configuration file */ static int loadFromFile (const char *path, n2n_edge_conf_t *conf, n2n_tuntap_priv_config_t *ec) { char buffer[4096], *line; char *line_vec[3]; int tmp; FILE *fd; fd = fopen(path, "r"); if(fd == NULL) { traceEvent(TRACE_WARNING, "config file %s not found", path); return -1; } // we mess around with optind, better save it tmp = optind; while((line = fgets(buffer, sizeof(buffer), fd)) != NULL) { line = trim(line); if(strlen(line) < 2 || line[0] == '#') continue; // executable, cannot be omitted, content can be anything line_vec[0] = line; // first token, e.g. `-p` or `-A3', eventually followed by a whitespace or '=' delimiter line_vec[1] = strtok(line, "\t ="); // separate parameter option, if present line_vec[2] = strtok(NULL, ""); if(line_vec[2]) line_vec[2] = trim(line_vec[2]); // not to duplicate the option parser code, call loadFromCLI and pretend we have no option read yet at all optind = 0; // if second token present (optional argument, not part of first), then announce 3 vector members loadFromCLI(line_vec[2] ? 3 : 2, line_vec, conf, ec); } fclose(fd); optind = tmp; return 0; } /* ************************************** */ #ifndef WIN32 static void daemonize () { int childpid; traceEvent(TRACE_NORMAL, "parent process is exiting (this is normal)"); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGCHLD, SIG_IGN); signal(SIGQUIT, SIG_IGN); if((childpid = fork()) < 0) traceEvent(TRACE_ERROR, "occurred while daemonizing (errno=%d)", errno); else { if(!childpid) { /* child */ int rc; //traceEvent(TRACE_NORMAL, "Bye bye: I'm becoming a daemon..."); rc = chdir("/"); if(rc != 0) traceEvent(TRACE_ERROR, "error while moving to / directory"); setsid(); /* detach from the terminal */ fclose(stdin); fclose(stdout); /* fclose(stderr); */ /* * clear any inherited file mode creation mask */ //umask(0); /* * Use line buffered stdout */ /* setlinebuf (stdout); */ setvbuf(stdout, (char *)NULL, _IOLBF, 0); } else /* father */ exit(0); } } #endif /* *************************************************** */ static int keep_on_running; #if defined(__linux__) || defined(WIN32) #ifdef WIN32 BOOL WINAPI term_handler(DWORD sig) #else static void term_handler(int sig) #endif { static int called = 0; if(called) { traceEvent(TRACE_NORMAL, "ok, I am leaving now"); _exit(0); } else { traceEvent(TRACE_NORMAL, "shutting down..."); called = 1; } keep_on_running = 0; #ifdef WIN32 return(TRUE); #endif } #endif /* defined(__linux__) || defined(WIN32) */ /* *************************************************** */ /** Entry point to program from kernel. */ int main (int argc, char* argv[]) { int rc; tuntap_dev tuntap; /* a tuntap device */ n2n_edge_t *eee; /* single instance for this program */ n2n_edge_conf_t conf; /* generic N2N edge config */ n2n_tuntap_priv_config_t ec; /* config used for standalone program execution */ uint8_t runlevel = 0; /* bootstrap: runlevel */ uint8_t seek_answer = 1; /* expecting answer from supernode */ time_t now, last_action = 0; /* timeout */ macstr_t mac_buf; /* output mac address */ fd_set socket_mask; /* for supernode answer */ struct timeval wait_time; /* timeout for sn answer */ peer_info_t *scan, *scan_tmp; /* supernode iteration */ uint16_t expected = sizeof(uint16_t); uint16_t position = 0; uint8_t pktbuf[N2N_SN_PKTBUF_SIZE + sizeof(uint16_t)]; /* buffer + prepended buffer length in case of tcp */ #ifndef WIN32 struct passwd *pw = NULL; #endif #ifdef HAVE_LIBCAP cap_t caps; #endif #ifdef WIN32 initWin32(); #endif /* Defaults */ edge_init_conf_defaults(&conf); memset(&ec, 0, sizeof(ec)); ec.mtu = DEFAULT_MTU; ec.daemon = 1; /* By default run in daemon mode. */ #ifndef WIN32 if(((pw = getpwnam("n2n")) != NULL) || ((pw = getpwnam("nobody")) != NULL)) { ec.userid = pw->pw_uid; ec.groupid = pw->pw_gid; } #endif #ifdef WIN32 ec.tuntap_dev_name[0] = '\0'; ec.metric = 0; #else snprintf(ec.tuntap_dev_name, sizeof(ec.tuntap_dev_name), N2N_EDGE_DEFAULT_DEV_NAME); #endif snprintf(ec.netmask, sizeof(ec.netmask), N2N_EDGE_DEFAULT_NETMASK); if((argc >= 2) && (argv[1][0] != '-')) { rc = loadFromFile(argv[1], &conf, &ec); if(argc > 2) rc = loadFromCLI(argc, argv, &conf, &ec); } else if(argc > 1) rc = loadFromCLI(argc, argv, &conf, &ec); else #ifdef WIN32 // load from current directory rc = loadFromFile("edge.conf", &conf, &ec); #else rc = -1; #endif // --- additional crypto setup; REVISIT: move to edge_init()? // payload if(conf.transop_id == N2N_TRANSFORM_ID_NULL) { if(conf.encrypt_key) { // make sure that AES is default cipher if key only (and no cipher) is specified traceEvent(TRACE_WARNING, "switching to AES as key was provided"); conf.transop_id = N2N_TRANSFORM_ID_AES; } } // user auth if(conf.shared_secret /* containing private key only so far*/) { // if user-password auth and no federation public key provided, use default if(!conf.federation_public_key) { conf.federation_public_key = calloc(1, sizeof(n2n_private_public_key_t)); if(conf.federation_public_key) { traceEvent(TRACE_WARNING, "using default federation public key; FOR TESTING ONLY, usage of a custom federation name and key (-P) is highly recommended!"); generate_private_key(*(conf.federation_public_key), &FEDERATION_NAME[1]); generate_public_key(*(conf.federation_public_key), *(conf.federation_public_key)); } } // calculate public key and shared secret if(conf.federation_public_key) { traceEvent(TRACE_NORMAL, "using username and password for edge authentication"); bind_private_key_to_username(*(conf.shared_secret), (char *)conf.dev_desc); conf.public_key = calloc(1, sizeof(n2n_private_public_key_t)); if(conf.public_key) generate_public_key(*conf.public_key, *(conf.shared_secret)); generate_shared_secret(*(conf.shared_secret), *(conf.shared_secret), *(conf.federation_public_key)); // prepare (first 128 bit) for use as key conf.shared_secret_ctx = (he_context_t*)calloc(1, sizeof(speck_context_t)); speck_init((speck_context_t**)&(conf.shared_secret_ctx), *(conf.shared_secret), 128); } // force header encryption if(conf.header_encryption != HEADER_ENCRYPTION_ENABLED) { traceEvent(TRACE_NORMAL, "enabling header encryption for edge authentication"); conf.header_encryption = HEADER_ENCRYPTION_ENABLED; } } if(rc < 0) help(1); /* short help */ if(edge_verify_conf(&conf) != 0) help(1); /* short help */ traceEvent(TRACE_NORMAL, "starting n2n edge %s %s", PACKAGE_VERSION, PACKAGE_BUILDDATE); #if defined(HAVE_OPENSSL_1_1) traceEvent(TRACE_NORMAL, "using %s", OpenSSL_version(0)); #endif traceEvent(TRACE_NORMAL, "using compression: %s.", compression_str(conf.compression)); traceEvent(TRACE_NORMAL, "using %s cipher.", transop_str(conf.transop_id)); /* Random seed */ n2n_srand (n2n_seed()); #ifndef WIN32 /* If running suid root then we need to setuid before using the force. */ if(setuid(0) != 0) traceEvent(TRACE_ERROR, "unable to become root [%u/%s]", errno, strerror(errno)); /* setgid(0); */ #endif if(conf.encrypt_key && !strcmp((char*)conf.community_name, conf.encrypt_key)) traceEvent(TRACE_WARNING, "community and encryption key must differ, otherwise security will be compromised"); if((eee = edge_init(&conf, &rc)) == NULL) { traceEvent(TRACE_ERROR, "failed in edge_init"); exit(1); } memcpy(&(eee->tuntap_priv_conf), &ec, sizeof(ec)); if((0 == strcmp("static", eee->tuntap_priv_conf.ip_mode)) || ((eee->tuntap_priv_conf.ip_mode[0] == '\0') && (eee->tuntap_priv_conf.ip_addr[0] != '\0'))) { traceEvent(TRACE_NORMAL, "use manually set IP address"); eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_STATIC; } else if(0 == strcmp("dhcp", eee->tuntap_priv_conf.ip_mode)) { traceEvent(TRACE_NORMAL, "obtain IP from other edge DHCP services"); eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_DHCP; } else { traceEvent(TRACE_NORMAL, "automatically assign IP address by supernode"); eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_SN_ASSIGN; } // mini main loop for bootstrap, not using main loop code because some of its mechanisms do not fit in here // for the sake of quickly establishing connection. REVISIT when a more elegant way to re-use main loop code // is found // find at least one supernode alive to faster establish connection // exceptions: if((HASH_COUNT(eee->conf.supernodes) <= 1) || (eee->conf.connect_tcp) || (eee->conf.shared_secret)) { // skip the initial supernode ping traceEvent(TRACE_DEBUG, "skip PING to supernode"); runlevel = 2; } eee->last_sup = 0; /* if it wasn't zero yet */ eee->curr_sn = eee->conf.supernodes; supernode_connect(eee); while(runlevel < 5) { now = time(NULL); // we do not use switch-case because we also check for 'greater than' if(runlevel == 0) { /* PING to all known supernodes */ last_action = now; eee->sn_pong = 0; // (re-)initialize the number of max concurrent pings (decreases by calling send_query_peer) eee->conf.number_max_sn_pings = NUMBER_SN_PINGS_INITIAL; send_query_peer(eee, null_mac); traceEvent(TRACE_NORMAL, "send PING to supernodes"); runlevel++; } if(runlevel == 1) { /* PING has been sent to all known supernodes */ if(eee->sn_pong) { // first answer eee->sn_pong = 0; sn_selection_sort(&(eee->conf.supernodes)); eee->curr_sn = eee->conf.supernodes; supernode_connect(eee); traceEvent(TRACE_NORMAL, "received first PONG from supernode [%s]", eee->curr_sn->ip_addr); runlevel++; } else if(last_action <= (now - BOOTSTRAP_TIMEOUT)) { // timeout runlevel--; // skip waiting for answer to direcly go to send PING again seek_answer = 0; traceEvent(TRACE_DEBUG, "PONG timeout"); } } // by the way, have every later PONG cause the remaining (!) list to be sorted because the entries // before have already been tried; as opposed to initial PONG, do not change curr_sn if(runlevel > 1) { if(eee->sn_pong) { eee->sn_pong = 0; if(eee->curr_sn->hh.next) { sn_selection_sort((peer_info_t**)&(eee->curr_sn->hh.next)); traceEvent(TRACE_DEBUG, "received additional PONG from supernode"); // here, it is hard to detemine from which one, so no details to output } } } if(runlevel == 2) { /* send REGISTER_SUPER to get auto ip address from a supernode */ if(eee->conf.tuntap_ip_mode == TUNTAP_IP_MODE_SN_ASSIGN) { last_action = now; eee->sn_wait = 1; send_register_super(eee); runlevel++; traceEvent(TRACE_NORMAL, "send REGISTER_SUPER to supernode [%s] asking for IP address", eee->curr_sn->ip_addr); } else { runlevel += 2; /* skip waiting for TUNTAP IP address */ traceEvent(TRACE_DEBUG, "skip auto IP address asignment"); } } if(runlevel == 3) { /* REGISTER_SUPER to get auto ip address from a sn has been sent */ if(!eee->sn_wait) { /* TUNTAP IP address received */ runlevel++; traceEvent(TRACE_NORMAL, "received REGISTER_SUPER_ACK from supernode for IP address asignment"); // it should be from curr_sn, but we can't determine definitely here, so no details to output } else if(last_action <= (now - BOOTSTRAP_TIMEOUT)) { // timeout, so try next supernode if(eee->curr_sn->hh.next) eee->curr_sn = eee->curr_sn->hh.next; else eee->curr_sn = eee->conf.supernodes; supernode_connect(eee); runlevel--; // skip waiting for answer to direcly go to send REGISTER_SUPER again seek_answer = 0; traceEvent(TRACE_DEBUG, "REGISTER_SUPER_ACK timeout"); } } if(runlevel == 4) { /* configure the TUNTAP device, including routes */ if(tuntap_open(&tuntap, eee->tuntap_priv_conf.tuntap_dev_name, eee->tuntap_priv_conf.ip_mode, eee->tuntap_priv_conf.ip_addr, eee->tuntap_priv_conf.netmask, eee->tuntap_priv_conf.device_mac, eee->tuntap_priv_conf.mtu #ifdef WIN32 , eee->tuntap_priv_conf.metric #endif ) < 0) exit(1); memcpy(&eee->device, &tuntap, sizeof(tuntap)); traceEvent(TRACE_NORMAL, "created local tap device IP: %s, Mask: %s, MAC: %s", eee->tuntap_priv_conf.ip_addr, eee->tuntap_priv_conf.netmask, macaddr_str(mac_buf, eee->device.mac_addr)); // routes if(edge_init_routes(eee, eee->conf.routes, eee->conf.num_routes) < 0) { traceEvent(TRACE_ERROR, "routes setup failed"); exit(1); } runlevel = 5; // no more answers required seek_answer = 0; } // we usually wait for some answer, there however are exceptions when going back to a previous runlevel if(seek_answer) { FD_ZERO(&socket_mask); FD_SET(eee->sock, &socket_mask); wait_time.tv_sec = BOOTSTRAP_TIMEOUT; wait_time.tv_usec = 0; if(select(eee->sock + 1, &socket_mask, NULL, NULL, &wait_time) > 0) { if(FD_ISSET(eee->sock, &socket_mask)) { fetch_and_eventually_process_data (eee, eee->sock, pktbuf, &expected, &position, now); } } } seek_answer = 1; resolve_check(eee->resolve_parameter, 0 /* no intermediate resolution requirement at this point */, now); } // allow a higher number of pings for first regular round of ping // to quicker get an inital 'supernode selection criterion overview' eee->conf.number_max_sn_pings = NUMBER_SN_PINGS_INITIAL; // shape supernode list; make current one the first on the list HASH_ITER(hh, eee->conf.supernodes, scan, scan_tmp) { if(scan == eee->curr_sn) sn_selection_criterion_good(&(scan->selection_criterion)); else sn_selection_criterion_default(&(scan->selection_criterion)); } sn_selection_sort(&(eee->conf.supernodes)); // do not immediately ping again, allow some time eee->last_sweep = now - SWEEP_TIME + 2 * BOOTSTRAP_TIMEOUT; eee->sn_wait = 1; eee->last_register_req = 0; #ifndef WIN32 if(eee->tuntap_priv_conf.daemon) { setUseSyslog(1); /* traceEvent output now goes to syslog. */ daemonize(); } #ifdef HAVE_LIBCAP /* Before dropping the privileges, retain capabilities to regain them in future. */ caps = cap_get_proc(); cap_set_flag(caps, CAP_PERMITTED, num_cap, cap_values, CAP_SET); cap_set_flag(caps, CAP_EFFECTIVE, num_cap, cap_values, CAP_SET); if((cap_set_proc(caps) != 0) || (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0)) traceEvent(TRACE_WARNING, "unable to retain permitted capabilities [%s]\n", strerror(errno)); #else #ifndef __APPLE__ traceEvent(TRACE_WARNING, "n2n has not been compiled with libcap-dev; some commands may fail"); #endif #endif /* HAVE_LIBCAP */ if((eee->tuntap_priv_conf.userid != 0) || (eee->tuntap_priv_conf.groupid != 0)) { traceEvent(TRACE_NORMAL, "dropping privileges to uid=%d, gid=%d", (signed int)eee->tuntap_priv_conf.userid, (signed int)eee->tuntap_priv_conf.groupid); /* Finished with the need for root privileges. Drop to unprivileged user. */ if((setgid(eee->tuntap_priv_conf.groupid) != 0) || (setuid(eee->tuntap_priv_conf.userid) != 0)) { traceEvent(TRACE_ERROR, "unable to drop privileges [%u/%s]", errno, strerror(errno)); exit(1); } } if((getuid() == 0) || (getgid() == 0)) traceEvent(TRACE_WARNING, "running as root is discouraged, check out the -u/-g options"); #endif #ifdef __linux__ signal(SIGPIPE, SIG_IGN); signal(SIGTERM, term_handler); signal(SIGINT, term_handler); #endif #ifdef WIN32 SetConsoleCtrlHandler(term_handler, TRUE); #endif keep_on_running = 1; eee->keep_running = &keep_on_running; traceEvent(TRACE_NORMAL, "edge started"); rc = run_edge_loop(eee); print_edge_stats(eee); #ifdef HAVE_LIBCAP /* Before completing the cleanup, regain the capabilities as some * cleanup tasks require them (e.g. routes cleanup). */ cap_set_flag(caps, CAP_EFFECTIVE, num_cap, cap_values, CAP_SET); if(cap_set_proc(caps) != 0) traceEvent(TRACE_WARNING, "could not regain the capabilities [%s]\n", strerror(errno)); cap_free(caps); #endif /* Cleanup */ edge_term_conf(&eee->conf); tuntap_close(&eee->device); edge_term(eee); #ifdef WIN32 destroyWin32(); #endif return(rc); } /* ************************************** */ ntop-n2n-90215bd/src/edge_management.c000066400000000000000000000773071422132035700175650ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #include "edge_utils_win32.h" typedef struct strbuf { size_t size; char str[]; } strbuf_t; #define STRBUF_INIT(buf,p) do { \ buf = (void *)p; \ buf->size = sizeof(*p) - sizeof(size_t); \ } while(0) enum n2n_mgmt_type { N2N_MGMT_UNKNOWN = 0, N2N_MGMT_READ = 1, N2N_MGMT_WRITE = 2, N2N_MGMT_SUB = 3, }; /* * Everything needed to reply to a request */ typedef struct mgmt_req { n2n_edge_t *eee; enum n2n_mgmt_type type; char tag[10]; struct sockaddr_in sender_sock; } mgmt_req_t; /* * Read/Write handlers are defined in this structure */ #define FLAG_WROK 1 typedef struct mgmt_handler { int flags; char *cmd; char *help; void (*func)(mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv); } mgmt_handler_t; /* * Event topic names are defined in this structure */ typedef struct mgmt_events { enum n2n_event_topic topic; char *cmd; char *help; } mgmt_events_t; // Lookup the index of matching argv0 in a cmd list // store index in "Result", or -1 for not found #define lookup_handler(Result, list, argv0) do { \ int nr_max = sizeof(list) / sizeof(list[0]); \ for( Result=0; Result < nr_max; Result++ ) { \ if(0 == strcmp(list[Result].cmd, argv0)) { \ break; \ } \ } \ if( Result >= nr_max ) { \ Result = -1; \ } \ } while(0) ssize_t send_reply (mgmt_req_t *req, strbuf_t *buf, size_t msg_len) { // TODO: better error handling (counters?) return sendto(req->eee->udp_mgmt_sock, buf->str, msg_len, 0, (struct sockaddr *) &req->sender_sock, sizeof(struct sockaddr_in)); } size_t gen_json_1str (strbuf_t *buf, char *tag, char *_type, char *key, char *val) { return snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"%s\"," "\"%s\":\"%s\"}\n", tag, _type, key, val); } size_t gen_json_1uint (strbuf_t *buf, char *tag, char *_type, char *key, unsigned int val) { return snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"%s\"," "\"%s\":%u}\n", tag, _type, key, val); } static void send_json_1str (mgmt_req_t *req, strbuf_t *buf, char *_type, char *key, char *val) { size_t msg_len = gen_json_1str(buf, req->tag, _type, key, val); send_reply(req, buf, msg_len); } static void send_json_1uint (mgmt_req_t *req, strbuf_t *buf, char *_type, char *key, unsigned int val) { size_t msg_len = gen_json_1uint(buf, req->tag, _type, key, val); send_reply(req, buf, msg_len); } size_t event_debug (strbuf_t *buf, char *tag, int data0, void *data1) { traceEvent(TRACE_DEBUG, "Unexpected call to event_debug"); return 0; } size_t event_test (strbuf_t *buf, char *tag, int data0, void *data1) { size_t msg_len = gen_json_1str(buf, tag, "event", "test", (char *)data1); return msg_len; } size_t event_peer (strbuf_t *buf, char *tag, int data0, void *data1) { int action = data0; struct peer_info *peer = (struct peer_info *)data1; macstr_t mac_buf; n2n_sock_str_t sockbuf; /* * Just the peer_info bits that are needed for lookup (maccaddr) or * firewall and routing (sockaddr) * If needed, other details can be fetched via the edges method call. */ return snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"event\"," "\"action\":%i," "\"macaddr\":\"%s\"," "\"sockaddr\":\"%s\"}\n", tag, action, (is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock))); } static void mgmt_error (mgmt_req_t *req, strbuf_t *buf, char *msg) { send_json_1str(req, buf, "error", "error", msg); } static void mgmt_stop (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { if(req->type==N2N_MGMT_WRITE) { *req->eee->keep_running = 0; } send_json_1uint(req, buf, "row", "keep_running", *req->eee->keep_running); } static void mgmt_verbose (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { if(req->type==N2N_MGMT_WRITE) { if(argv) { setTraceLevel(strtoul(argv, NULL, 0)); } } send_json_1uint(req, buf, "row", "traceLevel", getTraceLevel()); } static void mgmt_communities (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { if(req->eee->conf.header_encryption != HEADER_ENCRYPTION_NONE) { mgmt_error(req, buf, "noaccess"); return; } send_json_1str(req, buf, "row", "community", (char *)req->eee->conf.community_name); } static void mgmt_supernodes (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { size_t msg_len; struct peer_info *peer, *tmpPeer; macstr_t mac_buf; n2n_sock_str_t sockbuf; selection_criterion_str_t sel_buf; HASH_ITER(hh, req->eee->conf.supernodes, peer, tmpPeer) { /* * TODO: * The version string provided by the remote supernode could contain * chars that make our JSON invalid. * - do we care? */ msg_len = snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"version\":\"%s\"," "\"purgeable\":%i," "\"current\":%i," "\"macaddr\":\"%s\"," "\"sockaddr\":\"%s\"," "\"selection\":\"%s\"," "\"last_seen\":%li," "\"uptime\":%li}\n", req->tag, peer->version, peer->purgeable, (peer == req->eee->curr_sn) ? (req->eee->sn_wait ? 2 : 1 ) : 0, is_null_mac(peer->mac_addr) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), sn_selection_criterion_str(req->eee, sel_buf, peer), peer->last_seen, peer->uptime); send_reply(req, buf, msg_len); } } static void mgmt_edges_row (mgmt_req_t *req, strbuf_t *buf, struct peer_info *peer, char *mode) { size_t msg_len; macstr_t mac_buf; n2n_sock_str_t sockbuf; dec_ip_bit_str_t ip_bit_str = {'\0'}; msg_len = snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"mode\":\"%s\"," "\"ip4addr\":\"%s\"," "\"purgeable\":%i," "\"local\":%i," "\"macaddr\":\"%s\"," "\"sockaddr\":\"%s\"," "\"desc\":\"%s\"," "\"last_p2p\":%li,\n" "\"last_sent_query\":%li,\n" "\"last_seen\":%li}\n", req->tag, mode, (peer->dev_addr.net_addr == 0) ? "" : ip_subnet_to_str(ip_bit_str, &peer->dev_addr), peer->purgeable, peer->local, (is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), peer->dev_desc, peer->last_p2p, peer->last_sent_query, peer->last_seen); send_reply(req, buf, msg_len); } static void mgmt_edges (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { struct peer_info *peer, *tmpPeer; // dump nodes with forwarding through supernodes HASH_ITER(hh, req->eee->pending_peers, peer, tmpPeer) { mgmt_edges_row(req, buf, peer, "pSp"); } // dump peer-to-peer nodes HASH_ITER(hh, req->eee->known_peers, peer, tmpPeer) { mgmt_edges_row(req, buf, peer, "p2p"); } } static void mgmt_timestamps (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { size_t msg_len; msg_len = snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"start_time\":%lu," "\"last_super\":%ld," "\"last_p2p\":%ld}\n", req->tag, req->eee->start_time, req->eee->last_sup, req->eee->last_p2p); send_reply(req, buf, msg_len); } static void mgmt_packetstats (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { size_t msg_len; msg_len = snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"type\":\"transop\"," "\"tx_pkt\":%lu," "\"rx_pkt\":%lu}\n", req->tag, req->eee->transop.tx_cnt, req->eee->transop.rx_cnt); send_reply(req, buf, msg_len); msg_len = snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"type\":\"p2p\"," "\"tx_pkt\":%u," "\"rx_pkt\":%u}\n", req->tag, req->eee->stats.tx_p2p, req->eee->stats.rx_p2p); send_reply(req, buf, msg_len); msg_len = snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"type\":\"super\"," "\"tx_pkt\":%u," "\"rx_pkt\":%u}\n", req->tag, req->eee->stats.tx_sup, req->eee->stats.rx_sup); send_reply(req, buf, msg_len); msg_len = snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"type\":\"super_broadcast\"," "\"tx_pkt\":%u," "\"rx_pkt\":%u}\n", req->tag, req->eee->stats.tx_sup_broadcast, req->eee->stats.rx_sup_broadcast); send_reply(req, buf, msg_len); } static void mgmt_post_test (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { send_json_1str(req, buf, "row", "sending", "test"); mgmt_event_post(N2N_EVENT_TEST, -1, argv); } static void mgmt_unimplemented (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { mgmt_error(req, buf, "unimplemented"); } // Forward define so we can include this in the mgmt_handlers[] table static void mgmt_help (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv); static void mgmt_help_events (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv); static const mgmt_handler_t mgmt_handlers[] = { { .cmd = "reload_communities", .flags = FLAG_WROK, .help = "Reserved for supernode", .func = mgmt_unimplemented}, { .cmd = "stop", .flags = FLAG_WROK, .help = "Gracefully exit edge", .func = mgmt_stop}, { .cmd = "verbose", .flags = FLAG_WROK, .help = "Manage verbosity level", .func = mgmt_verbose}, { .cmd = "communities", .help = "Show current community", .func = mgmt_communities}, { .cmd = "edges", .help = "List current edges/peers", .func = mgmt_edges}, { .cmd = "supernodes", .help = "List current supernodes", .func = mgmt_supernodes}, { .cmd = "timestamps", .help = "Event timestamps", .func = mgmt_timestamps}, { .cmd = "packetstats", .help = "traffic counters", .func = mgmt_packetstats}, { .cmd = "post.test", .help = "send a test event", .func = mgmt_post_test}, { .cmd = "help", .flags = FLAG_WROK, .help = "Show JSON commands", .func = mgmt_help}, { .cmd = "help.events", .help = "Show available Subscribe topics", .func = mgmt_help_events}, }; /* Current subscriber for each event topic */ static mgmt_req_t mgmt_event_subscribers[] = { [N2N_EVENT_DEBUG] = { .eee = NULL, .type = N2N_MGMT_UNKNOWN, .tag = "\0" }, [N2N_EVENT_TEST] = { .eee = NULL, .type = N2N_MGMT_UNKNOWN, .tag = "\0" }, [N2N_EVENT_PEER] = { .eee = NULL, .type = N2N_MGMT_UNKNOWN, .tag = "\0" }, }; /* Map topic number to function */ static const size_t (*mgmt_events[])(strbuf_t *buf, char *tag, int data0, void *data1) = { [N2N_EVENT_DEBUG] = event_debug, [N2N_EVENT_TEST] = event_test, [N2N_EVENT_PEER] = event_peer, }; /* Allow help and subscriptions to use topic name */ static const mgmt_events_t mgmt_event_names[] = { { .cmd = "debug", .topic = N2N_EVENT_DEBUG, .help = "All events - for event debugging"}, { .cmd = "test", .topic = N2N_EVENT_TEST, .help = "Used only by post.test"}, { .cmd = "peer", .topic = N2N_EVENT_PEER, .help = "Changes to peer list"}, }; void mgmt_event_post (enum n2n_event_topic topic, int data0, void *data1) { mgmt_req_t *debug = &mgmt_event_subscribers[N2N_EVENT_DEBUG]; mgmt_req_t *sub = &mgmt_event_subscribers[topic]; traceEvent(TRACE_DEBUG, "post topic=%i data0=%i", topic, data0); if( sub->type != N2N_MGMT_SUB && debug->type != N2N_MGMT_SUB) { // If neither of this topic or the debug topic have a subscriber // then we dont need to do any work return; } char buf_space[100]; strbuf_t *buf; STRBUF_INIT(buf, buf_space); char *tag; if(sub->type == N2N_MGMT_SUB) { tag = sub->tag; } else { tag = debug->tag; } size_t msg_len = mgmt_events[topic](buf, tag, data0, data1); if(sub->type == N2N_MGMT_SUB) { send_reply(sub, buf, msg_len); } if(debug->type == N2N_MGMT_SUB) { send_reply(debug, buf, msg_len); } } static void mgmt_help_events (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { size_t msg_len; int i; int nr_handlers = sizeof(mgmt_event_names) / sizeof(mgmt_events_t); for( i=0; i < nr_handlers; i++ ) { int topic = mgmt_event_names[i].topic; mgmt_req_t *sub = &mgmt_event_subscribers[topic]; char host[40]; char serv[6]; if((sub->type != N2N_MGMT_SUB) || getnameinfo((struct sockaddr *)&sub->sender_sock, sizeof(sub->sender_sock), host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { host[0] = '?'; host[1] = 0; serv[0] = '?'; serv[1] = 0; } // TODO: handle a topic with no subscribers more cleanly msg_len = snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"topic\":\"%s\"," "\"tag\":\"%s\"," "\"sockaddr\":\"%s:%s\"," "\"help\":\"%s\"}\n", req->tag, mgmt_event_names[i].cmd, sub->tag, host, serv, mgmt_event_names[i].help); send_reply(req, buf, msg_len); } } static void mgmt_help (mgmt_req_t *req, strbuf_t *buf, char *argv0, char *argv) { size_t msg_len; /* * Even though this command is readonly, we deliberately do not check * the type - allowing help replies to both read and write requests */ int i; int nr_handlers = sizeof(mgmt_handlers) / sizeof(mgmt_handler_t); for( i=0; i < nr_handlers; i++ ) { msg_len = snprintf(buf->str, buf->size, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"cmd\":\"%s\"," "\"help\":\"%s\"}\n", req->tag, mgmt_handlers[i].cmd, mgmt_handlers[i].help); send_reply(req, buf, msg_len); } } /* * Check if the user is authorised for this command. * - this should be more configurable! * - for the moment we use some simple heuristics: * Reads are not dangerous, so they are simply allowed * Writes are possibly dangerous, so they need a fake password */ static int mgmt_auth (mgmt_req_t *req, char *auth, char *argv0, char *argv) { if(auth) { /* If we have an auth key, it must match */ if(req->eee->conf.mgmt_password_hash == pearson_hash_64((uint8_t*)auth, strlen(auth))) { return 1; } return 0; } /* if we dont have an auth key, we can still read */ if(req->type == N2N_MGMT_READ) { return 1; } return 0; } static void handleMgmtJson (mgmt_req_t *req, char *udp_buf, const int recvlen) { strbuf_t *buf; char cmdlinebuf[80]; char *typechar; char *options; char *argv0; char *argv; char *flagstr; int flags; char *auth; /* Initialise the tag field until we extract it from the cmdline */ req->tag[0] = '-'; req->tag[1] = '1'; req->tag[2] = '\0'; /* save a copy of the commandline before we reuse the udp_buf */ strncpy(cmdlinebuf, udp_buf, sizeof(cmdlinebuf)-1); cmdlinebuf[sizeof(cmdlinebuf)-1] = 0; traceEvent(TRACE_DEBUG, "mgmt json %s", cmdlinebuf); /* we reuse the buffer already on the stack for all our strings */ STRBUF_INIT(buf, udp_buf); typechar = strtok(cmdlinebuf, " \r\n"); if(!typechar) { /* should not happen */ mgmt_error(req, buf, "notype"); return; } if(*typechar == 'r') { req->type=N2N_MGMT_READ; } else if(*typechar == 'w') { req->type=N2N_MGMT_WRITE; } else if(*typechar == 's') { req->type=N2N_MGMT_SUB; } else { mgmt_error(req, buf, "badtype"); return; } /* Extract the tag to use in all reply packets */ options = strtok(NULL, " \r\n"); if(!options) { mgmt_error(req, buf, "nooptions"); return; } argv0 = strtok(NULL, " \r\n"); if(!argv0) { mgmt_error(req, buf, "nocmd"); return; } /* * The entire rest of the line is the argv. We apply no processing * or arg separation so that the cmd can use it however it needs. */ argv = strtok(NULL, "\r\n"); /* * There might be an auth token mixed in with the tag */ char *tagp = strtok(options, ":"); strncpy(req->tag, tagp, sizeof(req->tag)-1); req->tag[sizeof(req->tag)-1] = '\0'; flagstr = strtok(NULL, ":"); if(flagstr) { flags = strtoul(flagstr, NULL, 16); } else { flags = 0; } /* Only 1 flag bit defined at the moment - "auth option present" */ if(flags & 1) { auth = strtok(NULL, ":"); } else { auth = NULL; } if(!mgmt_auth(req, auth, argv0, argv)) { mgmt_error(req, buf, "badauth"); return; } if(req->type == N2N_MGMT_SUB) { int handler; lookup_handler(handler, mgmt_event_names, argv0); if(handler == -1) { mgmt_error(req, buf, "unknowntopic"); return; } int topic = mgmt_event_names[handler].topic; if(mgmt_event_subscribers[topic].type == N2N_MGMT_SUB) { send_json_1str(&mgmt_event_subscribers[topic], buf, "unsubscribed", "topic", argv0); send_json_1str(req, buf, "replacing", "topic", argv0); } memcpy(&mgmt_event_subscribers[topic], req, sizeof(*req)); send_json_1str(req, buf, "subscribe", "topic", argv0); return; } int handler; lookup_handler(handler, mgmt_handlers, argv0); if(handler == -1) { mgmt_error(req, buf, "unknowncmd"); return; } if((req->type==N2N_MGMT_WRITE) && !(mgmt_handlers[handler].flags & FLAG_WROK)) { mgmt_error(req, buf, "readonly"); return; } /* * TODO: * The tag provided by the requester could contain chars * that make our JSON invalid. * - do we care? */ send_json_1str(req, buf, "begin", "cmd", argv0); mgmt_handlers[handler].func(req, buf, argv0, argv); send_json_1str(req, buf, "end", "cmd", argv0); return; } /** Read a datagram from the management UDP socket and take appropriate * action. */ void readFromMgmtSocket (n2n_edge_t *eee) { char udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */ ssize_t recvlen; /* ssize_t sendlen; */ mgmt_req_t req; socklen_t i; size_t msg_len; time_t now; struct peer_info *peer, *tmpPeer; macstr_t mac_buf; char time_buf[10]; /* 9 digits + 1 terminating zero */ char uptime_buf[11]; /* 10 digits + 1 terminating zero */ /* dec_ip_bit_str_t ip_bit_str = {'\0'}; */ /* dec_ip_str_t ip_str = {'\0'}; */ in_addr_t net; n2n_sock_str_t sockbuf; uint32_t num_pending_peers = 0; uint32_t num_known_peers = 0; uint32_t num = 0; selection_criterion_str_t sel_buf; req.eee = eee; now = time(NULL); i = sizeof(req.sender_sock); recvlen = recvfrom(eee->udp_mgmt_sock, udp_buf, N2N_PKT_BUF_SIZE, 0 /*flags*/, (struct sockaddr *) &req.sender_sock, (socklen_t *) &i); if(recvlen < 0) { traceEvent(TRACE_WARNING, "mgmt recvfrom failed: %d - %s", errno, strerror(errno)); return; /* failed to receive data from UDP */ } /* avoid parsing any uninitialized junk from the stack */ udp_buf[recvlen] = 0; if((0 == memcmp(udp_buf, "help", 4)) || (0 == memcmp(udp_buf, "?", 1))) { strbuf_t *buf; STRBUF_INIT(buf, &udp_buf); msg_len = snprintf(buf->str, buf->size, "Help for edge management console:\n" "\tstop | Gracefully exit edge\n" "\thelp | This help message\n" "\t+verb | Increase verbosity of logging\n" "\t-verb | Decrease verbosity of logging\n" "\tr ... | start query with JSON reply\n" "\tw ... | start update with JSON reply\n" "\ts ... | subscribe to event channel JSON reply\n" "\t | Display statistics\n\n"); send_reply(&req, buf, msg_len); return; } if(0 == memcmp(udp_buf, "stop", 4)) { traceEvent(TRACE_NORMAL, "stop command received"); *eee->keep_running = 0; return; } if(0 == memcmp(udp_buf, "+verb", 5)) { setTraceLevel(getTraceLevel() + 1); traceEvent(TRACE_NORMAL, "+verb traceLevel=%u", (unsigned int) getTraceLevel()); strbuf_t *buf; STRBUF_INIT(buf, &udp_buf); msg_len = snprintf(buf->str, buf->size, "> +OK traceLevel=%u\n", (unsigned int) getTraceLevel()); send_reply(&req, buf, msg_len); return; } if(0 == memcmp(udp_buf, "-verb", 5)) { strbuf_t *buf; STRBUF_INIT(buf, &udp_buf); if(getTraceLevel() > 0) { setTraceLevel(getTraceLevel() - 1); msg_len = snprintf(buf->str, buf->size, "> -OK traceLevel=%u\n", getTraceLevel()); } else { msg_len = snprintf(buf->str, buf->size, "> -NOK traceLevel=%u\n", getTraceLevel()); } traceEvent(TRACE_NORMAL, "-verb traceLevel=%u", (unsigned int) getTraceLevel()); send_reply(&req, buf, msg_len); return; } if((udp_buf[0] >= 'a' && udp_buf[0] <= 'z') && (udp_buf[1] == ' ')) { /* this is a JSON request */ handleMgmtJson(&req, udp_buf, recvlen); return; } traceEvent(TRACE_DEBUG, "mgmt status requested"); msg_len = 0; msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "COMMUNITY '%s'\n\n", (eee->conf.header_encryption == HEADER_ENCRYPTION_NONE) ? (char*)eee->conf.community_name : "-- header encrypted --"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), " ### | TAP | MAC | EDGE | HINT | LAST SEEN | UPTIME\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "=============================================================================================================\n"); // dump nodes with forwarding through supernodes msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "SUPERNODE FORWARD\n"); num = 0; HASH_ITER(hh, eee->pending_peers, peer, tmpPeer) { ++num_pending_peers; net = htonl(peer->dev_addr.net_addr); snprintf(time_buf, sizeof(time_buf), "%9u", (unsigned int)(now - peer->last_seen)); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "%4u | %-15s | %-17s | %-21s | %-15s | %9s |\n", ++num, (peer->dev_addr.net_addr == 0) ? "" : inet_ntoa(*(struct in_addr *) &net), (is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), peer->dev_desc, (peer->last_seen) ? time_buf : ""); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in)); msg_len = 0; } // dump peer-to-peer nodes msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "-------------------------------------------------------------------------------------------------------------\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "PEER TO PEER\n"); num = 0; HASH_ITER(hh, eee->known_peers, peer, tmpPeer) { ++num_known_peers; net = htonl(peer->dev_addr.net_addr); snprintf(time_buf, sizeof(time_buf), "%9u", (unsigned int)(now - peer->last_seen)); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "%4u | %-15s | %-17s | %-21s | %-15s | %9s |\n", ++num, (peer->dev_addr.net_addr == 0) ? "" : inet_ntoa(*(struct in_addr *) &net), (is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), peer->dev_desc, (peer->last_seen) ? time_buf : ""); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in)); msg_len = 0; } // dump supernodes msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "-------------------------------------------------------------------------------------------------------------\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "SUPERNODES\n"); HASH_ITER(hh, eee->conf.supernodes, peer, tmpPeer) { net = htonl(peer->dev_addr.net_addr); snprintf(time_buf, sizeof(time_buf), "%9u", (unsigned int)(now - peer->last_seen)); snprintf(uptime_buf, sizeof(uptime_buf), "%10u", (unsigned int)(peer->uptime)); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "%-19s %1s%1s | %-17s | %-21s | %-15s | %9s | %10s\n", peer->version, (peer->purgeable == SN_UNPURGEABLE) ? "l" : "", (peer == eee->curr_sn) ? (eee->sn_wait ? "." : "*" ) : "", is_null_mac(peer->mac_addr) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), sn_selection_criterion_str(eee, sel_buf, peer), (peer->last_seen) ? time_buf : "", (peer->uptime) ? uptime_buf : ""); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in)); msg_len = 0; } // further stats msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "=============================================================================================================\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "uptime %lu | ", time(NULL) - eee->start_time); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "pend_peers %u | ", num_pending_peers); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "known_peers %u | ", num_known_peers); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "transop %u,%u\n", (unsigned int) eee->transop.tx_cnt, (unsigned int) eee->transop.rx_cnt); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "super %u,%u | ", (unsigned int) eee->stats.tx_sup, (unsigned int) eee->stats.rx_sup); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "p2p %u,%u\n", (unsigned int) eee->stats.tx_p2p, (unsigned int) eee->stats.rx_p2p); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "last_super %ld sec ago | ", (now - eee->last_sup)); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "last_p2p %ld sec ago\n", (now - eee->last_p2p)); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "\nType \"help\" to see more commands.\n\n"); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in)); } ntop-n2n-90215bd/src/edge_utils.c000066400000000000000000004057661422132035700166150ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #include "network_traffic_filter.h" #include "edge_utils_win32.h" /* ************************************** */ int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn_list); int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, time_t now); int resolve_cancel_thread (n2n_resolve_parameter_t *param); #ifdef HAVE_PORT_FORWARDING int port_map_create_thread (n2n_port_map_parameter_t **param, uint16_t mgmt_port); int port_map_cancel_thread (n2n_port_map_parameter_t *param); #endif static const char * supernode_ip (const n2n_edge_t * eee); static void send_register (n2n_edge_t *eee, const n2n_sock_t *remote_peer, const n2n_mac_t peer_mac, n2n_cookie_t cookie); static void check_peer_registration_needed (n2n_edge_t *eee, uint8_t from_supernode, uint8_t via_multicast, const n2n_mac_t mac, const n2n_cookie_t cookie, const n2n_ip_subnet_t *dev_addr, const n2n_desc_t *dev_desc, const n2n_sock_t *peer); static int edge_init_sockets (n2n_edge_t *eee); int edge_init_routes (n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_routes); static void edge_cleanup_routes (n2n_edge_t *eee); static void check_known_peer_sock_change (n2n_edge_t *eee, uint8_t from_supernode, uint8_t via_multicast, const n2n_mac_t mac, const n2n_ip_subnet_t *dev_addr, const n2n_desc_t *dev_desc, const n2n_sock_t *peer, time_t when); /* ************************************** */ int edge_verify_conf (const n2n_edge_conf_t *conf) { if(conf->community_name[0] == 0) return -1; // REVISIT: are the following two conditions equal? if so, remove one. but note that sn_num is used elsewhere if(conf->sn_num == 0) return -2; if(HASH_COUNT(conf->supernodes) == 0) return -5; if(conf->register_interval < 1) return -3; if(((conf->encrypt_key == NULL) && (conf->transop_id != N2N_TRANSFORM_ID_NULL)) || ((conf->encrypt_key != NULL) && (conf->transop_id == N2N_TRANSFORM_ID_NULL))) return -4; return 0; } /* ************************************** */ void edge_set_callbacks (n2n_edge_t *eee, const n2n_edge_callbacks_t *callbacks) { memcpy(&eee->cb, callbacks, sizeof(n2n_edge_callbacks_t)); } /* ************************************** */ void edge_set_userdata (n2n_edge_t *eee, void *user_data) { eee->user_data = user_data; } /* ************************************** */ void* edge_get_userdata (n2n_edge_t *eee) { return(eee->user_data); } /* ************************************** */ int edge_get_n2n_socket (n2n_edge_t *eee) { return(eee->sock); } /* ************************************** */ int edge_get_management_socket (n2n_edge_t *eee) { return(eee->udp_mgmt_sock); } /* ************************************** */ const char* transop_str (enum n2n_transform tr) { switch(tr) { case N2N_TRANSFORM_ID_NULL: return("null"); case N2N_TRANSFORM_ID_TWOFISH: return("Twofish"); case N2N_TRANSFORM_ID_AES: return("AES"); case N2N_TRANSFORM_ID_CHACHA20:return("ChaCha20"); case N2N_TRANSFORM_ID_SPECK: return("Speck"); default: return("invalid"); }; } /* ************************************** */ const char* compression_str (uint8_t cmpr) { switch(cmpr) { case N2N_COMPRESSION_ID_NONE: return("none"); case N2N_COMPRESSION_ID_LZO: return("lzo1x"); case N2N_COMPRESSION_ID_ZSTD: return("zstd"); default: return("invalid"); }; } /* ************************************** */ /** Destination 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF is multicast ethernet. */ static int is_ethMulticast (const void * buf, size_t bufsize) { int retval = 0; /* Match 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF */ if(bufsize >= sizeof(ether_hdr_t)) { /* copy to aligned memory */ ether_hdr_t eh; memcpy(&eh, buf, sizeof(ether_hdr_t)); if((0x01 == eh.dhost[0]) && (0x00 == eh.dhost[1]) && (0x5E == eh.dhost[2]) && (0 == (0x80 & eh.dhost[3]))) retval = 1; /* This is an ethernet multicast packet [RFC1112]. */ } return retval; } /* ************************************** */ /** Destination MAC 33:33:0:00:00:00 - 33:33:FF:FF:FF:FF is reserved for IPv6 * neighbour discovery. */ static int is_ip6_discovery (const void * buf, size_t bufsize) { int retval = 0; if(bufsize >= sizeof(ether_hdr_t)) { /* copy to aligned memory */ ether_hdr_t eh; memcpy(&eh, buf, sizeof(ether_hdr_t)); if((0x33 == eh.dhost[0]) && (0x33 == eh.dhost[1])) retval = 1; /* This is an IPv6 multicast packet [RFC2464]. */ } return retval; } /* ************************************** */ // reset number of supernode connection attempts: try only once for already more realiable tcp connections void reset_sup_attempts (n2n_edge_t *eee) { eee->sup_attempts = (eee->conf.connect_tcp) ? 1 : N2N_EDGE_SUP_ATTEMPTS; } // detect local IP address by probing a connection to the supernode static int detect_local_ip_address (n2n_sock_t* out_sock, const n2n_edge_t* eee) { struct sockaddr_in local_sock; struct sockaddr_in sn_sock; socklen_t sock_len = sizeof(local_sock); SOCKET probe_sock; int ret = 0; out_sock->family = AF_INVALID; // always detetct local port even/especially if chosen by OS... if((getsockname(eee->sock, (struct sockaddr *)&local_sock, &sock_len) == 0) && (local_sock.sin_family == AF_INET) && (sock_len == sizeof(local_sock))) // remember the port number out_sock->port = ntohs(local_sock.sin_port); else ret = -1; // probe for local IP address probe_sock = socket(PF_INET, SOCK_DGRAM, 0); // connecting the UDP socket makes getsockname read the local address it uses to connect (to the sn in this case); // we cannot do it with the real (eee->sock) socket because socket does not accept any conenction from elsewhere then, // e.g. from another edge instead of the supernode; as re-connecting to AF_UNSPEC might not work to release the socket // on non-UNIXoids, we use a temporary socket if((int)probe_sock >= 0) { fill_sockaddr((struct sockaddr*)&sn_sock, sizeof(sn_sock), &eee->curr_sn->sock); if(connect(probe_sock, (struct sockaddr *)&sn_sock, sizeof(sn_sock)) == 0) { if((getsockname(probe_sock, (struct sockaddr *)&local_sock, &sock_len) == 0) && (local_sock.sin_family == AF_INET) && (sock_len == sizeof(local_sock))) { memcpy(&(out_sock->addr.v4), &(local_sock.sin_addr.s_addr), IPV4_SIZE); } else ret = -4; } else ret = -3; closesocket(probe_sock); } else ret = -2; out_sock->family = AF_INET; return ret; } // open socket, close it before if TCP // in case of TCP, 'connect()' is required int supernode_connect (n2n_edge_t *eee) { int sockopt; struct sockaddr_in sn_sock; n2n_sock_t local_sock; n2n_sock_str_t sockbuf; if((eee->conf.connect_tcp) && (eee->sock >= 0)) { closesocket(eee->sock); eee->sock = -1; } if(eee->sock < 0) { if(eee->conf.local_port > 0) traceEvent(TRACE_NORMAL, "binding to local port %d", (eee->conf.connect_tcp) ? 0 : eee->conf.local_port); eee->sock = open_socket((eee->conf.connect_tcp) ? 0 : eee->conf.local_port, eee->conf.bind_address, eee->conf.connect_tcp); if(eee->sock < 0) { traceEvent(TRACE_ERROR, "failed to bind main UDP port %u", (eee->conf.connect_tcp) ? 0 : eee->conf.local_port); return -1; } fill_sockaddr((struct sockaddr*)&sn_sock, sizeof(sn_sock), &eee->curr_sn->sock); // set tcp socket to O_NONBLOCK so connect does not hang // requires checking the socket for readiness before sending and receving if(eee->conf.connect_tcp) { #ifdef WIN32 u_long value = 1; ioctlsocket(eee->sock, FIONBIO, &value); #else fcntl(eee->sock, F_SETFL, O_NONBLOCK); #endif if((connect(eee->sock, (struct sockaddr*)&(sn_sock), sizeof(struct sockaddr)) < 0) && (errno != EINPROGRESS)) { eee->sock = -1; return -1; } } if(eee->conf.tos) { /* https://www.tucny.com/Home/dscp-tos */ sockopt = eee->conf.tos; if(setsockopt(eee->sock, IPPROTO_IP, IP_TOS, (char *)&sockopt, sizeof(sockopt)) == 0) traceEvent(TRACE_INFO, "TOS set to 0x%x", eee->conf.tos); else traceEvent(TRACE_WARNING, "could not set TOS 0x%x[%d]: %s", eee->conf.tos, errno, strerror(errno)); } #ifdef IP_PMTUDISC_DO sockopt = (eee->conf.disable_pmtu_discovery) ? IP_PMTUDISC_DONT : IP_PMTUDISC_DO; if(setsockopt(eee->sock, IPPROTO_IP, IP_MTU_DISCOVER, &sockopt, sizeof(sockopt)) < 0) traceEvent(TRACE_WARNING, "could not %s PMTU discovery[%d]: %s", (eee->conf.disable_pmtu_discovery) ? "disable" : "enable", errno, strerror(errno)); else traceEvent(TRACE_INFO, "PMTU discovery %s", (eee->conf.disable_pmtu_discovery) ? "disabled" : "enabled"); #endif memset(&local_sock, 0, sizeof(n2n_sock_t)); if(detect_local_ip_address(&local_sock, eee) == 0) { // always overwrite local port even/especially if chosen by OS... eee->conf.preferred_sock.port = local_sock.port; // only if auto-detection mode, ... if(eee->conf.preferred_sock_auto) { // ... overwrite IP address, too (whole socket struct here) memcpy(&eee->conf.preferred_sock, &local_sock, sizeof(n2n_sock_t)); traceEvent(TRACE_INFO, "determined local socket [%s]", sock_to_cstr(sockbuf, &local_sock)); } } if(eee->cb.sock_opened) eee->cb.sock_opened(eee); } #ifdef HAVE_PORT_FORWARDING if(eee->conf.port_forwarding) // REVISIT: replace with mgmt port notification to listener for mgmt port // subscription support n2n_chg_port_mapping(eee, eee->conf.preferred_sock.port); #endif // HAVE_PORT_FORWARDING return 0; } // always closes the socket void supernode_disconnect (n2n_edge_t *eee) { if(eee->sock >= 0) { closesocket(eee->sock); eee->sock = -1; } } /* ************************************** */ /** Initialise an edge to defaults. * * This also initialises the NULL transform operation opstruct. */ n2n_edge_t* edge_init (const n2n_edge_conf_t *conf, int *rv) { n2n_transform_t transop_id = conf->transop_id; n2n_edge_t *eee = calloc(1, sizeof(n2n_edge_t)); int rc = -1, i = 0; struct peer_info *scan, *tmp; uint8_t tmp_key[N2N_AUTH_CHALLENGE_SIZE]; if((rc = edge_verify_conf(conf)) != 0) { traceEvent(TRACE_ERROR, "invalid configuration"); goto edge_init_error; } if(!eee) { traceEvent(TRACE_ERROR, "cannot allocate memory"); goto edge_init_error; } memcpy(&eee->conf, conf, sizeof(*conf)); eee->curr_sn = eee->conf.supernodes; eee->start_time = time(NULL); eee->known_peers = NULL; eee->pending_peers = NULL; reset_sup_attempts(eee); sn_selection_criterion_common_data_default(eee); pearson_hash_init(); // always initialize compression transforms so we can at least decompress rc = n2n_transop_lzo_init(&eee->conf, &eee->transop_lzo); if(rc) goto edge_init_error; /* error message is printed in lzo_init */ #ifdef HAVE_ZSTD rc = n2n_transop_zstd_init(&eee->conf, &eee->transop_zstd); if(rc) goto edge_init_error; /* error message is printed in zstd_init */ #endif traceEvent(TRACE_NORMAL, "number of supernodes in the list: %d\n", HASH_COUNT(eee->conf.supernodes)); HASH_ITER(hh, eee->conf.supernodes, scan, tmp) { traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (scan->ip_addr)); i++; } /* Set active transop */ switch(transop_id) { case N2N_TRANSFORM_ID_TWOFISH: rc = n2n_transop_tf_init(&eee->conf, &eee->transop); break; case N2N_TRANSFORM_ID_AES: rc = n2n_transop_aes_init(&eee->conf, &eee->transop); break; case N2N_TRANSFORM_ID_CHACHA20: rc = n2n_transop_cc20_init(&eee->conf, &eee->transop); break; case N2N_TRANSFORM_ID_SPECK: rc = n2n_transop_speck_init(&eee->conf, &eee->transop); break; default: rc = n2n_transop_null_init(&eee->conf, &eee->transop); } if((rc < 0) || (eee->transop.fwd == NULL) || (eee->transop.transform_id != transop_id)) { traceEvent(TRACE_ERROR, "transop init failed"); goto edge_init_error; } // set the key schedule (context) for header encryption if enabled if(conf->header_encryption == HEADER_ENCRYPTION_ENABLED) { traceEvent(TRACE_NORMAL, "Header encryption is enabled."); packet_header_setup_key((char *)(eee->conf.community_name), &(eee->conf.header_encryption_ctx_static), &(eee->conf.header_encryption_ctx_dynamic), &(eee->conf.header_iv_ctx_static), &(eee->conf.header_iv_ctx_dynamic)); // in case of user/password auth, initialize a random dynamic key to prevent // unintentional communication with only-header-encrypted community; will be // overwritten by legit key later if(conf->shared_secret) { memrnd(tmp_key, N2N_AUTH_CHALLENGE_SIZE); packet_header_change_dynamic_key(tmp_key, &(eee->conf.header_encryption_ctx_dynamic), &(eee->conf.header_iv_ctx_dynamic)); } } // setup authentication scheme if(!conf->shared_secret) { // id-based scheme eee->conf.auth.scheme = n2n_auth_simple_id; // random authentication token memrnd(eee->conf.auth.token, N2N_AUTH_ID_TOKEN_SIZE); eee->conf.auth.token_size = N2N_AUTH_ID_TOKEN_SIZE; } else { // user-password scheme eee->conf.auth.scheme = n2n_auth_user_password; // 'token' stores public key and the last random challenge being set upon sending REGISTER_SUPER memcpy(eee->conf.auth.token, eee->conf.public_key, N2N_PRIVATE_PUBLIC_KEY_SIZE); // random part of token (challenge) will be generated and filled in at each REGISTER_SUPER eee->conf.auth.token_size = N2N_AUTH_PW_TOKEN_SIZE; // make sure that only stream ciphers are being used if((transop_id != N2N_TRANSFORM_ID_CHACHA20) && (transop_id != N2N_TRANSFORM_ID_SPECK)) { traceEvent(TRACE_ERROR, "user-password authentication requires ChaCha20 (-A4) or SPECK (-A5) to be used."); goto edge_init_error; } } if(eee->transop.no_encryption) traceEvent(TRACE_WARNING, "encryption is disabled in edge"); // first time calling edge_init_sockets needs -1 in the sockets for it does throw an error // on trying to close them (open_sockets does so for also being able to RE-open the sockets // if called in-between, see "Supernode not responding" in update_supernode_reg(...) eee->sock = -1; eee->udp_mgmt_sock = -1; #ifndef SKIP_MULTICAST_PEERS_DISCOVERY eee->udp_multicast_sock = -1; #endif if(edge_init_sockets(eee) < 0) { traceEvent(TRACE_ERROR, "socket setup failed"); goto edge_init_error; } if(resolve_create_thread(&(eee->resolve_parameter), eee->conf.supernodes) == 0) { traceEvent(TRACE_NORMAL, "successfully created resolver thread"); } #ifdef HAVE_PORT_FORWARDING if(eee->conf.port_forwarding) if(port_map_create_thread(&eee->port_map_parameter, eee->conf.mgmt_port) == 0) { traceEvent(TRACE_NORMAL, "successfully created port mapping thread"); } #endif // HAVE_MINIUPNP || HAVE_NATPMP eee->network_traffic_filter = create_network_traffic_filter(); network_traffic_filter_add_rule(eee->network_traffic_filter, eee->conf.network_traffic_filter_rules); //edge_init_success: *rv = 0; return(eee); edge_init_error: if(eee) free(eee); *rv = rc; return(NULL); } /* ************************************** */ static int find_and_remove_peer (struct peer_info **head, const n2n_mac_t mac) { struct peer_info *peer; HASH_FIND_PEER(*head, mac, peer); if(peer) { HASH_DEL(*head, peer); free(peer); return(1); } return(0); } /* ************************************** */ static uint32_t localhost_v4 = 0x7f000001; static uint8_t localhost_v6[IPV6_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; /* Exclude localhost as it may be received when an edge node runs * in the same supernode host. */ static int is_valid_peer_sock (const n2n_sock_t *sock) { switch(sock->family) { case AF_INET: { uint32_t *a = (uint32_t*)sock->addr.v4; if(*a != htonl(localhost_v4)) return(1); } break; case AF_INET6: if(memcmp(sock->addr.v6, localhost_v6, IPV6_SIZE)) return(1); break; } return(0); } /* ***************************************************** */ /*** * * For a given packet, find the apporopriate internal last valid time stamp for lookup * and verify it (and also update, if applicable). */ static int find_peer_time_stamp_and_verify (n2n_edge_t * eee, peer_info_t *sn, const n2n_mac_t mac, uint64_t stamp, int allow_jitter) { uint64_t *previous_stamp = NULL; if(sn) { // from supernode previous_stamp = &(sn->last_valid_time_stamp); } else { // from (peer) edge struct peer_info *peer; HASH_FIND_PEER(eee->pending_peers, mac, peer); if(!peer) { HASH_FIND_PEER(eee->known_peers, mac, peer); } if(peer) { // time_stamp_verify_and_update allows the pointer a previous stamp to be NULL // if it is a (so far) unknown peer previous_stamp = &(peer->last_valid_time_stamp); } } // failure --> 0; success --> 1 return time_stamp_verify_and_update(stamp, previous_stamp, allow_jitter); } /* ************************************** */ /*** * * Register over multicast in case there is a peer on the same network listening */ static void register_with_local_peers (n2n_edge_t * eee) { #ifndef SKIP_MULTICAST_PEERS_DISCOVERY if((eee->multicast_joined && eee->conf.allow_p2p) && (eee->conf.preferred_sock.family == (uint8_t)AF_INVALID)) { /* send registration to the local multicast group */ traceEvent(TRACE_DEBUG, "registering with multicast group %s:%u", N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT); send_register(eee, &(eee->multicast_peer), NULL, N2N_MCAST_REG_COOKIE); } #else traceEvent(TRACE_DEBUG, "multicast peers discovery is disabled, skipping"); #endif } /* ************************************** */ static struct peer_info* find_peer_by_sock (const n2n_sock_t *sock, struct peer_info *peer_list) { struct peer_info *scan, *tmp, *ret = NULL; HASH_ITER(hh, peer_list, scan, tmp) { if(memcmp(&(scan->sock), sock, sizeof(n2n_sock_t)) == 0) { ret = scan; break; } } return ret; } /* ************************************** */ /** Start the registration process. * * If the peer is already in pending_peers, ignore the request. * If not in pending_peers, add it and send a REGISTER. * * If hdr is for a direct peer-to-peer packet, try to register back to sender * even if the MAC is in pending_peers. This is because an incident direct * packet indicates that peer-to-peer exchange should work so more aggressive * registration can be permitted (once per incoming packet) as this should only * last for a small number of packets.. * * Called from the main loop when Rx a packet for our device mac. */ static void register_with_new_peer (n2n_edge_t *eee, uint8_t from_supernode, uint8_t via_multicast, const n2n_mac_t mac, const n2n_ip_subnet_t *dev_addr, const n2n_desc_t *dev_desc, const n2n_sock_t *peer) { /* REVISIT: purge of pending_peers not yet done. */ struct peer_info *scan; macstr_t mac_buf; n2n_sock_str_t sockbuf; HASH_FIND_PEER(eee->pending_peers, mac, scan); /* NOTE: pending_peers are purged periodically with purge_expired_nodes */ if(scan == NULL) { scan = calloc(1, sizeof(struct peer_info)); memcpy(scan->mac_addr, mac, N2N_MAC_SIZE); scan->sock = *peer; scan->timeout = eee->conf.register_interval; /* TODO: should correspond to the peer supernode registration timeout */ scan->last_valid_time_stamp = initial_time_stamp(); if(via_multicast) scan->local = 1; HASH_ADD_PEER(eee->pending_peers, scan); traceEvent(TRACE_DEBUG, "new pending peer %s [%s]", macaddr_str(mac_buf, scan->mac_addr), sock_to_cstr(sockbuf, &(scan->sock))); traceEvent(TRACE_DEBUG, "pending peers list size=%u", HASH_COUNT(eee->pending_peers)); /* trace Sending REGISTER */ if(from_supernode) { /* UDP NAT hole punching through supernode. Send to peer first(punch local UDP hole) * and then ask supernode to forward. Supernode then ask peer to ack. Some nat device * drop and block ports with incoming UDP packet if out-come traffic does not exist. * So we can alternatively set TTL so that the packet sent to peer never really reaches * The register_ttl is basically nat level + 1. Set it to 1 means host like DMZ. */ if(eee->conf.register_ttl == 1) { /* We are DMZ host or port is directly accessible. Just let peer to send back the ack */ #ifndef WIN32 } else if(eee->conf.register_ttl > 1) { /* Setting register_ttl usually implies that the edge knows the internal net topology * clearly, we can apply aggressive port prediction to support incoming Symmetric NAT */ int curTTL = 0; socklen_t lenTTL = sizeof(int); n2n_sock_t sock = scan->sock; int alter = 16; /* TODO: set by command line or more reliable prediction method */ getsockopt(eee->sock, IPPROTO_IP, IP_TTL, (void *) (char *) &curTTL, &lenTTL); setsockopt(eee->sock, IPPROTO_IP, IP_TTL, (void *) (char *) &eee->conf.register_ttl, sizeof(eee->conf.register_ttl)); for(; alter > 0; alter--, sock.port++) { send_register(eee, &sock, mac, N2N_PORT_REG_COOKIE); } setsockopt(eee->sock, IPPROTO_IP, IP_TTL, (void *) (char *) &curTTL, sizeof(curTTL)); #endif } else { /* eee->conf.register_ttl <= 0 */ /* Normal STUN */ send_register(eee, &(scan->sock), mac, N2N_REGULAR_REG_COOKIE); } send_register(eee, &(eee->curr_sn->sock), mac, N2N_FORWARDED_REG_COOKIE); } else { /* P2P register, send directly */ send_register(eee, &(scan->sock), mac, N2N_REGULAR_REG_COOKIE); } register_with_local_peers(eee); } else{ scan->sock = *peer; } scan->last_seen = time(NULL); if(dev_addr != NULL) { memcpy(&(scan->dev_addr), dev_addr, sizeof(n2n_ip_subnet_t)); } if(dev_desc) memcpy(scan->dev_desc, dev_desc, N2N_DESC_SIZE); } /* ************************************** */ /** Update the last_seen time for this peer, or get registered. */ static void check_peer_registration_needed (n2n_edge_t *eee, uint8_t from_supernode, uint8_t via_multicast, const n2n_mac_t mac, const n2n_cookie_t cookie, const n2n_ip_subnet_t *dev_addr, const n2n_desc_t *dev_desc, const n2n_sock_t *peer) { struct peer_info *scan; HASH_FIND_PEER(eee->known_peers, mac, scan); /* If we were not able to find it by MAC, we try to find it by socket. */ if(scan == NULL ) { scan = find_peer_by_sock(peer, eee->known_peers); // MAC change if(scan) { HASH_DEL(eee->known_peers, scan); memcpy(scan->mac_addr, mac, sizeof(n2n_mac_t)); HASH_ADD_PEER(eee->known_peers, scan); // reset last_local_reg to allow re-registration scan->last_cookie = N2N_NO_REG_COOKIE; } } if(scan == NULL) { /* Not in known_peers - start the REGISTER process. */ register_with_new_peer(eee, from_supernode, via_multicast, mac, dev_addr, dev_desc, peer); } else { /* Already in known_peers. */ time_t now = time(NULL); if(!from_supernode) scan->last_p2p = now; if(via_multicast) scan->local = 1; if(((now - scan->last_seen) > 0 /* >= 1 sec */) ||(cookie > scan->last_cookie)) { /* Don't register too often */ check_known_peer_sock_change(eee, from_supernode, via_multicast, mac, dev_addr, dev_desc, peer, now); } } } /* ************************************** */ /* Confirm that a pending peer is reachable directly via P2P. * * peer must be a pointer to an element of the pending_peers list. */ static void peer_set_p2p_confirmed (n2n_edge_t * eee, const n2n_mac_t mac, const n2n_cookie_t cookie, const n2n_sock_t * peer, time_t now) { struct peer_info *scan, *scan_tmp; macstr_t mac_buf; n2n_sock_str_t sockbuf; HASH_FIND_PEER(eee->pending_peers, mac, scan); if(scan == NULL) { scan = find_peer_by_sock(peer, eee->pending_peers); // in case of MAC change, reset last_local_reg to allow re-registration if(scan) scan->last_cookie = N2N_NO_REG_COOKIE; } if(scan) { HASH_DEL(eee->pending_peers, scan); scan_tmp = find_peer_by_sock(peer, eee->known_peers); if(scan_tmp != NULL) { HASH_DEL(eee->known_peers, scan_tmp); mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_DEL_P2P,scan); free(scan); scan = scan_tmp; memcpy(scan->mac_addr, mac, sizeof(n2n_mac_t)); // in case of MAC change, reset cookie to allow immediate re-registration scan->last_cookie = N2N_NO_REG_COOKIE; } else { // update sock but ... // ... ignore ACKs's (and their socks) from lower ranked inbound ways for a while if(((now - scan->last_seen) > REGISTRATION_TIMEOUT / 4) ||(cookie > scan->last_cookie)) { scan->sock = *peer; scan->last_cookie = cookie; } } HASH_ADD_PEER(eee->known_peers, scan); scan->last_p2p = now; mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_ADD_P2P,scan); traceEvent(TRACE_DEBUG, "p2p connection established: %s [%s]", macaddr_str(mac_buf, mac), sock_to_cstr(sockbuf, peer)); traceEvent(TRACE_DEBUG, "new peer %s [%s]", macaddr_str(mac_buf, scan->mac_addr), sock_to_cstr(sockbuf, &(scan->sock))); traceEvent(TRACE_DEBUG, "pending peers list size=%u", HASH_COUNT(eee->pending_peers)); traceEvent(TRACE_DEBUG, "known peers list size=%u", HASH_COUNT(eee->known_peers)); scan->last_seen = now; } else traceEvent(TRACE_DEBUG, "failed to find sender in pending_peers"); } /* ************************************** */ // provides the current / a new local auth token static int get_local_auth (n2n_edge_t *eee, n2n_auth_t *auth) { switch(eee->conf.auth.scheme) { case n2n_auth_simple_id: memcpy(auth, &(eee->conf.auth), sizeof(n2n_auth_t)); break; case n2n_auth_user_password: // start from the locally stored complete auth token (including type and size fields) memcpy(auth, &(eee->conf.auth), sizeof(n2n_auth_t)); // the token data consists of // 32 bytes public key // 16 bytes random challenge // generate a new random auth challenge every time memrnd(auth->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, N2N_AUTH_CHALLENGE_SIZE); // store it in local auth token (for comparison later) memcpy(eee->conf.auth.token + N2N_PRIVATE_PUBLIC_KEY_SIZE, auth->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, N2N_AUTH_CHALLENGE_SIZE); // encrypt the challenge for transmission speck_128_encrypt(auth->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, (speck_context_t*)eee->conf.shared_secret_ctx); break; default: break; } return 0; } // handles a returning (remote) auth token, takes action as required by auth scheme static int handle_remote_auth (n2n_edge_t *eee, struct peer_info *peer, const n2n_auth_t *remote_auth) { uint8_t tmp_token[N2N_AUTH_MAX_TOKEN_SIZE]; switch(eee->conf.auth.scheme) { case n2n_auth_simple_id: // no action required break; case n2n_auth_user_password: memcpy(tmp_token, remote_auth->token, N2N_AUTH_PW_TOKEN_SIZE); // the returning token data consists of // 16 bytes double-encrypted challenge // 16 bytes public key (second half) // 16 bytes encrypted (original random challenge XOR shared secret XOR dynamic key) // decrypt double-encrypted received challenge (first half of public key field) speck_128_decrypt(tmp_token, (speck_context_t*)eee->conf.shared_secret_ctx); speck_128_decrypt(tmp_token, (speck_context_t*)eee->conf.shared_secret_ctx); // compare to original challenge if(0 != memcmp(tmp_token, eee->conf.auth.token + N2N_PRIVATE_PUBLIC_KEY_SIZE, N2N_AUTH_CHALLENGE_SIZE)) return -1; // decrypt the received challenge in which the dynamic key is wrapped speck_128_decrypt(tmp_token + N2N_PRIVATE_PUBLIC_KEY_SIZE, (speck_context_t*)eee->conf.shared_secret_ctx); // un-XOR the original challenge memxor(tmp_token + N2N_PRIVATE_PUBLIC_KEY_SIZE, eee->conf.auth.token + N2N_PRIVATE_PUBLIC_KEY_SIZE, N2N_AUTH_CHALLENGE_SIZE); // un-XOR the shared secret memxor(tmp_token + N2N_PRIVATE_PUBLIC_KEY_SIZE, *(eee->conf.shared_secret), N2N_AUTH_CHALLENGE_SIZE); // setup for use as dynamic key packet_header_change_dynamic_key(tmp_token + N2N_PRIVATE_PUBLIC_KEY_SIZE, &(eee->conf.header_encryption_ctx_dynamic), &(eee->conf.header_iv_ctx_dynamic)); break; default: break; } return 0; } /* ************************************** */ int is_empty_ip_address (const n2n_sock_t * sock) { const uint8_t * ptr = NULL; size_t len = 0; size_t i; if(AF_INET6 == sock->family) { ptr = sock->addr.v6; len = 16; } else { ptr = sock->addr.v4; len = 4; } for(i = 0; i < len; ++i) { if(0 != ptr[i]) { /* found a non-zero byte in address */ return 0; } } return 1; } /* ************************************** */ /** Check if a known peer socket has changed and possibly register again. */ static void check_known_peer_sock_change (n2n_edge_t *eee, uint8_t from_supernode, uint8_t via_multicast, const n2n_mac_t mac, const n2n_ip_subnet_t *dev_addr, const n2n_desc_t *dev_desc, const n2n_sock_t *peer, time_t when) { struct peer_info *scan; n2n_sock_str_t sockbuf1; n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ macstr_t mac_buf; if(is_empty_ip_address(peer)) return; if(is_multi_broadcast(mac)) return; /* Search the peer in known_peers */ HASH_FIND_PEER(eee->known_peers, mac, scan); if(!scan) /* Not in known_peers */ return; if(!sock_equal(&(scan->sock), peer)) { if(!from_supernode) { /* This is a P2P packet */ traceEvent(TRACE_NORMAL, "peer %s changed [%s] -> [%s]", macaddr_str(mac_buf, scan->mac_addr), sock_to_cstr(sockbuf1, &(scan->sock)), sock_to_cstr(sockbuf2, peer)); /* The peer has changed public socket. It can no longer be assumed to be reachable. */ HASH_DEL(eee->known_peers, scan); mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_DEL_P2P,scan); free(scan); register_with_new_peer(eee, from_supernode, via_multicast, mac, dev_addr, dev_desc, peer); } else { /* Don't worry about what the supernode reports, it could be seeing a different socket. */ } } else scan->last_seen = when; } /* ************************************** */ /** Send a datagram to a socket file descriptor */ static ssize_t sendto_fd (n2n_edge_t *eee, const void *buf, size_t len, struct sockaddr_in *dest) { ssize_t sent = 0; int rc = 1; // if required (tcp), wait until writeable as soket is set to O_NONBLOCK, could require // some wait time directly after re-opening if(eee->conf.connect_tcp) { fd_set socket_mask; struct timeval wait_time; FD_ZERO(&socket_mask); FD_SET(eee->sock, &socket_mask); wait_time.tv_sec = 0; wait_time.tv_usec = 500000; rc = select(eee->sock + 1, NULL, &socket_mask, NULL, &wait_time); } if(rc > 0) { sent = sendto(eee->sock, buf, len, 0 /*flags*/, (struct sockaddr *)dest, sizeof(struct sockaddr_in)); if((sent <= 0) && (errno)) { char * c = strerror(errno); // downgrade to TRACE_DEBUG in case of custom AF_INVALID, i.e. supernode not resolved yet if(errno == EAFNOSUPPORT /* 93 */) { traceEvent(TRACE_DEBUG, "sendto failed (%d) %s", errno, c); #ifdef WIN32 traceEvent(TRACE_DEBUG, "WSAGetLastError(): %u", WSAGetLastError()); #endif } else { traceEvent(TRACE_WARNING, "sendto failed (%d) %s", errno, c); #ifdef WIN32 traceEvent(TRACE_WARNING, "WSAGetLastError(): %u", WSAGetLastError()); #endif } if(eee->conf.connect_tcp) { supernode_disconnect(eee); eee->sn_wait = 1; traceEvent(TRACE_DEBUG, "disconnected supernode due to sendto() error"); return -1; } } else { traceEvent(TRACE_DEBUG, "sent=%d to ", (signed int)sent); } } else { supernode_disconnect(eee); eee->sn_wait = 1; traceEvent(TRACE_DEBUG, "disconnected supernode due to select() timeout"); return -1; } return sent; } /** Send a datagram to a socket defined by a n2n_sock_t */ static ssize_t sendto_sock (n2n_edge_t *eee, const void * buf, size_t len, const n2n_sock_t * dest) { struct sockaddr_in peer_addr; ssize_t sent; int value = 0; if(!dest->family) // invalid socket return 0; if(eee->sock < 0) // invalid socket file descriptor, e.g. TCP unconnected has fd of '-1' return 0; // network order socket fill_sockaddr((struct sockaddr *) &peer_addr, sizeof(peer_addr), dest); // if the connection is tcp, i.e. not the regular sock... if(eee->conf.connect_tcp) { setsockopt(eee->sock, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value)); value = 1; #ifdef LINUX setsockopt(eee->sock, IPPROTO_TCP, TCP_CORK, &value, sizeof(value)); #endif // prepend packet length... uint16_t pktsize16 = htobe16(len); sent = sendto_fd(eee, (uint8_t*)&pktsize16, sizeof(pktsize16), &peer_addr); if(sent <= 0) return -1; // ...before sending the actual data } sent = sendto_fd(eee, buf, len, &peer_addr); // if the connection is tcp, i.e. not the regular sock... if(eee->conf.connect_tcp) { value = 1; /* value should still be set to 1 */ setsockopt(eee->sock, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value)); #ifdef LINUX value = 0; setsockopt(eee->sock, IPPROTO_TCP, TCP_CORK, &value, sizeof(value)); #endif } return sent; } /* ************************************** */ /* Bind eee->udp_multicast_sock to multicast group */ static void check_join_multicast_group (n2n_edge_t *eee) { #ifndef SKIP_MULTICAST_PEERS_DISCOVERY if((eee->conf.allow_p2p) && (eee->conf.preferred_sock.family == (uint8_t)AF_INVALID)) { if(!eee->multicast_joined) { struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr(N2N_MULTICAST_GROUP); #ifdef WIN32 dec_ip_str_t ip_addr; get_best_interface_ip(eee, ip_addr); mreq.imr_interface.s_addr = inet_addr(ip_addr); #else mreq.imr_interface.s_addr = htonl(INADDR_ANY); #endif if(setsockopt(eee->udp_multicast_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0) { traceEvent(TRACE_WARNING, "failed to bind to local multicast group %s:%u [errno %u]", N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT, errno); #ifdef WIN32 traceEvent(TRACE_WARNING, "WSAGetLastError(): %u", WSAGetLastError()); #endif } else { traceEvent(TRACE_NORMAL, "successfully joined multicast group %s:%u", N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT); eee->multicast_joined = 1; } } } #endif } /* ************************************** */ /** Send a QUERY_PEER packet to the current supernode. */ void send_query_peer (n2n_edge_t * eee, const n2n_mac_t dst_mac) { uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx; n2n_common_t cmn = {0}; n2n_QUERY_PEER_t query = {0}; struct peer_info *peer, *tmp; int n_o_pings = 0; int n_o_top_sn = 0; int n_o_rest_sn = 0; int n_o_skip_sn = 0; cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_query_peer; cmn.flags = 0; memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); idx = 0; encode_mac(query.srcMac, &idx, eee->device.mac_addr); idx = 0; encode_mac(query.targetMac, &idx, dst_mac); idx = 0; encode_QUERY_PEER(pktbuf, &idx, &cmn, &query); if(!is_null_mac(dst_mac)) { traceEvent(TRACE_DEBUG, "send QUERY_PEER to supernode"); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(pktbuf, idx, idx, eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic, time_stamp()); } sendto_sock(eee, pktbuf, idx, &(eee->curr_sn->sock)); } else { traceEvent(TRACE_DEBUG, "send PING to supernodes"); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(pktbuf, idx, idx, eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic, time_stamp()); } n_o_pings = eee->conf.number_max_sn_pings; eee->conf.number_max_sn_pings = NUMBER_SN_PINGS_REGULAR; // ping the 'floor(n/2)' top supernodes and 'ceiling(n/2)' of the remaining n_o_top_sn = n_o_pings >> 1; n_o_rest_sn = (n_o_pings + 1) >> 1; // skip a random number of supernodes between top and remaining n_o_skip_sn = HASH_COUNT(eee->conf.supernodes) - n_o_pings; n_o_skip_sn = (n_o_skip_sn < 0) ? 0 : n2n_rand_sqr(n_o_skip_sn); HASH_ITER(hh, eee->conf.supernodes, peer, tmp) { if(n_o_top_sn) { n_o_top_sn--; // fall through (send to top supernode) } else if(n_o_skip_sn) { n_o_skip_sn--; // skip (do not send) continue; } else if(n_o_rest_sn) { n_o_rest_sn--; // fall through (send to remaining supernode) } else { // done with the remaining (do not send anymore) break; } sendto_sock(eee, pktbuf, idx, &(peer->sock)); } } } /* ******************************************************** */ /** Send a REGISTER_SUPER packet to the current supernode. */ void send_register_super (n2n_edge_t *eee) { uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; uint8_t hash_buf[16] = {0}; size_t idx; /* ssize_t sent; */ n2n_common_t cmn; n2n_REGISTER_SUPER_t reg; n2n_sock_str_t sockbuf; memset(&cmn, 0, sizeof(cmn)); memset(®, 0, sizeof(reg)); cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_register_super; if(eee->conf.preferred_sock.family == (uint8_t)AF_INVALID) { cmn.flags = 0; } else { cmn.flags = N2N_FLAGS_SOCKET; memcpy(&(reg.sock), &(eee->conf.preferred_sock), sizeof(n2n_sock_t)); } memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); eee->curr_sn->last_cookie = n2n_rand(); reg.cookie = eee->curr_sn->last_cookie; reg.dev_addr.net_addr = ntohl(eee->device.ip_addr); reg.dev_addr.net_bitlen = mask2bitlen(ntohl(eee->device.device_mask)); memcpy(reg.dev_desc, eee->conf.dev_desc, N2N_DESC_SIZE); get_local_auth(eee, &(reg.auth)); idx = 0; encode_mac(reg.edgeMac, &idx, eee->device.mac_addr); idx = 0; encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®); traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to [%s]", sock_to_cstr(sockbuf, &(eee->curr_sn->sock))); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(pktbuf, idx, idx, eee->conf.header_encryption_ctx_static, eee->conf.header_iv_ctx_static, time_stamp()); if(eee->conf.shared_secret) { pearson_hash_128(hash_buf, pktbuf, idx); speck_128_encrypt(hash_buf, (speck_context_t*)eee->conf.shared_secret_ctx); encode_buf(pktbuf, &idx, hash_buf, N2N_REG_SUP_HASH_CHECK_LEN); } } /* sent = */ sendto_sock(eee, pktbuf, idx, &(eee->curr_sn->sock)); } static void send_unregister_super (n2n_edge_t *eee) { uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; size_t idx; /* ssize_t sent; */ n2n_common_t cmn; n2n_UNREGISTER_SUPER_t unreg; n2n_sock_str_t sockbuf; memset(&cmn, 0, sizeof(cmn)); memset(&unreg, 0, sizeof(unreg)); cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_unregister_super; cmn.flags = 0; memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); get_local_auth(eee, &(unreg.auth)); idx = 0; encode_mac(unreg.srcMac, &idx, eee->device.mac_addr); idx = 0; encode_UNREGISTER_SUPER(pktbuf, &idx, &cmn, &unreg); traceEvent(TRACE_DEBUG, "send UNREGISTER_SUPER to [%s]", sock_to_cstr(sockbuf, &(eee->curr_sn->sock))); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt(pktbuf, idx, idx, eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic, time_stamp()); /* sent = */ sendto_sock(eee, pktbuf, idx, &(eee->curr_sn->sock)); } static int sort_supernodes (n2n_edge_t *eee, time_t now) { struct peer_info *scan, *tmp; if(now - eee->last_sweep > SWEEP_TIME) { // this routine gets periodically called if(!eee->sn_wait) { // sort supernodes in ascending order of their selection_criterion fields sn_selection_sort(&(eee->conf.supernodes)); } if(eee->curr_sn != eee->conf.supernodes) { // we have not been connected to the best/top one send_unregister_super(eee); eee->curr_sn = eee->conf.supernodes; reset_sup_attempts(eee); supernode_connect(eee); traceEvent(TRACE_INFO, "registering with supernode [%s][number of supernodes %d][attempts left %u]", supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigned int)eee->sup_attempts); send_register_super(eee); eee->last_register_req = now; eee->sn_wait = 1; } HASH_ITER(hh, eee->conf.supernodes, scan, tmp) { if(scan == eee->curr_sn) sn_selection_criterion_good(&(scan->selection_criterion)); else sn_selection_criterion_default(&(scan->selection_criterion)); } sn_selection_criterion_common_data_default(eee); // send PING to all the supernodes if(!eee->conf.connect_tcp) send_query_peer(eee, null_mac); eee->last_sweep = now; // no answer yet (so far, unused in regular edge code; mainly used during bootstrap loading) eee->sn_pong = 0; } return 0; /* OK */ } /** Send a REGISTER packet to another edge. */ static void send_register (n2n_edge_t * eee, const n2n_sock_t * remote_peer, const n2n_mac_t peer_mac, const n2n_cookie_t cookie) { uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx; /* ssize_t sent; */ n2n_common_t cmn; n2n_REGISTER_t reg; n2n_sock_str_t sockbuf; if(!eee->conf.allow_p2p) { traceEvent(TRACE_DEBUG, "skipping register as P2P is disabled"); return; } memset(&cmn, 0, sizeof(cmn)); memset(®, 0, sizeof(reg)); cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_register; cmn.flags = 0; memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); reg.cookie = cookie; idx = 0; encode_mac(reg.srcMac, &idx, eee->device.mac_addr); if(peer_mac) { // can be NULL for multicast registrations idx = 0; encode_mac(reg.dstMac, &idx, peer_mac); } reg.dev_addr.net_addr = ntohl(eee->device.ip_addr); reg.dev_addr.net_bitlen = mask2bitlen(ntohl(eee->device.device_mask)); memcpy(reg.dev_desc, eee->conf.dev_desc, N2N_DESC_SIZE); idx = 0; encode_REGISTER(pktbuf, &idx, &cmn, ®); traceEvent(TRACE_INFO, "send REGISTER to [%s]", sock_to_cstr(sockbuf, remote_peer)); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt(pktbuf, idx, idx, eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic, time_stamp()); /* sent = */ sendto_sock(eee, pktbuf, idx, remote_peer); } /* ************************************** */ /** Send a REGISTER_ACK packet to a peer edge. */ static void send_register_ack (n2n_edge_t * eee, const n2n_sock_t * remote_peer, const n2n_REGISTER_t * reg) { uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx; /* ssize_t sent; */ n2n_common_t cmn; n2n_REGISTER_ACK_t ack; n2n_sock_str_t sockbuf; if(!eee->conf.allow_p2p) { traceEvent(TRACE_DEBUG, "skipping register ACK as P2P is disabled"); return; } memset(&cmn, 0, sizeof(cmn)); memset(&ack, 0, sizeof(reg)); cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_register_ack; cmn.flags = 0; memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); memset(&ack, 0, sizeof(ack)); ack.cookie = reg->cookie; memcpy(ack.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); memcpy(ack.dstMac, reg->srcMac, N2N_MAC_SIZE); idx = 0; encode_REGISTER_ACK(pktbuf, &idx, &cmn, &ack); traceEvent(TRACE_INFO, "send REGISTER_ACK to [%s]", sock_to_cstr(sockbuf, remote_peer)); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt(pktbuf, idx, idx, eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic, time_stamp()); /* sent = */ sendto_sock(eee, pktbuf, idx, remote_peer); } /* ************************************** */ static char gratuitous_arp[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* dest MAC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* src MAC */ 0x08, 0x06, /* ARP */ 0x00, 0x01, /* ethernet */ 0x08, 0x00, /* IP */ 0x06, /* hw Size */ 0x04, /* protocol Size */ 0x00, 0x02, /* ARP reply */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* src MAC */ 0x00, 0x00, 0x00, 0x00, /* src IP */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* target MAC */ 0x00, 0x00, 0x00, 0x00 /* target IP */ }; // build a gratuitous ARP packet */ static int build_gratuitous_arp (n2n_edge_t * eee, char *buffer, uint16_t buffer_len) { if(buffer_len < sizeof(gratuitous_arp)) return(-1); memcpy(buffer, gratuitous_arp, sizeof(gratuitous_arp)); memcpy(&buffer[6], eee->device.mac_addr, 6); memcpy(&buffer[22], eee->device.mac_addr, 6); memcpy(&buffer[28], &(eee->device.ip_addr), 4); memcpy(&buffer[38], &(eee->device.ip_addr), 4); return(sizeof(gratuitous_arp)); } /** Called from update_supernode_reg to periodically send gratuitous ARP * broadcasts. */ static void send_grat_arps (n2n_edge_t * eee) { uint8_t buffer[48]; size_t len; traceEvent(TRACE_DEBUG, "sending gratuitous ARP..."); len = build_gratuitous_arp(eee, (char*)buffer, sizeof(buffer)); edge_send_packet2net(eee, buffer, len); edge_send_packet2net(eee, buffer, len); /* Two is better than one :-) */ } /* ************************************** */ /** @brief Check to see if we should re-register with the supernode. * * This is frequently called by the main loop. */ void update_supernode_reg (n2n_edge_t * eee, time_t now) { struct peer_info *peer, *tmp_peer; int cnt = 0; int off = 0; if((eee->sn_wait && (now > (eee->last_register_req + (eee->conf.register_interval / 10)))) ||(eee->sn_wait == 2)) /* immediately re-register in case of RE_REGISTER_SUPER */ { /* fall through */ traceEvent(TRACE_DEBUG, "update_supernode_reg: doing fast retry."); } else if(now < (eee->last_register_req + eee->conf.register_interval)) return; /* Too early */ // determine time offset to apply on last_register_req for // all edges's next re-registration does not happen all at once if(eee->sn_wait == 2) { // remaining 1/4 is greater than 1/10 fast retry allowance; // '%' might be expensive but does not happen all too often off = n2n_rand() % ((eee->conf.register_interval * 3) / 4); } check_join_multicast_group(eee); if(0 == eee->sup_attempts) { /* Give up on that supernode and try the next one. */ sn_selection_criterion_bad(&(eee->curr_sn->selection_criterion)); sn_selection_sort(&(eee->conf.supernodes)); eee->curr_sn = eee->conf.supernodes; traceEvent(TRACE_WARNING, "supernode not responding, now trying [%s]", supernode_ip(eee)); reset_sup_attempts(eee); // trigger out-of-schedule DNS resolution eee->resolution_request = 1; // in some multi-NATed scenarios communication gets stuck on losing connection to supernode // closing and re-opening the socket allows for re-establishing communication // this can only be done, if working on some unprivileged port and/or having sufficent // privileges. as we are not able to check for sufficent privileges here, we only do it // if port is sufficently high or unset. uncovered: privileged port and sufficent privileges if((eee->conf.local_port == 0) || (eee->conf.local_port > 1024)) { // do not explicitly disconnect every time as the condition described is rare, so ... // ... check that there are no external peers (indicating a working socket) ... HASH_ITER(hh, eee->known_peers, peer, tmp_peer) if(!peer->local) { cnt++; break; } if(!cnt) { // ... and then count the connection retries (eee->close_socket_counter)++; if(eee->close_socket_counter >= N2N_CLOSE_SOCKET_COUNTER_MAX) { eee->close_socket_counter = 0; supernode_disconnect(eee); traceEvent(TRACE_DEBUG, "disconnected supernode"); } } traceEvent(TRACE_DEBUG, "reconnected to supernode"); } supernode_connect(eee); } else { --(eee->sup_attempts); } #ifndef HAVE_PTHREAD if(supernode2sock(&(eee->curr_sn->sock), eee->curr_sn->ip_addr) == 0) { #endif traceEvent(TRACE_INFO, "registering with supernode [%s][number of supernodes %d][attempts left %u]", supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigned int)eee->sup_attempts); send_register_super(eee); #ifndef HAVE_PTHREAD } #endif register_with_local_peers(eee); // if supernode repeatedly not responding (already waiting), safeguard the // current known connections to peers by re-registering if(eee->sn_wait == 1) HASH_ITER(hh, eee->known_peers, peer, tmp_peer) if((now - peer->last_seen) > REGISTER_SUPER_INTERVAL_DFL) send_register(eee, &(peer->sock), peer->mac_addr, peer->last_cookie); eee->sn_wait = 1; eee->last_register_req = now - off; } /* ************************************** */ /** Return the IP address of the current supernode in the ring. */ static const char * supernode_ip (const n2n_edge_t * eee) { return (eee->curr_sn->ip_addr); } /* ************************************** */ /** A PACKET has arrived containing an encapsulated ethernet datagram - usually * encrypted. */ static int handle_PACKET (n2n_edge_t * eee, const uint8_t from_supernode, const n2n_PACKET_t * pkt, const n2n_sock_t * orig_sender, uint8_t * payload, size_t psize) { ssize_t data_sent_len; uint8_t * eth_payload = NULL; int retval = -1; time_t now; ether_hdr_t * eh; ipstr_t ip_buf; macstr_t mac_buf; n2n_sock_str_t sockbuf; now = time(NULL); traceEvent(TRACE_DEBUG, "handle_PACKET size %u transform %u", (unsigned int)psize, (unsigned int)pkt->transform); /* hexdump(payload, psize); */ if(from_supernode) { if(is_multi_broadcast(pkt->dstMac)) ++(eee->stats.rx_sup_broadcast); ++(eee->stats.rx_sup); eee->last_sup = now; } else { ++(eee->stats.rx_p2p); eee->last_p2p=now; } /* Handle transform. */ { uint8_t decode_buf[N2N_PKT_BUF_SIZE]; uint8_t deflate_buf[N2N_PKT_BUF_SIZE]; size_t eth_size; n2n_transform_t rx_transop_id; uint8_t rx_compression_id; rx_transop_id = (n2n_transform_t)pkt->transform; rx_compression_id = pkt->compression; if(rx_transop_id == eee->conf.transop_id) { uint8_t is_multicast; // decrypt eth_payload = decode_buf; eth_size = eee->transop.rev(&eee->transop, eth_payload, N2N_PKT_BUF_SIZE, payload, psize, pkt->srcMac); ++(eee->transop.rx_cnt); /* stats */ /* decompress if necessary */ size_t deflate_len; switch(rx_compression_id) { case N2N_COMPRESSION_ID_NONE: break; // continue afterwards case N2N_COMPRESSION_ID_LZO: deflate_len = eee->transop_lzo.rev(&eee->transop_lzo, deflate_buf, N2N_PKT_BUF_SIZE, decode_buf, eth_size, pkt->srcMac); break; #ifdef HAVE_ZSTD case N2N_COMPRESSION_ID_ZSTD: deflate_len = eee->transop_zstd.rev(&eee->transop_zstd, deflate_buf, N2N_PKT_BUF_SIZE, decode_buf, eth_size, pkt->srcMac); break; #endif default: traceEvent(TRACE_WARNING, "payload decompression failed: received packet indicating unsupported %s compression.", compression_str(rx_compression_id)); return(-1); // cannot handle it } if(rx_compression_id != N2N_COMPRESSION_ID_NONE) { traceEvent(TRACE_DEBUG, "payload decompression %s: deflated %u bytes to %u bytes", compression_str(rx_compression_id), eth_size, (int)deflate_len); eth_payload = deflate_buf; eth_size = deflate_len; } eh = (ether_hdr_t*)eth_payload; is_multicast = (is_ip6_discovery(eth_payload, eth_size) || is_ethMulticast(eth_payload, eth_size)); if(eee->conf.drop_multicast && is_multicast) { traceEvent(TRACE_INFO, "dropping RX multicast"); return(-1); } else if((!eee->conf.allow_routing) && (!is_multicast)) { /* Check if it is a routed packet */ if((ntohs(eh->type) == 0x0800) && (eth_size >= ETH_FRAMESIZE + IP4_MIN_SIZE)) { uint32_t *dst = (uint32_t*)ð_payload[ETH_FRAMESIZE + IP4_DSTOFFSET]; uint8_t *dst_mac = (uint8_t*)eth_payload; /* Note: all elements of the_ip are in network order */ if(!memcmp(dst_mac, broadcast_mac, N2N_MAC_SIZE)) traceEvent(TRACE_DEBUG, "RX broadcast packet destined to [%s]", intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); else if((*dst != eee->device.ip_addr)) { /* This is a packet that needs to be routed */ traceEvent(TRACE_INFO, "discarding routed packet destined to [%s]", intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); return(-1); } else { /* This packet is directed to us */ /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ } } } if(eee->network_traffic_filter->filter_packet_from_peer(eee->network_traffic_filter, eee, orig_sender, eth_payload, eth_size) == N2N_DROP) { traceEvent(TRACE_DEBUG, "filtered packet of size %u", (unsigned int)eth_size); return(0); } if(eee->cb.packet_from_peer) { uint16_t tmp_eth_size = eth_size; if(eee->cb.packet_from_peer(eee, orig_sender, eth_payload, &tmp_eth_size) == N2N_DROP) { traceEvent(TRACE_DEBUG, "DROP packet of size %u", (unsigned int)eth_size); return(0); } eth_size = tmp_eth_size; } /* Write ethernet packet to tap device. */ traceEvent(TRACE_DEBUG, "sending data of size %u to TAP", (unsigned int)eth_size); data_sent_len = tuntap_write(&(eee->device), eth_payload, eth_size); if(data_sent_len == eth_size) { retval = 0; } } else { traceEvent(TRACE_WARNING, "invalid transop ID: expected %s (%u), got %s (%u) from %s [%s]", transop_str(eee->conf.transop_id), eee->conf.transop_id, transop_str(rx_transop_id), rx_transop_id, macaddr_str(mac_buf, pkt->srcMac), sock_to_cstr(sockbuf, orig_sender)); } } return retval; } /* ************************************** */ #if 0 #ifndef WIN32 static char *get_ip_from_arp (dec_ip_str_t buf, const n2n_mac_t req_mac) { FILE *fd; dec_ip_str_t ip_str = {'\0'}; char dev_str[N2N_IFNAMSIZ] = {'\0'}; macstr_t mac_str = {'\0'}; n2n_mac_t mac = {'\0'}; strncpy(buf, "0.0.0.0", N2N_NETMASK_STR_SIZE - 1); if(is_null_mac(req_mac)) { traceEvent(TRACE_DEBUG, "MAC address is null."); return buf; } if(!(fd = fopen("/proc/net/arp", "r"))) { traceEvent(TRACE_WARNING, "could not open arp table: %d - %s", errno, strerror(errno)); return buf; } while(!feof(fd) && fgetc(fd) != '\n'); while(!feof(fd) && (fscanf(fd, " %15[0-9.] %*s %*s %17[A-Fa-f0-9:] %*s %15s", ip_str, mac_str, dev_str) == 3)) { str2mac(mac, mac_str); if(0 == memcmp(mac, req_mac, sizeof(n2n_mac_t))) { strncpy(buf, ip_str, N2N_NETMASK_STR_SIZE - 1); break; } } fclose(fd); return buf; } #endif #endif /* ************************************** */ static int check_query_peer_info (n2n_edge_t *eee, time_t now, n2n_mac_t mac) { struct peer_info *scan; HASH_FIND_PEER(eee->pending_peers, mac, scan); if(!scan) { scan = calloc(1, sizeof(struct peer_info)); memcpy(scan->mac_addr, mac, N2N_MAC_SIZE); scan->timeout = eee->conf.register_interval; /* TODO: should correspond to the peer supernode registration timeout */ scan->last_seen = now; /* Don't change this it marks the pending peer for removal. */ scan->last_valid_time_stamp = initial_time_stamp(); HASH_ADD_PEER(eee->pending_peers, scan); } if(now - scan->last_sent_query > eee->conf.register_interval) { send_register(eee, &(eee->curr_sn->sock), mac, N2N_FORWARDED_REG_COOKIE); send_query_peer(eee, scan->mac_addr); scan->last_sent_query = now; return(0); } return(1); } /* ************************************** */ /* @return 1 if destination is a peer, 0 if destination is supernode */ static int find_peer_destination (n2n_edge_t * eee, n2n_mac_t mac_address, n2n_sock_t * destination) { struct peer_info *scan; macstr_t mac_buf; n2n_sock_str_t sockbuf; int retval = 0; time_t now = time(NULL); if(is_multi_broadcast(mac_address)) { traceEvent(TRACE_DEBUG, "multicast or broadcast destination peer, using supernode"); memcpy(destination, &(eee->curr_sn->sock), sizeof(struct sockaddr_in)); return(0); } traceEvent(TRACE_DEBUG, "searching destination socket for %s", macaddr_str(mac_buf, mac_address)); HASH_FIND_PEER(eee->known_peers, mac_address, scan); if(scan && (scan->last_seen > 0)) { if((now - scan->last_p2p) >= (scan->timeout / 2)) { /* Too much time passed since we saw the peer, need to register again * since the peer address may have changed. */ traceEvent(TRACE_DEBUG, "refreshing idle known peer"); HASH_DEL(eee->known_peers, scan); mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_DEL_P2P,scan); free(scan); /* NOTE: registration will be performed upon the receival of the next response packet */ } else { /* Valid known peer found */ memcpy(destination, &scan->sock, sizeof(n2n_sock_t)); retval = 1; } } if(retval == 0) { memcpy(destination, &(eee->curr_sn->sock), sizeof(struct sockaddr_in)); traceEvent(TRACE_DEBUG, "p2p peer %s not found, using supernode", macaddr_str(mac_buf, mac_address)); check_query_peer_info(eee, now, mac_address); } traceEvent(TRACE_DEBUG, "found peer's socket %s [%s]", macaddr_str(mac_buf, mac_address), sock_to_cstr(sockbuf, destination)); return retval; } /* ***************************************************** */ /** Send an ecapsulated ethernet PACKET to a destination edge or broadcast MAC * address. */ static int send_packet (n2n_edge_t * eee, n2n_mac_t dstMac, const uint8_t * pktbuf, size_t pktlen) { int is_p2p; /*ssize_t s; */ n2n_sock_str_t sockbuf; n2n_sock_t destination; macstr_t mac_buf; struct peer_info *peer, *tmp_peer; /* hexdump(pktbuf, pktlen); */ is_p2p = find_peer_destination(eee, dstMac, &destination); traceEvent(TRACE_INFO, "Tx PACKET of %u bytes to %s [%s]", pktlen, macaddr_str(mac_buf, dstMac), sock_to_cstr(sockbuf, &destination)); if(is_p2p) ++(eee->stats.tx_p2p); else ++(eee->stats.tx_sup); if(is_multi_broadcast(dstMac)) { ++(eee->stats.tx_sup_broadcast); // if no supernode around, foward the broadcast to all known peers if(eee->sn_wait) { HASH_ITER(hh, eee->known_peers, peer, tmp_peer) /* s = */ sendto_sock(eee, pktbuf, pktlen, &peer->sock); return 0; } // fall through otherwise } /* s = */ sendto_sock(eee, pktbuf, pktlen, &destination); return 0; } /* ************************************** */ /** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */ void edge_send_packet2net (n2n_edge_t * eee, uint8_t *tap_pkt, size_t len) { ipstr_t ip_buf; n2n_mac_t destMac; n2n_common_t cmn; n2n_PACKET_t pkt; uint8_t *enc_src = tap_pkt; size_t enc_len = len; uint8_t compression_buf[N2N_PKT_BUF_SIZE]; uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx = 0; n2n_transform_t tx_transop_idx = eee->transop.transform_id; ether_hdr_t eh; /* tap_pkt is not aligned so we have to copy to aligned memory */ memcpy(&eh, tap_pkt, sizeof(ether_hdr_t)); /* Discard IP packets that are not originated by this hosts */ if(!(eee->conf.allow_routing)) { if(ntohs(eh.type) == 0x0800) { /* This is an IP packet from the local source address - not forwarded. */ uint32_t *src = (uint32_t*)&tap_pkt[ETH_FRAMESIZE + IP4_SRCOFFSET]; /* Note: all elements of the_ip are in network order */ if(*src != eee->device.ip_addr) { /* This is a packet that needs to be routed */ traceEvent(TRACE_INFO, "discarding routed packet destined to [%s]", intoa(ntohl(*src), ip_buf, sizeof(ip_buf))); return; } else { /* This packet is originated by us */ /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ } } } /* Optionally compress then apply transforms, eg encryption. */ /* Once processed, send to destination in PACKET */ memcpy(destMac, tap_pkt, N2N_MAC_SIZE); /* dest MAC is first in ethernet header */ memset(&cmn, 0, sizeof(cmn)); cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_packet; cmn.flags = 0; /* no options, not from supernode, no socket */ memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE); memset(&pkt, 0, sizeof(pkt)); memcpy(pkt.srcMac, eee->device.mac_addr, N2N_MAC_SIZE); memcpy(pkt.dstMac, destMac, N2N_MAC_SIZE); pkt.transform = tx_transop_idx; // compression needs to be tried before encode_PACKET is called for compression indication gets encoded there pkt.compression = N2N_COMPRESSION_ID_NONE; if(eee->conf.compression) { int32_t compression_len; switch(eee->conf.compression) { case N2N_COMPRESSION_ID_LZO: compression_len = eee->transop_lzo.fwd(&eee->transop_lzo, compression_buf, sizeof(compression_buf), tap_pkt, len, pkt.dstMac); if((compression_len > 0) && (compression_len < len)) { pkt.compression = N2N_COMPRESSION_ID_LZO; } break; #ifdef HAVE_ZSTD case N2N_COMPRESSION_ID_ZSTD: compression_len = eee->transop_zstd.fwd(&eee->transop_zstd, compression_buf, sizeof(compression_buf), tap_pkt, len, pkt.dstMac); if((compression_len > 0) && (compression_len < len)) { pkt.compression = N2N_COMPRESSION_ID_ZSTD; } break; #endif default: break; } if(pkt.compression != N2N_COMPRESSION_ID_NONE) { traceEvent(TRACE_DEBUG, "payload compression [%s]: compressed %u bytes to %u bytes\n", compression_str(pkt.compression), len, compression_len); enc_src = compression_buf; enc_len = compression_len; } } idx = 0; encode_PACKET(pktbuf, &idx, &cmn, &pkt); uint16_t headerIdx = idx; idx += eee->transop.fwd(&eee->transop, pktbuf + idx, N2N_PKT_BUF_SIZE - idx, enc_src, enc_len, pkt.dstMac); traceEvent(TRACE_DEBUG, "encode PACKET of %u bytes, %u bytes data, %u bytes overhead, transform %u", (u_int)idx, (u_int)len, (u_int)(idx - len), tx_transop_idx); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) // in case of user-password auth, also encrypt the iv of payload assuming ChaCha20 and SPECK having the same iv size packet_header_encrypt(pktbuf, headerIdx + (NULL != eee->conf.shared_secret) * min(idx - headerIdx, N2N_SPECK_IVEC_SIZE), idx, eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic, time_stamp()); #ifdef MTU_ASSERT_VALUE { const u_int eth_udp_overhead = ETH_FRAMESIZE + IP4_MIN_SIZE + UDP_SIZE; // MTU assertion which avoids fragmentation by N2N assert(idx + eth_udp_overhead <= MTU_ASSERT_VALUE); } #endif eee->transop.tx_cnt++; /* stats */ send_packet(eee, destMac, pktbuf, idx); /* to peer or supernode */ } /* ************************************** */ /** Read a single packet from the TAP interface, process it and write out the * corresponding packet to the cooked socket. */ void edge_read_from_tap (n2n_edge_t * eee) { /* tun -> remote */ uint8_t eth_pkt[N2N_PKT_BUF_SIZE]; macstr_t mac_buf; ssize_t len; len = tuntap_read( &(eee->device), eth_pkt, N2N_PKT_BUF_SIZE ); if((len <= 0) || (len > N2N_PKT_BUF_SIZE)) { traceEvent(TRACE_WARNING, "read()=%d [%d/%s]", (signed int)len, errno, strerror(errno)); traceEvent(TRACE_WARNING, "TAP I/O operation aborted, restart later."); sleep(3); tuntap_close(&(eee->device)); tuntap_open(&(eee->device), eee->tuntap_priv_conf.tuntap_dev_name, eee->tuntap_priv_conf.ip_mode, eee->tuntap_priv_conf.ip_addr, eee->tuntap_priv_conf.netmask, eee->tuntap_priv_conf.device_mac, eee->tuntap_priv_conf.mtu #ifdef WIN32 ,eee->tuntap_priv_conf.metric #endif ); } else { const uint8_t * mac = eth_pkt; traceEvent(TRACE_DEBUG, "Rx TAP packet (%4d) for %s", (signed int)len, macaddr_str(mac_buf, mac)); if(eee->conf.drop_multicast && (is_ip6_discovery(eth_pkt, len) || is_ethMulticast(eth_pkt, len))) { traceEvent(TRACE_INFO, "dropping Tx multicast"); } else { if(!eee->last_sup) { // drop packets before first registration with supernode traceEvent(TRACE_DEBUG, "DROP packet before first registration with supernode"); return; } if(eee->network_traffic_filter) { if(eee->network_traffic_filter->filter_packet_from_tap(eee->network_traffic_filter, eee, eth_pkt, len) == N2N_DROP) { traceEvent(TRACE_DEBUG, "filtered packet of size %u", (unsigned int)len); return; } } if(eee->cb.packet_from_tap) { uint16_t tmp_len = len; if(eee->cb.packet_from_tap(eee, eth_pkt, &tmp_len) == N2N_DROP) { traceEvent(TRACE_DEBUG, "DROP packet of size %u", (unsigned int)len); return; } len = tmp_len; } edge_send_packet2net(eee, eth_pkt, len); } } } /* ************************************** */ /** handle a datagram from the main UDP socket to the internet. */ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const SOCKET in_sock, uint8_t *udp_buf, size_t udp_size, time_t now) { n2n_common_t cmn; /* common fields in the packet header */ n2n_sock_str_t sockbuf1; n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ macstr_t mac_buf1; macstr_t mac_buf2; uint8_t hash_buf[16]; size_t rem; size_t idx; size_t msg_type; uint8_t from_supernode; uint8_t via_multicast; peer_info_t *sn = NULL; n2n_sock_t sender; n2n_sock_t * orig_sender = NULL; uint32_t header_enc = 0; uint64_t stamp = 0; int skip_add = 0; /* REVISIT: when UDP/IPv6 is supported we will need a flag to indicate which * IP transport version the packet arrived on. May need to UDP sockets. */ memset(&sender, 0, sizeof(n2n_sock_t)); if(eee->conf.connect_tcp) // TCP expects that we know our comm partner and does not deliver the sender memcpy(&sender, &(eee->curr_sn->sock), sizeof(struct sockaddr_in)); else { sender.family = AF_INET; /* UDP socket was opened PF_INET v4 */ sender.port = ntohs(sender_sock->sin_port); memcpy(&(sender.addr.v4), &(sender_sock->sin_addr.s_addr), IPV4_SIZE); } /* The packet may not have an orig_sender socket spec. So default to last * hop as sender. */ orig_sender = &sender; #ifdef SKIP_MULTICAST_PEERS_DISCOVERY via_multicast = 0; #else via_multicast = (in_sock == eee->udp_multicast_sock); #endif traceEvent(TRACE_DEBUG, "Rx N2N_UDP of size %d from [%s]", (signed int)udp_size, sock_to_cstr(sockbuf1, &sender)); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { // match with static (1) or dynamic (2) ctx? // check dynamic first as it is identical to static in normal header encryption mode if(packet_header_decrypt(udp_buf, udp_size, (char *)eee->conf.community_name, eee->conf.header_encryption_ctx_dynamic, eee->conf.header_iv_ctx_dynamic, &stamp)) { header_enc = 2; /* not accurate with normal header encryption but does not matter */ } if(!header_enc) { // check static now (very likely to be REGISTER_SUPER_ACK, REGISTER_SUPER_NAK or invalid) if(eee->conf.shared_secret) { // hash the still encrypted packet to eventually be able to check it later (required for REGISTER_SUPER_ACK with user/pw auth) pearson_hash_128(hash_buf, udp_buf, max(0, (int)udp_size - (int)N2N_REG_SUP_HASH_CHECK_LEN)); } header_enc = packet_header_decrypt(udp_buf, max(0, (int)udp_size - (int)N2N_REG_SUP_HASH_CHECK_LEN), (char *)eee->conf.community_name, eee->conf.header_encryption_ctx_static, eee->conf.header_iv_ctx_static, &stamp); } if(!header_enc) { traceEvent(TRACE_DEBUG, "failed to decrypt header"); return; } // time stamp verification follows in the packet specific section as it requires to determine the // sender from the hash list by its MAC, or the packet might be from the supernode, this all depends // on packet type, path taken (via supernode) and packet structure (MAC is not always in the same place) } rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */ idx = 0; /* marches through packet header as parts are decoded. */ if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) { if(via_multicast) { // from some other edge on local network, possibly header encrypted traceEvent(TRACE_DEBUG, "dropped packet arriving via multicast due to error while decoding N2N_UDP"); } else { traceEvent(TRACE_INFO, "failed to decode common section in N2N_UDP"); } return; /* failed to decode packet */ } msg_type = cmn.pc; /* packet code */ // special case for user/pw auth // community's auth scheme and message type need to match the used key (dynamic) if((eee->conf.shared_secret) && (msg_type != MSG_TYPE_REGISTER_SUPER_ACK) && (msg_type != MSG_TYPE_REGISTER_SUPER_NAK)) { if(header_enc != 2) { traceEvent(TRACE_INFO, "dropped packet encrypted with static key where dynamic key expected"); return; } } // check if packet is from supernode and find the corresponding supernode in list from_supernode = cmn.flags & N2N_FLAGS_FROM_SUPERNODE; if(from_supernode) { skip_add = SN_ADD_SKIP; sn = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &sender, null_mac, &skip_add); if(!sn) { traceEvent(TRACE_DEBUG, "dropped incoming data from unknown supernode"); return; } } if(0 == memcmp(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE)) { switch(msg_type) { case MSG_TYPE_PACKET: { /* process PACKET - most frequent so first in list. */ n2n_PACKET_t pkt; decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_peer_time_stamp_and_verify(eee, sn, pkt.srcMac, stamp, TIME_STAMP_ALLOW_JITTER)) { traceEvent(TRACE_DEBUG, "dropped PACKET due to time stamp error"); return; } } if(!eee->last_sup) { // drop packets received before first registration with supernode traceEvent(TRACE_DEBUG, "dropped PACKET recevied before first registration with supernode"); return; } if(!from_supernode) { /* This is a P2P packet from the peer. We purge a pending * registration towards the possibly nat-ted peer address as we now have * a valid channel. We still use check_peer_registration_needed in * handle_PACKET to double check this. */ traceEvent(TRACE_DEBUG, "[p2p] from %s", macaddr_str(mac_buf1, pkt.srcMac)); find_and_remove_peer(&eee->pending_peers, pkt.srcMac); } else { /* [PsP] : edge Peer->Supernode->edge Peer */ if(is_valid_peer_sock(&pkt.sock)) orig_sender = &(pkt.sock); traceEvent(TRACE_DEBUG, "[pSp] from %s via [%s]", macaddr_str(mac_buf1, pkt.srcMac), sock_to_cstr(sockbuf1, &sender)); } /* Update the sender in peer table entry */ check_peer_registration_needed(eee, from_supernode, via_multicast, pkt.srcMac, // REVISIT: also consider PORT_REG_COOKIEs when implemented from_supernode ? N2N_FORWARDED_REG_COOKIE : N2N_REGULAR_REG_COOKIE, NULL, NULL, orig_sender); handle_PACKET(eee, from_supernode, &pkt, orig_sender, udp_buf + idx, udp_size - idx); break; } case MSG_TYPE_REGISTER: { /* Another edge is registering with us */ n2n_REGISTER_t reg; decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); via_multicast &= is_null_mac(reg.dstMac); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_peer_time_stamp_and_verify(eee, sn, reg.srcMac, stamp, via_multicast ? TIME_STAMP_ALLOW_JITTER : TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped REGISTER due to time stamp error"); return; } } if(is_valid_peer_sock(®.sock)) orig_sender = &(reg.sock); if(via_multicast && !memcmp(reg.srcMac, eee->device.mac_addr, N2N_MAC_SIZE)) { traceEvent(TRACE_DEBUG, "skipping REGISTER from self"); break; } if(!via_multicast && memcmp(reg.dstMac, eee->device.mac_addr, N2N_MAC_SIZE)) { traceEvent(TRACE_DEBUG, "skipping REGISTER for other peer"); break; } if(!from_supernode) { /* This is a P2P registration from the peer. We purge a pending * registration towards the possibly nat-ted peer address as we now have * a valid channel. We still use check_peer_registration_needed below * to double check this. */ traceEvent(TRACE_INFO, "[p2p] Rx REGISTER from %s [%s]%s", macaddr_str(mac_buf1, reg.srcMac), sock_to_cstr(sockbuf1, &sender), (reg.cookie & N2N_LOCAL_REG_COOKIE) ? " (local)" : ""); find_and_remove_peer(&eee->pending_peers, reg.srcMac); /* NOTE: only ACK to peers */ send_register_ack(eee, orig_sender, ®); } else { traceEvent(TRACE_INFO, "[pSp] Rx REGISTER from %s [%s] to %s via [%s]", macaddr_str(mac_buf1, reg.srcMac), sock_to_cstr(sockbuf2, orig_sender), macaddr_str(mac_buf2, reg.dstMac), sock_to_cstr(sockbuf1, &sender)); } check_peer_registration_needed(eee, from_supernode, via_multicast, reg.srcMac, reg.cookie, ®.dev_addr, (const n2n_desc_t*)®.dev_desc, orig_sender); break; } case MSG_TYPE_REGISTER_ACK: { /* Peer edge is acknowledging our register request */ n2n_REGISTER_ACK_t ra; decode_REGISTER_ACK(&ra, &cmn, udp_buf, &rem, &idx); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_peer_time_stamp_and_verify(eee, sn, ra.srcMac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped REGISTER_ACK due to time stamp error"); return; } } if(is_valid_peer_sock(&ra.sock)) orig_sender = &(ra.sock); traceEvent(TRACE_INFO, "Rx REGISTER_ACK from %s [%s] to %s via [%s]%s", macaddr_str(mac_buf1, ra.srcMac), sock_to_cstr(sockbuf2, orig_sender), macaddr_str(mac_buf2, ra.dstMac), sock_to_cstr(sockbuf1, &sender), (ra.cookie & N2N_LOCAL_REG_COOKIE) ? " (local)" : ""); peer_set_p2p_confirmed(eee, ra.srcMac, ra.cookie, &sender, now); break; } case MSG_TYPE_REGISTER_SUPER_ACK: { in_addr_t net; char * ip_str = NULL; n2n_REGISTER_SUPER_ACK_t ra; uint8_t tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE]; char ip_tmp[N2N_EDGE_SN_HOST_SIZE]; n2n_REGISTER_SUPER_ACK_payload_t *payload; int i; int skip_add; if(!(eee->sn_wait)) { traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER"); return; } memset(&ra, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); decode_REGISTER_SUPER_ACK(&ra, &cmn, udp_buf, &rem, &idx, tmpbuf); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_peer_time_stamp_and_verify(eee, sn, ra.srcMac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_ACK due to time stamp error"); return; } } // hash check (user/pw auth only) if(eee->conf.shared_secret) { speck_128_encrypt(hash_buf, (speck_context_t*)eee->conf.shared_secret_ctx); if(memcmp(hash_buf, udp_buf + udp_size - N2N_REG_SUP_HASH_CHECK_LEN /* length is has already been checked */, N2N_REG_SUP_HASH_CHECK_LEN)) { traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong hash"); return; } } if(ra.cookie != eee->curr_sn->last_cookie) { traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie"); return; } if(handle_remote_auth(eee, sn, &(ra.auth))) { traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old response to challenge"); if(eee->conf.shared_secret) { traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK with wrong or old response to challenge, maybe indicating wrong federation public key (-P)"); } return; } if(is_valid_peer_sock(&ra.sock)) orig_sender = &(ra.sock); traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK from %s [%s] (external %s) with %u attempts left", macaddr_str(mac_buf1, ra.srcMac), sock_to_cstr(sockbuf1, &sender), sock_to_cstr(sockbuf2, orig_sender), (unsigned int)eee->sup_attempts); if(is_null_mac(eee->curr_sn->mac_addr)) { HASH_DEL(eee->conf.supernodes, eee->curr_sn); memcpy(&eee->curr_sn->mac_addr, ra.srcMac, N2N_MAC_SIZE); HASH_ADD_PEER(eee->conf.supernodes, eee->curr_sn); } payload = (n2n_REGISTER_SUPER_ACK_payload_t*)tmpbuf; // from here on, 'sn' gets used differently for(i = 0; i < ra.num_sn; i++) { skip_add = SN_ADD; sn = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &(payload->sock), payload->mac, &skip_add); if(skip_add == SN_ADD_ADDED) { sn->ip_addr = calloc(1, N2N_EDGE_SN_HOST_SIZE); if(sn->ip_addr != NULL) { inet_ntop(payload->sock.family, (payload->sock.family == AF_INET) ? (void*)&(payload->sock.addr.v4) : (void*)&(payload->sock.addr.v6), sn->ip_addr, N2N_EDGE_SN_HOST_SIZE - 1); sprintf(ip_tmp, "%s:%u", (char*)sn->ip_addr, (uint16_t)(payload->sock.port)); memcpy(sn->ip_addr, ip_tmp, sizeof(ip_tmp)); } sn_selection_criterion_default(&(sn->selection_criterion)); sn->last_seen = 0; /* as opposed to payload handling in supernode */ traceEvent(TRACE_NORMAL, "supernode '%s' added to the list of supernodes.", sn->ip_addr); } // shift to next payload entry payload++; } if(eee->conf.tuntap_ip_mode == TUNTAP_IP_MODE_SN_ASSIGN) { if((ra.dev_addr.net_addr != 0) && (ra.dev_addr.net_bitlen != 0)) { net = htonl(ra.dev_addr.net_addr); if((ip_str = inet_ntoa(*(struct in_addr *) &net)) != NULL) { strncpy(eee->tuntap_priv_conf.ip_addr, ip_str, N2N_NETMASK_STR_SIZE); eee->tuntap_priv_conf.ip_addr[N2N_NETMASK_STR_SIZE - 1] = '\0'; } net = htonl(bitlen2mask(ra.dev_addr.net_bitlen)); if((ip_str = inet_ntoa(*(struct in_addr *) &net)) != NULL) { strncpy(eee->tuntap_priv_conf.netmask, ip_str, N2N_NETMASK_STR_SIZE); eee->tuntap_priv_conf.netmask[N2N_NETMASK_STR_SIZE - 1] = '\0'; } } } eee->sn_wait = 0; reset_sup_attempts(eee); /* refresh because we got a response */ // update last_sup only on 'real' REGISTER_SUPER_ACKs, not on bootstrap ones (own MAC address // still null_mac) this allows reliable in/out PACKET drop if not really registered with a supernode yet if(!is_null_mac(eee->device.mac_addr)) { if(!eee->last_sup) { // indicates first successful connection between the edge and a supernode traceEvent(TRACE_NORMAL, "[OK] edge <<< ================ >>> supernode"); // send gratuitous ARP only upon first registration with supernode send_grat_arps(eee); } eee->last_sup = now; } // NOTE: the register_interval should be chosen by the edge node based on its NAT configuration. // eee->conf.register_interval = ra.lifetime; if(eee->cb.sn_registration_updated && !is_null_mac(eee->device.mac_addr)) eee->cb.sn_registration_updated(eee, now, &sender); break; } case MSG_TYPE_REGISTER_SUPER_NAK: { n2n_REGISTER_SUPER_NAK_t nak; if(!(eee->sn_wait)) { traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_NAK with no outstanding REGISTER_SUPER"); return; } memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t)); decode_REGISTER_SUPER_NAK(&nak, &cmn, udp_buf, &rem, &idx); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_peer_time_stamp_and_verify(eee, sn, nak.srcMac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_NAK due to time stamp error"); return; } } if(nak.cookie != eee->curr_sn->last_cookie) { traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER_NAK with wrong or old cookie"); return; } // REVISIT: authenticate the NAK packet really originating from the supernode along the auth token. // this must follow a different scheme because it needs to prove authenticity although the // edge-provided credentials are wrong traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_NAK"); if((memcmp(nak.srcMac, eee->device.mac_addr, sizeof(n2n_mac_t))) == 0) { if(eee->conf.shared_secret) { traceEvent(TRACE_ERROR, "authentication error, username or password not recognized by supernode"); } else { traceEvent(TRACE_ERROR, "authentication error, MAC or IP address already in use or not released yet by supernode"); } // REVISIT: the following portion is too harsh, repeated error warning should be sufficient until it eventually is resolved, // preventing de-auth attacks /* exit(1); this is too harsh, repeated error warning should be sufficient until it eventually is resolved, preventing de-auth attacks } else { HASH_FIND_PEER(eee->known_peers, nak.srcMac, peer); if(peer != NULL) { HASH_DEL(eee->known_peers, peer); } HASH_FIND_PEER(eee->pending_peers, nak.srcMac, scan); if(scan != NULL) { HASH_DEL(eee->pending_peers, scan); } */ } break; } case MSG_TYPE_PEER_INFO: { n2n_PEER_INFO_t pi; struct peer_info * scan; int skip_add; decode_PEER_INFO(&pi, &cmn, udp_buf, &rem, &idx); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_peer_time_stamp_and_verify(eee, sn, null_mac, stamp, TIME_STAMP_ALLOW_JITTER)) { traceEvent(TRACE_DEBUG, "dropped PEER_INFO due to time stamp error"); return; } } if((cmn.flags & N2N_FLAGS_SOCKET) && !is_valid_peer_sock(&pi.sock)) { traceEvent(TRACE_DEBUG, "skip invalid PEER_INFO from %s [%s]", macaddr_str(mac_buf1, pi.mac), sock_to_cstr(sockbuf1, &pi.sock)); break; } if(is_null_mac(pi.mac)) { // PONG - answer to PING (QUERY_PEER_INFO with null mac) skip_add = SN_ADD_SKIP; scan = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &sender, pi.srcMac, &skip_add); if(scan != NULL) { eee->sn_pong = 1; scan->last_seen = now; scan->uptime = pi.uptime; memcpy(scan->version, pi.version, sizeof(n2n_version_t)); /* The data type depends on the actual selection strategy that has been chosen. */ SN_SELECTION_CRITERION_DATA_TYPE sn_sel_tmp = pi.load; sn_selection_criterion_calculate(eee, scan, &sn_sel_tmp); traceEvent(TRACE_INFO, "Rx PONG from supernode %s version '%s'", macaddr_str(mac_buf1, pi.srcMac), pi.version); break; } } else { // regular PEER_INFO HASH_FIND_PEER(eee->pending_peers, pi.mac, scan); if(!scan) // just in case the remote edge has been upgraded by the REG/ACK mechanism in the meantime HASH_FIND_PEER(eee->known_peers, pi.mac, scan); if(scan) { scan->sock = pi.sock; traceEvent(TRACE_INFO, "Rx PEER_INFO %s can be found at [%s]", macaddr_str(mac_buf1, pi.mac), sock_to_cstr(sockbuf1, &pi.sock)); if(cmn.flags & N2N_FLAGS_SOCKET) { scan->preferred_sock = pi.preferred_sock; send_register(eee, &scan->preferred_sock, scan->mac_addr, N2N_LOCAL_REG_COOKIE); traceEvent(TRACE_INFO, "%s has preferred local socket at [%s]", macaddr_str(mac_buf1, pi.mac), sock_to_cstr(sockbuf1, &pi.preferred_sock)); } send_register(eee, &scan->sock, scan->mac_addr, N2N_REGULAR_REG_COOKIE); } else { traceEvent(TRACE_INFO, "Rx PEER_INFO unknown peer %s", macaddr_str(mac_buf1, pi.mac)); } } break; } case MSG_TYPE_RE_REGISTER_SUPER: { if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_peer_time_stamp_and_verify(eee, sn, null_mac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped RE_REGISTER due to time stamp error"); return; } } // only accept in user/pw mode for immediate re-registration because the new // key is required for continous traffic flow, in other modes edge will realize // changes with regular recurring REGISTER_SUPER if(!eee->conf.shared_secret) { traceEvent(TRACE_DEBUG, "dropped RE_REGISTER_SUPER as not in user/pw auth mode"); return; } traceEvent(TRACE_INFO, "Rx RE_REGISTER_SUPER"); eee->sn_wait = 2; /* immediately */ break; } default: /* Not a known message type */ traceEvent(TRACE_INFO, "unable to handle packet type %d: ignored", (signed int)msg_type); return; } /* switch(msg_type) */ } else if(from_supernode) /* if(community match) */ traceEvent(TRACE_INFO, "received packet with unknown community"); else traceEvent(TRACE_INFO, "ignoring packet with unknown community"); } /* ************************************** */ int fetch_and_eventually_process_data (n2n_edge_t *eee, SOCKET sock, uint8_t *pktbuf, uint16_t *expected, uint16_t *position, time_t now) { ssize_t bread = 0; if((!eee->conf.connect_tcp) #ifndef SKIP_MULTICAST_PEERS_DISCOVERY || (sock == eee->udp_multicast_sock) #endif ) { // udp struct sockaddr_in sender_sock; socklen_t i; i = sizeof(sender_sock); bread = recvfrom(sock, pktbuf, N2N_PKT_BUF_SIZE, 0 /*flags*/, (struct sockaddr *)&sender_sock, (socklen_t *)&i); if((bread < 0) #ifdef WIN32 && (WSAGetLastError() != WSAECONNRESET) #endif ) { /* For UDP bread of zero just means no data (unlike TCP). */ /* The fd is no good now. Maybe we lost our interface. */ traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); #ifdef WIN32 traceEvent(TRACE_ERROR, "WSAGetLastError(): %u", WSAGetLastError()); #endif return -1; } // we have a datagram to process... if(bread > 0) { // ...and the datagram has data (not just a header) process_udp(eee, &sender_sock, sock, pktbuf, bread, now); } } else { // tcp struct sockaddr_in sender_sock; socklen_t i; i = sizeof(sender_sock); bread = recvfrom(sock, pktbuf + *position, *expected - *position, 0 /*flags*/, (struct sockaddr *)&sender_sock, (socklen_t *)&i); if((bread <= 0) && (errno)) { traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); #ifdef WIN32 traceEvent(TRACE_ERROR, "WSAGetLastError(): %u", WSAGetLastError()); #endif supernode_disconnect(eee); eee->sn_wait = 1; traceEvent(TRACE_DEBUG, "disconnected supernode due to connection error"); goto tcp_done; } *position = *position + bread; if(*position == *expected) { if(*position == sizeof(uint16_t)) { // the prepended length has been read, preparing for the packet *expected = *expected + be16toh(*(uint16_t*)(pktbuf)); if(*expected > N2N_PKT_BUF_SIZE) { supernode_disconnect(eee); eee->sn_wait = 1; traceEvent(TRACE_DEBUG, "disconnected supernode due to too many bytes expected"); goto tcp_done; } } else { // full packet read, handle it process_udp(eee, (struct sockaddr_in*)&sender_sock, sock, pktbuf + sizeof(uint16_t), *position - sizeof(uint16_t), now); // reset, await new prepended length *expected = sizeof(uint16_t); *position = 0; } } } tcp_done: ; return 0; } void print_edge_stats (const n2n_edge_t *eee) { const struct n2n_edge_stats *s = &eee->stats; traceEvent(TRACE_NORMAL, "**********************************"); traceEvent(TRACE_NORMAL, "Packet stats:"); traceEvent(TRACE_NORMAL, " TX P2P: %u pkts", s->tx_p2p); traceEvent(TRACE_NORMAL, " RX P2P: %u pkts", s->rx_p2p); traceEvent(TRACE_NORMAL, " TX Supernode: %u pkts (%u broadcast)", s->tx_sup, s->tx_sup_broadcast); traceEvent(TRACE_NORMAL, " RX Supernode: %u pkts (%u broadcast)", s->rx_sup, s->rx_sup_broadcast); traceEvent(TRACE_NORMAL, "**********************************"); } /* ************************************** */ int run_edge_loop (n2n_edge_t *eee) { size_t numPurged; time_t lastIfaceCheck = 0; time_t lastTransop = 0; time_t last_purge_known = 0; time_t last_purge_pending = 0; uint16_t expected = sizeof(uint16_t); uint16_t position = 0; uint8_t pktbuf[N2N_PKT_BUF_SIZE + sizeof(uint16_t)]; /* buffer + prepended buffer length in case of tcp */ #ifdef WIN32 struct tunread_arg arg; arg.eee = eee; HANDLE tun_read_thread = startTunReadThread(&arg); #endif *eee->keep_running = 1; update_supernode_reg(eee, time(NULL)); /* Main loop * * select() is used to wait for input on either the TAP fd or the UDP/TCP * socket. When input is present the data is read and processed by either * readFromIPSocket() or edge_read_from_tap() */ while(*eee->keep_running) { int rc, max_sock = 0; fd_set socket_mask; struct timeval wait_time; time_t now; FD_ZERO(&socket_mask); FD_SET(eee->udp_mgmt_sock, &socket_mask); max_sock = eee->udp_mgmt_sock; if(eee->sock >= 0) { FD_SET(eee->sock, &socket_mask); max_sock = max(eee->sock, eee->udp_mgmt_sock); } #ifndef SKIP_MULTICAST_PEERS_DISCOVERY if((eee->conf.allow_p2p) && (eee->conf.preferred_sock.family == (uint8_t)AF_INVALID)) { FD_SET(eee->udp_multicast_sock, &socket_mask); max_sock = max(eee->sock, eee->udp_multicast_sock); } #endif #ifndef WIN32 FD_SET(eee->device.fd, &socket_mask); max_sock = max(max_sock, eee->device.fd); #endif wait_time.tv_sec = (eee->sn_wait) ? (SOCKET_TIMEOUT_INTERVAL_SECS / 10 + 1) : (SOCKET_TIMEOUT_INTERVAL_SECS); wait_time.tv_usec = 0; rc = select(max_sock + 1, &socket_mask, NULL, NULL, &wait_time); now = time(NULL); // make sure ciphers are updated before the packet is treated if((now - lastTransop) > TRANSOP_TICK_INTERVAL) { lastTransop = now; eee->transop.tick(&eee->transop, now); } if(rc > 0) { // any or all of the FDs could have input; check them all // external if(FD_ISSET(eee->sock, &socket_mask)) { if(0 != fetch_and_eventually_process_data(eee, eee->sock, pktbuf, &expected, &position, now)) { *eee->keep_running = 0; break; } if(eee->conf.connect_tcp) { if((expected >= N2N_PKT_BUF_SIZE) || (position >= N2N_PKT_BUF_SIZE)) { // something went wrong, possibly even before // e.g. connection failure/closure in the middle of transmission (between len & data) supernode_disconnect(eee); eee->sn_wait = 1; expected = sizeof(uint16_t); position = 0; } } } #ifndef SKIP_MULTICAST_PEERS_DISCOVERY if(FD_ISSET(eee->udp_multicast_sock, &socket_mask)) { if(0 != fetch_and_eventually_process_data(eee, eee->udp_multicast_sock, pktbuf, &expected, &position, now)) { *eee->keep_running = 0; break; } } #endif if(FD_ISSET(eee->udp_mgmt_sock, &socket_mask)) { // read from the management port socket readFromMgmtSocket(eee); if(!(*eee->keep_running)) break; } #ifndef WIN32 if(FD_ISSET(eee->device.fd, &socket_mask)) { // read an ethernet frame from the TAP socket; write on the IP socket edge_read_from_tap(eee); } #endif } // finished processing select data update_supernode_reg(eee, now); numPurged = 0; // keep, i.e. do not purge, the known peers while no supernode supernode connection if(!eee->sn_wait) numPurged = purge_expired_nodes(&eee->known_peers, eee->sock, NULL, &last_purge_known, PURGE_REGISTRATION_FREQUENCY, REGISTRATION_TIMEOUT); numPurged += purge_expired_nodes(&eee->pending_peers, eee->sock, NULL, &last_purge_pending, PURGE_REGISTRATION_FREQUENCY, REGISTRATION_TIMEOUT); if(numPurged > 0) { traceEvent(TRACE_INFO, "%u peers removed. now: pending=%u, operational=%u", numPurged, HASH_COUNT(eee->pending_peers), HASH_COUNT(eee->known_peers)); } if((eee->conf.tuntap_ip_mode == TUNTAP_IP_MODE_DHCP) && ((now - lastIfaceCheck) > IFACE_UPDATE_INTERVAL)) { uint32_t old_ip = eee->device.ip_addr; traceEvent(TRACE_NORMAL, "re-checking dynamic IP address"); tuntap_get_address(&(eee->device)); lastIfaceCheck = now; if((old_ip != eee->device.ip_addr) && eee->cb.ip_address_changed) eee->cb.ip_address_changed(eee, old_ip, eee->device.ip_addr); } sort_supernodes(eee, now); eee->resolution_request = resolve_check(eee->resolve_parameter, eee->resolution_request, now); if(eee->cb.main_loop_period) eee->cb.main_loop_period(eee, now); } /* while */ send_unregister_super(eee); #ifdef WIN32 WaitForSingleObject(tun_read_thread, INFINITE); #endif supernode_disconnect(eee); return 0; } /* ************************************** */ /** Deinitialise the edge and deallocate any owned memory. */ void edge_term (n2n_edge_t * eee) { resolve_cancel_thread(eee->resolve_parameter); #ifdef HAVE_PORT_FORWARDING if(eee->conf.port_forwarding) port_map_cancel_thread(eee->port_map_parameter); #endif // HAVE_MINIUPNP || HAVE_NATPMP if(eee->sock >= 0) closesocket(eee->sock); if(eee->udp_mgmt_sock >= 0) closesocket(eee->udp_mgmt_sock); #ifndef SKIP_MULTICAST_PEERS_DISCOVERY if(eee->udp_multicast_sock >= 0) closesocket(eee->udp_multicast_sock); #endif clear_peer_list(&eee->pending_peers); clear_peer_list(&eee->known_peers); eee->transop.deinit(&eee->transop); eee->transop_lzo.deinit(&eee->transop_lzo); #ifdef HAVE_ZSTD eee->transop_zstd.deinit(&eee->transop_zstd); #endif edge_cleanup_routes(eee); destroy_network_traffic_filter(eee->network_traffic_filter); closeTraceFile(); free(eee); } /* ************************************** */ static int edge_init_sockets (n2n_edge_t *eee) { if(eee->udp_mgmt_sock >= 0) closesocket(eee->udp_mgmt_sock); #ifndef SKIP_MULTICAST_PEERS_DISCOVERY if(eee->udp_multicast_sock >= 0) closesocket(eee->udp_multicast_sock); #endif eee->udp_mgmt_sock = open_socket(eee->conf.mgmt_port, INADDR_LOOPBACK, 0 /* UDP */); if(eee->udp_mgmt_sock < 0) { traceEvent(TRACE_ERROR, "failed to bind management UDP port %u", eee->conf.mgmt_port); return(-2); } #ifndef SKIP_MULTICAST_PEERS_DISCOVERY /* Populate the multicast group for local edge */ eee->multicast_peer.family = AF_INET; eee->multicast_peer.port = N2N_MULTICAST_PORT; eee->multicast_peer.addr.v4[0] = 224; /* N2N_MULTICAST_GROUP */ eee->multicast_peer.addr.v4[1] = 0; eee->multicast_peer.addr.v4[2] = 0; eee->multicast_peer.addr.v4[3] = 68; eee->udp_multicast_sock = open_socket(N2N_MULTICAST_PORT, INADDR_ANY, 0 /* UDP */); if(eee->udp_multicast_sock < 0) return(-3); else { u_int enable_reuse = 1; /* allow multiple sockets to use the same PORT number */ setsockopt(eee->udp_multicast_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&enable_reuse, sizeof(enable_reuse)); #ifdef SO_REUSEPORT /* no SO_REUSEPORT in Windows / old linux versions */ setsockopt(eee->udp_multicast_sock, SOL_SOCKET, SO_REUSEPORT, &enable_reuse, sizeof(enable_reuse)); #endif } #endif return(0); } /* ************************************** */ #ifdef __linux__ static uint32_t get_gateway_ip () { FILE *fd; char *token = NULL; char *gateway_ip_str = NULL; char buf[256]; uint32_t gateway = 0; if(!(fd = fopen("/proc/net/route", "r"))) return(0); while(fgets(buf, sizeof(buf), fd)) { if(strtok(buf, "\t") && (token = strtok(NULL, "\t")) && (!strcmp(token, "00000000"))) { token = strtok(NULL, "\t"); if(token) { struct in_addr addr; addr.s_addr = strtoul(token, NULL, 16); gateway_ip_str = inet_ntoa(addr); if(gateway_ip_str) { gateway = addr.s_addr; break; } } } } fclose(fd); return(gateway); } static char* route_cmd_to_str (int cmd, const n2n_route_t *route, char *buf, size_t bufsize) { const char *cmd_str; struct in_addr addr; char netbuf[64], gwbuf[64]; switch(cmd) { case RTM_NEWROUTE: cmd_str = "Add"; break; case RTM_DELROUTE: cmd_str = "Delete"; break; default: cmd_str = "?"; } addr.s_addr = route->net_addr; inet_ntop(AF_INET, &addr, netbuf, sizeof(netbuf)); addr.s_addr = route->gateway; inet_ntop(AF_INET, &addr, gwbuf, sizeof(gwbuf)); snprintf(buf, bufsize, "%s %s/%d via %s", cmd_str, netbuf, route->net_bitlen, gwbuf); return(buf); } /* Adapted from https://olegkutkov.me/2019/08/29/modifying-linux-network-routes-using-netlink/ */ #define NLMSG_TAIL(nmsg) \ ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) /* Add new data to rtattr */ static int rtattr_add (struct nlmsghdr *n, int maxlen, int type, const void *data, int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; if(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { traceEvent(TRACE_ERROR, "rtattr_add error: message exceeded bound of %d\n", maxlen); return -1; } rta = NLMSG_TAIL(n); rta->rta_type = type; rta->rta_len = len; if(alen) memcpy(RTA_DATA(rta), data, alen); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); return 0; } static int routectl (int cmd, int flags, n2n_route_t *route, int if_idx) { int rv = -1; int rv2; char nl_buf[8192]; /* >= 8192 to avoid truncation, see "man 7 netlink" */ char route_buf[256]; struct iovec iov; struct msghdr msg; struct sockaddr_nl sa; uint8_t read_reply = 1; int nl_sock; struct { struct nlmsghdr n; struct rtmsg r; char buf[4096]; } nl_request; if((nl_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { traceEvent(TRACE_ERROR, "netlink socket creation failed [%d]: %s", errno, strerror(errno)); return(-1); } /* Subscribe to route change events */ iov.iov_base = nl_buf; iov.iov_len = sizeof(nl_buf); memset(&sa, 0, sizeof(sa)); sa.nl_family = PF_NETLINK; sa.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_NOTIFY; sa.nl_pid = getpid(); memset(&msg, 0, sizeof(msg)); msg.msg_name = &sa; msg.msg_namelen = sizeof(sa); msg.msg_iov = &iov; msg.msg_iovlen = 1; /* Subscribe to route events */ if(bind(nl_sock, (struct sockaddr*)&sa, sizeof(sa)) == -1) { traceEvent(TRACE_ERROR, "netlink socket bind failed [%d]: %s", errno, strerror(errno)); goto out; } /* Initialize request structure */ memset(&nl_request, 0, sizeof(nl_request)); nl_request.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nl_request.n.nlmsg_flags = NLM_F_REQUEST | flags; nl_request.n.nlmsg_type = cmd; nl_request.r.rtm_family = AF_INET; nl_request.r.rtm_table = RT_TABLE_MAIN; nl_request.r.rtm_scope = RT_SCOPE_NOWHERE; /* Set additional flags if NOT deleting route */ if(cmd != RTM_DELROUTE) { nl_request.r.rtm_protocol = RTPROT_BOOT; nl_request.r.rtm_type = RTN_UNICAST; } nl_request.r.rtm_family = AF_INET; nl_request.r.rtm_dst_len = route->net_bitlen; /* Select scope, for simplicity we supports here only IPv6 and IPv4 */ if(nl_request.r.rtm_family == AF_INET6) nl_request.r.rtm_scope = RT_SCOPE_UNIVERSE; else nl_request.r.rtm_scope = RT_SCOPE_LINK; /* Set gateway */ if(route->net_bitlen) { if(rtattr_add(&nl_request.n, sizeof(nl_request), RTA_GATEWAY, &route->gateway, 4) < 0) goto out; nl_request.r.rtm_scope = 0; nl_request.r.rtm_family = AF_INET; } /* Don't set destination and interface in case of default gateways */ if(route->net_bitlen) { /* Set destination network */ if(rtattr_add(&nl_request.n, sizeof(nl_request), /*RTA_NEWDST*/ RTA_DST, &route->net_addr, 4) < 0) goto out; /* Set interface */ if(if_idx > 0) { if(rtattr_add(&nl_request.n, sizeof(nl_request), RTA_OIF, &if_idx, sizeof(int)) < 0) goto out; } } /* Send message to the netlink */ if((rv2 = send(nl_sock, &nl_request, sizeof(nl_request), 0)) != sizeof(nl_request)) { traceEvent(TRACE_ERROR, "netlink send failed [%d]: %s", errno, strerror(errno)); goto out; } /* Wait for the route notification. Assume that the first reply we get is the correct one. */ traceEvent(TRACE_DEBUG, "waiting for netlink response..."); while(read_reply) { ssize_t len = recvmsg(nl_sock, &msg, 0); struct nlmsghdr *nh; for(nh = (struct nlmsghdr *)nl_buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { /* Stop after the first reply */ read_reply = 0; if(nh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *err = NLMSG_DATA(nh); int errcode = err->error; if(errcode < 0) errcode = -errcode; /* Ignore EEXIST as existing rules are ok */ if(errcode != EEXIST) { traceEvent(TRACE_ERROR, "[err=%d] route: %s", errcode, route_cmd_to_str(cmd, route, route_buf, sizeof(route_buf))); goto out; } } if(nh->nlmsg_type == NLMSG_DONE) break; if(nh->nlmsg_type == cmd) { traceEvent(TRACE_DEBUG, "Found netlink reply"); break; } } } traceEvent(TRACE_DEBUG, route_cmd_to_str(cmd, route, route_buf, sizeof(route_buf))); rv = 0; out: close(nl_sock); return(rv); } #endif /* ************************************** */ #ifdef __linux__ static int edge_init_routes_linux (n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_routes) { int i; for(i = 0; inet_addr == 0) && (route->net_bitlen == 0)) { /* This is a default gateway rule. We need to: * * 1. Add a route to the supernode via the host internet gateway * 2. Add the new default gateway route * * Instead of modifying the system default gateway, we use the trick * of adding a route to the networks 0.0.0.0/1 and 128.0.0.0/1, thus * covering the whole IPv4 range. Such routes in linux take precedence * over the default gateway (0.0.0.0/0) since are more specific. * This leaves the default gateway unchanged so that after n2n is * stopped the cleanup is easier. * See https://github.com/zerotier/ZeroTierOne/issues/178#issuecomment-204599227 */ n2n_sock_t sn; n2n_route_t custom_route; uint32_t *a; if(eee->sn_route_to_clean) { traceEvent(TRACE_ERROR, "only one default gateway route allowed"); return(-1); } if(eee->conf.sn_num != 1) { traceEvent(TRACE_ERROR, "only one supernode supported with routes"); return(-1); } if(supernode2sock(&sn, eee->conf.supernodes->ip_addr) < 0) return(-1); if(sn.family != AF_INET) { traceEvent(TRACE_ERROR, "only IPv4 routes supported"); return(-1); } a = (u_int32_t*)sn.addr.v4; custom_route.net_addr = *a; custom_route.net_bitlen = 32; custom_route.gateway = get_gateway_ip(); if(!custom_route.gateway) { traceEvent(TRACE_ERROR, "could not determine the gateway IP address"); return(-1); } /* ip route add supernode via internet_gateway */ if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, -1) < 0) return(-1); /* Save the route to delete it when n2n is stopped */ eee->sn_route_to_clean = calloc(1, sizeof(n2n_route_t)); /* Store a copy of the rules into the runtime to delete it during shutdown */ if(eee->sn_route_to_clean) *eee->sn_route_to_clean = custom_route; /* ip route add 0.0.0.0/1 via n2n_gateway */ custom_route.net_addr = 0; custom_route.net_bitlen = 1; custom_route.gateway = route->gateway; if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, eee->device.if_idx) < 0) return(-1); /* ip route add 128.0.0.0/1 via n2n_gateway */ custom_route.net_addr = 128; custom_route.net_bitlen = 1; custom_route.gateway = route->gateway; if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, eee->device.if_idx) < 0) return(-1); } else { /* ip route add net via n2n_gateway */ if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, route, eee->device.if_idx) < 0) return(-1); } } return(0); } #endif /* ************************************** */ #ifdef WIN32 static int edge_init_routes_win (n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_routes, uint8_t verb /* 0 = add, 1 = delete */) { int i; struct in_addr net_addr, gateway; char c_net_addr[32]; char c_gateway[32]; char c_interface[32]; char c_verb[32]; char cmd[256]; for(i = 0; i < num_routes; i++) { n2n_route_t *route = &routes[i]; if((route->net_addr == 0) && (route->net_bitlen == 0)) { // REVISIT: there might be a chance to get it working on Windows following the hints at // https://docs.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipinterface_row // // " The DisableDefaultRoutes member of the MIB_IPINTERFACE_ROW structure can be used to disable // using the default route on an interface. This member can be used as a security measure by // VPN clients to restrict split tunneling when split tunneling is not required by the VPN client. // A VPN client can call the SetIpInterfaceEntry function to set the DisableDefaultRoutes member // to TRUE when required. A VPN client can query the current state of the DisableDefaultRoutes // member by calling the GetIpInterfaceEntry function. " traceEvent(TRACE_WARNING, "the 0.0.0.0/0 route settings are not supported on Windows"); return(-1); } else { /* ip route add net via n2n_gateway */ memcpy(&net_addr, &(route->net_addr), sizeof(net_addr)); memcpy(&gateway, &(route->gateway), sizeof(gateway)); _snprintf(c_net_addr, sizeof(c_net_addr), inet_ntoa(net_addr)); _snprintf(c_gateway, sizeof(c_gateway), inet_ntoa(gateway)); _snprintf(c_interface, sizeof(c_interface), "if %u", eee->device.if_idx); _snprintf(c_verb, sizeof(c_verb), verb ? "delete" : "add"); _snprintf(cmd, sizeof(cmd), "route %s %s/%d %s %s > nul", c_verb, c_net_addr, route->net_bitlen, c_gateway, c_interface); traceEvent(TRACE_NORMAL, "ROUTE CMD = '%s'\n", cmd); system(cmd); } } return (0); } #endif // WIN32 /* ************************************** */ /* Add the user-provided routes to the linux routing table. Network routes * are bound to the n2n TAP device, so they are automatically removed when * the TAP device is destroyed. */ int edge_init_routes (n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_routes) { #ifdef __linux__ return edge_init_routes_linux(eee, routes, num_routes); #endif #ifdef WIN32 return edge_init_routes_win(eee, routes, num_routes, 0 /* add */); #endif return 0; } /* ************************************** */ static void edge_cleanup_routes (n2n_edge_t *eee) { #ifdef __linux__ if(eee->sn_route_to_clean) { /* ip route del supernode via internet_gateway */ routectl(RTM_DELROUTE, 0, eee->sn_route_to_clean, -1); free(eee->sn_route_to_clean); } #endif #ifdef WIN32 edge_init_routes_win(eee, eee->conf.routes, eee->conf.num_routes, 1 /* del */); #endif } /* ************************************** */ void edge_init_conf_defaults (n2n_edge_conf_t *conf) { char *tmp_string; memset(conf, 0, sizeof(*conf)); conf->bind_address = INADDR_ANY; /* any address */ conf->local_port = 0 /* any port */; conf->preferred_sock.family = AF_INVALID; conf->mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */ conf->transop_id = N2N_TRANSFORM_ID_NULL; conf->header_encryption = HEADER_ENCRYPTION_NONE; conf->compression = N2N_COMPRESSION_ID_NONE; conf->drop_multicast = 1; conf->allow_p2p = 1; conf->disable_pmtu_discovery = 1; conf->register_interval = REGISTER_SUPER_INTERVAL_DFL; conf->tuntap_ip_mode = TUNTAP_IP_MODE_SN_ASSIGN; /* reserve possible last char as null terminator. */ gethostname((char*)conf->dev_desc, N2N_DESC_SIZE-1); if(getenv("N2N_KEY")) { conf->encrypt_key = strdup(getenv("N2N_KEY")); conf->transop_id = N2N_TRANSFORM_ID_AES; } if(getenv("N2N_COMMUNITY")) { strncpy((char*)conf->community_name, getenv("N2N_COMMUNITY"), N2N_COMMUNITY_SIZE); conf->community_name[N2N_COMMUNITY_SIZE - 1] = '\0'; } if(getenv("N2N_PASSWORD")) { conf->shared_secret = calloc(1, sizeof(n2n_private_public_key_t)); if(conf->shared_secret) generate_private_key(*(conf->shared_secret), getenv("N2N_PASSWORD")); } tmp_string = calloc(1, strlen(N2N_MGMT_PASSWORD) + 1); if(tmp_string) { strncpy((char*)tmp_string, N2N_MGMT_PASSWORD, strlen(N2N_MGMT_PASSWORD) + 1); conf->mgmt_password_hash = pearson_hash_64((uint8_t*)tmp_string, strlen(N2N_MGMT_PASSWORD)); free(tmp_string); } #if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP) conf->port_forwarding = 1; #endif // HAVE_MINIUPNP || HAVE_NATPMP conf->sn_selection_strategy = SN_SELECTION_STRATEGY_LOAD; conf->metric = 0; } /* ************************************** */ void edge_term_conf (n2n_edge_conf_t *conf) { if(conf->routes) free(conf->routes); if(conf->encrypt_key) free(conf->encrypt_key); if(conf->network_traffic_filter_rules) { filter_rule_t *el = 0, *tmp = 0; HASH_ITER(hh, conf->network_traffic_filter_rules, el, tmp) { HASH_DEL(conf->network_traffic_filter_rules, el); free(el); } } } /* ************************************** */ const n2n_edge_conf_t* edge_get_conf (const n2n_edge_t *eee) { return(&eee->conf); } /* ************************************** */ int edge_conf_add_supernode (n2n_edge_conf_t *conf, const char *ip_and_port) { struct peer_info *sn; n2n_sock_t *sock; int skip_add; int rv = -1; sock = (n2n_sock_t*)calloc(1,sizeof(n2n_sock_t)); rv = supernode2sock(sock, ip_and_port); if(rv < -2) { /* we accept resolver failure as it might resolve later */ traceEvent(TRACE_WARNING, "invalid supernode parameter."); free(sock); return 1; } skip_add = SN_ADD; sn = add_sn_to_list_by_mac_or_sock(&(conf->supernodes), sock, null_mac, &skip_add); if(sn != NULL) { sn->ip_addr = calloc(1, N2N_EDGE_SN_HOST_SIZE); if(sn->ip_addr != NULL) { strncpy(sn->ip_addr, ip_and_port, N2N_EDGE_SN_HOST_SIZE - 1); memcpy(&(sn->sock), sock, sizeof(n2n_sock_t)); memcpy(sn->mac_addr, null_mac, sizeof(n2n_mac_t)); sn->purgeable = SN_UNPURGEABLE; } } free(sock); traceEvent(TRACE_NORMAL, "adding supernode = %s", sn->ip_addr); conf->sn_num++; return 0; } /* ************************************** */ int quick_edge_init (char *device_name, char *community_name, char *encrypt_key, char *device_mac, char *local_ip_address, char *supernode_ip_address_port, int *keep_on_running) { tuntap_dev tuntap; n2n_edge_t *eee; n2n_edge_conf_t conf; int rv; /* Setup the configuration */ edge_init_conf_defaults(&conf); conf.encrypt_key = encrypt_key; conf.transop_id = N2N_TRANSFORM_ID_AES; conf.compression = N2N_COMPRESSION_ID_NONE; snprintf((char*)conf.community_name, sizeof(conf.community_name), "%s", community_name); edge_conf_add_supernode(&conf, supernode_ip_address_port); /* Validate configuration */ if(edge_verify_conf(&conf) != 0) return(-1); /* Open the tuntap device */ if(tuntap_open(&tuntap, device_name, "static", local_ip_address, "255.255.255.0", device_mac, DEFAULT_MTU #ifdef WIN32 , 0 #endif ) < 0) return(-2); /* Init edge */ if((eee = edge_init(&conf, &rv)) == NULL) goto quick_edge_init_end; eee->keep_running = keep_on_running; rv = run_edge_loop(eee); edge_term(eee); edge_term_conf(&conf); quick_edge_init_end: tuntap_close(&tuntap); return(rv); } /* ************************************** */ ntop-n2n-90215bd/src/edge_utils_win32.c000066400000000000000000000102161422132035700176150ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #ifdef WIN32 #include "edge_utils_win32.h" /* ************************************** */ static DWORD* tunReadThread (LPVOID lpArg) { struct tunread_arg *arg = (struct tunread_arg*)lpArg; while(*arg->eee->keep_running) { edge_read_from_tap(arg->eee); } return((DWORD*)NULL); } /* ************************************** */ /** Start a second thread in Windows because TUNTAP interfaces do not expose * file descriptors. */ HANDLE startTunReadThread (struct tunread_arg *arg) { DWORD dwThreadId; return(CreateThread(NULL, /* security attributes */ 0, /* use default stack size */ (LPTHREAD_START_ROUTINE)tunReadThread, /* thread function */ (void*)arg, /* argument to thread function */ 0, /* thread creation flags */ &dwThreadId)); /* thread id out */ } int get_best_interface_ip (n2n_edge_t * eee, dec_ip_str_t ip_addr){ DWORD interface_index = -1; DWORD dwRetVal = 0; PIP_ADAPTER_INFO pAdapterInfo = NULL, pAdapter = NULL; macstr_t mac_buf; ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); dwRetVal = GetBestInterface(*(IPAddr*)(&eee->curr_sn->sock.addr.v4), &interface_index); if(dwRetVal != NO_ERROR) return -1; pAdapterInfo = (PIP_ADAPTER_INFO)malloc(ulOutBufLen); if(pAdapterInfo == NULL) { traceEvent(TRACE_INFO, "Error allocating memory needed to call GetAdaptersInfo\n"); return -1; } dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); if(dwRetVal == ERROR_BUFFER_OVERFLOW) { pAdapterInfo = (PIP_ADAPTER_INFO)realloc(pAdapterInfo, ulOutBufLen); if(pAdapterInfo == NULL) { traceEvent(TRACE_INFO, "Error allocating memory needed to call GetAdaptersInfo\n"); return -1; } } dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); // hexdump((uint8_t*)pAdapterInfo, ulOutBufLen); if(dwRetVal == NO_ERROR) { for(pAdapter = pAdapterInfo; pAdapter != NULL; pAdapter = pAdapter->Next) { if(pAdapter->Index != interface_index) continue; traceEvent(TRACE_DEBUG, "Adapter Index: %ld\n", pAdapter->Index); traceEvent(TRACE_DEBUG, "Combo Index: %ld\n", pAdapter->ComboIndex); traceEvent(TRACE_DEBUG, "Adapter Name: %s\n", pAdapter->AdapterName); traceEvent(TRACE_DEBUG, "Adapter Desc: %s\n", pAdapter->Description); traceEvent(TRACE_DEBUG, "Adapter Type: %u\n", pAdapter->Type); macaddr_str(mac_buf, pAdapter->Address); traceEvent(TRACE_DEBUG, "Adapter Addr: %s\n", mac_buf); traceEvent(TRACE_DEBUG, "DHCP Enabled: %u\n", pAdapter->DhcpEnabled); traceEvent(TRACE_DEBUG, "DHCP Server: %s\n", pAdapter->DhcpServer.IpAddress.String); traceEvent(TRACE_DEBUG, "IP Address: %s\n", pAdapter->IpAddressList.IpAddress.String); traceEvent(TRACE_DEBUG, "IP Mask: %s\n", pAdapter->IpAddressList.IpMask.String); traceEvent(TRACE_DEBUG, "Gateway: %s\n", pAdapter->GatewayList.IpAddress.String); strncpy(ip_addr, pAdapter->IpAddressList.IpAddress.String, sizeof(dec_ip_str_t)-1); } } else { traceEvent(TRACE_WARNING, "GetAdaptersInfo failed with error: %d\n", dwRetVal); } if(pAdapterInfo != NULL) { free(pAdapterInfo); pAdapterInfo = NULL; } return 0; } #endif ntop-n2n-90215bd/src/example_edge_embed.c000066400000000000000000000067721422132035700202360ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" static int keep_running; int main() { n2n_edge_conf_t conf; tuntap_dev tuntap; n2n_edge_t *eee; int rc; edge_init_conf_defaults(&conf); conf.allow_p2p = 1; // Whether to allow peer-to-peer communication conf.allow_routing = 1; // Whether to allow the edge to route packets to other edges snprintf((char *)conf.community_name, sizeof(conf.community_name), "%s", "mycommunity"); // Community to connect to conf.disable_pmtu_discovery = 1; // Whether to disable the path MTU discovery conf.drop_multicast = 0; // Whether to disable multicast conf.tuntap_ip_mode = TUNTAP_IP_MODE_SN_ASSIGN; // How to set the IP address conf.encrypt_key = "mysecret"; // Secret to decrypt & encrypt with conf.local_port = 0; // What port to use (0 = any port) conf.mgmt_port = N2N_EDGE_MGMT_PORT; // Edge management port (5644 by default) conf.register_interval = 1; // Interval for both UDP NAT hole punching and supernode registration conf.register_ttl = 1; // Interval for UDP NAT hole punching through supernode edge_conf_add_supernode(&conf, "localhost:1234"); // Supernode to connect to conf.tos = 16; // Type of service for sent packets conf.transop_id = N2N_TRANSFORM_ID_TWOFISH; // Use the twofish encryption if(edge_verify_conf(&conf) != 0) { return -1; } if(tuntap_open(&tuntap, "edge0", // Name of the device to create "static", // IP mode; static|dhcp "10.0.0.1", // Set ip address "255.255.255.0", // Netmask to use "DE:AD:BE:EF:01:10", // Set mac address DEFAULT_MTU // MTU to use #ifdef WIN32 , 0 #endif ) < 0) { return -1; } eee = edge_init(&conf, &rc); if(eee == NULL) { exit(1); } keep_running = 1; eee->keep_running = &keep_running; rc = run_edge_loop(eee); edge_term(eee); tuntap_close(&tuntap); return rc; } ntop-n2n-90215bd/src/example_edge_embed_quick_edge_init.c000066400000000000000000000032471422132035700234330ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" /* This tool demonstrates how to easily embed n2n on an existing application */ int main (int argc, char* argv[]) { char *device_name = (char*)"n2n0"; char *network_name = (char*)"mynetwork"; char *secret_key = (char*)"mysecret"; char *my_mac_address = (char*)"DE:AD:BE:EF:01:10"; char *my_ipv4_addr = (char*)"1.2.3.4"; char *supernode = (char*)"7.8.9.10:1234"; int keep_on_running = 1; /* Increase tracelevel to see what's happening */ setTraceLevel(10); /* Random seed */ n2n_srand(n2n_seed()); /* NOTE As the function below won't end, you should call it inside a separate thread */ return(quick_edge_init(device_name, network_name, secret_key, my_mac_address, my_ipv4_addr, supernode, &keep_on_running)); } ntop-n2n-90215bd/src/example_sn_embed.c000066400000000000000000000026751422132035700177500ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" static int keep_running; int main () { n2n_sn_t sss_node; int rc; sn_init_defaults(&sss_node); sss_node.daemon = 0; // Whether to daemonize sss_node.lport = 1234; // Main UDP listen port sss_node.sock = open_socket(sss_node.lport, INADDR_ANY, 0 /* UDP */); if(-1 == sss_node.sock) { exit(-2); } sss_node.mgmt_sock = open_socket(5645, INADDR_LOOPBACK, 0 /* UDP */); // Main UDP management port if(-1 == sss_node.mgmt_sock) { exit(-2); } sn_init(&sss_node); keep_running = 1; sss_node.keep_running = &keep_running; rc = run_sn_loop(&sss_node); sn_term(&sss_node); return rc; } ntop-n2n-90215bd/src/header_encryption.c000066400000000000000000000135301422132035700201530ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) int packet_header_decrypt (uint8_t packet[], uint16_t packet_len, char *community_name, he_context_t *ctx, he_context_t *ctx_iv, uint64_t *stamp) { // try community name as possible key and check for magic bytes "n2__" uint32_t magic = 0x6E320000; uint32_t test_magic; uint32_t checksum_high = 0; // check for magic // so, as a first step, decrypt last 4 bytes from where originally the community name would be speck_ctr((uint8_t*)&test_magic, &packet[16], 4, packet, (speck_context_t*)ctx); test_magic = be32toh(test_magic); //extract header length (lower 2 bytes) uint32_t header_len = test_magic - magic; if(header_len <= packet_len) { // decrypt the complete header speck_ctr(&packet[16], &packet[16], header_len - 16, packet, (speck_context_t*)ctx); // extract time stamp and un-xor actual checksum (calculated here) from it // if payload was altered (different checksum than original), time stamp verification will fail // use speck block cipher step (1 block == 128 bit == 16 bytes) speck_128_decrypt(packet, (speck_context_t*)ctx_iv); // extract the required data *stamp = be64toh(*(uint64_t*)&packet[4]); checksum_high = be32toh(*(uint32_t*)packet); // restore original packet order before calculating checksum memcpy(&packet[0], &packet[20], 4); memcpy(&packet[4], community_name, N2N_COMMUNITY_SIZE); uint64_t checksum = pearson_hash_64(packet, packet_len); if((checksum >> 32) != checksum_high) { traceEvent(TRACE_DEBUG, "packet_header_decrypt dropped a packet with invalid checksum."); // unsuccessful return 0; } *stamp = *stamp ^ (checksum << 32); // successful return 1; } else { // unsuccessful return 0; } } int packet_header_encrypt (uint8_t packet[], uint16_t header_len, uint16_t packet_len, he_context_t *ctx, he_context_t *ctx_iv, uint64_t stamp) { uint32_t *p32 = (uint32_t*)packet; uint64_t *p64 = (uint64_t*)packet; uint64_t checksum = 0; uint32_t magic = 0x6E320000; /* == ASCII "n2__" */ magic += header_len; if(packet_len < 24) { traceEvent(TRACE_DEBUG, "packet_header_encrypt dropped a packet too short to be valid."); return -1; } // we trust in the caller assuring header_len <= packet_len checksum = pearson_hash_64(packet, packet_len); // re-order packet p32[5] = p32[0]; // add time stamp, checksum, and random to form the pre-IV p64[0] = htobe64(checksum); p32[1] = p32[1] ^ htobe32((uint32_t)(stamp >> 32)); p32[2] = htobe32((uint32_t)stamp); p32[3] = n2n_rand(); // encrypt this pre-IV to IV speck_128_encrypt(packet, (speck_context_t*)ctx_iv); // place IV plus magic in packet p32[4] = htobe32(magic); // encrypt, starting from magic speck_ctr(&packet[16], &packet[16], header_len - 16, packet, (speck_context_t*)ctx); return 0; } void packet_header_setup_key (const char *community_name, he_context_t **ctx_static, he_context_t **ctx_dynamic, he_context_t **ctx_iv_static, he_context_t **ctx_iv_dynamic) { uint8_t key[16]; // for REGISTER_SUPER, REGISTER_SUPER_ACK, REGISTER_SUPER_NAK only; // for all other packets, same as static by default (changed by user/pw auth scheme // calling packet_header_change_dynamic_key later) pearson_hash_128(key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); if(!*ctx_static) *ctx_static = (he_context_t*)calloc(1, sizeof(speck_context_t)); speck_init((speck_context_t**)ctx_static, key, 128); if(!*ctx_dynamic) *ctx_dynamic = (he_context_t*)calloc(1, sizeof(speck_context_t)); speck_init((speck_context_t**)ctx_dynamic, key, 128); // hash again and use as key for IV encryption pearson_hash_128(key, key, sizeof(key)); if(!*ctx_iv_static) *ctx_iv_static = (he_context_t*)calloc(1, sizeof(speck_context_t)); speck_init((speck_context_t**)ctx_iv_static, key, 128); if(!*ctx_iv_dynamic) *ctx_iv_dynamic = (he_context_t*)calloc(1, sizeof(speck_context_t)); speck_init((speck_context_t**)ctx_iv_dynamic, key, 128); } void packet_header_change_dynamic_key (uint8_t *key_dynamic, he_context_t **ctx_dynamic, he_context_t **ctx_iv_dynamic) { uint8_t key[16]; pearson_hash_128(key, key_dynamic, N2N_AUTH_CHALLENGE_SIZE); // for REGISTER_SUPER, REGISTER_SUPER_ACK, REGISTER_SUPER_NAK only // for all other packets, same as static by default (changed by user/pw auth scheme) speck_init((speck_context_t**)ctx_dynamic, key, 128); // hash again and use as key for IV encryption // REMOVE as soon as checksum and replay protection get their own fields pearson_hash_128(key, key, sizeof(key)); speck_init((speck_context_t**)ctx_iv_dynamic, key, 128); } ntop-n2n-90215bd/src/hexdump.c000066400000000000000000000026641422132035700161310ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include #include "n2n.h" #include "hexdump.h" void fhexdump(unsigned int display_addr, void *in, int size, FILE *stream) { uint8_t *p = in; while(size>0) { int i; fprintf(stream, "%03x: ", display_addr); for (i = 0; i < 16; i++) { if (i < size) { fprintf(stream, "%02x", p[i]); } else { fprintf(stream, " "); } if (i==7) { fprintf(stream, " "); } else { fprintf(stream, " "); } } fprintf(stream, " |"); for (i = 0; i < 16; i++) { if (i < size) { char ch = p[i]; if (ch>=0x20 && ch<=0x7e) { fprintf(stream, "%c", ch); } else { fprintf(stream, " "); } } } fprintf(stream, "|\n"); size -= 16; display_addr += 16; p += 16; } } ntop-n2n-90215bd/src/minilzo.c000066400000000000000000006425521422132035700161460ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* minilzo.c -- mini subset of the LZO real-time data compression library This file is part of the LZO real-time data compression library. Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ /* * NOTE: * the full LZO package can be found at * http://www.oberhumer.com/opensource/lzo/ */ #define __LZO_IN_MINILZO 1 #if defined(LZO_CFG_FREESTANDING) # undef MINILZO_HAVE_CONFIG_H # define LZO_LIBC_FREESTANDING 1 # define LZO_OS_FREESTANDING 1 #endif #ifdef MINILZO_HAVE_CONFIG_H # include #endif #include #include #if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) #ifndef __LZODEFS_H_INCLUDED #define __LZODEFS_H_INCLUDED 1 #if defined(__CYGWIN32__) && !defined(__CYGWIN__) # define __CYGWIN__ __CYGWIN32__ #endif #if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) # define _ALL_SOURCE 1 #endif #if defined(__mips__) && defined(__R5900__) # if !defined(__LONG_MAX__) # define __LONG_MAX__ 9223372036854775807L # endif #endif #if 0 #elif !defined(__LZO_LANG_OVERRIDE) #if (defined(__clang__) || defined(__GNUC__)) && defined(__ASSEMBLER__) # if (__ASSEMBLER__+0) <= 0 # error "__ASSEMBLER__" # else # define LZO_LANG_ASSEMBLER 1 # endif #elif defined(__cplusplus) # if (__cplusplus+0) <= 0 # error "__cplusplus" # elif (__cplusplus < 199711L) # define LZO_LANG_CXX 1 # elif defined(_MSC_VER) && defined(_MSVC_LANG) && (_MSVC_LANG+0 >= 201402L) && 1 # define LZO_LANG_CXX _MSVC_LANG # else # define LZO_LANG_CXX __cplusplus # endif # define LZO_LANG_CPLUSPLUS LZO_LANG_CXX #else # if defined(__STDC_VERSION__) && (__STDC_VERSION__+0 >= 199409L) # define LZO_LANG_C __STDC_VERSION__ # else # define LZO_LANG_C 1 # endif #endif #endif #if !defined(LZO_CFG_NO_DISABLE_WUNDEF) #if defined(__ARMCC_VERSION) # pragma diag_suppress 193 #elif defined(__clang__) && defined(__clang_minor__) # pragma clang diagnostic ignored "-Wundef" #elif defined(__INTEL_COMPILER) # pragma warning(disable: 193) #elif defined(__KEIL__) && defined(__C166__) # pragma warning disable = 322 #elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) # if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) # pragma GCC diagnostic ignored "-Wundef" # endif #elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) # if ((_MSC_VER-0) >= 1300) # pragma warning(disable: 4668) # endif #endif #endif #if 0 && defined(__POCC__) && defined(_WIN32) # if (__POCC__ >= 400) # pragma warn(disable: 2216) # endif #endif #if 0 && defined(__WATCOMC__) # if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) # pragma warning 203 9 # endif #endif #if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) # pragma option -h #endif #if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) #ifndef _CRT_NONSTDC_NO_DEPRECATE #define _CRT_NONSTDC_NO_DEPRECATE 1 #endif #ifndef _CRT_NONSTDC_NO_WARNINGS #define _CRT_NONSTDC_NO_WARNINGS 1 #endif #ifndef _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE 1 #endif #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS 1 #endif #endif #if 0 #define LZO_0xffffUL 0xfffful #define LZO_0xffffffffUL 0xfffffffful #else #define LZO_0xffffUL 65535ul #define LZO_0xffffffffUL 4294967295ul #endif #define LZO_0xffffL LZO_0xffffUL #define LZO_0xffffffffL LZO_0xffffffffUL #if (LZO_0xffffL == LZO_0xffffffffL) # error "your preprocessor is broken 1" #endif #if (16ul * 16384ul != 262144ul) # error "your preprocessor is broken 2" #endif #if 0 #if (32767 >= 4294967295ul) # error "your preprocessor is broken 3" #endif #if (65535u >= 4294967295ul) # error "your preprocessor is broken 4" #endif #endif #if defined(__COUNTER__) # ifndef LZO_CFG_USE_COUNTER # define LZO_CFG_USE_COUNTER 1 # endif #else # undef LZO_CFG_USE_COUNTER #endif #if (UINT_MAX == LZO_0xffffL) #if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) # if !defined(MSDOS) # define MSDOS 1 # endif # if !defined(_MSDOS) # define _MSDOS 1 # endif #elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) # if (__VERSION == 520) && (MB_LEN_MAX == 1) # if !defined(__AZTEC_C__) # define __AZTEC_C__ __VERSION # endif # if !defined(__DOS__) # define __DOS__ 1 # endif # endif #endif #endif #if (UINT_MAX == LZO_0xffffL) #if defined(_MSC_VER) && defined(M_I86HM) # define ptrdiff_t long # define _PTRDIFF_T_DEFINED 1 #endif #endif #if (UINT_MAX == LZO_0xffffL) # undef __LZO_RENAME_A # undef __LZO_RENAME_B # if defined(__AZTEC_C__) && defined(__DOS__) # define __LZO_RENAME_A 1 # elif defined(_MSC_VER) && defined(MSDOS) # if (_MSC_VER < 600) # define __LZO_RENAME_A 1 # elif (_MSC_VER < 700) # define __LZO_RENAME_B 1 # endif # elif defined(__TSC__) && defined(__OS2__) # define __LZO_RENAME_A 1 # elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) # define __LZO_RENAME_A 1 # elif defined(__PACIFIC__) && defined(DOS) # if !defined(__far) # define __far far # endif # if !defined(__near) # define __near near # endif # endif # if defined(__LZO_RENAME_A) # if !defined(__cdecl) # define __cdecl cdecl # endif # if !defined(__far) # define __far far # endif # if !defined(__huge) # define __huge huge # endif # if !defined(__near) # define __near near # endif # if !defined(__pascal) # define __pascal pascal # endif # if !defined(__huge) # define __huge huge # endif # elif defined(__LZO_RENAME_B) # if !defined(__cdecl) # define __cdecl _cdecl # endif # if !defined(__far) # define __far _far # endif # if !defined(__huge) # define __huge _huge # endif # if !defined(__near) # define __near _near # endif # if !defined(__pascal) # define __pascal _pascal # endif # elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) # if !defined(__cdecl) # define __cdecl cdecl # endif # if !defined(__pascal) # define __pascal pascal # endif # endif # undef __LZO_RENAME_A # undef __LZO_RENAME_B #endif #if (UINT_MAX == LZO_0xffffL) #if defined(__AZTEC_C__) && defined(__DOS__) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 #elif defined(_MSC_VER) && defined(MSDOS) # if (_MSC_VER < 600) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 # endif # if (_MSC_VER < 700) # define LZO_BROKEN_INTEGRAL_PROMOTION 1 # define LZO_BROKEN_SIZEOF 1 # endif #elif defined(__PACIFIC__) && defined(DOS) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 #elif defined(__TURBOC__) && defined(__MSDOS__) # if (__TURBOC__ < 0x0150) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 # define LZO_BROKEN_INTEGRAL_PROMOTION 1 # endif # if (__TURBOC__ < 0x0200) # define LZO_BROKEN_SIZEOF 1 # endif # if (__TURBOC__ < 0x0400) && defined(__cplusplus) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # endif #elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # define LZO_BROKEN_SIZEOF 1 #endif #endif #if defined(__WATCOMC__) && (__WATCOMC__ < 900) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 #endif #if defined(_CRAY) && defined(_CRAY1) # define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 #endif #define LZO_PP_STRINGIZE(x) #x #define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) #define LZO_PP_CONCAT0() /*empty*/ #define LZO_PP_CONCAT1(a) a #define LZO_PP_CONCAT2(a,b) a ## b #define LZO_PP_CONCAT3(a,b,c) a ## b ## c #define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e #define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f #define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() #define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) #define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) #define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) #define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) #define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) #define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) #define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) #define LZO_PP_EMPTY /*empty*/ #define LZO_PP_EMPTY0() /*empty*/ #define LZO_PP_EMPTY1(a) /*empty*/ #define LZO_PP_EMPTY2(a,b) /*empty*/ #define LZO_PP_EMPTY3(a,b,c) /*empty*/ #define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ #define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ #define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ #define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ #if 1 #define LZO_CPP_STRINGIZE(x) #x #define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) #define LZO_CPP_CONCAT2(a,b) a ## b #define LZO_CPP_CONCAT3(a,b,c) a ## b ## c #define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e #define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f #define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) #define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) #define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) #define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) #define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) #define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) #endif #define __LZO_MASK_GEN(o,b) (((((o) << ((b)-((b)!=0))) - (o)) << 1) + (o)*((b)!=0)) #if 1 && defined(__cplusplus) # if !defined(__STDC_CONSTANT_MACROS) # define __STDC_CONSTANT_MACROS 1 # endif # if !defined(__STDC_LIMIT_MACROS) # define __STDC_LIMIT_MACROS 1 # endif #endif #if defined(__cplusplus) # define LZO_EXTERN_C extern "C" # define LZO_EXTERN_C_BEGIN extern "C" { # define LZO_EXTERN_C_END } #else # define LZO_EXTERN_C extern # define LZO_EXTERN_C_BEGIN /*empty*/ # define LZO_EXTERN_C_END /*empty*/ #endif #if !defined(__LZO_OS_OVERRIDE) #if (LZO_OS_FREESTANDING) # define LZO_INFO_OS "freestanding" #elif (LZO_OS_EMBEDDED) # define LZO_INFO_OS "embedded" #elif 1 && defined(__IAR_SYSTEMS_ICC__) # define LZO_OS_EMBEDDED 1 # define LZO_INFO_OS "embedded" #elif defined(__CYGWIN__) && defined(__GNUC__) # define LZO_OS_CYGWIN 1 # define LZO_INFO_OS "cygwin" #elif defined(__EMX__) && defined(__GNUC__) # define LZO_OS_EMX 1 # define LZO_INFO_OS "emx" #elif defined(__BEOS__) # define LZO_OS_BEOS 1 # define LZO_INFO_OS "beos" #elif defined(__Lynx__) # define LZO_OS_LYNXOS 1 # define LZO_INFO_OS "lynxos" #elif defined(__OS400__) # define LZO_OS_OS400 1 # define LZO_INFO_OS "os400" #elif defined(__QNX__) # define LZO_OS_QNX 1 # define LZO_INFO_OS "qnx" #elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" #elif defined(__BORLANDC__) && defined(__DPMI16__) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" #elif defined(__ZTC__) && defined(DOS386) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" #elif defined(__OS2__) || defined(__OS2V2__) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_OS216 1 # define LZO_INFO_OS "os216" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_OS2 1 # define LZO_INFO_OS "os2" # else # error "check your limits.h header" # endif #elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) # define LZO_OS_WIN64 1 # define LZO_INFO_OS "win64" #elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" #elif defined(__MWERKS__) && defined(__INTEL__) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" #elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_WIN16 1 # define LZO_INFO_OS "win16" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" # else # error "check your limits.h header" # endif #elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" # else # error "check your limits.h header" # endif #elif defined(__WATCOMC__) # if defined(__NT__) && (UINT_MAX == LZO_0xffffL) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" # elif defined(__NT__) && (__WATCOMC__ < 1100) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" # elif defined(__linux__) || defined(__LINUX__) # define LZO_OS_POSIX 1 # define LZO_INFO_OS "posix" # else # error "please specify a target using the -bt compiler option" # endif #elif defined(__palmos__) # define LZO_OS_PALMOS 1 # define LZO_INFO_OS "palmos" #elif defined(__TOS__) || defined(__atarist__) # define LZO_OS_TOS 1 # define LZO_INFO_OS "tos" #elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__) # define LZO_OS_MACCLASSIC 1 # define LZO_INFO_OS "macclassic" #elif defined(__VMS) # define LZO_OS_VMS 1 # define LZO_INFO_OS "vms" #elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PS2 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "ps2" #elif defined(__mips__) && defined(__psp__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PSP 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "psp" #else # define LZO_OS_POSIX 1 # define LZO_INFO_OS "posix" #endif #if (LZO_OS_POSIX) # if defined(_AIX) || defined(__AIX__) || defined(__aix__) # define LZO_OS_POSIX_AIX 1 # define LZO_INFO_OS_POSIX "aix" # elif defined(__FreeBSD__) # define LZO_OS_POSIX_FREEBSD 1 # define LZO_INFO_OS_POSIX "freebsd" # elif defined(__hpux__) || defined(__hpux) # define LZO_OS_POSIX_HPUX 1 # define LZO_INFO_OS_POSIX "hpux" # elif defined(__INTERIX) # define LZO_OS_POSIX_INTERIX 1 # define LZO_INFO_OS_POSIX "interix" # elif defined(__IRIX__) || defined(__irix__) # define LZO_OS_POSIX_IRIX 1 # define LZO_INFO_OS_POSIX "irix" # elif defined(__linux__) || defined(__linux) || defined(__LINUX__) # define LZO_OS_POSIX_LINUX 1 # define LZO_INFO_OS_POSIX "linux" # elif defined(__APPLE__) && defined(__MACH__) # if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) # define LZO_OS_POSIX_DARWIN 1040 # define LZO_INFO_OS_POSIX "darwin_iphone" # elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) # define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ # define LZO_INFO_OS_POSIX "darwin" # else # define LZO_OS_POSIX_DARWIN 1 # define LZO_INFO_OS_POSIX "darwin" # endif # define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN # elif defined(__minix__) || defined(__minix) # define LZO_OS_POSIX_MINIX 1 # define LZO_INFO_OS_POSIX "minix" # elif defined(__NetBSD__) # define LZO_OS_POSIX_NETBSD 1 # define LZO_INFO_OS_POSIX "netbsd" # elif defined(__OpenBSD__) # define LZO_OS_POSIX_OPENBSD 1 # define LZO_INFO_OS_POSIX "openbsd" # elif defined(__osf__) # define LZO_OS_POSIX_OSF 1 # define LZO_INFO_OS_POSIX "osf" # elif defined(__solaris__) || defined(__sun) # if defined(__SVR4) || defined(__svr4__) # define LZO_OS_POSIX_SOLARIS 1 # define LZO_INFO_OS_POSIX "solaris" # else # define LZO_OS_POSIX_SUNOS 1 # define LZO_INFO_OS_POSIX "sunos" # endif # elif defined(__ultrix__) || defined(__ultrix) # define LZO_OS_POSIX_ULTRIX 1 # define LZO_INFO_OS_POSIX "ultrix" # elif defined(_UNICOS) # define LZO_OS_POSIX_UNICOS 1 # define LZO_INFO_OS_POSIX "unicos" # else # define LZO_OS_POSIX_UNKNOWN 1 # define LZO_INFO_OS_POSIX "unknown" # endif #endif #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (UINT_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) # define LZO_CC_CILLY 1 # define LZO_INFO_CC "Cilly" # if defined(__CILLY__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) # else # define LZO_INFO_CCVER "unknown" # endif #elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) # define LZO_CC_SDCC 1 # define LZO_INFO_CC "sdcc" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) #elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) # define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) # define LZO_INFO_CC "Pathscale C" # define LZO_INFO_CCVER __PATHSCALE__ # if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) # define LZO_CC_INTELC __INTEL_COMPILER # define LZO_INFO_CC "Intel C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_INTELC_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__POCC__) && defined(_WIN32) # define LZO_CC_PELLESC 1 # define LZO_INFO_CC "Pelles C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) #elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) # define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else # define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_ARMCC __ARMCC_VERSION # define LZO_INFO_CC "ARM C Compiler" # define LZO_INFO_CCVER __VERSION__ #elif defined(__clang__) && defined(__c2__) && defined(__c2_version__) && defined(_MSC_VER) # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # define LZO_CC_CLANG_C2 _MSC_VER # define LZO_CC_CLANG_VENDOR_MICROSOFT 1 # define LZO_INFO_CC "clang/c2" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__c2_version__) #elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) # if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # else # define LZO_CC_CLANG 0x010000L # endif # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_CLANG_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif # if defined(__APPLE_CC__) # define LZO_CC_CLANG_VENDOR_APPLE 1 # define LZO_INFO_CC "clang/apple" # else # define LZO_CC_CLANG_VENDOR_LLVM 1 # define LZO_INFO_CC "clang" # endif # if defined(__clang_version__) # define LZO_INFO_CCVER __clang_version__ # else # define LZO_INFO_CCVER __VERSION__ # endif #elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_LLVM LZO_CC_LLVM_GNUC # define LZO_INFO_CC "llvm-gcc" # define LZO_INFO_CCVER __VERSION__ #elif defined(__ACK__) && defined(_ACK) # define LZO_CC_ACK 1 # define LZO_INFO_CC "Amsterdam Compiler Kit C" # define LZO_INFO_CCVER "unknown" #elif defined(__ARMCC_VERSION) && !defined(__GNUC__) # define LZO_CC_ARMCC __ARMCC_VERSION # define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION # define LZO_INFO_CC "ARM C Compiler" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) #elif defined(__AZTEC_C__) # define LZO_CC_AZTECC 1 # define LZO_INFO_CC "Aztec C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) #elif defined(__CODEGEARC__) # define LZO_CC_CODEGEARC 1 # define LZO_INFO_CC "CodeGear C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) #elif defined(__BORLANDC__) # define LZO_CC_BORLANDC 1 # define LZO_INFO_CC "Borland C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) #elif defined(_CRAYC) && defined(_RELEASE) # define LZO_CC_CRAYC 1 # define LZO_INFO_CC "Cray C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) #elif defined(__DMC__) && defined(__SC__) # define LZO_CC_DMC 1 # define LZO_INFO_CC "Digital Mars C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) #elif defined(__DECC) # define LZO_CC_DECC 1 # define LZO_INFO_CC "DEC C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) #elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) # define LZO_CC_GHS 1 # define LZO_INFO_CC "Green Hills C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_GHS_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__HIGHC__) # define LZO_CC_HIGHC 1 # define LZO_INFO_CC "MetaWare High C" # define LZO_INFO_CCVER "unknown" #elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) # define LZO_CC_HPACC __HP_aCC # define LZO_INFO_CC "HP aCC" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) #elif defined(__IAR_SYSTEMS_ICC__) # define LZO_CC_IARC 1 # define LZO_INFO_CC "IAR C" # if defined(__VER__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) # else # define LZO_INFO_CCVER "unknown" # endif #elif defined(__IBMC__) && ((__IBMC__-0) > 0) # define LZO_CC_IBMC __IBMC__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) #elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) # define LZO_CC_IBMC __IBMCPP__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) #elif defined(__KEIL__) && defined(__C166__) # define LZO_CC_KEILC 1 # define LZO_INFO_CC "Keil C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) #elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) # define LZO_CC_LCCWIN32 1 # define LZO_INFO_CC "lcc-win32" # define LZO_INFO_CCVER "unknown" #elif defined(__LCC__) # define LZO_CC_LCC 1 # define LZO_INFO_CC "lcc" # if defined(__LCC_VERSION__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) # else # define LZO_INFO_CCVER "unknown" # endif #elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) # define LZO_CC_MWERKS __MWERKS__ # define LZO_INFO_CC "Metrowerks C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) #elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) # define LZO_CC_NDPC 1 # define LZO_INFO_CC "Microway NDP C" # define LZO_INFO_CCVER "unknown" #elif defined(__PACIFIC__) # define LZO_CC_PACIFICC 1 # define LZO_INFO_CC "Pacific C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) #elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) # if defined(__PGIC_PATCHLEVEL__) # define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) # else # define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" # endif # define LZO_INFO_CC "Portland Group PGI C" #elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) # define LZO_CC_PGI 1 # define LZO_INFO_CC "Portland Group PGI C" # define LZO_INFO_CCVER "unknown" #elif defined(__PUREC__) && defined(__TOS__) # define LZO_CC_PUREC 1 # define LZO_INFO_CC "Pure C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) #elif defined(__SC__) && defined(__ZTC__) # define LZO_CC_SYMANTECC 1 # define LZO_INFO_CC "Symantec C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) #elif defined(__SUNPRO_C) # define LZO_INFO_CC "SunPro C" # if ((__SUNPRO_C-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_C # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) # else # define LZO_CC_SUNPROC 1 # define LZO_INFO_CCVER "unknown" # endif #elif defined(__SUNPRO_CC) # define LZO_INFO_CC "SunPro C" # if ((__SUNPRO_CC-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_CC # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) # else # define LZO_CC_SUNPROC 1 # define LZO_INFO_CCVER "unknown" # endif #elif defined(__TINYC__) # define LZO_CC_TINYC 1 # define LZO_INFO_CC "Tiny C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) #elif defined(__TSC__) # define LZO_CC_TOPSPEEDC 1 # define LZO_INFO_CC "TopSpeed C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) #elif defined(__WATCOMC__) # define LZO_CC_WATCOMC 1 # define LZO_INFO_CC "Watcom C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) #elif defined(__TURBOC__) # define LZO_CC_TURBOC 1 # define LZO_INFO_CC "Turbo C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) #elif defined(__ZTC__) # define LZO_CC_ZORTECHC 1 # define LZO_INFO_CC "Zortech C" # if ((__ZTC__-0) == 0x310) # define LZO_INFO_CCVER "0x310" # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) # endif #elif defined(__GNUC__) && defined(__VERSION__) # if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) # define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # elif defined(__GNUC_MINOR__) # define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # else # define LZO_CC_GNUC (__GNUC__ * 0x10000L) # endif # define LZO_INFO_CC "gcc" # define LZO_INFO_CCVER __VERSION__ #elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_MSC _MSC_VER # define LZO_INFO_CC "Microsoft C" # if defined(_MSC_FULL_VER) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) # endif #else # define LZO_CC_UNKNOWN 1 # define LZO_INFO_CC "unknown" # define LZO_INFO_CCVER "unknown" #endif #if (LZO_CC_GNUC) && defined(__OPEN64__) # if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) # define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) # define LZO_CC_OPEN64_GNUC LZO_CC_GNUC # endif #endif #if (LZO_CC_GNUC) && defined(__PCC__) # if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) # define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) # define LZO_CC_PCC_GNUC LZO_CC_GNUC # endif #endif #if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) # error "LZO_CC_MSC: _MSC_FULL_VER is not defined" #endif #if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) # if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) # if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) # define LZO_ARCH_CRAY_MPP 1 # elif defined(_CRAY1) # define LZO_ARCH_CRAY_PVP 1 # endif # endif #endif #if !defined(__LZO_ARCH_OVERRIDE) #if (LZO_ARCH_GENERIC) # define LZO_INFO_ARCH "generic" #elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086 1 # define LZO_INFO_ARCH "i086" #elif defined(__aarch64__) || defined(_M_ARM64) # define LZO_ARCH_ARM64 1 # define LZO_INFO_ARCH "arm64" #elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" #elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" #elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) # define LZO_ARCH_AMD64 1 # define LZO_INFO_ARCH "amd64" #elif defined(__arm__) || defined(_M_ARM) # define LZO_ARCH_ARM 1 # define LZO_INFO_ARCH "arm" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) # define LZO_ARCH_ARM 1 # define LZO_INFO_ARCH "arm" #elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) # define LZO_ARCH_AVR 1 # define LZO_INFO_ARCH "avr" #elif defined(__avr32__) || defined(__AVR32__) # define LZO_ARCH_AVR32 1 # define LZO_INFO_ARCH "avr32" #elif defined(__bfin__) # define LZO_ARCH_BLACKFIN 1 # define LZO_INFO_ARCH "blackfin" #elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) # define LZO_ARCH_C166 1 # define LZO_INFO_ARCH "c166" #elif defined(__cris__) # define LZO_ARCH_CRIS 1 # define LZO_INFO_ARCH "cris" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) # define LZO_ARCH_EZ80 1 # define LZO_INFO_ARCH "ez80" #elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) # define LZO_ARCH_H8300 1 # define LZO_INFO_ARCH "h8300" #elif defined(__hppa__) || defined(__hppa) # define LZO_ARCH_HPPA 1 # define LZO_INFO_ARCH "hppa" #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif (LZO_CC_ZORTECHC && defined(__I86__)) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) # define LZO_ARCH_IA64 1 # define LZO_INFO_ARCH "ia64" #elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) # define LZO_ARCH_M16C 1 # define LZO_INFO_ARCH "m16c" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) # define LZO_ARCH_M16C 1 # define LZO_INFO_ARCH "m16c" #elif defined(__m32r__) # define LZO_ARCH_M32R 1 # define LZO_INFO_ARCH "m32r" #elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) # define LZO_ARCH_M68K 1 # define LZO_INFO_ARCH "m68k" #elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) # define LZO_ARCH_MCS251 1 # define LZO_INFO_ARCH "mcs251" #elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) # define LZO_ARCH_MCS51 1 # define LZO_INFO_ARCH "mcs51" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) # define LZO_ARCH_MCS51 1 # define LZO_INFO_ARCH "mcs51" #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) # define LZO_ARCH_MIPS 1 # define LZO_INFO_ARCH "mips" #elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) # define LZO_ARCH_MSP430 1 # define LZO_INFO_ARCH "msp430" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) # define LZO_ARCH_MSP430 1 # define LZO_INFO_ARCH "msp430" #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__powerpc64__) || defined(__powerpc64) || defined(__ppc64__) || defined(__PPC64__) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__powerpc64le__) || defined(__powerpc64le) || defined(__ppc64le__) || defined(__PPC64LE__) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__riscv) # define LZO_ARCH_RISCV 1 # define LZO_INFO_ARCH "riscv" #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) # define LZO_ARCH_S390 1 # define LZO_INFO_ARCH "s390" #elif defined(__sh__) || defined(_M_SH) # define LZO_ARCH_SH 1 # define LZO_INFO_ARCH "sh" #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) # define LZO_ARCH_SPARC 1 # define LZO_INFO_ARCH "sparc" #elif defined(__SPU__) # define LZO_ARCH_SPU 1 # define LZO_INFO_ARCH "spu" #elif (UINT_MAX == LZO_0xffffL) && defined(__z80) # define LZO_ARCH_Z80 1 # define LZO_INFO_ARCH "z80" #elif (LZO_ARCH_CRAY_PVP) # if defined(_CRAYSV1) # define LZO_ARCH_CRAY_SV1 1 # define LZO_INFO_ARCH "cray_sv1" # elif (_ADDR64) # define LZO_ARCH_CRAY_T90 1 # define LZO_INFO_ARCH "cray_t90" # elif (_ADDR32) # define LZO_ARCH_CRAY_YMP 1 # define LZO_INFO_ARCH "cray_ymp" # else # define LZO_ARCH_CRAY_XMP 1 # define LZO_INFO_ARCH "cray_xmp" # endif #else # define LZO_ARCH_UNKNOWN 1 # define LZO_INFO_ARCH "unknown" #endif #endif #if !defined(LZO_ARCH_ARM_THUMB2) #if (LZO_ARCH_ARM) # if defined(__thumb__) || defined(__thumb) || defined(_M_THUMB) # if defined(__thumb2__) # define LZO_ARCH_ARM_THUMB2 1 # elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4) # define LZO_ARCH_ARM_THUMB2 1 # elif 1 && defined(_MSC_VER) && defined(_M_THUMB) && ((_M_THUMB)+0 >= 7) # define LZO_ARCH_ARM_THUMB2 1 # endif # endif #endif #endif #if (LZO_ARCH_ARM_THUMB2) # undef LZO_INFO_ARCH # define LZO_INFO_ARCH "arm_thumb2" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) # error "FIXME - missing define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) # error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) # error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" #endif #if (LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && defined(BLX286)) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) # define LZO_ARCH_I086PM 1 #endif #if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) # define LZO_ARCH_X64 1 #elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_AMD64 1 #endif #if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) # define LZO_ARCH_AARCH64 1 #elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_ARM64 1 #endif #if (LZO_ARCH_I386 && !LZO_ARCH_X86) # define LZO_ARCH_X86 1 #elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_I386 1 #endif #if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086PM && !LZO_ARCH_I086) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086) # if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_I386) # if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) # error "unexpected configuration - check your compiler defines" # endif # if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_AMD64 || LZO_ARCH_I386) # if !defined(LZO_TARGET_FEATURE_SSE2) # if defined(__SSE2__) # define LZO_TARGET_FEATURE_SSE2 1 # elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) # define LZO_TARGET_FEATURE_SSE2 1 # elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64) # define LZO_TARGET_FEATURE_SSE2 1 # endif # endif # if !defined(LZO_TARGET_FEATURE_SSSE3) # if (LZO_TARGET_FEATURE_SSE2) # if defined(__SSSE3__) # define LZO_TARGET_FEATURE_SSSE3 1 # elif defined(_MSC_VER) && defined(__AVX__) # define LZO_TARGET_FEATURE_SSSE3 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_SSE4_2) # if (LZO_TARGET_FEATURE_SSSE3) # if defined(__SSE4_2__) # define LZO_TARGET_FEATURE_SSE4_2 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_AVX) # if (LZO_TARGET_FEATURE_SSSE3) # if defined(__AVX__) # define LZO_TARGET_FEATURE_AVX 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_AVX2) # if (LZO_TARGET_FEATURE_AVX) # if defined(__AVX2__) # define LZO_TARGET_FEATURE_AVX2 1 # endif # endif # endif #endif #if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM) # if !defined(LZO_TARGET_FEATURE_NEON) # if defined(__ARM_NEON) && ((__ARM_NEON)+0) # define LZO_TARGET_FEATURE_NEON 1 # elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0) # define LZO_TARGET_FEATURE_NEON 1 # elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0) # define LZO_TARGET_FEATURE_NEON 1 # endif # endif #elif (LZO_ARCH_ARM64) # if !defined(LZO_TARGET_FEATURE_NEON) # if 1 # define LZO_TARGET_FEATURE_NEON 1 # endif # endif #endif #if 0 #elif !defined(__LZO_MM_OVERRIDE) #if (LZO_ARCH_I086) #if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" #endif #if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) # define LZO_MM_TINY 1 #elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) # define LZO_MM_HUGE 1 #elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) # define LZO_MM_SMALL 1 #elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) # define LZO_MM_MEDIUM 1 #elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) # define LZO_MM_COMPACT 1 #elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) # define LZO_MM_LARGE 1 #elif (LZO_CC_AZTECC) # if defined(_LARGE_CODE) && defined(_LARGE_DATA) # define LZO_MM_LARGE 1 # elif defined(_LARGE_CODE) # define LZO_MM_MEDIUM 1 # elif defined(_LARGE_DATA) # define LZO_MM_COMPACT 1 # else # define LZO_MM_SMALL 1 # endif #elif (LZO_CC_ZORTECHC && defined(__VCM__)) # define LZO_MM_LARGE 1 #else # error "unknown LZO_ARCH_I086 memory model" #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) #define LZO_HAVE_MM_HUGE_PTR 1 #define LZO_HAVE_MM_HUGE_ARRAY 1 #if (LZO_MM_TINY) # undef LZO_HAVE_MM_HUGE_ARRAY #endif #if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) # undef LZO_HAVE_MM_HUGE_PTR # undef LZO_HAVE_MM_HUGE_ARRAY #elif (LZO_CC_DMC || LZO_CC_SYMANTECC) # undef LZO_HAVE_MM_HUGE_ARRAY #elif (LZO_CC_MSC && defined(_QC)) # undef LZO_HAVE_MM_HUGE_ARRAY # if (_MSC_VER < 600) # undef LZO_HAVE_MM_HUGE_PTR # endif #elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) # undef LZO_HAVE_MM_HUGE_ARRAY #endif #if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) # if (LZO_OS_DOS16) # error "unexpected configuration - check your compiler defines" # elif (LZO_CC_ZORTECHC) # else # error "unexpected configuration - check your compiler defines" # endif #endif #if defined(__cplusplus) extern "C" { #endif #if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) # define LZO_MM_AHSHIFT 12 #elif (LZO_CC_WATCOMC) extern unsigned char _HShift; # define LZO_MM_AHSHIFT ((unsigned) _HShift) #else # error "FIXME - implement LZO_MM_AHSHIFT" #endif #if defined(__cplusplus) } #endif #endif #elif (LZO_ARCH_C166) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_C166 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_C166 __MODEL__" #endif #elif (LZO_ARCH_MCS251) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_MCS251 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_MCS251 __MODEL__" #endif #elif (LZO_ARCH_MCS51) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_MCS51 __MODEL__" #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_MCS51 __MODEL__" #endif #elif (LZO_ARCH_CRAY_PVP) # define LZO_MM_PVP 1 #else # define LZO_MM_FLAT 1 #endif #if (LZO_MM_COMPACT) # define LZO_INFO_MM "compact" #elif (LZO_MM_FLAT) # define LZO_INFO_MM "flat" #elif (LZO_MM_HUGE) # define LZO_INFO_MM "huge" #elif (LZO_MM_LARGE) # define LZO_INFO_MM "large" #elif (LZO_MM_MEDIUM) # define LZO_INFO_MM "medium" #elif (LZO_MM_PVP) # define LZO_INFO_MM "pvp" #elif (LZO_MM_SMALL) # define LZO_INFO_MM "small" #elif (LZO_MM_TINY) # define LZO_INFO_MM "tiny" #else # error "unknown memory model" #endif #endif #if !defined(__lzo_gnuc_extension__) #if (LZO_CC_GNUC >= 0x020800ul) # define __lzo_gnuc_extension__ __extension__ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_gnuc_extension__ __extension__ #elif (LZO_CC_IBMC >= 600) # define __lzo_gnuc_extension__ __extension__ #endif #endif #if !defined(__lzo_gnuc_extension__) # define __lzo_gnuc_extension__ /*empty*/ #endif #if !defined(lzo_has_builtin) #if (LZO_CC_CLANG) && defined(__has_builtin) # define lzo_has_builtin __has_builtin #endif #endif #if !defined(lzo_has_builtin) # define lzo_has_builtin(x) 0 #endif #if !defined(lzo_has_attribute) #if (LZO_CC_CLANG) && defined(__has_attribute) # define lzo_has_attribute __has_attribute #endif #endif #if !defined(lzo_has_attribute) # define lzo_has_attribute(x) 0 #endif #if !defined(lzo_has_declspec_attribute) #if (LZO_CC_CLANG) && defined(__has_declspec_attribute) # define lzo_has_declspec_attribute __has_declspec_attribute #endif #endif #if !defined(lzo_has_declspec_attribute) # define lzo_has_declspec_attribute(x) 0 #endif #if !defined(lzo_has_feature) #if (LZO_CC_CLANG) && defined(__has_feature) # define lzo_has_feature __has_feature #endif #endif #if !defined(lzo_has_feature) # define lzo_has_feature(x) 0 #endif #if !defined(lzo_has_extension) #if (LZO_CC_CLANG) && defined(__has_extension) # define lzo_has_extension __has_extension #elif (LZO_CC_CLANG) && defined(__has_feature) # define lzo_has_extension __has_feature #endif #endif #if !defined(lzo_has_extension) # define lzo_has_extension(x) 0 #endif #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 # elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 # else # define LZO_CFG_USE_NEW_STYLE_CASTS 1 # endif #endif #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 #endif #if !defined(__cplusplus) # if defined(LZO_CFG_USE_NEW_STYLE_CASTS) # undef LZO_CFG_USE_NEW_STYLE_CASTS # endif # define LZO_CFG_USE_NEW_STYLE_CASTS 0 #endif #if !defined(LZO_REINTERPRET_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast (e)) # endif #endif #if !defined(LZO_REINTERPRET_CAST) # define LZO_REINTERPRET_CAST(t,e) ((t) (e)) #endif #if !defined(LZO_STATIC_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_STATIC_CAST(t,e) (static_cast (e)) # endif #endif #if !defined(LZO_STATIC_CAST) # define LZO_STATIC_CAST(t,e) ((t) (e)) #endif #if !defined(LZO_STATIC_CAST2) # define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) #endif #if !defined(LZO_UNCONST_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNCONST_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNCONST_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) # endif #endif #if !defined(LZO_UNCONST_CAST) # define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) #endif #if !defined(LZO_UNCONST_VOLATILE_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) # endif #endif #if !defined(LZO_UNCONST_VOLATILE_CAST) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) #endif #if !defined(LZO_UNVOLATILE_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNVOLATILE_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) # endif #endif #if !defined(LZO_UNVOLATILE_CAST) # define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) #endif #if !defined(LZO_UNVOLATILE_CONST_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) # endif #endif #if !defined(LZO_UNVOLATILE_CONST_CAST) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) #endif #if !defined(LZO_PCAST) # if (LZO_HAVE_MM_HUGE_PTR) # define LZO_PCAST(t,e) ((t) (e)) # endif #endif #if !defined(LZO_PCAST) # define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) #endif #if !defined(LZO_CCAST) # if (LZO_HAVE_MM_HUGE_PTR) # define LZO_CCAST(t,e) ((t) (e)) # endif #endif #if !defined(LZO_CCAST) # define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) #endif #if !defined(LZO_ICONV) # define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(LZO_ICAST) # define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(LZO_ITRUNC) # define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(__lzo_cte) # if (LZO_CC_MSC || LZO_CC_WATCOMC) # define __lzo_cte(e) ((void)0,(e)) # elif 1 # define __lzo_cte(e) ((void)0,(e)) # endif #endif #if !defined(__lzo_cte) # define __lzo_cte(e) (e) #endif #if !defined(LZO_BLOCK_BEGIN) # define LZO_BLOCK_BEGIN do { # define LZO_BLOCK_END } while __lzo_cte(0) #endif #if !defined(LZO_UNUSED) # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) # define LZO_UNUSED(var) ((void) &var) # elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) # define LZO_UNUSED(var) if (&var) ; else # elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) # define LZO_UNUSED(var) ((void) &var) # elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNUSED(var) ((void) var) # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_UNUSED(var) if (&var) ; else # elif (LZO_CC_KEILC) # define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;} # elif (LZO_CC_PACIFICC) # define LZO_UNUSED(var) ((void) sizeof(var)) # elif (LZO_CC_WATCOMC) && defined(__cplusplus) # define LZO_UNUSED(var) ((void) var) # else # define LZO_UNUSED(var) ((void) &var) # endif #endif #if !defined(LZO_UNUSED_RESULT) # define LZO_UNUSED_RESULT(var) LZO_UNUSED(var) #endif #if !defined(LZO_UNUSED_FUNC) # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) # define LZO_UNUSED_FUNC(func) ((void) func) # elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) # define LZO_UNUSED_FUNC(func) if (func) ; else # elif (LZO_CC_CLANG || LZO_CC_LLVM) # define LZO_UNUSED_FUNC(func) ((void) &func) # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_UNUSED_FUNC(func) if (func) ; else # elif (LZO_CC_MSC) # define LZO_UNUSED_FUNC(func) ((void) &func) # elif (LZO_CC_KEILC || LZO_CC_PELLESC) # define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;} # else # define LZO_UNUSED_FUNC(func) ((void) func) # endif #endif #if !defined(LZO_UNUSED_LABEL) # if (LZO_CC_CLANG >= 0x020800ul) # define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) # elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) # define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l # else # define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l # endif #endif #if !defined(LZO_DEFINE_UNINITIALIZED_VAR) # if 0 # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var # elif 0 && (LZO_CC_GNUC) # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var # else # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init # endif #endif #if !defined(__lzo_inline) #if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) #elif defined(__cplusplus) # define __lzo_inline inline #elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) # define __lzo_inline inline #elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) # define __lzo_inline __inline #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define __lzo_inline __inline__ #elif (LZO_CC_DMC) # define __lzo_inline __inline #elif (LZO_CC_GHS) # define __lzo_inline __inline__ #elif (LZO_CC_IBMC >= 600) # define __lzo_inline __inline__ #elif (LZO_CC_INTELC) # define __lzo_inline __inline #elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) # define __lzo_inline __inline #elif (LZO_CC_MSC && (_MSC_VER >= 900)) # define __lzo_inline __inline #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_inline __inline__ #endif #endif #if defined(__lzo_inline) # ifndef __lzo_HAVE_inline # define __lzo_HAVE_inline 1 # endif #else # define __lzo_inline /*empty*/ #endif #if !defined(__lzo_forceinline) #if (LZO_CC_GNUC >= 0x030200ul) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) # define __lzo_forceinline __forceinline #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) # define __lzo_forceinline __forceinline #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #endif #endif #if defined(__lzo_forceinline) # ifndef __lzo_HAVE_forceinline # define __lzo_HAVE_forceinline 1 # endif #else # define __lzo_forceinline __lzo_inline #endif #if !defined(__lzo_noinline) #if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) # define __lzo_noinline __attribute__((__noinline__,__used__)) #elif (LZO_CC_GNUC >= 0x030200ul) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) # define __lzo_noinline __declspec(noinline) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_noinline __declspec(noinline) #elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) # if defined(__cplusplus) # else # define __lzo_noinline __declspec(noinline) # endif #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_noinline __attribute__((__noinline__)) #endif #endif #if defined(__lzo_noinline) # ifndef __lzo_HAVE_noinline # define __lzo_HAVE_noinline 1 # endif #else # define __lzo_noinline /*empty*/ #endif #if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) # error "unexpected configuration - check your compiler defines" #endif #if !defined(__lzo_static_inline) #if (LZO_CC_IBMC) # define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline #endif #endif #if !defined(__lzo_static_inline) # define __lzo_static_inline static __lzo_inline #endif #if !defined(__lzo_static_forceinline) #if (LZO_CC_IBMC) # define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline #endif #endif #if !defined(__lzo_static_forceinline) # define __lzo_static_forceinline static __lzo_forceinline #endif #if !defined(__lzo_static_noinline) #if (LZO_CC_IBMC) # define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline #endif #endif #if !defined(__lzo_static_noinline) # define __lzo_static_noinline static __lzo_noinline #endif #if !defined(__lzo_c99_extern_inline) #if defined(__GNUC_GNU_INLINE__) # define __lzo_c99_extern_inline __lzo_inline #elif defined(__GNUC_STDC_INLINE__) # define __lzo_c99_extern_inline extern __lzo_inline #elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) # define __lzo_c99_extern_inline extern __lzo_inline #endif #if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) # define __lzo_c99_extern_inline __lzo_inline #endif #endif #if defined(__lzo_c99_extern_inline) # ifndef __lzo_HAVE_c99_extern_inline # define __lzo_HAVE_c99_extern_inline 1 # endif #else # define __lzo_c99_extern_inline /*empty*/ #endif #if !defined(__lzo_may_alias) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_CLANG >= 0x020900ul) # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 # define __lzo_may_alias __attribute__((__may_alias__)) #endif #endif #if defined(__lzo_may_alias) # ifndef __lzo_HAVE_may_alias # define __lzo_HAVE_may_alias 1 # endif #else # define __lzo_may_alias /*empty*/ #endif #if !defined(__lzo_noreturn) #if (LZO_CC_GNUC >= 0x020700ul) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) # define __lzo_noreturn __declspec(noreturn) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) # define __lzo_noreturn __declspec(noreturn) #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_noreturn __attribute__((__noreturn__)) #endif #endif #if defined(__lzo_noreturn) # ifndef __lzo_HAVE_noreturn # define __lzo_HAVE_noreturn 1 # endif #else # define __lzo_noreturn /*empty*/ #endif #if !defined(__lzo_nothrow) #if (LZO_CC_GNUC >= 0x030300ul) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) # define __lzo_nothrow __declspec(nothrow) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) # define __lzo_nothrow __declspec(nothrow) #endif #endif #if defined(__lzo_nothrow) # ifndef __lzo_HAVE_nothrow # define __lzo_HAVE_nothrow 1 # endif #else # define __lzo_nothrow /*empty*/ #endif #if !defined(__lzo_restrict) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_restrict __restrict__ #elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) # define __lzo_restrict __restrict__ #elif (LZO_CC_IBMC >= 1210) # define __lzo_restrict __restrict__ #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) # define __lzo_restrict __restrict__ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) # define __lzo_restrict __restrict__ #elif (LZO_CC_MSC && (_MSC_VER >= 1400)) # define __lzo_restrict __restrict #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_restrict __restrict__ #endif #endif #if defined(__lzo_restrict) # ifndef __lzo_HAVE_restrict # define __lzo_HAVE_restrict 1 # endif #else # define __lzo_restrict /*empty*/ #endif #if !defined(__lzo_alignof) #if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_GHS) && !defined(__cplusplus) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_IBMC >= 600) # define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_alignof(e) __alignof(e) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_alignof(e) __alignof__(e) #endif #endif #if defined(__lzo_alignof) # ifndef __lzo_HAVE_alignof # define __lzo_HAVE_alignof 1 # endif #endif #if !defined(__lzo_struct_packed) #if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) #elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) #elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) # define __lzo_struct_packed(s) struct s { # define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_struct_packed(s) struct s { # define __lzo_struct_packed_end() } __attribute__((__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_IBMC >= 700) # define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { # define __lzo_struct_packed_end() } __attribute__((__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { # define __lzo_struct_packed_end() } __pragma(pack(pop)); #elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) # define __lzo_struct_packed(s) _Packed struct s { # define __lzo_struct_packed_end() }; #endif #endif #if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) # define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) #endif #if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) # define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() #endif #if !defined(__lzo_byte_struct) #if defined(__lzo_struct_packed) # define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() # define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() #elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); # define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); #endif #endif #if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) # define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) #endif #if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) #if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) #elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_CILLY || LZO_CC_PCC) #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_struct_align16(s) struct __declspec(align(16)) s { # define __lzo_struct_align16_end() }; # define __lzo_struct_align32(s) struct __declspec(align(32)) s { # define __lzo_struct_align32_end() }; # define __lzo_struct_align64(s) struct __declspec(align(64)) s { # define __lzo_struct_align64_end() }; #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_struct_align16(s) struct s { # define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); # define __lzo_struct_align32(s) struct s { # define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); # define __lzo_struct_align64(s) struct s { # define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); #endif #endif #if !defined(__lzo_union_um) #if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) #elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) #elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_union_am(s) union s { # define __lzo_union_am_end() } __lzo_may_alias; # define __lzo_union_um(s) union s { # define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_IBMC >= 700) # define __lzo_union_am(s) __lzo_gnuc_extension__ union s { # define __lzo_union_am_end() } __lzo_may_alias; # define __lzo_union_um(s) __lzo_gnuc_extension__ union s { # define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_union_um(s) __pragma(pack(push,1)) union s { # define __lzo_union_um_end() } __pragma(pack(pop)); #elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) # define __lzo_union_um(s) _Packed union s { # define __lzo_union_um_end() }; #endif #endif #if !defined(__lzo_union_am) # define __lzo_union_am(s) union s { # define __lzo_union_am_end() }; #endif #if !defined(__lzo_constructor) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_constructor __attribute__((__constructor__,__used__)) #elif (LZO_CC_GNUC >= 0x020700ul) # define __lzo_constructor __attribute__((__constructor__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_constructor __attribute__((__constructor__,__used__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_constructor __attribute__((__constructor__)) #endif #endif #if defined(__lzo_constructor) # ifndef __lzo_HAVE_constructor # define __lzo_HAVE_constructor 1 # endif #endif #if !defined(__lzo_destructor) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_destructor __attribute__((__destructor__,__used__)) #elif (LZO_CC_GNUC >= 0x020700ul) # define __lzo_destructor __attribute__((__destructor__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_destructor __attribute__((__destructor__,__used__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_destructor __attribute__((__destructor__)) #endif #endif #if defined(__lzo_destructor) # ifndef __lzo_HAVE_destructor # define __lzo_HAVE_destructor 1 # endif #endif #if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) # error "unexpected configuration - check your compiler defines" #endif #if !defined(__lzo_likely) && !defined(__lzo_unlikely) #if (LZO_CC_GNUC >= 0x030200ul) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_IBMC >= 1010) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_CLANG && LZO_CC_CLANG_C2) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #endif #endif #if defined(__lzo_likely) # ifndef __lzo_HAVE_likely # define __lzo_HAVE_likely 1 # endif #else # define __lzo_likely(e) (e) #endif #if defined(__lzo_very_likely) # ifndef __lzo_HAVE_very_likely # define __lzo_HAVE_very_likely 1 # endif #else # define __lzo_very_likely(e) __lzo_likely(e) #endif #if defined(__lzo_unlikely) # ifndef __lzo_HAVE_unlikely # define __lzo_HAVE_unlikely 1 # endif #else # define __lzo_unlikely(e) (e) #endif #if defined(__lzo_very_unlikely) # ifndef __lzo_HAVE_very_unlikely # define __lzo_HAVE_very_unlikely 1 # endif #else # define __lzo_very_unlikely(e) __lzo_unlikely(e) #endif #if !defined(__lzo_loop_forever) # if (LZO_CC_IBMC) # define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END # else # define __lzo_loop_forever() do { ; } while __lzo_cte(1) # endif #endif #if !defined(__lzo_unreachable) #if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable) # define __lzo_unreachable() __builtin_unreachable(); #elif (LZO_CC_GNUC >= 0x040500ul) # define __lzo_unreachable() __builtin_unreachable(); #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 # define __lzo_unreachable() __builtin_unreachable(); #endif #endif #if defined(__lzo_unreachable) # ifndef __lzo_HAVE_unreachable # define __lzo_HAVE_unreachable 1 # endif #else # if 0 # define __lzo_unreachable() ((void)0); # else # define __lzo_unreachable() __lzo_loop_forever(); # endif #endif #if !defined(lzo_unused_funcs_impl) # if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f # elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC) # define lzo_unused_funcs_impl(r,f) static r f # else # define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f # endif #endif #ifndef __LZO_CTA_NAME #if (LZO_CFG_USE_COUNTER) # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) #else # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) #endif #endif #if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) # if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_DMC || LZO_CC_SYMANTECC) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END # else # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END # endif #endif #if !defined(LZO_COMPILE_TIME_ASSERT) # if (LZO_CC_AZTECC) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} # elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul)) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} # elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) # define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} # elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) # define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} # elif (LZO_CC_GNUC >= 0x040700ul) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # else # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} # endif #endif #if (LZO_LANG_ASSEMBLER) # undef LZO_COMPILE_TIME_ASSERT_HEADER # define LZO_COMPILE_TIME_ASSERT_HEADER(e) /*empty*/ #else LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) #if defined(__cplusplus) extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } #endif LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) #endif #if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) # elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) # define __lzo_cdecl __cdecl # define __lzo_cdecl_atexit /*empty*/ # define __lzo_cdecl_main __cdecl # if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) # define __lzo_cdecl_qsort __pascal # elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) # define __lzo_cdecl_qsort _stdcall # else # define __lzo_cdecl_qsort __cdecl # endif # elif (LZO_CC_WATCOMC) # define __lzo_cdecl __cdecl # else # define __lzo_cdecl __cdecl # define __lzo_cdecl_atexit __cdecl # define __lzo_cdecl_main __cdecl # define __lzo_cdecl_qsort __cdecl # endif # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) # elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) # define __lzo_cdecl_sighandler __pascal # elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) # define __lzo_cdecl_sighandler _stdcall # elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) # define __lzo_cdecl_sighandler __clrcall # elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) # if defined(_DLL) # define __lzo_cdecl_sighandler _far _cdecl _loadds # elif defined(_MT) # define __lzo_cdecl_sighandler _far _cdecl # else # define __lzo_cdecl_sighandler _cdecl # endif # else # define __lzo_cdecl_sighandler __cdecl # endif #elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) # define __lzo_cdecl __cdecl #elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) # define __lzo_cdecl cdecl #endif #if !defined(__lzo_cdecl) # define __lzo_cdecl /*empty*/ #endif #if !defined(__lzo_cdecl_atexit) # define __lzo_cdecl_atexit /*empty*/ #endif #if !defined(__lzo_cdecl_main) # define __lzo_cdecl_main /*empty*/ #endif #if !defined(__lzo_cdecl_qsort) # define __lzo_cdecl_qsort /*empty*/ #endif #if !defined(__lzo_cdecl_sighandler) # define __lzo_cdecl_sighandler /*empty*/ #endif #if !defined(__lzo_cdecl_va) # define __lzo_cdecl_va __lzo_cdecl #endif #if !(LZO_CFG_NO_WINDOWS_H) #if !defined(LZO_HAVE_WINDOWS_H) #if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) # if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) # elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))) # elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) # else # define LZO_HAVE_WINDOWS_H 1 # endif #endif #endif #endif #define LZO_SIZEOF_CHAR 1 #ifndef LZO_SIZEOF_SHORT #if defined(SIZEOF_SHORT) # define LZO_SIZEOF_SHORT (SIZEOF_SHORT) #elif defined(__SIZEOF_SHORT__) # define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) #endif #endif #ifndef LZO_SIZEOF_INT #if defined(SIZEOF_INT) # define LZO_SIZEOF_INT (SIZEOF_INT) #elif defined(__SIZEOF_INT__) # define LZO_SIZEOF_INT (__SIZEOF_INT__) #endif #endif #ifndef LZO_SIZEOF_LONG #if defined(SIZEOF_LONG) # define LZO_SIZEOF_LONG (SIZEOF_LONG) #elif defined(__SIZEOF_LONG__) # define LZO_SIZEOF_LONG (__SIZEOF_LONG__) #endif #endif #ifndef LZO_SIZEOF_LONG_LONG #if defined(SIZEOF_LONG_LONG) # define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) #elif defined(__SIZEOF_LONG_LONG__) # define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) #endif #endif #ifndef LZO_SIZEOF___INT16 #if defined(SIZEOF___INT16) # define LZO_SIZEOF___INT16 (SIZEOF___INT16) #endif #endif #ifndef LZO_SIZEOF___INT32 #if defined(SIZEOF___INT32) # define LZO_SIZEOF___INT32 (SIZEOF___INT32) #endif #endif #ifndef LZO_SIZEOF___INT64 #if defined(SIZEOF___INT64) # define LZO_SIZEOF___INT64 (SIZEOF___INT64) #endif #endif #ifndef LZO_SIZEOF_VOID_P #if defined(SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) #elif defined(__SIZEOF_POINTER__) # define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) #endif #endif #ifndef LZO_SIZEOF_SIZE_T #if defined(SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) #elif defined(__SIZEOF_SIZE_T__) # define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) #endif #endif #ifndef LZO_SIZEOF_PTRDIFF_T #if defined(SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) #elif defined(__SIZEOF_PTRDIFF_T__) # define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) #endif #endif #define __LZO_LSR(x,b) (((x)+0ul) >> (b)) #if !defined(LZO_SIZEOF_SHORT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_SHORT 8 # elif (USHRT_MAX == LZO_0xffffL) # define LZO_SIZEOF_SHORT 2 # elif (__LZO_LSR(USHRT_MAX,7) == 1) # define LZO_SIZEOF_SHORT 1 # elif (__LZO_LSR(USHRT_MAX,15) == 1) # define LZO_SIZEOF_SHORT 2 # elif (__LZO_LSR(USHRT_MAX,31) == 1) # define LZO_SIZEOF_SHORT 4 # elif (__LZO_LSR(USHRT_MAX,63) == 1) # define LZO_SIZEOF_SHORT 8 # elif (__LZO_LSR(USHRT_MAX,127) == 1) # define LZO_SIZEOF_SHORT 16 # else # error "LZO_SIZEOF_SHORT" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) #if !defined(LZO_SIZEOF_INT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_INT 8 # elif (UINT_MAX == LZO_0xffffL) # define LZO_SIZEOF_INT 2 # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_INT 4 # elif (__LZO_LSR(UINT_MAX,7) == 1) # define LZO_SIZEOF_INT 1 # elif (__LZO_LSR(UINT_MAX,15) == 1) # define LZO_SIZEOF_INT 2 # elif (__LZO_LSR(UINT_MAX,31) == 1) # define LZO_SIZEOF_INT 4 # elif (__LZO_LSR(UINT_MAX,63) == 1) # define LZO_SIZEOF_INT 8 # elif (__LZO_LSR(UINT_MAX,127) == 1) # define LZO_SIZEOF_INT 16 # else # error "LZO_SIZEOF_INT" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) #if !defined(LZO_SIZEOF_LONG) # if (ULONG_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_LONG 4 # elif (__LZO_LSR(ULONG_MAX,7) == 1) # define LZO_SIZEOF_LONG 1 # elif (__LZO_LSR(ULONG_MAX,15) == 1) # define LZO_SIZEOF_LONG 2 # elif (__LZO_LSR(ULONG_MAX,31) == 1) # define LZO_SIZEOF_LONG 4 # elif (__LZO_LSR(ULONG_MAX,39) == 1) # define LZO_SIZEOF_LONG 5 # elif (__LZO_LSR(ULONG_MAX,63) == 1) # define LZO_SIZEOF_LONG 8 # elif (__LZO_LSR(ULONG_MAX,127) == 1) # define LZO_SIZEOF_LONG 16 # else # error "LZO_SIZEOF_LONG" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) # if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) # if (LZO_CC_GNUC >= 0x030300ul) # if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) # define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG # elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) # define LZO_SIZEOF_LONG_LONG 4 # endif # endif # endif #endif #endif #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) #if (LZO_ARCH_I086 && LZO_CC_DMC) #elif (LZO_CC_CILLY) && defined(__GNUC__) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_SIZEOF_LONG_LONG 8 #elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_OS_WIN64 || defined(_WIN64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_DMC)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) # define LZO_SIZEOF___INT64 8 #elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) # define LZO_SIZEOF___INT64 8 #elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) # define LZO_SIZEOF_LONG_LONG 8 #elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) #elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define LZO_SIZEOF_LONG_LONG 8 #endif #endif #endif #if defined(__cplusplus) && (LZO_CC_GNUC) # if (LZO_CC_GNUC < 0x020800ul) # undef LZO_SIZEOF_LONG_LONG # endif #endif #if (LZO_CFG_NO_LONG_LONG) # undef LZO_SIZEOF_LONG_LONG #elif defined(__NO_LONG_LONG) # undef LZO_SIZEOF_LONG_LONG #elif defined(_NO_LONGLONG) # undef LZO_SIZEOF_LONG_LONG #endif #if !defined(LZO_WORDSIZE) #if (LZO_ARCH_ALPHA) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_AMD64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_ARM64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_AVR) # define LZO_WORDSIZE 1 #elif (LZO_ARCH_H8300) # if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) # define LZO_WORDSIZE 4 # else # define LZO_WORDSIZE 2 # endif #elif (LZO_ARCH_I086) # define LZO_WORDSIZE 2 #elif (LZO_ARCH_IA64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_M16C) # define LZO_WORDSIZE 2 #elif (LZO_ARCH_SPU) # define LZO_WORDSIZE 4 #elif (LZO_ARCH_Z80) # define LZO_WORDSIZE 1 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) # define LZO_WORDSIZE 8 #elif (LZO_OS_OS400 || defined(__OS400__)) # define LZO_WORDSIZE 8 #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_WORDSIZE 8 #endif #endif #if !defined(LZO_SIZEOF_VOID_P) #if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) # define LZO_SIZEOF_VOID_P 4 #elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) # define LZO_SIZEOF_VOID_P 8 #elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) # define LZO_SIZEOF_VOID_P 8 #elif defined(__LP64__) || defined(__LP64) || defined(_LP64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) # define LZO_SIZEOF_VOID_P 8 #elif (LZO_ARCH_AVR) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_H8300) # if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 4) # if defined(__NORMAL_MODE__) # define LZO_SIZEOF_VOID_P 2 # else # define LZO_SIZEOF_VOID_P 4 # endif # else LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 2) # define LZO_SIZEOF_VOID_P 2 # endif # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT # endif #elif (LZO_ARCH_I086) # if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) # define LZO_SIZEOF_VOID_P 2 # elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) # define LZO_SIZEOF_VOID_P 4 # else # error "invalid LZO_ARCH_I086 memory model" # endif #elif (LZO_ARCH_M16C) # if defined(__m32c_cpu__) || defined(__m32cm_cpu__) # define LZO_SIZEOF_VOID_P 4 # else # define LZO_SIZEOF_VOID_P 2 # endif #elif (LZO_ARCH_SPU) # define LZO_SIZEOF_VOID_P 4 #elif (LZO_ARCH_Z80) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) # define LZO_SIZEOF_VOID_P 4 #elif (LZO_OS_OS400 || defined(__OS400__)) # if defined(__LLP64_IFC__) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG # else # define LZO_SIZEOF_VOID_P 16 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG # endif #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG #endif #endif #if !defined(LZO_SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) #if !defined(LZO_SIZEOF_SIZE_T) #if (LZO_ARCH_I086 || LZO_ARCH_M16C) # define LZO_SIZEOF_SIZE_T 2 #endif #endif #if !defined(LZO_SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P #endif #if defined(offsetof) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) #if (LZO_ARCH_I086) # if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P # elif (LZO_MM_COMPACT || LZO_MM_LARGE) # if (LZO_CC_BORLANDC || LZO_CC_TURBOC) # define LZO_SIZEOF_PTRDIFF_T 4 # else # define LZO_SIZEOF_PTRDIFF_T 2 # endif # else # error "invalid LZO_ARCH_I086 memory model" # endif #endif #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T #endif #if defined(offsetof) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) #endif #if !defined(LZO_WORDSIZE) # define LZO_WORDSIZE LZO_SIZEOF_VOID_P #endif #if (LZO_ABI_NEUTRAL_ENDIAN) # undef LZO_ABI_BIG_ENDIAN # undef LZO_ABI_LITTLE_ENDIAN #elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) #if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) # define LZO_ABI_BIG_ENDIAN 1 #elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430 || LZO_ARCH_RISCV) # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) # if (__LITTLE_ENDIAN__ == 1) # define LZO_ABI_LITTLE_ENDIAN 1 # else # define LZO_ABI_BIG_ENDIAN 1 # endif #elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(_MSC_VER) && defined(_WIN32) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) # if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) # error "unexpected configuration - check your compiler defines" # elif defined(__BIG_ENDIAN) # define LZO_ABI_BIG_ENDIAN 1 # else # define LZO_ABI_LITTLE_ENDIAN 1 # endif # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(_MSC_VER) && defined(_WIN32) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) # define LZO_ABI_LITTLE_ENDIAN 1 #endif #endif #if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ABI_BIG_ENDIAN) # define LZO_INFO_ABI_ENDIAN "be" #elif (LZO_ABI_LITTLE_ENDIAN) # define LZO_INFO_ABI_ENDIAN "le" #elif (LZO_ABI_NEUTRAL_ENDIAN) # define LZO_INFO_ABI_ENDIAN "neutral" #endif #if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_I8LP16 1 # define LZO_INFO_ABI_PM "i8lp16" #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_ILP16 1 # define LZO_INFO_ABI_PM "ilp16" #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_LP32 1 # define LZO_INFO_ABI_PM "lp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_ILP32 1 # define LZO_INFO_ABI_PM "ilp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) # define LZO_ABI_LLP64 1 # define LZO_INFO_ABI_PM "llp64" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) # define LZO_ABI_LP64 1 # define LZO_INFO_ABI_PM "lp64" #elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) # define LZO_ABI_ILP64 1 # define LZO_INFO_ABI_PM "ilp64" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_IP32L64 1 # define LZO_INFO_ABI_PM "ip32l64" #endif #if (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_VOID_P == 4 && LZO_WORDSIZE == 8) # define LZO_ABI_IP32W64 1 # ifndef LZO_INFO_ABI_PM # define LZO_INFO_ABI_PM "ip32w64" # endif #endif #if 0 #elif !defined(__LZO_LIBC_OVERRIDE) #if (LZO_LIBC_NAKED) # define LZO_INFO_LIBC "naked" #elif (LZO_LIBC_FREESTANDING) # define LZO_INFO_LIBC "freestanding" #elif (LZO_LIBC_MOSTLY_FREESTANDING) # define LZO_INFO_LIBC "mfreestanding" #elif (LZO_LIBC_ISOC90) # define LZO_INFO_LIBC "isoc90" #elif (LZO_LIBC_ISOC99) # define LZO_INFO_LIBC "isoc99" #elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) # define LZO_LIBC_ISOC90 1 # define LZO_INFO_LIBC "isoc90" #elif defined(__dietlibc__) # define LZO_LIBC_DIETLIBC 1 # define LZO_INFO_LIBC "dietlibc" #elif defined(_NEWLIB_VERSION) # define LZO_LIBC_NEWLIB 1 # define LZO_INFO_LIBC "newlib" #elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) # if defined(__UCLIBC_SUBLEVEL__) # define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) # else # define LZO_LIBC_UCLIBC 0x00090bL # endif # define LZO_INFO_LIBC "uc" "libc" #elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) # define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) # define LZO_INFO_LIBC "glibc" #elif (LZO_CC_MWERKS) && defined(__MSL__) # define LZO_LIBC_MSL __MSL__ # define LZO_INFO_LIBC "msl" #elif 1 && defined(__IAR_SYSTEMS_ICC__) # define LZO_LIBC_ISOC90 1 # define LZO_INFO_LIBC "isoc90" #else # define LZO_LIBC_DEFAULT 1 # define LZO_INFO_LIBC "default" #endif #endif #if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) # define LZO_ASM_SYNTAX_MSC 1 #elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) #elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) #elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) # define LZO_ASM_SYNTAX_GNUC 1 #elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) # define LZO_ASM_SYNTAX_GNUC 1 #elif (LZO_CC_GNUC) # define LZO_ASM_SYNTAX_GNUC 1 #endif #if (LZO_ASM_SYNTAX_GNUC) #if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) # define __LZO_ASM_CLOBBER "ax" # define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) # define __LZO_ASM_CLOBBER "memory" # define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #else # define __LZO_ASM_CLOBBER "cc", "memory" # define __LZO_ASM_CLOBBER_LIST_CC : "cc" # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #endif #endif #if (LZO_ARCH_ALPHA) # define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_AMD64) # define LZO_OPT_AVOID_INT_INDEX 1 # define LZO_OPT_AVOID_UINT_INDEX 1 # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif #elif (LZO_ARCH_ARM) # if defined(__ARM_FEATURE_UNALIGNED) # if ((__ARM_FEATURE_UNALIGNED)+0) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif # elif 1 && (LZO_ARCH_ARM_THUMB2) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__ARM_ARCH) && ((__ARM_ARCH)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R)) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(_MSC_VER) && defined(_M_ARM) && ((_M_ARM)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif #elif (LZO_ARCH_ARM64) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif #elif (LZO_ARCH_CRIS) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif #elif (LZO_ARCH_I386) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif #elif (LZO_ARCH_IA64) # define LZO_OPT_AVOID_INT_INDEX 1 # define LZO_OPT_AVOID_UINT_INDEX 1 # define LZO_OPT_PREFER_POSTINC 1 #elif (LZO_ARCH_M68K) # define LZO_OPT_PREFER_POSTINC 1 # define LZO_OPT_PREFER_PREDEC 1 # if defined(__mc68020__) && !defined(__mcoldfire__) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif #elif (LZO_ARCH_MIPS) # define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_POWERPC) # define LZO_OPT_PREFER_PREINC 1 # define LZO_OPT_PREFER_PREDEC 1 # if (LZO_ABI_BIG_ENDIAN) || (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif # endif #elif (LZO_ARCH_RISCV) # define LZO_OPT_AVOID_UINT_INDEX 1 # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif #elif (LZO_ARCH_S390) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif #elif (LZO_ARCH_SH) # define LZO_OPT_PREFER_POSTINC 1 # define LZO_OPT_PREFER_PREDEC 1 #endif #ifndef LZO_CFG_NO_INLINE_ASM #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_INLINE_ASM 1 #elif (LZO_CC_LLVM) # define LZO_CFG_NO_INLINE_ASM 1 #endif #endif #if (LZO_CFG_NO_INLINE_ASM) # undef LZO_ASM_SYNTAX_MSC # undef LZO_ASM_SYNTAX_GNUC # undef __LZO_ASM_CLOBBER # undef __LZO_ASM_CLOBBER_LIST_CC # undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY # undef __LZO_ASM_CLOBBER_LIST_EMPTY #endif #ifndef LZO_CFG_NO_UNALIGNED #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_UNALIGNED 1 #endif #endif #if (LZO_CFG_NO_UNALIGNED) # undef LZO_OPT_UNALIGNED16 # undef LZO_OPT_UNALIGNED32 # undef LZO_OPT_UNALIGNED64 #endif #if defined(__LZO_INFOSTR_MM) #elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) # define __LZO_INFOSTR_MM "" #elif defined(LZO_INFO_MM) # define __LZO_INFOSTR_MM "." LZO_INFO_MM #else # define __LZO_INFOSTR_MM "" #endif #if defined(__LZO_INFOSTR_PM) #elif defined(LZO_INFO_ABI_PM) # define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM #else # define __LZO_INFOSTR_PM "" #endif #if defined(__LZO_INFOSTR_ENDIAN) #elif defined(LZO_INFO_ABI_ENDIAN) # define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN #else # define __LZO_INFOSTR_ENDIAN "" #endif #if defined(__LZO_INFOSTR_OSNAME) #elif defined(LZO_INFO_OS_CONSOLE) # define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE #elif defined(LZO_INFO_OS_POSIX) # define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX #else # define __LZO_INFOSTR_OSNAME LZO_INFO_OS #endif #if defined(__LZO_INFOSTR_LIBC) #elif defined(LZO_INFO_LIBC) # define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC #else # define __LZO_INFOSTR_LIBC "" #endif #if defined(__LZO_INFOSTR_CCVER) #elif defined(LZO_INFO_CCVER) # define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER #else # define __LZO_INFOSTR_CCVER "" #endif #define LZO_INFO_STRING \ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER #if !(LZO_CFG_SKIP_LZO_TYPES) #if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) # error "missing defines for sizes" #endif #if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) # error "missing defines for sizes" #endif #define LZO_TYPEOF_CHAR 1u #define LZO_TYPEOF_SHORT 2u #define LZO_TYPEOF_INT 3u #define LZO_TYPEOF_LONG 4u #define LZO_TYPEOF_LONG_LONG 5u #define LZO_TYPEOF___INT8 17u #define LZO_TYPEOF___INT16 18u #define LZO_TYPEOF___INT32 19u #define LZO_TYPEOF___INT64 20u #define LZO_TYPEOF___INT128 21u #define LZO_TYPEOF___INT256 22u #define LZO_TYPEOF___MODE_QI 33u #define LZO_TYPEOF___MODE_HI 34u #define LZO_TYPEOF___MODE_SI 35u #define LZO_TYPEOF___MODE_DI 36u #define LZO_TYPEOF___MODE_TI 37u #define LZO_TYPEOF_CHAR_P 129u #if !defined(lzo_llong_t) #if (LZO_SIZEOF_LONG_LONG+0 > 0) # if !(LZO_LANG_ASSEMBLER) __lzo_gnuc_extension__ typedef long long lzo_llong_t__; __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; # endif # define lzo_llong_t lzo_llong_t__ # define lzo_ullong_t lzo_ullong_t__ #endif #endif #if !defined(lzo_int16e_t) #if (LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) && (LZO_SIZEOF_SHORT != 2) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T #endif #if (LZO_SIZEOF_LONG == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) # define lzo_int16e_t long # define lzo_uint16e_t unsigned long # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_INT == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) # define lzo_int16e_t int # define lzo_uint16e_t unsigned int # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == 2) # define lzo_int16e_t short int # define lzo_uint16e_t unsigned short int # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT #elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); # endif # define lzo_int16e_t lzo_int16e_hi_t__ # define lzo_uint16e_t lzo_uint16e_hi_t__ # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI #elif (LZO_SIZEOF___INT16 == 2) # define lzo_int16e_t __int16 # define lzo_uint16e_t unsigned __int16 # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16 #else #endif #endif #if defined(lzo_int16e_t) # define LZO_SIZEOF_LZO_INT16E_T 2 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) #endif #if !defined(lzo_int32e_t) #if (LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) && (LZO_SIZEOF_INT != 4) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T #endif #if (LZO_SIZEOF_LONG == 4) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) # define lzo_int32e_t long int # define lzo_uint32e_t unsigned long int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_INT == 4) # define lzo_int32e_t int # define lzo_uint32e_t unsigned int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == 4) # define lzo_int32e_t short int # define lzo_uint32e_t unsigned short int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT #elif (LZO_SIZEOF_LONG_LONG == 4) # define lzo_int32e_t lzo_llong_t # define lzo_uint32e_t lzo_ullong_t # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); # endif # define lzo_int32e_t lzo_int32e_si_t__ # define lzo_uint32e_t lzo_uint32e_si_t__ # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); # endif # define lzo_int32e_t lzo_int32e_si_t__ # define lzo_uint32e_t lzo_uint32e_si_t__ # define LZO_INT32_C(c) (c##LL) # define LZO_UINT32_C(c) (c##ULL) # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI #elif (LZO_SIZEOF___INT32 == 4) # define lzo_int32e_t __int32 # define lzo_uint32e_t unsigned __int32 # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32 #else #endif #endif #if defined(lzo_int32e_t) # define LZO_SIZEOF_LZO_INT32E_T 4 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) #endif #if !defined(lzo_int64e_t) #if (LZO_SIZEOF___INT64 == 8) # if (LZO_CC_BORLANDC) && !defined(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T) # define LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T LZO_TYPEOF___INT64 # endif #endif #if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && (LZO_SIZEOF_LONG_LONG != 8) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T #endif #if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) && (LZO_SIZEOF___INT64 != 8) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T #endif #if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_int64e_t int # define lzo_uint64e_t unsigned int # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) # define lzo_int64e_t long int # define lzo_uint64e_t unsigned long int # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) # define lzo_int64e_t lzo_llong_t # define lzo_uint64e_t lzo_ullong_t # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG # if (LZO_CC_BORLANDC) # define LZO_INT64_C(c) ((c) + 0ll) # define LZO_UINT64_C(c) ((c) + 0ull) # elif 0 # define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) # define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) # else # define LZO_INT64_C(c) (c##LL) # define LZO_UINT64_C(c) (c##ULL) # endif #elif (LZO_SIZEOF___INT64 == 8) # define lzo_int64e_t __int64 # define lzo_uint64e_t unsigned __int64 # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64 # if (LZO_CC_BORLANDC) # define LZO_INT64_C(c) ((c) + 0i64) # define LZO_UINT64_C(c) ((c) + 0ui64) # else # define LZO_INT64_C(c) (c##i64) # define LZO_UINT64_C(c) (c##ui64) # endif #else #endif #endif #if defined(lzo_int64e_t) # define LZO_SIZEOF_LZO_INT64E_T 8 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) #endif #if !defined(lzo_int32l_t) #if defined(lzo_int32e_t) # define lzo_int32l_t lzo_int32e_t # define lzo_uint32l_t lzo_uint32e_t # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T # define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T #elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_int32l_t int # define lzo_uint32l_t unsigned int # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT #elif (LZO_SIZEOF_LONG >= 4) # define lzo_int32l_t long int # define lzo_uint32l_t unsigned long int # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG #else # error "lzo_int32l_t" #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) #endif #if !defined(lzo_int64l_t) #if defined(lzo_int64e_t) # define lzo_int64l_t lzo_int64e_t # define lzo_uint64l_t lzo_uint64e_t # define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T # define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T #else #endif #endif #if defined(lzo_int64l_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) #endif #if !defined(lzo_int32f_t) #if (LZO_SIZEOF_SIZE_T >= 8) # define lzo_int32f_t lzo_int64l_t # define lzo_uint32f_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T #else # define lzo_int32f_t lzo_int32l_t # define lzo_uint32f_t lzo_uint32l_t # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T # define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) #endif #if !defined(lzo_int64f_t) #if defined(lzo_int64l_t) # define lzo_int64f_t lzo_int64l_t # define lzo_uint64f_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T #else #endif #endif #if defined(lzo_int64f_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) #endif #if !defined(lzo_intptr_t) #if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) # define __LZO_INTPTR_T_IS_POINTER 1 # if !(LZO_LANG_ASSEMBLER) typedef char * lzo_intptr_t; typedef char * lzo_uintptr_t; # endif # define lzo_intptr_t lzo_intptr_t # define lzo_uintptr_t lzo_uintptr_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P #elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) # if !(LZO_LANG_ASSEMBLER) typedef __w64 int lzo_intptr_t; typedef __w64 unsigned int lzo_uintptr_t; # endif # define lzo_intptr_t lzo_intptr_t # define lzo_uintptr_t lzo_uintptr_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) # define lzo_intptr_t short # define lzo_uintptr_t unsigned short # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT #elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_intptr_t int # define lzo_uintptr_t unsigned int # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) # define lzo_intptr_t long # define lzo_uintptr_t unsigned long # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) # define lzo_intptr_t lzo_int64l_t # define lzo_uintptr_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T #else # error "lzo_intptr_t" #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) #endif #if !defined(lzo_word_t) #if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) #if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) # define lzo_word_t lzo_uintptr_t # define lzo_sword_t lzo_intptr_t # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T #elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) # define lzo_word_t unsigned long # define lzo_sword_t long # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG #elif (LZO_WORDSIZE == LZO_SIZEOF_INT) # define lzo_word_t unsigned int # define lzo_sword_t int # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT #elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) # define lzo_word_t unsigned short # define lzo_sword_t short # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT #elif (LZO_WORDSIZE == 1) # define lzo_word_t unsigned char # define lzo_sword_t signed char # define LZO_SIZEOF_LZO_WORD_T 1 # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR #elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) # define lzo_word_t lzo_uint64l_t # define lzo_sword_t lzo_int64l_t # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T #elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) #if 0 # if !(LZO_LANG_ASSEMBLER) typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); # endif # define lzo_word_t lzo_word_t # define lzo_sword_t lzo_sword_t # define LZO_SIZEOF_LZO_WORD_T 16 # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI #endif #else # error "lzo_word_t" #endif #endif #endif #if 1 && defined(lzo_word_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) #endif #if 1 #define lzo_int8_t signed char #define lzo_uint8_t unsigned char #define LZO_SIZEOF_LZO_INT8_T 1 #define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) #endif #if defined(lzo_int16e_t) #define lzo_int16_t lzo_int16e_t #define lzo_uint16_t lzo_uint16e_t #define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T #define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) #endif #if defined(lzo_int32e_t) #define lzo_int32_t lzo_int32e_t #define lzo_uint32_t lzo_uint32e_t #define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T #define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) #endif #if defined(lzo_int64e_t) #define lzo_int64_t lzo_int64e_t #define lzo_uint64_t lzo_uint64e_t #define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T #define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) #endif #if 1 #define lzo_int_least32_t lzo_int32l_t #define lzo_uint_least32_t lzo_uint32l_t #define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T #define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) #endif #if defined(lzo_int64l_t) #define lzo_int_least64_t lzo_int64l_t #define lzo_uint_least64_t lzo_uint64l_t #define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T #define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) #endif #if 1 #define lzo_int_fast32_t lzo_int32f_t #define lzo_uint_fast32_t lzo_uint32f_t #define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T #define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) #endif #if defined(lzo_int64f_t) #define lzo_int_fast64_t lzo_int64f_t #define lzo_uint_fast64_t lzo_uint64f_t #define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T #define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) #endif #if !defined(LZO_INT16_C) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) # define LZO_INT16_C(c) ((c) + 0) # define LZO_UINT16_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) # define LZO_INT16_C(c) ((c) + 0L) # define LZO_UINT16_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 2) # define LZO_INT16_C(c) (c) # define LZO_UINT16_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 2) # define LZO_INT16_C(c) (c##L) # define LZO_UINT16_C(c) (c##UL) # else # error "LZO_INT16_C" # endif #endif #if !defined(LZO_INT32_C) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) # define LZO_INT32_C(c) ((c) + 0) # define LZO_UINT32_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) # define LZO_INT32_C(c) ((c) + 0L) # define LZO_UINT32_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 4) # define LZO_INT32_C(c) (c) # define LZO_UINT32_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 4) # define LZO_INT32_C(c) (c##L) # define LZO_UINT32_C(c) (c##UL) # elif (LZO_SIZEOF_LONG_LONG >= 4) # define LZO_INT32_C(c) (c##LL) # define LZO_UINT32_C(c) (c##ULL) # else # error "LZO_INT32_C" # endif #endif #if !defined(LZO_INT64_C) && defined(lzo_int64l_t) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) # define LZO_INT64_C(c) ((c) + 0) # define LZO_UINT64_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) # define LZO_INT64_C(c) ((c) + 0L) # define LZO_UINT64_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 8) # define LZO_INT64_C(c) (c) # define LZO_UINT64_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 8) # define LZO_INT64_C(c) (c##L) # define LZO_UINT64_C(c) (c##UL) # else # error "LZO_INT64_C" # endif #endif #endif #endif #endif #undef LZO_HAVE_CONFIG_H #include "minilzo.h" #if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x20a0) # error "version mismatch in miniLZO source files" #endif #ifdef MINILZO_HAVE_CONFIG_H # define LZO_HAVE_CONFIG_H 1 #endif #ifndef __LZO_CONF_H #define __LZO_CONF_H 1 #if !defined(__LZO_IN_MINILZO) #if defined(LZO_CFG_FREESTANDING) && (LZO_CFG_FREESTANDING) # define LZO_LIBC_FREESTANDING 1 # define LZO_OS_FREESTANDING 1 #endif #if defined(LZO_CFG_EXTRA_CONFIG_HEADER) # include LZO_CFG_EXTRA_CONFIG_HEADER #endif #if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) # error "include this file first" #endif #if defined(LZO_CFG_BUILD_DLL) && (LZO_CFG_BUILD_DLL+0) && !defined(__LZO_EXPORT1) && !defined(__LZO_EXPORT2) && 0 #ifndef __LZODEFS_H_INCLUDED #if defined(LZO_HAVE_CONFIG_H) # include #endif #include #include #include #endif #endif #include #if defined(LZO_CFG_EXTRA_CONFIG_HEADER2) # include LZO_CFG_EXTRA_CONFIG_HEADER2 #endif #endif #if !defined(__LZOCONF_H_INCLUDED) || (LZO_VERSION+0 != 0x20a0) # error "version mismatch" #endif #if (LZO_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1100)) # pragma warning(disable: 4702) #endif #if (LZO_CC_MSC && (_MSC_VER >= 1000)) # pragma warning(disable: 4127 4701) # pragma warning(disable: 4514 4710 4711) #endif #if (LZO_CC_MSC && (_MSC_VER >= 1300)) # pragma warning(disable: 4820) #endif #if (LZO_CC_MSC && (_MSC_VER >= 1800)) # pragma warning(disable: 4746) #endif #if (LZO_CC_INTELC && (__INTEL_COMPILER >= 900)) # pragma warning(disable: 1684) #endif #if (LZO_CC_SUNPROC) #if !defined(__cplusplus) # pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) # pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) # pragma error_messages(off,E_STATEMENT_NOT_REACHED) #endif #endif #if !defined(__LZO_NOEXPORT1) # define __LZO_NOEXPORT1 /*empty*/ #endif #if !defined(__LZO_NOEXPORT2) # define __LZO_NOEXPORT2 /*empty*/ #endif #if 1 # define LZO_PUBLIC_DECL(r) LZO_EXTERN(r) #endif #if 1 # define LZO_PUBLIC_IMPL(r) LZO_PUBLIC(r) #endif #if !defined(LZO_LOCAL_DECL) # define LZO_LOCAL_DECL(r) __LZO_EXTERN_C LZO_LOCAL_IMPL(r) #endif #if !defined(LZO_LOCAL_IMPL) # define LZO_LOCAL_IMPL(r) __LZO_NOEXPORT1 r __LZO_NOEXPORT2 __LZO_CDECL #endif #if 1 # define LZO_STATIC_DECL(r) LZO_PRIVATE(r) #endif #if 1 # define LZO_STATIC_IMPL(r) LZO_PRIVATE(r) #endif #if defined(__LZO_IN_MINILZO) || (LZO_CFG_FREESTANDING) #elif 1 # include #else # define LZO_WANT_ACC_INCD_H 1 #endif #if defined(LZO_HAVE_CONFIG_H) # define LZO_CFG_NO_CONFIG_HEADER 1 #endif #if 1 && !defined(LZO_CFG_FREESTANDING) #if 1 && !defined(HAVE_STRING_H) #define HAVE_STRING_H 1 #endif #if 1 && !defined(HAVE_MEMCMP) #define HAVE_MEMCMP 1 #endif #if 1 && !defined(HAVE_MEMCPY) #define HAVE_MEMCPY 1 #endif #if 1 && !defined(HAVE_MEMMOVE) #define HAVE_MEMMOVE 1 #endif #if 1 && !defined(HAVE_MEMSET) #define HAVE_MEMSET 1 #endif #endif #if 1 && defined(HAVE_STRING_H) #include #endif #if 1 || defined(lzo_int8_t) || defined(lzo_uint8_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint8_t) == 1) #endif #if 1 || defined(lzo_int16_t) || defined(lzo_uint16_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint16_t) == 2) #endif #if 1 || defined(lzo_int32_t) || defined(lzo_uint32_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32_t) == 4) #endif #if defined(lzo_int64_t) || defined(lzo_uint64_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64_t) == 8) #endif #if (LZO_CFG_FREESTANDING) # undef HAVE_MEMCMP # undef HAVE_MEMCPY # undef HAVE_MEMMOVE # undef HAVE_MEMSET #endif #if !(HAVE_MEMCMP) # undef memcmp # define memcmp(a,b,c) lzo_memcmp(a,b,c) #else # undef lzo_memcmp # define lzo_memcmp(a,b,c) memcmp(a,b,c) #endif #if !(HAVE_MEMCPY) # undef memcpy # define memcpy(a,b,c) lzo_memcpy(a,b,c) #else # undef lzo_memcpy # define lzo_memcpy(a,b,c) memcpy(a,b,c) #endif #if !(HAVE_MEMMOVE) # undef memmove # define memmove(a,b,c) lzo_memmove(a,b,c) #else # undef lzo_memmove # define lzo_memmove(a,b,c) memmove(a,b,c) #endif #if !(HAVE_MEMSET) # undef memset # define memset(a,b,c) lzo_memset(a,b,c) #else # undef lzo_memset # define lzo_memset(a,b,c) memset(a,b,c) #endif #undef NDEBUG #if (LZO_CFG_FREESTANDING) # undef LZO_DEBUG # define NDEBUG 1 # undef assert # define assert(e) ((void)0) #else # if !defined(LZO_DEBUG) # define NDEBUG 1 # endif # include #endif #if 0 && defined(__BOUNDS_CHECKING_ON) # include #else # define BOUNDS_CHECKING_OFF_DURING(stmt) stmt # define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) #endif #if (LZO_CFG_PGO) # undef __lzo_likely # undef __lzo_unlikely # define __lzo_likely(e) (e) # define __lzo_unlikely(e) (e) #endif #undef _ #undef __ #undef ___ #undef ____ #undef _p0 #undef _p1 #undef _p2 #undef _p3 #undef _p4 #undef _s0 #undef _s1 #undef _s2 #undef _s3 #undef _s4 #undef _ww #if 1 # define LZO_BYTE(x) ((unsigned char) (x)) #else # define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) #endif #define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) #define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) #define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) #define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) #define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) #define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) #define LZO_SIZE(bits) (1u << (bits)) #define LZO_MASK(bits) (LZO_SIZE(bits) - 1) #define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) #define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) #if !defined(DMUL) #if 0 # define DMUL(a,b) ((lzo_xint) ((lzo_uint32_t)(a) * (lzo_uint32_t)(b))) #else # define DMUL(a,b) ((lzo_xint) ((a) * (b))) #endif #endif #ifndef __LZO_FUNC_H #define __LZO_FUNC_H 1 #if !defined(LZO_BITOPS_USE_ASM_BITSCAN) && !defined(LZO_BITOPS_USE_GNUC_BITSCAN) && !defined(LZO_BITOPS_USE_MSC_BITSCAN) #if 1 && (LZO_ARCH_AMD64) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_ASM_SYNTAX_GNUC) #define LZO_BITOPS_USE_ASM_BITSCAN 1 #elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) #define LZO_BITOPS_USE_GNUC_BITSCAN 1 #elif (LZO_OS_WIN32 || LZO_OS_WIN64) && ((LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 1010)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) #define LZO_BITOPS_USE_MSC_BITSCAN 1 #if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) #include #endif #if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) #pragma intrinsic(_BitScanReverse) #pragma intrinsic(_BitScanForward) #endif #if (LZO_CC_MSC) && (LZO_ARCH_AMD64) #pragma intrinsic(_BitScanReverse64) #pragma intrinsic(_BitScanForward64) #endif #endif #endif __lzo_static_forceinline unsigned lzo_bitops_ctlz32_func(lzo_uint32_t v) { #if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) unsigned long r; (void) _BitScanReverse(&r, v); return (unsigned) r ^ 31; #define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) #elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) lzo_uint32_t r; __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); return (unsigned) r ^ 31; #define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT == 4) unsigned r; r = (unsigned) __builtin_clz(v); return r; #define lzo_bitops_ctlz32(v) ((unsigned) __builtin_clz(v)) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_clzl(v); return r ^ 32; #define lzo_bitops_ctlz32(v) (((unsigned) __builtin_clzl(v)) ^ 32) #else LZO_UNUSED(v); return 0; #endif } #if defined(lzo_uint64_t) __lzo_static_forceinline unsigned lzo_bitops_ctlz64_func(lzo_uint64_t v) { #if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) unsigned long r; (void) _BitScanReverse64(&r, v); return (unsigned) r ^ 63; #define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) #elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) lzo_uint64_t r; __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); return (unsigned) r ^ 63; #define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_clzl(v); return r; #define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzl(v)) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG == 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_clzll(v); return r; #define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzll(v)) #else LZO_UNUSED(v); return 0; #endif } #endif __lzo_static_forceinline unsigned lzo_bitops_cttz32_func(lzo_uint32_t v) { #if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) unsigned long r; (void) _BitScanForward(&r, v); return (unsigned) r; #define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) #elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) lzo_uint32_t r; __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); return (unsigned) r; #define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT >= 4) unsigned r; r = (unsigned) __builtin_ctz(v); return r; #define lzo_bitops_cttz32(v) ((unsigned) __builtin_ctz(v)) #else LZO_UNUSED(v); return 0; #endif } #if defined(lzo_uint64_t) __lzo_static_forceinline unsigned lzo_bitops_cttz64_func(lzo_uint64_t v) { #if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) unsigned long r; (void) _BitScanForward64(&r, v); return (unsigned) r; #define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) #elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) lzo_uint64_t r; __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); return (unsigned) r; #define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG >= 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_ctzl(v); return r; #define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzl(v)) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG >= 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_ctzll(v); return r; #define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzll(v)) #else LZO_UNUSED(v); return 0; #endif } #endif lzo_unused_funcs_impl(void, lzo_bitops_unused_funcs)(void) { LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); LZO_UNUSED_FUNC(lzo_bitops_ctlz32_func); LZO_UNUSED_FUNC(lzo_bitops_cttz32_func); #if defined(lzo_uint64_t) LZO_UNUSED_FUNC(lzo_bitops_ctlz64_func); LZO_UNUSED_FUNC(lzo_bitops_cttz64_func); #endif } #if defined(__lzo_alignof) && !(LZO_CFG_NO_UNALIGNED) #if !defined(lzo_memops_tcheck__) && 0 #define lzo_memops_tcheck__(t,a,b) ((void)0, sizeof(t) == (a) && __lzo_alignof(t) == (b)) #endif #endif #ifndef lzo_memops_TU0p #define lzo_memops_TU0p void __LZO_MMODEL * #endif #ifndef lzo_memops_TU1p #define lzo_memops_TU1p unsigned char __LZO_MMODEL * #endif #ifndef lzo_memops_TU2p #if (LZO_OPT_UNALIGNED16) typedef lzo_uint16_t __lzo_may_alias lzo_memops_TU2; #define lzo_memops_TU2p volatile lzo_memops_TU2 * #elif defined(__lzo_byte_struct) __lzo_byte_struct(lzo_memops_TU2_struct,2) typedef struct lzo_memops_TU2_struct lzo_memops_TU2; #else struct lzo_memops_TU2_struct { unsigned char a[2]; } __lzo_may_alias; typedef struct lzo_memops_TU2_struct lzo_memops_TU2; #endif #ifndef lzo_memops_TU2p #define lzo_memops_TU2p lzo_memops_TU2 * #endif #endif #ifndef lzo_memops_TU4p #if (LZO_OPT_UNALIGNED32) typedef lzo_uint32_t __lzo_may_alias lzo_memops_TU4; #define lzo_memops_TU4p volatile lzo_memops_TU4 __LZO_MMODEL * #elif defined(__lzo_byte_struct) __lzo_byte_struct(lzo_memops_TU4_struct,4) typedef struct lzo_memops_TU4_struct lzo_memops_TU4; #else struct lzo_memops_TU4_struct { unsigned char a[4]; } __lzo_may_alias; typedef struct lzo_memops_TU4_struct lzo_memops_TU4; #endif #ifndef lzo_memops_TU4p #define lzo_memops_TU4p lzo_memops_TU4 __LZO_MMODEL * #endif #endif #ifndef lzo_memops_TU8p #if (LZO_OPT_UNALIGNED64) typedef lzo_uint64_t __lzo_may_alias lzo_memops_TU8; #define lzo_memops_TU8p volatile lzo_memops_TU8 __LZO_MMODEL * #elif defined(__lzo_byte_struct) __lzo_byte_struct(lzo_memops_TU8_struct,8) typedef struct lzo_memops_TU8_struct lzo_memops_TU8; #else struct lzo_memops_TU8_struct { unsigned char a[8]; } __lzo_may_alias; typedef struct lzo_memops_TU8_struct lzo_memops_TU8; #endif #ifndef lzo_memops_TU8p #define lzo_memops_TU8p lzo_memops_TU8 __LZO_MMODEL * #endif #endif #ifndef lzo_memops_set_TU1p #define lzo_memops_set_TU1p volatile lzo_memops_TU1p #endif #ifndef lzo_memops_move_TU1p #define lzo_memops_move_TU1p lzo_memops_TU1p #endif #define LZO_MEMOPS_SET1(dd,cc) \ LZO_BLOCK_BEGIN \ lzo_memops_set_TU1p d__1 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ d__1[0] = LZO_BYTE(cc); \ LZO_BLOCK_END #define LZO_MEMOPS_SET2(dd,cc) \ LZO_BLOCK_BEGIN \ lzo_memops_set_TU1p d__2 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ d__2[0] = LZO_BYTE(cc); d__2[1] = LZO_BYTE(cc); \ LZO_BLOCK_END #define LZO_MEMOPS_SET3(dd,cc) \ LZO_BLOCK_BEGIN \ lzo_memops_set_TU1p d__3 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ d__3[0] = LZO_BYTE(cc); d__3[1] = LZO_BYTE(cc); d__3[2] = LZO_BYTE(cc); \ LZO_BLOCK_END #define LZO_MEMOPS_SET4(dd,cc) \ LZO_BLOCK_BEGIN \ lzo_memops_set_TU1p d__4 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ d__4[0] = LZO_BYTE(cc); d__4[1] = LZO_BYTE(cc); d__4[2] = LZO_BYTE(cc); d__4[3] = LZO_BYTE(cc); \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE1(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__1 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__1 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__1[0] = s__1[0]; \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE2(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__2 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__2 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__2[0] = s__2[0]; d__2[1] = s__2[1]; \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE3(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__3 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__3 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__3[0] = s__3[0]; d__3[1] = s__3[1]; d__3[2] = s__3[2]; \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE4(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__4 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__4 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__4[0] = s__4[0]; d__4[1] = s__4[1]; d__4[2] = s__4[2]; d__4[3] = s__4[3]; \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE8(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__8 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__8 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__8[0] = s__8[0]; d__8[1] = s__8[1]; d__8[2] = s__8[2]; d__8[3] = s__8[3]; \ d__8[4] = s__8[4]; d__8[5] = s__8[5]; d__8[6] = s__8[6]; d__8[7] = s__8[7]; \ LZO_BLOCK_END LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU1p)0)==1) #define LZO_MEMOPS_COPY1(dd,ss) LZO_MEMOPS_MOVE1(dd,ss) #if (LZO_OPT_UNALIGNED16) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) #define LZO_MEMOPS_COPY2(dd,ss) \ * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) #elif defined(lzo_memops_tcheck__) #define LZO_MEMOPS_COPY2(dd,ss) \ LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU2,2,1)) { \ * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss); \ } else { LZO_MEMOPS_MOVE2(dd,ss); } LZO_BLOCK_END #else #define LZO_MEMOPS_COPY2(dd,ss) LZO_MEMOPS_MOVE2(dd,ss) #endif #if (LZO_OPT_UNALIGNED32) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) #define LZO_MEMOPS_COPY4(dd,ss) \ * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) #elif defined(lzo_memops_tcheck__) #define LZO_MEMOPS_COPY4(dd,ss) \ LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU4,4,1)) { \ * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss); \ } else { LZO_MEMOPS_MOVE4(dd,ss); } LZO_BLOCK_END #else #define LZO_MEMOPS_COPY4(dd,ss) LZO_MEMOPS_MOVE4(dd,ss) #endif #if (LZO_WORDSIZE != 8) #define LZO_MEMOPS_COPY8(dd,ss) \ LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END #else #if (LZO_OPT_UNALIGNED64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) #define LZO_MEMOPS_COPY8(dd,ss) \ * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) #elif (LZO_OPT_UNALIGNED32) #define LZO_MEMOPS_COPY8(dd,ss) \ LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END #elif defined(lzo_memops_tcheck__) #define LZO_MEMOPS_COPY8(dd,ss) \ LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU8,8,1)) { \ * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss); \ } else { LZO_MEMOPS_MOVE8(dd,ss); } LZO_BLOCK_END #else #define LZO_MEMOPS_COPY8(dd,ss) LZO_MEMOPS_MOVE8(dd,ss) #endif #endif #define LZO_MEMOPS_COPYN(dd,ss,nn) \ LZO_BLOCK_BEGIN \ lzo_memops_TU1p d__n = (lzo_memops_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_TU1p s__n = (const lzo_memops_TU1p) (const lzo_memops_TU0p) (ss); \ lzo_uint n__n = (nn); \ while ((void)0, n__n >= 8) { LZO_MEMOPS_COPY8(d__n, s__n); d__n += 8; s__n += 8; n__n -= 8; } \ if ((void)0, n__n >= 4) { LZO_MEMOPS_COPY4(d__n, s__n); d__n += 4; s__n += 4; n__n -= 4; } \ if ((void)0, n__n > 0) do { *d__n++ = *s__n++; } while (--n__n > 0); \ LZO_BLOCK_END __lzo_static_forceinline lzo_uint16_t lzo_memops_get_le16(const lzo_voidp ss) { lzo_uint16_t v; #if (LZO_ABI_LITTLE_ENDIAN) LZO_MEMOPS_COPY2(&v, ss); #elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) const lzo_memops_TU2p s = (const lzo_memops_TU2p) ss; unsigned long vv; __asm__("lhbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); v = (lzo_uint16_t) vv; #else const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; v = (lzo_uint16_t) (((lzo_uint16_t)s[0]) | ((lzo_uint16_t)s[1] << 8)); #endif return v; } #if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_GET_LE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)) #else #define LZO_MEMOPS_GET_LE16(ss) lzo_memops_get_le16(ss) #endif __lzo_static_forceinline lzo_uint32_t lzo_memops_get_le32(const lzo_voidp ss) { lzo_uint32_t v; #if (LZO_ABI_LITTLE_ENDIAN) LZO_MEMOPS_COPY4(&v, ss); #elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) const lzo_memops_TU4p s = (const lzo_memops_TU4p) ss; unsigned long vv; __asm__("lwbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); v = (lzo_uint32_t) vv; #else const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; v = (lzo_uint32_t) (((lzo_uint32_t)s[0]) | ((lzo_uint32_t)s[1] << 8) | ((lzo_uint32_t)s[2] << 16) | ((lzo_uint32_t)s[3] << 24)); #endif return v; } #if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_GET_LE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)) #else #define LZO_MEMOPS_GET_LE32(ss) lzo_memops_get_le32(ss) #endif #if (LZO_OPT_UNALIGNED64) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_GET_LE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)) #endif __lzo_static_forceinline lzo_uint16_t lzo_memops_get_ne16(const lzo_voidp ss) { lzo_uint16_t v; LZO_MEMOPS_COPY2(&v, ss); return v; } #if (LZO_OPT_UNALIGNED16) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) #define LZO_MEMOPS_GET_NE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)) #else #define LZO_MEMOPS_GET_NE16(ss) lzo_memops_get_ne16(ss) #endif __lzo_static_forceinline lzo_uint32_t lzo_memops_get_ne32(const lzo_voidp ss) { lzo_uint32_t v; LZO_MEMOPS_COPY4(&v, ss); return v; } #if (LZO_OPT_UNALIGNED32) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) #define LZO_MEMOPS_GET_NE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)) #else #define LZO_MEMOPS_GET_NE32(ss) lzo_memops_get_ne32(ss) #endif #if (LZO_OPT_UNALIGNED64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) #define LZO_MEMOPS_GET_NE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)) #endif __lzo_static_forceinline void lzo_memops_put_le16(lzo_voidp dd, lzo_uint16_t vv) { #if (LZO_ABI_LITTLE_ENDIAN) LZO_MEMOPS_COPY2(dd, &vv); #elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) lzo_memops_TU2p d = (lzo_memops_TU2p) dd; unsigned long v = vv; __asm__("sthbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); #else lzo_memops_TU1p d = (lzo_memops_TU1p) dd; d[0] = LZO_BYTE((vv ) & 0xff); d[1] = LZO_BYTE((vv >> 8) & 0xff); #endif } #if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_PUT_LE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) #else #define LZO_MEMOPS_PUT_LE16(dd,vv) lzo_memops_put_le16(dd,vv) #endif __lzo_static_forceinline void lzo_memops_put_le32(lzo_voidp dd, lzo_uint32_t vv) { #if (LZO_ABI_LITTLE_ENDIAN) LZO_MEMOPS_COPY4(dd, &vv); #elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) lzo_memops_TU4p d = (lzo_memops_TU4p) dd; unsigned long v = vv; __asm__("stwbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); #else lzo_memops_TU1p d = (lzo_memops_TU1p) dd; d[0] = LZO_BYTE((vv ) & 0xff); d[1] = LZO_BYTE((vv >> 8) & 0xff); d[2] = LZO_BYTE((vv >> 16) & 0xff); d[3] = LZO_BYTE((vv >> 24) & 0xff); #endif } #if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_PUT_LE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) #else #define LZO_MEMOPS_PUT_LE32(dd,vv) lzo_memops_put_le32(dd,vv) #endif __lzo_static_forceinline void lzo_memops_put_ne16(lzo_voidp dd, lzo_uint16_t vv) { LZO_MEMOPS_COPY2(dd, &vv); } #if (LZO_OPT_UNALIGNED16) #define LZO_MEMOPS_PUT_NE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) #else #define LZO_MEMOPS_PUT_NE16(dd,vv) lzo_memops_put_ne16(dd,vv) #endif __lzo_static_forceinline void lzo_memops_put_ne32(lzo_voidp dd, lzo_uint32_t vv) { LZO_MEMOPS_COPY4(dd, &vv); } #if (LZO_OPT_UNALIGNED32) #define LZO_MEMOPS_PUT_NE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) #else #define LZO_MEMOPS_PUT_NE32(dd,vv) lzo_memops_put_ne32(dd,vv) #endif lzo_unused_funcs_impl(void, lzo_memops_unused_funcs)(void) { LZO_UNUSED_FUNC(lzo_memops_unused_funcs); LZO_UNUSED_FUNC(lzo_memops_get_le16); LZO_UNUSED_FUNC(lzo_memops_get_le32); LZO_UNUSED_FUNC(lzo_memops_get_ne16); LZO_UNUSED_FUNC(lzo_memops_get_ne32); LZO_UNUSED_FUNC(lzo_memops_put_le16); LZO_UNUSED_FUNC(lzo_memops_put_le32); LZO_UNUSED_FUNC(lzo_memops_put_ne16); LZO_UNUSED_FUNC(lzo_memops_put_ne32); } #endif #ifndef UA_SET1 #define UA_SET1 LZO_MEMOPS_SET1 #endif #ifndef UA_SET2 #define UA_SET2 LZO_MEMOPS_SET2 #endif #ifndef UA_SET3 #define UA_SET3 LZO_MEMOPS_SET3 #endif #ifndef UA_SET4 #define UA_SET4 LZO_MEMOPS_SET4 #endif #ifndef UA_MOVE1 #define UA_MOVE1 LZO_MEMOPS_MOVE1 #endif #ifndef UA_MOVE2 #define UA_MOVE2 LZO_MEMOPS_MOVE2 #endif #ifndef UA_MOVE3 #define UA_MOVE3 LZO_MEMOPS_MOVE3 #endif #ifndef UA_MOVE4 #define UA_MOVE4 LZO_MEMOPS_MOVE4 #endif #ifndef UA_MOVE8 #define UA_MOVE8 LZO_MEMOPS_MOVE8 #endif #ifndef UA_COPY1 #define UA_COPY1 LZO_MEMOPS_COPY1 #endif #ifndef UA_COPY2 #define UA_COPY2 LZO_MEMOPS_COPY2 #endif #ifndef UA_COPY3 #define UA_COPY3 LZO_MEMOPS_COPY3 #endif #ifndef UA_COPY4 #define UA_COPY4 LZO_MEMOPS_COPY4 #endif #ifndef UA_COPY8 #define UA_COPY8 LZO_MEMOPS_COPY8 #endif #ifndef UA_COPYN #define UA_COPYN LZO_MEMOPS_COPYN #endif #ifndef UA_COPYN_X #define UA_COPYN_X LZO_MEMOPS_COPYN #endif #ifndef UA_GET_LE16 #define UA_GET_LE16 LZO_MEMOPS_GET_LE16 #endif #ifndef UA_GET_LE32 #define UA_GET_LE32 LZO_MEMOPS_GET_LE32 #endif #ifdef LZO_MEMOPS_GET_LE64 #ifndef UA_GET_LE64 #define UA_GET_LE64 LZO_MEMOPS_GET_LE64 #endif #endif #ifndef UA_GET_NE16 #define UA_GET_NE16 LZO_MEMOPS_GET_NE16 #endif #ifndef UA_GET_NE32 #define UA_GET_NE32 LZO_MEMOPS_GET_NE32 #endif #ifdef LZO_MEMOPS_GET_NE64 #ifndef UA_GET_NE64 #define UA_GET_NE64 LZO_MEMOPS_GET_NE64 #endif #endif #ifndef UA_PUT_LE16 #define UA_PUT_LE16 LZO_MEMOPS_PUT_LE16 #endif #ifndef UA_PUT_LE32 #define UA_PUT_LE32 LZO_MEMOPS_PUT_LE32 #endif #ifndef UA_PUT_NE16 #define UA_PUT_NE16 LZO_MEMOPS_PUT_NE16 #endif #ifndef UA_PUT_NE32 #define UA_PUT_NE32 LZO_MEMOPS_PUT_NE32 #endif #define MEMCPY8_DS(dest,src,len) \ lzo_memcpy(dest,src,len); dest += len; src += len #define BZERO8_PTR(s,l,n) \ lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) #define MEMCPY_DS(dest,src,len) \ do *dest++ = *src++; while (--len > 0) LZO_EXTERN(const lzo_bytep) lzo_copyright(void); #ifndef __LZO_PTR_H #define __LZO_PTR_H 1 #ifdef __cplusplus extern "C" { #endif #if (LZO_ARCH_I086) #error "LZO_ARCH_I086 is unsupported" #elif (LZO_MM_PVP) #error "LZO_MM_PVP is unsupported" #else #define PTR(a) ((lzo_uintptr_t) (a)) #define PTR_LINEAR(a) PTR(a) #define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) #define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) #define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) #define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) #endif #define PTR_LT(a,b) (PTR(a) < PTR(b)) #define PTR_GE(a,b) (PTR(a) >= PTR(b)) #define PTR_DIFF(a,b) (PTR(a) - PTR(b)) #define pd(a,b) ((lzo_uint) ((a)-(b))) LZO_EXTERN(lzo_uintptr_t) __lzo_ptr_linear(const lzo_voidp ptr); typedef union { char a_char; unsigned char a_uchar; short a_short; unsigned short a_ushort; int a_int; unsigned int a_uint; long a_long; unsigned long a_ulong; lzo_int a_lzo_int; lzo_uint a_lzo_uint; lzo_xint a_lzo_xint; lzo_int16_t a_lzo_int16_t; lzo_uint16_t a_lzo_uint16_t; lzo_int32_t a_lzo_int32_t; lzo_uint32_t a_lzo_uint32_t; #if defined(lzo_uint64_t) lzo_int64_t a_lzo_int64_t; lzo_uint64_t a_lzo_uint64_t; #endif size_t a_size_t; ptrdiff_t a_ptrdiff_t; lzo_uintptr_t a_lzo_uintptr_t; void * a_void_p; char * a_char_p; unsigned char * a_uchar_p; const void * a_c_void_p; const char * a_c_char_p; const unsigned char * a_c_uchar_p; lzo_voidp a_lzo_voidp; lzo_bytep a_lzo_bytep; const lzo_voidp a_c_lzo_voidp; const lzo_bytep a_c_lzo_bytep; } lzo_full_align_t; #ifdef __cplusplus } #endif #endif #ifndef LZO_DETERMINISTIC #define LZO_DETERMINISTIC 1 #endif #ifndef LZO_DICT_USE_PTR #define LZO_DICT_USE_PTR 1 #endif #if (LZO_DICT_USE_PTR) # define lzo_dict_t const lzo_bytep # define lzo_dict_p lzo_dict_t * #else # define lzo_dict_t lzo_uint # define lzo_dict_p lzo_dict_t * #endif #endif #if !defined(MINILZO_CFG_SKIP_LZO_PTR) LZO_PUBLIC(lzo_uintptr_t) __lzo_ptr_linear(const lzo_voidp ptr) { lzo_uintptr_t p; #if (LZO_ARCH_I086) #error "LZO_ARCH_I086 is unsupported" #elif (LZO_MM_PVP) #error "LZO_MM_PVP is unsupported" #else p = (lzo_uintptr_t) PTR_LINEAR(ptr); #endif return p; } LZO_PUBLIC(unsigned) __lzo_align_gap(const lzo_voidp ptr, lzo_uint size) { #if (__LZO_UINTPTR_T_IS_POINTER) #error "__LZO_UINTPTR_T_IS_POINTER is unsupported" #else lzo_uintptr_t p, n; if (size < 2) return 0; p = __lzo_ptr_linear(ptr); #if 0 n = (((p + size - 1) / size) * size) - p; #else if ((size & (size - 1)) != 0) return 0; n = size; n = ((p + n - 1) & ~(n - 1)) - p; #endif #endif assert((long)n >= 0); assert(n <= size); return (unsigned)n; } #endif #if !defined(MINILZO_CFG_SKIP_LZO_UTIL) /* If you use the LZO library in a product, I would appreciate that you * keep this copyright string in the executable of your product. */ static const char lzo_copyright_[] = #if !defined(__LZO_IN_MINLZO) LZO_VERSION_STRING; #else "\r\n\n" "LZO data compression library.\n" "$Copyright: LZO Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer\n" "\n" "http://www.oberhumer.com $\n\n" "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" "$Info: " LZO_INFO_STRING " $\n"; #endif static const char lzo_version_string_[] = LZO_VERSION_STRING; static const char lzo_version_date_[] = LZO_VERSION_DATE; LZO_PUBLIC(const lzo_bytep) lzo_copyright(void) { return (const lzo_bytep) lzo_copyright_; } LZO_PUBLIC(unsigned) lzo_version(void) { return LZO_VERSION; } LZO_PUBLIC(const char *) lzo_version_string(void) { return lzo_version_string_; } LZO_PUBLIC(const char *) lzo_version_date(void) { return lzo_version_date_; } LZO_PUBLIC(const lzo_charp) _lzo_version_string(void) { return lzo_version_string_; } LZO_PUBLIC(const lzo_charp) _lzo_version_date(void) { return lzo_version_date_; } #define LZO_BASE 65521u #define LZO_NMAX 5552 #define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 #define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1) #define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2) #define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4) #define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8) LZO_PUBLIC(lzo_uint32_t) lzo_adler32(lzo_uint32_t adler, const lzo_bytep buf, lzo_uint len) { lzo_uint32_t s1 = adler & 0xffff; lzo_uint32_t s2 = (adler >> 16) & 0xffff; unsigned k; if (buf == NULL) return 1; while (len > 0) { k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; len -= k; if (k >= 16) do { LZO_DO16(buf,0); buf += 16; k -= 16; } while (k >= 16); if (k != 0) do { s1 += *buf++; s2 += s1; } while (--k > 0); s1 %= LZO_BASE; s2 %= LZO_BASE; } return (s2 << 16) | s1; } #undef LZO_DO1 #undef LZO_DO2 #undef LZO_DO4 #undef LZO_DO8 #undef LZO_DO16 #endif #if !defined(MINILZO_CFG_SKIP_LZO_STRING) #undef lzo_memcmp #undef lzo_memcpy #undef lzo_memmove #undef lzo_memset #if !defined(__LZO_MMODEL_HUGE) # undef LZO_HAVE_MM_HUGE_PTR #endif #define lzo_hsize_t lzo_uint #define lzo_hvoid_p lzo_voidp #define lzo_hbyte_p lzo_bytep #define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f #define lzo_hmemcmp lzo_memcmp #define lzo_hmemcpy lzo_memcpy #define lzo_hmemmove lzo_memmove #define lzo_hmemset lzo_memset #define __LZOLIB_HMEMCPY_CH_INCLUDED 1 #if !defined(LZOLIB_PUBLIC) # define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) #endif LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP) const lzo_hbyte_p p1 = LZO_STATIC_CAST(const lzo_hbyte_p, s1); const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, s2); if __lzo_likely(len > 0) do { int d = *p1 - *p2; if (d != 0) return d; p1++; p2++; } while __lzo_likely(--len > 0); return 0; #else return memcmp(s1, s2, len); #endif } LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY) lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); if (!(len > 0) || p1 == p2) return dest; do *p1++ = *p2++; while __lzo_likely(--len > 0); return dest; #else return memcpy(dest, src, len); #endif } LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE) lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); if (!(len > 0) || p1 == p2) return dest; if (p1 < p2) { do *p1++ = *p2++; while __lzo_likely(--len > 0); } else { p1 += len; p2 += len; do *--p1 = *--p2; while __lzo_likely(--len > 0); } return dest; #else return memmove(dest, src, len); #endif } LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int cc, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET) lzo_hbyte_p p = LZO_STATIC_CAST(lzo_hbyte_p, s); unsigned char c = LZO_ITRUNC(unsigned char, cc); if __lzo_likely(len > 0) do *p++ = c; while __lzo_likely(--len > 0); return s; #else return memset(s, cc, len); #endif } #undef LZOLIB_PUBLIC #endif #if !defined(MINILZO_CFG_SKIP_LZO_INIT) #if !defined(__LZO_IN_MINILZO) #define LZO_WANT_ACC_CHK_CH 1 #undef LZOCHK_ASSERT LZOCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) LZOCHK_ASSERT_IS_SIGNED_T(lzo_int) LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) #if !(__LZO_UINTPTR_T_IS_POINTER) LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) #endif LZOCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) #endif #undef LZOCHK_ASSERT union lzo_config_check_union { lzo_uint a[2]; unsigned char b[2*LZO_MAX(8,sizeof(lzo_uint))]; #if defined(lzo_uint64_t) lzo_uint64_t c[2]; #endif }; #if 0 #define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off))) #else static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off) { return (lzo_voidp) ((lzo_bytep) ptr + off); } #endif LZO_PUBLIC(int) _lzo_config_check(void) { #if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030100ul && LZO_CC_CLANG < 0x030300ul)) # if 0 volatile # endif #endif union lzo_config_check_union u; lzo_voidp p; unsigned r = 1; u.a[0] = u.a[1] = 0; p = u2p(&u, 0); r &= ((* (lzo_bytep) p) == 0); #if !(LZO_CFG_NO_CONFIG_CHECK) #if (LZO_ABI_BIG_ENDIAN) u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128; p = u2p(&u, 0); r &= ((* (lzo_uintp) p) == 128); #endif #if (LZO_ABI_LITTLE_ENDIAN) u.a[0] = u.a[1] = 0; u.b[0] = 128; p = u2p(&u, 0); r &= ((* (lzo_uintp) p) == 128); #endif u.a[0] = u.a[1] = 0; u.b[0] = 1; u.b[3] = 2; p = u2p(&u, 1); r &= UA_GET_NE16(p) == 0; r &= UA_GET_LE16(p) == 0; u.b[1] = 128; r &= UA_GET_LE16(p) == 128; u.b[2] = 129; r &= UA_GET_LE16(p) == LZO_UINT16_C(0x8180); #if (LZO_ABI_BIG_ENDIAN) r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8081); #endif #if (LZO_ABI_LITTLE_ENDIAN) r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8180); #endif u.a[0] = u.a[1] = 0; u.b[0] = 3; u.b[5] = 4; p = u2p(&u, 1); r &= UA_GET_NE32(p) == 0; r &= UA_GET_LE32(p) == 0; u.b[1] = 128; r &= UA_GET_LE32(p) == 128; u.b[2] = 129; u.b[3] = 130; u.b[4] = 131; r &= UA_GET_LE32(p) == LZO_UINT32_C(0x83828180); #if (LZO_ABI_BIG_ENDIAN) r &= UA_GET_NE32(p) == LZO_UINT32_C(0x80818283); #endif #if (LZO_ABI_LITTLE_ENDIAN) r &= UA_GET_NE32(p) == LZO_UINT32_C(0x83828180); #endif #if defined(UA_GET_NE64) u.c[0] = u.c[1] = 0; u.b[0] = 5; u.b[9] = 6; p = u2p(&u, 1); u.c[0] = u.c[1] = 0; r &= UA_GET_NE64(p) == 0; #if defined(UA_GET_LE64) r &= UA_GET_LE64(p) == 0; u.b[1] = 128; r &= UA_GET_LE64(p) == 128; #endif #endif #if defined(lzo_bitops_ctlz32) { unsigned i = 0; lzo_uint32_t v; for (v = 1; v != 0 && r == 1; v <<= 1, i++) { r &= lzo_bitops_ctlz32(v) == 31 - i; r &= lzo_bitops_ctlz32_func(v) == 31 - i; }} #endif #if defined(lzo_bitops_ctlz64) { unsigned i = 0; lzo_uint64_t v; for (v = 1; v != 0 && r == 1; v <<= 1, i++) { r &= lzo_bitops_ctlz64(v) == 63 - i; r &= lzo_bitops_ctlz64_func(v) == 63 - i; }} #endif #if defined(lzo_bitops_cttz32) { unsigned i = 0; lzo_uint32_t v; for (v = 1; v != 0 && r == 1; v <<= 1, i++) { r &= lzo_bitops_cttz32(v) == i; r &= lzo_bitops_cttz32_func(v) == i; }} #endif #if defined(lzo_bitops_cttz64) { unsigned i = 0; lzo_uint64_t v; for (v = 1; v != 0 && r == 1; v <<= 1, i++) { r &= lzo_bitops_cttz64(v) == i; r &= lzo_bitops_cttz64_func(v) == i; }} #endif #endif LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); return r == 1 ? LZO_E_OK : LZO_E_ERROR; } LZO_PUBLIC(int) __lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, int s6, int s7, int s8, int s9) { int r; #if defined(__LZO_IN_MINILZO) #elif (LZO_CC_MSC && ((_MSC_VER) < 700)) #else #define LZO_WANT_ACC_CHK_CH 1 #undef LZOCHK_ASSERT #define LZOCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) #endif #undef LZOCHK_ASSERT if (v == 0) return LZO_E_ERROR; r = (s1 == -1 || s1 == (int) sizeof(short)) && (s2 == -1 || s2 == (int) sizeof(int)) && (s3 == -1 || s3 == (int) sizeof(long)) && (s4 == -1 || s4 == (int) sizeof(lzo_uint32_t)) && (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && (s7 == -1 || s7 == (int) sizeof(char *)) && (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); if (!r) return LZO_E_ERROR; r = _lzo_config_check(); if (r != LZO_E_OK) return r; return r; } #if !defined(__LZO_IN_MINILZO) #if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) #if 0 BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, WORD wHeapSize, LPSTR lpszCmdLine ) #else int __far __pascal LibMain ( int a, short b, short c, long d ) #endif { LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); return 1; } #endif #endif #endif #define LZO1X 1 #define LZO_EOF_CODE 1 #define M2_MAX_OFFSET 0x0800 #if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) #if 1 && defined(UA_GET_LE32) #undef LZO_DICT_USE_PTR #define LZO_DICT_USE_PTR 0 #undef lzo_dict_t #define lzo_dict_t lzo_uint16_t #endif #define LZO_NEED_DICT_H 1 #ifndef D_BITS #define D_BITS 14 #endif #define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) #define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) #if 1 #define DINDEX(dv,p) DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS))) #else #define DINDEX(dv,p) DM((dv) + ((dv) >> (32-D_BITS))) #endif #ifndef __LZO_CONFIG1X_H #define __LZO_CONFIG1X_H 1 #if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) # define LZO1X 1 #endif #if !defined(__LZO_IN_MINILZO) #include #endif #ifndef LZO_EOF_CODE #define LZO_EOF_CODE 1 #endif #undef LZO_DETERMINISTIC #define M1_MAX_OFFSET 0x0400 #ifndef M2_MAX_OFFSET #define M2_MAX_OFFSET 0x0800 #endif #define M3_MAX_OFFSET 0x4000 #define M4_MAX_OFFSET 0xbfff #define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) #define M1_MIN_LEN 2 #define M1_MAX_LEN 2 #define M2_MIN_LEN 3 #ifndef M2_MAX_LEN #define M2_MAX_LEN 8 #endif #define M3_MIN_LEN 3 #define M3_MAX_LEN 33 #define M4_MIN_LEN 3 #define M4_MAX_LEN 9 #define M1_MARKER 0 #define M2_MARKER 64 #define M3_MARKER 32 #define M4_MARKER 16 #ifndef MIN_LOOKAHEAD #define MIN_LOOKAHEAD (M2_MAX_LEN + 1) #endif #if defined(LZO_NEED_DICT_H) #ifndef LZO_HASH #define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B #endif #define DL_MIN_LEN M2_MIN_LEN #ifndef __LZO_DICT_H #define __LZO_DICT_H 1 #ifdef __cplusplus extern "C" { #endif #if !defined(D_BITS) && defined(DBITS) # define D_BITS DBITS #endif #if !defined(D_BITS) # error "D_BITS is not defined" #endif #if (D_BITS < 16) # define D_SIZE LZO_SIZE(D_BITS) # define D_MASK LZO_MASK(D_BITS) #else # define D_SIZE LZO_USIZE(D_BITS) # define D_MASK LZO_UMASK(D_BITS) #endif #define D_HIGH ((D_MASK >> 1) + 1) #if !defined(DD_BITS) # define DD_BITS 0 #endif #define DD_SIZE LZO_SIZE(DD_BITS) #define DD_MASK LZO_MASK(DD_BITS) #if !defined(DL_BITS) # define DL_BITS (D_BITS - DD_BITS) #endif #if (DL_BITS < 16) # define DL_SIZE LZO_SIZE(DL_BITS) # define DL_MASK LZO_MASK(DL_BITS) #else # define DL_SIZE LZO_USIZE(DL_BITS) # define DL_MASK LZO_UMASK(DL_BITS) #endif #if (D_BITS != DL_BITS + DD_BITS) # error "D_BITS does not match" #endif #if (D_BITS < 6 || D_BITS > 18) # error "invalid D_BITS" #endif #if (DL_BITS < 6 || DL_BITS > 20) # error "invalid DL_BITS" #endif #if (DD_BITS < 0 || DD_BITS > 6) # error "invalid DD_BITS" #endif #if !defined(DL_MIN_LEN) # define DL_MIN_LEN 3 #endif #if !defined(DL_SHIFT) # define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) #endif #define LZO_HASH_GZIP 1 #define LZO_HASH_GZIP_INCREMENTAL 2 #define LZO_HASH_LZO_INCREMENTAL_A 3 #define LZO_HASH_LZO_INCREMENTAL_B 4 #if !defined(LZO_HASH) # error "choose a hashing strategy" #endif #undef DM #undef DX #if (DL_MIN_LEN == 3) # define _DV2_A(p,shift1,shift2) \ (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) # define _DV2_B(p,shift1,shift2) \ (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) # define _DV3_B(p,shift1,shift2,shift3) \ ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) #elif (DL_MIN_LEN == 2) # define _DV2_A(p,shift1,shift2) \ (( (lzo_xint)(p[0]) << shift1) ^ p[1]) # define _DV2_B(p,shift1,shift2) \ (( (lzo_xint)(p[1]) << shift1) ^ p[2]) #else # error "invalid DL_MIN_LEN" #endif #define _DV_A(p,shift) _DV2_A(p,shift,shift) #define _DV_B(p,shift) _DV2_B(p,shift,shift) #define DA2(p,s1,s2) \ (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) #define DS2(p,s1,s2) \ (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) #define DX2(p,s1,s2) \ (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) #define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) #define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) #define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) #define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) #define DM(v) DMS(v,0) #if (LZO_HASH == LZO_HASH_GZIP) # define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) #elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) # define __LZO_HASH_INCREMENTAL 1 # define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) # define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) # define _DINDEX(dv,p) (dv) # define DVAL_LOOKAHEAD DL_MIN_LEN #elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) # define __LZO_HASH_INCREMENTAL 1 # define DVAL_FIRST(dv,p) dv = _DV_A((p),5) # define DVAL_NEXT(dv,p) \ dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) # define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) # define DVAL_LOOKAHEAD DL_MIN_LEN #elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) # define __LZO_HASH_INCREMENTAL 1 # define DVAL_FIRST(dv,p) dv = _DV_B((p),5) # define DVAL_NEXT(dv,p) \ dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) # define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) # define DVAL_LOOKAHEAD DL_MIN_LEN #else # error "choose a hashing strategy" #endif #ifndef DINDEX #define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) #endif #if !defined(DINDEX1) && defined(D_INDEX1) #define DINDEX1 D_INDEX1 #endif #if !defined(DINDEX2) && defined(D_INDEX2) #define DINDEX2 D_INDEX2 #endif #if !defined(__LZO_HASH_INCREMENTAL) # define DVAL_FIRST(dv,p) ((void) 0) # define DVAL_NEXT(dv,p) ((void) 0) # define DVAL_LOOKAHEAD 0 #endif #if !defined(DVAL_ASSERT) #if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) #if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) static void __attribute__((__unused__)) #else static void #endif DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) { lzo_xint df; DVAL_FIRST(df,(p)); assert(DINDEX(dv,p) == DINDEX(df,p)); } #else # define DVAL_ASSERT(dv,p) ((void) 0) #endif #endif #if (LZO_DICT_USE_PTR) # define DENTRY(p,in) (p) # define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] #else # define DENTRY(p,in) ((lzo_dict_t) pd(p, in)) # define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] #endif #if (DD_BITS == 0) # define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) # define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) # define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) #else # define UPDATE_D(dict,drun,dv,p,in) \ dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK # define UPDATE_I(dict,drun,index,p,in) \ dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK # define UPDATE_P(ptr,drun,p,in) \ (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK #endif #if (LZO_DICT_USE_PTR) #define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) #define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ (BOUNDS_CHECKING_OFF_IN_EXPR(( \ m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ PTR_LT(m_pos,in) || \ (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \ m_off > max_offset ))) #else #define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ (m_off == 0 || \ ((m_off = pd(ip, in) - m_off) > max_offset) || \ (m_pos = (ip) - (m_off), 0) ) #define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ (pd(ip, in) <= m_off || \ ((m_off = pd(ip, in) - m_off) > max_offset) || \ (m_pos = (ip) - (m_off), 0) ) #endif #if (LZO_DETERMINISTIC) # define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET #else # define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET #endif #ifdef __cplusplus } #endif #endif #endif #endif #define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR) #ifndef DO_COMPRESS #define DO_COMPRESS lzo1x_1_compress #endif #if 1 && defined(DO_COMPRESS) && !defined(do_compress) # define do_compress LZO_PP_ECONCAT2(DO_COMPRESS,_core) #endif static __lzo_noinline lzo_uint do_compress ( const lzo_bytep in , lzo_uint in_len, lzo_bytep out, lzo_uintp out_len, lzo_uint ti, lzo_voidp wrkmem) { const lzo_bytep ip; lzo_bytep op; const lzo_bytep const in_end = in + in_len; const lzo_bytep const ip_end = in + in_len - 20; const lzo_bytep ii; lzo_dict_p const dict = (lzo_dict_p) wrkmem; op = out; ip = in; ii = ip; ip += ti < 4 ? 4 - ti : 0; for (;;) { const lzo_bytep m_pos; #if !(LZO_DETERMINISTIC) LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0); lzo_uint m_len; lzo_uint dindex; next: if __lzo_unlikely(ip >= ip_end) break; DINDEX1(dindex,ip); GINDEX(m_pos,m_off,dict,dindex,in); if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) goto literal; #if 1 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) goto try_match; DINDEX2(dindex,ip); #endif GINDEX(m_pos,m_off,dict,dindex,in); if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) goto literal; if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) goto try_match; goto literal; try_match: #if (LZO_OPT_UNALIGNED32) if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip)) #else if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3]) #endif { literal: UPDATE_I(dict,0,dindex,ip,in); ip += 1 + ((ip - ii) >> 5); continue; } UPDATE_I(dict,0,dindex,ip,in); #else lzo_uint m_off; lzo_uint m_len; { lzo_uint32_t dv; lzo_uint dindex; literal: ip += 1 + ((ip - ii) >> 5); next: if __lzo_unlikely(ip >= ip_end) break; dv = UA_GET_LE32(ip); dindex = DINDEX(dv,ip); GINDEX(m_off,m_pos,in+dict,dindex,in); UPDATE_I(dict,0,dindex,ip,in); if __lzo_unlikely(dv != UA_GET_LE32(m_pos)) goto literal; } #endif ii -= ti; ti = 0; { lzo_uint t = pd(ip,ii); if (t != 0) { if (t <= 3) { op[-2] = LZO_BYTE(op[-2] | t); #if (LZO_OPT_UNALIGNED32) UA_COPY4(op, ii); op += t; #else { do *op++ = *ii++; while (--t > 0); } #endif } #if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) else if (t <= 16) { *op++ = LZO_BYTE(t - 3); UA_COPY8(op, ii); UA_COPY8(op+8, ii+8); op += t; } #endif else { if (t <= 18) *op++ = LZO_BYTE(t - 3); else { lzo_uint tt = t - 18; *op++ = 0; while __lzo_unlikely(tt > 255) { tt -= 255; UA_SET1(op, 0); op++; } assert(tt > 0); *op++ = LZO_BYTE(tt); } #if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) do { UA_COPY8(op, ii); UA_COPY8(op+8, ii+8); op += 16; ii += 16; t -= 16; } while (t >= 16); if (t > 0) #endif { do *op++ = *ii++; while (--t > 0); } } } } m_len = 4; { #if (LZO_OPT_UNALIGNED64) lzo_uint64_t v; v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); if __lzo_unlikely(v == 0) { do { m_len += 8; v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); if __lzo_unlikely(ip + m_len >= ip_end) goto m_len_done; } while (v == 0); } #if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64) m_len += lzo_bitops_ctlz64(v) / CHAR_BIT; #elif (LZO_ABI_BIG_ENDIAN) if ((v >> (64 - CHAR_BIT)) == 0) do { v <<= CHAR_BIT; m_len += 1; } while ((v >> (64 - CHAR_BIT)) == 0); #elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64) m_len += lzo_bitops_cttz64(v) / CHAR_BIT; #elif (LZO_ABI_LITTLE_ENDIAN) if ((v & UCHAR_MAX) == 0) do { v >>= CHAR_BIT; m_len += 1; } while ((v & UCHAR_MAX) == 0); #else if (ip[m_len] == m_pos[m_len]) do { m_len += 1; } while (ip[m_len] == m_pos[m_len]); #endif #elif (LZO_OPT_UNALIGNED32) lzo_uint32_t v; v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); if __lzo_unlikely(v == 0) { do { m_len += 4; v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); if (v != 0) break; m_len += 4; v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); if __lzo_unlikely(ip + m_len >= ip_end) goto m_len_done; } while (v == 0); } #if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32) m_len += lzo_bitops_ctlz32(v) / CHAR_BIT; #elif (LZO_ABI_BIG_ENDIAN) if ((v >> (32 - CHAR_BIT)) == 0) do { v <<= CHAR_BIT; m_len += 1; } while ((v >> (32 - CHAR_BIT)) == 0); #elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32) m_len += lzo_bitops_cttz32(v) / CHAR_BIT; #elif (LZO_ABI_LITTLE_ENDIAN) if ((v & UCHAR_MAX) == 0) do { v >>= CHAR_BIT; m_len += 1; } while ((v & UCHAR_MAX) == 0); #else if (ip[m_len] == m_pos[m_len]) do { m_len += 1; } while (ip[m_len] == m_pos[m_len]); #endif #else if __lzo_unlikely(ip[m_len] == m_pos[m_len]) { do { m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if __lzo_unlikely(ip + m_len >= ip_end) goto m_len_done; } while (ip[m_len] == m_pos[m_len]); } #endif } m_len_done: m_off = pd(ip,m_pos); ip += m_len; ii = ip; if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) { m_off -= 1; #if defined(LZO1X) *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); *op++ = LZO_BYTE(m_off >> 3); #elif defined(LZO1Y) *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); *op++ = LZO_BYTE(m_off >> 2); #endif } else if (m_off <= M3_MAX_OFFSET) { m_off -= 1; if (m_len <= M3_MAX_LEN) *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); else { m_len -= M3_MAX_LEN; *op++ = M3_MARKER | 0; while __lzo_unlikely(m_len > 255) { m_len -= 255; UA_SET1(op, 0); op++; } *op++ = LZO_BYTE(m_len); } *op++ = LZO_BYTE(m_off << 2); *op++ = LZO_BYTE(m_off >> 6); } else { m_off -= 0x4000; if (m_len <= M4_MAX_LEN) *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2)); else { m_len -= M4_MAX_LEN; *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8)); while __lzo_unlikely(m_len > 255) { m_len -= 255; UA_SET1(op, 0); op++; } *op++ = LZO_BYTE(m_len); } *op++ = LZO_BYTE(m_off << 2); *op++ = LZO_BYTE(m_off >> 6); } goto next; } *out_len = pd(op, out); return pd(in_end,ii-ti); } LZO_PUBLIC(int) DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, lzo_bytep out, lzo_uintp out_len, lzo_voidp wrkmem ) { const lzo_bytep ip = in; lzo_bytep op = out; lzo_uint l = in_len; lzo_uint t = 0; while (l > 20) { lzo_uint ll = l; lzo_uintptr_t ll_end; #if 0 || (LZO_DETERMINISTIC) ll = LZO_MIN(ll, 49152); #endif ll_end = (lzo_uintptr_t)ip + ll; if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll) break; #if (LZO_DETERMINISTIC) lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t)); #endif t = do_compress(ip,ll,op,out_len,t,wrkmem); ip += ll; op += *out_len; l -= ll; } t += l; if (t > 0) { const lzo_bytep ii = in + in_len - t; if (op == out && t <= 238) *op++ = LZO_BYTE(17 + t); else if (t <= 3) op[-2] = LZO_BYTE(op[-2] | t); else if (t <= 18) *op++ = LZO_BYTE(t - 3); else { lzo_uint tt = t - 18; *op++ = 0; while (tt > 255) { tt -= 255; UA_SET1(op, 0); op++; } assert(tt > 0); *op++ = LZO_BYTE(tt); } UA_COPYN(op, ii, t); op += t; } *op++ = M4_MARKER | 1; *op++ = 0; *op++ = 0; *out_len = pd(op, out); return LZO_E_OK; } #endif #undef do_compress #undef DO_COMPRESS #undef LZO_HASH #undef LZO_TEST_OVERRUN #undef DO_DECOMPRESS #define DO_DECOMPRESS lzo1x_decompress #if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) #if defined(LZO_TEST_OVERRUN) # if !defined(LZO_TEST_OVERRUN_INPUT) # define LZO_TEST_OVERRUN_INPUT 2 # endif # if !defined(LZO_TEST_OVERRUN_OUTPUT) # define LZO_TEST_OVERRUN_OUTPUT 2 # endif # if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) # define LZO_TEST_OVERRUN_LOOKBEHIND 1 # endif #endif #undef TEST_IP #undef TEST_OP #undef TEST_IP_AND_TEST_OP #undef TEST_LB #undef TEST_LBO #undef NEED_IP #undef NEED_OP #undef TEST_IV #undef TEST_OV #undef HAVE_TEST_IP #undef HAVE_TEST_OP #undef HAVE_NEED_IP #undef HAVE_NEED_OP #undef HAVE_ANY_IP #undef HAVE_ANY_OP #if defined(LZO_TEST_OVERRUN_INPUT) # if (LZO_TEST_OVERRUN_INPUT >= 1) # define TEST_IP (ip < ip_end) # endif # if (LZO_TEST_OVERRUN_INPUT >= 2) # define NEED_IP(x) \ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun # define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_OUTPUT) # if (LZO_TEST_OVERRUN_OUTPUT >= 1) # define TEST_OP (op <= op_end) # endif # if (LZO_TEST_OVERRUN_OUTPUT >= 2) # undef TEST_OP # define NEED_OP(x) \ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun # define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) # define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun # define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun #else # define TEST_LB(m_pos) ((void) 0) # define TEST_LBO(m_pos,o) ((void) 0) #endif #if !defined(LZO_EOF_CODE) && !defined(TEST_IP) # define TEST_IP (ip < ip_end) #endif #if defined(TEST_IP) # define HAVE_TEST_IP 1 #else # define TEST_IP 1 #endif #if defined(TEST_OP) # define HAVE_TEST_OP 1 #else # define TEST_OP 1 #endif #if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) # define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) #elif defined(HAVE_TEST_IP) # define TEST_IP_AND_TEST_OP TEST_IP #elif defined(HAVE_TEST_OP) # define TEST_IP_AND_TEST_OP TEST_OP #else # define TEST_IP_AND_TEST_OP 1 #endif #if defined(NEED_IP) # define HAVE_NEED_IP 1 #else # define NEED_IP(x) ((void) 0) # define TEST_IV(x) ((void) 0) #endif #if defined(NEED_OP) # define HAVE_NEED_OP 1 #else # define NEED_OP(x) ((void) 0) # define TEST_OV(x) ((void) 0) #endif #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) # define HAVE_ANY_IP 1 #endif #if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) # define HAVE_ANY_OP 1 #endif #if defined(DO_DECOMPRESS) LZO_PUBLIC(int) DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, lzo_bytep out, lzo_uintp out_len, lzo_voidp wrkmem ) #endif { lzo_bytep op; const lzo_bytep ip; lzo_uint t; #if defined(COPY_DICT) lzo_uint m_off; const lzo_bytep dict_end; #else const lzo_bytep m_pos; #endif const lzo_bytep const ip_end = in + in_len; #if defined(HAVE_ANY_OP) lzo_bytep const op_end = out + *out_len; #endif #if defined(LZO1Z) lzo_uint last_m_off = 0; #endif LZO_UNUSED(wrkmem); #if defined(COPY_DICT) if (dict) { if (dict_len > M4_MAX_OFFSET) { dict += dict_len - M4_MAX_OFFSET; dict_len = M4_MAX_OFFSET; } dict_end = dict + dict_len; } else { dict_len = 0; dict_end = NULL; } #endif *out_len = 0; op = out; ip = in; NEED_IP(1); if (*ip > 17) { t = *ip++ - 17; if (t < 4) goto match_next; assert(t > 0); NEED_OP(t); NEED_IP(t+3); do *op++ = *ip++; while (--t > 0); goto first_literal_run; } for (;;) { NEED_IP(3); t = *ip++; if (t >= 16) goto match; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_IV(t); NEED_IP(1); } t += 15 + *ip++; } assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); #if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) t += 3; if (t >= 8) do { UA_COPY8(op,ip); op += 8; ip += 8; t -= 8; } while (t >= 8); if (t >= 4) { UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } if (t > 0) { *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } } #elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) #if !(LZO_OPT_UNALIGNED32) if (PTR_ALIGNED2_4(op,ip)) { #endif UA_COPY4(op,ip); op += 4; ip += 4; if (--t > 0) { if (t >= 4) { do { UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *ip++; while (--t > 0); } else do *op++ = *ip++; while (--t > 0); } #if !(LZO_OPT_UNALIGNED32) } else #endif #endif #if !(LZO_OPT_UNALIGNED32) { *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; do *op++ = *ip++; while (--t > 0); } #endif first_literal_run: t = *ip++; if (t >= 16) goto match; #if defined(COPY_DICT) #if defined(LZO1Z) m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); #endif NEED_OP(3); t = 3; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - (1 + M2_MAX_OFFSET); m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LB(m_pos); NEED_OP(3); *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; for (;;) { match: if (t >= 64) { #if defined(COPY_DICT) #if defined(LZO1X) m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); t = (t >> 5) - 1; #elif defined(LZO1Y) m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); t = (t >> 4) - 3; #elif defined(LZO1Z) m_off = t & 0x1f; if (m_off >= 0x1c) m_off = last_m_off; else { m_off = 1 + (m_off << 6) + (*ip++ >> 2); last_m_off = m_off; } t = (t >> 5) - 1; #endif #else #if defined(LZO1X) m_pos = op - 1; m_pos -= (t >> 2) & 7; m_pos -= *ip++ << 3; t = (t >> 5) - 1; #elif defined(LZO1Y) m_pos = op - 1; m_pos -= (t >> 2) & 3; m_pos -= *ip++ << 2; t = (t >> 4) - 3; #elif defined(LZO1Z) { lzo_uint off = t & 0x1f; m_pos = op; if (off >= 0x1c) { assert(last_m_off > 0); m_pos -= last_m_off; } else { off = 1 + (off << 6) + (*ip++ >> 2); m_pos -= off; last_m_off = off; } } t = (t >> 5) - 1; #endif TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); goto copy_match; #endif } else if (t >= 32) { t &= 31; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_OV(t); NEED_IP(1); } t += 31 + *ip++; NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); last_m_off = m_off; #else m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); #endif #else #if defined(LZO1Z) { lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); m_pos = op - off; last_m_off = off; } #elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos = op - 1; m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos = op - 1; m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif #endif ip += 2; } else if (t >= 16) { #if defined(COPY_DICT) m_off = (t & 8) << 11; #else m_pos = op; m_pos -= (t & 8) << 11; #endif t &= 7; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_OV(t); NEED_IP(1); } t += 7 + *ip++; NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) m_off += (ip[0] << 6) + (ip[1] >> 2); #else m_off += (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_off == 0) goto eof_found; m_off += 0x4000; #if defined(LZO1Z) last_m_off = m_off; #endif #else #if defined(LZO1Z) m_pos -= (ip[0] << 6) + (ip[1] >> 2); #elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_pos == op) goto eof_found; m_pos -= 0x4000; #if defined(LZO1Z) last_m_off = pd((const lzo_bytep)op, m_pos); #endif #endif } else { #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = 1 + (t >> 2) + (*ip++ << 2); #endif NEED_OP(2); t = 2; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = 1 + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - 1; m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LB(m_pos); NEED_OP(2); *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; } #if defined(COPY_DICT) NEED_OP(t+3-1); t += 3-1; COPY_DICT(t,m_off) #else TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); #if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) if (op - m_pos >= 8) { t += (3 - 1); if (t >= 8) do { UA_COPY8(op,m_pos); op += 8; m_pos += 8; t -= 8; } while (t >= 8); if (t >= 4) { UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } if (t > 0) { *op++ = m_pos[0]; if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } } } else #elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) #if !(LZO_OPT_UNALIGNED32) if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) { assert((op - m_pos) >= 4); #else if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { #endif UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4 - (3 - 1); do { UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *m_pos++; while (--t > 0); } else #endif { copy_match: *op++ = *m_pos++; *op++ = *m_pos++; do *op++ = *m_pos++; while (--t > 0); } #endif match_done: #if defined(LZO1Z) t = ip[-1] & 3; #else t = ip[-2] & 3; #endif if (t == 0) break; match_next: assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); #if 0 do *op++ = *ip++; while (--t > 0); #else *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } #endif t = *ip++; } } eof_found: *out_len = pd(op, out); return (ip == ip_end ? LZO_E_OK : (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); #if defined(HAVE_NEED_IP) input_overrun: *out_len = pd(op, out); return LZO_E_INPUT_OVERRUN; #endif #if defined(HAVE_NEED_OP) output_overrun: *out_len = pd(op, out); return LZO_E_OUTPUT_OVERRUN; #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) lookbehind_overrun: *out_len = pd(op, out); return LZO_E_LOOKBEHIND_OVERRUN; #endif } #endif #define LZO_TEST_OVERRUN 1 #undef DO_DECOMPRESS #define DO_DECOMPRESS lzo1x_decompress_safe #if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) #if defined(LZO_TEST_OVERRUN) # if !defined(LZO_TEST_OVERRUN_INPUT) # define LZO_TEST_OVERRUN_INPUT 2 # endif # if !defined(LZO_TEST_OVERRUN_OUTPUT) # define LZO_TEST_OVERRUN_OUTPUT 2 # endif # if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) # define LZO_TEST_OVERRUN_LOOKBEHIND 1 # endif #endif #undef TEST_IP #undef TEST_OP #undef TEST_IP_AND_TEST_OP #undef TEST_LB #undef TEST_LBO #undef NEED_IP #undef NEED_OP #undef TEST_IV #undef TEST_OV #undef HAVE_TEST_IP #undef HAVE_TEST_OP #undef HAVE_NEED_IP #undef HAVE_NEED_OP #undef HAVE_ANY_IP #undef HAVE_ANY_OP #if defined(LZO_TEST_OVERRUN_INPUT) # if (LZO_TEST_OVERRUN_INPUT >= 1) # define TEST_IP (ip < ip_end) # endif # if (LZO_TEST_OVERRUN_INPUT >= 2) # define NEED_IP(x) \ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun # define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_OUTPUT) # if (LZO_TEST_OVERRUN_OUTPUT >= 1) # define TEST_OP (op <= op_end) # endif # if (LZO_TEST_OVERRUN_OUTPUT >= 2) # undef TEST_OP # define NEED_OP(x) \ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun # define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) # define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun # define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun #else # define TEST_LB(m_pos) ((void) 0) # define TEST_LBO(m_pos,o) ((void) 0) #endif #if !defined(LZO_EOF_CODE) && !defined(TEST_IP) # define TEST_IP (ip < ip_end) #endif #if defined(TEST_IP) # define HAVE_TEST_IP 1 #else # define TEST_IP 1 #endif #if defined(TEST_OP) # define HAVE_TEST_OP 1 #else # define TEST_OP 1 #endif #if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) # define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) #elif defined(HAVE_TEST_IP) # define TEST_IP_AND_TEST_OP TEST_IP #elif defined(HAVE_TEST_OP) # define TEST_IP_AND_TEST_OP TEST_OP #else # define TEST_IP_AND_TEST_OP 1 #endif #if defined(NEED_IP) # define HAVE_NEED_IP 1 #else # define NEED_IP(x) ((void) 0) # define TEST_IV(x) ((void) 0) #endif #if defined(NEED_OP) # define HAVE_NEED_OP 1 #else # define NEED_OP(x) ((void) 0) # define TEST_OV(x) ((void) 0) #endif #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) # define HAVE_ANY_IP 1 #endif #if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) # define HAVE_ANY_OP 1 #endif #if defined(DO_DECOMPRESS) LZO_PUBLIC(int) DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, lzo_bytep out, lzo_uintp out_len, lzo_voidp wrkmem ) #endif { lzo_bytep op; const lzo_bytep ip; lzo_uint t; #if defined(COPY_DICT) lzo_uint m_off; const lzo_bytep dict_end; #else const lzo_bytep m_pos; #endif const lzo_bytep const ip_end = in + in_len; #if defined(HAVE_ANY_OP) lzo_bytep const op_end = out + *out_len; #endif #if defined(LZO1Z) lzo_uint last_m_off = 0; #endif LZO_UNUSED(wrkmem); #if defined(COPY_DICT) if (dict) { if (dict_len > M4_MAX_OFFSET) { dict += dict_len - M4_MAX_OFFSET; dict_len = M4_MAX_OFFSET; } dict_end = dict + dict_len; } else { dict_len = 0; dict_end = NULL; } #endif *out_len = 0; op = out; ip = in; NEED_IP(1); if (*ip > 17) { t = *ip++ - 17; if (t < 4) goto match_next; assert(t > 0); NEED_OP(t); NEED_IP(t+3); do *op++ = *ip++; while (--t > 0); goto first_literal_run; } for (;;) { NEED_IP(3); t = *ip++; if (t >= 16) goto match; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_IV(t); NEED_IP(1); } t += 15 + *ip++; } assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); #if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) t += 3; if (t >= 8) do { UA_COPY8(op,ip); op += 8; ip += 8; t -= 8; } while (t >= 8); if (t >= 4) { UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } if (t > 0) { *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } } #elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) #if !(LZO_OPT_UNALIGNED32) if (PTR_ALIGNED2_4(op,ip)) { #endif UA_COPY4(op,ip); op += 4; ip += 4; if (--t > 0) { if (t >= 4) { do { UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *ip++; while (--t > 0); } else do *op++ = *ip++; while (--t > 0); } #if !(LZO_OPT_UNALIGNED32) } else #endif #endif #if !(LZO_OPT_UNALIGNED32) { *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; do *op++ = *ip++; while (--t > 0); } #endif first_literal_run: t = *ip++; if (t >= 16) goto match; #if defined(COPY_DICT) #if defined(LZO1Z) m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); #endif NEED_OP(3); t = 3; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - (1 + M2_MAX_OFFSET); m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LB(m_pos); NEED_OP(3); *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; for (;;) { match: if (t >= 64) { #if defined(COPY_DICT) #if defined(LZO1X) m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); t = (t >> 5) - 1; #elif defined(LZO1Y) m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); t = (t >> 4) - 3; #elif defined(LZO1Z) m_off = t & 0x1f; if (m_off >= 0x1c) m_off = last_m_off; else { m_off = 1 + (m_off << 6) + (*ip++ >> 2); last_m_off = m_off; } t = (t >> 5) - 1; #endif #else #if defined(LZO1X) m_pos = op - 1; m_pos -= (t >> 2) & 7; m_pos -= *ip++ << 3; t = (t >> 5) - 1; #elif defined(LZO1Y) m_pos = op - 1; m_pos -= (t >> 2) & 3; m_pos -= *ip++ << 2; t = (t >> 4) - 3; #elif defined(LZO1Z) { lzo_uint off = t & 0x1f; m_pos = op; if (off >= 0x1c) { assert(last_m_off > 0); m_pos -= last_m_off; } else { off = 1 + (off << 6) + (*ip++ >> 2); m_pos -= off; last_m_off = off; } } t = (t >> 5) - 1; #endif TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); goto copy_match; #endif } else if (t >= 32) { t &= 31; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_OV(t); NEED_IP(1); } t += 31 + *ip++; NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); last_m_off = m_off; #else m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); #endif #else #if defined(LZO1Z) { lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); m_pos = op - off; last_m_off = off; } #elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos = op - 1; m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos = op - 1; m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif #endif ip += 2; } else if (t >= 16) { #if defined(COPY_DICT) m_off = (t & 8) << 11; #else m_pos = op; m_pos -= (t & 8) << 11; #endif t &= 7; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_OV(t); NEED_IP(1); } t += 7 + *ip++; NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) m_off += (ip[0] << 6) + (ip[1] >> 2); #else m_off += (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_off == 0) goto eof_found; m_off += 0x4000; #if defined(LZO1Z) last_m_off = m_off; #endif #else #if defined(LZO1Z) m_pos -= (ip[0] << 6) + (ip[1] >> 2); #elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_pos == op) goto eof_found; m_pos -= 0x4000; #if defined(LZO1Z) last_m_off = pd((const lzo_bytep)op, m_pos); #endif #endif } else { #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = 1 + (t >> 2) + (*ip++ << 2); #endif NEED_OP(2); t = 2; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = 1 + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - 1; m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LB(m_pos); NEED_OP(2); *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; } #if defined(COPY_DICT) NEED_OP(t+3-1); t += 3-1; COPY_DICT(t,m_off) #else TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); #if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) if (op - m_pos >= 8) { t += (3 - 1); if (t >= 8) do { UA_COPY8(op,m_pos); op += 8; m_pos += 8; t -= 8; } while (t >= 8); if (t >= 4) { UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } if (t > 0) { *op++ = m_pos[0]; if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } } } else #elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) #if !(LZO_OPT_UNALIGNED32) if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) { assert((op - m_pos) >= 4); #else if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { #endif UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4 - (3 - 1); do { UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *m_pos++; while (--t > 0); } else #endif { copy_match: *op++ = *m_pos++; *op++ = *m_pos++; do *op++ = *m_pos++; while (--t > 0); } #endif match_done: #if defined(LZO1Z) t = ip[-1] & 3; #else t = ip[-2] & 3; #endif if (t == 0) break; match_next: assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); #if 0 do *op++ = *ip++; while (--t > 0); #else *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } #endif t = *ip++; } } eof_found: *out_len = pd(op, out); return (ip == ip_end ? LZO_E_OK : (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); #if defined(HAVE_NEED_IP) input_overrun: *out_len = pd(op, out); return LZO_E_INPUT_OVERRUN; #endif #if defined(HAVE_NEED_OP) output_overrun: *out_len = pd(op, out); return LZO_E_OUTPUT_OVERRUN; #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) lookbehind_overrun: *out_len = pd(op, out); return LZO_E_LOOKBEHIND_OVERRUN; #endif } #endif /***** End of minilzo.c *****/ ntop-n2n-90215bd/src/n2n.c000066400000000000000000000666441422132035700151640ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #include "sn_selection.h" #include "minilzo.h" #include /* ************************************** */ SOCKET open_socket (int local_port, in_addr_t address, int type /* 0 = UDP, TCP otherwise */) { SOCKET sock_fd; struct sockaddr_in local_address; int sockopt; if((int)(sock_fd = socket(PF_INET, ((type == 0) ? SOCK_DGRAM : SOCK_STREAM) , 0)) < 0) { traceEvent(TRACE_ERROR, "Unable to create socket [%s][%d]\n", strerror(errno), sock_fd); return(-1); } #ifndef WIN32 /* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */ #endif sockopt = 1; setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt)); memset(&local_address, 0, sizeof(local_address)); local_address.sin_family = AF_INET; local_address.sin_port = htons(local_port); local_address.sin_addr.s_addr = htonl(address); if(bind(sock_fd,(struct sockaddr*) &local_address, sizeof(local_address)) == -1) { traceEvent(TRACE_ERROR, "Bind error on local port %u [%s]\n", local_port, strerror(errno)); return(-1); } return(sock_fd); } static int traceLevel = 2 /* NORMAL */; static int useSyslog = 0, syslog_opened = 0; static FILE *traceFile = NULL; int getTraceLevel () { return(traceLevel); } void setTraceLevel (int level) { traceLevel = level; } void setUseSyslog (int use_syslog) { useSyslog = use_syslog; } void setTraceFile (FILE *f) { traceFile = f; } void closeTraceFile () { if((traceFile != NULL) && (traceFile != stdout)) { fclose(traceFile); } #ifndef WIN32 if(useSyslog && syslog_opened) { closelog(); syslog_opened = 0; } #endif } #define N2N_TRACE_DATESIZE 32 void traceEvent (int eventTraceLevel, char* file, int line, char * format, ...) { va_list va_ap; if(traceFile == NULL) { traceFile = stdout; } if(eventTraceLevel <= traceLevel) { char buf[1024]; char out_buf[1280]; char theDate[N2N_TRACE_DATESIZE]; char *extra_msg = ""; time_t theTime = time(NULL); int i; /* We have two paths - one if we're logging, one if we aren't * Note that the no-log case is those systems which don't support it(WIN32), * those without the headers !defined(USE_SYSLOG) * those where it's parametrically off... */ memset(buf, 0, sizeof(buf)); strftime(theDate, N2N_TRACE_DATESIZE, "%d/%b/%Y %H:%M:%S", localtime(&theTime)); va_start(va_ap, format); vsnprintf(buf, sizeof(buf) - 1, format, va_ap); va_end(va_ap); if(eventTraceLevel == 0 /* TRACE_ERROR */) { extra_msg = "ERROR: "; } else if(eventTraceLevel == 1 /* TRACE_WARNING */) { extra_msg = "WARNING: "; } while(buf[strlen(buf) - 1] == '\n') { buf[strlen(buf) - 1] = '\0'; } #ifndef WIN32 if(useSyslog) { if(!syslog_opened) { openlog("n2n", LOG_PID, LOG_DAEMON); syslog_opened = 1; } snprintf(out_buf, sizeof(out_buf), "%s%s", extra_msg, buf); syslog(LOG_INFO, "%s", out_buf); } else { #endif for(i = strlen(file) - 1; i > 0; i--) { if((file[i] == '/') || (file[i] == '\\')) { i++; break; } } snprintf(out_buf, sizeof(out_buf), "%s [%s:%d] %s%s", theDate, &file[i], line, extra_msg, buf); fprintf(traceFile, "%s\n", out_buf); fflush(traceFile); #ifndef WIN32 } #endif } } /* *********************************************** */ /* addr should be in network order. Things are so much simpler that way. */ char* intoa (uint32_t /* host order */ addr, char* buf, uint16_t buf_len) { char *cp, *retStr; uint8_t byteval; int n; cp = &buf[buf_len]; *--cp = '\0'; n = 4; do { byteval = addr & 0xff; *--cp = byteval % 10 + '0'; byteval /= 10; if(byteval > 0) { *--cp = byteval % 10 + '0'; byteval /= 10; if(byteval > 0) { *--cp = byteval + '0'; } } *--cp = '.'; addr >>= 8; } while(--n > 0); /* Convert the string to lowercase */ retStr = (char*)(cp + 1); return(retStr); } /** Convert subnet prefix bit length to host order subnet mask. */ uint32_t bitlen2mask (uint8_t bitlen) { uint8_t i; uint32_t mask = 0; for (i = 1; i <= bitlen; ++i) { mask |= 1 << (32 - i); } return mask; } /** Convert host order subnet mask to subnet prefix bit length. */ uint8_t mask2bitlen (uint32_t mask) { uint8_t i, bitlen = 0; for (i = 0; i < 32; ++i) { if((mask << i) & 0x80000000) { ++bitlen; } else { break; } } return bitlen; } /* *********************************************** */ char * macaddr_str (macstr_t buf, const n2n_mac_t mac) { snprintf(buf, N2N_MACSTR_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0] & 0xFF, mac[1] & 0xFF, mac[2] & 0xFF, mac[3] & 0xFF, mac[4] & 0xFF, mac[5] & 0xFF); return(buf); } /* *********************************************** */ /** Resolve the supernode IP address. * */ int supernode2sock (n2n_sock_t *sn, const n2n_sn_name_t addrIn) { n2n_sn_name_t addr; char *supernode_host; char *supernode_port; int rv = 0; int nameerr; const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; struct addrinfo * ainfo = NULL; struct sockaddr_in * saddr; sn->family = AF_INVALID; memcpy(addr, addrIn, N2N_EDGE_SN_HOST_SIZE); supernode_host = strtok(addr, ":"); if(supernode_host) { supernode_port = strtok(NULL, ":"); if(supernode_port) { sn->port = atoi(supernode_port); nameerr = getaddrinfo(supernode_host, NULL, &aihints, &ainfo); if(0 == nameerr) { /* ainfo s the head of a linked list if non-NULL. */ if(ainfo && (PF_INET == ainfo->ai_family)) { /* It is definitely and IPv4 address -> sockaddr_in */ saddr = (struct sockaddr_in *)ainfo->ai_addr; memcpy(sn->addr.v4, &(saddr->sin_addr.s_addr), IPV4_SIZE); sn->family = AF_INET; traceEvent(TRACE_INFO, "supernode2sock successfully resolves supernode IPv4 address for %s", supernode_host); rv = 0; } else { /* Should only return IPv4 addresses due to aihints. */ traceEvent(TRACE_WARNING, "supernode2sock fails to resolve supernode IPv4 address for %s", supernode_host); rv = -1; } freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ } else { traceEvent(TRACE_WARNING, "supernode2sock fails to resolve supernode host %s, %d: %s", supernode_host, nameerr, gai_strerror(nameerr)); rv = -2; } } else { traceEvent(TRACE_WARNING, "supernode2sock sees malformed supernode parameter (-l ) %s", addrIn); rv = -3; } } else { traceEvent(TRACE_WARNING, "supernode2sock sees malformed supernode parameter (-l ) %s", addrIn); rv = -4; } ainfo = NULL; return rv; } #ifdef HAVE_PTHREAD N2N_THREAD_RETURN_DATATYPE resolve_thread(N2N_THREAD_PARAMETER_DATATYPE p) { n2n_resolve_parameter_t *param = (n2n_resolve_parameter_t*)p; n2n_resolve_ip_sock_t *entry, *tmp_entry; time_t rep_time = N2N_RESOLVE_INTERVAL / 10; time_t now; while(1) { sleep(N2N_RESOLVE_INTERVAL / 60); /* wake up in-between to check for signaled requests */ // what's the time? now = time(NULL); // lock access pthread_mutex_lock(¶m->access); // is it time to resolve yet? if(((param->request)) || ((now - param->last_resolved) > rep_time)) { HASH_ITER(hh, param->list, entry, tmp_entry) { // resolve entry->error_code = supernode2sock(&entry->sock, entry->org_ip); // if socket changed and no error if(!sock_equal(&entry->sock, entry->org_sock) && (!entry->error_code)) { // flag the change param->changed = 1; } } param->last_resolved = now; // any request fulfilled param->request = 0; // determine next resolver repetition (shorter time if resolver errors occured) rep_time = N2N_RESOLVE_INTERVAL; HASH_ITER(hh, param->list, entry, tmp_entry) { if(entry->error_code) { rep_time = N2N_RESOLVE_INTERVAL / 10; break; } } } // unlock access pthread_mutex_unlock(¶m->access); } } #endif int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn_list) { #ifdef HAVE_PTHREAD struct peer_info *sn, *tmp_sn; n2n_resolve_ip_sock_t *entry; int ret; // create parameter structure *param = (n2n_resolve_parameter_t*)calloc(1, sizeof(n2n_resolve_parameter_t)); if(*param) { HASH_ITER(hh, sn_list, sn, tmp_sn) { // create entries for those peers that come with ip_addr string (from command-line) if(sn->ip_addr) { entry = (n2n_resolve_ip_sock_t*)calloc(1, sizeof(n2n_resolve_ip_sock_t)); if(entry) { entry->org_ip = sn->ip_addr; entry->org_sock = &(sn->sock); memcpy(&(entry->sock), &(sn->sock), sizeof(n2n_sock_t)); HASH_ADD(hh, (*param)->list, org_ip, sizeof(char*), entry); } else traceEvent(TRACE_WARNING, "resolve_create_thread was unable to add list entry for supernode '%s'", sn->ip_addr); } } (*param)->check_interval = N2N_RESOLVE_CHECK_INTERVAL; } else { traceEvent(TRACE_WARNING, "resolve_create_thread was unable to create list of supernodes"); return -1; } // create thread ret = pthread_create(&((*param)->id), NULL, resolve_thread, (void *)*param); if(ret) { traceEvent(TRACE_WARNING, "resolve_create_thread failed to create resolver thread with error number %d", ret); return -1; } pthread_mutex_init(&((*param)->access), NULL); return 0; #else return -1; #endif } void resolve_cancel_thread (n2n_resolve_parameter_t *param) { #ifdef HAVE_PTHREAD pthread_cancel(param->id); free(param); #endif } uint8_t resolve_check (n2n_resolve_parameter_t *param, uint8_t requires_resolution, time_t now) { uint8_t ret = requires_resolution; /* if trylock fails, it still requires resolution */ #ifdef HAVE_PTHREAD n2n_resolve_ip_sock_t *entry, *tmp_entry; n2n_sock_str_t sock_buf; if(NULL == param) return ret; // check_interval and last_check do not need to be guarded by the mutex because // their values get changed and evaluated only here if((now - param->last_checked > param->check_interval) || (requires_resolution)) { // try to lock access if(pthread_mutex_trylock(¶m->access) == 0) { // any changes? if(param->changed) { // reset flag param->changed = 0; // unselectively copy all socks (even those with error code, that would be the old one because // sockets do not get overwritten in case of error in resolve_thread) from list to supernode list HASH_ITER(hh, param->list, entry, tmp_entry) { memcpy(entry->org_sock, &entry->sock, sizeof(n2n_sock_t)); traceEvent(TRACE_INFO, "resolve_check renews ip address of supernode '%s' to %s", entry->org_ip, sock_to_cstr(sock_buf, &(entry->sock))); } } // let the resolver thread know eventual difficulties in reaching the supernode if(requires_resolution) { param->request = 1; ret = 0; } param->last_checked = now; // next appointment if(param->request) // earlier if resolver still working on fulfilling a request param->check_interval = N2N_RESOLVE_CHECK_INTERVAL / 10; else param->check_interval = N2N_RESOLVE_CHECK_INTERVAL; // unlock access pthread_mutex_unlock(¶m->access); } } #endif return ret; } /* ************************************** */ struct peer_info* add_sn_to_list_by_mac_or_sock (struct peer_info **sn_list, n2n_sock_t *sock, const n2n_mac_t mac, int *skip_add) { struct peer_info *scan, *tmp, *peer = NULL; if(!is_null_mac(mac)) { /* not zero MAC */ HASH_FIND_PEER(*sn_list, mac, peer); } if(peer == NULL) { /* zero MAC, search by socket */ HASH_ITER(hh, *sn_list, scan, tmp) { if(memcmp(&(scan->sock), sock, sizeof(n2n_sock_t)) == 0) { // update mac if appropriate, needs to be deleted first because it is key to the hash list if(!is_null_mac(mac)) { HASH_DEL(*sn_list, scan); memcpy(scan->mac_addr, mac, sizeof(n2n_mac_t)); HASH_ADD_PEER(*sn_list, scan); } peer = scan; break; } } if((peer == NULL) && (*skip_add == SN_ADD)) { peer = (struct peer_info*)calloc(1, sizeof(struct peer_info)); if(peer) { sn_selection_criterion_default(&(peer->selection_criterion)); peer->last_valid_time_stamp = initial_time_stamp(); memcpy(&(peer->sock), sock, sizeof(n2n_sock_t)); memcpy(peer->mac_addr, mac, sizeof(n2n_mac_t)); HASH_ADD_PEER(*sn_list, peer); *skip_add = SN_ADD_ADDED; } } } return peer; } /* ************************************************ */ /* http://www.faqs.org/rfcs/rfc908.html */ uint8_t is_multi_broadcast (const n2n_mac_t dest_mac) { int is_broadcast = (memcmp(broadcast_mac, dest_mac, N2N_MAC_SIZE) == 0); int is_multicast = (memcmp(multicast_mac, dest_mac, 3) == 0) && !(dest_mac[3] >> 7); int is_ipv6_multicast = (memcmp(ipv6_multicast_mac, dest_mac, 2) == 0); return is_broadcast || is_multicast || is_ipv6_multicast; } uint8_t is_broadcast (const n2n_mac_t dest_mac) { int is_broadcast = (memcmp(broadcast_mac, dest_mac, N2N_MAC_SIZE) == 0); return is_broadcast; } uint8_t is_null_mac (const n2n_mac_t dest_mac) { int is_null_mac = (memcmp(null_mac, dest_mac, N2N_MAC_SIZE) == 0); return is_null_mac; } /* *********************************************** */ char* msg_type2str (uint16_t msg_type) { switch(msg_type) { case MSG_TYPE_REGISTER: return("MSG_TYPE_REGISTER"); case MSG_TYPE_DEREGISTER: return("MSG_TYPE_DEREGISTER"); case MSG_TYPE_PACKET: return("MSG_TYPE_PACKET"); case MSG_TYPE_REGISTER_ACK: return("MSG_TYPE_REGISTER_ACK"); case MSG_TYPE_REGISTER_SUPER: return("MSG_TYPE_REGISTER_SUPER"); case MSG_TYPE_REGISTER_SUPER_ACK: return("MSG_TYPE_REGISTER_SUPER_ACK"); case MSG_TYPE_REGISTER_SUPER_NAK: return("MSG_TYPE_REGISTER_SUPER_NAK"); case MSG_TYPE_FEDERATION: return("MSG_TYPE_FEDERATION"); default: return("???"); } return("???"); } /* *********************************************** */ void hexdump (const uint8_t *buf, size_t len) { size_t i; if(0 == len) { return; } printf("-----------------------------------------------\n"); for(i = 0; i < len; i++) { if((i > 0) && ((i % 16) == 0)) { printf("\n"); } printf("%02X ", buf[i] & 0xFF); } printf("\n"); printf("-----------------------------------------------\n"); } /* *********************************************** */ void print_n2n_version () { printf("Welcome to n2n v.%s for %s\n" "Built on %s\n" "Copyright 2007-2022 - ntop.org and contributors\n\n", PACKAGE_VERSION, PACKAGE_OSNAME, PACKAGE_BUILDDATE); } /* *********************************************** */ size_t purge_expired_nodes (struct peer_info **peer_list, SOCKET socket_not_to_close, n2n_tcp_connection_t **tcp_connections, time_t *p_last_purge, int frequency, int timeout) { time_t now = time(NULL); size_t num_reg = 0; if((now - (*p_last_purge)) < frequency) { return 0; } traceEvent(TRACE_DEBUG, "Purging old registrations"); num_reg = purge_peer_list(peer_list, socket_not_to_close, tcp_connections, now - timeout); (*p_last_purge) = now; traceEvent(TRACE_DEBUG, "Remove %ld registrations", num_reg); return num_reg; } /** Purge old items from the peer_list, eventually close the related socket, and * return the number of items that were removed. */ size_t purge_peer_list (struct peer_info **peer_list, SOCKET socket_not_to_close, n2n_tcp_connection_t **tcp_connections, time_t purge_before) { struct peer_info *scan, *tmp; n2n_tcp_connection_t *conn; size_t retval = 0; HASH_ITER(hh, *peer_list, scan, tmp) { if((scan->purgeable == SN_PURGEABLE) && (scan->last_seen < purge_before)) { if((scan->socket_fd >=0) && (scan->socket_fd != socket_not_to_close)) { if(tcp_connections) { HASH_FIND_INT(*tcp_connections, &scan->socket_fd, conn); if(conn) { HASH_DEL(*tcp_connections, conn); free(conn); } shutdown(scan->socket_fd, SHUT_RDWR); closesocket(scan->socket_fd); } } HASH_DEL(*peer_list, scan); mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_PURGE,scan); /* FIXME: generates events for more than just p2p */ retval++; free(scan); } } return retval; } /** Purge all items from the peer_list and return the number of items that were removed. */ size_t clear_peer_list (struct peer_info ** peer_list) { struct peer_info *scan, *tmp; size_t retval = 0; HASH_ITER(hh, *peer_list, scan, tmp) { HASH_DEL(*peer_list, scan); mgmt_event_post(N2N_EVENT_PEER,N2N_EVENT_PEER_CLEAR,scan); /* FIXME: generates events for more than just p2p */ retval++; free(scan); } return retval; } static uint8_t hex2byte (const char * s) { char tmp[3]; tmp[0] = s[0]; tmp[1] = s[1]; tmp[2] = 0; /* NULL term */ return((uint8_t)strtol(tmp, NULL, 16)); } extern int str2mac (uint8_t * outmac /* 6 bytes */, const char * s) { size_t i; /* break it down as one case for the first "HH", the 5 x through loop for * each ":HH" where HH is a two hex nibbles in ASCII. */ *outmac = hex2byte(s); ++outmac; s += 2; /* don't skip colon yet - helps generalise loop. */ for(i = 1; i < 6; ++i) { s += 1; *outmac = hex2byte(s); ++outmac; s += 2; } return 0; /* ok */ } extern char * sock_to_cstr (n2n_sock_str_t out, const n2n_sock_t * sock) { if(NULL == out) { return NULL; } memset(out, 0, N2N_SOCKBUF_SIZE); if(AF_INET6 == sock->family) { /* INET6 not written yet */ snprintf(out, N2N_SOCKBUF_SIZE, "XXXX:%hu", sock->port); return out; } else { const uint8_t * a = sock->addr.v4; snprintf(out, N2N_SOCKBUF_SIZE, "%hu.%hu.%hu.%hu:%hu", (unsigned short)(a[0] & 0xff), (unsigned short)(a[1] & 0xff), (unsigned short)(a[2] & 0xff), (unsigned short)(a[3] & 0xff), (unsigned short)sock->port); return out; } } char *ip_subnet_to_str (dec_ip_bit_str_t buf, const n2n_ip_subnet_t *ipaddr) { snprintf(buf, sizeof(dec_ip_bit_str_t), "%hhu.%hhu.%hhu.%hhu/%hhu", (uint8_t) ((ipaddr->net_addr >> 24) & 0xFF), (uint8_t) ((ipaddr->net_addr >> 16) & 0xFF), (uint8_t) ((ipaddr->net_addr >> 8) & 0xFF), (uint8_t) (ipaddr->net_addr & 0xFF), ipaddr->net_bitlen); return buf; } /* @return 1 if the two sockets are equivalent. */ int sock_equal (const n2n_sock_t * a, const n2n_sock_t * b) { if(a->port != b->port) { return(0); } if(a->family != b->family) { return(0); } switch(a->family) { case AF_INET: if(memcmp(a->addr.v4, b->addr.v4, IPV4_SIZE)) { return(0); } break; default: if(memcmp(a->addr.v6, b->addr.v6, IPV6_SIZE)) { return(0); } break; } /* equal */ return(1); } /* *********************************************** */ // fills a specified memory area with random numbers int memrnd (uint8_t *address, size_t len) { for(; len >= 4; len -= 4) { *(uint32_t*)address = n2n_rand(); address += 4; } for(; len > 0; len--) { *address = n2n_rand(); address++; } return 0; } // exclusive-ors a specified memory area with another int memxor (uint8_t *destination, const uint8_t *source, size_t len) { for(; len >= 4; len -= 4) { *(uint32_t*)destination ^= *(uint32_t*)source; source += 4; destination += 4; } for(; len > 0; len--) { *destination ^= *source; source++; destination++; } return 0; } /* *********************************************** */ #if defined(WIN32) int gettimeofday (struct timeval *tp, void *tzp) { time_t clock; struct tm tm; SYSTEMTIME wtm; GetLocalTime(&wtm); tm.tm_year = wtm.wYear - 1900; tm.tm_mon = wtm.wMonth - 1; tm.tm_mday = wtm.wDay; tm.tm_hour = wtm.wHour; tm.tm_min = wtm.wMinute; tm.tm_sec = wtm.wSecond; tm.tm_isdst = -1; clock = mktime(&tm); tp->tv_sec = clock; tp->tv_usec = wtm.wMilliseconds * 1000; return 0; } #endif // stores the previously issued time stamp static uint64_t previously_issued_time_stamp = 0; // returns a time stamp for use with replay protection (branchless code) // // depending on the self-detected accuracy, it has the following format // // MMMMMMMMCCCCCCCF or // // MMMMMMMMSSSSSCCF // // with M being the 32-bit second time stamp // S the 20-bit sub-second (microsecond) time stamp part, if applicable // C a counter (8 bit or 24 bit) reset to 0 with every MMMMMMMM(SSSSS) turn-over // F a 4-bit flag field with // ...c being the accuracy indicator (if set, only counter and no sub-second accuracy) // uint64_t time_stamp (void) { struct timeval tod; uint64_t micro_seconds; uint64_t co, mask_lo, mask_hi, hi_unchanged, counter, new_co; gettimeofday(&tod, NULL); // (roughly) calculate the microseconds since 1970, leftbound micro_seconds = ((uint64_t)(tod.tv_sec) << 32) + ((uint64_t)tod.tv_usec << 12); // more exact but more costly due to the multiplication: // micro_seconds = ((uint64_t)(tod.tv_sec) * 1000000ULL + tod.tv_usec) << 12; // extract "counter only" flag (lowest bit) co = (previously_issued_time_stamp << 63) >> 63; // set mask accordingly mask_lo = -co; mask_lo >>= 32; // either 0x00000000FFFFFFFF (if co flag set) or 0x0000000000000000 (if co flag not set) mask_lo |= (~mask_lo) >> 52; // either 0x00000000FFFFFFFF (unchanged) or 0x0000000000000FFF (lowest 12 bit set) mask_hi = ~mask_lo; hi_unchanged = ((previously_issued_time_stamp & mask_hi) == (micro_seconds & mask_hi)); // 0 if upper bits unchanged (compared to previous stamp), 1 otherwise // read counter and shift right for flags counter = (previously_issued_time_stamp & mask_lo) >> 4; counter += hi_unchanged; counter &= -hi_unchanged; // either counter++ if upper part of timestamp unchanged, 0 otherwise // back to time stamp format counter <<= 4; // set new co flag if counter overflows while upper bits unchanged or if it was set before new_co = (((counter & mask_lo) == 0) & hi_unchanged) | co; // in case co flag changed, masks need to be recalculated mask_lo = -new_co; mask_lo >>= 32; mask_lo |= (~mask_lo) >> 52; mask_hi = ~mask_lo; // assemble new timestamp micro_seconds &= mask_hi; micro_seconds |= counter; micro_seconds |= new_co; previously_issued_time_stamp = micro_seconds; return micro_seconds; } // returns an initial time stamp for use with replay protection uint64_t initial_time_stamp (void) { return time_stamp() - TIME_STAMP_FRAME; } // checks if a provided time stamp is consistent with current time and previously valid time stamps // and, in case of validity, updates the "last valid time stamp" int time_stamp_verify_and_update (uint64_t stamp, uint64_t *previous_stamp, int allow_jitter) { int64_t diff; /* do not change to unsigned */ uint64_t co; /* counter only mode (for sub-seconds) */ co = (stamp << 63) >> 63; // is it around current time (+/- allowed deviation TIME_STAMP_FRAME)? diff = stamp - time_stamp(); // abs() diff = (diff < 0 ? -diff : diff); if(diff >= TIME_STAMP_FRAME) { traceEvent(TRACE_DEBUG, "time_stamp_verify_and_update found a timestamp out of allowed frame."); return 0; // failure } // if applicable: is it higher than previous time stamp (including allowed deviation of TIME_STAMP_JITTER)? if(NULL != previous_stamp) { diff = stamp - *previous_stamp; if(allow_jitter) { // 8 times higher jitter allowed for counter-only flagged timestamps ( ~ 1.25 sec with 160 ms default jitter) diff += TIME_STAMP_JITTER << (co << 3); } if(diff <= 0) { traceEvent(TRACE_DEBUG, "time_stamp_verify_and_update found a timestamp too old compared to previous."); return 0; // failure } // for not allowing to exploit the allowed TIME_STAMP_JITTER to "turn the clock backwards", // set the higher of the values *previous_stamp = (stamp > *previous_stamp ? stamp : *previous_stamp); } return 1; // success } ntop-n2n-90215bd/src/n2n_port_mapping.c000066400000000000000000000515641422132035700177360ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // This file contains code taken from MiniUPnPc and natpmp found at // https://github.com/miniupnp/miniupnp/ or // https://github.com/miniupnp/natpmp/ respectively // both as of October 2021 /** * MiniUPnPc * Copyright (c) 2005-2021, Thomas BERNARD * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "n2n.h" #ifdef HAVE_PORT_FORWARDING #ifdef HAVE_MINIUPNP #if 0 /* unused code */ /* protofix() checks if protocol is "UDP" or "TCP" * returns NULL if not */ static const char *protofix (const char *proto) { int i, b; const char proto_tcp[4] = {'T', 'C', 'P', 0}; const char proto_udp[4] = {'U', 'D', 'P', 0}; for(i = 0, b = 1; i < 4; i++) b = b && ((proto[i] == proto_tcp[i]) || (proto[i] == (proto_tcp[i] | 32))); if(b) return proto; for(i = 0, b = 1; i < 4; i++) b = b && ((proto[i] == proto_udp[i]) || (proto[i] == (proto_udp[i] | 32))); if(b) return proto; return NULL; } #endif // unused code static int n2n_UPNP_GetValidIGD (struct UPNPUrls *urls, struct IGDdatas *data, char *lanaddr, char *externaladdr) { struct UPNPDev *devlist = NULL; struct UPNPDev *device = NULL; int delay = 2000; const char *multicastif = NULL; const char *minissdpdpath = NULL; int localport = UPNP_LOCAL_PORT_ANY; int ipv6 = 0; unsigned char ttl = 2; /* defaulting to 2 */ int error = 0; int ret = 0; devlist = upnpDiscover(delay, multicastif, minissdpdpath, localport, ipv6, ttl, &error); if((error != UPNPDISCOVER_SUCCESS) || (devlist == NULL) ) { traceEvent(TRACE_WARNING, "no IGD UPnP device found on the network"); return -1; } traceEvent(TRACE_INFO, "list of UPnP devices found on the network:"); for(device = devlist; device; device = device->pNext) { traceEvent(TRACE_INFO, " desc: %s", device->descURL); traceEvent(TRACE_INFO, " st: %s", device->st); traceEvent(TRACE_INFO, " usn: %s", device->usn); } ret = UPNP_GetValidIGD(devlist, urls, data, lanaddr, N2N_NETMASK_STR_SIZE); if(ret == 0) { traceEvent(TRACE_WARNING, "UPnP get valid IGD failed, code %d (%s)", ret, strupnperror(ret)); freeUPNPDevlist(devlist); devlist = NULL; return -1; } freeUPNPDevlist(devlist); devlist = NULL; traceEvent(TRACE_INFO, "UPnP found valid IGD: %s", urls->controlURL); ret = UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, externaladdr); if(ret != UPNPCOMMAND_SUCCESS) { traceEvent(TRACE_WARNING, "UPnP get external ip address failed, code %d (%s)", ret, strupnperror(ret)); } return 0; } #if 0 /* unused code */ static int n2n_upnp_get_port_mapping (struct UPNPUrls *urls, const struct IGDdatas *data, const uint16_t port, const char *proto, char *lanaddr, char *lanport, char *description, char *enabled, char *duration) { int errorcode = 0; // struct UPNPUrls urls; // struct IGDdatas data; // char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'}; // char lanport[6] = {'\0'}; // char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'}; char externalport[6] = {'\0'}; // char description[64] = {'\0'}; // char enabled[16] = {'\0'}; // char duration[16] = {'\0'}; int ret = 0; proto = protofix(proto); if(!proto) { traceEvent(TRACE_ERROR, "invalid protocol"); errorcode = -1; goto end; } snprintf(externalport, sizeof(externalport), "%d", port); ret = UPNP_GetSpecificPortMappingEntry(urls->controlURL, data->first.servicetype, externalport, proto, NULL, lanaddr, lanport, description, enabled, duration); if(ret != UPNPCOMMAND_SUCCESS) { traceEvent(TRACE_WARNING, "UPNP_GetSpecificPortMappingEntry() failed, code %d (%s)", ret, strupnperror(ret)); errorcode = -1; goto end; } end: FreeUPNPUrls(urls); return errorcode; } #endif // unused code static int n2n_upnp_set_port_mapping (const uint16_t port) { int errorcode = 0; struct UPNPUrls urls; struct IGDdatas data; char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'}; char lanport[6] = {'\0'}; char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'}; char externalport[6] = {'\0'}; int ret = 0; if(port == 0) { traceEvent(TRACE_ERROR, "invalid port"); errorcode = -1; return errorcode; } snprintf(lanport, sizeof(lanport), "%d", port); memcpy(externalport, lanport, sizeof(externalport)); ret = n2n_UPNP_GetValidIGD(&urls, &data, lanaddr, externaladdr); if(ret != 0) { errorcode = -1; return errorcode; } // TCP port ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, externalport, lanport, lanaddr, "n2n-vpn", "TCP", NULL, "0"); if(ret != UPNPCOMMAND_SUCCESS) { traceEvent(TRACE_WARNING, "UPnP local TCP port %s mapping failed, code %d (%s)", lanport, ret, strupnperror(ret)); errorcode = -1; } else traceEvent(TRACE_NORMAL, "UPnP added TCP port mapping: %s:%s -> %s:%s", externaladdr, externalport, lanaddr, lanport); // UDP port ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, externalport, lanport, lanaddr, "n2n-vpn", "UDP", NULL, "0"); if(ret != UPNPCOMMAND_SUCCESS) { traceEvent(TRACE_WARNING, "UPnP local UDP port %s mapping failed, code %d (%s)", lanport, ret, strupnperror(ret)); errorcode = -1; } else traceEvent(TRACE_NORMAL, "UPnP added UDP port mapping: %s:%s -> %s:%s", externaladdr, externalport, lanaddr, lanport); FreeUPNPUrls(&urls); return errorcode; } static int n2n_upnp_del_port_mapping (const uint16_t port) { int errorcode = 0; struct UPNPUrls urls; struct IGDdatas data; char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'}; // char lanport[6] = {'\0'}; char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'}; char externalport[6] = {'\0'}; int ret = 0; if(port == 0) { traceEvent(TRACE_ERROR, "invalid port"); errorcode = -1; return errorcode; } snprintf(externalport, sizeof(externalport), "%d", port); ret = n2n_UPNP_GetValidIGD(&urls, &data, lanaddr, externaladdr); if(ret != 0) { errorcode = -1; return errorcode; } // TCP port ret = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, externalport, "TCP", NULL); if(ret != UPNPCOMMAND_SUCCESS) { traceEvent(TRACE_WARNING, "UPnP failed to delete TCP port mapping for %s:%s, code %d (%s)", externaladdr, externalport, ret, strupnperror(ret)); errorcode = -1; } else traceEvent(TRACE_NORMAL, "UPnP deleted TCP port mapping for %s:%s", externaladdr, externalport); // UDP port ret = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, externalport, "UDP", NULL); if(ret != UPNPCOMMAND_SUCCESS) { traceEvent(TRACE_WARNING, "UPnP failed to delete UDP port mapping for %s:%s, code %d (%s)", externaladdr, externalport, ret, strupnperror(ret)); errorcode = -1; } else traceEvent(TRACE_NORMAL, "UPnP deleted UDP port mapping for %s:%s", externaladdr, externalport); FreeUPNPUrls(&urls); return errorcode; } #endif // HAVE_MINIUPNP // ---------------------------------------------------------------------------------------------------- #ifdef HAVE_NATPMP static int n2n_natpmp_initialization (natpmp_t *natpmp, char *lanaddr, char *externaladdr) { int errorcode = 0; natpmpresp_t response; int ret = 0; int forcegw = 0; in_addr_t gateway = 0; struct in_addr gateway_in_use; struct timeval timeout; fd_set fds; ret = initnatpmp(natpmp, forcegw, gateway); if(ret != 0) { traceEvent(TRACE_WARNING, "NAT-PMP failed to initialize, code %d", ret); errorcode = -1; return errorcode; } gateway_in_use.s_addr = natpmp->gateway; traceEvent(TRACE_INFO, "NAT-PMP using gateway: %s", inet_ntoa(gateway_in_use)); ret = sendpublicaddressrequest(natpmp); if(ret != 2) { traceEvent(TRACE_WARNING, "NAT-PMP get external ip address failed, code %d", ret); closenatpmp(natpmp); errorcode = -1; return errorcode; } do { FD_ZERO(&fds); FD_SET(natpmp->s, &fds); getnatpmprequesttimeout(natpmp, &timeout); select(FD_SETSIZE, &fds, NULL, NULL, &timeout); ret = readnatpmpresponseorretry(natpmp, &response); traceEvent(TRACE_INFO, "NAT-PMP read response returned %d (%s)", ret, ret == 0 ? "OK" : (ret == NATPMP_TRYAGAIN ? "TRY AGAIN" : "FAILED")); } while (ret == NATPMP_TRYAGAIN); if(response.type != NATPMP_RESPTYPE_PUBLICADDRESS) { traceEvent(TRACE_WARNING, "NAT-PMP invalid response type %u", response.type); closenatpmp(natpmp); errorcode = -1; return errorcode; } snprintf(externaladdr, N2N_NETMASK_STR_SIZE, "%s", inet_ntoa(response.pnu.publicaddress.addr)); snprintf(lanaddr, N2N_NETMASK_STR_SIZE, "localhost"); return errorcode; } static int n2n_natpmp_port_mapping_request (natpmp_t *natpmp, const uint16_t port, const int protocol /* NATPMP_PROTOCOL_TCP or NATPMP_PROTOCOL_UDP */, const int method /* set:1 del:0 */) { int errorcode = 0; natpmpresp_t response; int ret = 0; uint16_t lanport = 0; uint16_t externalport = 0; struct timeval timeout; fd_set fds; if(port == 0) { traceEvent(TRACE_ERROR, "invalid port"); errorcode = -1; return errorcode; } lanport = port; externalport = port; ret = sendnewportmappingrequest(natpmp, protocol, lanport, externalport, (method ? 31104000 /* lifetime 360 days*/ : 0)); if(ret != 12) { traceEvent(TRACE_WARNING, "NAT-PMP new port mapping request failed, code %d", ret); errorcode = -1; return errorcode; } do { FD_ZERO(&fds); FD_SET(natpmp->s, &fds); getnatpmprequesttimeout(natpmp, &timeout); select(FD_SETSIZE, &fds, NULL, NULL, &timeout); ret = readnatpmpresponseorretry(natpmp, &response); traceEvent(TRACE_INFO, "NAT-PMP read response returned %d (%s)", ret, ret == 0 ? "OK" : (ret == NATPMP_TRYAGAIN ? "TRY AGAIN" : "FAILED")); } while (ret == NATPMP_TRYAGAIN); if(!((response.type == NATPMP_RESPTYPE_TCPPORTMAPPING) || (response.type == NATPMP_RESPTYPE_UDPPORTMAPPING))) { traceEvent(TRACE_WARNING, "NAT-PMP invalid response type %u", response.type); errorcode = -1; return errorcode; } return errorcode; } static int n2n_natpmp_set_port_mapping (const uint16_t port) { int errorcode = 0; natpmp_t natpmp; int ret = 0; char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'}; uint16_t lanport = 0; char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'}; uint16_t externalport = 0; lanport = port; externalport = port; ret = n2n_natpmp_initialization(&natpmp, lanaddr, externaladdr); if(ret != 0) { errorcode = -1; return errorcode; } // TCP port ret = n2n_natpmp_port_mapping_request(&natpmp, port, NATPMP_PROTOCOL_TCP, 1); if(ret != 0) { traceEvent(TRACE_WARNING, "NAT-PMP local TCP port %hu mapping failed", lanport); errorcode = -1; } else traceEvent(TRACE_NORMAL, "NAT-PMP added TCP port mapping: %s:%hu -> %s:%hu", externaladdr, externalport, lanaddr, lanport); // UDP port ret = n2n_natpmp_port_mapping_request(&natpmp, port, NATPMP_PROTOCOL_UDP, 1); if(ret != 0) { traceEvent(TRACE_WARNING, "NAT-PMP local UDP port %hu mapping failed", lanport); errorcode = -1; } else traceEvent(TRACE_NORMAL, "NAT-PMP added UDP port mapping: %s:%hu -> %s:%hu", externaladdr, externalport, lanaddr, lanport); closenatpmp(&natpmp); return errorcode; } static int n2n_natpmp_del_port_mapping (const uint16_t port) { int errorcode = 0; natpmp_t natpmp; int ret = 0; char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'}; // uint16_t lanport = 0; char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'}; uint16_t externalport = 0; // lanport = port; externalport = port; ret = n2n_natpmp_initialization(&natpmp, lanaddr, externaladdr); if(ret != 0) { errorcode = -1; return errorcode; } // TCP port ret = n2n_natpmp_port_mapping_request(&natpmp, port, NATPMP_PROTOCOL_TCP, 0); if(ret != 0) { traceEvent(TRACE_WARNING, "NAT-PMP failed to delete TCP port mapping for %s:%hu", externaladdr, externalport); errorcode = -1; } else traceEvent(TRACE_NORMAL, "NAT-PMP deleted TCP port mapping for %s:%hu", externaladdr, externalport); // UDP port ret = n2n_natpmp_port_mapping_request(&natpmp, port, NATPMP_PROTOCOL_UDP, 0); if(ret != 0) { traceEvent(TRACE_WARNING, "NAT-PMP failed to delete UDP port mapping for %s:%hu", externaladdr, externalport); errorcode = -1; } else traceEvent(TRACE_NORMAL, "NAT-PMP deleted UDP port mapping for %s:%hu", externaladdr, externalport); closenatpmp(&natpmp); return errorcode; } #endif // HAVE_NATPMP // ---------------------------------------------------------------------------------------------------- static void n2n_set_port_mapping (const uint16_t port) { #ifdef HAVE_NATPMP // since the NAT-PMP protocol is more concise than UPnP, NAT-PMP is preferred. if(n2n_natpmp_set_port_mapping(port)) #endif // HAVE_NATPMP { #ifdef HAVE_MINIUPNP n2n_upnp_set_port_mapping(port); #endif // HAVE_MINIUPNP } } static void n2n_del_port_mapping (const uint16_t port) { #ifdef HAVE_NATPMP if(n2n_natpmp_del_port_mapping(port)) #endif // HAVE_NATPMP { #ifdef HAVE_MINIUPNP n2n_upnp_del_port_mapping(port); #endif // HAVE_MINIUPNP } } // static // ---------------------------------------------------------------------------------------------------- // public #ifdef HAVE_PTHREAD /* future management port subscriptions will deprecate the following temporary code */ void n2n_chg_port_mapping (struct n2n_edge *eee, uint16_t port) { // write a port change request to param struct, it will be handled in the thread pthread_mutex_lock(&eee->port_map_parameter->access); eee->port_map_parameter->new_port = port; pthread_mutex_unlock(&eee->port_map_parameter->access); } #else #error "enabling port mapping requires enabling pthread" #endif N2N_THREAD_RETURN_DATATYPE port_map_thread(N2N_THREAD_PARAMETER_DATATYPE p) { #ifdef HAVE_PTHREAD /* future management port subscriptions will deprecate the following temporary code */ n2n_port_map_parameter_t *param = (n2n_port_map_parameter_t*)p; while(1) { sleep(2); pthread_mutex_lock(¶m->access); if(param->mapped_port != param->new_port) { if(param->mapped_port) n2n_del_port_mapping(param->mapped_port); if(param->new_port) n2n_set_port_mapping(param->new_port); param->mapped_port = param->new_port; } pthread_mutex_unlock(¶m->access); } #endif #if 0 /* to be used with future management port subscriptions */ n2n_port_map_parameter_t *param = (n2n_port_map_parameter_t*)p; SOCKET socket_fd; fd_set socket_mask; struct timeval wait_time; int ret = 0; char udp_buf[N2N_PKT_BUF_SIZE]; ssize_t msg_len; uint32_t addr_tmp = htonl(INADDR_LOOPBACK); n2n_sock_t sock_tmp; struct sockaddr_in sock; socklen_t sock_len; // open a new socket ... socket_fd = open_socket(0 /* no specific port */, INADDR_LOOPBACK, 0 /* UDP */); if(socket_fd < 0) { traceEvent(TRACE_ERROR, "port_map_thread failed to open a socket to management port"); return 0; } // ... and connect to local mgmt port sock_tmp.family = AF_INET; memcpy(&sock_tmp.addr.v4, &addr_tmp, IPV4_SIZE); sock_tmp.port = param->mgmt_port; sock_len = sizeof(sock); fill_sockaddr((struct sockaddr*)&sock, sock_len, &sock_tmp); connect(socket_fd, (struct sockaddr*)&sock, sock_len); // prepare a subscription request in 'udp_buf' of length 'msg_len' // !!! dummy udp_buf[0] = '\n'; msg_len = 1; send(socket_fd, udp_buf, msg_len, 0 /*flags*/); // note: 'msg_len' and 'sock' get re-used hereafter while(1) { FD_ZERO(&socket_mask); FD_SET(socket_fd, &socket_mask); wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS; wait_time.tv_usec = 0; ret = select(socket_fd + 1, &socket_mask, NULL, NULL, &wait_time); if(ret > 0) { if(FD_ISSET(socket_fd, &socket_mask)) { // get the data sock_len = sizeof(sock); msg_len = recv(socket_fd, udp_buf, N2N_PKT_BUF_SIZE, 0 /*flags*/); // check message format, first message could be the still buffered answer to the subscription request // !!! if(1 /* !!! correct message format */) { // delete an eventually previous port mapping if(param->mapped_port) n2n_del_port_mapping(param->mapped_port); // extract port from message and set accordingly if valid param->mapped_port = 0; // !!! if(param->mapped_port) n2n_set_port_mapping(param->mapped_port); } } } } #endif return 0; /* should never happen */ } int port_map_create_thread (n2n_port_map_parameter_t **param, uint16_t mgmt_port) { #ifdef HAVE_PTHREAD int ret; // create parameter structure *param = (n2n_port_map_parameter_t*)calloc(1, sizeof(n2n_port_map_parameter_t)); if(*param) { // initialize (*param)->mgmt_port = mgmt_port; } else { traceEvent(TRACE_WARNING, "port_map_create_thread was unable to create parameter structure"); return -1; } // create thread ret = pthread_create(&((*param)->id), NULL, port_map_thread, (void *)*param); if(ret) { traceEvent(TRACE_WARNING, "port_map_create_thread failed to create port mapping thread with error number %d", ret); return -1; } return 0; #else return -1; #endif } void port_map_cancel_thread (n2n_port_map_parameter_t *param) { #ifdef HAVE_PTHREAD pthread_cancel(param->id); if(param->mapped_port) n2n_del_port_mapping(param->mapped_port); free(param); #endif } #endif // HAVE_PORT_FORWARDING ntop-n2n-90215bd/src/n2n_regex.c000066400000000000000000000370311422132035700163420ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // taken from https://github.com/kokke/tiny-regex-c // under Unlicense as of August 4, 2020 /* * * Mini regex-module inspired by Rob Pike's regex code described in: * * http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html * * * * Supports: * --------- * '.' Dot, matches any character * '^' Start anchor, matches beginning of string -- NOTE: currently disabled (checking for full matches anyway) * '$' End anchor, matches end of string -- NOTE: currently disabled (checking for full matches anyway) * '*' Asterisk, match zero or more (greedy) * '+' Plus, match one or more (greedy) * '?' Question, match zero or one (non-greedy) * '[abc]' Character class, match if one of {'a', 'b', 'c'} * '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} -- NOTE: feature is currently broken! * '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z } * '\s' Whitespace, \t \f \r \n \v and spaces * '\S' Non-whitespace * '\w' Alphanumeric, [a-zA-Z0-9_] * '\W' Non-alphanumeric * '\d' Digits, [0-9] * '\D' Non-digits * * */ #include "n2n.h" #include "n2n_regex.h" /* Definitions: */ #define MAX_REGEXP_OBJECTS 30 /* Max number of regex symbols in expression. */ #define MAX_CHAR_CLASS_LEN 40 /* Max length of character-class buffer in. */ enum { UNUSED, DOT, BEGIN, END, QUESTIONMARK, STAR, PLUS, CHAR_TYPE, CHAR_CLASS, INV_CHAR_CLASS, DIGIT, NOT_DIGIT, ALPHA, NOT_ALPHA, WHITESPACE, NOT_WHITESPACE, /* BRANCH */ }; typedef struct regex_t { unsigned char type; /* CHAR_TYPE, STAR, etc. */ union { unsigned char ch; /* the character itself */ unsigned char* ccl; /* OR a pointer to characters in class */ }; } regex_t; /* Private function declarations: */ static int matchpattern (regex_t* pattern, const char* text, int* matchlength); static int matchcharclass (char c, const char* str); static int matchstar (regex_t p, regex_t* pattern, const char* text, int* matchlength); static int matchplus (regex_t p, regex_t* pattern, const char* text, int* matchlength); static int matchone (regex_t p, char c); static int matchdigit (char c); static int matchalpha (char c); static int matchwhitespace (char c); static int matchmetachar (char c, const char* str); static int matchrange (char c, const char* str); static int matchdot (char c); static int ismetachar (char c); /* Public functions: */ int re_match (const char* pattern, const char* text, int* matchlength) { re_t re_p; /* pointer to (to be created) copy of compiled regex */ int ret = -1; re_p = re_compile (pattern); ret = re_matchp(re_p, text, matchlength); free(re_p); return(ret); } int re_matchp (re_t pattern, const char* text, int* matchlength) { *matchlength = 0; if(pattern != 0) { if(pattern[0].type == BEGIN) { return ((matchpattern(&pattern[1], text, matchlength)) ? 0 : -1); } else { int idx = -1; do { idx += 1; if(matchpattern(pattern, text, matchlength)) { if(text[0] == '\0') { return -1; } return idx; } } while(*text++ != '\0'); } } return -1; } re_t re_compile (const char* pattern) { /* The sizes of the two static arrays below substantiates the static RAM usage of this module. MAX_REGEXP_OBJECTS is the max number of symbols in the expression. MAX_CHAR_CLASS_LEN determines the size of buffer for chars in all char-classes in the expression. */ static regex_t re_compiled[MAX_REGEXP_OBJECTS]; re_t re_p; /* pointer to (to be created) copy of compiled regex in re_compiled */ static unsigned char ccl_buf[MAX_CHAR_CLASS_LEN]; int ccl_bufidx = 1; char c; /* current char in pattern */ int i = 0; /* index into pattern */ int j = 0; /* index into re_compiled */ while(pattern[i] != '\0' && (j + 1 < MAX_REGEXP_OBJECTS)) { c = pattern[i]; switch(c) { /* Meta-characters: */ // case '^': { re_compiled[j].type = BEGIN; } break; <-- disabled (always full matches) // case '$': { re_compiled[j].type = END; } break; <-- disabled (always full matches) case '.': { re_compiled[j].type = DOT; } break; case '*': { re_compiled[j].type = STAR; } break; case '+': { re_compiled[j].type = PLUS; } break; case '?': { re_compiled[j].type = QUESTIONMARK; } break; /* case '|': { re_compiled[j].type = BRANCH; } break; <-- not working properly */ /* Escaped character-classes (\s \w ...): */ case '\\': { if(pattern[i + 1] != '\0') { /* Skip the escape-char '\\' */ i += 1; /* ... and check the next */ switch(pattern[i]) { /* Meta-character: */ case 'd': { re_compiled[j].type = DIGIT; } break; case 'D': { re_compiled[j].type = NOT_DIGIT; } break; case 'w': { re_compiled[j].type = ALPHA; } break; case 'W': { re_compiled[j].type = NOT_ALPHA; } break; case 's': { re_compiled[j].type = WHITESPACE; } break; case 'S': { re_compiled[j].type = NOT_WHITESPACE; } break; /* Escaped character, e.g. '.' */ default: { re_compiled[j].type = CHAR_TYPE; re_compiled[j].ch = pattern[i]; } break; } } /* '\\' as last char in pattern -> invalid regular expression. */ /* else { re_compiled[j].type = CHAR_TYPE; re_compiled[j].ch = pattern[i]; } */ } break; /* Character class: */ case '[': { /* Remember where the char-buffer starts. */ int buf_begin = ccl_bufidx; /* Look-ahead to determine if negated */ if(pattern[i+1] == '^') { re_compiled[j].type = INV_CHAR_CLASS; i += 1; /* Increment i to avoid including '^' in the char-buffer */ } else { re_compiled[j].type = CHAR_CLASS; } /* Copy characters inside [..] to buffer */ while((pattern[++i] != ']') && (pattern[i] != '\0')) /* Missing ] */ { if(pattern[i] == '\\') { if(ccl_bufidx >= MAX_CHAR_CLASS_LEN - 1) { //fputs("exceeded internal buffer!\n", stderr); return 0; } ccl_buf[ccl_bufidx++] = pattern[i++]; } else if(ccl_bufidx >= MAX_CHAR_CLASS_LEN) { //fputs("exceeded internal buffer!\n", stderr); return 0; } ccl_buf[ccl_bufidx++] = pattern[i]; } if(ccl_bufidx >= MAX_CHAR_CLASS_LEN) { /* Catches cases such as [00000000000000000000000000000000000000][ */ //fputs("exceeded internal buffer!\n", stderr); return 0; } /* Null-terminate string end */ ccl_buf[ccl_bufidx++] = 0; re_compiled[j].ccl = &ccl_buf[buf_begin]; } break; /* Other characters: */ default: { re_compiled[j].type = CHAR_TYPE; re_compiled[j].ch = c; } break; } i += 1; j += 1; } /* 'UNUSED' is a sentinel used to indicate end-of-pattern */ re_compiled[j].type = UNUSED; re_p = (re_t)calloc(1, sizeof(re_compiled)); memcpy (re_p, re_compiled, sizeof(re_compiled)); return (re_t) re_p; } void re_print (regex_t* pattern) { const char* types[] = { "UNUSED", "DOT", "BEGIN", "END", "QUESTIONMARK", "STAR", "PLUS", "CHAR_TYPE", "CHAR_CLASS", "INV_CHAR_CLASS", "DIGIT", "NOT_DIGIT", "ALPHA", "NOT_ALPHA", "WHITESPACE" , "NOT_WHITESPACE", /* "BRANCH" */ }; int i; int j; char c; for(i = 0; i < MAX_REGEXP_OBJECTS; ++i) { if(pattern[i].type == UNUSED) { break; } printf("type: %s", types[pattern[i].type]); if((pattern[i].type == CHAR_CLASS) || (pattern[i].type == INV_CHAR_CLASS)) { printf(" ["); for(j = 0; j < MAX_CHAR_CLASS_LEN; ++j) { c = pattern[i].ccl[j]; if((c == '\0') || (c == ']')) { break; } printf("%c", c); } printf("]"); } else if(pattern[i].type == CHAR_TYPE) { printf(" '%c'", pattern[i].ch); } printf("\n"); } } /* Private functions: */ static int matchdigit (char c) { return ((c >= '0') && (c <= '9')); } static int matchalpha (char c) { return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')); } static int matchwhitespace (char c) { return ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') || (c == '\f') || (c == '\v')); } static int matchalphanum (char c) { return ((c == '_') || matchalpha(c) || matchdigit(c)); } static int matchrange (char c, const char* str) { return ((c != '-') && (str[0] != '\0') && (str[0] != '-') && (str[1] == '-') && (str[1] != '\0') && (str[2] != '\0') && ((c >= str[0]) && (c <= str[2]))); } static int matchdot (char c) { return ((c != '\n') && (c != '\r')); } static int ismetachar (char c) { return ((c == 's') || (c == 'S') || (c == 'w') || (c == 'W') || (c == 'd') || (c == 'D')); } static int matchmetachar (char c, const char* str) { switch(str[0]) { case 'd': return matchdigit(c); case 'D': return !matchdigit(c); case 'w': return matchalphanum(c); case 'W': return !matchalphanum(c); case 's': return matchwhitespace(c); case 'S': return !matchwhitespace(c); default: return (c == str[0]); } } static int matchcharclass (char c, const char* str) { do { if(matchrange(c, str)) { return 1; } else if(str[0] == '\\') { /* Escape-char: increment str-ptr and match on next char */ str += 1; if(matchmetachar(c, str)) { return 1; } else if((c == str[0]) && !ismetachar(c)) { return 1; } } else if(c == str[0]) { if(c == '-') { return ((str[-1] == '\0') || (str[1] == '\0')); } else { return 1; } } } while(*str++ != '\0'); return 0; } static int matchone (regex_t p, char c) { switch(p.type) { case DOT: return matchdot(c); case CHAR_CLASS: return matchcharclass(c, (const char*)p.ccl); case INV_CHAR_CLASS: return !matchcharclass(c, (const char*)p.ccl); case DIGIT: return matchdigit(c); case NOT_DIGIT: return !matchdigit(c); case ALPHA: return matchalphanum(c); case NOT_ALPHA: return !matchalphanum(c); case WHITESPACE: return matchwhitespace(c); case NOT_WHITESPACE: return !matchwhitespace(c); default: return (p.ch == c); } } static int matchstar (regex_t p, regex_t* pattern, const char* text, int* matchlength) { int prelen = *matchlength; const char* prepoint = text; while((text[0] != '\0') && matchone(p, *text)) { text++; (*matchlength)++; } while(text >= prepoint) { if(matchpattern(pattern, text--, matchlength)) { return 1; } (*matchlength)--; } *matchlength = prelen; return 0; } static int matchplus (regex_t p, regex_t* pattern, const char* text, int* matchlength) { const char* prepoint = text; while((text[0] != '\0') && matchone(p, *text)) { text++; (*matchlength)++; } while(text > prepoint) { if(matchpattern(pattern, text--, matchlength)) { return 1; } (*matchlength)--; } return 0; } static int matchquestion (regex_t p, regex_t* pattern, const char* text, int* matchlength) { if(p.type == UNUSED) { return 1; } if(matchpattern(pattern, text, matchlength)) { return 1; } if(*text && matchone(p, *text++)) { if(matchpattern(pattern, text, matchlength)) { (*matchlength)++; return 1; } } return 0; } #if 0 /* Recursive matching */ static int matchpattern (regex_t* pattern, const char* text, int *matchlength) { int pre = *matchlength; if((pattern[0].type == UNUSED) || (pattern[1].type == QUESTIONMARK)) { return matchquestion(pattern[1], &pattern[2], text, matchlength); } else if(pattern[1].type == STAR) { return matchstar(pattern[0], &pattern[2], text, matchlength); } else if(pattern[1].type == PLUS) { return matchplus(pattern[0], &pattern[2], text, matchlength); } else if((pattern[0].type == END) && pattern[1].type == UNUSED) { return text[0] == '\0'; } else if((text[0] != '\0') && matchone(pattern[0], text[0])) { (*matchlength)++; return matchpattern(&pattern[1], text+1); } else { *matchlength = pre; return 0; } } #else /* Iterative matching */ static int matchpattern (regex_t* pattern, const char* text, int* matchlength) { int pre = *matchlength; do { if((pattern[0].type == UNUSED) || (pattern[1].type == QUESTIONMARK)) { return matchquestion(pattern[0], &pattern[2], text, matchlength); } else if(pattern[1].type == STAR) { return matchstar(pattern[0], &pattern[2], text, matchlength); } else if(pattern[1].type == PLUS) { return matchplus(pattern[0], &pattern[2], text, matchlength); } else if((pattern[0].type == END) && pattern[1].type == UNUSED) { return (text[0] == '\0'); } /* Branching is not working properly else if (pattern[1].type == BRANCH) { return (matchpattern(pattern, text) || matchpattern(&pattern[2], text)); } */ (*matchlength)++; } while((text[0] != '\0') && matchone(*pattern++, *text++)); *matchlength = pre; return 0; } #endif ntop-n2n-90215bd/src/network_traffic_filter.c000066400000000000000000000762211422132035700212130ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #include "network_traffic_filter.h" #include "uthash.h" // cache that hit less than 10 while 10000 package processed will be delete; #define CLEAR_CACHE_EVERY_X_COUNT 10000 #define CLAER_CACHE_ACTIVE_COUNT 10 /* for [-Wmissing-declarations] */ const char* get_filter_packet_proto_name (filter_packet_proto proto); const char* get_filter_packet_proto_name (filter_packet_proto proto) { switch(proto) { case FPP_ARP: return "ARP"; case FPP_TCP: return "TCP"; case FPP_UDP: return "UDP"; case FPP_ICMP: return "ICMP"; case FPP_IGMP: return "IGMP"; default: return "UNKNOWN_PROTO"; } } /* for [-Wmissing-declarations] */ const char* get_filter_packet_info_log_string (packet_address_proto_info_t* info); const char* get_filter_packet_info_log_string (packet_address_proto_info_t* info) { static char buf[1024] = {0}; switch(info->proto) { case FPP_ARP: case FPP_ICMP: case FPP_IGMP: return get_filter_packet_proto_name(info->proto); case FPP_TCP: case FPP_UDP: { struct in_addr src, dst; src.s_addr = info->src_ip; dst.s_addr = info->dst_ip; const char* proto = get_filter_packet_proto_name(info->proto); char src_ip[64] = {0}; char dst_ip[64] = {0}; strcpy(src_ip, inet_ntoa(src)); strcpy(dst_ip, inet_ntoa(dst)); sprintf(buf, "%s\t%s:%d->%s:%d", proto, src_ip, info->src_port, dst_ip, info->dst_port); return buf; } default: return "UNKNOWN_PROTO"; } } /* for [-Wmissing-declarations] */ void collect_packet_info (packet_address_proto_info_t* out_info, unsigned char *buffer, int size); void collect_packet_info (packet_address_proto_info_t* out_info, unsigned char *buffer, int size) { ether_hdr_t *hdr_ether = (ether_hdr_t*)buffer; uint16_t ether_type = ntohs(hdr_ether->type); struct n2n_iphdr *hdr_ip = NULL; struct n2n_tcphdr *hdr_tcp = NULL; struct n2n_udphdr *udp_hdr = NULL; memset(out_info, 0, sizeof(packet_address_proto_info_t)); switch(ether_type) { case 0x0800: { buffer += sizeof(ether_hdr_t); size -= sizeof(ether_hdr_t); if(size <= 0) { return; } hdr_ip = (struct n2n_iphdr*)buffer; switch(hdr_ip->version) { case 4: { out_info->src_ip = hdr_ip->saddr; out_info->dst_ip = hdr_ip->daddr; switch(hdr_ip->protocol) { case 0x01: out_info->proto = FPP_ICMP; break; case 0x02: out_info->proto = FPP_IGMP; break; case 0x06: { out_info->proto = FPP_TCP; buffer += hdr_ip->ihl * 4; size -= hdr_ip->ihl * 4; if(size <= 0) { return; } hdr_tcp = (struct n2n_tcphdr*)buffer; out_info->src_port = ntohs(hdr_tcp->source); out_info->dst_port = ntohs(hdr_tcp->dest); break; } case 0x11: { out_info->proto = FPP_UDP; buffer += hdr_ip->ihl * 4; size -= hdr_ip->ihl * 4; if(size <= 0) { return; } udp_hdr = (struct n2n_udphdr*)buffer; out_info->src_port = ntohs(udp_hdr->source); out_info->dst_port = ntohs(udp_hdr->dest); break; } default: out_info->proto = FPP_UNKNOWN; }; break; } case 6: { // TODO: IPV6 Not Support out_info->proto = FPP_UNKNOWN; break; } default: out_info->proto = FPP_UNKNOWN; } break; } case 0x0806: out_info->proto = FPP_ARP; break; case 0x86DD: out_info->proto = FPP_UNKNOWN; break; default: traceEvent(TRACE_DEBUG, "collect_packet_info stumbled across the unknown ether type 0x%04X", ether_type); }; } /* for [-Wmissing-declarations] */ const char* get_filter_rule_info_log_string (filter_rule_t* rule); const char* get_filter_rule_info_log_string (filter_rule_t* rule) { static char buf[1024] = {0}; char* print_start = buf; char src_net[64] = {0}; char dst_net[64] = {0}; struct in_addr src, dst; src.s_addr = rule->key.src_net_cidr; dst.s_addr = rule->key.dst_net_cidr; strcpy(src_net, inet_ntoa(src)); strcpy(dst_net, inet_ntoa(dst)); print_start += sprintf(print_start, "%s/%d:[%d,%d],%s/%d:[%d,%d]", src_net, rule->key.src_net_bit_len, rule->key.src_port_range.start_port, rule->key.src_port_range.end_port, dst_net, rule->key.dst_net_bit_len, rule->key.dst_port_range.start_port, rule->key.dst_port_range.end_port #if 0 , rule->bool_accept_tcp ? '+' : '-', rule->bool_accept_udp ? '+' : '-', rule->bool_accept_icmp ? '+' : '-' #endif ); if(rule->key.bool_tcp_configured) { print_start += sprintf(print_start, ",TCP%c", rule->bool_accept_tcp ? '+' : '-'); } if(rule->key.bool_udp_configured) { print_start += sprintf(print_start, ",UDP%c", rule->bool_accept_udp ? '+' : '-'); } if(rule->key.bool_icmp_configured) { print_start += sprintf(print_start, ",ICMP%c", rule->bool_accept_icmp ? '+' : '-'); } return buf; } /* for [-Wmissing-declarations] */ uint8_t march_cidr_and_address (in_addr_t network, uint8_t net_bitlen, in_addr_t ip_addr); uint8_t march_cidr_and_address (in_addr_t network, uint8_t net_bitlen, in_addr_t ip_addr) { in_addr_t mask = 0, ip_addr_network = 0; network = ntohl(network); ip_addr = ntohl(ip_addr); uint32_t mask1 = net_bitlen != 0 ? ((~mask) << (32u-net_bitlen)) : 0; ip_addr_network = ip_addr & mask1; if(network == ip_addr_network) { return net_bitlen + 1; // march 0.0.0.0/0 still march success, that case return 1 } else { return 0; } } /* for [-Wmissing-declarations] */ uint8_t march_rule_and_cache_key (filter_rule_key_t *rule_key, packet_address_proto_info_t *pkt_addr_info); // if ports march, compare cidr. if cidr ok, return sum of src&dst cidr net_bitlen. means always select larger net_bitlen record when multi record is marched. uint8_t march_rule_and_cache_key (filter_rule_key_t *rule_key, packet_address_proto_info_t *pkt_addr_info) { // march failed if proto is not configured at the rule. switch(pkt_addr_info->proto) { case FPP_ICMP: if(!rule_key->bool_icmp_configured) { return 0; } break; case FPP_UDP: if(!rule_key->bool_udp_configured) { return 0; } break; case FPP_TCP: if(!rule_key->bool_tcp_configured) { return 0; } break; default: return 0; } // ignore ports for ICMP proto. if(pkt_addr_info->proto == FPP_ICMP || (rule_key->src_port_range.start_port <= pkt_addr_info->src_port && pkt_addr_info->src_port <= rule_key->src_port_range.end_port && rule_key->dst_port_range.start_port <= pkt_addr_info->dst_port && pkt_addr_info->dst_port <= rule_key->dst_port_range.end_port)) { uint8_t march_src_score = march_cidr_and_address(rule_key->src_net_cidr, rule_key->src_net_bit_len, pkt_addr_info->src_ip); uint8_t march_dst_score = march_cidr_and_address(rule_key->dst_net_cidr, rule_key->dst_net_bit_len, pkt_addr_info->dst_ip); if((march_src_score > 0) && (march_dst_score > 0)) { return march_src_score + march_dst_score; } } return(0); } /* for [-Wmissing-declarations] */ filter_rule_t* get_filter_rule (filter_rule_t **rules, packet_address_proto_info_t *pkt_addr_info); filter_rule_t* get_filter_rule (filter_rule_t **rules, packet_address_proto_info_t *pkt_addr_info) { filter_rule_t *item = 0, *tmp = 0, *marched_rule = 0; int march_score = 0; HASH_ITER(hh, *rules, item, tmp) { /* ... it is safe to delete and free s here */ uint8_t cur_march_score = march_rule_and_cache_key(&(item->key), pkt_addr_info); if(cur_march_score > march_score) { marched_rule = item; march_score = cur_march_score; } } return marched_rule; } /* for [-Wmissing-declarations] */ void update_and_clear_cache_if_need (network_traffic_filter_t *filter); void update_and_clear_cache_if_need (network_traffic_filter_t *filter) { if(++(filter->work_count_scene_last_clear) > CLEAR_CACHE_EVERY_X_COUNT) { filter_rule_pair_cache_t *item = NULL, *tmp = NULL; HASH_ITER(hh, filter->connections_rule_cache, item, tmp) { /* ... it is safe to delete and free s here */ if(item->active_count < CLAER_CACHE_ACTIVE_COUNT) { traceEvent(TRACE_DEBUG, "### DELETE filter cache %s", get_filter_packet_info_log_string(&item->key)); HASH_DEL(filter->connections_rule_cache, item); free(item); } else { item->active_count = 0; } } filter->work_count_scene_last_clear = 0; } } /* for [-Wmissing-declarations] */ filter_rule_pair_cache_t* get_or_create_filter_rule_cache (network_traffic_filter_t *filter, packet_address_proto_info_t *pkt_addr_info); filter_rule_pair_cache_t* get_or_create_filter_rule_cache (network_traffic_filter_t *filter, packet_address_proto_info_t *pkt_addr_info) { filter_rule_pair_cache_t* rule_cache_find_result = 0; HASH_FIND(hh, filter->connections_rule_cache, pkt_addr_info, sizeof(packet_address_proto_info_t), rule_cache_find_result); if(!rule_cache_find_result) { filter_rule_t* rule = get_filter_rule(&filter->rules, pkt_addr_info); if(!rule) { return NULL; } rule_cache_find_result = malloc(sizeof(filter_rule_pair_cache_t)); memset(rule_cache_find_result, 0, sizeof(filter_rule_pair_cache_t)); rule_cache_find_result->key = *pkt_addr_info; switch(rule_cache_find_result->key.proto) { case FPP_ICMP: rule_cache_find_result->bool_allow_traffic = rule->bool_accept_icmp; break; case FPP_UDP: rule_cache_find_result->bool_allow_traffic = rule->bool_accept_udp; break; case FPP_TCP: rule_cache_find_result->bool_allow_traffic = rule->bool_accept_tcp; break; default: traceEvent(TRACE_WARNING, "### Generate filter rule cache failed!"); return NULL; } traceEvent(TRACE_DEBUG, "### ADD filter cache %s", get_filter_packet_info_log_string(&rule_cache_find_result->key)); HASH_ADD(hh, filter->connections_rule_cache, key, sizeof(packet_address_proto_info_t), rule_cache_find_result); } ++(rule_cache_find_result->active_count); update_and_clear_cache_if_need(filter); return rule_cache_find_result; } /* for [-Wmissing-declarations] */ n2n_verdict filter_packet_from_peer (network_traffic_filter_t *filter, n2n_edge_t *eee, const n2n_sock_t *peer, uint8_t *payload, uint16_t payload_size); n2n_verdict filter_packet_from_peer (network_traffic_filter_t *filter, n2n_edge_t *eee, const n2n_sock_t *peer, uint8_t *payload, uint16_t payload_size) { filter_rule_pair_cache_t *cur_pkt_rule = 0; packet_address_proto_info_t pkt_info; collect_packet_info(&pkt_info, payload, payload_size); cur_pkt_rule = get_or_create_filter_rule_cache(filter, &pkt_info); if(cur_pkt_rule && !cur_pkt_rule->bool_allow_traffic) { traceEvent(TRACE_DEBUG, "### DROP %s", get_filter_packet_info_log_string(&pkt_info)); return N2N_DROP; } return N2N_ACCEPT; } /* for [-Wmissing-declarations] */ n2n_verdict filter_packet_from_tap (network_traffic_filter_t *filter, n2n_edge_t *eee, uint8_t *payload, uint16_t payload_size); n2n_verdict filter_packet_from_tap (network_traffic_filter_t *filter, n2n_edge_t *eee, uint8_t *payload, uint16_t payload_size) { filter_rule_pair_cache_t *cur_pkt_rule = 0; packet_address_proto_info_t pkt_info; collect_packet_info(&pkt_info, payload, payload_size); cur_pkt_rule = get_or_create_filter_rule_cache(filter, &pkt_info); if(cur_pkt_rule && !cur_pkt_rule->bool_allow_traffic) { traceEvent(TRACE_DEBUG, "### DROP %s", get_filter_packet_info_log_string(&pkt_info)); return N2N_DROP; } return N2N_ACCEPT; } /* for [-Wmissing-declarations] */ network_traffic_filter_t *create_network_traffic_filter (); network_traffic_filter_t *create_network_traffic_filter () { network_traffic_filter_t *filter = malloc(sizeof(network_traffic_filter_t)); memset(filter, 0, sizeof(network_traffic_filter_t)); filter->filter_packet_from_peer = filter_packet_from_peer; filter->filter_packet_from_tap = filter_packet_from_tap; return filter; } /* for [-Wmissing-declarations] */ void destroy_network_traffic_filter (network_traffic_filter_t *filter); void destroy_network_traffic_filter (network_traffic_filter_t *filter) { filter_rule_t *el = 0, *tmp = 0; filter_rule_pair_cache_t* el1 = 0, * tmp1 = 0; HASH_ITER(hh, filter->rules, el, tmp) { HASH_DEL(filter->rules, el); free(el); } HASH_ITER(hh, filter->connections_rule_cache, el1, tmp1) { HASH_DEL(filter->connections_rule_cache, el1); free(el); } free(filter); } /* for [-Wmissing-declarations] */ void network_traffic_filter_add_rule (network_traffic_filter_t* filter, filter_rule_t* rules); void network_traffic_filter_add_rule (network_traffic_filter_t* filter, filter_rule_t* rules) { filter_rule_t *item = NULL, *tmp = NULL; HASH_ITER(hh, rules, item, tmp) { filter_rule_t *new_rule = malloc(sizeof(filter_rule_t)); memcpy(new_rule, item, sizeof(filter_rule_t)); HASH_ADD(hh, filter->rules, key, sizeof(filter_rule_key_t), new_rule); traceEvent(TRACE_NORMAL, "### ADD network traffic filter %s", get_filter_rule_info_log_string(new_rule)); } } /* for [-Wmissing-declarations] */ in_addr_t get_int32_addr_from_ip_string (const char* begin, const char* next_pos_of_last_char); in_addr_t get_int32_addr_from_ip_string (const char* begin, const char* next_pos_of_last_char) { char buf[16] = {0}; if((next_pos_of_last_char - begin) > 15) { traceEvent(TRACE_WARNING, "Internal Error"); return -1; } memcpy(buf, begin, (next_pos_of_last_char - begin)); return inet_addr(buf); } /* for [-Wmissing-declarations] */ int get_int32_from_number_string (const char* begin, const char* next_pos_of_last_char); int get_int32_from_number_string (const char* begin, const char* next_pos_of_last_char) { char buf[6] = {0}; if((next_pos_of_last_char - begin) > 5 ) { // max is 65535, 5 char traceEvent(TRACE_WARNING, "Internal Error"); return 0; } memcpy(buf, begin, (next_pos_of_last_char - begin)); return atoi(buf); } /* for [-Wmissing-declarations] */ void process_traffic_filter_proto (const char* begin, const char* next_pos_of_last_char, filter_rule_t *rule_struct); void process_traffic_filter_proto (const char* begin, const char* next_pos_of_last_char, filter_rule_t *rule_struct) { char buf[6] = {0}; if((next_pos_of_last_char - begin) > 5 ) { // max length str is "ICMP+", 5 char traceEvent(TRACE_WARNING, "Internal Error"); } memcpy(buf, begin, (next_pos_of_last_char - begin)); if(strstr(buf, "TCP")) { rule_struct->key.bool_tcp_configured = 1; rule_struct->bool_accept_tcp = buf[3] == '+'; } else if(strstr(buf, "UDP")) { rule_struct->key.bool_udp_configured = 1; rule_struct->bool_accept_udp = buf[3] == '+'; } else if(strstr(buf, "ICMP")) { rule_struct->key.bool_icmp_configured = 1; rule_struct->bool_accept_icmp = buf[4] == '+'; } else { traceEvent(TRACE_WARNING, "Invalid Proto : %s", buf); } } typedef enum { FPS_SRC_NET = 1, FPS_SRC_NET_BIT_LEN, FPS_SRC_PORT_SINGLE, FPS_SRC_PORT_RANGE, FPS_SRC_PORT_START, FPS_SRC_PORT_END, FPS_DST_NET, FPS_DST_NET_BIT_LEN, FPS_DST_PORT_SINGLE, FPS_DST_PORT_RANGE, FPS_DST_PORT_START, FPS_DST_PORT_END, FPS_PROTO } filter_process_stage; /* for [-Wmissing-declarations] */ uint8_t process_traffic_filter_rule_str (const char *rule_str, filter_rule_t *rule_struct); uint8_t process_traffic_filter_rule_str (const char *rule_str, filter_rule_t *rule_struct) { const char *cur_pos = rule_str, *stage_begin_pos = rule_str; filter_process_stage stage = FPS_SRC_NET; while(1) { switch(stage) { case FPS_SRC_NET: { if((*cur_pos >= '0' && *cur_pos <= '9') || *cur_pos == '.') { ; // Normal FPS_SRC_NET, next char } else if(*cur_pos == '/') { // FPS_SRC_NET finish, next is FPS_SRC_NET_BIT_LEN rule_struct->key.src_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); stage_begin_pos = cur_pos + 1; stage = FPS_SRC_NET_BIT_LEN; } else if(*cur_pos == ':') { // FPS_SRC_NET finish, ignore FPS_SRC_NET_BIT_LEN(default 32), next is one of FPS_SRC_PORT_RANGE/FPS_SRC_PORT_SINGLE rule_struct->key.src_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); rule_struct->key.src_net_bit_len = 32; stage_begin_pos = cur_pos + 1; if(*(cur_pos + 1) == '[') { stage = FPS_SRC_PORT_RANGE; } else { stage = FPS_SRC_PORT_SINGLE; } } else if(*cur_pos == ',') { // FPS_SRC_NET finish, ignore FPS_SRC_NET_BIT_LEN(default 32), ignore FPS_SRC_PORT(default all), // next is FPS_DST_NET rule_struct->key.src_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); rule_struct->key.src_net_bit_len = 32; rule_struct->key.src_port_range.start_port = 0; rule_struct->key.src_port_range.end_port = 65535; stage_begin_pos = cur_pos + 1; stage = FPS_DST_NET; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_SRC_NET_BIT_LEN: { if((*cur_pos >= '0') && (*cur_pos <= '9')) { ; // Normal FPS_SRC_NET_BIT_LEN, next char } else if(*cur_pos == ':') { // FPS_SRC_NET_BIT_LEN finish, next is one of FPS_SRC_PORT_RANGE/FPS_SRC_PORT_SINGLE rule_struct->key.src_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos); stage_begin_pos = cur_pos + 1; if(*(cur_pos + 1) == '[') { stage = FPS_SRC_PORT_RANGE; } else { stage = FPS_SRC_PORT_SINGLE; } } else if(*cur_pos == ',') { // FPS_SRC_NET_BIT_LEN finish, ignore FPS_SRC_PORT(default all), next is FPS_DST_NET rule_struct->key.src_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos);; rule_struct->key.src_port_range.start_port = 0; rule_struct->key.src_port_range.end_port = 65535; stage_begin_pos = cur_pos + 1; stage = FPS_DST_NET; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_SRC_PORT_SINGLE: { if((*cur_pos >= '0') && (*cur_pos <= '9')) { ; // Normal FPS_SRC_PORT_SINGLE, next char } else if(*cur_pos == ',') { // FPS_SRC_PORT_SINGLE finish, next is FPS_DST_NET rule_struct->key.src_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); rule_struct->key.src_port_range.end_port = rule_struct->key.src_port_range.start_port; stage_begin_pos = cur_pos + 1; stage = FPS_DST_NET; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_SRC_PORT_RANGE: { if(*cur_pos == '[') { stage_begin_pos = cur_pos + 1; stage = FPS_SRC_PORT_START; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_SRC_PORT_START: { if((*cur_pos >= '0') && (*cur_pos <= '9')) { ; // Normal FPS_SRC_PORT_START, next char } else if(*cur_pos == ',') { // FPS_SRC_PORT_START finish, next is FPS_SRC_PORT_END rule_struct->key.src_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); stage_begin_pos = cur_pos + 1; stage = FPS_SRC_PORT_END; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_SRC_PORT_END: { if((*cur_pos >= '0') && (*cur_pos <= '9')) { ; // Normal FPS_SRC_PORT_END, next char } else if((*cur_pos == ']') && (*(cur_pos + 1) == ',')) { // FPS_SRC_PORT_END finish, next is FPS_DST_NET rule_struct->key.src_port_range.end_port = get_int32_from_number_string(stage_begin_pos, cur_pos); stage_begin_pos = cur_pos + 2; stage = FPS_DST_NET; ++cur_pos; //skip next char ',' } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_DST_NET: { if((*cur_pos >= '0' && *cur_pos <= '9') || *cur_pos == '.') { ; // Normal FPS_DST_NET, next char } else if(*cur_pos == '/') { // FPS_DST_NET finish, next is FPS_DST_NET_BIT_LEN rule_struct->key.dst_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); stage_begin_pos = cur_pos + 1; stage = FPS_DST_NET_BIT_LEN; } else if(*cur_pos == ':') { // FPS_DST_NET finish, ignore FPS_DST_NET_BIT_LEN(default 32), next is one of FPS_DST_PORT_RANGE/FPS_DST_PORT_SINGLE rule_struct->key.dst_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); rule_struct->key.dst_net_bit_len = 32; stage_begin_pos = cur_pos + 1; if(*(cur_pos + 1) == '[') { stage = FPS_DST_PORT_RANGE; } else { stage = FPS_DST_PORT_SINGLE; } } else if((*cur_pos == ',') || (*cur_pos == 0)) { // FPS_DST_NET finish, ignore FPS_DST_NET_BIT_LEN(default 32), ignore FPS_DST_PORT(default all), // next is FPS_PROTO rule_struct->key.dst_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); rule_struct->key.dst_net_bit_len = 32; rule_struct->key.dst_port_range.start_port = 0; rule_struct->key.dst_port_range.end_port = 65535; stage_begin_pos = cur_pos + 1; stage = FPS_PROTO; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_DST_NET_BIT_LEN: { if((*cur_pos >= '0') && (*cur_pos <= '9')) { ; // Normal FPS_DST_NET_BIT_LEN, next char } else if(*cur_pos == ':') { // FPS_DST_NET_BIT_LEN finish, next is one of FPS_DST_PORT_RANGE/FPS_DST_PORT_SINGLE rule_struct->key.dst_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos); stage_begin_pos = cur_pos + 1; if(*(cur_pos + 1) == '[') { stage = FPS_DST_PORT_RANGE; } else { stage = FPS_DST_PORT_SINGLE; } } else if((*cur_pos == ',') || (*cur_pos == 0)) { // FPS_DST_NET_BIT_LEN finish, ignore FPS_DST_PORT(default all), next is FPS_PROTO rule_struct->key.dst_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos);; rule_struct->key.dst_port_range.start_port = 0; rule_struct->key.dst_port_range.end_port = 65535; stage_begin_pos = cur_pos + 1; stage = FPS_PROTO; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_DST_PORT_SINGLE: { if((*cur_pos >= '0') && (*cur_pos <= '9')) { ; // Normal FPS_DST_PORT_SINGLE, next char } else if((*cur_pos == ',') || (*cur_pos == 0)) { // FPS_DST_PORT_SINGLE finish, next is FPS_PROTO rule_struct->key.dst_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); rule_struct->key.dst_port_range.end_port = rule_struct->key.dst_port_range.start_port; stage_begin_pos = cur_pos + 1; stage = FPS_PROTO; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_DST_PORT_RANGE: { if(*cur_pos == '[') { stage_begin_pos = cur_pos + 1; stage = FPS_DST_PORT_START; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_DST_PORT_START: { if((*cur_pos >= '0') && (*cur_pos <= '9')) { ; // Normal FPS_DST_PORT_START, next char } else if(*cur_pos == ',') { // FPS_DST_PORT_START finish, next is FPS_DST_PORT_END rule_struct->key.dst_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); stage_begin_pos = cur_pos + 1; stage = FPS_DST_PORT_END; } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_DST_PORT_END: { if((*cur_pos >= '0') && (*cur_pos <= '9')) { ; // Normal FPS_DST_PORT_END, next char } else if(*cur_pos == ']') { // FPS_DST_PORT_END finish, next is FPS_PROTO rule_struct->key.dst_port_range.end_port = get_int32_from_number_string(stage_begin_pos, cur_pos); stage = FPS_PROTO; if(*(cur_pos + 1) == ',') { stage_begin_pos = cur_pos + 2; ++cur_pos; //skip next char ',' } else if(*(cur_pos + 1) != 0) { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } } else { traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); return 0; } break; } case FPS_PROTO: { if((*cur_pos != '-') && (*cur_pos != '+') && (*cur_pos != ',')) { ; // Normal FPS_PROTO. next char } else if(*cur_pos != ',') { process_traffic_filter_proto(stage_begin_pos, cur_pos + 1, rule_struct); if(*(cur_pos+1) == 0) { // end of whole rule string break; } else { // new proto info, and skip next char ',' stage_begin_pos = cur_pos + 2; ++cur_pos; } } else { traceEvent(TRACE_WARNING, "Internal Error: ',' should skiped", *cur_pos, cur_pos - rule_str); return 0; } break; } } if(0 == *cur_pos) { break; } ++cur_pos; } return 1; } ntop-n2n-90215bd/src/pearson.c000066400000000000000000000122071422132035700161200ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // taken from https://github.com/Logan007/pearsonB // this is free and unencumbered software released into the public domain #include "pearson.h" // Christopher Wellons' triple32 from https://github.com/skeeto/hash-prospector // published under The Unlicense #define permute32(in) \ in ^= in >> 17; \ in *= 0xed5ad4bb; \ in ^= in >> 11; \ in *= 0xac4c1b51; \ in ^= in >> 15; \ in *= 0x31848bab; \ in ^= in >> 14 // David Stafford's Mix13 from http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html // the author clarified via eMail that this of his work is released to the public domain #define permute64(in) \ in ^= (in >> 30); \ in *= 0xbf58476d1ce4e5b9; \ in ^= (in >> 27); \ in *= 0x94d049bb133111eb; \ in ^= (in >> 31) #define dec1(in) \ in-- #define dec2(in) \ dec1(in); \ dec1(in) #define dec3(in) \ dec2(in); \ dec1(in) #define dec4(in) \ dec3(in); \ dec1(in) #define hash_round(hash, in, part) \ hash##part ^= in; \ dec##part(hash##part); \ permute64(hash##part) void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len) { uint64_t *current; current = (uint64_t*)in; uint64_t org_len = len; uint64_t hash1 = 0; uint64_t hash2 = 0; uint64_t hash3 = 0; uint64_t hash4 = 0; while (len > 7) { // digest words little endian first hash_round(hash, le64toh(*current), 1); hash_round(hash, le64toh(*current), 2); hash_round(hash, le64toh(*current), 3); hash_round(hash, le64toh(*current), 4); current++; len-=8; } // handle the rest hash1 = ~hash1; hash2 = ~hash2; hash3 = ~hash3; hash4 = ~hash4; while(len) { // byte-wise, no endianess hash_round(hash, *(uint8_t*)current, 1); hash_round(hash, *(uint8_t*)current, 2); hash_round(hash, *(uint8_t*)current, 3); hash_round(hash, *(uint8_t*)current, 4); current = (uint64_t*)((uint8_t*)current + 1); len--; } // digest length hash1 = ~hash1; hash2 = ~hash2; hash3 = ~hash3; hash4 = ~hash4; hash_round(hash, org_len, 1); hash_round(hash, org_len, 2); hash_round(hash, org_len, 3); hash_round(hash, org_len, 4); // hash string is stored big endian, the natural way to read uint64_t *o; o = (uint64_t*)out; *o = htobe64(hash4); o++; *o = htobe64(hash3); o++; *o = htobe64(hash2); o++; *o = htobe64(hash1); } void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len) { uint64_t *current; current = (uint64_t*)in; uint64_t org_len = len; uint64_t hash1 = 0; uint64_t hash2 = 0; while (len > 7) { // digest words little endian first hash_round(hash, le64toh(*current), 1); hash_round(hash, le64toh(*current), 2); current++; len-=8; } // handle the rest hash1 = ~hash1; hash2 = ~hash2; while(len) { // byte-wise, no endianess hash_round(hash, *(uint8_t*)current, 1); hash_round(hash, *(uint8_t*)current, 2); current = (uint64_t*)((uint8_t*)current + 1); len--; } // digest length hash1 = ~hash1; hash2 = ~hash2; hash_round(hash, org_len, 1); hash_round(hash, org_len, 2); // hash string is stored big endian, the natural way to read uint64_t *o; o = (uint64_t*)out; *o = htobe64(hash2); o++; *o = htobe64(hash1); } uint64_t pearson_hash_64 (const uint8_t *in, size_t len) { uint64_t *current; current = (uint64_t*)in; uint64_t org_len = len; uint64_t hash1 = 0; while(len > 7) { // digest words little endian first hash_round(hash, le64toh(*current), 1); current++; len-=8; } // handle the rest hash1 = ~hash1; while(len) { // byte-wise, no endianess hash_round(hash, *(uint8_t*)current, 1); current = (uint64_t*)((uint8_t*)current + 1); len--; } // digest length hash1 = ~hash1; hash_round(hash, org_len, 1); // caller is responsible for storing it big endian to memory (if ever) return hash1; } uint32_t pearson_hash_32 (const uint8_t *in, size_t len) { return pearson_hash_64(in, len); } uint16_t pearson_hash_16 (const uint8_t *in, size_t len) { return pearson_hash_64(in, len); } void pearson_hash_init(void) { } ntop-n2n-90215bd/src/random_numbers.c000066400000000000000000000155321422132035700174700ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "random_numbers.h" // the following code offers an alterate pseudo random number generator // namely XORSHIFT128+ to use instead of C's rand() // its performance is on par with C's rand() // the state must be seeded in a way that it is not all zero, choose some // arbitrary defaults (in this case: taken from splitmix64) static rn_generator_state_t rn_current_state = { .a = 0x9E3779B97F4A7C15, .b = 0xBF58476D1CE4E5B9 }; // used for mixing the initializing seed static uint64_t splitmix64 (splitmix64_state_t *state) { uint64_t result = state->s; state->s = result + 0x9E3779B97F4A7C15; result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9; result = (result ^ (result >> 27)) * 0x94D049BB133111EB; return result ^ (result >> 31); } int n2n_srand (uint64_t seed) { uint8_t i; splitmix64_state_t smstate = { seed }; rn_current_state.a = 0; rn_current_state.b = 0; rn_current_state.a = splitmix64 (&smstate); rn_current_state.b = splitmix64 (&smstate); // the following lines could be deleted as soon as it is formally prooved that // there is no seed leading to (a == b == 0). until then, just to be safe: if((rn_current_state.a == 0) && (rn_current_state.b == 0)) { rn_current_state.a = 0x9E3779B97F4A7C15; rn_current_state.b = 0xBF58476D1CE4E5B9; } // stabilize in unlikely case of weak state with only a few bits set for(i = 0; i < 32; i++) n2n_rand(); return 0; } // the following code of xorshift128p was taken from // https://en.wikipedia.org/wiki/Xorshift as of July, 2019 // and thus is considered public domain uint64_t n2n_rand (void) { uint64_t t = rn_current_state.a; uint64_t const s = rn_current_state.b; rn_current_state.a = s; t ^= t << 23; t ^= t >> 17; t ^= s ^ (s >> 26); rn_current_state.b = t; return t + s; } // the following code tries to gather some entropy from several sources // for use as seed. Note, that this code does not set the random generator // state yet, a call to n2n_srand (n2n_seed()) would do uint64_t n2n_seed (void) { uint64_t seed = 0; /* this could even go uninitialized */ uint64_t ret = 0; /* this could even go uninitialized */ size_t i = 0; #ifdef SYS_getrandom int rc = -1; for(i = 0; (i < RND_RETRIES) && (rc != sizeof(seed)); i++) { rc = syscall (SYS_getrandom, &seed, sizeof(seed), GRND_NONBLOCK); // if successful, rc should contain the requested number of random bytes if(rc != sizeof(seed)) { if (errno != EAGAIN) { traceEvent(TRACE_ERROR, "n2n_seed faced error errno=%u from getrandom syscall.", errno); break; } } } // if we still see an EAGAIN error here, we must have run out of retries if(errno == EAGAIN) { traceEvent(TRACE_ERROR, "n2n_seed saw getrandom syscall indicate not being able to provide enough entropy yet."); } #endif // as we want randomness, it does no harm to add up even uninitialized values or // erroneously arbitrary values returned from the syscall for the first time ret += seed; // __RDRND__ is set only if architecturual feature is set, e.g. compiled with -march=native #ifdef __RDRND__ for(i = 0; i < RND_RETRIES; i++) { if(_rdrand64_step((unsigned long long*)&seed)) { // success! // from now on, we keep this inside the loop because in case of failure // and with unchanged values, we do not want to double the previous value ret += seed; break; } // continue loop to try again otherwise } if(i == RND_RETRIES) { traceEvent(TRACE_ERROR, "n2n_seed was not able to get a hardware generated random number from RDRND."); } #endif // __RDSEED__ ist set only if architecturual feature is set, e.g. compile with -march=native #ifdef __RDSEED__ #if __GNUC__ > 4 for(i = 0; i < RND_RETRIES; i++) { if(_rdseed64_step((unsigned long long*)&seed)) { // success! ret += seed; break; } // continue loop to try again otherwise } if(i == RND_RETRIES) { traceEvent(TRACE_ERROR, "n2n_seed was not able to get a hardware generated random number from RDSEED."); } #endif #endif #ifdef WIN32 HCRYPTPROV crypto_provider; CryptAcquireContext (&crypto_provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); CryptGenRandom (crypto_provider, 8, &seed); CryptReleaseContext (crypto_provider, 0); ret += seed; #endif seed = time(NULL); /* UTC in seconds */ ret += seed; seed = clock(); /* ticks since program start */ seed *= 18444244737; ret += seed; return ret; } // an integer squrare root approximation // from https://stackoverflow.com/a/1100591 static int ftbl[33] = { 0, 1, 1, 2, 2, 4, 5, 8, 11, 16, 22, 32, 45, 64, 90, 128, 181 ,256 ,362, 512, 724, 1024, 1448, 2048, 2896, 4096, 5792, 8192, 11585, 16384, 23170, 32768, 46340 }; static int ftbl2[32] = { 32768, 33276, 33776, 34269, 34755, 35235, 35708, 36174, 36635, 37090, 37540, 37984, 38423, 38858, 39287, 39712, 40132, 40548, 40960, 41367, 41771, 42170, 42566, 42959, 43347, 43733, 44115, 44493, 44869, 45241, 45611, 45977 }; static int i_sqrt (int val) { int cnt = 0; int t = val; while(t) { cnt++; t>>=1; } if(6 >= cnt) t = (val << (6-cnt)); else t = (val >> (cnt-6)); return (ftbl[cnt] * ftbl2[t & 31]) >> 15; } static int32_t int_sqrt (int val) { int ret; ret = i_sqrt (val); ret += i_sqrt (val - ret * ret) / 16; return ret; } // returns a random number from [0, max_n] with higher probability towards the borders uint32_t n2n_rand_sqr (uint32_t max_n) { uint32_t raw_max = 0; uint32_t raw_rnd = 0; int32_t ret = 0; raw_max = (max_n+2) * (max_n+2); raw_rnd = n2n_rand() % (raw_max); ret = int_sqrt(raw_rnd) / 2; ret = (raw_rnd & 1) ? ret : -ret; ret = max_n / 2 + ret; if(ret < 0) ret = 0; if (ret > max_n) ret = max_n; return ret; } ntop-n2n-90215bd/src/sn_management.c000066400000000000000000000564341422132035700172770ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* * This file has a large amount of duplication with the edge_management.c * code. In the fullness of time, they should both be merged */ #include "n2n.h" #include "edge_utils_win32.h" int load_allowed_sn_community (n2n_sn_t *sss); /* defined in sn_utils.c */ enum n2n_mgmt_type { N2N_MGMT_READ = 0, N2N_MGMT_WRITE = 1, }; #define FLAG_WROK 1 typedef struct mgmt_handler { int flags; char *cmd; char *help; void (*func)(n2n_sn_t *sss, char *udp_buf, struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv); } mgmt_handler_t; static void mgmt_error (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, char *tag, char *msg) { size_t msg_len; msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"error\"," "\"error\":\"%s\"}\n", tag, msg); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } static void mgmt_stop (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { size_t msg_len; if(type==N2N_MGMT_WRITE) { *sss->keep_running = 0; } msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"keep_running\":%u}\n", tag, *sss->keep_running); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } static void mgmt_verbose (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { size_t msg_len; if(type==N2N_MGMT_WRITE) { if(argv) { setTraceLevel(strtoul(argv, NULL, 0)); } } msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"traceLevel\":%u}\n", tag, getTraceLevel()); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } static void mgmt_reload_communities (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { size_t msg_len; if(type!=N2N_MGMT_WRITE) { mgmt_error(sss, udp_buf, sender_sock, tag, "writeonly"); return; } if(!sss->community_file) { mgmt_error(sss, udp_buf, sender_sock, tag, "nofile"); return; } int ok = load_allowed_sn_community(sss); msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"ok\":%i}\n", tag, ok); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } static void mgmt_timestamps (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { size_t msg_len; msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"start_time\":%lu," "\"last_fwd\":%ld," "\"last_reg_super\":%ld}\n", tag, sss->start_time, sss->stats.last_fwd, sss->stats.last_reg_super); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } static void mgmt_packetstats (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { size_t msg_len; msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"type\":\"forward\"," "\"tx_pkt\":%lu}\n", tag, sss->stats.fwd); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"type\":\"broadcast\"," "\"tx_pkt\":%lu}\n", tag, sss->stats.broadcast); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"type\":\"reg_super\"," "\"rx_pkt\":%lu," "\"nak\":%lu}\n", tag, sss->stats.reg_super, sss->stats.reg_super_nak); /* Note: reg_super_nak is not currently incremented anywhere */ sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); /* Generic errors when trying to sendto() */ msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"type\":\"errors\"," "\"tx_pkt\":%lu}\n", tag, sss->stats.errors); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } static void mgmt_communities (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { size_t msg_len; struct sn_community *community, *tmp; dec_ip_bit_str_t ip_bit_str = {'\0'}; HASH_ITER(hh, sss->communities, community, tmp) { msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"community\":\"%s\"," "\"purgeable\":%i," "\"is_federation\":%i," "\"ip4addr\":\"%s\"}\n", tag, (community->is_federation) ? "-/-" : community->community, community->purgeable, community->is_federation, (community->auto_ip_net.net_addr == 0) ? "" : ip_subnet_to_str(ip_bit_str, &community->auto_ip_net)); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } } static void mgmt_edges (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { size_t msg_len; struct sn_community *community, *tmp; struct peer_info *peer, *tmpPeer; macstr_t mac_buf; n2n_sock_str_t sockbuf; dec_ip_bit_str_t ip_bit_str = {'\0'}; HASH_ITER(hh, sss->communities, community, tmp) { HASH_ITER(hh, community->edges, peer, tmpPeer) { msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"community\":\"%s\"," "\"ip4addr\":\"%s\"," "\"purgeable\":%i," "\"macaddr\":\"%s\"," "\"sockaddr\":\"%s\"," "\"proto\":\"%s\"," "\"desc\":\"%s\"," "\"last_seen\":%li}\n", tag, (community->is_federation) ? "-/-" : community->community, (peer->dev_addr.net_addr == 0) ? "" : ip_subnet_to_str(ip_bit_str, &peer->dev_addr), peer->purgeable, (is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), ((peer->socket_fd >= 0) && (peer->socket_fd != sss->sock)) ? "TCP" : "UDP", peer->dev_desc, peer->last_seen); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } } } static void mgmt_unimplemented (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { mgmt_error(sss, udp_buf, sender_sock, tag, "unimplemented"); } static void mgmt_help (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv); mgmt_handler_t mgmt_handlers[] = { { .cmd = "supernodes", .help = "Reserved for edge", .func = mgmt_unimplemented}, { .cmd = "stop", .flags = FLAG_WROK, .help = "Gracefully exit edge", .func = mgmt_stop}, { .cmd = "verbose", .flags = FLAG_WROK, .help = "Manage verbosity level", .func = mgmt_verbose}, { .cmd = "reload_communities", .flags = FLAG_WROK, .help = "Reloads communities and user's public keys", .func = mgmt_reload_communities}, { .cmd = "communities", .help = "List current communities", .func = mgmt_communities}, { .cmd = "edges", .help = "List current edges/peers", .func = mgmt_edges}, { .cmd = "timestamps", .help = "Event timestamps", .func = mgmt_timestamps}, { .cmd = "packetstats", .help = "Traffic statistics", .func = mgmt_packetstats}, { .cmd = "help", .flags = FLAG_WROK, .help = "Show JSON commands", .func = mgmt_help}, { .cmd = NULL }, }; static void mgmt_help (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { size_t msg_len; mgmt_handler_t *handler; /* * Even though this command is readonly, we deliberately do not check * the type - allowing help replies to both read and write requests */ for( handler=mgmt_handlers; handler->cmd; handler++ ) { msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{" "\"_tag\":\"%s\"," "\"_type\":\"row\"," "\"cmd\":\"%s\"," "\"help\":\"%s\"}\n", tag, handler->cmd, handler->help); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); } } /* * Check if the user is authorised for this command. * - this should be more configurable! * - for the moment we use some simple heuristics: * Reads are not dangerous, so they are simply allowed * Writes are possibly dangerous, so they need a fake password */ static int mgmt_auth (n2n_sn_t *sss, const struct sockaddr_in sender_sock, enum n2n_mgmt_type type, char *auth, char *argv0, char *argv) { if(auth) { /* If we have an auth key, it must match */ if(sss->mgmt_password_hash == pearson_hash_64((uint8_t*)auth, strlen(auth))) { return 1; } return 0; } /* if we dont have an auth key, we can still read */ if(type == N2N_MGMT_READ) { return 1; } return 0; } static void handleMgmtJson (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in sender_sock) { char cmdlinebuf[80]; enum n2n_mgmt_type type; char *typechar; char *options; char *argv0; char *argv; char *tag; char *flagstr; int flags; char *auth; mgmt_handler_t *handler; size_t msg_len; /* save a copy of the commandline before we reuse the udp_buf */ strncpy(cmdlinebuf, udp_buf, sizeof(cmdlinebuf)-1); cmdlinebuf[sizeof(cmdlinebuf)-1] = 0; traceEvent(TRACE_DEBUG, "mgmt json %s", cmdlinebuf); typechar = strtok(cmdlinebuf, " \r\n"); if(!typechar) { /* should not happen */ mgmt_error(sss, udp_buf, sender_sock, "-1", "notype"); return; } if(*typechar == 'r') { type=N2N_MGMT_READ; } else if(*typechar == 'w') { type=N2N_MGMT_WRITE; } else { /* dunno how we got here */ mgmt_error(sss, udp_buf, sender_sock, "-1", "badtype"); return; } /* Extract the tag to use in all reply packets */ options = strtok(NULL, " \r\n"); if(!options) { mgmt_error(sss, udp_buf, sender_sock, "-1", "nooptions"); return; } argv0 = strtok(NULL, " \r\n"); if(!argv0) { mgmt_error(sss, udp_buf, sender_sock, "-1", "nocmd"); return; } /* * The entire rest of the line is the argv. We apply no processing * or arg separation so that the cmd can use it however it needs. */ argv = strtok(NULL, "\r\n"); /* * There might be an auth token mixed in with the tag */ tag = strtok(options, ":"); flagstr = strtok(NULL, ":"); if(flagstr) { flags = strtoul(flagstr, NULL, 16); } else { flags = 0; } /* Only 1 flag bit defined at the moment - "auth option present" */ if(flags & 1) { auth = strtok(NULL, ":"); } else { auth = NULL; } if(!mgmt_auth(sss, sender_sock, type, auth, argv0, argv)) { mgmt_error(sss, udp_buf, sender_sock, tag, "badauth"); return; } for( handler=mgmt_handlers; handler->cmd; handler++ ) { if(0 == strcmp(handler->cmd, argv0)) { break; } } if(!handler->cmd) { mgmt_error(sss, udp_buf, sender_sock, tag, "unknowncmd"); return; } if((type==N2N_MGMT_WRITE) && !(handler->flags & FLAG_WROK)) { mgmt_error(sss, udp_buf, sender_sock, tag, "readonly"); return; } /* * TODO: * The tag provided by the requester could contain chars * that make our JSON invalid. * - do we care? */ msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{\"_tag\":\"%s\",\"_type\":\"begin\",\"cmd\":\"%s\"}\n", tag, argv0); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); handler->func(sss, udp_buf, sender_sock, type, tag, argv0, argv); msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, "{\"_tag\":\"%s\",\"_type\":\"end\"}\n", tag); sendto(sss->mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); return; } static int sendto_mgmt (n2n_sn_t *sss, const struct sockaddr_in *sender_sock, const uint8_t *mgmt_buf, size_t mgmt_size) { ssize_t r = sendto(sss->mgmt_sock, (void *)mgmt_buf, mgmt_size, 0 /*flags*/, (struct sockaddr *)sender_sock, sizeof (struct sockaddr_in)); if(r <= 0) { ++(sss->stats.errors); traceEvent(TRACE_ERROR, "sendto_mgmt : sendto failed. %s", strerror(errno)); return -1; } return 0; } int process_mgmt (n2n_sn_t *sss, const struct sockaddr_in *sender_sock, char *mgmt_buf, size_t mgmt_size, time_t now) { char resbuf[N2N_SN_PKTBUF_SIZE]; size_t ressize = 0; uint32_t num_edges = 0; uint32_t num_comm = 0; uint32_t num = 0; struct sn_community *community, *tmp; struct peer_info *peer, *tmpPeer; macstr_t mac_buf; n2n_sock_str_t sockbuf; char time_buf[10]; /* 9 digits + 1 terminating zero */ dec_ip_bit_str_t ip_bit_str = {'\0'}; traceEvent(TRACE_DEBUG, "process_mgmt"); /* avoid parsing any uninitialized junk from the stack */ mgmt_buf[mgmt_size] = 0; // process input, if any if((0 == memcmp(mgmt_buf, "help", 4)) || (0 == memcmp(mgmt_buf, "?", 1))) { ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "Help for supernode management console:\n" "\thelp | This help message\n" "\treload_communities | Reloads communities and user's public keys\n" "\t | Display status and statistics\n"); sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); return 0; /* no status output afterwards */ } if(0 == memcmp(mgmt_buf, "reload_communities", 18)) { if(!sss->community_file) { ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "No community file provided (-c command line option)\n"); sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); return 0; /* no status output afterwards */ } traceEvent(TRACE_NORMAL, "'reload_communities' command"); if(load_allowed_sn_community(sss)) { ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "Error while re-loading community file (not found or no valid content)\n"); sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); return 0; /* no status output afterwards */ } ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "OK.\n"); sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); return 0; /* no status output afterwards */ } if((mgmt_buf[0] == 'r' || mgmt_buf[0] == 'w') && (mgmt_buf[1] == ' ')) { /* this is a JSON request */ handleMgmtJson(sss, mgmt_buf, *sender_sock); return 0; } // output current status ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, " ### | TAP | MAC | EDGE | HINT | LAST SEEN\n"); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "========================================================================================================\n"); HASH_ITER(hh, sss->communities, community, tmp) { if(num_comm) ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "--------------------------------------------------------------------------------------------------------\n"); num_comm++; num_edges += HASH_COUNT(community->edges); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "%s '%s'\n", (community->is_federation) ? "FEDERATION" : ((community->purgeable == COMMUNITY_UNPURGEABLE) ? "FIXED NAME COMMUNITY" : "COMMUNITY"), (community->is_federation) ? "-/-" : community->community); sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); ressize = 0; num = 0; HASH_ITER(hh, community->edges, peer, tmpPeer) { sprintf(time_buf, "%9u", (unsigned int)(now - peer->last_seen)); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "%4u | %-19s | %-17s | %-21s %-3s | %-15s | %9s\n", ++num, (peer->dev_addr.net_addr == 0) ? ((peer->purgeable == SN_UNPURGEABLE) ? "-l" : "") : ip_subnet_to_str(ip_bit_str, &peer->dev_addr), (is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), ((peer->socket_fd >= 0) && (peer->socket_fd != sss->sock)) ? "TCP" : "", peer->dev_desc, (peer->last_seen) ? time_buf : ""); sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); ressize = 0; } } ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "========================================================================================================\n"); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "uptime %lu | ", (now - sss->start_time)); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "edges %u | ", num_edges); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "reg_sup %u | ", (unsigned int) sss->stats.reg_super); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "reg_nak %u | ", (unsigned int) sss->stats.reg_super_nak); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "errors %u \n", (unsigned int) sss->stats.errors); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "fwd %u | ", (unsigned int) sss->stats.fwd); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "broadcast %u | ", (unsigned int) sss->stats.broadcast); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "cur_cmnts %u\n", HASH_COUNT(sss->communities)); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "last_fwd %lu sec ago | ", (long unsigned int) (now - sss->stats.last_fwd)); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "last reg %lu sec ago\n\n", (long unsigned int) (now - sss->stats.last_reg_super)); sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); return 0; } ntop-n2n-90215bd/src/sn_selection.c000066400000000000000000000211151422132035700171340ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" static SN_SELECTION_CRITERION_DATA_TYPE sn_selection_criterion_common_read (n2n_edge_t *eee); static int sn_selection_criterion_sort (peer_info_t *a, peer_info_t *b); /* Initialize selection_criterion field in peer_info structure*/ int sn_selection_criterion_init (peer_info_t *peer) { if(peer != NULL) { sn_selection_criterion_default(&(peer->selection_criterion)); } return 0; /* OK */ } /* Set selection_criterion field to default value according to selected strategy. */ int sn_selection_criterion_default (SN_SELECTION_CRITERION_DATA_TYPE *selection_criterion) { *selection_criterion = (SN_SELECTION_CRITERION_DATA_TYPE)(UINT64_MAX >> 1) - 1; return 0; /* OK */ } /* Set selection_criterion field to 'bad' value (worse than default) according to selected strategy. */ int sn_selection_criterion_bad (SN_SELECTION_CRITERION_DATA_TYPE *selection_criterion) { *selection_criterion = (SN_SELECTION_CRITERION_DATA_TYPE)(UINT64_MAX >> 1); return 0; /* OK */ } /* Set selection_criterion field to 'good' value (better than default) according to selected strategy. */ int sn_selection_criterion_good (SN_SELECTION_CRITERION_DATA_TYPE *selection_criterion) { *selection_criterion = (SN_SELECTION_CRITERION_DATA_TYPE)(UINT64_MAX >> 1) - 2; return 0; /* OK */ } /* Take data from PEER_INFO payload and transform them into a selection_criterion. * This function is highly dependant of the chosen selection criterion. */ int sn_selection_criterion_calculate (n2n_edge_t *eee, peer_info_t *peer, SN_SELECTION_CRITERION_DATA_TYPE *data) { SN_SELECTION_CRITERION_DATA_TYPE common_data; int sum = 0; common_data = sn_selection_criterion_common_read(eee); switch(eee->conf.sn_selection_strategy) { case SN_SELECTION_STRATEGY_LOAD: { peer->selection_criterion = (SN_SELECTION_CRITERION_DATA_TYPE)(be32toh(*data) + common_data); /* Mitigation of the real supernode load in order to see less oscillations. * Edges jump from a supernode to another back and forth due to purging. * Because this behavior has a cost of switching, the real load is mitigated with a stickyness factor. * This factor is dynamically calculated basing on network size and prevent that unnecessary switching */ if(peer == eee->curr_sn) { sum = HASH_COUNT(eee->known_peers) + HASH_COUNT(eee->pending_peers); peer->selection_criterion = peer->selection_criterion * sum / (sum + 1); } break; } case SN_SELECTION_STRATEGY_RTT: { peer->selection_criterion = (SN_SELECTION_CRITERION_DATA_TYPE)((uint32_t)time_stamp() >> 22) - common_data; break; } case SN_SELECTION_STRATEGY_MAC: { peer->selection_criterion = 0; memcpy(&peer->selection_criterion, /* leftbound, don't mess with pointer arithmetics */ peer->mac_addr, N2N_MAC_SIZE); peer->selection_criterion = be64toh(peer->selection_criterion); peer->selection_criterion >>= (sizeof(peer->selection_criterion) - N2N_MAC_SIZE) * 8; /* rightbound */ break; } default: { // this should never happen traceEvent(TRACE_ERROR, "selection_criterion unknown selection strategy configuration"); break; } } return 0; /* OK */ } /* Set sn_selection_criterion_common_data field to default value. */ int sn_selection_criterion_common_data_default (n2n_edge_t *eee) { switch(eee->conf.sn_selection_strategy) { case SN_SELECTION_STRATEGY_LOAD: { SN_SELECTION_CRITERION_DATA_TYPE tmp = 0; tmp = HASH_COUNT(eee->pending_peers); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) { tmp *= 2; } eee->sn_selection_criterion_common_data = tmp / HASH_COUNT(eee->conf.supernodes); break; } case SN_SELECTION_STRATEGY_RTT: { eee->sn_selection_criterion_common_data = (SN_SELECTION_CRITERION_DATA_TYPE)((uint32_t)time_stamp() >> 22); break; } case SN_SELECTION_STRATEGY_MAC: { eee->sn_selection_criterion_common_data = 0; break; } default: { // this should never happen traceEvent(TRACE_ERROR, "selection_criterion unknown selection strategy configuration"); break; } } return 0; /* OK */ } /* Return the value of sn_selection_criterion_common_data field. */ static SN_SELECTION_CRITERION_DATA_TYPE sn_selection_criterion_common_read (n2n_edge_t *eee) { return eee->sn_selection_criterion_common_data; } /* Function that compare two selection_criterion fields and sorts them in ascending order. */ static int sn_selection_criterion_sort (peer_info_t *a, peer_info_t *b) { int ret = 0; // comparison function for sorting supernodes in ascending order of their selection_criterion. if(a->selection_criterion > b->selection_criterion) ret = 1; else if(a->selection_criterion < b->selection_criterion) ret = -1; return ret; } /* Function that sorts peer_list using sn_selection_criterion_sort. */ int sn_selection_sort (peer_info_t **peer_list) { HASH_SORT(*peer_list, sn_selection_criterion_sort); return 0; /* OK */ } /* Function that gathers requested data on a supernode. * it remains unaffected by selection strategy because it refers to edge behaviour only */ SN_SELECTION_CRITERION_DATA_TYPE sn_selection_criterion_gather_data (n2n_sn_t *sss) { SN_SELECTION_CRITERION_DATA_TYPE data = 0, tmp = 0; struct sn_community *comm, *tmp_comm; HASH_ITER(hh, sss->communities, comm, tmp_comm) { // number of nodes in the community + the community itself tmp = HASH_COUNT(comm->edges) + 1; if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { // double-count encrypted communities (and their nodes): they exert more load on supernode tmp *= 2; } data += tmp; } return htobe64(data); } /* Convert selection_criterion field in a string for management port output. */ extern char * sn_selection_criterion_str (n2n_edge_t *eee, selection_criterion_str_t out, peer_info_t *peer) { int chars = 0; if(NULL == out) { return NULL; } memset(out, 0, SN_SELECTION_CRITERION_BUF_SIZE); // keep off the super-big values (used for "bad" or "good" or "undetermined" supernodes, // easier to sort to the end of the list). // Alternatively, typecast to (int16_t) and check for greater or equal zero if(peer->selection_criterion < (UINT64_MAX >> 2)) { switch(eee->conf.sn_selection_strategy) { case SN_SELECTION_STRATEGY_LOAD: { chars = snprintf(out, SN_SELECTION_CRITERION_BUF_SIZE, "load = %8ld", peer->selection_criterion); break; } case SN_SELECTION_STRATEGY_RTT: { chars = snprintf(out, SN_SELECTION_CRITERION_BUF_SIZE, "rtt = %6ld ms", peer->selection_criterion); break; } case SN_SELECTION_STRATEGY_MAC: { chars = snprintf(out, SN_SELECTION_CRITERION_BUF_SIZE, "%s", ((int64_t)peer->selection_criterion > 0 ? ((peer == eee->curr_sn) ? "active" : "standby") : "")); break; } default: { // this should never happen traceEvent(TRACE_ERROR, "selection_criterion unknown selection strategy configuration"); break; } } // this test is to make "-Wformat-truncation" less sad if(chars > SN_SELECTION_CRITERION_BUF_SIZE) { traceEvent(TRACE_ERROR, "selection_criterion buffer overflow"); } } return out; } ntop-n2n-90215bd/src/sn_utils.c000066400000000000000000003426371422132035700163260ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn_list); int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, time_t now); int resolve_cancel_thread (n2n_resolve_parameter_t *param); static ssize_t sendto_peer (n2n_sn_t *sss, const struct peer_info *peer, const uint8_t *pktbuf, size_t pktsize); static uint16_t reg_lifetime (n2n_sn_t *sss); static int update_edge (n2n_sn_t *sss, const n2n_common_t* cmn, const n2n_REGISTER_SUPER_t* reg, struct sn_community *comm, const n2n_sock_t *sender_sock, const SOCKET socket_fd, n2n_auth_t *answer_auth, int skip_add, time_t now); static int re_register_and_purge_supernodes (n2n_sn_t *sss, struct sn_community *comm, time_t *p_last_re_reg_and_purge, time_t now, uint8_t forced); static int purge_expired_communities (n2n_sn_t *sss, time_t* p_last_purge, time_t now); static int sort_communities (n2n_sn_t *sss, time_t* p_last_sort, time_t now); int process_mgmt (n2n_sn_t *sss, const struct sockaddr_in *sender_sock, char *mgmt_buf, size_t mgmt_size, time_t now); static int process_udp (n2n_sn_t *sss, const struct sockaddr_in *sender_sock, const SOCKET socket_fd, uint8_t *udp_buf, size_t udp_size, time_t now); /* ************************************** */ void close_tcp_connection (n2n_sn_t *sss, n2n_tcp_connection_t *conn) { struct sn_community *comm, *tmp_comm; struct peer_info *edge, *tmp_edge; if(!conn) return; // find peer by file descriptor HASH_ITER(hh, sss->communities, comm, tmp_comm) { HASH_ITER(hh, comm->edges, edge, tmp_edge) { if(edge->socket_fd == conn->socket_fd) { // remove peer HASH_DEL(comm->edges, edge); free(edge); goto close_conn; /* break - level 2 */ } } } close_conn: // close the connection shutdown(conn->socket_fd, SHUT_RDWR); closesocket(conn->socket_fd); // forget about the connection, will be deleted later conn->inactive = 1; } /* *************************************************** */ // generate shared secrets for user authentication; can be done only after // federation name is known (-F) and community list completely read (-c) void calculate_shared_secrets (n2n_sn_t *sss) { struct sn_community *comm, *tmp_comm; sn_user_t *user, *tmp_user; traceEvent(TRACE_INFO, "started shared secrets calculation for edge authentication"); generate_private_key(sss->private_key, sss->federation->community + 1); /* skip '*' federation leading character */ HASH_ITER(hh, sss->communities, comm, tmp_comm) { if(comm->is_federation) { continue; } HASH_ITER(hh, comm->allowed_users, user, tmp_user) { // calculate common shared secret (ECDH) generate_shared_secret(user->shared_secret, sss->private_key, user->public_key); // prepare for use as key user->shared_secret_ctx = (he_context_t*)calloc(1, sizeof(speck_context_t)); speck_init((speck_context_t**)&user->shared_secret_ctx, user->shared_secret, 128); } } traceEvent(TRACE_NORMAL, "calculated shared secrets for edge authentication"); } // calculate dynamic keys void calculate_dynamic_keys (n2n_sn_t *sss) { struct sn_community *comm, *tmp_comm = NULL; traceEvent(TRACE_INFO, "calculating dynamic keys"); HASH_ITER(hh, sss->communities, comm, tmp_comm) { // skip federation if(comm->is_federation) { continue; } // calculate dynamic keys if this is a user/pw auth'ed community if(comm->allowed_users) { calculate_dynamic_key(comm->dynamic_key, /* destination */ sss->dynamic_key_time, /* time - same for all */ (uint8_t *)comm->community, /* community name */ (uint8_t *)sss->federation->community); /* federation name */ packet_header_change_dynamic_key(comm->dynamic_key, &(comm->header_encryption_ctx_dynamic), &(comm->header_iv_ctx_dynamic)); traceEvent(TRACE_DEBUG, "calculated dynamic key for community '%s'", comm->community); } } } // send RE_REGISTER_SUPER to all edges from user/pw auth'ed communites void send_re_register_super (n2n_sn_t *sss) { struct sn_community *comm, *tmp_comm = NULL; struct peer_info *edge, *tmp_edge = NULL; n2n_common_t cmn; uint8_t rereg_buf[N2N_SN_PKTBUF_SIZE]; size_t encx = 0; n2n_sock_str_t sockbuf; HASH_ITER(hh, sss->communities, comm, tmp_comm) { if(comm->is_federation) { continue; } // send RE_REGISTER_SUPER to edges if this is a user/pw auth community if(comm->allowed_users) { // prepare cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_re_register_super; cmn.flags = N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE); HASH_ITER(hh, comm->edges, edge, tmp_edge) { // encode encx = 0; encode_common(rereg_buf, &encx, &cmn); // send traceEvent(TRACE_DEBUG, "send RE_REGISTER_SUPER to %s", sock_to_cstr(sockbuf, &(edge->sock))); packet_header_encrypt(rereg_buf, encx, encx, comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic, time_stamp()); /* sent = */ sendto_peer(sss, edge, rereg_buf, encx); } } } } /** Load the list of allowed communities. Existing/previous ones will be removed, * return 0 on success, -1 if file not found, -2 if no valid entries found */ int load_allowed_sn_community (n2n_sn_t *sss) { char buffer[4096], *line, *cmn_str, net_str[20], format[20]; sn_user_t *user, *tmp_user; n2n_desc_t username; n2n_private_public_key_t public_key; char ascii_public_key[(N2N_PRIVATE_PUBLIC_KEY_SIZE * 8 + 5) / 6 + 1]; dec_ip_str_t ip_str = {'\0'}; uint8_t bitlen; in_addr_t net; uint32_t mask; FILE *fd = fopen(sss->community_file, "r"); struct sn_community *comm, *tmp_comm, *last_added_comm = NULL; struct peer_info *edge, *tmp_edge; node_supernode_association_t *assoc, *tmp_assoc; n2n_tcp_connection_t *conn; time_t any_time = 0; uint32_t num_communities = 0; struct sn_community_regular_expression *re, *tmp_re; uint32_t num_regex = 0; int has_net; if(fd == NULL) { traceEvent(TRACE_WARNING, "File %s not found", sss->community_file); return -1; } // reset data structures ------------------------------ // send RE_REGISTER_SUPER to all edges from user/pw auth communites, this is safe because // follow-up REGISTER_SUPER cannot be handled before this function ends send_re_register_super(sss); // remove communities (not: federation) HASH_ITER(hh, sss->communities, comm, tmp_comm) { if(comm->is_federation) { continue; } // remove all edges from community HASH_ITER(hh, comm->edges, edge, tmp_edge) { // remove all edge associations (with other supernodes) HASH_ITER(hh, comm->assoc, assoc, tmp_assoc) { HASH_DEL(comm->assoc, assoc); free(assoc); } // close TCP connections, if any (also causes reconnect) // and delete edge from list if((edge->socket_fd != sss->sock) && (edge->socket_fd >= 0)) { HASH_FIND_INT(sss->tcp_connections, &(edge->socket_fd), conn); close_tcp_connection(sss, conn); /* also deletes the edge */ } else { HASH_DEL(comm->edges, edge); free(edge); } } // remove allowed users from community HASH_ITER(hh, comm->allowed_users, user, tmp_user) { free(user->shared_secret_ctx); HASH_DEL(comm->allowed_users, user); free(user); } // remove community HASH_DEL(sss->communities, comm); if(NULL != comm->header_encryption_ctx_static) { // remove header encryption keys free(comm->header_encryption_ctx_static); free(comm->header_iv_ctx_static); free(comm->header_encryption_ctx_dynamic); free(comm->header_iv_ctx_dynamic); } free(comm); } // remove all regular expressions for allowed communities HASH_ITER(hh, sss->rules, re, tmp_re) { HASH_DEL(sss->rules, re); free(re); } // prepare reading data ------------------------------- // new key_time for all communities, requires dynamic keys to be recalculated (see further below), // and edges to re-register (see above) and ... sss->dynamic_key_time = time(NULL); // ... federated supernodes to re-register re_register_and_purge_supernodes(sss, sss->federation, &any_time, any_time, 1 /* forced */); // format definition for possible user-key entries sprintf(format, "%c %%%ds %%%lds", N2N_USER_KEY_LINE_STARTER, N2N_DESC_SIZE - 1, sizeof(ascii_public_key)-1); while((line = fgets(buffer, sizeof(buffer), fd)) != NULL) { int len = strlen(line); if((len < 2) || line[0] == '#') { continue; } len--; while(len > 0) { if((line[len] == '\n') || (line[len] == '\r')) { line[len] = '\0'; len--; } else { break; } } // the loop above does not always determine correct 'len' len = strlen(line); // user-key line for edge authentication? if(line[0] == N2N_USER_KEY_LINE_STARTER) { /* special first character */ if(sscanf(line, format, username, ascii_public_key) == 2) { /* correct format */ if(last_added_comm) { /* is there a valid community to add users to */ user = (sn_user_t*)calloc(1, sizeof(sn_user_t)); if(user) { // username memcpy(user->name, username, sizeof(username)); // public key ascii_to_bin(public_key, ascii_public_key); memcpy(user->public_key, public_key, sizeof(public_key)); // common shared secret will be calculated later // add to list HASH_ADD(hh, last_added_comm->allowed_users, public_key, sizeof(n2n_private_public_key_t), user); traceEvent(TRACE_INFO, "added user '%s' with public key '%s' to community '%s'", user->name, ascii_public_key, last_added_comm->community); // enable header encryption last_added_comm->header_encryption = HEADER_ENCRYPTION_ENABLED; packet_header_setup_key(last_added_comm->community, &(last_added_comm->header_encryption_ctx_static), &(last_added_comm->header_encryption_ctx_dynamic), &(last_added_comm->header_iv_ctx_static), &(last_added_comm->header_iv_ctx_dynamic)); // dynamic key setup follows at a later point in code } continue; } } } // --- community name or regular expression // cut off any IP sub-network upfront cmn_str = (char*)calloc(len + 1, sizeof(char)); has_net = (sscanf(line, "%s %s", cmn_str, net_str) == 2); // if it contains typical characters... if(NULL != strpbrk(cmn_str, ".*+?[]\\")) { // ...it is treated as regular expression re = (struct sn_community_regular_expression*)calloc(1, sizeof(struct sn_community_regular_expression)); if(re) { re->rule = re_compile(cmn_str); HASH_ADD_PTR(sss->rules, rule, re); num_regex++; traceEvent(TRACE_INFO, "added regular expression for allowed communities '%s'", cmn_str); free(cmn_str); last_added_comm = NULL; continue; } } comm = (struct sn_community*)calloc(1,sizeof(struct sn_community)); if(comm != NULL) { comm_init(comm, cmn_str); /* loaded from file, this community is unpurgeable */ comm->purgeable = COMMUNITY_UNPURGEABLE; /* we do not know if header encryption is used in this community, * first packet will show. just in case, setup the key. */ comm->header_encryption = HEADER_ENCRYPTION_UNKNOWN; packet_header_setup_key(comm->community, &(comm->header_encryption_ctx_static), &(comm->header_encryption_ctx_dynamic), &(comm->header_iv_ctx_static), &(comm->header_iv_ctx_dynamic)); HASH_ADD_STR(sss->communities, community, comm); last_added_comm = comm; num_communities++; traceEvent(TRACE_INFO, "added allowed community '%s' [total: %u]", (char*)comm->community, num_communities); // check for sub-network address if(has_net) { if(sscanf(net_str, "%15[^/]/%hhu", ip_str, &bitlen) != 2) { traceEvent(TRACE_WARNING, "bad net/bit format '%s' for community '%c', ignoring; see comments inside community.list file", net_str, cmn_str); has_net = 0; } net = inet_addr(ip_str); mask = bitlen2mask(bitlen); if((net == (in_addr_t)(-1)) || (net == INADDR_NONE) || (net == INADDR_ANY) || ((ntohl(net) & ~mask) != 0)) { traceEvent(TRACE_WARNING, "bad network '%s/%u' in '%s' for community '%s', ignoring", ip_str, bitlen, net_str, cmn_str); has_net = 0; } if((bitlen > 30) || (bitlen == 0)) { traceEvent(TRACE_WARNING, "bad prefix '%hhu' in '%s' for community '%s', ignoring", bitlen, net_str, cmn_str); has_net = 0; } } if(has_net) { comm->auto_ip_net.net_addr = ntohl(net); comm->auto_ip_net.net_bitlen = bitlen; traceEvent(TRACE_INFO, "assigned sub-network %s/%u to community '%s'", inet_ntoa(*(struct in_addr *) &net), comm->auto_ip_net.net_bitlen, comm->community); } else { assign_one_ip_subnet(sss, comm); } } free(cmn_str); } fclose(fd); if((num_regex + num_communities) == 0) { traceEvent(TRACE_WARNING, "file %s does not contain any valid community names or regular expressions", sss->community_file); return -2; } traceEvent(TRACE_NORMAL, "loaded %u fixed-name communities from %s", num_communities, sss->community_file); traceEvent(TRACE_NORMAL, "loaded %u regular expressions for community name matching from %s", num_regex, sss->community_file); // calculate allowed user's shared secrets (shared with federation) calculate_shared_secrets(sss); // calculcate communties' dynamic keys calculate_dynamic_keys(sss); // no new communities will be allowed sss->lock_communities = 1; return 0; } /* *************************************************** */ /** Send a datagram to a file descriptor socket. * * @return -1 on error otherwise number of bytes sent */ static ssize_t sendto_fd (n2n_sn_t *sss, SOCKET socket_fd, const struct sockaddr *socket, const uint8_t *pktbuf, size_t pktsize) { ssize_t sent = 0; n2n_tcp_connection_t *conn; sent = sendto(socket_fd, (void *)pktbuf, pktsize, 0 /* flags */, socket, sizeof(struct sockaddr_in)); if((sent <= 0) && (errno)) { char * c = strerror(errno); traceEvent(TRACE_ERROR, "sendto failed (%d) %s", errno, c); #ifdef WIN32 traceEvent(TRACE_ERROR, "WSAGetLastError(): %u", WSAGetLastError()); #endif // if the erroneous connection is tcp, i.e. not the regular sock... if((socket_fd >= 0) && (socket_fd != sss->sock)) { // ...forget about the corresponding peer and the connection HASH_FIND_INT(sss->tcp_connections, &socket_fd, conn); close_tcp_connection(sss, conn); return -1; } } else { traceEvent(TRACE_DEBUG, "sendto sent=%d to ", (signed int)sent); } return sent; } /** Send a datagram to a network order socket of type struct sockaddr. * * @return -1 on error otherwise number of bytes sent */ static ssize_t sendto_sock(n2n_sn_t *sss, SOCKET socket_fd, const struct sockaddr *socket, const uint8_t *pktbuf, size_t pktsize) { ssize_t sent = 0; int value = 0; // if the connection is tcp, i.e. not the regular sock... if((socket_fd >= 0) && (socket_fd != sss->sock)) { setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value)); value = 1; #ifdef LINUX setsockopt(socket_fd, IPPROTO_TCP, TCP_CORK, &value, sizeof(value)); #endif // prepend packet length... uint16_t pktsize16 = htobe16(pktsize); sent = sendto_fd(sss, socket_fd, socket, (uint8_t*)&pktsize16, sizeof(pktsize16)); if(sent <= 0) return -1; // ...before sending the actual data } sent = sendto_fd(sss, socket_fd, socket, pktbuf, pktsize); // if the connection is tcp, i.e. not the regular sock... if((socket_fd >= 0) && (socket_fd != sss->sock)) { value = 1; /* value should still be set to 1 */ setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value)); #ifdef LINUX value = 0; setsockopt(socket_fd, IPPROTO_TCP, TCP_CORK, &value, sizeof(value)); #endif } return sent; } /** Send a datagram to a peer whose destination socket is embodied in its sock field of type n2n_sock_t. * It calls sendto_sock to do the final send. * * @return -1 on error otherwise number of bytes sent */ static ssize_t sendto_peer (n2n_sn_t *sss, const struct peer_info *peer, const uint8_t *pktbuf, size_t pktsize) { n2n_sock_str_t sockbuf; if(AF_INET == peer->sock.family) { // network order socket struct sockaddr_in socket; fill_sockaddr((struct sockaddr *)&socket, sizeof(socket), &(peer->sock)); traceEvent(TRACE_DEBUG, "sent %lu bytes to [%s]", pktsize, sock_to_cstr(sockbuf, &(peer->sock))); return sendto_sock(sss, (peer->socket_fd >= 0) ? peer->socket_fd : sss->sock, (const struct sockaddr*)&socket, pktbuf, pktsize); } else { /* AF_INET6 not implemented */ errno = EAFNOSUPPORT; return -1; } } /** Try and broadcast a message to all edges in the community. * * This will send the exact same datagram to zero or more edges registered to * the supernode. */ static int try_broadcast (n2n_sn_t * sss, const struct sn_community *comm, const n2n_common_t * cmn, const n2n_mac_t srcMac, uint8_t from_supernode, const uint8_t * pktbuf, size_t pktsize, time_t now) { struct peer_info *scan, *tmp; macstr_t mac_buf; n2n_sock_str_t sockbuf; traceEvent(TRACE_DEBUG, "try_broadcast"); /* We have to make sure that a broadcast reaches the other supernodes and edges * connected to them. try_broadcast needs a from_supernode parameter: if set, * do forward to edges of community only. If unset, forward to all locally known * nodes of community AND all supernodes associated with the community */ if (!from_supernode) { HASH_ITER(hh, sss->federation->edges, scan, tmp) { int data_sent_len; // only forward to active supernodes if(scan->last_seen + LAST_SEEN_SN_INACTIVE > now) { data_sent_len = sendto_peer(sss, scan, pktbuf, pktsize); if(data_sent_len != pktsize) { ++(sss->stats.errors); traceEvent(TRACE_WARNING, "multicast %lu to supernode [%s] %s failed %s", pktsize, sock_to_cstr(sockbuf, &(scan->sock)), macaddr_str(mac_buf, scan->mac_addr), strerror(errno)); } else { ++(sss->stats.broadcast); traceEvent(TRACE_DEBUG, "multicast %lu to supernode [%s] %s", pktsize, sock_to_cstr(sockbuf, &(scan->sock)), macaddr_str(mac_buf, scan->mac_addr)); } } } } if(comm) { HASH_ITER(hh, comm->edges, scan, tmp) { if(memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)) != 0) { /* REVISIT: exclude if the destination socket is where the packet came from. */ int data_sent_len; data_sent_len = sendto_peer(sss, scan, pktbuf, pktsize); if(data_sent_len != pktsize) { ++(sss->stats.errors); traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", pktsize, sock_to_cstr(sockbuf, &(scan->sock)), macaddr_str(mac_buf, scan->mac_addr), strerror(errno)); } else { ++(sss->stats.broadcast); traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", pktsize, sock_to_cstr(sockbuf, &(scan->sock)), macaddr_str(mac_buf, scan->mac_addr)); } } } } return 0; } static int try_forward (n2n_sn_t * sss, const struct sn_community *comm, const n2n_common_t * cmn, const n2n_mac_t dstMac, uint8_t from_supernode, const uint8_t * pktbuf, size_t pktsize, time_t now) { struct peer_info * scan; node_supernode_association_t *assoc; macstr_t mac_buf; n2n_sock_str_t sockbuf; HASH_FIND_PEER(comm->edges, dstMac, scan); if(NULL != scan) { int data_sent_len; data_sent_len = sendto_peer(sss, scan, pktbuf, pktsize); if(data_sent_len == pktsize) { ++(sss->stats.fwd); traceEvent(TRACE_DEBUG, "unicast %lu to [%s] %s", pktsize, sock_to_cstr(sockbuf, &(scan->sock)), macaddr_str(mac_buf, scan->mac_addr)); } else { ++(sss->stats.errors); traceEvent(TRACE_ERROR, "unicast %lu to [%s] %s FAILED (%d: %s)", pktsize, sock_to_cstr(sockbuf, &(scan->sock)), macaddr_str(mac_buf, scan->mac_addr), errno, strerror(errno)); return -1; } } else { if(!from_supernode) { // check if target edge is associated with a certain supernode HASH_FIND(hh, comm->assoc, dstMac, sizeof(n2n_mac_t), assoc); if(assoc) { traceEvent(TRACE_DEBUG, "found mac address associated with a known supernode, forwarding packet to that supernode"); sendto_sock(sss, sss->sock, (const struct sockaddr*)&(assoc->sock), pktbuf, pktsize); } else { // forwarding packet to all federated supernodes traceEvent(TRACE_DEBUG, "unknown mac address, broadcasting packet to all federated supernodes"); try_broadcast(sss, NULL, cmn, sss->mac_addr, from_supernode, pktbuf, pktsize, now); } } else { traceEvent(TRACE_DEBUG, "unknown mac address in packet from a supernode, dropping the packet"); /* Not a known MAC so drop. */ return -2; } } return 0; } /** Initialise some fields of the community structure **/ int comm_init (struct sn_community *comm, char *cmn) { strncpy((char*)comm->community, cmn, N2N_COMMUNITY_SIZE); comm->community[N2N_COMMUNITY_SIZE - 1] = '\0'; comm->is_federation = IS_NO_FEDERATION; return 0; /* OK */ } /** Initialise the supernode structure */ int sn_init_defaults (n2n_sn_t *sss) { char *tmp_string; #ifdef WIN32 initWin32(); #endif pearson_hash_init(); memset(sss, 0, sizeof(n2n_sn_t)); strncpy(sss->version, PACKAGE_VERSION, sizeof(n2n_version_t)); sss->version[sizeof(n2n_version_t) - 1] = '\0'; sss->daemon = 1; /* By defult run as a daemon. */ sss->lport = N2N_SN_LPORT_DEFAULT; sss->mport = N2N_SN_MGMT_PORT; sss->sock = -1; sss->mgmt_sock = -1; sss->min_auto_ip_net.net_addr = inet_addr(N2N_SN_MIN_AUTO_IP_NET_DEFAULT); sss->min_auto_ip_net.net_addr = ntohl(sss->min_auto_ip_net.net_addr); sss->min_auto_ip_net.net_bitlen = N2N_SN_AUTO_IP_NET_BIT_DEFAULT; sss->max_auto_ip_net.net_addr = inet_addr(N2N_SN_MAX_AUTO_IP_NET_DEFAULT); sss->max_auto_ip_net.net_addr = ntohl(sss->max_auto_ip_net.net_addr); sss->max_auto_ip_net.net_bitlen = N2N_SN_AUTO_IP_NET_BIT_DEFAULT; sss->federation = (struct sn_community *)calloc(1, sizeof(struct sn_community)); /* Initialize the federation */ if(sss->federation) { if(getenv("N2N_FEDERATION")) snprintf(sss->federation->community, N2N_COMMUNITY_SIZE - 1 ,"*%s", getenv("N2N_FEDERATION")); else strncpy(sss->federation->community, (char*)FEDERATION_NAME, N2N_COMMUNITY_SIZE); sss->federation->community[N2N_COMMUNITY_SIZE - 1] = '\0'; /* enable the flag for federation */ sss->federation->is_federation = IS_FEDERATION; sss->federation->purgeable = COMMUNITY_UNPURGEABLE; /* header encryption enabled by default */ sss->federation->header_encryption = HEADER_ENCRYPTION_ENABLED; /*setup the encryption key */ packet_header_setup_key(sss->federation->community, &(sss->federation->header_encryption_ctx_static), &(sss->federation->header_encryption_ctx_dynamic), &(sss->federation->header_iv_ctx_static), &(sss->federation->header_iv_ctx_dynamic)); sss->federation->edges = NULL; } n2n_srand(n2n_seed()); /* Random auth token */ sss->auth.scheme = n2n_auth_simple_id; memrnd(sss->auth.token, N2N_AUTH_ID_TOKEN_SIZE); sss->auth.token_size = N2N_AUTH_ID_TOKEN_SIZE; /* Random MAC address */ memrnd(sss->mac_addr, N2N_MAC_SIZE); sss->mac_addr[0] &= ~0x01; /* Clear multicast bit */ sss->mac_addr[0] |= 0x02; /* Set locally-assigned bit */ tmp_string = calloc(1, strlen(N2N_MGMT_PASSWORD) + 1); if(tmp_string) { strncpy((char*)tmp_string, N2N_MGMT_PASSWORD, strlen(N2N_MGMT_PASSWORD) + 1); sss->mgmt_password_hash = pearson_hash_64((uint8_t*)tmp_string, strlen(N2N_MGMT_PASSWORD)); free(tmp_string); } return 0; /* OK */ } /** Initialise the supernode */ void sn_init (n2n_sn_t *sss) { if(resolve_create_thread(&(sss->resolve_parameter), sss->federation->edges) == 0) { traceEvent(TRACE_NORMAL, "successfully created resolver thread"); } } /** Deinitialise the supernode structure and deallocate any memory owned by * it. */ void sn_term (n2n_sn_t *sss) { struct sn_community *community, *tmp; struct sn_community_regular_expression *re, *tmp_re; n2n_tcp_connection_t *conn, *tmp_conn; node_supernode_association_t *assoc, *tmp_assoc; resolve_cancel_thread(sss->resolve_parameter); if(sss->sock >= 0) { closesocket(sss->sock); } sss->sock = -1; HASH_ITER(hh, sss->tcp_connections, conn, tmp_conn) { shutdown(conn->socket_fd, SHUT_RDWR); closesocket(conn->socket_fd); HASH_DEL(sss->tcp_connections, conn); free(conn); } if(sss->tcp_sock >= 0) { shutdown(sss->tcp_sock, SHUT_RDWR); closesocket(sss->tcp_sock); } sss->tcp_sock = -1; if(sss->mgmt_sock >= 0) { closesocket(sss->mgmt_sock); } sss->mgmt_sock = -1; HASH_ITER(hh, sss->communities, community, tmp) { clear_peer_list(&community->edges); if(NULL != community->header_encryption_ctx_static) { free(community->header_encryption_ctx_static); free(community->header_encryption_ctx_dynamic); } // remove all associations HASH_ITER(hh, community->assoc, assoc, tmp_assoc) { HASH_DEL(community->assoc, assoc); free(assoc); } HASH_DEL(sss->communities, community); free(community); } HASH_ITER(hh, sss->rules, re, tmp_re) { HASH_DEL(sss->rules, re); if (NULL != re->rule) { free(re->rule); } free(re); } if(sss->community_file) free(sss->community_file); #ifdef WIN32 destroyWin32(); #endif } void update_node_supernode_association (struct sn_community *comm, n2n_mac_t *edgeMac, const struct sockaddr_in *sender_sock, time_t now) { node_supernode_association_t *assoc; HASH_FIND(hh, comm->assoc, edgeMac, sizeof(n2n_mac_t), assoc); if(!assoc) { // create a new association assoc = (node_supernode_association_t*)malloc(sizeof(node_supernode_association_t)); if(assoc) { memcpy(&(assoc->mac), edgeMac, sizeof(n2n_mac_t)); memcpy((struct sockaddr_in*)&(assoc->sock), sender_sock, sizeof(struct sockaddr_in)); assoc->last_seen = now; HASH_ADD(hh, comm->assoc, mac, sizeof(n2n_mac_t), assoc); } else { // already there, update socket and time only memcpy((struct sockaddr_in*)&(assoc->sock), sender_sock, sizeof(struct sockaddr_in)); assoc->last_seen = now; } } } /** Determine the appropriate lifetime for new registrations. * * If the supernode has been put into a pre-shutdown phase then this lifetime * should not allow registrations to continue beyond the shutdown point. */ static uint16_t reg_lifetime (n2n_sn_t *sss) { /* NOTE: UDP firewalls usually have a 30 seconds timeout */ return 15; } /** Verifies authentication tokens from known edges. * * It is called by update_edge and during UNREGISTER_SUPER handling * to verify the stored auth token. */ static int auth_edge (const n2n_auth_t *present, const n2n_auth_t *presented, n2n_auth_t *answer, struct sn_community *community) { sn_user_t *user = NULL; if(present->scheme == n2n_auth_none) { // n2n_auth_none scheme (set at supernode if cli option '-M') // if required, zero_token answer (not for NAK) if(answer) memset(answer, 0, sizeof(n2n_auth_t)); // 0 == (always) successful return 0; } if((present->scheme == n2n_auth_simple_id) && (presented->scheme == n2n_auth_simple_id)) { // n2n_auth_simple_id scheme: if required, zero_token answer (not for NAK) if(answer) memset(answer, 0, sizeof(n2n_auth_t)); // 0 = success (tokens are equal) return (memcmp(present, presented, sizeof(n2n_auth_t))); } if((present->scheme == n2n_auth_user_password) && (presented->scheme == n2n_auth_user_password)) { // check if submitted public key is in list of allowed users HASH_FIND(hh, community->allowed_users, &presented->token, sizeof(n2n_private_public_key_t), user); if(user) { if(answer) { memcpy(answer, presented, sizeof(n2n_auth_t)); // return a double-encrypted challenge (just encrypt again) in the (first half of) public key field so edge can verify memcpy(answer->token, answer->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, N2N_AUTH_CHALLENGE_SIZE); speck_128_encrypt(answer->token, (speck_context_t*)user->shared_secret_ctx); // decrypt the challenge using user's shared secret speck_128_decrypt(answer->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, (speck_context_t*)user->shared_secret_ctx); // xor-in the community dynamic key memxor(answer->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, community->dynamic_key, N2N_AUTH_CHALLENGE_SIZE); // xor-in the user's shared secret memxor(answer->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, user->shared_secret, N2N_AUTH_CHALLENGE_SIZE); // encrypt it using user's shared secret speck_128_encrypt(answer->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, (speck_context_t*)user->shared_secret_ctx); // user in list? success! (we will see if edge can handle the key for further com) } return 0; } } // if not successful earlier: failure return -1; } // provides the current / a new local auth token // REVISIT: behavior should depend on some local auth scheme setting (to be implemented) static int get_local_auth (n2n_sn_t *sss, n2n_auth_t *auth) { // n2n_auth_simple_id scheme memcpy(auth, &(sss->auth), sizeof(n2n_auth_t)); return 0; } // handles an incoming (remote) auth token from a so far unknown edge, // takes action as required by auth scheme, and // could provide an answer auth token for use in REGISTER_SUPER_ACK static int handle_remote_auth (n2n_sn_t *sss, const n2n_auth_t *remote_auth, n2n_auth_t *answer_auth, struct sn_community *community) { sn_user_t *user = NULL; if((NULL == community->allowed_users) != (remote_auth->scheme != n2n_auth_user_password)) { // received token's scheme does not match expected scheme return -1; } switch(remote_auth->scheme) { // we do not handle n2n_auth_none because the edge always edge always uses either id or user/password // auth_none is sn-internal only (skipping MAC/IP address spoofing protection) case n2n_auth_none: case n2n_auth_simple_id: // zero_token answer memset(answer_auth, 0, sizeof(n2n_auth_t)); return 0; case n2n_auth_user_password: // check if submitted public key is in list of allowed users HASH_FIND(hh, community->allowed_users, &remote_auth->token, sizeof(n2n_private_public_key_t), user); if(user) { memcpy(answer_auth, remote_auth, sizeof(n2n_auth_t)); // return a double-encrypted challenge (just encrypt again) in the (first half of) public key field so edge can verify memcpy(answer_auth->token, answer_auth->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, N2N_AUTH_CHALLENGE_SIZE); speck_128_encrypt(answer_auth->token, (speck_context_t*)user->shared_secret_ctx); // wrap dynamic key for transmission // decrypt the challenge using user's shared secret speck_128_decrypt(answer_auth->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, (speck_context_t*)user->shared_secret_ctx); // xor-in the community dynamic key memxor(answer_auth->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, community->dynamic_key, N2N_AUTH_CHALLENGE_SIZE); // xor-in the user's shared secret memxor(answer_auth->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, user->shared_secret, N2N_AUTH_CHALLENGE_SIZE); // encrypt it using user's shared secret speck_128_encrypt(answer_auth->token + N2N_PRIVATE_PUBLIC_KEY_SIZE, (speck_context_t*)user->shared_secret_ctx); return 0; } break; default: break; } // if not successful earlier: failure return -1; } /** Update the edge table with the details of the edge which contacted the * supernode. */ static int update_edge (n2n_sn_t *sss, const n2n_common_t* cmn, const n2n_REGISTER_SUPER_t* reg, struct sn_community *comm, const n2n_sock_t *sender_sock, const SOCKET socket_fd, n2n_auth_t *answer_auth, int skip_add, time_t now) { macstr_t mac_buf; n2n_sock_str_t sockbuf; struct peer_info *scan, *iter, *tmp; int ret; traceEvent(TRACE_DEBUG, "update_edge for %s [%s]", macaddr_str(mac_buf, reg->edgeMac), sock_to_cstr(sockbuf, sender_sock)); HASH_FIND_PEER(comm->edges, reg->edgeMac, scan); // if unknown, make sure it is also not known by IP address if(NULL == scan) { HASH_ITER(hh,comm->edges,iter,tmp) { if(iter->dev_addr.net_addr == reg->dev_addr.net_addr) { scan = iter; HASH_DEL(comm->edges, scan); memcpy(scan->mac_addr, reg->edgeMac, sizeof(n2n_mac_t)); HASH_ADD_PEER(comm->edges, scan); break; } } } if(NULL == scan) { /* Not known */ if(handle_remote_auth(sss, &(reg->auth), answer_auth, comm) == 0) { if(skip_add == SN_ADD) { scan = (struct peer_info *) calloc(1, sizeof(struct peer_info)); /* deallocated in purge_expired_nodes */ memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t)); scan->dev_addr.net_addr = reg->dev_addr.net_addr; scan->dev_addr.net_bitlen = reg->dev_addr.net_bitlen; memcpy((char*)scan->dev_desc, reg->dev_desc, N2N_DESC_SIZE); memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); scan->socket_fd = socket_fd; scan->last_cookie = reg->cookie; scan->last_valid_time_stamp = initial_time_stamp(); // eventually, store edge's preferred local socket from REGISTER_SUPER if(cmn->flags & N2N_FLAGS_SOCKET) memcpy(&scan->preferred_sock, ®->sock, sizeof(n2n_sock_t)); else scan->preferred_sock.family = AF_INVALID; // store the submitted auth token memcpy(&(scan->auth), &(reg->auth), sizeof(n2n_auth_t)); // manually set to type 'auth_none' if cli option disables MAC/IP address spoofing protection // for id based auth communities. This will be obsolete when handling public keys only (v4.0?) if((reg->auth.scheme == n2n_auth_simple_id) && (sss->override_spoofing_protection)) scan->auth.scheme = n2n_auth_none; HASH_ADD_PEER(comm->edges, scan); traceEvent(TRACE_INFO, "created edge %s ==> %s", macaddr_str(mac_buf, reg->edgeMac), sock_to_cstr(sockbuf, sender_sock)); } ret = update_edge_new_sn; } else { traceEvent(TRACE_INFO, "authentication failed"); ret = update_edge_auth_fail; } } else { /* Known */ if(auth_edge(&(scan->auth), &(reg->auth), answer_auth, comm) == 0) { if(!sock_equal(sender_sock, &(scan->sock))) { memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); scan->socket_fd = socket_fd; scan->last_cookie = reg->cookie; // eventually, update edge's preferred local socket from REGISTER_SUPER if(cmn->flags & N2N_FLAGS_SOCKET) memcpy(&scan->preferred_sock, ®->sock, sizeof(n2n_sock_t)); else scan->preferred_sock.family = AF_INVALID; traceEvent(TRACE_INFO, "updated edge %s ==> %s", macaddr_str(mac_buf, reg->edgeMac), sock_to_cstr(sockbuf, sender_sock)); ret = update_edge_sock_change; } else { scan->last_cookie = reg->cookie; traceEvent(TRACE_DEBUG, "edge unchanged %s ==> %s", macaddr_str(mac_buf, reg->edgeMac), sock_to_cstr(sockbuf, sender_sock)); ret = update_edge_no_change; } } else { traceEvent(TRACE_INFO, "authentication failed"); ret = update_edge_auth_fail; } } if((scan != NULL) && (ret != update_edge_auth_fail)) { scan->last_seen = now; } return ret; } /** checks if a certain ip address is still available, i.e. not used by any other edge of a given community */ static int ip_addr_available (struct sn_community *comm, n2n_ip_subnet_t *ip_addr) { int success = 1; struct peer_info *peer, *tmp_peer; // prerequisite: list of peers is sorted according to peer's tap ip address HASH_ITER(hh, comm->edges, peer, tmp_peer) { if(peer->dev_addr.net_addr > ip_addr->net_addr) { break; } if(peer->dev_addr.net_addr == ip_addr->net_addr) { success = 0; break; } } return success; } static signed int peer_tap_ip_sort (struct peer_info *a, struct peer_info *b) { uint32_t a_host_id = a->dev_addr.net_addr & (~bitlen2mask(a->dev_addr.net_bitlen)); uint32_t b_host_id = b->dev_addr.net_addr & (~bitlen2mask(b->dev_addr.net_bitlen)); return ((signed int)a_host_id - (signed int)b_host_id); } /** The IP address assigned to the edge by the auto ip address function of sn. */ static int assign_one_ip_addr (struct sn_community *comm, n2n_desc_t dev_desc, n2n_ip_subnet_t *ip_addr) { uint32_t tmp, success, net_id, mask, max_host, host_id = 1; dec_ip_bit_str_t ip_bit_str = {'\0'}; mask = bitlen2mask(comm->auto_ip_net.net_bitlen); net_id = comm->auto_ip_net.net_addr & mask; max_host = ~mask; // sorting is a prerequisite for more efficient availabilitiy check HASH_SORT(comm->edges, peer_tap_ip_sort); // first proposal derived from hash of mac address tmp = pearson_hash_32(dev_desc, sizeof(n2n_desc_t)) & max_host; if(tmp == 0) tmp++; /* avoid 0 host */ if(tmp == max_host) tmp--; /* avoid broadcast address */ tmp |= net_id; // candidate ip_addr->net_bitlen = comm->auto_ip_net.net_bitlen; // check for availability starting from proposal, then downwards, ... for(host_id = tmp; host_id > net_id; host_id--) { ip_addr->net_addr = host_id; success = ip_addr_available(comm, ip_addr); if(success) { break; } } // ... then upwards if(!success) { for(host_id = tmp + 1; host_id < (net_id + max_host); host_id++) { ip_addr->net_addr = host_id; success = ip_addr_available(comm, ip_addr); if(success) { break; } } } if(success) { traceEvent(TRACE_INFO, "assign IP %s to tap adapter of edge", ip_subnet_to_str(ip_bit_str, ip_addr)); return 0; } else { traceEvent(TRACE_WARNING, "no assignable IP to edge tap adapter"); return -1; } } /** checks if a certain sub-network is still available, i.e. does not cut any other community's sub-network */ int subnet_available (n2n_sn_t *sss, struct sn_community *comm, uint32_t net_id, uint32_t mask) { struct sn_community *cmn, *tmpCmn; int success = 1; HASH_ITER(hh, sss->communities, cmn, tmpCmn) { if(cmn == comm) { continue; } if(cmn->is_federation == IS_FEDERATION) { continue; } if((net_id <= (cmn->auto_ip_net.net_addr + ~bitlen2mask(cmn->auto_ip_net.net_bitlen))) &&(net_id + ~mask >= cmn->auto_ip_net.net_addr)) { success = 0; break; } } return success; } /** The IP address range (subnet) assigned to the community by the auto ip address function of sn. */ int assign_one_ip_subnet (n2n_sn_t *sss, struct sn_community *comm) { uint32_t net_id, net_id_i, mask, net_increment; uint32_t no_subnets; uint8_t success; in_addr_t net; mask = bitlen2mask(sss->min_auto_ip_net.net_bitlen); // number of possible sub-networks no_subnets = (sss->max_auto_ip_net.net_addr - sss->min_auto_ip_net.net_addr); no_subnets >>= (32 - sss->min_auto_ip_net.net_bitlen); no_subnets += 1; // proposal for sub-network to choose net_id = pearson_hash_32((const uint8_t *)comm->community, N2N_COMMUNITY_SIZE) % no_subnets; net_id = sss->min_auto_ip_net.net_addr + (net_id << (32 - sss->min_auto_ip_net.net_bitlen)); // check for availability starting from net_id, then downwards, ... net_increment = (~mask+1); for(net_id_i = net_id; net_id_i >= sss->min_auto_ip_net.net_addr; net_id_i -= net_increment) { success = subnet_available(sss, comm, net_id_i, mask); if(success) { break; } } // ... then upwards if(!success) { for(net_id_i = net_id + net_increment; net_id_i <= sss->max_auto_ip_net.net_addr; net_id_i += net_increment) { success = subnet_available(sss, comm, net_id_i, mask); if(success) { break; } } } if(success) { comm->auto_ip_net.net_addr = net_id_i; comm->auto_ip_net.net_bitlen = sss->min_auto_ip_net.net_bitlen; net = htonl(comm->auto_ip_net.net_addr); traceEvent(TRACE_INFO, "assigned sub-network %s/%u to community '%s'", inet_ntoa(*(struct in_addr *) &net), comm->auto_ip_net.net_bitlen, comm->community); return 0; } else { comm->auto_ip_net.net_addr = 0; comm->auto_ip_net.net_bitlen = 0; traceEvent(TRACE_WARNING, "no assignable sub-network left for community '%s'", comm->community); return -1; } } /*** * * For a given packet, find the apporopriate internal last valid time stamp for lookup * and verify it (and also update, if applicable). */ static int find_edge_time_stamp_and_verify (struct peer_info * edges, peer_info_t *sn, n2n_mac_t mac, uint64_t stamp, int allow_jitter) { uint64_t *previous_stamp = NULL; if(sn) { previous_stamp = &(sn->last_valid_time_stamp); } else { struct peer_info *edge; HASH_FIND_PEER(edges, mac, edge); if(edge) { // time_stamp_verify_and_update allows the pointer a previous stamp to be NULL // if it is a (so far) unknown edge previous_stamp = &(edge->last_valid_time_stamp); } } // failure --> 0; success --> 1 return time_stamp_verify_and_update(stamp, previous_stamp, allow_jitter); } static int re_register_and_purge_supernodes (n2n_sn_t *sss, struct sn_community *comm, time_t *p_last_re_reg_and_purge, time_t now, uint8_t forced) { time_t time; struct peer_info *peer, *tmp; if(!forced) { if((now - (*p_last_re_reg_and_purge)) < RE_REG_AND_PURGE_FREQUENCY) { return 0; } // purge long-time-not-seen supernodes purge_expired_nodes(&(comm->edges), sss->sock, &sss->tcp_connections, p_last_re_reg_and_purge, RE_REG_AND_PURGE_FREQUENCY, LAST_SEEN_SN_INACTIVE); } if(comm != NULL) { HASH_ITER(hh,comm->edges,peer,tmp) { time = now - peer->last_seen; if(!forced) { if(time <= LAST_SEEN_SN_ACTIVE) { continue; } } /* re-register (send REGISTER_SUPER) */ uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; size_t idx; /* ssize_t sent; */ n2n_common_t cmn; n2n_REGISTER_SUPER_t reg; n2n_sock_str_t sockbuf; memset(&cmn, 0, sizeof(cmn)); memset(®, 0, sizeof(reg)); cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_register_super; cmn.flags = N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE); reg.cookie = n2n_rand(); peer->last_cookie = reg.cookie; reg.dev_addr.net_addr = ntohl(peer->dev_addr.net_addr); reg.dev_addr.net_bitlen = mask2bitlen(ntohl(peer->dev_addr.net_bitlen)); get_local_auth(sss, &(reg.auth)); reg.key_time = sss->dynamic_key_time; idx = 0; encode_mac(reg.edgeMac, &idx, sss->mac_addr); idx = 0; encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®); traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s", sock_to_cstr(sockbuf, &(peer->sock))); packet_header_encrypt(pktbuf, idx, idx, comm->header_encryption_ctx_static, comm->header_iv_ctx_static, time_stamp()); /* sent = */ sendto_peer(sss, peer, pktbuf, idx); } } return 0; /* OK */ } static int purge_expired_communities (n2n_sn_t *sss, time_t* p_last_purge, time_t now) { struct sn_community *comm, *tmp_comm; node_supernode_association_t *assoc, *tmp_assoc; size_t num_reg = 0; size_t num_assoc = 0; if((now - (*p_last_purge)) < PURGE_REGISTRATION_FREQUENCY) { return 0; } traceEvent(TRACE_DEBUG, "purging old communities and edges"); HASH_ITER(hh, sss->communities, comm, tmp_comm) { // federation is taken care of in re_register_and_purge_supernodes() if(comm->is_federation == IS_FEDERATION) continue; // purge the community's local peers num_reg += purge_peer_list(&comm->edges, sss->sock, &sss->tcp_connections, now - REGISTRATION_TIMEOUT); // purge the community's associated peers (connected to other supernodes) HASH_ITER(hh, comm->assoc, assoc, tmp_assoc) { if(comm->assoc->last_seen < (now - 3 * REGISTRATION_TIMEOUT)) { HASH_DEL(comm->assoc, assoc); free(assoc); num_assoc++; } } if((comm->edges == NULL) && (comm->purgeable == COMMUNITY_PURGEABLE)) { traceEvent(TRACE_INFO, "purging idle community %s", comm->community); if(NULL != comm->header_encryption_ctx_static) { /* this should not happen as 'purgeable' and thus only communities w/o encrypted header here */ free(comm->header_encryption_ctx_static); free(comm->header_iv_ctx_static); free(comm->header_encryption_ctx_dynamic); free(comm->header_iv_ctx_dynamic); } // remove all associations HASH_ITER(hh, comm->assoc, assoc, tmp_assoc) { HASH_DEL(comm->assoc, assoc); free(assoc); } HASH_DEL(sss->communities, comm); free(comm); } } (*p_last_purge) = now; traceEvent(TRACE_DEBUG, "purge_expired_communities removed %ld locally registered edges and %ld remotely associated edges", num_reg, num_assoc); return 0; } static int number_enc_packets_sort (struct sn_community *a, struct sn_community *b) { // comparison function for sorting communities in descending order of their // number_enc_packets-fields return (b->number_enc_packets - a->number_enc_packets); } static int sort_communities (n2n_sn_t *sss, time_t* p_last_sort, time_t now) { struct sn_community *comm, *tmp; if((now - (*p_last_sort)) < SORT_COMMUNITIES_INTERVAL) { return 0; } // this routine gets periodically called as defined in SORT_COMMUNITIES_INTERVAL // it sorts the communities in descending order of their number_enc_packets-fields... HASH_SORT(sss->communities, number_enc_packets_sort); // ... and afterward resets the number_enc__packets-fields to zero // (other models could reset it to half of their value to respect history) HASH_ITER(hh, sss->communities, comm, tmp) { comm->number_enc_packets = 0; } (*p_last_sort) = now; return 0; } /** Examine a datagram and determine what to do with it. * */ static int process_udp (n2n_sn_t * sss, const struct sockaddr_in *sender_sock, const SOCKET socket_fd, uint8_t * udp_buf, size_t udp_size, time_t now) { n2n_common_t cmn; /* common fields in the packet header */ size_t rem; size_t idx; size_t msg_type; uint8_t from_supernode; peer_info_t *sn = NULL; n2n_sock_t sender; macstr_t mac_buf; macstr_t mac_buf2; n2n_sock_str_t sockbuf; char buf[32]; uint8_t hash_buf[16] = {0}; /* always size of 16 (max) despite the actual value of N2N_REG_SUP_HASH_CHECK_LEN (<= 16) */ struct sn_community *comm, *tmp; uint32_t header_enc = 0; /* 1 == encrypted by static key, 2 == encrypted by dynamic key */ uint64_t stamp; int skip_add; time_t any_time = 0; traceEvent(TRACE_DEBUG, "processing incoming UDP packet [len: %lu][sender: %s:%u]", udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), ntohs(sender_sock->sin_port)); /* check if header is unencrypted. the following check is around 99.99962 percent reliable. * it heavily relies on the structure of packet's common part * changes to wire.c:encode/decode_common need to go together with this code */ if(udp_size < 24) { traceEvent(TRACE_DEBUG, "dropped a packet too short to be valid"); return -1; } if((udp_buf[23] == (uint8_t)0x00) // null terminated community name && (udp_buf[00] == N2N_PKT_VERSION) // correct packet version && ((be16toh(*(uint16_t*)&(udp_buf[02])) & N2N_FLAGS_TYPE_MASK) <= MSG_TYPE_MAX_TYPE) // message type && ( be16toh(*(uint16_t*)&(udp_buf[02])) < N2N_FLAGS_OPTIONS) // flags ) { /* most probably unencrypted */ /* make sure, no downgrading happens here and no unencrypted packets can be * injected in a community which definitely deals with encrypted headers */ HASH_FIND_COMMUNITY(sss->communities, (char *)&udp_buf[04], comm); if(comm) { if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { traceEvent(TRACE_DEBUG, "dropped a packet with unencrypted header " "addressed to community '%s' which uses encrypted headers", comm->community); return -1; } if(comm->header_encryption == HEADER_ENCRYPTION_UNKNOWN) { traceEvent(TRACE_INFO, "locked community '%s' to " "unencrypted headers", comm->community); /* set 'no encryption' in case it is not set yet */ comm->header_encryption = HEADER_ENCRYPTION_NONE; comm->header_encryption_ctx_static = NULL; comm->header_encryption_ctx_dynamic = NULL; } } } else { /* most probably encrypted */ /* cycle through the known communities (as keys) to eventually decrypt */ HASH_ITER(hh, sss->communities, comm, tmp) { /* skip the definitely unencrypted communities */ if(comm->header_encryption == HEADER_ENCRYPTION_NONE) { continue; } // match with static (1) or dynamic (2) ctx? // check dynamic first as it is identical to static in normal header encryption mode if(packet_header_decrypt(udp_buf, udp_size, comm->community, comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic, &stamp)) { header_enc = 2; } if(!header_enc) { pearson_hash_128(hash_buf, udp_buf, max(0, (int)udp_size - (int)N2N_REG_SUP_HASH_CHECK_LEN)); header_enc = packet_header_decrypt(udp_buf, max(0, (int)udp_size - (int)N2N_REG_SUP_HASH_CHECK_LEN), comm->community, comm->header_encryption_ctx_static, comm->header_iv_ctx_static, &stamp); } if(header_enc) { // time stamp verification follows in the packet specific section as it requires to determine the // sender from the hash list by its MAC, this all depends on packet type and packet structure // (MAC is not always in the same place) if(comm->header_encryption == HEADER_ENCRYPTION_UNKNOWN) { traceEvent(TRACE_INFO, "locked community '%s' to " "encrypted headers", comm->community); /* set 'encrypted' in case it is not set yet */ comm->header_encryption = HEADER_ENCRYPTION_ENABLED; } // count the number of encrypted packets for sorting the communities from time to time // for the HASH_ITER a few lines above gets faster for the more busy communities (comm->number_enc_packets)++; // no need to test further communities break; } } if(!header_enc) { // no matching key/community traceEvent(TRACE_DEBUG, "dropped a packet with seemingly encrypted header " "for which no matching community which uses encrypted headers was found"); return -1; } } /* Use decode_common() to determine the kind of packet then process it: * * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK * * REGISTER, REGISTER_ACK and PACKET messages are forwarded to their * destination edge. If the destination is not known then PACKETs are * broadcast. */ rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */ idx = 0; /* marches through packet header as parts are decoded. */ if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) { traceEvent(TRACE_ERROR, "failed to decode common section"); return -1; /* failed to decode packet */ } msg_type = cmn.pc; /* packet code */ // special case for user/pw auth // community's auth scheme and message type need to match the used key (dynamic) if(comm) { if((comm->allowed_users) && (msg_type != MSG_TYPE_REGISTER_SUPER) && (msg_type != MSG_TYPE_REGISTER_SUPER_ACK) && (msg_type != MSG_TYPE_REGISTER_SUPER_NAK)) { if(header_enc != 2) { traceEvent(TRACE_WARNING, "dropped packet encrypted with static key where expecting dynamic key"); return -1; } } } /* REVISIT: when UDP/IPv6 is supported we will need a flag to indicate which * IP transport version the packet arrived on. May need to UDP sockets. */ memset(&sender, 0, sizeof(n2n_sock_t)); sender.family = AF_INET; /* UDP socket was opened PF_INET v4 */ sender.port = ntohs(sender_sock->sin_port); memcpy(&(sender.addr.v4), &(sender_sock->sin_addr.s_addr), IPV4_SIZE); from_supernode = cmn.flags & N2N_FLAGS_FROM_SUPERNODE; if(from_supernode) { skip_add = SN_ADD_SKIP; sn = add_sn_to_list_by_mac_or_sock (&(sss->federation->edges), &sender, null_mac, &skip_add); // only REGISTER_SUPER allowed from unknown supernodes if((!sn) && (msg_type != MSG_TYPE_REGISTER_SUPER)) { traceEvent(TRACE_DEBUG, "dropped incoming data from unknown supernode"); return -1; } } if(cmn.ttl < 1) { traceEvent(TRACE_WARNING, "expired TTL"); return 0; /* Don't process further */ } --(cmn.ttl); /* The value copied into all forwarded packets. */ switch(msg_type) { case MSG_TYPE_PACKET: { /* PACKET from one edge to another edge via supernode. */ /* pkt will be modified in place and recoded to an output of potentially * different size due to addition of the socket.*/ n2n_PACKET_t pkt; n2n_common_t cmn2; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx = 0; int unicast; /* non-zero if unicast */ uint8_t * rec_buf; /* either udp_buf or encbuf */ if(!comm) { traceEvent(TRACE_DEBUG, "PACKET with unknown community %s", cmn.community); return -1; } sss->stats.last_fwd = now; decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); // already checked for valid comm if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_edge_time_stamp_and_verify(comm->edges, sn, pkt.srcMac, stamp, TIME_STAMP_ALLOW_JITTER)) { traceEvent(TRACE_DEBUG, "dropped PACKET due to time stamp error"); return -1; } } unicast = (0 == is_multi_broadcast(pkt.dstMac)); traceEvent(TRACE_DEBUG, "RX PACKET (%s) %s -> %s %s", (unicast ? "unicast" : "multicast"), macaddr_str(mac_buf, pkt.srcMac), macaddr_str(mac_buf2, pkt.dstMac), (from_supernode ? "from sn" : "local")); if(!from_supernode) { memcpy(&cmn2, &cmn, sizeof(n2n_common_t)); /* We are going to add socket even if it was not there before */ cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; pkt.sock.family = AF_INET; pkt.sock.port = ntohs(sender_sock->sin_port); memcpy(pkt.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); rec_buf = encbuf; /* Re-encode the header. */ encode_PACKET(encbuf, &encx, &cmn2, &pkt); uint16_t oldEncx = encx; /* Copy the original payload unchanged */ encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { // in case of user-password auth, also encrypt the iv of payload assuming ChaCha20 and SPECK having the same iv size packet_header_encrypt(rec_buf, oldEncx + (NULL != comm->allowed_users) * min(encx - oldEncx, N2N_SPECK_IVEC_SIZE), encx, comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic, time_stamp()); } } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ traceEvent(TRACE_DEBUG, "Rx PACKET fwd unmodified"); rec_buf = udp_buf; encx = udp_size; if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { // in case of user-password auth, also encrypt the iv of payload assuming ChaCha20 and SPECK having the same iv size packet_header_encrypt(rec_buf, idx + (NULL != comm->allowed_users) * min(encx - idx, N2N_SPECK_IVEC_SIZE), encx, comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic, time_stamp()); } } /* Common section to forward the final product. */ if(unicast) { try_forward(sss, comm, &cmn, pkt.dstMac, from_supernode, rec_buf, encx, now); } else { try_broadcast(sss, comm, &cmn, pkt.srcMac, from_supernode, rec_buf, encx, now); } break; } case MSG_TYPE_REGISTER: { /* Forwarding a REGISTER from one edge to the next */ n2n_REGISTER_t reg; n2n_common_t cmn2; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx = 0; int unicast; /* non-zero if unicast */ uint8_t * rec_buf; /* either udp_buf or encbuf */ if(!comm) { traceEvent(TRACE_DEBUG, "REGISTER from unknown community %s", cmn.community); return -1; } sss->stats.last_fwd = now; decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); // already checked for valid comm if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_edge_time_stamp_and_verify(comm->edges, sn, reg.srcMac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped REGISTER due to time stamp error"); return -1; } } unicast = (0 == is_multi_broadcast(reg.dstMac)); if(unicast) { traceEvent(TRACE_DEBUG, "Rx REGISTER %s -> %s %s", macaddr_str(mac_buf, reg.srcMac), macaddr_str(mac_buf2, reg.dstMac), ((cmn.flags & N2N_FLAGS_FROM_SUPERNODE) ? "from sn" : "local")); if(0 == (cmn.flags & N2N_FLAGS_FROM_SUPERNODE)) { memcpy(&cmn2, &cmn, sizeof(n2n_common_t)); /* We are going to add socket even if it was not there before */ cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; reg.sock.family = AF_INET; reg.sock.port = ntohs(sender_sock->sin_port); memcpy(reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); /* Re-encode the header. */ encode_REGISTER(encbuf, &encx, &cmn2, ®); rec_buf = encbuf; } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ rec_buf = udp_buf; encx = udp_size; } if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(rec_buf, encx, encx, comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic, time_stamp()); } try_forward(sss, comm, &cmn, reg.dstMac, from_supernode, rec_buf, encx, now); /* unicast only */ } else { traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); } break; } case MSG_TYPE_REGISTER_ACK: { traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (not implemented) should not be via supernode"); break; } case MSG_TYPE_REGISTER_SUPER: { n2n_REGISTER_SUPER_t reg; n2n_REGISTER_SUPER_ACK_t ack; n2n_REGISTER_SUPER_NAK_t nak; n2n_common_t cmn2; uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; uint8_t payload_buf[REG_SUPER_ACK_PAYLOAD_SPACE]; n2n_REGISTER_SUPER_ACK_payload_t *payload; size_t encx = 0; struct sn_community_regular_expression *re, *tmp_re; struct peer_info *peer, *tmp_peer, *p; int8_t allowed_match = -1; uint8_t match = 0; int match_length = 0; n2n_ip_subnet_t ipaddr; int num = 0; int skip; int ret_value; sn_user_t *user = NULL; memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t)); /* Edge/supernode requesting registration with us. */ sss->stats.last_reg_super=now; ++(sss->stats.reg_super); decode_REGISTER_SUPER(®, &cmn, udp_buf, &rem, &idx); if(comm) { if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_edge_time_stamp_and_verify(comm->edges, sn, reg.edgeMac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER due to time stamp error"); return -1; } } } /* Before we move any further, we need to check if the requested community is allowed by the supernode. In case it is not we do not report any message back to the edge to hide the supernode existance (better from the security standpoint) */ if(!comm && sss->lock_communities) { HASH_ITER(hh, sss->rules, re, tmp_re) { allowed_match = re_matchp(re->rule, (const char *)cmn.community, &match_length); if((allowed_match != -1) && (match_length == strlen((const char *)cmn.community)) // --- only full matches allowed (remove, if also partial matches wanted) && (allowed_match == 0)) { // --- only full matches allowed (remove, if also partial matches wanted) match = 1; break; } } if(match != 1) { traceEvent(TRACE_INFO, "discarded registration with unallowed community '%s'", (char*)cmn.community); return -1; } } if(!comm && (!sss->lock_communities || (match == 1))) { comm = (struct sn_community*)calloc(1, sizeof(struct sn_community)); if(comm) { comm_init(comm, (char *)cmn.community); /* new communities introduced by REGISTERs could not have had encrypted header... */ comm->header_encryption = HEADER_ENCRYPTION_NONE; comm->header_encryption_ctx_static = NULL; comm->header_encryption_ctx_dynamic = NULL; /* ... and also are purgeable during periodic purge */ comm->purgeable = COMMUNITY_PURGEABLE; comm->number_enc_packets = 0; HASH_ADD_STR(sss->communities, community, comm); traceEvent(TRACE_INFO, "new community: %s", comm->community); assign_one_ip_subnet(sss, comm); } } if(!comm) { traceEvent(TRACE_INFO, "discarded registration with unallowed community '%s'", (char*)cmn.community); return -1; } // hash check (user/pw auth only) if(comm->allowed_users) { // check if submitted public key is in list of allowed users HASH_FIND(hh, comm->allowed_users, ®.auth.token, sizeof(n2n_private_public_key_t), user); if(user) { speck_128_encrypt(hash_buf, (speck_context_t*)user->shared_secret_ctx); if(memcmp(hash_buf, udp_buf + udp_size - N2N_REG_SUP_HASH_CHECK_LEN /* length has already been checked */, N2N_REG_SUP_HASH_CHECK_LEN)) { traceEvent(TRACE_INFO, "Rx REGISTER_SUPER with wrong hash"); return -1; } } else { traceEvent(TRACE_INFO, "Rx REGISTER_SUPER from unknown user"); // continue and let auth check do the rest (otherwise, no NAK is sent) } } if(!memcmp(reg.edgeMac, sss->mac_addr, sizeof(n2n_mac_t))) { traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER from self, ignoring"); return -1; } cmn2.ttl = N2N_DEFAULT_TTL; cmn2.pc = n2n_register_super_ack; cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); ack.cookie = reg.cookie; memcpy(ack.srcMac, sss->mac_addr, sizeof(n2n_mac_t)); if(comm->is_federation != IS_FEDERATION) { /* alternatively, do not send zero tap ip address in federation REGISTER_SUPER */ if((reg.dev_addr.net_addr == 0) || (reg.dev_addr.net_addr == 0xFFFFFFFF) || (reg.dev_addr.net_bitlen == 0) || ((reg.dev_addr.net_addr & 0xFFFF0000) == 0xA9FE0000 /* 169.254.0.0 */)) { memset(&ipaddr, 0, sizeof(n2n_ip_subnet_t)); assign_one_ip_addr(comm, reg.dev_desc, &ipaddr); ack.dev_addr.net_addr = ipaddr.net_addr; ack.dev_addr.net_bitlen = ipaddr.net_bitlen; } } ack.lifetime = reg_lifetime(sss); ack.sock.family = AF_INET; ack.sock.port = ntohs(sender_sock->sin_port); memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); /* Add sender's data to federation (or update it) */ if(comm->is_federation == IS_FEDERATION) { skip_add = SN_ADD; p = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &(ack.sock), reg.edgeMac, &skip_add); p->last_seen = now; // communication with other supernodes happens via standard udp port p->socket_fd = sss->sock; } /* Skip random numbers of supernodes before payload assembling, calculating an appropriate random_number. * That way, all supernodes have a chance to be propagated with REGISTER_SUPER_ACK. */ skip = HASH_COUNT(sss->federation->edges) - (int)(REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE / REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE); skip = (skip < 0) ? 0 : n2n_rand_sqr(skip); /* Assembling supernode list for REGISTER_SUPER_ACK payload */ payload = (n2n_REGISTER_SUPER_ACK_payload_t*)payload_buf; HASH_ITER(hh, sss->federation->edges, peer, tmp_peer) { if(skip) { skip--; continue; } if(peer->sock.family == (uint8_t)AF_INVALID) continue; /* do not add unresolved supernodes to payload */ if(memcmp(&(peer->sock), &(ack.sock), sizeof(n2n_sock_t)) == 0) continue; /* a supernode doesn't add itself to the payload */ if((now - peer->last_seen) >= LAST_SEEN_SN_NEW) continue; /* skip long-time-not-seen supernodes. * We need to allow for a little extra time because supernodes sometimes exceed * their SN_ACTIVE time before they get re-registred to. */ if(((++num)*REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE) > REG_SUPER_ACK_PAYLOAD_SPACE) break; /* no more space available in REGISTER_SUPER_ACK payload */ memcpy(&(payload->sock), &(peer->sock), sizeof(n2n_sock_t)); memcpy(payload->mac, peer->mac_addr, sizeof(n2n_mac_t)); // shift to next payload entry payload++; } ack.num_sn = num; traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", macaddr_str(mac_buf, reg.edgeMac), sock_to_cstr(sockbuf, &(ack.sock))); // check authentication ret_value = update_edge_no_change; if(comm->is_federation != IS_FEDERATION) { /* REVISIT: auth among supernodes is not implemented yet */ if(cmn.flags & N2N_FLAGS_FROM_SUPERNODE) { ret_value = update_edge(sss, &cmn, ®, comm, &(ack.sock), socket_fd, &(ack.auth), SN_ADD_SKIP, now); } else { // do not add in case of null mac (edge asking for ip address) ret_value = update_edge(sss, &cmn, ®, comm, &(ack.sock), socket_fd, &(ack.auth), is_null_mac(reg.edgeMac) ? SN_ADD_SKIP : SN_ADD, now); } } if(ret_value == update_edge_auth_fail) { // send REGISTER_SUPER_NAK cmn2.pc = n2n_register_super_nak; nak.cookie = reg.cookie; memcpy(nak.srcMac, reg.edgeMac, sizeof(n2n_mac_t)); encode_REGISTER_SUPER_NAK(ackbuf, &encx, &cmn2, &nak); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(ackbuf, encx, encx, comm->header_encryption_ctx_static, comm->header_iv_ctx_static, time_stamp()); // if user-password-auth if(comm->allowed_users) { encode_buf(ackbuf, &encx, hash_buf /* no matter what content */, N2N_REG_SUP_HASH_CHECK_LEN); } } sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, ackbuf, encx); traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_NAK for %s", macaddr_str(mac_buf, reg.edgeMac)); } else { // if this is not already from a supernode ... // and not from federation, ... if((!(cmn.flags & N2N_FLAGS_FROM_SUPERNODE)) || (!(cmn.flags & N2N_FLAGS_SOCKET))) { // ... forward to all other supernodes (note try_broadcast()'s behavior with // NULL comm and from_supernode parameter) // exception: do not forward auto ip draw if(!is_null_mac(reg.edgeMac)) { reg.sock.family = AF_INET; reg.sock.port = ntohs(sender_sock->sin_port); memcpy(reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); cmn2.pc = n2n_register_super; encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, ®); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(ackbuf, encx, encx, comm->header_encryption_ctx_static, comm->header_iv_ctx_static, time_stamp()); // if user-password-auth if(comm->allowed_users) { // append an encrypted packet hash pearson_hash_128(hash_buf, ackbuf, encx); // same 'user' as above speck_128_encrypt(hash_buf, (speck_context_t*)user->shared_secret_ctx); encode_buf(ackbuf, &encx, hash_buf, N2N_REG_SUP_HASH_CHECK_LEN); } } try_broadcast(sss, NULL, &cmn, reg.edgeMac, from_supernode, ackbuf, encx, now); } // dynamic key time handling if appropriate ack.key_time = 0; if(comm->is_federation == IS_FEDERATION) { if(reg.key_time > sss->dynamic_key_time) { traceEvent(TRACE_DEBUG, "setting new key time"); // have all edges re_register (using old dynamic key) send_re_register_super(sss); // set new key time sss->dynamic_key_time = reg.key_time; // calculate new dynamic keys for all communities calculate_dynamic_keys(sss); // force re-register with all supernodes re_register_and_purge_supernodes(sss, sss->federation, &any_time, now, 1 /* forced */); } ack.key_time = sss->dynamic_key_time; } // send REGISTER_SUPER_ACK encx = 0; cmn2.pc = n2n_register_super_ack; encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack, payload_buf); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(ackbuf, encx, encx, comm->header_encryption_ctx_static, comm->header_iv_ctx_static, time_stamp()); // if user-password-auth if(comm->allowed_users) { // append an encrypted packet hash pearson_hash_128(hash_buf, ackbuf, encx); // same 'user' as above speck_128_encrypt(hash_buf, (speck_context_t*)user->shared_secret_ctx); encode_buf(ackbuf, &encx, hash_buf, N2N_REG_SUP_HASH_CHECK_LEN); } } sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, ackbuf, encx); traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", macaddr_str(mac_buf, reg.edgeMac), sock_to_cstr(sockbuf, &(ack.sock))); } else { // this is an edge with valid authentication registering with another supernode, so ... // 1- ... associate it with that other supernode update_node_supernode_association(comm, &(reg.edgeMac), sender_sock, now); // 2- ... we can delete it from regular list if present (can happen) HASH_FIND_PEER(comm->edges, reg.edgeMac, peer); if(peer != NULL) { if((peer->socket_fd != sss->sock) && (peer->socket_fd >= 0)) { n2n_tcp_connection_t *conn; HASH_FIND_INT(sss->tcp_connections, &(peer->socket_fd), conn); close_tcp_connection(sss, conn); /* also deletes the peer */ } else { HASH_DEL(comm->edges, peer); free(peer); } } } } break; } case MSG_TYPE_UNREGISTER_SUPER: { n2n_UNREGISTER_SUPER_t unreg; struct peer_info *peer; int auth; memset(&unreg, 0, sizeof(n2n_UNREGISTER_SUPER_t)); if(!comm) { traceEvent(TRACE_DEBUG, "dropped UNREGISTER_SUPER with unknown community %s", cmn.community); return -1; } if((from_supernode == 1) || (comm->is_federation == IS_FEDERATION)) { traceEvent(TRACE_DEBUG, "dropped UNREGISTER_SUPER: should not come from a supernode or federation."); return -1; } decode_UNREGISTER_SUPER(&unreg, &cmn, udp_buf, &rem, &idx); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_edge_time_stamp_and_verify(comm->edges, sn, unreg.srcMac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped UNREGISTER_SUPER due to time stamp error"); return -1; } } traceEvent(TRACE_DEBUG, "Rx UNREGISTER_SUPER from %s", macaddr_str(mac_buf, unreg.srcMac)); HASH_FIND_PEER(comm->edges, unreg.srcMac, peer); if(peer != NULL) { if((auth = auth_edge(&(peer->auth), &unreg.auth, NULL, comm)) == 0) { if((peer->socket_fd != sss->sock) && (peer->socket_fd >= 0)) { n2n_tcp_connection_t *conn; HASH_FIND_INT(sss->tcp_connections, &(peer->socket_fd), conn); close_tcp_connection(sss, conn); /* also deletes the peer */ } else { HASH_DEL(comm->edges, peer); free(peer); } } } break; } case MSG_TYPE_REGISTER_SUPER_ACK: { n2n_REGISTER_SUPER_ACK_t ack; struct peer_info *scan, *tmp; n2n_sock_str_t sockbuf1; n2n_sock_str_t sockbuf2; macstr_t mac_buf1; n2n_sock_t sender; n2n_sock_t *orig_sender; int i; uint8_t dec_tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE]; n2n_REGISTER_SUPER_ACK_payload_t *payload; memset(&sender, 0, sizeof(n2n_sock_t)); sender.family = AF_INET; sender.port = ntohs(sender_sock->sin_port); memcpy(&(sender.addr.v4), &(sender_sock->sin_addr.s_addr), IPV4_SIZE); orig_sender = &sender; memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); if(!comm) { traceEvent(TRACE_DEBUG, "REGISTER_SUPER_ACK with unknown community %s", cmn.community); return -1; } if((from_supernode == 0) || (comm->is_federation == IS_NO_FEDERATION)) { traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_ACK, should not come from an edge or regular community"); return -1; } decode_REGISTER_SUPER_ACK(&ack, &cmn, udp_buf, &rem, &idx, dec_tmpbuf); orig_sender = &(ack.sock); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_edge_time_stamp_and_verify(comm->edges, sn, ack.srcMac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_ACK due to time stamp error"); return -1; } } traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK from MAC %s [%s] (external %s)", macaddr_str(mac_buf1, ack.srcMac), sock_to_cstr(sockbuf1, &sender), sock_to_cstr(sockbuf2, orig_sender)); skip_add = SN_ADD_SKIP; scan = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &sender, ack.srcMac, &skip_add); if(scan != NULL) { scan->last_seen = now; } else { traceEvent(TRACE_DEBUG, "dropped REGISTER_SUPER_ACK due to an unknown supernode"); break; } if(ack.cookie == scan->last_cookie) { payload = (n2n_REGISTER_SUPER_ACK_payload_t *)dec_tmpbuf; for(i = 0; i < ack.num_sn; i++) { skip_add = SN_ADD; tmp = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &(payload->sock), payload->mac, &skip_add); // other supernodes communicate via standard udp socket tmp->socket_fd = sss->sock; if(skip_add == SN_ADD_ADDED) { tmp->last_seen = now - LAST_SEEN_SN_NEW; } // shift to next payload entry payload++; } if(ack.key_time > sss->dynamic_key_time) { traceEvent(TRACE_DEBUG, "setting new key time"); // have all edges re_register (using old dynamic key) send_re_register_super(sss); // set new key time sss->dynamic_key_time = ack.key_time; // calculate new dynamic keys for all communities calculate_dynamic_keys(sss); // force re-register with all supernodes re_register_and_purge_supernodes(sss, sss->federation, &any_time, now, 1 /* forced */); } } else { traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie"); } break; } case MSG_TYPE_REGISTER_SUPER_NAK: { n2n_REGISTER_SUPER_NAK_t nak; uint8_t nakbuf[N2N_SN_PKTBUF_SIZE]; size_t encx = 0; struct peer_info *peer; n2n_sock_str_t sockbuf; macstr_t mac_buf; n2n_sock_t sender; memset(&sender, 0, sizeof(n2n_sock_t)); sender.family = AF_INET; sender.port = ntohs(sender_sock->sin_port); memcpy(&(sender.addr.v4), &(sender_sock->sin_addr.s_addr), IPV4_SIZE); memset(&nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t)); if(!comm) { traceEvent(TRACE_DEBUG, "REGISTER_SUPER_NAK with unknown community %s", cmn.community); return -1; } decode_REGISTER_SUPER_NAK(&nak, &cmn, udp_buf, &rem, &idx); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_edge_time_stamp_and_verify(comm->edges, sn, nak.srcMac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER_NAK due to time stamp error"); return -1; } } traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_NAK from %s [%s]", macaddr_str(mac_buf, nak.srcMac), sock_to_cstr(sockbuf, &sender)); HASH_FIND_PEER(comm->edges, nak.srcMac, peer); if(comm->is_federation == IS_NO_FEDERATION) { if(peer != NULL) { // this is a NAK for one of the edges conencted to this supernode, forward, // i.e. re-assemble (memcpy from udpbuf to nakbuf could be sufficient as well) // use incoming cmn (with already decreased TTL) // NAK (cookie, srcMac, auth) remains unchanged encode_REGISTER_SUPER_NAK(nakbuf, &encx, &cmn, &nak); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(nakbuf, encx, encx, comm->header_encryption_ctx_static, comm->header_iv_ctx_static, time_stamp()); // if user-password-auth if(comm->allowed_users) { encode_buf(nakbuf, &encx, hash_buf /* no matter what content */, N2N_REG_SUP_HASH_CHECK_LEN); } } sendto_peer(sss, peer, nakbuf, encx); if((peer->socket_fd != sss->sock) && (peer->socket_fd >= 0)) { n2n_tcp_connection_t *conn; HASH_FIND_INT(sss->tcp_connections, &(peer->socket_fd), conn); close_tcp_connection(sss, conn); /* also deletes the peer */ } else { HASH_DEL(comm->edges, peer); free(peer); } } } break; } case MSG_TYPE_QUERY_PEER: { n2n_QUERY_PEER_t query; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx = 0; n2n_common_t cmn2; n2n_PEER_INFO_t pi; struct sn_community_regular_expression *re, *tmp_re; int8_t allowed_match = -1; uint8_t match = 0; int match_length = 0; if(!comm && sss->lock_communities) { HASH_ITER(hh, sss->rules, re, tmp_re) { allowed_match = re_matchp(re->rule, (const char *)cmn.community, &match_length); if((allowed_match != -1) && (match_length == strlen((const char *)cmn.community)) // --- only full matches allowed (remove, if also partial matches wanted) && (allowed_match == 0)) { // --- only full matches allowed (remove, if also partial matches wanted) match = 1; break; } } if(match != 1) { traceEvent(TRACE_DEBUG, "QUERY_PEER from unknown community %s", cmn.community); return -1; } } if(!comm && sss->lock_communities && (match == 0)) { traceEvent(TRACE_DEBUG, "QUERY_PEER from not allowed community %s", cmn.community); return -1; } decode_QUERY_PEER( &query, &cmn, udp_buf, &rem, &idx ); // to answer a PING, it is sufficient if the provided communtiy would be a valid one, there does not // neccessarily need to be a comm entry present, e.g. because there locally are no edges of the // community connected (several supernodes in a federation setup) if(comm) { if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_edge_time_stamp_and_verify(comm->edges, sn, query.srcMac, stamp, TIME_STAMP_ALLOW_JITTER)) { traceEvent(TRACE_DEBUG, "dropped QUERY_PEER due to time stamp error"); return -1; } } } if(is_null_mac(query.targetMac)) { traceEvent(TRACE_DEBUG, "Rx PING from %s", macaddr_str(mac_buf, query.srcMac)); cmn2.ttl = N2N_DEFAULT_TTL; cmn2.pc = n2n_peer_info; cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); pi.aflags = 0; memcpy(pi.mac, query.targetMac, sizeof(n2n_mac_t)); memcpy(pi.srcMac, sss->mac_addr, sizeof(n2n_mac_t)); pi.sock.family = AF_INET; pi.sock.port = ntohs(sender_sock->sin_port); memcpy(pi.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); pi.load = sn_selection_criterion_gather_data(sss); snprintf(pi.version, sizeof(pi.version), "%s", sss->version); pi.uptime = now - sss->start_time; encode_PEER_INFO(encbuf, &encx, &cmn2, &pi); if(comm) { if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(encbuf, encx, encx, comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic, time_stamp()); } } sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, encbuf, encx); traceEvent(TRACE_DEBUG, "Tx PONG to %s", macaddr_str(mac_buf, query.srcMac)); } else { traceEvent(TRACE_DEBUG, "Rx QUERY_PEER from %s for %s", macaddr_str(mac_buf, query.srcMac), macaddr_str(mac_buf2, query.targetMac)); struct peer_info *scan; // as opposed to the special case 'PING', proper QUERY_PEER processing requires a locally actually present community entry if(!comm) { traceEvent(TRACE_DEBUG, "QUERY_PEER with unknown community %s", cmn.community); return -1; } HASH_FIND_PEER(comm->edges, query.targetMac, scan); if(scan) { cmn2.ttl = N2N_DEFAULT_TTL; cmn2.pc = n2n_peer_info; cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); pi.aflags = 0; memcpy(pi.srcMac, query.srcMac, sizeof(n2n_mac_t)); memcpy(pi.mac, query.targetMac, sizeof(n2n_mac_t)); pi.sock = scan->sock; if(scan->preferred_sock.family != (uint8_t)AF_INVALID) { cmn2.flags |= N2N_FLAGS_SOCKET; pi.preferred_sock = scan->preferred_sock; } encode_PEER_INFO(encbuf, &encx, &cmn2, &pi); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(encbuf, encx, encx, comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic, time_stamp()); } // back to sender, be it edge or supernode (which will forward to edge) sendto_sock(sss, socket_fd, (struct sockaddr *)sender_sock, encbuf, encx); traceEvent(TRACE_DEBUG, "Tx PEER_INFO to %s", macaddr_str(mac_buf, query.srcMac)); } else { if(from_supernode) { traceEvent(TRACE_DEBUG, "QUERY_PEER on unknown edge from supernode %s, dropping the packet", macaddr_str(mac_buf, query.srcMac)); } else { traceEvent(TRACE_DEBUG, "QUERY_PEER from unknown edge %s, forwarding to all other supernodes", macaddr_str(mac_buf, query.srcMac)); memcpy(&cmn2, &cmn, sizeof(n2n_common_t)); cmn2.flags |= N2N_FLAGS_FROM_SUPERNODE; encode_QUERY_PEER(encbuf, &encx, &cmn2, &query); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(encbuf, encx, encx, comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic, time_stamp()); } try_broadcast(sss, NULL, &cmn, query.srcMac, from_supernode, encbuf, encx, now); } } } break; } case MSG_TYPE_PEER_INFO: { n2n_PEER_INFO_t pi; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx = 0; struct peer_info *peer; if(!comm) { traceEvent(TRACE_DEBUG, "PEER_INFO with unknown community %s", cmn.community); return -1; } decode_PEER_INFO(&pi, &cmn, udp_buf, &rem, &idx); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { if(!find_edge_time_stamp_and_verify(comm->edges, sn, pi.srcMac, stamp, TIME_STAMP_NO_JITTER)) { traceEvent(TRACE_DEBUG, "dropped PEER_INFO due to time stamp error"); return -1; } } traceEvent(TRACE_INFO, "Rx PEER_INFO from %s [%s]", macaddr_str(mac_buf, pi.srcMac), sock_to_cstr(sockbuf, &sender)); HASH_FIND_PEER(comm->edges, pi.srcMac, peer); if(peer != NULL) { if((comm->is_federation == IS_NO_FEDERATION) && (!is_null_mac(pi.srcMac))) { // snoop on the information to use for supernode forwarding (do not wait until first remote REGISTER_SUPER) update_node_supernode_association(comm, &(pi.mac), sender_sock, now); // this is a PEER_INFO for one of the edges conencted to this supernode, forward, // i.e. re-assemble (memcpy of udpbuf to encbuf could be sufficient as well) // use incoming cmn (with already decreased TTL) // PEER_INFO remains unchanged encode_PEER_INFO(encbuf, &encx, &cmn, &pi); if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { packet_header_encrypt(encbuf, encx, encx, comm->header_encryption_ctx_dynamic, comm->header_iv_ctx_dynamic, time_stamp()); } sendto_peer(sss, peer, encbuf, encx); } } break; } default: /* Not a known message type */ traceEvent(TRACE_WARNING, "unable to handle packet type %d: ignored", (signed int)msg_type); } /* switch(msg_type) */ return 0; } /** Long lived processing entry point. Split out from main to simply * daemonisation on some platforms. */ int run_sn_loop (n2n_sn_t *sss) { uint8_t pktbuf[N2N_SN_PKTBUF_SIZE]; time_t last_purge_edges = 0; time_t last_sort_communities = 0; time_t last_re_reg_and_purge = 0; sss->start_time = time(NULL); while(*sss->keep_running) { int rc; ssize_t bread; int max_sock; fd_set socket_mask; n2n_tcp_connection_t *conn, *tmp_conn; #ifdef N2N_HAVE_TCP SOCKET tmp_sock; n2n_sock_str_t sockbuf; #endif struct timeval wait_time; time_t before, now = 0; FD_ZERO(&socket_mask); FD_SET(sss->sock, &socket_mask); #ifdef N2N_HAVE_TCP FD_SET(sss->tcp_sock, &socket_mask); #endif FD_SET(sss->mgmt_sock, &socket_mask); max_sock = MAX(MAX(sss->sock, sss->mgmt_sock), sss->tcp_sock); #ifdef N2N_HAVE_TCP // add the tcp connections' sockets HASH_ITER(hh, sss->tcp_connections, conn, tmp_conn) { //socket descriptor FD_SET(conn->socket_fd, &socket_mask); if(conn->socket_fd > max_sock) max_sock = conn->socket_fd; } #endif wait_time.tv_sec = 10; wait_time.tv_usec = 0; before = time(NULL); rc = select(max_sock + 1, &socket_mask, NULL, NULL, &wait_time); now = time(NULL); if(rc > 0) { // external udp if(FD_ISSET(sss->sock, &socket_mask)) { struct sockaddr_in sender_sock; socklen_t i; i = sizeof(sender_sock); bread = recvfrom(sss->sock, (void *)pktbuf, N2N_SN_PKTBUF_SIZE, 0 /*flags*/, (struct sockaddr *)&sender_sock, (socklen_t *)&i); if((bread < 0) #ifdef WIN32 && (WSAGetLastError() != WSAECONNRESET) #endif ) { /* For UDP bread of zero just means no data (unlike TCP). */ /* The fd is no good now. Maybe we lost our interface. */ traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); #ifdef WIN32 traceEvent(TRACE_ERROR, "WSAGetLastError(): %u", WSAGetLastError()); #endif *sss->keep_running = 0; break; } // we have a datagram to process... if(bread > 0) { // ...and the datagram has data (not just a header) process_udp(sss, &sender_sock, sss->sock, pktbuf, bread, now); } } #ifdef N2N_HAVE_TCP // the so far known tcp connections // beware: current conn and other items of the connection list may be found // due for deletion while processing packets. Even OTHER connections, e.g. if // forwarding to another edge node fails. connections due for deletion will // not immediately be deleted but marked 'inactive' for later deletion HASH_ITER(hh, sss->tcp_connections, conn, tmp_conn) { // do not process entries that have been marked inactive, those will be deleted // immediately after this loop if(conn->inactive) continue; if(FD_ISSET(conn->socket_fd, &socket_mask)) { struct sockaddr_in sender_sock; socklen_t i; i = sizeof(sender_sock); bread = recvfrom(conn->socket_fd, conn->buffer + conn->position, conn->expected - conn->position, 0 /*flags*/, (struct sockaddr *)&sender_sock, (socklen_t *)&i); if(bread <= 0) { traceEvent(TRACE_INFO, "closing tcp connection to [%s]", sock_to_cstr(sockbuf, (n2n_sock_t*)&sender_sock)); traceEvent(TRACE_DEBUG, "recvfrom() returns %d and sees errno %d (%s)", bread, errno, strerror(errno)); #ifdef WIN32 traceEvent(TRACE_DEBUG, "WSAGetLastError(): %u", WSAGetLastError()); #endif close_tcp_connection(sss, conn); continue; } conn->position += bread; if(conn->position == conn->expected) { if(conn->position == sizeof(uint16_t)) { // the prepended length has been read, preparing for the packet conn->expected += be16toh(*(uint16_t*)(conn->buffer)); if(conn->expected > N2N_SN_PKTBUF_SIZE) { traceEvent(TRACE_INFO, "closing tcp connection to [%s]", sock_to_cstr(sockbuf, (n2n_sock_t*)&sender_sock)); traceEvent(TRACE_DEBUG, "too many bytes in tcp packet expected"); close_tcp_connection(sss, conn); continue; } } else { // full packet read, handle it process_udp(sss, (struct sockaddr_in*)&(conn->sock), conn->socket_fd, conn->buffer + sizeof(uint16_t), conn->position - sizeof(uint16_t), now); // reset, await new prepended length conn->expected = sizeof(uint16_t); conn->position = 0; } } } } // remove inactive / already closed tcp connections from list HASH_ITER(hh, sss->tcp_connections, conn, tmp_conn) { if(conn->inactive) { HASH_DEL(sss->tcp_connections, conn); free(conn); } } // accept new incoming tcp connection if(FD_ISSET(sss->tcp_sock, &socket_mask)) { struct sockaddr_in sender_sock; socklen_t i; i = sizeof(sender_sock); if((HASH_COUNT(sss->tcp_connections) + 4) < FD_SETSIZE) { tmp_sock = accept(sss->tcp_sock, (struct sockaddr *)&sender_sock, (socklen_t *)&i); if(tmp_sock >= 0) { conn = (n2n_tcp_connection_t*)malloc(sizeof(n2n_tcp_connection_t)); if(conn) { conn->socket_fd = tmp_sock; memcpy(&(conn->sock), &sender_sock, sizeof(struct sockaddr_in)); conn->inactive = 0; conn->expected = sizeof(uint16_t); conn->position = 0; HASH_ADD_INT(sss->tcp_connections, socket_fd, conn); traceEvent(TRACE_INFO, "accepted incoming TCP connection from [%s]", sock_to_cstr(sockbuf, (n2n_sock_t*)&sender_sock)); } } } else { // no space to store the socket for a new connection, close immediately traceEvent(TRACE_DEBUG, "denied incoming TCP connection from [%s] due to max connections limit hit", sock_to_cstr(sockbuf, (n2n_sock_t*)&sender_sock)); } } #endif /* N2N_HAVE_TCP */ // handle management port input if(FD_ISSET(sss->mgmt_sock, &socket_mask)) { struct sockaddr_in sender_sock; size_t i; i = sizeof(sender_sock); bread = recvfrom(sss->mgmt_sock, (void *)pktbuf, N2N_SN_PKTBUF_SIZE, 0 /*flags*/, (struct sockaddr *)&sender_sock, (socklen_t *)&i); if(bread <= 0) { traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); *sss->keep_running = 0; break; } // we have a datagram to process process_mgmt(sss, &sender_sock, (char *)pktbuf, bread, now); } } else { if(((now - before) < wait_time.tv_sec) && (*sss->keep_running)){ // this is no real timeout, something went wrong with one of the tcp connections (probably) // close them all, edges will re-open if they detect closure traceEvent(TRACE_DEBUG, "falsly claimed timeout, assuming issue with tcp connection, closing them all"); HASH_ITER(hh, sss->tcp_connections, conn, tmp_conn) close_tcp_connection(sss, conn); } else traceEvent(TRACE_DEBUG, "timeout"); } re_register_and_purge_supernodes(sss, sss->federation, &last_re_reg_and_purge, now, 0 /* not forced */); purge_expired_communities(sss, &last_purge_edges, now); sort_communities(sss, &last_sort_communities, now); resolve_check(sss->resolve_parameter, 0 /* presumably, no special resolution requirement */, now); } /* while */ sn_term(sss); return 0; } ntop-n2n-90215bd/src/speck.c000066400000000000000000001330631422132035700155620ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // cipher SPECK -- 128 bit block size -- 128 and 256 bit key size -- CTR mode // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ #include "speck.h" #if defined (__AVX512F__) // AVX512 support ---------------------------------------------------------------------- #define LCS(x,r) (((x)<>(64-r))) #define RCS(x,r) (((x)>>r)|((x)<<(64-r))) #define SET _mm512_set_epi64 #define XOR _mm512_xor_si512 #define ADD _mm512_add_epi64 #define AND _mm512_and_si512 #define ROL(X,r) (_mm512_rol_epi64(X,r)) #define ROR(X,r) (_mm512_ror_epi64(X,r)) #define _q8 SET(0x7LL,0x3LL,0x6LL,0x2LL,0x5LL,0x1LL,0x4LL,0x0LL) #define _eight SET(0x8LL,0x8LL,0x8LL,0x8LL,0x8LL,0x8LL,0x8LL,0x8LL) #define SET1(X,c) (X=SET(c,c,c,c,c,c,c,c)) #define SET8(X,c) (X=SET(c,c,c,c,c,c,c,c), X=ADD(X,_q8)) #define LOW _mm512_unpacklo_epi64 #define HIGH _mm512_unpackhi_epi64 #define LD(ip) (_mm512_load_epi64(((void *)(ip)))) #define ST(ip,X) _mm512_storeu_si512((void *)(ip),X) #define STORE(out,X,Y) (ST(out,LOW(Y,X)), ST(out+64,HIGH(Y,X))) #define XOR_STORE(in,out,X,Y) (ST(out,XOR(LD(in),LOW(Y,X))), ST(out+64,XOR(LD(in+64),HIGH(Y,X)))) #define Rx8(X,Y,k) (X[0]=XOR(ADD(ROR(X[0],8),Y[0]),k), \ Y[0]=XOR(ROL(Y[0],3),X[0])) #define Rx16(X,Y,k) (X[0]=XOR(ADD(ROR(X[0],8),Y[0]),k), X[1]=XOR(ADD(ROR(X[1],8),Y[1]),k), \ Y[0]=XOR(ROL(Y[0],3),X[0]), Y[1]=XOR(ROL(Y[1],3),X[1])) #define Rx24(X,Y,k) (X[0]=XOR(ADD(ROR(X[0],8),Y[0]),k), X[1]=XOR(ADD(ROR(X[1],8),Y[1]),k), X[2]=XOR(ADD(ROR(X[2],8),Y[2]),k), \ Y[0]=XOR(ROL(Y[0],3),X[0]), Y[1]=XOR(ROL(Y[1],3),X[1]), Y[2]=XOR(ROL(Y[2],3),X[2])) #define Rx32(X,Y,k) (X[0]=XOR(ADD(ROR(X[0],8),Y[0]),k), X[1]=XOR(ADD(ROR(X[1],8),Y[1]),k), \ X[2]=XOR(ADD(ROR(X[2],8),Y[2]),k), X[3]=XOR(ADD(ROR(X[3],8),Y[3]),k), \ Y[0]=XOR(ROL(Y[0],3),X[0]), Y[1]=XOR(ROL(Y[1],3),X[1]), \ Y[2]=XOR(ROL(Y[2],3),X[2]), Y[3]=XOR(ROL(Y[3],3),X[3])) #define Rx1(x,y,k) (x[0]=RCS(x[0],8), x[0]+=y[0], x[0]^=k, y[0]=LCS(y[0],3), y[0]^=x[0]) #define Rx1b(x,y,k) (x=RCS(x,8), x+=y, x^=k, y=LCS(y,3), y^=x) #define Rx2(x,y,k) (x[0]=RCS(x[0],8), x[1]=RCS(x[1],8), x[0]+=y[0], x[1]+=y[1], \ x[0]^=k, x[1]^=k, y[0]=LCS(y[0],3), y[1]=LCS(y[1],3), y[0]^=x[0], y[1]^=x[1]) #define Encrypt_128(X,Y,k,n) (Rx##n(X,Y,k[0]), Rx##n(X,Y,k[1]), Rx##n(X,Y,k[2]), Rx##n(X,Y,k[3]), Rx##n(X,Y,k[4]), Rx##n(X,Y,k[5]), Rx##n(X,Y,k[6]), Rx##n(X,Y,k[7]), \ Rx##n(X,Y,k[8]), Rx##n(X,Y,k[9]), Rx##n(X,Y,k[10]), Rx##n(X,Y,k[11]), Rx##n(X,Y,k[12]), Rx##n(X,Y,k[13]), Rx##n(X,Y,k[14]), Rx##n(X,Y,k[15]), \ Rx##n(X,Y,k[16]), Rx##n(X,Y,k[17]), Rx##n(X,Y,k[18]), Rx##n(X,Y,k[19]), Rx##n(X,Y,k[20]), Rx##n(X,Y,k[21]), Rx##n(X,Y,k[22]), Rx##n(X,Y,k[23]), \ Rx##n(X,Y,k[24]), Rx##n(X,Y,k[25]), Rx##n(X,Y,k[26]), Rx##n(X,Y,k[27]), Rx##n(X,Y,k[28]), Rx##n(X,Y,k[29]), Rx##n(X,Y,k[30]), Rx##n(X,Y,k[31])) #define Encrypt_256(X,Y,k,n) (Encrypt_128(X,Y,k,n), \ Rx##n(X,Y,k[32]), Rx##n(X,Y,k[33])) #define RK(X,Y,k,key,i) (SET1(k[i],Y), key[i]=Y, X=RCS(X,8), X+=Y, X^=i, Y=LCS(Y,3), Y^=X) #define EK(A,B,C,D,k,key) (RK(B,A,k,key,0), RK(C,A,k,key,1), RK(D,A,k,key,2), RK(B,A,k,key,3), RK(C,A,k,key,4), RK(D,A,k,key,5), RK(B,A,k,key,6), \ RK(C,A,k,key,7), RK(D,A,k,key,8), RK(B,A,k,key,9), RK(C,A,k,key,10), RK(D,A,k,key,11), RK(B,A,k,key,12), RK(C,A,k,key,13), \ RK(D,A,k,key,14), RK(B,A,k,key,15), RK(C,A,k,key,16), RK(D,A,k,key,17), RK(B,A,k,key,18), RK(C,A,k,key,19), RK(D,A,k,key,20), \ RK(B,A,k,key,21), RK(C,A,k,key,22), RK(D,A,k,key,23), RK(B,A,k,key,24), RK(C,A,k,key,25), RK(D,A,k,key,26), RK(B,A,k,key,27), \ RK(C,A,k,key,28), RK(D,A,k,key,29), RK(B,A,k,key,30), RK(C,A,k,key,31), RK(D,A,k,key,32), RK(B,A,k,key,33)) #define Encrypt_Dispatcher(keysize) \ u64 x[2], y[2]; \ u512 X[4], Y[4]; \ unsigned char block1024[128]; \ \ if(numbytes == 16) { \ x[0] = nonce[1]; y[0] = nonce[0]; nonce[0]++; \ Encrypt_##keysize(x, y, ctx->key, 1); \ ((u64 *)out)[1] = x[0]; ((u64 *)out)[0] = y[0]; \ return 0; \ } \ \ if(numbytes == 32) { \ x[0] = nonce[1]; y[0] = nonce[0]; nonce[0]++; \ x[1] = nonce[1]; y[1] = nonce[0]; nonce[0]++; \ Encrypt_##keysize(x, y, ctx->key, 2); \ ((u64 *)out)[1] = x[0] ^ ((u64 *)in)[1]; ((u64 *)out)[0] = y[0] ^ ((u64 *)in)[0]; \ ((u64 *)out)[3] = x[1] ^ ((u64 *)in)[3]; ((u64 *)out)[2] = y[1] ^ ((u64 *)in)[2]; \ return 0; \ } \ \ if(numbytes == 64) { \ SET1(X[0], nonce[1]); \ SET8(Y[0], nonce[0]); \ Encrypt_##keysize(X, Y, ctx->rk, 8); \ nonce[0] += (numbytes >> 4); \ memcpy(block1024, in, 64); \ XOR_STORE(block1024, block1024, X[0], Y[0]); \ memcpy(out, block1024, 64); \ return 0; \ } \ \ SET1(X[0], nonce[1]); SET8(Y[0], nonce[0]); \ \ if(numbytes == 128) \ Encrypt_##keysize(X, Y, ctx->rk, 8); \ else { \ X[1] = X[0]; \ Y[1] = ADD(Y[0], _eight); \ if(numbytes == 256) \ Encrypt_##keysize(X, Y, ctx->rk, 16); \ else { \ X[2] = X[0]; \ Y[2] = ADD(Y[1], _eight); \ if(numbytes == 384) \ Encrypt_##keysize(X, Y, ctx->rk, 24); \ else { \ X[3] = X[0]; \ Y[3] = ADD(Y[2], _eight); \ Encrypt_##keysize(X, Y, ctx->rk, 32); \ } \ } \ } \ \ nonce[0] += (numbytes >> 4); \ \ XOR_STORE(in, out, X[0], Y[0]); \ if (numbytes >= 256) \ XOR_STORE(in + 128, out + 128, X[1], Y[1]); \ if(numbytes >= 384) \ XOR_STORE(in + 256, out + 256, X[2], Y[2]); \ if(numbytes >= 512) \ XOR_STORE(in + 384, out + 384, X[3], Y[3]); \ \ return 0 static int speck_encrypt_xor(unsigned char *out, const unsigned char *in, u64 nonce[], speck_context_t *ctx, int numbytes) { if(ctx->keysize == 256) { Encrypt_Dispatcher(256); } else { Encrypt_Dispatcher(128); } } static int internal_speck_ctr(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *n, speck_context_t *ctx) { int i; u64 nonce[2]; unsigned char block[16]; u64 * const block64 = (u64 *)block; if (!inlen) return 0; nonce[0] = ((u64 *)n)[0]; nonce[1] = ((u64 *)n)[1]; while(inlen >= 512) { speck_encrypt_xor(out, in, nonce, ctx, 512); in += 512; inlen -= 512; out += 512; } if(inlen >= 384) { speck_encrypt_xor(out, in, nonce, ctx, 384); in += 384; inlen -= 384; out += 384; } if(inlen >= 256) { speck_encrypt_xor(out, in, nonce, ctx, 256); in += 256; inlen -= 256; out += 256; } if(inlen >= 128) { speck_encrypt_xor(out, in, nonce, ctx, 128); in += 128; inlen -= 128; out += 128; } if(inlen >= 64) { speck_encrypt_xor(out, in, nonce, ctx, 64); in += 64; inlen -= 64; out += 64; } if(inlen >= 32) { speck_encrypt_xor(out, in, nonce, ctx, 32); in += 32; inlen -= 32; out += 32; } if(inlen >= 16) { speck_encrypt_xor(block, in, nonce, ctx, 16); ((u64 *)out)[0] = block64[0] ^ ((u64 *)in)[0]; ((u64 *)out)[1] = block64[1] ^ ((u64 *)in)[1]; in += 16; inlen -= 16; out += 16; } if(inlen > 0) { speck_encrypt_xor(block, in, nonce, ctx, 16); for(i = 0; i < inlen; i++) out[i] = block[i] ^ in[i]; } return 0; } static int speck_expand_key (speck_context_t *ctx, const unsigned char *k, int keysize) { u64 K[4]; size_t i; for(i = 0; i < (keysize >> 6); i++) K[i] = ((u64 *)k)[i]; // 128 bit has only two keys A and B thus replacing both C and D with B then if(keysize == 128) { EK(K[0], K[1], K[1], K[1], ctx->rk, ctx->key); } else { EK(K[0], K[1], K[2], K[3], ctx->rk, ctx->key); } ctx->keysize = keysize; return 0; } #elif defined (__AVX2__) // AVX2 support ------------------------------------------------------------------------- #define LCS(x,r) (((x)<>(64-r))) #define RCS(x,r) (((x)>>r)|((x)<<(64-r))) #define XOR _mm256_xor_si256 #define AND _mm256_and_si256 #define ADD _mm256_add_epi64 #define SL _mm256_slli_epi64 #define SR _mm256_srli_epi64 #define _q SET(0x3,0x1,0x2,0x0) #define _four SET(0x4,0x4,0x4,0x4) #define SET _mm256_set_epi64x #define SET1(X,c) (X=SET(c,c,c,c)) #define SET4(X,c) (X=SET(c,c,c,c), X=ADD(X,_q)) #define LOW _mm256_unpacklo_epi64 #define HIGH _mm256_unpackhi_epi64 #define LD(ip) _mm256_loadu_si256((__m256i *)(ip)) #define ST(ip,X) _mm256_storeu_si256((__m256i *)(ip),X) #define STORE(out,X,Y) (ST(out,LOW(Y,X)), ST(out+32,HIGH(Y,X))) #define STORE_ALT(out,X,Y) (ST(out,LOW(X,Y)), ST(out+32,HIGH(X,Y))) #define XOR_STORE(in,out,X,Y) (ST(out,XOR(LD(in),LOW(Y,X))), ST(out+32,XOR(LD(in+32),HIGH(Y,X)))) #define XOR_STORE_ALT(in,out,X,Y) (ST(out,XOR(LD(in),LOW(X,Y))), ST(out+32,XOR(LD(in+32),HIGH(X,Y)))) #define SHFL _mm256_shuffle_epi8 #define R8 SET(0x080f0e0d0c0b0a09LL,0x0007060504030201LL,0x080f0e0d0c0b0a09LL,0x0007060504030201LL) #define L8 SET(0x0e0d0c0b0a09080fLL,0x0605040302010007LL,0x0e0d0c0b0a09080fLL,0x0605040302010007LL) #define ROL8(X) (SHFL(X,L8)) #define ROR8(X) (SHFL(X,R8)) #define ROL(X,r) (XOR(SL(X,r),SR(X,(64-r)))) #define ROR(X,r) (XOR(SR(X,r),SL(X,(64-r)))) #define R(X,Y,k) (X=XOR(ADD(ROR8(X),Y),k), Y=XOR(ROL(Y,3),X)) #define Rx4(X,Y,k) (R(X[0],Y[0],k)) #define Rx8(X,Y,k) (R(X[0],Y[0],k), R(X[1],Y[1],k)) #define Rx12(X,Y,k) (R(X[0],Y[0],k), R(X[1],Y[1],k), R(X[2],Y[2],k)) #define Rx16(X,Y,k) (X[0]=ROR8(X[0]), X[0]=ADD(X[0],Y[0]), X[1]=ROR8(X[1]), X[1]=ADD(X[1],Y[1]), \ X[2]=ROR8(X[2]), X[2]=ADD(X[2],Y[2]), X[3]=ROR8(X[3]), X[3]=ADD(X[3],Y[3]), \ X[0]=XOR(X[0],k), X[1]=XOR(X[1],k), X[2]=XOR(X[2],k), X[3]=XOR(X[3],k), \ Z[0]=Y[0], Z[1]=Y[1], Z[2]=Y[2], Z[3]=Y[3], \ Z[0]=SL(Z[0],3), Y[0]=SR(Y[0],61), Z[1]=SL(Z[1],3), Y[1]=SR(Y[1],61), \ Z[2]=SL(Z[2],3), Y[2]=SR(Y[2],61), Z[3]=SL(Z[3],3), Y[3]=SR(Y[3],61), \ Y[0]=XOR(Y[0],Z[0]), Y[1]=XOR(Y[1],Z[1]), Y[2]=XOR(Y[2],Z[2]), Y[3]=XOR(Y[3],Z[3]), \ Y[0]=XOR(X[0],Y[0]), Y[1]=XOR(X[1],Y[1]), Y[2]=XOR(X[2],Y[2]), Y[3]=XOR(X[3],Y[3])) #define Rx1(x,y,k) (x[0]=RCS(x[0],8), x[0]+=y[0], x[0]^=k, y[0]=LCS(y[0],3), y[0]^=x[0]) #define Rx1b(x,y,k) (x=RCS(x,8), x+=y, x^=k, y=LCS(y,3), y^=x) #define Rx2(x,y,k) (x[0]=RCS(x[0],8), x[1]=RCS(x[1],8), x[0]+=y[0], x[1]+=y[1], \ x[0]^=k, x[1]^=k, y[0]=LCS(y[0],3), y[1]=LCS(y[1],3), y[0]^=x[0], y[1]^=x[1]) #define Encrypt_128(X,Y,k,n) (Rx##n(X,Y,k[0]), Rx##n(X,Y,k[1]), Rx##n(X,Y,k[2]), Rx##n(X,Y,k[3]), Rx##n(X,Y,k[4]), Rx##n(X,Y,k[5]), Rx##n(X,Y,k[6]), Rx##n(X,Y,k[7]), \ Rx##n(X,Y,k[8]), Rx##n(X,Y,k[9]), Rx##n(X,Y,k[10]), Rx##n(X,Y,k[11]), Rx##n(X,Y,k[12]), Rx##n(X,Y,k[13]), Rx##n(X,Y,k[14]), Rx##n(X,Y,k[15]), \ Rx##n(X,Y,k[16]), Rx##n(X,Y,k[17]), Rx##n(X,Y,k[18]), Rx##n(X,Y,k[19]), Rx##n(X,Y,k[20]), Rx##n(X,Y,k[21]), Rx##n(X,Y,k[22]), Rx##n(X,Y,k[23]), \ Rx##n(X,Y,k[24]), Rx##n(X,Y,k[25]), Rx##n(X,Y,k[26]), Rx##n(X,Y,k[27]), Rx##n(X,Y,k[28]), Rx##n(X,Y,k[29]), Rx##n(X,Y,k[30]), Rx##n(X,Y,k[31])) #define Encrypt_256(X,Y,k,n) (Encrypt_128(X,Y,k,n), \ Rx##n(X,Y,k[32]), Rx##n(X,Y,k[33])) #define RK(X,Y,k,key,i) (SET1(k[i],Y), key[i]=Y, X=RCS(X,8), X+=Y, X^=i, Y=LCS(Y,3), Y^=X) #define EK(A,B,C,D,k,key) (RK(B,A,k,key,0), RK(C,A,k,key,1), RK(D,A,k,key,2), RK(B,A,k,key,3), RK(C,A,k,key,4), RK(D,A,k,key,5), RK(B,A,k,key,6), \ RK(C,A,k,key,7), RK(D,A,k,key,8), RK(B,A,k,key,9), RK(C,A,k,key,10), RK(D,A,k,key,11), RK(B,A,k,key,12), RK(C,A,k,key,13), \ RK(D,A,k,key,14), RK(B,A,k,key,15), RK(C,A,k,key,16), RK(D,A,k,key,17), RK(B,A,k,key,18), RK(C,A,k,key,19), RK(D,A,k,key,20), \ RK(B,A,k,key,21), RK(C,A,k,key,22), RK(D,A,k,key,23), RK(B,A,k,key,24), RK(C,A,k,key,25), RK(D,A,k,key,26), RK(B,A,k,key,27), \ RK(C,A,k,key,28), RK(D,A,k,key,29), RK(B,A,k,key,30), RK(C,A,k,key,31), RK(D,A,k,key,32), RK(B,A,k,key,33)) #define Encrypt_Dispatcher(keysize) \ u64 x[2], y[2]; \ u256 X[4], Y[4], Z[4]; \ \ if(numbytes == 16) { \ x[0] = nonce[1]; y[0] = nonce[0]; nonce[0]++; \ Encrypt_##keysize(x, y, ctx->key, 1); \ ((u64 *)out)[1] = x[0]; ((u64 *)out)[0] = y[0]; \ return 0; \ } \ \ if(numbytes == 32) { \ x[0] = nonce[1]; y[0] = nonce[0]; nonce[0]++; \ x[1] = nonce[1]; y[1] = nonce[0]; nonce[0]++; \ Encrypt_##keysize(x , y, ctx->key, 2); \ ((u64 *)out)[1] = x[0] ^ ((u64 *)in)[1]; ((u64 *)out)[0] = y[0] ^ ((u64 *)in)[0]; \ ((u64 *)out)[3] = x[1] ^ ((u64 *)in)[3]; ((u64 *)out)[2] = y[1] ^ ((u64 *)in)[2]; \ return 0; \ } \ \ SET1(X[0], nonce[1]); SET4(Y[0], nonce[0]); \ \ if(numbytes == 64) \ Encrypt_##keysize(X, Y, ctx->rk, 4); \ else { \ X[1] = X[0]; \ Y[1] = ADD(Y[0], _four); \ if(numbytes == 128) \ Encrypt_##keysize(X, Y, ctx->rk, 8); \ else { \ X[2] = X[0]; \ Y[2] = ADD(Y[1], _four); \ if(numbytes == 192) \ Encrypt_##keysize(X, Y, ctx->rk, 12); \ else { \ X[3] = X[0]; \ Y[3] = ADD(Y[2], _four); \ Encrypt_##keysize(X, Y, ctx->rk, 16); \ } \ } \ } \ \ nonce[0] += (numbytes >> 4); \ \ XOR_STORE(in, out, X[0], Y[0]); \ if (numbytes >= 128) \ XOR_STORE(in + 64, out + 64, X[1], Y[1]); \ if(numbytes >= 192) \ XOR_STORE(in + 128, out + 128, X[2], Y[2]); \ if(numbytes >= 256) \ XOR_STORE(in + 192, out + 192, X[3], Y[3]); \ \ return 0 static int speck_encrypt_xor(unsigned char *out, const unsigned char *in, u64 nonce[], speck_context_t *ctx, int numbytes) { if(ctx->keysize == 256) { Encrypt_Dispatcher(256); } else { Encrypt_Dispatcher(128); } } static int internal_speck_ctr(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *n, speck_context_t *ctx) { int i; u64 nonce[2]; unsigned char block[16]; u64 * const block64 = (u64 *)block; if (!inlen) return 0; nonce[0] = ((u64 *)n)[0]; nonce[1] = ((u64 *)n)[1]; while(inlen >= 256) { speck_encrypt_xor(out, in, nonce, ctx, 256); in += 256; inlen -= 256; out += 256; } if(inlen >= 192) { speck_encrypt_xor(out, in, nonce, ctx, 192); in += 192; inlen -= 192; out += 192; } if(inlen >= 128) { speck_encrypt_xor(out, in, nonce, ctx, 128); in += 128; inlen -= 128; out += 128; } if(inlen >= 64) { speck_encrypt_xor(out, in, nonce, ctx, 64); in += 64; inlen -= 64; out += 64; } if(inlen >= 32) { speck_encrypt_xor(out, in, nonce, ctx, 32); in += 32; inlen -= 32; out += 32; } if(inlen >= 16) { speck_encrypt_xor(block, in, nonce, ctx, 16); ((u64 *)out)[0] = block64[0] ^ ((u64 *)in)[0]; ((u64 *)out)[1] = block64[1] ^ ((u64 *)in)[1]; in += 16; inlen -= 16; out += 16; } if(inlen > 0) { speck_encrypt_xor(block, in, nonce, ctx, 16); for(i = 0; i < inlen; i++) out[i] = block[i] ^ in[i]; } return 0; } static int speck_expand_key (speck_context_t *ctx, const unsigned char *k, int keysize) { u64 K[4]; size_t i; for(i = 0; i < (keysize >> 6); i++) K[i] = ((u64 *)k)[i]; // 128 bit has only two keys A and B thus replacing both C and D with B then if(keysize == 128) { EK(K[0], K[1], K[1], K[1], ctx->rk, ctx->key); } else { EK(K[0], K[1], K[2], K[3], ctx->rk, ctx->key); } ctx->keysize = keysize; return 0; } #elif defined (__SSE2__) // SSE support --------------------------------------------------------------------------- #define LCS(x,r) (((x)<>(64-r))) #define RCS(x,r) (((x)>>r)|((x)<<(64-r))) #define XOR _mm_xor_si128 #define AND _mm_and_si128 #define ADD _mm_add_epi64 #define SL _mm_slli_epi64 #define SR _mm_srli_epi64 #define _q SET(0x1,0x0) #define _two SET(0x2,0x2) #define SET _mm_set_epi64x #define SET1(X,c) (X=SET(c,c)) #define SET2(X,c) (X=SET(c,c), X=ADD(X,_q)) #define LOW _mm_unpacklo_epi64 #define HIGH _mm_unpackhi_epi64 #define LD(ip) _mm_loadu_si128((__m128i *)(ip)) #define ST(ip,X) _mm_storeu_si128((__m128i *)(ip),X) #define STORE(out,X,Y) (ST(out,LOW(Y,X)), ST(out+16,HIGH(Y,X))) #define STORE_ALT(out,X,Y) (ST(out,LOW(X,Y)), ST(out+16,HIGH(X,Y))) #define XOR_STORE(in,out,X,Y) (ST(out,XOR(LD(in),LOW(Y,X))), ST(out+16,XOR(LD(in+16),HIGH(Y,X)))) #define XOR_STORE_ALT(in,out,X,Y) (ST(out,XOR(LD(in),LOW(X,Y))), ST(out+16,XOR(LD(in+16),HIGH(X,Y)))) #define ROL(X,r) (XOR(SL(X,r),SR(X,(64-r)))) #define ROR(X,r) (XOR(SR(X,r),SL(X,(64-r)))) #if defined (__SSSE3__) // even SSSE3 ------------------------------- #define SHFL _mm_shuffle_epi8 #define R8 _mm_set_epi64x(0x080f0e0d0c0b0a09LL,0x0007060504030201LL) #define L8 _mm_set_epi64x(0x0e0d0c0b0a09080fLL,0x0605040302010007LL) #define ROL8(X) (SHFL(X,L8)) #define ROR8(X) (SHFL(X,R8)) #else // regular SSE2 ------------------------------------------------ #define ROL8(X) (ROL(X,8)) #define ROR8(X) (ROR(X,8)) #endif // SSS3 vs. SSE2 ---------------------------------------------- #define R(X,Y,k) (X=XOR(ADD(ROR8(X),Y),k), Y=XOR(ROL(Y,3),X)) #define Rx2(X,Y,k) (R(X[0],Y[0],k)) #define Rx4(X,Y,k) (R(X[0],Y[0],k), R(X[1],Y[1],k)) #define Rx6(X,Y,k) (R(X[0],Y[0],k), R(X[1],Y[1],k), R(X[2],Y[2],k)) #define Rx8(X,Y,k) (X[0]=ROR8(X[0]), X[0]=ADD(X[0],Y[0]), X[1]=ROR8(X[1]), X[1]=ADD(X[1],Y[1]), \ X[2]=ROR8(X[2]), X[2]=ADD(X[2],Y[2]), X[3]=ROR8(X[3]), X[3]=ADD(X[3],Y[3]), \ X[0]=XOR(X[0],k), X[1]=XOR(X[1],k), X[2]=XOR(X[2],k), X[3]=XOR(X[3],k), \ Z[0]=Y[0], Z[1]=Y[1], Z[2]=Y[2], Z[3]=Y[3], \ Z[0]=SL(Z[0],3), Y[0]=SR(Y[0],61), Z[1]=SL(Z[1],3), Y[1]=SR(Y[1],61), \ Z[2]=SL(Z[2],3), Y[2]=SR(Y[2],61), Z[3]=SL(Z[3],3), Y[3]=SR(Y[3],61), \ Y[0]=XOR(Y[0],Z[0]), Y[1]=XOR(Y[1],Z[1]), Y[2]=XOR(Y[2],Z[2]), Y[3]=XOR(Y[3],Z[3]), \ Y[0]=XOR(X[0],Y[0]), Y[1]=XOR(X[1],Y[1]), Y[2]=XOR(X[2],Y[2]), Y[3]=XOR(X[3],Y[3])) #define Rx1(x,y,k) (x[0]=RCS(x[0],8), x[0]+=y[0], x[0]^=k, y[0]=LCS(y[0],3), y[0]^=x[0]) #define Rx1b(x,y,k) (x=RCS(x,8), x+=y, x^=k, y=LCS(y,3), y^=x) #define Encrypt_128(X,Y,k,n) (Rx##n(X,Y,k[0]), Rx##n(X,Y,k[1]), Rx##n(X,Y,k[2]), Rx##n(X,Y,k[3]), Rx##n(X,Y,k[4]), Rx##n(X,Y,k[5]), Rx##n(X,Y,k[6]), Rx##n(X,Y,k[7]), \ Rx##n(X,Y,k[8]), Rx##n(X,Y,k[9]), Rx##n(X,Y,k[10]), Rx##n(X,Y,k[11]), Rx##n(X,Y,k[12]), Rx##n(X,Y,k[13]), Rx##n(X,Y,k[14]), Rx##n(X,Y,k[15]), \ Rx##n(X,Y,k[16]), Rx##n(X,Y,k[17]), Rx##n(X,Y,k[18]), Rx##n(X,Y,k[19]), Rx##n(X,Y,k[20]), Rx##n(X,Y,k[21]), Rx##n(X,Y,k[22]), Rx##n(X,Y,k[23]), \ Rx##n(X,Y,k[24]), Rx##n(X,Y,k[25]), Rx##n(X,Y,k[26]), Rx##n(X,Y,k[27]), Rx##n(X,Y,k[28]), Rx##n(X,Y,k[29]), Rx##n(X,Y,k[30]), Rx##n(X,Y,k[31])) #define Encrypt_256(X,Y,k,n) (Encrypt_128(X,Y,k,n), \ Rx##n(X,Y,k[32]), Rx##n(X,Y,k[33])) #define RK(X,Y,k,key,i) (SET1(k[i],Y), key[i]=Y, X=RCS(X,8), X+=Y, X^=i, Y=LCS(Y,3), Y^=X) #define EK(A,B,C,D,k,key) (RK(B,A,k,key,0), RK(C,A,k,key,1), RK(D,A,k,key,2), RK(B,A,k,key,3), RK(C,A,k,key,4), RK(D,A,k,key,5), RK(B,A,k,key,6), \ RK(C,A,k,key,7), RK(D,A,k,key,8), RK(B,A,k,key,9), RK(C,A,k,key,10), RK(D,A,k,key,11), RK(B,A,k,key,12), RK(C,A,k,key,13), \ RK(D,A,k,key,14), RK(B,A,k,key,15), RK(C,A,k,key,16), RK(D,A,k,key,17), RK(B,A,k,key,18), RK(C,A,k,key,19), RK(D,A,k,key,20), \ RK(B,A,k,key,21), RK(C,A,k,key,22), RK(D,A,k,key,23), RK(B,A,k,key,24), RK(C,A,k,key,25), RK(D,A,k,key,26), RK(B,A,k,key,27), \ RK(C,A,k,key,28), RK(D,A,k,key,29), RK(B,A,k,key,30), RK(C,A,k,key,31), RK(D,A,k,key,32), RK(B,A,k,key,33)) #define Encrypt_Dispatcher(keysize) \ u64 x[2], y[2]; \ u128 X[4], Y[4], Z[4]; \ \ if(numbytes == 16) { \ x[0] = nonce[1]; y[0] = nonce[0]; nonce[0]++; \ Encrypt_##keysize(x, y, ctx.key, 1); \ ((u64 *)out)[1] = x[0]; ((u64 *)out)[0] = y[0]; \ return 0; \ } \ \ SET1(X[0], nonce[1]); SET2(Y[0], nonce[0]); \ \ if(numbytes == 32) \ Encrypt_##keysize(X, Y, ctx.rk, 2); \ else { \ X[1] = X[0]; Y[1] = ADD(Y[0], _two); \ if(numbytes == 64) \ Encrypt_##keysize(X, Y, ctx.rk, 4); \ else { \ X[2] = X[0]; Y[2] = ADD(Y[1], _two); \ if(numbytes == 96) \ Encrypt_##keysize(X, Y, ctx.rk, 6); \ else { \ X[3] = X[0]; Y[3] = ADD(Y[2], _two); \ Encrypt_##keysize(X, Y, ctx.rk, 8); \ } \ } \ } \ \ nonce[0] += (numbytes >> 4); \ \ XOR_STORE(in, out, X[0], Y[0]); \ if(numbytes >= 64) \ XOR_STORE(in + 32, out + 32, X[1], Y[1]); \ if(numbytes >= 96) \ XOR_STORE(in + 64, out + 64, X[2], Y[2]); \ if(numbytes >= 128) \ XOR_STORE(in + 96, out + 96, X[3], Y[3]); \ \ return 0 // attention: ctx is provided by value as it is faster in this case, astonishingly static int speck_encrypt_xor (unsigned char *out, const unsigned char *in, u64 nonce[], const speck_context_t ctx, int numbytes) { if(ctx.keysize == 256) { Encrypt_Dispatcher(256); } else { Encrypt_Dispatcher(128); } } // attention: ctx is provided by value as it is faster in this case, astonishingly static int internal_speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *n, const speck_context_t ctx) { int i; u64 nonce[2]; unsigned char block[16]; u64 * const block64 = (u64 *)block; if(!inlen) return 0; nonce[0] = ((u64 *)n)[0]; nonce[1] = ((u64 *)n)[1]; while(inlen >= 128) { speck_encrypt_xor(out, in, nonce, ctx, 128); in += 128; inlen -= 128; out += 128; } if(inlen >= 96) { speck_encrypt_xor(out, in, nonce, ctx, 96); in += 96; inlen -= 96; out += 96; } if(inlen >= 64) { speck_encrypt_xor(out, in, nonce, ctx, 64); in += 64; inlen -= 64; out += 64; } if(inlen >= 32) { speck_encrypt_xor(out, in, nonce, ctx, 32); in += 32; inlen -= 32; out += 32; } if(inlen >= 16) { speck_encrypt_xor(block, in, nonce, ctx, 16); ((u64 *)out)[0] = block64[0] ^ ((u64 *)in)[0]; ((u64 *)out)[1] = block64[1] ^ ((u64 *)in)[1]; in += 16; inlen -= 16; out += 16; } if(inlen > 0) { speck_encrypt_xor (block, in, nonce, ctx, 16); for(i = 0; i < inlen; i++) out[i] = block[i] ^ in[i]; } return 0; } static int speck_expand_key (speck_context_t *ctx, const unsigned char *k, int keysize) { u64 K[4]; size_t i; for(i = 0; i < (keysize >> 6 ); i++) K[i] = ((u64 *)k)[i]; // 128 bit has only two keys A and B thus replacing both C and D with B then if(keysize == 128) { EK(K[0], K[1], K[1], K[1], ctx->rk, ctx->key); } else { EK(K[0], K[1], K[2], K[3], ctx->rk, ctx->key); } ctx->keysize = keysize; return 0; } #elif defined (__ARM_NEON) && defined (SPECK_ARM_NEON) // NEON support --------------------------------------- #define LCS(x,r) (((x)<>(64-r))) #define RCS(x,r) (((x)>>r)|((x)<<(64-r))) #define XOR veorq_u64 #define AND vandq_u64 #define ADD vaddq_u64 #define SL vshlq_n_u64 #define SR vshrq_n_u64 #define SET(a,b) vcombine_u64((uint64x1_t)(a),(uint64x1_t)(b)) #define SET1(X,c) (X=SET(c,c)) #define SET2(X,c) (SET1(X,c), X=ADD(X,SET(0x1ll,0x0ll)),c+=2) #define LOW(Z) vgetq_lane_u64(Z,0) #define HIGH(Z) vgetq_lane_u64(Z,1) #define STORE(ip,X,Y) (((u64 *)(ip))[0]=HIGH(Y), ((u64 *)(ip))[1]=HIGH(X), ((u64 *)(ip))[2]=LOW(Y), ((u64 *)(ip))[3]=LOW(X)) #define XOR_STORE(in,out,X,Y) (Y=XOR(Y,SET(((u64 *)(in))[2],((u64 *)(in))[0])), X=XOR(X,SET(((u64 *)(in))[3],((u64 *)(in))[1])), STORE(out,X,Y)) #define ROR(X,r) vsriq_n_u64(SL(X,(64-r)),X,r) #define ROL(X,r) ROR(X,(64-r)) #define tableR vcreate_u8(0x0007060504030201LL) #define tableL vcreate_u8(0x0605040302010007LL) #define ROR8(X) SET(vtbl1_u8((uint8x8_t)vget_low_u64(X),tableR), vtbl1_u8((uint8x8_t)vget_high_u64(X),tableR)) #define ROL8(X) SET(vtbl1_u8((uint8x8_t)vget_low_u64(X),tableL), vtbl1_u8((uint8x8_t)vget_high_u64(X),tableL)) #define R(X,Y,k) (X=XOR(ADD(ROR8(X),Y),k), Y=XOR(ROL(Y,3),X)) #define Rx2(X,Y,k) (R(X[0],Y[0],k)) #define Rx4(X,Y,k) (R(X[0],Y[0],k), R(X[1],Y[1],k)) #define Rx6(X,Y,k) (R(X[0],Y[0],k), R(X[1],Y[1],k), R(X[2],Y[2],k)) #define Rx8(X,Y,k) (X[0]=ROR8(X[0]), X[0]=ADD(X[0],Y[0]), X[0]=XOR(X[0],k), X[1]=ROR8(X[1]), X[1]=ADD(X[1],Y[1]), X[1]=XOR(X[1],k), \ X[2]=ROR8(X[2]), X[2]=ADD(X[2],Y[2]), X[2]=XOR(X[2],k), X[3]=ROR8(X[3]), X[3]=ADD(X[3],Y[3]), X[3]=XOR(X[3],k), \ Z[0]=SL(Y[0],3), Z[1]=SL(Y[1],3), Z[2]=SL(Y[2],3), Z[3]=SL(Y[3],3), \ Y[0]=SR(Y[0],61), Y[1]=SR(Y[1],61), Y[2]=SR(Y[2],61), Y[3]=SR(Y[3],61), \ Y[0]=XOR(Y[0],Z[0]), Y[1]=XOR(Y[1],Z[1]), Y[2]=XOR(Y[2],Z[2]), Y[3]=XOR(Y[3],Z[3]), \ Y[0]=XOR(X[0],Y[0]), Y[1]=XOR(X[1],Y[1]), Y[2]=XOR(X[2],Y[2]), Y[3]=XOR(X[3],Y[3])) #define Rx1(x,y,k) (x[0]=RCS(x[0],8), x[0]+=y[0], x[0]^=k, y[0]=LCS(y[0],3), y[0]^=x[0]) #define Rx1b(x,y,k) (x=RCS(x,8), x+=y, x^=k, y=LCS(y,3), y^=x) #define Encrypt_128(X,Y,k,n) (Rx##n(X,Y,k[0]), Rx##n(X,Y,k[1]), Rx##n(X,Y,k[2]), Rx##n(X,Y,k[3]), Rx##n(X,Y,k[4]), Rx##n(X,Y,k[5]), Rx##n(X,Y,k[6]), Rx##n(X,Y,k[7]), \ Rx##n(X,Y,k[8]), Rx##n(X,Y,k[9]), Rx##n(X,Y,k[10]), Rx##n(X,Y,k[11]), Rx##n(X,Y,k[12]), Rx##n(X,Y,k[13]), Rx##n(X,Y,k[14]), Rx##n(X,Y,k[15]), \ Rx##n(X,Y,k[16]), Rx##n(X,Y,k[17]), Rx##n(X,Y,k[18]), Rx##n(X,Y,k[19]), Rx##n(X,Y,k[20]), Rx##n(X,Y,k[21]), Rx##n(X,Y,k[22]), Rx##n(X,Y,k[23]), \ Rx##n(X,Y,k[24]), Rx##n(X,Y,k[25]), Rx##n(X,Y,k[26]), Rx##n(X,Y,k[27]), Rx##n(X,Y,k[28]), Rx##n(X,Y,k[29]), Rx##n(X,Y,k[30]), Rx##n(X,Y,k[31])) #define Encrypt_256(X,Y,k,n) (Encrypt_128(X,Y,k,n), \ Rx##n(X,Y,k[32]), Rx##n(X,Y,k[33])) #define RK(X,Y,k,key,i) (SET1(k[i],Y), key[i]=Y, X=RCS(X,8), X+=Y, X^=i, Y=LCS(Y,3), Y^=X) #define EK(A,B,C,D,k,key) (RK(B,A,k,key,0), RK(C,A,k,key,1), RK(D,A,k,key,2), RK(B,A,k,key,3), RK(C,A,k,key,4), RK(D,A,k,key,5), RK(B,A,k,key,6), \ RK(C,A,k,key,7), RK(D,A,k,key,8), RK(B,A,k,key,9), RK(C,A,k,key,10), RK(D,A,k,key,11), RK(B,A,k,key,12), RK(C,A,k,key,13), \ RK(D,A,k,key,14), RK(B,A,k,key,15), RK(C,A,k,key,16), RK(D,A,k,key,17), RK(B,A,k,key,18), RK(C,A,k,key,19), RK(D,A,k,key,20), \ RK(B,A,k,key,21), RK(C,A,k,key,22), RK(D,A,k,key,23), RK(B,A,k,key,24), RK(C,A,k,key,25), RK(D,A,k,key,26), RK(B,A,k,key,27), \ RK(C,A,k,key,28), RK(D,A,k,key,29), RK(B,A,k,key,30), RK(C,A,k,key,31), RK(D,A,k,key,32), RK(B,A,k,key,33)) #define Encrypt_Dispatcher(keysize) \ u64 x[2], y[2]; \ u128 X[4], Y[4], Z[4]; \ \ if(numbytes == 16) { \ x[0] = nonce[1]; y[0]=nonce[0]; nonce[0]++; \ Encrypt_##keysize(x, y, ctx->key, 1); \ ((u64 *)out)[1] = x[0]; ((u64 *)out)[0] = y[0]; \ return 0; \ } \ \ SET1(X[0], nonce[1]); SET2(Y[0], nonce[0]); \ \ if(numbytes == 32) \ Encrypt_##keysize(X, Y, ctx->rk, 2); \ else { \ X[1] = X[0]; SET2(Y[1], nonce[0]); \ if(numbytes == 64) \ Encrypt_##keysize(X, Y, ctx->rk, 4); \ else { \ X[2] = X[0]; SET2(Y[2], nonce[0]); \ if(numbytes == 96) \ Encrypt_##keysize(X, Y, ctx->rk, 6); \ else { \ X[3] = X[0]; SET2(Y[3], nonce[0]); \ Encrypt_##keysize(X, Y, ctx->rk, 8); \ } \ } \ } \ \ XOR_STORE(in, out, X[0], Y[0]); \ if(numbytes >= 64) \ XOR_STORE(in + 32, out + 32, X[1], Y[1]); \ if(numbytes >= 96) \ XOR_STORE(in + 64, out + 64, X[2], Y[2]); \ if(numbytes >= 128) \ XOR_STORE(in + 96, out + 96, X[3], Y[3]); \ \ return 0 static int speck_encrypt_xor (unsigned char *out, const unsigned char *in, u64 nonce[], speck_context_t *ctx, int numbytes) { if(ctx->keysize == 256) { Encrypt_Dispatcher(256); } else { Encrypt_Dispatcher(128); } } static int internal_speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *n, speck_context_t *ctx) { int i; u64 nonce[2]; unsigned char block[16]; u64 *const block64 = (u64 *)block; if(!inlen) return 0; nonce[0] = ((u64 *)n)[0]; nonce[1] = ((u64 *)n)[1]; while(inlen >= 128) { speck_encrypt_xor(out, in, nonce, ctx, 128); in += 128; inlen -= 128; out += 128; } if(inlen >= 96) { speck_encrypt_xor(out, in, nonce, ctx, 96); in += 96; inlen -= 96; out += 96; } if(inlen >= 64) { speck_encrypt_xor(out, in, nonce, ctx, 64); in += 64; inlen -= 64; out += 64; } if(inlen >= 32) { speck_encrypt_xor(out, in, nonce, ctx, 32); in += 32; inlen -= 32; out += 32; } if(inlen >= 16) { speck_encrypt_xor(block, in, nonce, ctx, 16); ((u64 *)out)[0] = block64[0] ^ ((u64 *)in)[0]; ((u64 *)out)[1] = block64[1] ^ ((u64 *)in)[1]; in += 16; inlen -= 16; out += 16; } if(inlen > 0) { speck_encrypt_xor(block, in, nonce, ctx, 16); for(i = 0; i < inlen; i++) out[i] = block[i] ^ in[i]; } return 0; } static int speck_expand_key (speck_context_t *ctx, const unsigned char *k, int keysize) { u64 K[4]; size_t i; for(i = 0; i < (keysize >> 6); i++) K[i] = ((u64 *)k)[i]; // 128 bit has only two keys A and B thus replacing both C and D with B then if(keysize == 128) { EK(K[0], K[1], K[1], K[1], ctx->rk, ctx->key); } else { EK(K[0], K[1], K[2], K[3], ctx->rk, ctx->key); } ctx->keysize = keysize; return 0; } #else // plain C ---------------------------------------------------------------------------------------- #define ROR(x,r) (((x)>>(r))|((x)<<(64-(r)))) #define ROL(x,r) (((x)<<(r))|((x)>>(64-(r)))) #define R(x,y,k) (x=ROR(x,8), x+=y, x^=k, y=ROL(y,3), y^=x) static int speck_encrypt (u64 *u, u64 *v, speck_context_t *ctx, int numrounds) { u64 i, x = *u, y = *v; for(i = 0; i < numrounds; i++) R(x, y, ctx->key[i]); *u = x; *v = y; return 0; } static int internal_speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *n, speck_context_t *ctx) { u64 i, nonce[2], x, y, t; unsigned char *block = malloc(16); int numrounds = (ctx->keysize == 256)?34:32; if(!inlen) { free(block); return 0; } nonce[0] = htole64( ((u64*)n)[0] ); nonce[1] = htole64( ((u64*)n)[1] ); t=0; while(inlen >= 16) { x = nonce[1]; y = nonce[0]; nonce[0]++; speck_encrypt(&x, &y, ctx, numrounds); ((u64 *)out)[1+t] = htole64(x ^ ((u64 *)in)[1+t]); ((u64 *)out)[0+t] = htole64(y ^ ((u64 *)in)[0+t]); t += 2; inlen -= 16; } if(inlen > 0) { x = nonce[1]; y = nonce[0]; speck_encrypt(&x, &y, ctx, numrounds); ((u64 *)block)[1] = htole64(x); ((u64 *)block)[0] = htole64(y); for(i = 0; i < inlen; i++) out[i + 8*t] = block[i] ^ in[i + 8*t]; } free(block); return 0; } static int speck_expand_key (speck_context_t *ctx, const unsigned char *k, int keysize) { u64 K[4]; u64 i; for(i = 0; i < (keysize >> 6); i++) K[i] = htole64( ((u64 *)k)[i] ); for(i = 0; i < 33; i += 3) { ctx->key[i ] = K[0]; R(K[1], K[0], i ); if(keysize == 256) { ctx->key[i+1] = K[0]; R(K[2], K[0], i + 1); ctx->key[i+2] = K[0]; R(K[3], K[0], i + 2); } else { // counter the i += 3 to make the loop go one by one in this case // we can afford the unused 31 and 32 i -= 2; } } ctx->key[33] = K[0]; ctx->keysize = keysize; return 1; } #endif // AVX, SSE, NEON, plain C ------------------------------------------------------------------------ // this functions wraps the call to internal_speck_ctr functions which have slightly different // signature -- ctx by value for SSE with SPECK_CTX_BYVAL defined in speck.h, by name otherwise int speck_ctr (unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *n, speck_context_t *ctx) { return internal_speck_ctr(out, in, inlen, n, #if defined (SPECK_CTX_BYVAL) *ctx); #else ctx); #endif } // create context loaded with round keys ready for use, key size either 128 or 256 (bits) int speck_init (speck_context_t **ctx, const unsigned char *k, int keysize) { #if defined (SPECK_ALIGNED_CTX) *ctx = (speck_context_t*)_mm_malloc(sizeof(speck_context_t), SPECK_ALIGNED_CTX); #else *ctx = (speck_context_t*)calloc(1, sizeof(speck_context_t)); #endif if(!(*ctx)) { return -1; } return speck_expand_key(*ctx, k, keysize); } int speck_deinit (speck_context_t *ctx) { if(ctx) { #if defined (SPECK_ALIGNED_CTX) _mm_free(ctx); #else free(ctx); #endif } return 0; } // ---------------------------------------------------------------------------------------------------------------- // cipher SPECK -- 128 bit block size -- 128 bit key size -- ECB mode (decrypt only) // follows endianess rules as used in official implementation guide and NOT as in original 2013 cipher presentation // used for IV in header encryption (one block) and challenge encryption (user/password) // for now: just plain C -- probably no need for AVX, SSE, NEON #define ROTL64(x,r) (((x)<<(r))|((x)>>(64-(r)))) #define ROTR64(x,r) (((x)>>(r))|((x)<<(64-(r)))) #define DR128(x,y,k) (y^=x, y=ROTR64(y,3), x^=k, x-=y, x=ROTL64(x,8)) #define ER128(x,y,k) (x=(ROTR64(x,8)+y)^k, y=ROTL64(y,3)^x) int speck_128_decrypt (unsigned char *inout, speck_context_t *ctx) { u64 x, y; int i; x = le64toh( *(u64*)&inout[8] ); y = le64toh( *(u64*)&inout[0] ); for(i = 31; i >= 0; i--) DR128(x, y, ctx->key[i]); ((u64*)inout)[1] = htole64(x); ((u64*)inout)[0] = htole64(y); return 0; } int speck_128_encrypt (unsigned char *inout, speck_context_t *ctx) { u64 x, y; int i; x = le64toh( *(u64*)&inout[8] ); y = le64toh( *(u64*)&inout[0] ); for(i = 0; i < 32; i++) ER128(x, y, ctx->key[i]); ((u64*)inout)[1] = htole64(x); ((u64*)inout)[0] = htole64(y); return 0; } ntop-n2n-90215bd/src/supernode.c000066400000000000000000000574611422132035700164700ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* Supernode for n2n-2.x */ #include "n2n.h" #include "header_encryption.h" #define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) static n2n_sn_t sss_node; void close_tcp_connection (n2n_sn_t *sss, n2n_tcp_connection_t *conn); void calculate_shared_secrets (n2n_sn_t *sss); int load_allowed_sn_community (n2n_sn_t *sss); int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn_list); /** Help message to print if the command line arguments are not valid. */ static void help (int level) { if(level == 0) /* no help required */ return; printf("\n"); print_n2n_version(); if(level == 1) /* short help */ { printf(" basic usage: supernode (see supernode.conf)\n" "\n" " or supernode " "[optional parameters, at least one] " "\n " "\n technically, all parameters are optional, but the supernode executable" "\n requires at least one parameter to run, .e.g. -v or -f, as otherwise this" "\n short help text is displayed" "\n\n -h shows a quick reference including all available options" "\n --help gives a detailed parameter description" "\n man files for n2n, edge, and superndode contain in-depth information" "\n\n"); } else if(level == 2) /* quick reference */ { printf(" general usage: supernode (see supernode.conf)\n" "\n" " or supernode " "[-p ] " "\n " "[-F ] " "\n options for under- " "[-l ] " "\n lying connection " #ifdef SN_MANUAL_MAC "[-m ] " #endif "[-M] " "[-V ] " "\n\n overlay network " "[-c ] " "\n configuration " "[-a -/] " "\n\n local options " #if defined(N2N_HAVE_DAEMON) "[-f] " #endif "[-t ] " "\n " "[--management-password ] " "[-v] " #ifndef WIN32 "\n " "[-u ]" "[-g ]" #endif "\n\n meaning of the " "[-M] disable MAC and IP address spoofing protection" "\n flag options " #if defined(N2N_HAVE_DAEMON) "[-f] do not fork but run in foreground" "\n " #endif "[-v] make more verbose, repeat as required" "\n " "\n technically, all parameters are optional, but the supernode executable" "\n requires at least one parameter to run, .e.g. -v or -f, as otherwise a" "\n short help text is displayed" "\n\n -h shows this quick reference including all available options" "\n --help gives a detailed parameter description" "\n man files for n2n, edge, and superndode contain in-depth information" "\n\n"); } else /* long help */ { printf(" general usage: supernode (see supernode.conf)\n" "\n" " or supernode [optional parameters, at least one]\n\n" ); printf (" OPTIONS FOR THE UNDERLYING NETWORK CONNECTION\n"); printf (" ---------------------------------------------\n\n"); printf(" -p | fixed local UDP port, defaults to %u\n", N2N_SN_LPORT_DEFAULT); printf(" -F | name of the supernode's federation, defaults to\n" " | '%s'\n", (char *)FEDERATION_NAME); printf(" -l | ip address or name, and port of known supernode\n"); #ifdef SN_MANUAL_MAC printf(" -m | fixed MAC address for the supernode, e.g.\n" " | '-m 10:20:30:40:50:60', random otherwise\n"); #endif printf(" -M | disable MAC and IP address spoofing protection for all\n" " | non-username-password-authenticating communities\n"); printf(" -V | sends a custom supernode version string of max 19 letters \n" " | length to edges, visible in their management port output\n"); printf ("\n"); printf (" TAP DEVICE AND OVERLAY NETWORK CONFIGURATION\n"); printf (" --------------------------------------------\n\n"); printf(" -c | file containing the allowed communities\n"); printf(" -a | subnet range for auto ip address service, e.g.\n" " | '-a 192.168.0.0-192.168.255.0/24', defaults\n" " | to '10.128.255.0-10.255.255.0/24'\n"); printf ("\n"); printf (" LOCAL OPTIONS\n"); printf (" -------------\n\n"); #if defined(N2N_HAVE_DAEMON) printf(" -f | do not fork and run as a daemon, rather run in foreground\n"); #endif printf(" -t | management UDP port, for multiple supernodes on a machine,\n" " | defaults to %u\n", N2N_SN_MGMT_PORT); printf(" --management_... | management port password, defaults to '%s'\n" " ...password | \n", N2N_MGMT_PASSWORD); printf(" -v | make more verbose, repeat as required\n"); #ifndef WIN32 printf(" -u | numeric user ID to use when privileges are dropped\n"); printf(" -g | numeric group ID to use when privileges are dropped\n"); #endif printf("\n technically, all parameters are optional, but the supernode executable" "\n requires at least one parameter to run, .e.g. -v or -f, as otherwise a" "\n short help text is displayed" "\n\n -h shows a quick reference including all available options" "\n --help gives this detailed parameter description" "\n man files for n2n, edge, and superndode contain in-depth information" "\n\n"); } exit(0); } /* *************************************************** */ static int setOption (int optkey, char *_optarg, n2n_sn_t *sss) { //traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : ""); switch(optkey) { case 'p': /* local-port */ sss->lport = atoi(_optarg); if(sss->lport == 0) traceEvent(TRACE_WARNING, "bad local port format, defaulting to %u", N2N_SN_LPORT_DEFAULT); // default is made sure in sn_init() break; case 't': /* mgmt-port */ sss->mport = atoi(_optarg); if(sss->mport == 0) traceEvent(TRACE_WARNING, "bad management port format, defaulting to %u", N2N_SN_MGMT_PORT); // default is made sure in sn_init() break; case 'l': { /* supernode:port */ n2n_sock_t *socket; struct peer_info *anchor_sn; size_t length; int rv = -1; int skip_add; char *double_column = strchr(_optarg, ':'); length = strlen(_optarg); if(length >= N2N_EDGE_SN_HOST_SIZE) { traceEvent(TRACE_WARNING, "size of -l argument too long: %zu; maximum size is %d", length, N2N_EDGE_SN_HOST_SIZE); return 1; } if(!double_column) { traceEvent(TRACE_WARNING, "invalid -l format, missing port"); return 1; } socket = (n2n_sock_t *)calloc(1, sizeof(n2n_sock_t)); rv = supernode2sock(socket, _optarg); if(rv < -2) { /* we accept resolver failure as it might resolve later */ traceEvent(TRACE_WARNING, "invalid supernode parameter"); free(socket); return 1; } if(sss->federation != NULL) { skip_add = SN_ADD; anchor_sn = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), socket, null_mac, &skip_add); if(anchor_sn != NULL) { anchor_sn->ip_addr = calloc(1, N2N_EDGE_SN_HOST_SIZE); if(anchor_sn->ip_addr) { strncpy(anchor_sn->ip_addr, _optarg, N2N_EDGE_SN_HOST_SIZE - 1); memcpy(&(anchor_sn->sock), socket, sizeof(n2n_sock_t)); memcpy(anchor_sn->mac_addr, null_mac, sizeof(n2n_mac_t)); anchor_sn->purgeable = SN_UNPURGEABLE; anchor_sn->last_valid_time_stamp = initial_time_stamp(); } } } free(socket); break; } case 'a': { dec_ip_str_t ip_min_str = {'\0'}; dec_ip_str_t ip_max_str = {'\0'}; in_addr_t net_min, net_max; uint8_t bitlen; uint32_t mask; if(sscanf(_optarg, "%15[^\\-]-%15[^/]/%hhu", ip_min_str, ip_max_str, &bitlen) != 3) { traceEvent(TRACE_WARNING, "bad net-net/bit format '%s'.", _optarg); return 2; } net_min = inet_addr(ip_min_str); net_max = inet_addr(ip_max_str); mask = bitlen2mask(bitlen); if((net_min == (in_addr_t)(-1)) || (net_min == INADDR_NONE) || (net_min == INADDR_ANY) || (net_max == (in_addr_t)(-1)) || (net_max == INADDR_NONE) || (net_max == INADDR_ANY) || (ntohl(net_min) > ntohl(net_max)) || ((ntohl(net_min) & ~mask) != 0) || ((ntohl(net_max) & ~mask) != 0)) { traceEvent(TRACE_WARNING, "bad network range '%s...%s/%u' in '%s', defaulting to '%s...%s/%d'", ip_min_str, ip_max_str, bitlen, _optarg, N2N_SN_MIN_AUTO_IP_NET_DEFAULT, N2N_SN_MAX_AUTO_IP_NET_DEFAULT, N2N_SN_AUTO_IP_NET_BIT_DEFAULT); return 2; } if((bitlen > 30) || (bitlen == 0)) { traceEvent(TRACE_WARNING, "bad prefix '%hhu' in '%s', defaulting to '%s...%s/%d'", bitlen, _optarg, N2N_SN_MIN_AUTO_IP_NET_DEFAULT, N2N_SN_MAX_AUTO_IP_NET_DEFAULT, N2N_SN_AUTO_IP_NET_BIT_DEFAULT); return 2; } traceEvent(TRACE_NORMAL, "the network range for community ip address service is '%s...%s/%hhu'", ip_min_str, ip_max_str, bitlen); sss->min_auto_ip_net.net_addr = ntohl(net_min); sss->min_auto_ip_net.net_bitlen = bitlen; sss->max_auto_ip_net.net_addr = ntohl(net_max); sss->max_auto_ip_net.net_bitlen = bitlen; break; } #ifndef WIN32 case 'u': /* unprivileged uid */ sss->userid = atoi(_optarg); break; case 'g': /* unprivileged uid */ sss->groupid = atoi(_optarg); break; #endif case 'F': { /* federation name */ snprintf(sss->federation->community, N2N_COMMUNITY_SIZE - 1 ,"*%s", _optarg); sss->federation->community[N2N_COMMUNITY_SIZE - 1] = '\0'; break; } #ifdef SN_MANUAL_MAC case 'm': {/* MAC address */ str2mac(sss->mac_addr, _optarg); // clear multicast bit sss->mac_addr[0] &= ~0x01; // set locally-assigned bit sss->mac_addr[0] |= 0x02; break; } #endif case 'M': /* override spoofing protection */ sss->override_spoofing_protection = 1; break; case 'V': /* version text */ strncpy(sss->version, _optarg, sizeof(n2n_version_t)); sss->version[sizeof(n2n_version_t) - 1] = '\0'; break; case 'c': /* community file */ sss->community_file = calloc(1, strlen(_optarg) + 1); if(sss->community_file) strcpy(sss->community_file, _optarg); break; case ']': /* password for management port */ { sss->mgmt_password_hash = pearson_hash_64((uint8_t*)_optarg, strlen(_optarg)); break; } #if defined(N2N_HAVE_DAEMON) case 'f': /* foreground */ sss->daemon = 0; break; #endif case 'h': /* quick reference */ return 2; case '@': /* long help */ return 3; case 'v': /* verbose */ setTraceLevel(getTraceLevel() + 1); break; default: traceEvent(TRACE_WARNING, "unknown option -%c:", (char) optkey); return 2; } return 0; } /* *********************************************** */ static const struct option long_options[] = { {"communities", required_argument, NULL, 'c'}, #if defined(N2N_HAVE_DAEMON) {"foreground", no_argument, NULL, 'f'}, #endif {"local-port", required_argument, NULL, 'p'}, {"mgmt-port", required_argument, NULL, 't'}, {"autoip", required_argument, NULL, 'a'}, {"verbose", no_argument, NULL, 'v'}, {"help", no_argument, NULL, '@'}, /* special character '@' to identify long help case */ {"management-password", required_argument, NULL, ']' }, /* ']' management port password */ {NULL, 0, NULL, 0} }; /* *************************************************** */ /* read command line options */ static int loadFromCLI (int argc, char * const argv[], n2n_sn_t *sss) { u_char c; while((c = getopt_long(argc, argv, "p:l:t:a:c:F:vhMV:" #ifdef SN_MANUAL_MAC "m:" #endif #if defined(N2N_HAVE_DAEMON) "f" #endif #ifndef WIN32 "u:g:" #endif , long_options, NULL)) != '?') { if(c == 255) { break; } help(setOption(c, optarg, sss)); } return 0; } /* *************************************************** */ static char *trim (char *s) { char *end; while(isspace(s[0]) || (s[0] == '"') || (s[0] == '\'')) { s++; } if(s[0] == 0) { return s; } end = &s[strlen(s) - 1]; while(end > s && (isspace(end[0])|| (end[0] == '"') || (end[0] == '\''))) { end--; } end[1] = 0; return s; } /* *************************************************** */ /* parse the configuration file */ static int loadFromFile (const char *path, n2n_sn_t *sss) { char buffer[4096], *line; char *line_vec[3]; int tmp; FILE *fd; fd = fopen(path, "r"); if(fd == NULL) { traceEvent(TRACE_WARNING, "config file %s not found", path); return -1; } // we mess around with optind, better save it tmp = optind; while((line = fgets(buffer, sizeof(buffer), fd)) != NULL) { line = trim(line); if(strlen(line) < 2 || line[0] == '#') { continue; } // executable, cannot be omitted, content can be anything line_vec[0] = line; // first token, e.g. `-p`, eventually followed by a whitespace or '=' delimiter line_vec[1] = strtok(line, "\t ="); // separate parameter option, if present line_vec[2] = strtok(NULL, "\t "); // not to duplicate the option parser code, call loadFromCLI and pretend we have no option read yet optind = 0; // if separate second token present (optional argument, not part of first), then announce 3 vector members loadFromCLI(line_vec[2] ? 3 : 2, line_vec, sss); } fclose(fd); optind = tmp; return 0; } /* *************************************************** */ /* Add the federation to the communities list of a supernode */ static int add_federation_to_communities (n2n_sn_t *sss) { uint32_t num_communities = 0; if(sss->federation != NULL) { HASH_ADD_STR(sss->communities, community, sss->federation); num_communities = HASH_COUNT(sss->communities); traceEvent(TRACE_INFO, "added federation '%s' to the list of communities [total: %u]", (char*)sss->federation->community, num_communities); } return 0; } /* *************************************************** */ #ifdef __linux__ static void dump_registrations (int signo) { struct sn_community *comm, *ctmp; struct peer_info *list, *tmp; char buf[32]; time_t now = time(NULL); u_int num = 0; traceEvent(TRACE_NORMAL, "===================================="); HASH_ITER(hh, sss_node.communities, comm, ctmp) { traceEvent(TRACE_NORMAL, "dumping community: %s", comm->community); HASH_ITER(hh, comm->edges, list, tmp) { if(list->sock.family == AF_INET) { traceEvent(TRACE_NORMAL, "[id: %u][MAC: %s][edge: %u.%u.%u.%u:%u][last seen: %u sec ago]", ++num, macaddr_str(buf, list->mac_addr), list->sock.addr.v4[0], list->sock.addr.v4[1], list->sock.addr.v4[2], list->sock.addr.v4[3], list->sock.port, now - list->last_seen); } else { traceEvent(TRACE_NORMAL, "[id: %u][MAC: %s][edge: IPv6:%u][last seen: %u sec ago]", ++num, macaddr_str(buf, list->mac_addr), list->sock.port, now - list->last_seen); } } } traceEvent(TRACE_NORMAL, "===================================="); } #endif /* *************************************************** */ static int keep_running; #if defined(__linux__) || defined(WIN32) #ifdef WIN32 BOOL WINAPI term_handler (DWORD sig) #else static void term_handler(int sig) #endif { static int called = 0; if(called) { traceEvent(TRACE_NORMAL, "ok, I am leaving now"); _exit(0); } else { traceEvent(TRACE_NORMAL, "shutting down..."); called = 1; } keep_running = 0; #ifdef WIN32 return(TRUE); #endif } #endif /* defined(__linux__) || defined(WIN32) */ /* *************************************************** */ /** Main program entry point from kernel. */ int main (int argc, char * const argv[]) { int rc; #ifndef WIN32 struct passwd *pw = NULL; #endif struct peer_info *scan, *tmp; sn_init_defaults(&sss_node); add_federation_to_communities(&sss_node); if((argc >= 2) && (argv[1][0] != '-')) { rc = loadFromFile(argv[1], &sss_node); if(argc > 2) { rc = loadFromCLI(argc, argv, &sss_node); } } else if(argc > 1) { rc = loadFromCLI(argc, argv, &sss_node); } else #ifdef WIN32 // load from current directory rc = loadFromFile("supernode.conf", &sss_node); #else rc = -1; #endif if(rc < 0) { help(1); /* short help */ } if(sss_node.community_file) load_allowed_sn_community(&sss_node); #if defined(N2N_HAVE_DAEMON) if(sss_node.daemon) { setUseSyslog(1); /* traceEvent output now goes to syslog. */ if(-1 == daemon(0, 0)) { traceEvent(TRACE_ERROR, "failed to become daemon"); exit(-5); } } #endif /* #if defined(N2N_HAVE_DAEMON) */ // warn on default federation name if(!strcmp(sss_node.federation->community, FEDERATION_NAME)) { traceEvent(TRACE_WARNING, "using default federation name; FOR TESTING ONLY, usage of a custom federation name (-F) is highly recommended!"); } if(sss_node.override_spoofing_protection) { traceEvent(TRACE_WARNING, "disabled MAC and IP address spoofing protection; FOR TESTING ONLY, usage of user-password authentication (-I, -J, -P) recommended instead!"); } calculate_shared_secrets(&sss_node); traceEvent(TRACE_DEBUG, "traceLevel is %d", getTraceLevel()); sss_node.sock = open_socket(sss_node.lport, INADDR_ANY, 0 /* UDP */); if(-1 == sss_node.sock) { traceEvent(TRACE_ERROR, "failed to open main socket. %s", strerror(errno)); exit(-2); } else { traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss_node.lport); } #ifdef N2N_HAVE_TCP sss_node.tcp_sock = open_socket(sss_node.lport, INADDR_ANY, 1 /* TCP */); if(-1 == sss_node.tcp_sock) { traceEvent(TRACE_ERROR, "failed to open auxiliary TCP socket, %s", strerror(errno)); exit(-2); } else { traceEvent(TRACE_NORMAL, "supernode opened TCP %u (aux)", sss_node.lport); } if(-1 == listen(sss_node.tcp_sock, N2N_TCP_BACKLOG_QUEUE_SIZE)) { traceEvent(TRACE_ERROR, "failed to listen on auxiliary TCP socket, %s", strerror(errno)); exit(-2); } else { traceEvent(TRACE_NORMAL, "supernode is listening on TCP %u (aux)", sss_node.lport); } #endif sss_node.mgmt_sock = open_socket(sss_node.mport, INADDR_LOOPBACK, 0 /* UDP */); if(-1 == sss_node.mgmt_sock) { traceEvent(TRACE_ERROR, "failed to open management socket, %s", strerror(errno)); exit(-2); } else { traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (management)", sss_node.mport); } HASH_ITER(hh, sss_node.federation->edges, scan, tmp) scan->socket_fd = sss_node.sock; #ifndef WIN32 /* * If no uid/gid is specified on the commandline, use the uid/gid of the * first found out of user "n2n" or "nobody" */ if(((pw = getpwnam ("n2n")) != NULL) || ((pw = getpwnam ("nobody")) != NULL)) { /* * If the uid/gid is not set from the CLI, set it from getpwnam * otherwise reset it to zero * (TODO: this looks wrong) */ sss_node.userid = sss_node.userid == 0 ? pw->pw_uid : 0; sss_node.groupid = sss_node.groupid == 0 ? pw->pw_gid : 0; } /* * If we have a non-zero requested uid/gid, attempt to switch to use * those */ if((sss_node.userid != 0) || (sss_node.groupid != 0)) { traceEvent(TRACE_NORMAL, "dropping privileges to uid=%d, gid=%d", (signed int)sss_node.userid, (signed int)sss_node.groupid); /* Finished with the need for root privileges. Drop to unprivileged user. */ if((setgid(sss_node.groupid) != 0) || (setuid(sss_node.userid) != 0)) { traceEvent(TRACE_ERROR, "unable to drop privileges [%u/%s]", errno, strerror(errno)); } } if((getuid() == 0) || (getgid() == 0)) { traceEvent(TRACE_WARNING, "running as root is discouraged, check out the -u/-g options"); } #endif sn_init(&sss_node); traceEvent(TRACE_NORMAL, "supernode started"); #ifdef __linux__ signal(SIGPIPE, SIG_IGN); signal(SIGTERM, term_handler); signal(SIGINT, term_handler); signal(SIGHUP, dump_registrations); #endif #ifdef WIN32 SetConsoleCtrlHandler(term_handler, TRUE); #endif keep_running = 1; sss_node.keep_running = &keep_running; return run_sn_loop(&sss_node); } ntop-n2n-90215bd/src/tf.c000066400000000000000000000635061422132035700150720ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ // taken (and modified) from github/fudanchii/twofish as of August 2020 // which itself is a modified copy of Andrew T. Csillag's implementation // published on github/drewcsillag/twofish /** * The MIT License (MIT) * * Copyright (c) 2015 Andrew T. Csillag * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "tf.h" const uint8_t RS[4][8] = { { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, }, { 0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5, }, { 0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19, }, { 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03 } }; const uint8_t Q0[] = { 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 }; const uint8_t Q1[] = { 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 }; const uint8_t mult5B[] = { 0x00, 0x5B, 0xB6, 0xED, 0x05, 0x5E, 0xB3, 0xE8, 0x0A, 0x51, 0xBC, 0xE7, 0x0F, 0x54, 0xB9, 0xE2, 0x14, 0x4F, 0xA2, 0xF9, 0x11, 0x4A, 0xA7, 0xFC, 0x1E, 0x45, 0xA8, 0xF3, 0x1B, 0x40, 0xAD, 0xF6, 0x28, 0x73, 0x9E, 0xC5, 0x2D, 0x76, 0x9B, 0xC0, 0x22, 0x79, 0x94, 0xCF, 0x27, 0x7C, 0x91, 0xCA, 0x3C, 0x67, 0x8A, 0xD1, 0x39, 0x62, 0x8F, 0xD4, 0x36, 0x6D, 0x80, 0xDB, 0x33, 0x68, 0x85, 0xDE, 0x50, 0x0B, 0xE6, 0xBD, 0x55, 0x0E, 0xE3, 0xB8, 0x5A, 0x01, 0xEC, 0xB7, 0x5F, 0x04, 0xE9, 0xB2, 0x44, 0x1F, 0xF2, 0xA9, 0x41, 0x1A, 0xF7, 0xAC, 0x4E, 0x15, 0xF8, 0xA3, 0x4B, 0x10, 0xFD, 0xA6, 0x78, 0x23, 0xCE, 0x95, 0x7D, 0x26, 0xCB, 0x90, 0x72, 0x29, 0xC4, 0x9F, 0x77, 0x2C, 0xC1, 0x9A, 0x6C, 0x37, 0xDA, 0x81, 0x69, 0x32, 0xDF, 0x84, 0x66, 0x3D, 0xD0, 0x8B, 0x63, 0x38, 0xD5, 0x8E, 0xA0, 0xFB, 0x16, 0x4D, 0xA5, 0xFE, 0x13, 0x48, 0xAA, 0xF1, 0x1C, 0x47, 0xAF, 0xF4, 0x19, 0x42, 0xB4, 0xEF, 0x02, 0x59, 0xB1, 0xEA, 0x07, 0x5C, 0xBE, 0xE5, 0x08, 0x53, 0xBB, 0xE0, 0x0D, 0x56, 0x88, 0xD3, 0x3E, 0x65, 0x8D, 0xD6, 0x3B, 0x60, 0x82, 0xD9, 0x34, 0x6F, 0x87, 0xDC, 0x31, 0x6A, 0x9C, 0xC7, 0x2A, 0x71, 0x99, 0xC2, 0x2F, 0x74, 0x96, 0xCD, 0x20, 0x7B, 0x93, 0xC8, 0x25, 0x7E, 0xF0, 0xAB, 0x46, 0x1D, 0xF5, 0xAE, 0x43, 0x18, 0xFA, 0xA1, 0x4C, 0x17, 0xFF, 0xA4, 0x49, 0x12, 0xE4, 0xBF, 0x52, 0x09, 0xE1, 0xBA, 0x57, 0x0C, 0xEE, 0xB5, 0x58, 0x03, 0xEB, 0xB0, 0x5D, 0x06, 0xD8, 0x83, 0x6E, 0x35, 0xDD, 0x86, 0x6B, 0x30, 0xD2, 0x89, 0x64, 0x3F, 0xD7, 0x8C, 0x61, 0x3A, 0xCC, 0x97, 0x7A, 0x21, 0xC9, 0x92, 0x7F, 0x24, 0xC6, 0x9D, 0x70, 0x2B, 0xC3, 0x98, 0x75, 0x2E }; const uint8_t multEF[] = { 0x00, 0xEF, 0xB7, 0x58, 0x07, 0xE8, 0xB0, 0x5F, 0x0E, 0xE1, 0xB9, 0x56, 0x09, 0xE6, 0xBE, 0x51, 0x1C, 0xF3, 0xAB, 0x44, 0x1B, 0xF4, 0xAC, 0x43, 0x12, 0xFD, 0xA5, 0x4A, 0x15, 0xFA, 0xA2, 0x4D, 0x38, 0xD7, 0x8F, 0x60, 0x3F, 0xD0, 0x88, 0x67, 0x36, 0xD9, 0x81, 0x6E, 0x31, 0xDE, 0x86, 0x69, 0x24, 0xCB, 0x93, 0x7C, 0x23, 0xCC, 0x94, 0x7B, 0x2A, 0xC5, 0x9D, 0x72, 0x2D, 0xC2, 0x9A, 0x75, 0x70, 0x9F, 0xC7, 0x28, 0x77, 0x98, 0xC0, 0x2F, 0x7E, 0x91, 0xC9, 0x26, 0x79, 0x96, 0xCE, 0x21, 0x6C, 0x83, 0xDB, 0x34, 0x6B, 0x84, 0xDC, 0x33, 0x62, 0x8D, 0xD5, 0x3A, 0x65, 0x8A, 0xD2, 0x3D, 0x48, 0xA7, 0xFF, 0x10, 0x4F, 0xA0, 0xF8, 0x17, 0x46, 0xA9, 0xF1, 0x1E, 0x41, 0xAE, 0xF6, 0x19, 0x54, 0xBB, 0xE3, 0x0C, 0x53, 0xBC, 0xE4, 0x0B, 0x5A, 0xB5, 0xED, 0x02, 0x5D, 0xB2, 0xEA, 0x05, 0xE0, 0x0F, 0x57, 0xB8, 0xE7, 0x08, 0x50, 0xBF, 0xEE, 0x01, 0x59, 0xB6, 0xE9, 0x06, 0x5E, 0xB1, 0xFC, 0x13, 0x4B, 0xA4, 0xFB, 0x14, 0x4C, 0xA3, 0xF2, 0x1D, 0x45, 0xAA, 0xF5, 0x1A, 0x42, 0xAD, 0xD8, 0x37, 0x6F, 0x80, 0xDF, 0x30, 0x68, 0x87, 0xD6, 0x39, 0x61, 0x8E, 0xD1, 0x3E, 0x66, 0x89, 0xC4, 0x2B, 0x73, 0x9C, 0xC3, 0x2C, 0x74, 0x9B, 0xCA, 0x25, 0x7D, 0x92, 0xCD, 0x22, 0x7A, 0x95, 0x90, 0x7F, 0x27, 0xC8, 0x97, 0x78, 0x20, 0xCF, 0x9E, 0x71, 0x29, 0xC6, 0x99, 0x76, 0x2E, 0xC1, 0x8C, 0x63, 0x3B, 0xD4, 0x8B, 0x64, 0x3C, 0xD3, 0x82, 0x6D, 0x35, 0xDA, 0x85, 0x6A, 0x32, 0xDD, 0xA8, 0x47, 0x1F, 0xF0, 0xAF, 0x40, 0x18, 0xF7, 0xA6, 0x49, 0x11, 0xFE, 0xA1, 0x4E, 0x16, 0xF9, 0xB4, 0x5B, 0x03, 0xEC, 0xB3, 0x5C, 0x04, 0xEB, 0xBA, 0x55, 0x0D, 0xE2, 0xBD, 0x52, 0x0A, 0xE5 }; #define RS_MOD 0x14D #define RHO 0x01010101L #define ROL(x,n) (((x) << ((n) & 0x1F)) | ((x) >> (32-((n) & 0x1F)))) #define ROR(x,n) (((x) >> ((n) & 0x1F)) | ((x) << (32-((n) & 0x1F)))) #define _b(x, N) (((x) >> (N*8)) & 0xFF) #define b0(x) ((uint8_t)(x)) #define b1(x) ((uint8_t)((x) >> 8)) #define b2(x) ((uint8_t)((x) >> 16)) #define b3(x) ((uint8_t)((x) >> 24)) #define U8ARRAY_TO_U32(r) ((r[0] << 24) ^ (r[1] << 16) ^ (r[2] << 8) ^ r[3]) #define U8S_TO_U32(r0, r1, r2, r3) ((r0 << 24) ^ (r1 << 16) ^ (r2 << 8) ^ r3) // multiply two polynomials represented as u32's, actually called with bytes uint32_t polyMult(uint32_t a, uint32_t b) { uint32_t t=0; while(a) { if(a & 1) t^=b; b <<= 1; a >>= 1; } return t; } // take the polynomial t and return the t % modulus in GF(256) uint32_t gfMod(uint32_t t, uint32_t modulus) { int i; uint32_t tt; modulus <<= 7; for(i = 0; i < 8; i++) { tt = t ^ modulus; if(tt < t) t = tt; modulus >>= 1; } return t; } // multiply a and b and return the modulus #define gfMult(a, b, modulus) gfMod(polyMult(a, b), modulus) // return a u32 containing the result of multiplying the RS Code matrix by the sd matrix uint32_t RSMatrixMultiply(uint8_t sd[8]) { int j, k; uint8_t t; uint8_t result[4]; for(j = 0; j < 4; j++) { t = 0; for(k = 0; k < 8; k++) { t ^= gfMult(RS[j][k], sd[k], RS_MOD); } result[3-j] = t; } return U8ARRAY_TO_U32(result); } // the Zero-keyed h function (used by the key setup routine) uint32_t h(uint32_t X, uint32_t L[4], int k) { uint8_t y0, y1, y2, y3; uint8_t z0, z1, z2, z3; y0 = b0(X); y1 = b1(X); y2 = b2(X); y3 = b3(X); switch(k) { case 4: y0 = Q1[y0] ^ b0(L[3]); y1 = Q0[y1] ^ b1(L[3]); y2 = Q0[y2] ^ b2(L[3]); y3 = Q1[y3] ^ b3(L[3]); case 3: y0 = Q1[y0] ^ b0(L[2]); y1 = Q1[y1] ^ b1(L[2]); y2 = Q0[y2] ^ b2(L[2]); y3 = Q0[y3] ^ b3(L[2]); case 2: y0 = Q1[ Q0 [ Q0[y0] ^ b0(L[1]) ] ^ b0(L[0]) ]; y1 = Q0[ Q0 [ Q1[y1] ^ b1(L[1]) ] ^ b1(L[0]) ]; y2 = Q1[ Q1 [ Q0[y2] ^ b2(L[1]) ] ^ b2(L[0]) ]; y3 = Q0[ Q1 [ Q1[y3] ^ b3(L[1]) ] ^ b3(L[0]) ]; } // inline the MDS matrix multiply z0 = multEF[y0] ^ y1 ^ multEF[y2] ^ mult5B[y3]; z1 = multEF[y0] ^ mult5B[y1] ^ y2 ^ multEF[y3]; z2 = mult5B[y0] ^ multEF[y1] ^ multEF[y2] ^ y3; z3 = y0 ^ multEF[y1] ^ mult5B[y2] ^ mult5B[y3]; return U8S_TO_U32(z0, z1, z2, z3); } // given the Sbox keys, create the fully keyed QF void fullKey(uint32_t L[4], int k, uint32_t QF[4][256]) { uint8_t y0, y1, y2, y3; int i; // for all input values to the Q permutations for(i = 0; i < 256; i++) { // run the Q permutations y0 = i; y1 = i; y2 = i; y3 = i; switch(k) { case 4: y0 = Q1[y0] ^ b0(L[3]); y1 = Q0[y1] ^ b1(L[3]); y2 = Q0[y2] ^ b2(L[3]); y3 = Q1[y3] ^ b3(L[3]); case 3: y0 = Q1[y0] ^ b0(L[2]); y1 = Q1[y1] ^ b1(L[2]); y2 = Q0[y2] ^ b2(L[2]); y3 = Q0[y3] ^ b3(L[2]); case 2: y0 = Q1[ Q0 [ Q0[y0] ^ b0(L[1]) ] ^ b0(L[0]) ]; y1 = Q0[ Q0 [ Q1[y1] ^ b1(L[1]) ] ^ b1(L[0]) ]; y2 = Q1[ Q1 [ Q0[y2] ^ b2(L[1]) ] ^ b2(L[0]) ]; y3 = Q0[ Q1 [ Q1[y3] ^ b3(L[1]) ] ^ b3(L[0]) ]; } // now do the partial MDS matrix multiplies QF[0][i] = ((multEF[y0] << 24) | (multEF[y0] << 16) | (mult5B[y0] << 8) | y0); QF[1][i] = ((y1 << 24) | (mult5B[y1] << 16) | (multEF[y1] << 8) | multEF[y1]); QF[2][i] = ((multEF[y2] << 24) | (y2 << 16) | (multEF[y2] << 8) | mult5B[y2]); QF[3][i] = ((mult5B[y3] << 24) | (multEF[y3] << 16) | (y3 << 8) | mult5B[y3]); } } // ---------------------------------------------------------------------------------------------------------------- // fully keyed h (aka g) function #define fkh(X) (ctx->QF[0][b0(X)]^ctx->QF[1][b1(X)]^ctx->QF[2][b2(X)]^ctx->QF[3][b3(X)]) // ---------------------------------------------------------------------------------------------------------------- // one encryption round #define ENC_ROUND(R0, R1, R2, R3, round) \ T0 = fkh(R0); \ T1 = fkh(ROL(R1, 8)); \ R2 = ROR(R2 ^ (T1 + T0 + ctx->K[2*round+8]), 1); \ R3 = ROL(R3, 1) ^ (2*T1 + T0 + ctx->K[2*round+9]); void twofish_internal_encrypt(uint8_t PT[16], tf_context_t *ctx) { uint32_t R0, R1, R2, R3; uint32_t T0, T1; // load/byteswap/whiten input R3 = ctx->K[3] ^ le32toh(((uint32_t*)PT)[3]); R2 = ctx->K[2] ^ le32toh(((uint32_t*)PT)[2]); R1 = ctx->K[1] ^ le32toh(((uint32_t*)PT)[1]); R0 = ctx->K[0] ^ le32toh(((uint32_t*)PT)[0]); ENC_ROUND(R0, R1, R2, R3, 0); ENC_ROUND(R2, R3, R0, R1, 1); ENC_ROUND(R0, R1, R2, R3, 2); ENC_ROUND(R2, R3, R0, R1, 3); ENC_ROUND(R0, R1, R2, R3, 4); ENC_ROUND(R2, R3, R0, R1, 5); ENC_ROUND(R0, R1, R2, R3, 6); ENC_ROUND(R2, R3, R0, R1, 7); ENC_ROUND(R0, R1, R2, R3, 8); ENC_ROUND(R2, R3, R0, R1, 9); ENC_ROUND(R0, R1, R2, R3, 10); ENC_ROUND(R2, R3, R0, R1, 11); ENC_ROUND(R0, R1, R2, R3, 12); ENC_ROUND(R2, R3, R0, R1, 13); ENC_ROUND(R0, R1, R2, R3, 14); ENC_ROUND(R2, R3, R0, R1, 15); // whiten/byteswap/store output ((uint32_t*)PT)[3] = htole32(R1 ^ ctx->K[7]); ((uint32_t*)PT)[2] = htole32(R0 ^ ctx->K[6]); ((uint32_t*)PT)[1] = htole32(R3 ^ ctx->K[5]); ((uint32_t*)PT)[0] = htole32(R2 ^ ctx->K[4]); } // ---------------------------------------------------------------------------------------------------------------- // one decryption round #define DEC_ROUND(R0, R1, R2, R3, round) \ T0 = fkh(R0); \ T1 = fkh(ROL(R1, 8)); \ R2 = ROL(R2, 1) ^ (T0 + T1 + ctx->K[2*round+8]); \ R3 = ROR(R3 ^ (T0 + 2*T1 + ctx->K[2*round+9]), 1); void twofish_internal_decrypt(uint8_t PT[16], const uint8_t CT[16], tf_context_t *ctx) { uint32_t T0, T1; uint32_t R0, R1, R2, R3; // load/byteswap/whiten input R3 = ctx->K[7] ^ le32toh(((uint32_t*)CT)[3]); R2 = ctx->K[6] ^ le32toh(((uint32_t*)CT)[2]); R1 = ctx->K[5] ^ le32toh(((uint32_t*)CT)[1]); R0 = ctx->K[4] ^ le32toh(((uint32_t*)CT)[0]); DEC_ROUND(R0, R1, R2, R3, 15); DEC_ROUND(R2, R3, R0, R1, 14); DEC_ROUND(R0, R1, R2, R3, 13); DEC_ROUND(R2, R3, R0, R1, 12); DEC_ROUND(R0, R1, R2, R3, 11); DEC_ROUND(R2, R3, R0, R1, 10); DEC_ROUND(R0, R1, R2, R3, 9); DEC_ROUND(R2, R3, R0, R1, 8); DEC_ROUND(R0, R1, R2, R3, 7); DEC_ROUND(R2, R3, R0, R1, 6); DEC_ROUND(R0, R1, R2, R3, 5); DEC_ROUND(R2, R3, R0, R1, 4); DEC_ROUND(R0, R1, R2, R3, 3); DEC_ROUND(R2, R3, R0, R1, 2); DEC_ROUND(R0, R1, R2, R3, 1); DEC_ROUND(R2, R3, R0, R1, 0); // whiten/byteswap/store output ((uint32_t*)PT)[3] = htole32(R1 ^ ctx->K[3]); ((uint32_t*)PT)[2] = htole32(R0 ^ ctx->K[2]); ((uint32_t*)PT)[1] = htole32(R3 ^ ctx->K[1]); ((uint32_t*)PT)[0] = htole32(R2 ^ ctx->K[0]); } // ------------------------------------------------------------------------------------- // the key schedule routine void keySched(const uint8_t M[], int N, uint32_t **S, uint32_t K[40], int *k) { uint32_t Mo[4], Me[4]; int i, j; uint8_t vector[8]; uint32_t A, B; *k = (N + 63) / 64; *S = (uint32_t*)malloc(sizeof(uint32_t) * (*k)); for(i = 0; i < *k; i++) { Me[i] = le32toh(((uint32_t*)M)[2*i]); Mo[i] = le32toh(((uint32_t*)M)[2*i+1]); } for(i = 0; i < *k; i++) { for(j = 0; j < 4; j++) vector[j] = _b(Me[i], j); for(j = 0; j < 4; j++) vector[j+4] = _b(Mo[i], j); (*S)[(*k)-i-1] = RSMatrixMultiply(vector); } for(i = 0; i < 20; i++) { A = h(2*i*RHO, Me, *k); B = ROL(h(2*i*RHO + RHO, Mo, *k), 8); K[2*i] = A+B; K[2*i+1] = ROL(A + 2*B, 9); } } // ---------------------------------------------------------------------------------------------------------------- #define fix_xor(target, source) *(uint32_t*)&(target)[0] = *(uint32_t*)&(target)[0] ^ *(uint32_t*)&(source)[0]; *(uint32_t*)&(target)[4] = *(uint32_t*)&(target)[4] ^ *(uint32_t*)&(source)[4]; \ *(uint32_t*)&(target)[8] = *(uint32_t*)&(target)[8] ^ *(uint32_t*)&(source)[8]; *(uint32_t*)&(target)[12] = *(uint32_t*)&(target)[12] ^ *(uint32_t*)&(source)[12]; // ---------------------------------------------------------------------------------------------------------------- // public API int tf_ecb_decrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx) { twofish_internal_decrypt(out, in, ctx); return TF_BLOCK_SIZE; } // not used int tf_ecb_encrypt (unsigned char *out, const unsigned char *in, tf_context_t *ctx) { memcpy(out, in, TF_BLOCK_SIZE); twofish_internal_encrypt(out, ctx); return TF_BLOCK_SIZE; } int tf_cbc_encrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, tf_context_t *ctx) { uint8_t tmp[TF_BLOCK_SIZE]; size_t i; size_t n; memcpy(tmp, iv, TF_BLOCK_SIZE); n = in_len / TF_BLOCK_SIZE; for(i = 0; i < n; i++) { fix_xor(tmp, &in[i * TF_BLOCK_SIZE]); twofish_internal_encrypt(tmp, ctx); memcpy(&out[i * TF_BLOCK_SIZE], tmp, TF_BLOCK_SIZE); } return n * TF_BLOCK_SIZE; } int tf_cbc_decrypt (unsigned char *out, const unsigned char *in, size_t in_len, const unsigned char *iv, tf_context_t *ctx) { int n; /* number of blocks */ /* int ret = (int)in_len & 15; remainder, unused*/ uint8_t ivec[TF_BLOCK_SIZE]; /* the ivec/old handling might be optimized if we */ uint8_t old[TF_BLOCK_SIZE]; /* can be sure that in != out */ memcpy(ivec, iv, TF_BLOCK_SIZE); // 3 parallel rails of twofish decryption for(n = in_len / TF_BLOCK_SIZE; n > 2; n -=3) { memcpy(old, in + 2 * TF_BLOCK_SIZE, TF_BLOCK_SIZE); uint32_t T0, T1; uint32_t Q0, Q1, Q2, Q3, R0, R1, R2, R3, S0, S1, S2, S3; // load/byteswap/whiten input/iv Q3 = ctx->K[7] ^ le32toh(((uint32_t*)in)[3]); Q2 = ctx->K[6] ^ le32toh(((uint32_t*)in)[2]); Q1 = ctx->K[5] ^ le32toh(((uint32_t*)in)[1]); Q0 = ctx->K[4] ^ le32toh(((uint32_t*)in)[0]); R3 = ctx->K[7] ^ le32toh(((uint32_t*)in)[7]); R2 = ctx->K[6] ^ le32toh(((uint32_t*)in)[6]); R1 = ctx->K[5] ^ le32toh(((uint32_t*)in)[5]); R0 = ctx->K[4] ^ le32toh(((uint32_t*)in)[4]); S3 = ctx->K[7] ^ le32toh(((uint32_t*)in)[11]); S2 = ctx->K[6] ^ le32toh(((uint32_t*)in)[10]); S1 = ctx->K[5] ^ le32toh(((uint32_t*)in)[9]); S0 = ctx->K[4] ^ le32toh(((uint32_t*)in)[8]); DEC_ROUND(Q0, Q1, Q2, Q3, 15); DEC_ROUND(R0, R1, R2, R3, 15); DEC_ROUND(S0, S1, S2, S3, 15); DEC_ROUND(Q2, Q3, Q0, Q1, 14); DEC_ROUND(R2, R3, R0, R1, 14); DEC_ROUND(S2, S3, S0, S1, 14); DEC_ROUND(Q0, Q1, Q2, Q3, 13); DEC_ROUND(R0, R1, R2, R3, 13); DEC_ROUND(S0, S1, S2, S3, 13); DEC_ROUND(Q2, Q3, Q0, Q1, 12); DEC_ROUND(R2, R3, R0, R1, 12); DEC_ROUND(S2, S3, S0, S1, 12); DEC_ROUND(Q0, Q1, Q2, Q3, 11); DEC_ROUND(R0, R1, R2, R3, 11); DEC_ROUND(S0, S1, S2, S3, 11); DEC_ROUND(Q2, Q3, Q0, Q1, 10); DEC_ROUND(R2, R3, R0, R1, 10); DEC_ROUND(S2, S3, S0, S1, 10); DEC_ROUND(Q0, Q1, Q2, Q3, 9); DEC_ROUND(R0, R1, R2, R3, 9); DEC_ROUND(S0, S1, S2, S3, 9); DEC_ROUND(Q2, Q3, Q0, Q1, 8); DEC_ROUND(R2, R3, R0, R1, 8); DEC_ROUND(S2, S3, S0, S1, 8); DEC_ROUND(Q0, Q1, Q2, Q3, 7); DEC_ROUND(R0, R1, R2, R3, 7); DEC_ROUND(S0, S1, S2, S3, 7); DEC_ROUND(Q2, Q3, Q0, Q1, 6); DEC_ROUND(R2, R3, R0, R1, 6); DEC_ROUND(S2, S3, S0, S1, 6); DEC_ROUND(Q0, Q1, Q2, Q3, 5); DEC_ROUND(R0, R1, R2, R3, 5); DEC_ROUND(S0, S1, S2, S3, 5); DEC_ROUND(Q2, Q3, Q0, Q1, 4); DEC_ROUND(R2, R3, R0, R1, 4); DEC_ROUND(S2, S3, S0, S1, 4); DEC_ROUND(Q0, Q1, Q2, Q3, 3); DEC_ROUND(R0, R1, R2, R3, 3); DEC_ROUND(S0, S1, S2, S3, 3); DEC_ROUND(Q2, Q3, Q0, Q1, 2); DEC_ROUND(R2, R3, R0, R1, 2); DEC_ROUND(S2, S3, S0, S1, 2); DEC_ROUND(Q0, Q1, Q2, Q3, 1); DEC_ROUND(R0, R1, R2, R3, 1); DEC_ROUND(S0, S1, S2, S3, 1); DEC_ROUND(Q2, Q3, Q0, Q1, 0); DEC_ROUND(R2, R3, R0, R1, 0); DEC_ROUND(S2, S3, S0, S1, 0); // whiten/byteswap/store output/iv ((uint32_t*)out)[11] = htole32(S1 ^ ctx->K[3] ^ ((uint32_t*)in)[7]); ((uint32_t*)out)[10] = htole32(S0 ^ ctx->K[2] ^ ((uint32_t*)in)[6]); ((uint32_t*)out)[9] = htole32(S3 ^ ctx->K[1] ^ ((uint32_t*)in)[5]); ((uint32_t*)out)[8] = htole32(S2 ^ ctx->K[0] ^ ((uint32_t*)in)[4]); ((uint32_t*)out)[7] = htole32(R1 ^ ctx->K[3] ^ ((uint32_t*)in)[3]); ((uint32_t*)out)[6] = htole32(R0 ^ ctx->K[2] ^ ((uint32_t*)in)[2]); ((uint32_t*)out)[5] = htole32(R3 ^ ctx->K[1] ^ ((uint32_t*)in)[1]); ((uint32_t*)out)[4] = htole32(R2 ^ ctx->K[0] ^ ((uint32_t*)in)[0]); ((uint32_t*)out)[3] = htole32(Q1 ^ ctx->K[3] ^ ((uint32_t*)ivec)[3]); ((uint32_t*)out)[2] = htole32(Q0 ^ ctx->K[2] ^ ((uint32_t*)ivec)[2]); ((uint32_t*)out)[1] = htole32(Q3 ^ ctx->K[1] ^ ((uint32_t*)ivec)[1]); ((uint32_t*)out)[0] = htole32(Q2 ^ ctx->K[0] ^ ((uint32_t*)ivec)[0]); in += 3 * TF_BLOCK_SIZE; out += 3 * TF_BLOCK_SIZE; memcpy(ivec, old, TF_BLOCK_SIZE); } // handle the two or less remaining block on a single rail for(; n != 0; n--) { uint32_t T0, T1; uint32_t Q0, Q1, Q2, Q3; memcpy(old, in, TF_BLOCK_SIZE); // load/byteswap/whiten input Q3 = ctx->K[7] ^ le32toh(((uint32_t*)in)[3]); Q2 = ctx->K[6] ^ le32toh(((uint32_t*)in)[2]); Q1 = ctx->K[5] ^ le32toh(((uint32_t*)in)[1]); Q0 = ctx->K[4] ^ le32toh(((uint32_t*)in)[0]); DEC_ROUND(Q0, Q1, Q2, Q3, 15); DEC_ROUND(Q2, Q3, Q0, Q1, 14); DEC_ROUND(Q0, Q1, Q2, Q3, 13); DEC_ROUND(Q2, Q3, Q0, Q1, 12); DEC_ROUND(Q0, Q1, Q2, Q3, 11); DEC_ROUND(Q2, Q3, Q0, Q1, 10); DEC_ROUND(Q0, Q1, Q2, Q3, 9); DEC_ROUND(Q2, Q3, Q0, Q1, 8); DEC_ROUND(Q0, Q1, Q2, Q3, 7); DEC_ROUND(Q2, Q3, Q0, Q1, 6); DEC_ROUND(Q0, Q1, Q2, Q3, 5); DEC_ROUND(Q2, Q3, Q0, Q1, 4); DEC_ROUND(Q0, Q1, Q2, Q3, 3); DEC_ROUND(Q2, Q3, Q0, Q1, 2); DEC_ROUND(Q0, Q1, Q2, Q3, 1); DEC_ROUND(Q2, Q3, Q0, Q1, 0); // load/byteswap/whiten output/iv ((uint32_t*)out)[3] = htole32(Q1 ^ ctx->K[3] ^ ((uint32_t*)ivec)[3]); ((uint32_t*)out)[2] = htole32(Q0 ^ ctx->K[2] ^ ((uint32_t*)ivec)[2]); ((uint32_t*)out)[1] = htole32(Q3 ^ ctx->K[1] ^ ((uint32_t*)ivec)[1]); ((uint32_t*)out)[0] = htole32(Q2 ^ ctx->K[0] ^ ((uint32_t*)ivec)[0]); in += TF_BLOCK_SIZE; out+= TF_BLOCK_SIZE; memcpy(ivec, old, TF_BLOCK_SIZE); } return n * TF_BLOCK_SIZE; } // by definition twofish can only accept key up to 256 bit // we wont do any checking here and will assume user already // know about it. twofish is undefined for key larger than 256 bit int tf_init (const unsigned char *key, size_t key_size, tf_context_t **ctx) { int k; uint32_t *S; *ctx = calloc(1, sizeof(tf_context_t)); if(!(*ctx)) { return -1; } (*ctx)->N = key_size; keySched(key, key_size, &S, (*ctx)->K, &k); fullKey(S, k, (*ctx)->QF); free(S); /* allocated in keySched(...) */ return 0; } int tf_deinit (tf_context_t *ctx) { if(ctx) free(ctx); return 0; } ntop-n2n-90215bd/src/transform_aes.c000066400000000000000000000216121422132035700173140ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" // size of random value prepended to plaintext defaults to AES BLOCK_SIZE; // gradually abandoning security, lower values could be chosen; // however, minimum transmission size with cipher text stealing scheme is one // block; as network packets should be longer anyway, only low level programmer // might encounter an issue with lower values here #define AES_PREAMBLE_SIZE (AES_BLOCK_SIZE) // cts/cbc mode is being used with random value prepended to plaintext // instead of iv so, actual iv is aes_null_iv const uint8_t aes_null_iv[AES_IV_SIZE] = { 0 }; typedef struct transop_aes { aes_context_t *ctx; } transop_aes_t; static int transop_deinit_aes (n2n_trans_op_t *arg) { transop_aes_t *priv = (transop_aes_t *)arg->priv; if(priv->ctx) aes_deinit(priv->ctx); if(priv) free(priv); return 0; } // the aes packet format consists of // // - a random AES_PREAMBLE_SIZE-sized value prepended to plaintext // encrypted together with the... // - ... payload data // // [VV|DDDDDDDDDDDDDDDDDDDDD] // | <---- encrypted ----> | // static int transop_encode_aes (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { transop_aes_t *priv = (transop_aes_t *)arg->priv; // the assembly buffer is a source for encrypting data // the whole contents of assembly are encrypted uint8_t assembly[N2N_PKT_BUF_SIZE]; size_t idx = 0; int padded_len; uint8_t padding; uint8_t buf[AES_BLOCK_SIZE]; if(in_len <= N2N_PKT_BUF_SIZE) { if((in_len + AES_PREAMBLE_SIZE + AES_BLOCK_SIZE) <= out_len) { traceEvent(TRACE_DEBUG, "transop_encode_aes %lu bytes plaintext", in_len); // full block sized random value (128 bit) encode_uint64(assembly, &idx, n2n_rand()); encode_uint64(assembly, &idx, n2n_rand()); // adjust for maybe differently chosen AES_PREAMBLE_SIZE idx = AES_PREAMBLE_SIZE; // the plaintext data encode_buf(assembly, &idx, inbuf, in_len); // round up to next whole AES block size padded_len = (((idx - 1) / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; padding = (padded_len-idx); // pad the following bytes with zero, fixed length (AES_BLOCK_SIZE) seems to compile // to slightly faster code than run-time dependant 'padding' memset(assembly + idx, 0, AES_BLOCK_SIZE); aes_cbc_encrypt(outbuf, assembly, padded_len, aes_null_iv, priv->ctx); if(padding) { // exchange last two cipher blocks memcpy(buf, outbuf+padded_len - AES_BLOCK_SIZE, AES_BLOCK_SIZE); memcpy(outbuf + padded_len - AES_BLOCK_SIZE, outbuf + padded_len - 2 * AES_BLOCK_SIZE, AES_BLOCK_SIZE); memcpy(outbuf + padded_len - 2 * AES_BLOCK_SIZE, buf, AES_BLOCK_SIZE); } } else traceEvent(TRACE_ERROR, "transop_encode_aes outbuf too small"); } else traceEvent(TRACE_ERROR, "transop_encode_aes inbuf too big to encrypt"); return idx; } // see transop_encode_aes for packet format static int transop_decode_aes (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { transop_aes_t *priv = (transop_aes_t *)arg->priv; uint8_t assembly[N2N_PKT_BUF_SIZE]; uint8_t rest; size_t penultimate_block; uint8_t buf[AES_BLOCK_SIZE]; int len = -1; if(((in_len - AES_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* cipher text fits in assembly */ && (in_len >= AES_PREAMBLE_SIZE) /* has at least random number */ && (in_len >= AES_BLOCK_SIZE)) { /* minimum size requirement for cipher text stealing */ traceEvent(TRACE_DEBUG, "transop_decode_aes %lu bytes ciphertext", in_len); rest = in_len % AES_BLOCK_SIZE; if(rest) { /* cipher text stealing */ penultimate_block = ((in_len / AES_BLOCK_SIZE) - 1) * AES_BLOCK_SIZE; // everything normal up to penultimate block memcpy(assembly, inbuf, penultimate_block); // prepare new penultimate block in buf aes_ecb_decrypt(buf, inbuf + penultimate_block, priv->ctx); memcpy(buf, inbuf + in_len - rest, rest); // former penultimate block becomes new ultimate block memcpy(assembly + penultimate_block + AES_BLOCK_SIZE, inbuf + penultimate_block, AES_BLOCK_SIZE); // write new penultimate block from buf memcpy(assembly + penultimate_block, buf, AES_BLOCK_SIZE); // regular cbc decryption of the re-arranged ciphertext aes_cbc_decrypt(assembly, assembly, in_len + AES_BLOCK_SIZE - rest, aes_null_iv, priv->ctx); // check for expected zero padding and give a warning otherwise if(memcmp(assembly + in_len, aes_null_iv, AES_BLOCK_SIZE - rest)) { traceEvent(TRACE_WARNING, "transop_decode_aes payload decryption failed with unexpected cipher text stealing padding"); return -1; } } else { // regular cbc decryption on multiple block-sized payload aes_cbc_decrypt(assembly, inbuf, in_len, aes_null_iv, priv->ctx); } len = in_len - AES_PREAMBLE_SIZE; memcpy(outbuf, assembly + AES_PREAMBLE_SIZE, len); } else traceEvent(TRACE_ERROR, "transop_decode_aes inbuf wrong size (%ul) to decrypt", in_len); return len; } static int setup_aes_key (transop_aes_t *priv, const uint8_t *password, ssize_t password_len) { unsigned char key_mat[32]; /* maximum aes key length, equals hash length */ unsigned char *key; size_t key_size; // let the user choose the degree of encryption: // long input passwords will pick AES192 or AES256 with more robust but expensive encryption // the input password always gets hashed to make a more unpredictable use of the key space // just think of usually reset MSB of ASCII coded password bytes pearson_hash_256(key_mat, password, password_len); // the length-dependant scheme for key setup was discussed on github: // https://github.com/ntop/n2n/issues/101 -- as no iv encryption required // anymore, the key-size trigger values were roughly halved if(password_len >= 33) { key_size = AES256_KEY_BYTES; /* 256 bit */ } else if(password_len >= 23) { key_size = AES192_KEY_BYTES; /* 192 bit */ } else { key_size = AES128_KEY_BYTES; /* 128 bit */ } // and use the last key-sized part of the hash as aes key key = key_mat + sizeof(key_mat) - key_size; // setup the key and have corresponding context created if(aes_init (key, key_size, &(priv->ctx))) { traceEvent(TRACE_ERROR, "setup_aes_key %u-bit key setup unsuccessful", key_size * 8); return -1; } traceEvent(TRACE_DEBUG, "setup_aes_key %u-bit key setup completed", key_size * 8); return 0; } static void transop_tick_aes (n2n_trans_op_t *arg, time_t now) { // no tick action } // AES initialization function int n2n_transop_aes_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { transop_aes_t *priv; const u_char *encrypt_key = (const u_char *)conf->encrypt_key; size_t encrypt_key_len = strlen(conf->encrypt_key); memset(ttt, 0, sizeof(*ttt)); ttt->transform_id = N2N_TRANSFORM_ID_AES; ttt->tick = transop_tick_aes; ttt->deinit = transop_deinit_aes; ttt->fwd = transop_encode_aes; ttt->rev = transop_decode_aes; priv = (transop_aes_t*)calloc(1, sizeof(transop_aes_t)); if(!priv) { traceEvent(TRACE_ERROR, "n2n_transop_aes_init cannot allocate transop_aes_t memory"); return -1; } ttt->priv = priv; // setup the cipher and key return setup_aes_key(priv, encrypt_key, encrypt_key_len); } ntop-n2n-90215bd/src/transform_cc20.c000066400000000000000000000115121422132035700172710ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" // ChaCha20 plaintext preamble #define CC20_PREAMBLE_SIZE (CC20_IV_SIZE) typedef struct transop_cc20 { cc20_context_t *ctx; } transop_cc20_t; static int transop_deinit_cc20 (n2n_trans_op_t *arg) { transop_cc20_t *priv = (transop_cc20_t *)arg->priv; if(priv->ctx) cc20_deinit(priv->ctx); if(priv) free(priv); return 0; } // the ChaCha20 packet format consists of // // - a 128-bit random iv // - encrypted payload // // [IIII|DDDDDDDDDDDDDDDDDDDDD] // |<---- encrypted ---->| // static int transop_encode_cc20 (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { int len = -1; transop_cc20_t *priv = (transop_cc20_t *)arg->priv; if(in_len <= N2N_PKT_BUF_SIZE) { if((in_len + CC20_PREAMBLE_SIZE) <= out_len) { size_t idx = 0; traceEvent(TRACE_DEBUG, "encode_cc20 %lu bytes", in_len); // full iv sized random value (128 bit) encode_uint64(outbuf, &idx, n2n_rand()); encode_uint64(outbuf, &idx, n2n_rand()); len = in_len; cc20_crypt(outbuf + CC20_PREAMBLE_SIZE, inbuf, in_len, outbuf, /* iv */ priv->ctx); // size of datacarried in UDP len += CC20_PREAMBLE_SIZE; } else traceEvent(TRACE_ERROR, "encode_cc20 outbuf too small."); } else traceEvent(TRACE_ERROR, "encode_cc20 inbuf too big to encrypt."); return len; } // see transop_encode_cc20 for packet format static int transop_decode_cc20 (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { int len = 0; transop_cc20_t *priv = (transop_cc20_t *)arg->priv; if(((in_len - CC20_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* cipher text fits in assembly */ && (in_len >= CC20_PREAMBLE_SIZE)) { /* has at least iv */ traceEvent(TRACE_DEBUG, "decode_cc20 %lu bytes", in_len); len = (in_len - CC20_PREAMBLE_SIZE); cc20_crypt(outbuf, inbuf + CC20_PREAMBLE_SIZE, in_len, inbuf, /* iv */ priv->ctx); } else traceEvent(TRACE_ERROR, "decode_cc20 inbuf wrong size (%ul) to decrypt.", in_len); return len; } static int setup_cc20_key (transop_cc20_t *priv, const uint8_t *password, ssize_t password_len) { uint8_t key_mat[CC20_KEY_BYTES]; // the input key always gets hashed to make a more unpredictable and more complete use of the key space pearson_hash_256(key_mat, password, password_len); if(cc20_init(key_mat, &(priv->ctx))) { traceEvent(TRACE_ERROR, "setup_cc20_key setup unsuccessful"); return -1; } traceEvent(TRACE_DEBUG, "setup_cc20_key completed"); return 0; } static void transop_tick_cc20 (n2n_trans_op_t *arg, time_t now) { // no tick action } // ChaCha20 initialization function int n2n_transop_cc20_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { transop_cc20_t *priv; const u_char *encrypt_key = (const u_char *)conf->encrypt_key; size_t encrypt_key_len = strlen(conf->encrypt_key); memset(ttt, 0, sizeof(*ttt)); ttt->transform_id = N2N_TRANSFORM_ID_CHACHA20; ttt->tick = transop_tick_cc20; ttt->deinit = transop_deinit_cc20; ttt->fwd = transop_encode_cc20; ttt->rev = transop_decode_cc20; priv = (transop_cc20_t*)calloc(1, sizeof(transop_cc20_t)); if(!priv) { traceEvent(TRACE_ERROR, "cannot allocate transop_cc20_t memory"); return -1; } ttt->priv = priv; // setup the cipher and key return setup_cc20_key(priv, encrypt_key, encrypt_key_len); } ntop-n2n-90215bd/src/transform_lzo.c000066400000000000000000000074741422132035700173620ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" /* heap allocation for compression as per lzo example doc */ #define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] typedef struct transop_lzo { HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); } transop_lzo_t; static int transop_deinit_lzo (n2n_trans_op_t *arg) { transop_lzo_t *priv = (transop_lzo_t *)arg->priv; if(priv) free(priv); return 0; } // returns compressed packet length // returns 0 if error occured, the caller would have to use // original, i.e. uncompressed data then static int transop_encode_lzo (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { transop_lzo_t *priv = (transop_lzo_t *)arg->priv; lzo_uint compression_len = 0; if(in_len > N2N_PKT_BUF_SIZE) { traceEvent(TRACE_ERROR, "encode_lzo inbuf wrong size (%ul) to compress", in_len); return 0; } if(out_len < in_len + in_len / 16 + 64 + 3) { traceEvent(TRACE_ERROR, "encode_lzo outbuf too small (%ul) to compress inbuf (%ul)", out_len, in_len); return 0; } if(lzo1x_1_compress(inbuf, in_len, outbuf, &compression_len, priv->wrkmem) != LZO_E_OK) { traceEvent(TRACE_ERROR, "encode_lzo compression error"); compression_len = 0; } return compression_len; } static int transop_decode_lzo (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { lzo_uint deflated_len = N2N_PKT_BUF_SIZE; if(in_len > N2N_PKT_BUF_SIZE) { traceEvent(TRACE_ERROR, "decode_lzo inbuf wrong size (%ul) to decompress", in_len); return 0; } lzo1x_decompress(inbuf, in_len, outbuf, &deflated_len, NULL); if(deflated_len > N2N_PKT_BUF_SIZE) { traceEvent(TRACE_ERROR, "decode_lzo outbuf wrong size (%ul) decompressed", deflated_len); return 0; } return deflated_len; } static void transop_tick_lzo (n2n_trans_op_t *arg, time_t now) { // no tick action } // lzo initialization function int n2n_transop_lzo_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { transop_lzo_t *priv; memset(ttt, 0, sizeof(*ttt)); ttt->transform_id = N2N_COMPRESSION_ID_LZO; ttt->tick = transop_tick_lzo; ttt->deinit = transop_deinit_lzo; ttt->fwd = transop_encode_lzo; ttt->rev = transop_decode_lzo; priv = (transop_lzo_t*)calloc(1, sizeof(transop_lzo_t)); if(!priv) { traceEvent(TRACE_ERROR, "lzo_init cannot allocate transop_lzo memory"); return -1; } ttt->priv = priv; if(lzo_init() != LZO_E_OK) { traceEvent(TRACE_ERROR, "lzo_init cannot init lzo compression"); return -1; } return 0; } ntop-n2n-90215bd/src/transform_null.c000066400000000000000000000050031422132035700175120ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" static int transop_deinit_null (n2n_trans_op_t *arg ) { // nothing to deallocate, nothing to release return 0; } static int transop_encode_null (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { int retval = -1; traceEvent(TRACE_DEBUG, "encode_null %lu", in_len); if(out_len >= in_len) { memcpy(outbuf, inbuf, in_len); retval = in_len; } else { traceEvent(TRACE_DEBUG, "encode_null %lu too big for packet buffer", in_len); } return retval; } static int transop_decode_null (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { int retval = -1; traceEvent(TRACE_DEBUG, "decode_null %lu", in_len); if(out_len >= in_len) { memcpy(outbuf, inbuf, in_len); retval = in_len; } else { traceEvent(TRACE_DEBUG, "decode_null %lu too big for packet buffer", in_len); } return retval; } static void transop_tick_null (n2n_trans_op_t *arg, time_t now) { // no tick action } int n2n_transop_null_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { memset(ttt, 0, sizeof(n2n_trans_op_t)); ttt->transform_id = N2N_TRANSFORM_ID_NULL; ttt->no_encryption = 1; ttt->deinit = transop_deinit_null; ttt->tick = transop_tick_null; ttt->fwd = transop_encode_null; ttt->rev = transop_decode_null; return 0; } ntop-n2n-90215bd/src/transform_speck.c000066400000000000000000000132671422132035700176600ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" // Speck plaintext preamble #define TRANSOP_SPECK_PREAMBLE_SIZE (N2N_SPECK_IVEC_SIZE) typedef struct transop_speck { speck_context_t *ctx; /* the round keys for payload encryption & decryption */ } transop_speck_t; static int transop_deinit_speck (n2n_trans_op_t *arg) { transop_speck_t *priv = (transop_speck_t *)arg->priv; if(priv->ctx) speck_deinit(priv->ctx); if(priv) free(priv); return 0; } // the Speck packet format consists of // // - a 128-bit random iv // - encrypted payload // // [IIII|DDDDDDDDDDDDDDDDDDDDD] // |<---- encrypted ---->| // static int transop_encode_speck (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { int len = -1; transop_speck_t *priv = (transop_speck_t *)arg->priv; if(in_len <= N2N_PKT_BUF_SIZE) { if((in_len + TRANSOP_SPECK_PREAMBLE_SIZE) <= out_len) { size_t idx = 0; traceEvent(TRACE_DEBUG, "encode_speck %lu bytes", in_len); // generate and encode the iv encode_uint64(outbuf, &idx, n2n_rand()); encode_uint64(outbuf, &idx, n2n_rand()); // encrypt the payload and write the ciphertext after the iv // len is set to the length of the cipher plain text to be encrpyted // which is (in this case) identical to original packet lentgh len = in_len; speck_ctr (outbuf + TRANSOP_SPECK_PREAMBLE_SIZE, /* output starts right after the iv */ inbuf, /* input */ in_len, /* len */ outbuf, /* iv, already encoded in outbuf, speck does not change it */ priv->ctx); /* ctx already setup with round keys */ traceEvent(TRACE_DEBUG, "encode_speck: encrypted %u bytes.\n", in_len); // size of data carried in UDP len += TRANSOP_SPECK_PREAMBLE_SIZE; } else traceEvent(TRACE_ERROR, "encode_speck outbuf too small."); } else traceEvent(TRACE_ERROR, "encode_speck inbuf too big to encrypt."); return len; } // see transop_encode_speck for packet format static int transop_decode_speck (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { int len = 0; transop_speck_t *priv = (transop_speck_t *)arg->priv; if(((in_len - TRANSOP_SPECK_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* cipher text fits in buffer */ && (in_len >= TRANSOP_SPECK_PREAMBLE_SIZE)) { /* has at least iv */ traceEvent(TRACE_DEBUG, "decode_speck %lu bytes", in_len); len = (in_len - TRANSOP_SPECK_PREAMBLE_SIZE); speck_ctr (outbuf, /* output */ inbuf + TRANSOP_SPECK_PREAMBLE_SIZE, /* encrypted data starts right after preamble (iv) */ len, /* len */ inbuf, /* iv can be found at input's beginning */ priv->ctx); /* ctx already setup with round keys */ traceEvent(TRACE_DEBUG, "decode_speck decrypted %u bytes.\n", len); } else traceEvent(TRACE_ERROR, "decode_speck inbuf wrong size (%ul) to decrypt.", in_len); return len; } static int setup_speck_key (transop_speck_t *priv, const uint8_t *key, ssize_t key_size) { uint8_t key_mat_buf[32]; // the input key always gets hashed to make a more unpredictable and more complete use of the key space pearson_hash_256(key_mat_buf, key, key_size); // expand the key material to the context (= round keys), 256 bit keysize speck_init(&(priv->ctx), key_mat_buf, 256); traceEvent(TRACE_DEBUG, "setup_speck_key completed\n"); return 0; } static void transop_tick_speck (n2n_trans_op_t *arg, time_t now) { // no tick action } // Speck initialization function int n2n_transop_speck_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { transop_speck_t *priv; const u_char *encrypt_key = (const u_char *)conf->encrypt_key; size_t encrypt_key_len = strlen(conf->encrypt_key); memset(ttt, 0, sizeof(*ttt)); ttt->transform_id = N2N_TRANSFORM_ID_SPECK; ttt->tick = transop_tick_speck; ttt->deinit = transop_deinit_speck; ttt->fwd = transop_encode_speck; ttt->rev = transop_decode_speck; priv = (transop_speck_t*)calloc(1, sizeof(transop_speck_t)); if(!priv) { traceEvent(TRACE_ERROR, "n2n_transop_speck_init cannot allocate transop_speck_t memory"); return -1; } ttt->priv = priv; // setup the cipher and key return setup_speck_key(priv, encrypt_key, encrypt_key_len); } ntop-n2n-90215bd/src/transform_tf.c000066400000000000000000000201541422132035700171550ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" // size of random value prepended to plaintext defaults to TF_BLOCK_SIZE; // gradually abandoning security, lower values could be chosen; // however, minimum transmission size with cipher text stealing scheme is one // block; as network packets should be longer anyway, only low level programmer // might encounter an issue with lower values here #define TF_PREAMBLE_SIZE (TF_BLOCK_SIZE) // cbc mode is being used with random value prepended to plaintext // instead of iv so, actual iv is tf_null_iv const uint8_t tf_null_iv[TF_IV_SIZE] = { 0 }; typedef struct transop_tf { tf_context_t *ctx; } transop_tf_t; static int transop_deinit_tf (n2n_trans_op_t *arg) { transop_tf_t *priv = (transop_tf_t *)arg->priv; if(priv->ctx) tf_deinit(priv->ctx); if(priv) free(priv); return 0; } // the Twofish packet format consists of // // - a random TF_PREAMBLE_SIZE-sized value prepended to plaintext // encrypted together with the... // - ... payload data // // [VV|DDDDDDDDDDDDDDDDDDDDD] // | <---- encrypted ----> | // static int transop_encode_tf (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { transop_tf_t *priv = (transop_tf_t *)arg->priv; // the assembly buffer is a source for encrypting data // the whole contents of assembly are encrypted uint8_t assembly[N2N_PKT_BUF_SIZE]; size_t idx = 0; int padded_len; uint8_t padding; uint8_t buf[TF_BLOCK_SIZE]; if(in_len <= N2N_PKT_BUF_SIZE) { if((in_len + TF_PREAMBLE_SIZE + TF_BLOCK_SIZE) <= out_len) { traceEvent(TRACE_DEBUG, "transop_encode_tf %lu bytes plaintext", in_len); // full block sized random value (128 bit) encode_uint64(assembly, &idx, n2n_rand()); encode_uint64(assembly, &idx, n2n_rand()); // adjust for maybe differently chosen TF_PREAMBLE_SIZE idx = TF_PREAMBLE_SIZE; // the plaintext data encode_buf(assembly, &idx, inbuf, in_len); // round up to next whole TF block size padded_len = (((idx - 1) / TF_BLOCK_SIZE) + 1) * TF_BLOCK_SIZE; padding = (padded_len-idx); // pad the following bytes with zero, fixed length (TF_BLOCK_SIZE) seems to compile // to slightly faster code than run-time dependant 'padding' memset(assembly + idx, 0, TF_BLOCK_SIZE); tf_cbc_encrypt(outbuf, assembly, padded_len, tf_null_iv, priv->ctx); if(padding) { // exchange last two cipher blocks memcpy(buf, outbuf + padded_len - TF_BLOCK_SIZE, TF_BLOCK_SIZE); memcpy(outbuf + padded_len - TF_BLOCK_SIZE, outbuf + padded_len - 2 * TF_BLOCK_SIZE, TF_BLOCK_SIZE); memcpy(outbuf + padded_len - 2 * TF_BLOCK_SIZE, buf, TF_BLOCK_SIZE); } } else traceEvent(TRACE_ERROR, "transop_encode_tf outbuf too small"); } else traceEvent(TRACE_ERROR, "transop_encode_tf inbuf too big to encrypt"); return idx; } // see transop_encode_tf for packet format static int transop_decode_tf (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { transop_tf_t *priv = (transop_tf_t *)arg->priv; uint8_t assembly[N2N_PKT_BUF_SIZE]; uint8_t rest; size_t penultimate_block; uint8_t buf[TF_BLOCK_SIZE]; int len = -1; if(((in_len - TF_PREAMBLE_SIZE) <= N2N_PKT_BUF_SIZE) /* cipher text fits in assembly */ && (in_len >= TF_PREAMBLE_SIZE) /* has at least random number */ && (in_len >= TF_BLOCK_SIZE)) { /* minimum size requirement for cipher text stealing */ traceEvent(TRACE_DEBUG, "transop_decode_tf %lu bytes ciphertext", in_len); rest = in_len % TF_BLOCK_SIZE; if(rest) { /* cipher text stealing */ penultimate_block = ((in_len / TF_BLOCK_SIZE) - 1) * TF_BLOCK_SIZE; // everything normal up to penultimate block memcpy(assembly, inbuf, penultimate_block); // prepare new penultimate block in buf tf_ecb_decrypt(buf, inbuf + penultimate_block, priv->ctx); memcpy(buf, inbuf + in_len - rest, rest); // former penultimate block becomes new ultimate block memcpy(assembly + penultimate_block + TF_BLOCK_SIZE, inbuf + penultimate_block, TF_BLOCK_SIZE); // write new penultimate block from buf memcpy(assembly + penultimate_block, buf, TF_BLOCK_SIZE); // regular cbc decryption of the re-arranged ciphertext tf_cbc_decrypt(assembly, assembly, in_len + TF_BLOCK_SIZE - rest, tf_null_iv, priv->ctx); // check for expected zero padding and give a warning otherwise if(memcmp(assembly + in_len, tf_null_iv, TF_BLOCK_SIZE - rest)) { traceEvent(TRACE_WARNING, "transop_decode_tf payload decryption failed with unexpected cipher text stealing padding"); return -1; } } else { // regular cbc decryption on multiple block-sized payload tf_cbc_decrypt(assembly, inbuf, in_len, tf_null_iv, priv->ctx); } len = in_len - TF_PREAMBLE_SIZE; memcpy(outbuf, assembly + TF_PREAMBLE_SIZE, len); } else traceEvent(TRACE_ERROR, "transop_decode_tf inbuf wrong size (%ul) to decrypt", in_len); return len; } static int setup_tf_key (transop_tf_t *priv, const uint8_t *password, ssize_t password_len) { unsigned char key[32]; /* tf key length, equals hash length */ size_t key_size; // the input password always gets hashed to make a more unpredictable use of the key space // just think of usually reset MSB of ASCII coded password bytes pearson_hash_256(key, password, password_len); key_size = 32; /* 256 bit */ // setup the key and have corresponding context created if(tf_init(key, key_size * 8, &(priv->ctx))) { traceEvent(TRACE_ERROR, "setup_tf_key %u-bit key setup unsuccessful", key_size * 8); return -1; } traceEvent(TRACE_DEBUG, "setup_tf_key %u-bit key setup completed", key_size * 8); return 0; } static void transop_tick_tf (n2n_trans_op_t *arg, time_t now) { // no tick action } // Twofish initialization function int n2n_transop_tf_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { transop_tf_t *priv; const u_char *encrypt_key = (const u_char *)conf->encrypt_key; size_t encrypt_key_len = strlen(conf->encrypt_key); memset(ttt, 0, sizeof(*ttt)); ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH; ttt->tick = transop_tick_tf; ttt->deinit = transop_deinit_tf; ttt->fwd = transop_encode_tf; ttt->rev = transop_decode_tf; priv = (transop_tf_t*)calloc(1, sizeof(transop_tf_t)); if(!priv) { traceEvent(TRACE_ERROR, "n2n_transop_tf_cbc_init cannot allocate transop_tf_t memory"); return -1; } ttt->priv = priv; // setup the cipher and key return setup_tf_key(priv, encrypt_key, encrypt_key_len); } ntop-n2n-90215bd/src/transform_zstd.c000066400000000000000000000107531422132035700175340ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #ifdef HAVE_ZSTD typedef struct transop_zstd { // no local data } transop_zstd_t; static int transop_deinit_zstd (n2n_trans_op_t *arg) { transop_zstd_t *priv = (transop_zstd_t *)arg->priv; if(priv) free(priv); return 0; } // returns compressed packet length // returns 0 if error occured, the caller would have to use // original, i.e. uncompressed data then static int transop_encode_zstd (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { /* transop_zstd_t *priv = (transop_zstd_t *)arg->priv; */ int32_t compression_len = 0; if(in_len > N2N_PKT_BUF_SIZE) { traceEvent(TRACE_ERROR, "encode_zstd inbuf wrong size (%ul) to compress", in_len); return 0; } if(out_len < in_len + 128) { // 128 leaves enough room, // for exact size call // ZSTD_compressBound(in_len) // which is slower traceEvent(TRACE_ERROR, "encode_zstd outbuf too small (%ul) to compress inbuf (%ul)", out_len, in_len); return 0; } compression_len = ZSTD_compress(outbuf, out_len, inbuf, in_len, ZSTD_COMPRESSION_LEVEL); if(ZSTD_isError(compression_len)) { traceEvent(TRACE_ERROR, "payload compression failed with zstd error '%s'", ZSTD_getErrorName(compression_len)); // we do no return the error code to the caller, just return 0 len // so, any further specific error handling would have to happen right here compression_len = 0; } return compression_len; } static int transop_decode_zstd (n2n_trans_op_t *arg, uint8_t *outbuf, size_t out_len, const uint8_t *inbuf, size_t in_len, const uint8_t *peer_mac) { int32_t deflated_len = 0; if(in_len > N2N_PKT_BUF_SIZE) { traceEvent(TRACE_ERROR, "decode_zstd inbuf wrong size (%ul) to decompress", in_len); return 0; } deflated_len = ZSTD_decompress(outbuf, out_len, inbuf, in_len); if(ZSTD_isError(deflated_len)) { traceEvent(TRACE_WARNING, "payload decompression failed with zstd error '%s'", ZSTD_getErrorName(deflated_len)); return 0; // cannot help it } // we should have noticed by memory break or ZSTD complaining about a too small of an out_len if(deflated_len > N2N_PKT_BUF_SIZE) { traceEvent(TRACE_ERROR, "decode_zstd outbuf wrong size (%ul) decompressed", deflated_len); return 0; } return deflated_len; } static void transop_tick_zstd (n2n_trans_op_t *arg, time_t now) { // no tick action } // zstd initialization function int n2n_transop_zstd_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { transop_zstd_t *priv; memset(ttt, 0, sizeof(*ttt)); ttt->transform_id = N2N_COMPRESSION_ID_ZSTD; ttt->tick = transop_tick_zstd; ttt->deinit = transop_deinit_zstd; ttt->fwd = transop_encode_zstd; ttt->rev = transop_decode_zstd; priv = (transop_zstd_t*)calloc(1, sizeof(transop_zstd_t)); if(!priv) { traceEvent(TRACE_ERROR, "zstd_init cannot allocate transop_zstd memory"); return -1; } ttt->priv = priv; // zstd does not require initialization // if it requires one day, this is the place to do it and eventually throw an error // (see 'transform_lzo.c') return 0; } #endif // HAVE_ZSTD ntop-n2n-90215bd/src/tuntap_freebsd.c000066400000000000000000000072461422132035700174650ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #ifdef __FreeBSD__ #define N2N_FREEBSD_TAPDEVICE_SIZE 32 void tuntap_close (tuntap_dev *device); int tuntap_open (tuntap_dev *device /* ignored */, char *dev, const char *address_mode, /* static or dhcp */ char *device_ip, char *device_mask, const char * device_mac, int mtu) { int i; char tap_device[N2N_FREEBSD_TAPDEVICE_SIZE]; for(i = 0; i < 255; i++) { snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); device->fd = open(tap_device, O_RDWR); if(device->fd > 0) { traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); break; } } if(device->fd < 0) { traceEvent(TRACE_ERROR, "Unable to open tap device"); return -1; } else { char buf[256]; FILE *fd; device->ip_addr = inet_addr(device_ip); if(device_mac && device_mac[0] != '\0') { // FIXME - this is not tested, might be wrong syntax for OS X // set the hw address before bringing the if up snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", i, device_mac); system(buf); } snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", i, device_ip, device_mask, mtu); system(buf); traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", i, device_ip, device_mask); // read MAC address snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); // traceEvent(TRACE_INFO, "%s", buf); fd = popen(buf, "r"); if(fd < 0) { tuntap_close(device); return -1; } else { int a, b, c, d, e, f; buf[0] = 0; fgets(buf, sizeof(buf), fd); pclose(fd); if(buf[0] == '\0') { traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); exit(0); } traceEvent(TRACE_NORMAL, "Interface tap%d mac %s", i, buf); if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { device->mac_addr[0] = a, device->mac_addr[1] = b; device->mac_addr[2] = c, device->mac_addr[3] = d; device->mac_addr[4] = e, device->mac_addr[5] = f; } } } // read_mac(dev, device->mac_addr); return device->fd; } int tuntap_read (struct tuntap_dev *tuntap, unsigned char *buf, int len) { return read(tuntap->fd, buf, len); } int tuntap_write (struct tuntap_dev *tuntap, unsigned char *buf, int len) { return write(tuntap->fd, buf, len); } void tuntap_close (struct tuntap_dev *tuntap) { close(tuntap->fd); } // fill out the ip_addr value from the interface, called to pick up dynamic address changes void tuntap_get_address (struct tuntap_dev *tuntap) { // no action } #endif /* #ifdef __FreeBSD__ */ ntop-n2n-90215bd/src/tuntap_linux.c000066400000000000000000000204751422132035700172110ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #ifdef __linux__ #include "n2n.h" static int setup_ifname (int fd, const char *ifname, const char *ipaddr, const char *netmask, uint8_t *mac, int mtu) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ-1] = '\0'; ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; memcpy(ifr.ifr_hwaddr.sa_data, mac, 6); if(ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) { traceEvent(TRACE_ERROR, "ioctl(SIOCSIFHWADDR) failed [%d]: %s", errno, strerror(errno)); return -1; } ifr.ifr_addr.sa_family = AF_INET; // interface address inet_pton(AF_INET, ipaddr, &((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr); if(ioctl(fd, SIOCSIFADDR, &ifr) == -1) { traceEvent(TRACE_ERROR, "ioctl(SIOCSIFADDR) failed [%d]: %s", errno, strerror(errno)); return -2; } // netmask if(netmask && (((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr != 0)) { inet_pton(AF_INET, netmask, &((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr); if(ioctl(fd, SIOCSIFNETMASK, &ifr) == -1) { traceEvent(TRACE_ERROR, "ioctl(SIOCSIFNETMASK, %s) failed [%d]: %s", netmask, errno, strerror(errno)); return -3; } } // MTU ifr.ifr_mtu = mtu; if(ioctl(fd, SIOCSIFMTU, &ifr) == -1) { traceEvent(TRACE_ERROR, "ioctl(SIOCSIFMTU) failed [%d]: %s", errno, strerror(errno)); return -4; } // set up and running if(ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) { traceEvent(TRACE_ERROR, "ioctl(SIOCGIFFLAGS) failed [%d]: %s", errno, strerror(errno)); return -5; } ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); if(ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) { traceEvent(TRACE_ERROR, "ioctl(SIOCSIFFLAGS) failed [%d]: %s", errno, strerror(errno)); return -6; } return 0; } /** @brief Open and configure the TAP device for packet read/write. * * This routine creates the interface via the tuntap driver and then * configures it. * * @param device - [inout] a device info holder object * @param dev - user-defined name for the new iface, * if NULL system will assign a name * @param device_ip - address of iface * @param device_mask - netmask for device_ip * @param mtu - MTU for device_ip * * @return - negative value on error * - non-negative file-descriptor on success */ int tuntap_open (tuntap_dev *device, char *dev, /* user-definable interface name, eg. edge0 */ const char *address_mode, /* static or dhcp */ char *device_ip, char *device_mask, const char * device_mac, int mtu) { char *tuntap_device = "/dev/net/tun"; int ioctl_fd; struct ifreq ifr; int rc; int nl_fd; char nl_buf[8192]; /* >= 8192 to avoid truncation, see "man 7 netlink" */ struct iovec iov; struct sockaddr_nl sa; int up_and_running = 0; struct msghdr msg; device->fd = open(tuntap_device, O_RDWR); if(device->fd < 0) { traceEvent(TRACE_ERROR, "tuntap open() error: %s[%d]. Is the tun kernel module loaded?\n", strerror(errno), errno); return -1; } memset(&ifr, 0, sizeof(ifr)); // want a TAP device for layer 2 frames ifr.ifr_flags = IFF_TAP|IFF_NO_PI; strncpy(ifr.ifr_name, dev, IFNAMSIZ-1); ifr.ifr_name[IFNAMSIZ-1] = '\0'; rc = ioctl(device->fd, TUNSETIFF, (void *)&ifr); if(rc < 0) { traceEvent(TRACE_ERROR, "tuntap ioctl(TUNSETIFF, IFF_TAP) error: %s[%d]\n", strerror(errno), rc); close(device->fd); return -1; } // store the device name for later reuse strncpy(device->dev_name, ifr.ifr_name, MIN(IFNAMSIZ, N2N_IFNAMSIZ)); if(device_mac && device_mac[0]) { // use the user-provided MAC str2mac(device->mac_addr, device_mac); } else { // set an explicit random MAC to know the exact MAC in use, manually // reading the MAC address is not safe as it may change internally // also after the TAP interface UP status has been notified memrnd(device->mac_addr, N2N_MAC_SIZE); // clear multicast bit device->mac_addr[0] &= ~0x01; // set locally-assigned bit device->mac_addr[0] |= 0x02; } // initialize netlink socket if((nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { traceEvent(TRACE_ERROR, "netlink socket creation failed [%d]: %s", errno, strerror(errno)); return -1; } iov.iov_base = nl_buf; iov.iov_len = sizeof(nl_buf); memset(&sa, 0, sizeof(sa)); sa.nl_family = PF_NETLINK; sa.nl_groups = RTMGRP_LINK; sa.nl_pid = getpid(); memset(&msg, 0, sizeof(msg)); msg.msg_name = &sa; msg.msg_namelen = sizeof(sa); msg.msg_iov = &iov; msg.msg_iovlen = 1; // subscribe to interface events if(bind(nl_fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { traceEvent(TRACE_ERROR, "netlink socket bind failed [%d]: %s", errno, strerror(errno)); return -1; } if((ioctl_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { traceEvent(TRACE_ERROR, "socket creation failed [%d]: %s", errno, strerror(errno)); close(nl_fd); return -1; } if(setup_ifname(ioctl_fd, device->dev_name, device_ip, device_mask, device->mac_addr, mtu) < 0) { close(nl_fd); close(ioctl_fd); close(device->fd); return -1; } close(ioctl_fd); // wait for the up and running notification traceEvent(TRACE_INFO, "Waiting for TAP interface to be up and running..."); while(!up_and_running) { ssize_t len = recvmsg(nl_fd, &msg, 0); struct nlmsghdr *nh; for(nh = (struct nlmsghdr *)nl_buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if(nh->nlmsg_type == NLMSG_ERROR) { traceEvent(TRACE_DEBUG, "nh->nlmsg_type == NLMSG_ERROR"); break; } if(nh->nlmsg_type == NLMSG_DONE) break; if(nh->nlmsg_type == NETLINK_GENERIC) { struct ifinfomsg *ifi = NLMSG_DATA(nh); // NOTE: skipping interface name check, assuming it's our TAP if((ifi->ifi_flags & IFF_UP) && (ifi->ifi_flags & IFF_RUNNING)) { up_and_running = 1; traceEvent(TRACE_INFO, "Interface is up and running"); break; } } } } close(nl_fd); device->ip_addr = inet_addr(device_ip); device->device_mask = inet_addr(device_mask); device->if_idx = if_nametoindex(dev); return device->fd; } int tuntap_read (struct tuntap_dev *tuntap, unsigned char *buf, int len) { return read(tuntap->fd, buf, len); } int tuntap_write (struct tuntap_dev *tuntap, unsigned char *buf, int len) { return write(tuntap->fd, buf, len); } void tuntap_close (struct tuntap_dev *tuntap) { close(tuntap->fd); } // fill out the ip_addr value from the interface, called to pick up dynamic address changes void tuntap_get_address (struct tuntap_dev *tuntap) { struct ifreq ifr; int fd; if((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { traceEvent(TRACE_ERROR, "socket creation failed [%d]: %s", errno, strerror(errno)); return; } ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, tuntap->dev_name, IFNAMSIZ); ifr.ifr_name[IFNAMSIZ-1] = '\0'; if(ioctl(fd, SIOCGIFADDR, &ifr) != -1) tuntap->ip_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; close(fd); } #endif /* #ifdef __linux__ */ ntop-n2n-90215bd/src/tuntap_netbsd.c000066400000000000000000000102461422132035700173240ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #ifdef __NetBSD__ #include #include #include #define N2N_NETBSD_TAPDEVICE_SIZE 32 void tun_close (tuntap_dev *device); int tuntap_open (tuntap_dev *device /* ignored */, char *dev, const char *address_mode, /* static or dhcp */ char *device_ip, char *device_mask, const char * device_mac, int mtu) { char tap_device[N2N_NETBSD_TAPDEVICE_SIZE]; struct ifreq req; if(dev) { snprintf(tap_device, sizeof(tap_device), "/dev/%s", dev); device->fd = open(tap_device, O_RDWR); snprintf(tap_device, sizeof(tap_device), "%s", dev); } else { device->fd = open("/dev/tap", O_RDWR); if(device->fd >= 0) { if(ioctl(device->fd, TAPGIFNAME, &req) == -1) { traceEvent(TRACE_ERROR, "Unable to obtain name of tap device (%s)", strerror(errno)); close(device->fd); return -1; } else { snprintf(tap_device, sizeof(tap_device), req.ifr_name); } } } if(device->fd < 0) { traceEvent(TRACE_ERROR, "Unable to open tap device (%s)", strerror(errno)); return -1; } else { char cmd[256]; FILE *fd; traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); device->ip_addr = inet_addr(device_ip); if(device_mac && device_mac[0] != '\0') { // set the hw address before bringing the if up snprintf(cmd, sizeof(cmd), "ifconfig %s link %s active", tap_device, device_mac); system(cmd); } snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s mtu %d up", tap_device, device_ip, device_mask, mtu); system(cmd); traceEvent(TRACE_NORMAL, "Interface %s up and running (%s/%s)", tap_device, device_ip, device_mask); // read MAC address snprintf(cmd, sizeof(cmd), "ifconfig %s |grep address|cut -c 11-28", tap_device); // traceEvent(TRACE_INFO, "%s", cmd); fd = popen(cmd, "r"); if(fd < 0) { tun_close(device); return -1; } else { int a, b, c, d, e, f; char buf[256]; buf[0] = 0; fgets(buf, sizeof(buf), fd); pclose(fd); if(buf[0] == '\0') { traceEvent(TRACE_ERROR, "Unable to read %s interface MAC address [%s]", tap_device, cmd); exit(0); } traceEvent(TRACE_NORMAL, "Interface %s mac %s", tap_device, buf); if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { device->mac_addr[0] = a, device->mac_addr[1] = b; device->mac_addr[2] = c, device->mac_addr[3] = d; device->mac_addr[4] = e, device->mac_addr[5] = f; } } } // read_mac(dev, device->mac_addr); return(device->fd); } int tuntap_read (struct tuntap_dev *tuntap, unsigned char *buf, int len) { return(read(tuntap->fd, buf, len)); } int tuntap_write (struct tuntap_dev *tuntap, unsigned char *buf, int len) { return(write(tuntap->fd, buf, len)); } void tuntap_close (struct tuntap_dev *tuntap) { close(tuntap->fd); } // fill out the ip_addr value from the interface, called to pick up dynamic address changes void tuntap_get_address (struct tuntap_dev *tuntap) { // no action } #endif /* #ifdef __NetBSD__ */ ntop-n2n-90215bd/src/tuntap_osx.c000066400000000000000000000075451422132035700166660ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include "n2n.h" #ifdef __APPLE__ #define N2N_OSX_TAPDEVICE_SIZE 32 void tun_close (tuntap_dev *device); int tuntap_open (tuntap_dev *device /* ignored */, char *dev, const char *address_mode, /* static or dhcp */ char *device_ip, char *device_mask, const char * device_mac, int mtu) { int i; char tap_device[N2N_OSX_TAPDEVICE_SIZE]; for(i = 0; i < 255; i++) { snprintf(tap_device, sizeof(tap_device), "/dev/tap%d", i); device->fd = open(tap_device, O_RDWR); if(device->fd > 0) { traceEvent(TRACE_NORMAL, "Succesfully open %s", tap_device); break; } } if(device->fd < 0) { traceEvent(TRACE_ERROR, "Unable to open any tap devices /dev/tap0 through /dev/tap254. Is this user properly authorized to access those descriptors?"); traceEvent(TRACE_ERROR, "Please read https://github.com/ntop/n2n/blob/dev/doc/Building.md"); return -1; } else { char buf[256]; FILE *fd; device->ip_addr = inet_addr(device_ip); if(device_mac && device_mac[0] != '\0') { // FIXME - this is not tested. might be wrong syntax for OS X // set the hw address before bringing the if up snprintf(buf, sizeof(buf), "ifconfig tap%d ether %s", i, device_mac); system(buf); } snprintf(buf, sizeof(buf), "ifconfig tap%d %s netmask %s mtu %d up", i, device_ip, device_mask, mtu); system(buf); traceEvent(TRACE_NORMAL, "Interface tap%d up and running (%s/%s)", i, device_ip, device_mask); // read MAC address snprintf(buf, sizeof(buf), "ifconfig tap%d |grep ether|cut -c 8-24", i); // traceEvent(TRACE_INFO, "%s", buf); fd = popen(buf, "r"); if(fd < 0) { tuntap_close(device); return -1; } else { int a, b, c, d, e, f; buf[0] = 0; fgets(buf, sizeof(buf), fd); pclose(fd); if(buf[0] == '\0') { traceEvent(TRACE_ERROR, "Unable to read tap%d interface MAC address"); exit(0); } traceEvent(TRACE_NORMAL, "Interface tap%d [MTU %d] mac %s", i, mtu, buf); if(sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", &a, &b, &c, &d, &e, &f) == 6) { device->mac_addr[0] = a, device->mac_addr[1] = b; device->mac_addr[2] = c, device->mac_addr[3] = d; device->mac_addr[4] = e, device->mac_addr[5] = f; } } } // read_mac(dev, device->mac_addr); return(device->fd); } int tuntap_read (struct tuntap_dev *tuntap, unsigned char *buf, int len) { return(read(tuntap->fd, buf, len)); } int tuntap_write (struct tuntap_dev *tuntap, unsigned char *buf, int len) { return(write(tuntap->fd, buf, len)); } void tuntap_close (struct tuntap_dev *tuntap) { close(tuntap->fd); } // fill out the ip_addr value from the interface, called to pick up dynamic address changes void tuntap_get_address (struct tuntap_dev *tuntap) { // no action } #endif /* __APPLE__ */ ntop-n2n-90215bd/src/wire.c000066400000000000000000000524671422132035700154330ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /** Routines for encoding and decoding n2n packets on the wire. * * encode_X(base,idx,v) prototypes are inspired by the erlang internal * encoding model. Passing the start of a buffer in base and a pointer to an * integer (initially set to zero). Each encode routine increases idx by the * amount written and returns the amount written. In this way complex sequences * of encodings can be represented cleanly. See encode_register() for an * example. */ #include "n2n.h" int encode_uint8 (uint8_t * base, size_t * idx, const uint8_t v) { *(base + (*idx)) = (v & 0xff); ++(*idx); return 1; } int decode_uint8 (uint8_t * out, const uint8_t * base, size_t * rem, size_t * idx) { if(*rem < 1) { return 0; } *out = ( base[*idx] & 0xff ); ++(*idx); --(*rem); return 1; } int encode_uint16 (uint8_t * base, size_t * idx, const uint16_t v) { *(base + (*idx)) = ( v >> 8) & 0xff; *(base + (1 + *idx)) = ( v & 0xff ); *idx += 2; return 2; } int decode_uint16 (uint16_t * out, const uint8_t * base, size_t * rem, size_t * idx) { if(*rem < 2) { return 0; } *out = ( base[*idx] & 0xff ) << 8; *out |= ( base[1 + *idx] & 0xff ); *idx += 2; *rem -= 2; return 2; } int encode_uint32 (uint8_t * base, size_t * idx, const uint32_t v) { *(base + (0 + *idx)) = ( v >> 24) & 0xff; *(base + (1 + *idx)) = ( v >> 16) & 0xff; *(base + (2 + *idx)) = ( v >> 8) & 0xff; *(base + (3 + *idx)) = ( v & 0xff ); *idx += 4; return 4; } int decode_uint32 (uint32_t * out, const uint8_t * base, size_t * rem, size_t * idx) { if(*rem < 4) { return 0; } *out = ( base[0 + *idx] & 0xff ) << 24; *out |= ( base[1 + *idx] & 0xff ) << 16; *out |= ( base[2 + *idx] & 0xff ) << 8; *out |= ( base[3 + *idx] & 0xff ); *idx += 4; *rem -= 4; return 4; } int encode_uint64 (uint8_t * base, size_t * idx, const uint64_t v) { *(uint64_t*)(base + *idx) = htobe64(v); *idx += 8; return 8; } int decode_uint64 (uint64_t * out, const uint8_t * base, size_t * rem, size_t * idx) { if(*rem < 8) { return 0; } *out = be64toh(*(uint64_t*)base + *idx); *idx += 8; *rem -= 8; return 8; } int encode_buf (uint8_t * base, size_t * idx, const void * p, size_t s) { memcpy((base + (*idx)), p, s); *idx += s; return s; } /* Copy from base to out of size bufsize */ int decode_buf (uint8_t * out, size_t bufsize, const uint8_t * base, size_t * rem, size_t * idx) { if(*rem < bufsize) { return 0; } memcpy(out, (base + *idx), bufsize); *idx += bufsize; *rem -= bufsize; return bufsize; } int encode_mac (uint8_t * base, /* n2n_mac_t is typedefed array type which is always passed by reference */ size_t * idx, const n2n_mac_t m) { return encode_buf(base, idx, m, N2N_MAC_SIZE); } int decode_mac (n2n_mac_t out, const uint8_t * base, size_t * rem, size_t * idx) { return decode_buf(out, N2N_MAC_SIZE, base, rem, idx); } int encode_cookie (uint8_t * base, size_t * idx, const n2n_cookie_t c) { return encode_uint32(base, idx, c); } int decode_cookie (n2n_cookie_t * out, /* cookies are typedef'd as uint32_t which needs to correspond to this code */ const uint8_t * base, size_t * rem, size_t * idx) { return decode_uint32(out, base, rem, idx); } int encode_common (uint8_t * base, size_t * idx, const n2n_common_t * common) { uint16_t flags = 0; encode_uint8(base, idx, N2N_PKT_VERSION); encode_uint8(base, idx, common->ttl); flags = common->pc & N2N_FLAGS_TYPE_MASK; flags |= common->flags & N2N_FLAGS_BITS_MASK; encode_uint16(base, idx, flags); encode_buf(base, idx, common->community, N2N_COMMUNITY_SIZE); return -1; } int decode_common (n2n_common_t * out, const uint8_t * base, size_t * rem, size_t * idx) { size_t idx0 = *idx; uint8_t dummy = 0; decode_uint8(&dummy, base, rem, idx); if(N2N_PKT_VERSION != dummy) { return -1; } decode_uint8(&(out->ttl), base, rem, idx); decode_uint16(&(out->flags), base, rem, idx); out->pc = (out->flags & N2N_FLAGS_TYPE_MASK); out->flags &= N2N_FLAGS_BITS_MASK; decode_buf(out->community, N2N_COMMUNITY_SIZE, base, rem, idx); return (*idx - idx0); } int encode_sock (uint8_t * base, size_t * idx, const n2n_sock_t * sock) { int retval = 0; uint16_t f; switch(sock->family) { case AF_INET: { f = 0; retval += encode_uint16(base, idx, f); retval += encode_uint16(base, idx, sock->port); retval += encode_buf(base, idx, sock->addr.v4, IPV4_SIZE); break; } case AF_INET6: { f = 0x8000; retval += encode_uint16(base, idx, f); retval += encode_uint16(base, idx, sock->port); retval += encode_buf(base, idx, sock->addr.v6, IPV6_SIZE); break; } default: retval = -1; } return retval; } int decode_sock (n2n_sock_t * sock, const uint8_t * base, size_t * rem, size_t * idx) { size_t * idx0 = idx; uint16_t f = 0; decode_uint16(&f, base, rem, idx); if(f & 0x8000) { /* IPv6 */ sock->family = AF_INET6; decode_uint16(&(sock->port), base, rem, idx); decode_buf(sock->addr.v6, IPV6_SIZE, base, rem, idx); } else { /* IPv4 */ sock->family = AF_INET; decode_uint16(&(sock->port), base, rem, idx); memset(sock->addr.v6, 0, IPV6_SIZE); /* so memcmp() works for equality. */ decode_buf(sock->addr.v4, IPV4_SIZE, base, rem, idx); } return (idx - idx0); } int encode_REGISTER (uint8_t *base, size_t *idx, const n2n_common_t *common, const n2n_REGISTER_t *reg) { int retval = 0; retval += encode_common(base, idx, common); retval += encode_cookie(base, idx, reg->cookie); retval += encode_mac(base, idx, reg->srcMac); retval += encode_mac(base, idx, reg->dstMac); if(common->flags & N2N_FLAGS_SOCKET) { retval += encode_sock(base, idx, &(reg->sock)); } retval += encode_uint32(base, idx, reg->dev_addr.net_addr); retval += encode_uint8(base, idx, reg->dev_addr.net_bitlen); retval += encode_buf(base, idx, reg->dev_desc, N2N_DESC_SIZE); return retval; } int decode_REGISTER (n2n_REGISTER_t *reg, const n2n_common_t *cmn, /* info on how to interpret it */ const uint8_t *base, size_t *rem, size_t *idx) { size_t retval = 0; memset(reg, 0, sizeof(n2n_REGISTER_t)); retval += decode_cookie(®->cookie, base, rem, idx); retval += decode_mac(reg->srcMac, base, rem, idx); retval += decode_mac(reg->dstMac, base, rem, idx); if(cmn->flags & N2N_FLAGS_SOCKET) { retval += decode_sock(&(reg->sock), base, rem, idx); } retval += decode_uint32(&(reg->dev_addr.net_addr), base, rem, idx); retval += decode_uint8(&(reg->dev_addr.net_bitlen), base, rem, idx); retval += decode_buf(reg->dev_desc, N2N_DESC_SIZE, base, rem, idx); return retval; } int encode_REGISTER_SUPER (uint8_t *base, size_t *idx, const n2n_common_t *common, const n2n_REGISTER_SUPER_t *reg) { int retval = 0; retval += encode_common(base, idx, common); retval += encode_cookie(base, idx, reg->cookie); retval += encode_mac(base, idx, reg->edgeMac); if(common->flags & N2N_FLAGS_SOCKET) { retval += encode_sock(base, idx, &(reg->sock)); } retval += encode_uint32(base, idx, reg->dev_addr.net_addr); retval += encode_uint8(base, idx, reg->dev_addr.net_bitlen); retval += encode_buf(base, idx, reg->dev_desc, N2N_DESC_SIZE); retval += encode_uint16(base, idx, reg->auth.scheme); retval += encode_uint16(base, idx, reg->auth.token_size); retval += encode_buf(base, idx, reg->auth.token, reg->auth.token_size); retval += encode_uint32(base, idx, reg->key_time); return retval; } int decode_REGISTER_SUPER (n2n_REGISTER_SUPER_t *reg, const n2n_common_t *cmn, /* info on how to interpret it */ const uint8_t *base, size_t *rem, size_t *idx) { size_t retval = 0; memset(reg, 0, sizeof(n2n_REGISTER_SUPER_t)); retval += decode_cookie(®->cookie, base, rem, idx); retval += decode_mac(reg->edgeMac, base, rem, idx); if(cmn->flags & N2N_FLAGS_SOCKET) { retval += decode_sock(&(reg->sock), base, rem, idx); } retval += decode_uint32(&(reg->dev_addr.net_addr), base, rem, idx); retval += decode_uint8(&(reg->dev_addr.net_bitlen), base, rem, idx); retval += decode_buf(reg->dev_desc, N2N_DESC_SIZE, base, rem, idx); retval += decode_uint16(&(reg->auth.scheme), base, rem, idx); retval += decode_uint16(&(reg->auth.token_size), base, rem, idx); retval += decode_buf(reg->auth.token, reg->auth.token_size, base, rem, idx); retval += decode_uint32(&(reg->key_time), base, rem, idx); return retval; } int encode_UNREGISTER_SUPER (uint8_t *base, size_t *idx, const n2n_common_t *common, const n2n_UNREGISTER_SUPER_t *unreg) { int retval = 0; retval += encode_common(base, idx, common); retval += encode_uint16(base, idx, unreg->auth.scheme); retval += encode_uint16(base, idx, unreg->auth.token_size); retval += encode_buf(base, idx, unreg->auth.token, unreg->auth.token_size); retval += encode_mac(base, idx, unreg->srcMac); return retval; } int decode_UNREGISTER_SUPER (n2n_UNREGISTER_SUPER_t *unreg, const n2n_common_t *cmn, /* info on how to interpret it */ const uint8_t *base, size_t *rem, size_t *idx) { size_t retval = 0; memset(unreg, 0, sizeof(n2n_UNREGISTER_SUPER_t)); retval += decode_uint16(&(unreg->auth.scheme), base, rem, idx); retval += decode_uint16(&(unreg->auth.token_size), base, rem, idx); retval += decode_buf(unreg->auth.token, unreg->auth.token_size, base, rem, idx); retval += decode_mac(unreg->srcMac, base, rem, idx); return retval; } int encode_REGISTER_ACK (uint8_t *base, size_t *idx, const n2n_common_t *common, const n2n_REGISTER_ACK_t *reg) { int retval = 0; retval += encode_common(base, idx, common); retval += encode_cookie(base, idx, reg->cookie); retval += encode_mac(base, idx, reg->dstMac); retval += encode_mac(base, idx, reg->srcMac); /* The socket in REGISTER_ACK is the socket from which the REGISTER * arrived. This is sent back to the sender so it knows what its public * socket is. */ if(common->flags & N2N_FLAGS_SOCKET) { retval += encode_sock(base, idx, &(reg->sock)); } return retval; } int decode_REGISTER_ACK (n2n_REGISTER_ACK_t *reg, const n2n_common_t *cmn, /* info on how to interpret it */ const uint8_t *base, size_t *rem, size_t *idx) { size_t retval = 0; memset(reg, 0, sizeof(n2n_REGISTER_ACK_t)); retval += decode_cookie(®->cookie, base, rem, idx); retval += decode_mac(reg->dstMac, base, rem, idx); retval += decode_mac(reg->srcMac, base, rem, idx); /* The socket in REGISTER_ACK is the socket from which the REGISTER * arrived. This is sent back to the sender so it knows what its public * socket is. */ if(cmn->flags & N2N_FLAGS_SOCKET) { retval += decode_sock(&(reg->sock), base, rem, idx); } return retval; } int encode_REGISTER_SUPER_ACK (uint8_t *base, size_t *idx, const n2n_common_t *common, const n2n_REGISTER_SUPER_ACK_t *reg, uint8_t *tmpbuf) { int retval = 0; retval += encode_common(base, idx, common); retval += encode_cookie(base, idx, reg->cookie); retval += encode_mac(base, idx, reg->srcMac); retval += encode_uint32(base, idx, reg->dev_addr.net_addr); retval += encode_uint8(base, idx, reg->dev_addr.net_bitlen); retval += encode_uint16(base, idx, reg->lifetime); retval += encode_sock(base, idx, &(reg->sock)); retval += encode_uint16(base, idx, reg->auth.scheme); retval += encode_uint16(base, idx, reg->auth.token_size); retval += encode_buf(base, idx, reg->auth.token, reg->auth.token_size); retval += encode_uint8(base, idx, reg->num_sn); retval += encode_buf(base, idx, tmpbuf, (reg->num_sn*REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE)); retval += encode_uint32(base, idx, reg->key_time); return retval; } int decode_REGISTER_SUPER_ACK (n2n_REGISTER_SUPER_ACK_t *reg, const n2n_common_t *cmn, /* info on how to interpret it */ const uint8_t *base, size_t *rem, size_t *idx, uint8_t *tmpbuf) { size_t retval = 0; memset(reg, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); retval += decode_cookie(®->cookie, base, rem, idx); retval += decode_mac(reg->srcMac, base, rem, idx); retval += decode_uint32(&(reg->dev_addr.net_addr), base, rem, idx); retval += decode_uint8(&(reg->dev_addr.net_bitlen), base, rem, idx); retval += decode_uint16(&(reg->lifetime), base, rem, idx); /* Socket is mandatory in this message type */ retval += decode_sock(&(reg->sock), base, rem, idx); retval += decode_uint16(&(reg->auth.scheme), base, rem, idx); retval += decode_uint16(&(reg->auth.token_size), base, rem, idx); retval += decode_buf(reg->auth.token, reg->auth.token_size, base, rem, idx); /* Following the edge socket are an array of backup supernodes. */ retval += decode_uint8(&(reg->num_sn), base, rem, idx); retval += decode_buf(tmpbuf, (reg->num_sn * REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE), base, rem, idx); retval += decode_uint32(&(reg->key_time), base, rem, idx); return retval; } int encode_REGISTER_SUPER_NAK (uint8_t *base, size_t *idx, const n2n_common_t *common, const n2n_REGISTER_SUPER_NAK_t *nak) { int retval = 0; retval += encode_common(base, idx, common); retval += encode_cookie(base, idx, nak->cookie); retval += encode_mac(base, idx, nak->srcMac); retval += encode_uint16(base, idx, nak->auth.scheme); retval += encode_uint16(base, idx, nak->auth.token_size); retval += encode_buf(base, idx, nak->auth.token, nak->auth.token_size); return retval; } int decode_REGISTER_SUPER_NAK (n2n_REGISTER_SUPER_NAK_t *nak, const n2n_common_t *cmn, /* info on how to interpret it */ const uint8_t *base, size_t *rem, size_t *idx) { size_t retval = 0; memset(nak, 0, sizeof(n2n_REGISTER_SUPER_NAK_t)); retval += decode_cookie(&nak->cookie, base, rem, idx); retval += decode_mac(nak->srcMac, base, rem, idx); retval += decode_uint16(&(nak->auth.scheme), base, rem, idx); retval += decode_uint16(&(nak->auth.token_size), base, rem, idx); retval += decode_buf(nak->auth.token, nak->auth.token_size, base, rem, idx); return retval; } int fill_sockaddr (struct sockaddr * addr, size_t addrlen, const n2n_sock_t * sock) { int retval = -1; if(AF_INET == sock->family) { if(addrlen >= sizeof(struct sockaddr_in)) { struct sockaddr_in * si = (struct sockaddr_in *)addr; si->sin_family = sock->family; si->sin_port = htons(sock->port); memcpy(&(si->sin_addr.s_addr), sock->addr.v4, IPV4_SIZE); retval = 0; } } return retval; } int encode_PACKET (uint8_t * base, size_t * idx, const n2n_common_t * common, const n2n_PACKET_t * pkt) { int retval = 0; retval += encode_common(base, idx, common); retval += encode_mac(base, idx, pkt->srcMac); retval += encode_mac(base, idx, pkt->dstMac); if(common->flags & N2N_FLAGS_SOCKET) { retval += encode_sock(base, idx, &(pkt->sock)); } retval += encode_uint8(base, idx, pkt->compression); retval += encode_uint8(base, idx, pkt->transform); return retval; } int decode_PACKET (n2n_PACKET_t * pkt, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx) { size_t retval = 0; memset(pkt, 0, sizeof(n2n_PACKET_t)); retval += decode_mac(pkt->srcMac, base, rem, idx); retval += decode_mac(pkt->dstMac, base, rem, idx); if(cmn->flags & N2N_FLAGS_SOCKET) { retval += decode_sock(&(pkt->sock), base, rem, idx); } retval += decode_uint8(&(pkt->compression), base, rem, idx); retval += decode_uint8(&(pkt->transform), base, rem, idx); return retval; } int encode_PEER_INFO (uint8_t *base, size_t *idx, const n2n_common_t *cmn, const n2n_PEER_INFO_t *pkt) { int retval = 0; retval += encode_common(base, idx, cmn); retval += encode_uint16(base, idx, pkt->aflags); retval += encode_mac(base, idx, pkt->srcMac); retval += encode_mac(base, idx, pkt->mac); retval += encode_sock(base, idx, &pkt->sock); if(cmn->flags & N2N_FLAGS_SOCKET) { retval += encode_sock(base, idx, &pkt->preferred_sock); } retval += encode_uint32(base, idx, (uint32_t)pkt->load); retval += encode_uint32(base, idx, (uint32_t)pkt->uptime); retval += encode_buf(base, idx, pkt->version, sizeof(n2n_version_t)); return retval; } int decode_PEER_INFO (n2n_PEER_INFO_t *pkt, const n2n_common_t *cmn, /* info on how to interpret it */ const uint8_t *base, size_t *rem, size_t *idx) { size_t retval = 0; memset(pkt, 0, sizeof(n2n_PEER_INFO_t)); retval += decode_uint16(&(pkt->aflags), base, rem, idx); retval += decode_mac(pkt->srcMac, base, rem, idx); retval += decode_mac(pkt->mac, base, rem, idx); retval += decode_sock(&pkt->sock, base, rem, idx); if(cmn->flags & N2N_FLAGS_SOCKET) { retval += decode_sock(&pkt->preferred_sock, base, rem, idx); } retval += decode_uint32(&pkt->load, base, rem, idx); retval += decode_uint32((uint32_t*)&pkt->uptime, base, rem, idx); retval += decode_buf((uint8_t*)pkt->version, sizeof(n2n_version_t), base, rem, idx); return retval; } int encode_QUERY_PEER (uint8_t * base, size_t * idx, const n2n_common_t * common, const n2n_QUERY_PEER_t * pkt) { int retval = 0; retval += encode_common(base, idx, common); retval += encode_mac(base, idx, pkt->srcMac); retval += encode_mac(base, idx, pkt->targetMac); retval += encode_uint16(base, idx, pkt->aflags); return retval; } int decode_QUERY_PEER (n2n_QUERY_PEER_t * pkt, const n2n_common_t * cmn, /* info on how to interpret it */ const uint8_t * base, size_t * rem, size_t * idx) { size_t retval = 0; memset(pkt, 0, sizeof(n2n_QUERY_PEER_t)); retval += decode_mac(pkt->srcMac, base, rem, idx); retval += decode_mac(pkt->targetMac, base, rem, idx); retval += decode_uint16(&(pkt->aflags), base, rem, idx); return retval; } ntop-n2n-90215bd/supernode.1000066400000000000000000000107051422132035700156050ustar00rootroot00000000000000.TH supernode 1 "Jul 16, 2021" "version 3" "USER COMMANDS" .SH NAME supernode \- n2n supernode daemon .SH SYNOPSIS .B supernode .br .B supernode [OPTION]... .SH DESCRIPTION N2N is a peer-to-peer VPN system. Supernode is a node introduction registry, broadcast conduit and packet relay node for the n2n system. On startup supernode begins listening on the specified UDP port for node registrations, and other packets to route. The supernode can service any number of communities and routes packets only between members of the same community. The supernode does not hold the community encryption key and so cannot snoop or inject packets into the community. .PP Supernode can service a number of n2n communities concurrently. Traffic does not cross between communities. .PP All logging goes to stdout. .PP The config file is similar to the command line, with one option per line. Lines starting with a "#" are ignored. An equal sign ('=') should be used between key and value. Example: -p=7777 .SH OPTIONS FOR THE UNDERLYING NETWORK CONNECTION .TP \fB\-p \fR<\fIlocal_port\fR>, \fB\-\-local-port\fR=<\fIlocal_port\fR> listen on this fixed local UDP port, defaults to 7654 .TP \fB\-F \fR<\fIfed_name\fR> name of the supernode's federation, defaults to '*Federation' (see also N2N_FEDERATION in ENVIRONMENT) .TP \fB\-l \fR<\fIhost:port\fR> ip address or name, and port of known supernode .TP \fB\-m \fR<\fImac_address\fR> fixed MAC address for the supernode, e.g. '-m 10:20:30:40:50:60', random otherwise .TP \fB\-M\fR disable MAC and IP address spoofing protection for all non-username-password-authenticating communities .TP \fB\-V \fR<\fIversion_string\fR> modify the supernode version string which is distributed to the edges and shown at their management port output, up to 19 characters .TP .SH TAP DEVICE AND OVERLAY NETWORK CONFIGURATION .TP \fB\-c \fR<\fIpath\fR>, \fB\-\-communities\fR=<\fIpath\fR> file containing the allowed communities and any User / Password based authentication details (See ALLOWED COMMUNITIES FILE section) .TP \fB\-a \fR<\fInet-net/n\fR>, \fB\-\-autoip\fR= subnet range for auto ip address service, .br e.g. '-a 192.168.0.0-192.168.255.0/24', .br defaults to '10.128.255.0-10.255.255.0/24' .SH LOCAL OPTIONS .TP \fB\-f\fR, \fB\-\-foreground\fR disable daemon mode (UNIX) and run in foreground. .TP \fB\-t \fR<\fIport\fR>, \fB\-\-mgmt-port\fR=<\fIport\fR> management UDP port, for multiple supernodes on a machine, defaults to 5645 .TP \fB\-\-management-password \fR<\fIpassword\fR> sets the password for access to JSON API at the management port, defaults to 'n2n'. The password has to be provided for relevant access to JSON API at the management port. .TP \fB\-v\fR, \fB\-\-verbose\fR use verbose logging .TP \fB\-u \fR<\fIUID\fR> numeric user ID to use when privileges are dropped .TP \fB\-g \fR<\fIGID\fR> numeric group ID to use when privileges are dropped .TP \fB-h\fR shows a quick reference including all available options .TP \fB\-\-help\fR shows detailed parameter description .SH ALLOWED COMMUNITIES FILE This file is a plain text file. Comments are introduced with a hash at the beginning of the line. A line that begins with an asterisk is a user authentication definition and adds an allowed user to the most recently defined community. Allowed communities can be specified with a regular expression. .PP Example community file: .PP .nf .RS # List of allowed communities mynetwork netleo * logan nHWum+r42k1qDXdIeH-WFKeylK5UyLStRzxofRNAgpG * sister HwHpPrdMft+38tFDDiunUds6927t0+zhCMMkQdJafcC .RE .fi .PP More details on creating the allowed communities file are found in the Communities.md and Authentication.md documentation included with this package. .SH ENVIRONMENT .TP .B N2N_FEDERATION set the federation name so it is not visible at the command line .SH EXAMPLES .TP .B supernode -p 7654 -v Start supernode listening on UDP port 7654 with verbose output. .TP .B echo | nc -w1 -u 127.0.0.1 5645 Shows the management status of a running supernode. .PP .SH RESTART When supernode restarts it loses all registration information from associated edge nodes. It can take up to five minutes for the edge nodes to re-register and normal traffic flow to resume. .SH EXIT STATUS supernode is a daemon and any exit is an error .SH AUTHOR Luca Deri ( deri (at) ntop.org ), Richard Andrews ( andrews (at) ntop.org ), Don Bindner .SH SEE ALSO ifconfig(8) edge(8) .br the documentation contained in the source code .br the extensive documentation found in n2n's \fBdoc/\fR folder ntop-n2n-90215bd/tests/000077500000000000000000000000001422132035700146565ustar00rootroot00000000000000ntop-n2n-90215bd/tests/test_integration_edge.sh.expected000066400000000000000000000011721422132035700233610ustar00rootroot00000000000000### ### [ { "community": "test" } ] ### [ { "rx_pkt": 0, "tx_pkt": 2, "type": "transop" }, { "rx_pkt": 0, "tx_pkt": 0, "type": "p2p" }, { "rx_pkt": 0, "tx_pkt": 2, "type": "super" }, { "rx_pkt": 0, "tx_pkt": 2, "type": "super_broadcast" } ] ### [] ### [ { "traceLevel": 2 } ] ### 0 ### [ { "traceLevel": 1 } ] ### [ { "keep_running": 1 } ] ### [ { "keep_running": 0 } ] ### [ { "keep_running": 0 } ] ntop-n2n-90215bd/tests/test_integration_supernode.sh.expected000066400000000000000000000011151422132035700244560ustar00rootroot00000000000000### ### [ { "community": "-/-", "ip4addr": "", "is_federation": 1, "purgeable": 0 } ] ### [ { "tx_pkt": 0, "type": "forward" }, { "tx_pkt": 0, "type": "broadcast" }, { "nak": 0, "rx_pkt": 0, "type": "reg_super" }, { "tx_pkt": 0, "type": "errors" } ] ### [] ### [ { "traceLevel": 3 } ] ### [ { "traceLevel": 1 } ] ### [ { "keep_running": 1 } ] ### [ { "keep_running": 0 } ] ntop-n2n-90215bd/tests/tests-auth.expected000066400000000000000000000027541422132035700205120ustar00rootroot00000000000000bin_to_ascii: input size = 0x10 000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | bin_to_ascii: output: 00420mG51WS82GeB30qE3m ascii_to_bin: input = 00420mG51WS82GeB30qE3m ascii_to_bin: output: 000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | | generate_private_key: input = 00420mG51WS82GeB30qE3m generate_private_key: output: 000: a4 f4 b5 1c 8a 0a 09 f9 7e 98 22 ca 8a cc b3 f9 | ~ " | 010: 4d 5a 0d 02 0b 9d 08 ea 03 9b 46 41 8e 3c 0d 49 |MZ FA < I| generate_public_key: input: 000: a4 f4 b5 1c 8a 0a 09 f9 7e 98 22 ca 8a cc b3 f9 | ~ " | 010: 4d 5a 0d 02 0b 9d 08 ea 03 9b 46 41 8e 3c 0d 49 |MZ FA < I| generate_public_key: output: 000: ca 58 61 6f f9 25 d0 cd 1d a5 62 48 a0 15 5e ad | Xao % bH ^ | 010: a9 f3 5c 10 5f 20 b6 42 b0 a9 7c 1e 0e d7 e9 4b | \ _ B | K| generate_shared_secret: input: prv 000: a4 f4 b5 1c 8a 0a 09 f9 7e 98 22 ca 8a cc b3 f9 | ~ " | 010: 4d 5a 0d 02 0b 9d 08 ea 03 9b 46 41 8e 3c 0d 49 |MZ FA < I| generate_shared_secret: input: pub 000: ca 58 61 6f f9 25 d0 cd 1d a5 62 48 a0 15 5e ad | Xao % bH ^ | 010: a9 f3 5c 10 5f 20 b6 42 b0 a9 7c 1e 0e d7 e9 4b | \ _ B | K| generate_shared_secret: output: 000: 5d 94 7b 0b db 54 e8 70 8a 09 b0 db 6f 0b 0d 31 |] { T p o 1| 010: 1b b8 5f ba 57 74 34 bd 3b c5 c4 6c d5 ae a4 84 | _ Wt4 ; l | ntop-n2n-90215bd/tests/tests-compress.expected000066400000000000000000000055451422132035700214050ustar00rootroot00000000000000original: input size = 0x200 000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 010: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 020: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 030: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 040: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 050: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 060: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 070: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 080: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 090: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0a0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0b0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0c0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0d0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0e0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0f0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 100: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 110: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 120: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 130: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 140: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 150: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 160: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 170: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 180: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 190: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1a0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1b0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1c0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1d0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1e0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1f0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | lzo1x: output size = 0x2f 000: 0d 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e | | 010: 0f 20 00 bc 3c 00 00 02 0c 0d 0e 0f 00 01 02 03 | < | 020: 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 11 00 00 | | zstd: output size = 0x21 000: 28 b5 2f fd 60 00 01 bd 00 00 80 00 01 02 03 04 |( / ` | 010: 05 06 07 08 09 0a 0b 0c 0d 0e 0f 01 00 da 47 9d | G | 020: 4b |K| ntop-n2n-90215bd/tests/tests-elliptic.expected000066400000000000000000000007731422132035700213550ustar00rootroot00000000000000environment: input 000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | | 010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 | | environment: key 000: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 |UUUUUUUUUUUUUUUU| 010: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 |UUUUUUUUUUUUUUUU| curve25519: output 000: 7f 42 1b f9 34 5a 59 84 4a 30 bc 53 64 74 fa 7c | B 4ZY J0 Sdt || 010: 15 81 77 a4 4d 34 6d 2f 8b c1 8c 05 d6 a9 44 54 | w M4m/ DT| ntop-n2n-90215bd/tests/tests-hashing.expected000066400000000000000000000054151422132035700211670ustar00rootroot00000000000000environment: input size = 0x200 000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 010: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 020: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 030: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 040: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 050: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 060: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 070: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 080: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 090: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0a0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0b0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0c0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0d0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0e0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0f0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 100: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 110: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 120: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 130: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 140: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 150: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 160: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 170: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 180: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 190: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1a0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1b0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1c0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1d0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1e0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1f0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | pearson_hash_256: output: 000: 40 09 5c ca 28 6b fb 93 4c 4a f7 c0 79 a8 04 5a |@ \ (k LJ y Z| 010: b5 3d cf b3 a7 ed 18 56 b2 d9 8f a8 2e a1 08 be | = V . | pearson_hash_128: output: 000: b5 3d cf b3 a7 ed 18 56 b2 d9 8f a8 2e a1 08 be | = V . | pearson_hash_64: output = 0xb2d98fa82ea108be pearson_hash_32: output = 0x2ea108be pearson_hash_16: output = 0x8be ntop-n2n-90215bd/tests/tests-transform.expected000066400000000000000000000407761422132035700215720ustar00rootroot00000000000000environment: community_name = "abc123def456" environment: encrypt_key = "SoMEVer!S$cUREPassWORD" environment: input size = 0x200 000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 010: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 020: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 030: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 040: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 050: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 060: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 070: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 080: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 090: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0a0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0b0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0c0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0d0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0e0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 0f0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 100: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 110: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 120: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 130: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 140: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 150: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 160: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 170: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 180: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 190: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1a0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1b0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1c0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1d0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1e0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | 1f0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | | null: output size = 0x226 000: 03 02 00 03 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| 010: 00 00 00 00 00 00 00 00 00 01 02 03 04 05 00 01 | | 020: 02 03 04 05 00 00 00 01 02 03 04 05 06 07 08 09 | | 030: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 040: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 050: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 060: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 070: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 080: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 090: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 0a0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 0b0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 0c0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 0d0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 0e0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 0f0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 100: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 110: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 120: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 130: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 140: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 150: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 160: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 170: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 180: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 190: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 1a0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 1b0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 1c0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 1d0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 1e0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 1f0: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 200: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 210: 0a 0b 0c 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 | | 220: 0a 0b 0c 0d 0e 0f | | tf: output size = 0x236 000: 03 02 00 03 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| 010: 00 00 00 00 00 00 00 00 00 01 02 03 04 05 00 01 | | 020: 02 03 04 05 00 00 69 54 ba b7 b9 00 7e 1f 4e 43 | iT ~ NC| 030: 6b 6e c0 b7 5a bb e1 6a 7d 8b f6 41 9e fb 7e c1 |kn Z j} A ~ | 040: a8 6c 67 6b c7 27 17 32 9b 89 f2 5d 1d 67 49 de | lgk ' 2 ] gI | 050: ab 5c d4 b7 a1 97 99 76 7d 90 8d 2c 7c 0d 65 66 | \ v} ,| ef| 060: d5 7f 1a 3b bf 0c 52 b3 42 0d c8 c8 0d 62 8e 4b | ; R B b K| 070: 98 7b bc 0d 9c db bf 61 dc 9d 9f 44 a4 fc 8d 1a | { a D | 080: 70 f0 14 87 89 0e 4a b8 7e 66 72 7a 04 6e 9b 17 |p J ~frz n | 090: e1 2c 06 ce 52 04 2a a0 0f 7f 76 f4 5c c5 e2 09 | , R * v \ | 0a0: f6 35 ff ad 87 ab 72 5a 6f bc 61 78 f6 3c 48 e2 | 5 rZo ax | 1a0: a7 fc d2 83 5b 61 b1 e0 fd 28 d1 ec 65 a2 cf 6c | [a ( e l| 1b0: ef 3b ad cc 75 e3 f9 71 0f 90 71 a6 bc 1a d5 17 | ; u q q | 1c0: 65 64 3e 0c d2 c8 de bd 1f d5 af 84 fc fe aa bd |ed> | 1d0: c5 88 13 af 09 ee 8c c0 38 49 79 09 a7 7a 01 48 | 8Iy z H| 1e0: 2e 3e 9a 38 1b c6 b8 c0 a9 4e 61 0f 19 2a 95 84 |.> 8 Na * | 1f0: 3b 53 1c db 9a ec af 8f 2d af 73 d5 cc 71 bd 42 |;S - s q B| 200: 4f e2 70 ca 45 b6 44 18 54 fe 6b 23 31 ba f4 b1 |O p E D T k#1 | 210: 02 a1 26 4f f1 a9 c0 78 e6 3b 11 9e d6 3c 61 e5 | &O x ; e 9 | 150: c2 4c 3d 3e 73 a7 15 fc 28 6c a6 e5 8b 16 bd c9 | L=>s (l | 160: e2 c9 5e d9 64 8e bc f5 92 a4 e5 74 04 cb 9c 90 | ^ d t | 170: 0c 10 28 5f 30 10 61 b7 44 50 b1 f9 3e 21 a1 41 | (_0 a DP >! A| 180: c2 e2 a5 e9 f7 33 16 52 32 61 d1 a3 c5 0b 61 d4 | 3 R2a a | 190: 53 0f 65 a8 d9 e1 fb e1 9b 1b 61 16 d1 75 0a 4b |S e a u K| 1a0: 9a 9f d1 f3 4e f6 ca b2 a2 24 50 8b 10 4d 45 54 | N $P MET| 1b0: 3d e1 c2 8f 07 52 67 52 7e d1 7f 99 3c 4e de eb |= RgR~ g|[2 6. | 080: 74 50 9f a3 de 38 4e c7 ca 6b 35 7c 1b 4e 39 ea |tP 8N k5| N9 | 090: 5f e2 8a 80 d9 58 6e 14 32 bf 8e e9 a2 b0 19 8a |_ Xn 2 | 0a0: e1 1d da fa 3f 4a b7 1c 03 e0 e3 17 85 54 84 c8 | ?J T | 0b0: 3e 90 8e 85 5b e7 12 3d 73 9e b9 ef 7e 48 c0 55 |> [ =s ~H U| 0c0: 59 28 29 f4 d1 12 62 b3 b3 db 65 0a 6c 8c 44 be |Y() b e l D | 0d0: e2 76 49 e6 b6 4a 9e 7e 9c 49 c9 10 d3 dc 85 33 | vI J ~ I 3| 0e0: fe eb a5 dc 5e 18 cf dc 9a 99 da bc 5c 9f c1 ff | ^ \ | 0f0: 9c 92 3b a9 9d d6 5d 03 f4 f3 5e a9 52 21 d2 d0 | ; ] ^ R! | 100: 8b 4e 8a b6 06 af 4e 34 98 e2 bc 9b c2 f1 9d 72 | N N4 r| 110: f8 0f f3 d5 83 34 7d 47 fe bf 6c 1d c2 d3 89 a4 | 4}G l | 120: ff 5b 76 3c cb 9b 4d 09 a6 3a a2 2f 0b 8d 7a 34 | [v< M : / z4| 130: 12 d5 73 c4 bc ba 13 76 e7 69 50 6d 50 ab 76 b5 | s v iPmP v | 140: a6 fb b4 fb c7 98 3d ac ce e1 e1 98 97 9f 24 98 | = $ | 150: 90 82 61 00 38 57 b0 36 7d 55 a7 70 9c ee 51 26 | a 8W 6}U p Q&| 160: 47 02 4f b5 fe cc 2c e0 07 c6 7b 04 6d a1 89 dc |G O , { m | 170: e8 98 71 fd 27 54 d1 f1 2d 0b 3e 64 ef 02 74 71 | q 'T - >d tq| 180: db f5 b1 84 87 6d c9 37 c5 c3 3a de ea 1b 53 d3 | m 7 : S | 190: f1 ed 8f 24 2d 74 a3 77 23 20 9b 75 c3 f2 ef 4a | $-t w# u J| 1a0: 75 ec d3 86 59 11 c5 fc b0 ed 79 b0 8e a8 03 c8 |u Y y | 1b0: 3e 05 db b0 65 62 53 e5 ef e7 95 88 ce 62 89 7a |> ebS b z| 1c0: 9d 3c bc ea a4 3a f6 df 1d 10 8a a3 80 7c 3b 80 | < : |; | 1d0: be 0a 27 76 2b bc 7d 02 98 bf b7 5e 4a 4c 53 df | 'v+ } ^JLS | 1e0: 57 ff 67 7e 33 6a 00 4c ff d6 c0 ff 3f 1c 24 f7 |W g~3j L ? $ | 1f0: fb fd 3b d2 4f 18 e3 9d 62 5b 9b 15 68 13 44 d8 | ; O b[ h D | 200: 71 79 9d b1 ab 2f bd f3 44 6b 77 96 b8 44 bc 90 |qy / Dkw D | 210: 1f 74 db d2 73 7d 5d 44 f7 a6 92 4e fa 24 e3 92 | t s}]D N $ | 220: c8 34 c7 1d 16 8b f5 80 d9 15 48 24 12 16 14 76 | 4 H$ v| 230: 15 5f d0 dc 1e 9c | _ | speck: output size = 0x236 000: 03 02 00 03 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| 010: 00 00 00 00 00 00 00 00 00 01 02 03 04 05 00 01 | | 020: 02 03 04 05 00 00 69 c2 17 4a ab 55 f3 8d 44 17 | i J U D | 030: 2c 31 09 b5 b0 2f 0c 87 f2 05 13 59 34 49 72 45 |,1 / Y4IrE| 040: 2c 79 51 cf 39 f5 ce 0e b9 fc c8 41 31 08 e9 a5 |,yQ 9 A1 | 050: 54 3c aa 77 aa 29 10 41 4a 16 4b e9 89 8f 92 7b |T< w ) AJ K {| 060: 29 b3 0b 4b 84 92 2a 3a fe bd c0 50 75 fc a4 7e |) K *: Pu ~| 070: 4e 20 2e 3b 53 eb d1 37 43 35 b6 5e 55 a6 5e 0e |N .;S 7C5 ^U ^ | 080: e3 05 db 07 5f a8 74 4d 9f 41 ed 5f 44 93 98 9b | _ tM A _D | 090: fb 48 3c 9c 36 8b a6 71 ed ee f4 e6 10 21 b1 b5 | H< 6 q ! | 0a0: f4 b7 28 db d5 5d 43 3d 4b 8d 1a 33 cf c5 54 09 | ( ]C=K 3 T | 0b0: b6 9d f5 f2 27 2f e7 be dd 4c 3c 5c c8 71 ca 71 | '/ L<\ q q| 0c0: 8c 47 37 21 6c ad 3f d6 9a 99 ab 18 fc d8 1b c7 | G7!l ? | 0d0: 72 c2 7d fb 57 8c 97 4f 77 4c 6c 94 4a ab f4 94 |r } W OwLl J | 0e0: d8 e3 02 e2 b9 bf 12 47 fb 53 aa b8 4a 93 38 c6 | G S J 8 | 0f0: bb 8b 27 8b d6 db f3 e4 e3 43 7e 7f 83 cf c9 df | ' C~ | 100: e5 71 b9 80 9c ad 38 e5 10 aa 99 ad e1 0d 34 6f | q 8 4o| 110: de 7e ff 29 cc fe b5 89 49 a9 a1 b5 9e 9f be 5e | ~ ) I ^| 120: e6 d2 74 2c 57 91 86 40 02 a0 7b 6b 42 6e b0 63 | t,W @ {kBn c| 130: 0e 04 19 7c f0 e5 ff 3d db de e3 c5 fc 70 18 7d | | = p }| 140: 06 33 7e 6a bb 46 3b 94 28 85 87 51 9f 6e 95 22 | 3~j F; ( Q n "| 150: 99 b4 34 bd 29 94 3a a8 a4 ff 5b 19 53 69 cb e5 | 4 ) : [ Si | 160: a6 0c 41 c5 22 89 82 a7 a5 f3 f3 49 ed 5d ce f3 | A " I ] | 170: a7 ee 77 dd a9 aa 26 5b 85 ec b1 6e f4 33 a0 b8 | w &[ n 3 | 180: 93 2a 80 6f 3f 5f 0a ff 1b 72 14 5d 4f 1a cc 74 | * o?_ r ]O t| 190: 69 01 da 81 7d 89 4b 0f 68 fe c6 c5 ae 39 86 1d |i } K h 9 | 1a0: ab e3 c7 35 2e 5d a8 3d 56 3e 26 52 74 72 5b f2 | 5.] =V>&Rtr[ | 1b0: 41 1a 7a 04 d9 d0 65 fe 92 c4 b9 be 75 e5 9e e1 |A z e u | 1c0: 8e 52 f4 27 98 44 61 26 7f 6b 96 0c c4 6a a6 6b | R ' Da& k j k| 1d0: 36 66 81 a1 f6 dd ab 2a a7 63 e5 7f 63 67 79 08 |6f * c cgy | 1e0: ba 7b bb 11 12 9c 14 b2 a4 2b 56 66 14 c1 54 c6 | { +Vf T | 1f0: 96 f0 e4 68 8a 5c 11 b6 27 af 61 ef ab 47 9e 7f | h \ ' a G | 200: 76 0e 39 c3 fb 88 94 29 7c 9e 96 9b e5 e1 6b ae |v 9 )| k | 210: 87 03 a4 86 a2 1f 91 cf 90 1c 11 08 57 bc c7 90 | W | 220: 0b c1 51 2e 28 a6 58 96 e2 e7 f2 20 c6 ac 06 05 | Q.( X | 230: 39 75 4a 56 cf f8 |9uJV | lzo: output size = 0x55 000: 03 02 00 03 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| 010: 00 00 00 00 00 00 00 00 00 01 02 03 04 05 00 01 | | 020: 02 03 04 05 00 00 0d 00 01 02 03 04 05 06 07 08 | | 030: 09 0a 0b 0c 0d 0e 0f 20 00 bc 3c 00 00 02 0c 0d | < | 040: 0e 0f 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d | | 050: 0e 0f 11 00 00 | | zstd: output size = 0x47 000: 03 02 00 03 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| 010: 00 00 00 00 00 00 00 00 00 01 02 03 04 05 00 01 | | 020: 02 03 04 05 00 00 28 b5 2f fd 60 00 01 bd 00 00 | ( / ` | 030: 80 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e | | 040: 0f 01 00 da 47 9d 4b | G K| ntop-n2n-90215bd/tests/tests-wire.expected000066400000000000000000000041511422132035700205100ustar00rootroot00000000000000environment: common.ttl = 2 environment: common.flags = 0 environment: common.community = "abc123def456z" REGISTER: common.pc = 1 REGISTER: reg.cookie = 0 REGISTER: reg.srcMac[] = 0:1:2:3:4:5 REGISTER: reg.dstMac[] = 10:11:12:13:14:15 REGISTER: reg.dev_addr.net_addr = 0x20212223 REGISTER: reg.dev_addr.net_bitlen = 25 REGISTER: reg.dev_desc = "Dummy_Dev_Desc" REGISTER: output retval = 0x24 REGISTER: output idx = 0x3d 000: 03 02 00 01 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| 010: 7a 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 |z | 020: 04 05 10 11 12 13 14 15 20 21 22 23 19 44 75 6d | !"# Dum| 030: 6d 79 5f 44 65 76 5f 44 65 73 63 00 00 |my_Dev_Desc | REGISTER_SUPER: common.pc = 5 REGISTER_SUPER: reg.cookie = 0 REGISTER_SUPER: reg.edgeMac[] = 20:21:22:23:24:25 REGISTER_SUPER: reg.dev_addr.net_addr = 0x20212223 REGISTER_SUPER: reg.dev_addr.net_bitlen = 25 REGISTER_SUPER: reg.dev_desc = "Dummy_Dev_Desc" REGISTER_SUPER: reg.auth.scheme = 1 REGISTER_SUPER: reg.auth.token_size = 16 REGISTER_SUPER: reg.auth.token[0] = 0xfe REGISTER_SUPER: reg.key_time = 600 REGISTER_SUPER: output retval = 0x36 REGISTER_SUPER: output idx = 0x4f 000: 03 02 00 05 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| 010: 7a 00 00 00 00 00 00 00 00 00 00 00 20 21 22 23 |z !"#| 020: 24 25 20 21 22 23 19 44 75 6d 6d 79 5f 44 65 76 |$% !"# Dummy_Dev| 030: 5f 44 65 73 63 00 00 00 01 00 10 fe 00 00 00 fd |_Desc | 040: 00 00 00 fc 00 00 00 00 00 00 fb 00 00 02 58 | X| UNREGISTER_SUPER: common.pc = 6 UNREGISTER_SUPER: unreg.auth.scheme = 1 UNREGISTER_SUPER: unreg.auth.token_size = 16 UNREGISTER_SUPER: unreg.auth.token[0] = 0xfe UNREGISTER_SUPER: unreg.srcMac[] = 30:31:32:33:34:35 UNREGISTER_SUPER: output retval = 0x19 UNREGISTER_SUPER: output idx = 0x32 000: 03 02 00 06 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| 010: 7a 00 00 00 00 00 00 00 00 01 00 10 fe 00 00 00 |z | 020: fd 00 00 00 fc 00 00 00 00 00 00 fb 30 31 32 33 | 0123| 030: 34 35 |45| ntop-n2n-90215bd/tests/tests_integration.list000066400000000000000000000001221422132035700213130ustar00rootroot00000000000000# # The integration tests test_integration_supernode.sh test_integration_edge.sh ntop-n2n-90215bd/tests/tests_units.list000066400000000000000000000001461422132035700201400ustar00rootroot00000000000000# # The unit tests tests-auth tests-compress tests-elliptic tests-hashing tests-transform tests-wire ntop-n2n-90215bd/thirdparty/000077500000000000000000000000001422132035700157065ustar00rootroot00000000000000ntop-n2n-90215bd/thirdparty/libnatpmp/000077500000000000000000000000001422132035700176745ustar00rootroot00000000000000ntop-n2n-90215bd/thirdparty/miniupnp/000077500000000000000000000000001422132035700175455ustar00rootroot00000000000000ntop-n2n-90215bd/tools/000077500000000000000000000000001422132035700146545ustar00rootroot00000000000000ntop-n2n-90215bd/tools/Makefile.in000066400000000000000000000017241422132035700167250ustar00rootroot00000000000000# # This is not a standalone makefile, it must be called from the toplevel # makefile to inherit the correct environment DEBUG?=-g3 HEADERS=$(wildcard include/*.h) CFLAGS+=-I../include ifeq ($(CONFIG_TARGET),mingw) CFLAGS+=-I../win32 endif CFLAGS+=$(DEBUG) LDFLAGS+=-L.. N2N_LIB=../libn2n.a TOOLS=n2n-benchmark n2n-keygen TOOLS+=@ADDITIONAL_TOOLS@ TESTS=tests-compress tests-elliptic tests-hashing tests-transform TESTS+=tests-wire TESTS+=tests-auth .PHONY: all clean install all: $(TOOLS) $(TESTS) n2n-benchmark.o: $(N2N_LIB) $(HEADERS) ../Makefile Makefile n2n-keygen.o: $(N2N_LIB) $(HEADERS) ../Makefile Makefile n2n-decode: n2n-decode.c $(N2N_LIB) $(HEADERS) ../Makefile Makefile $(CC) $(CFLAGS) $< $(LDFLAGS) $(LDLIBS) -lpcap -o $@ # See comments in the topdir Makefile about how to generate coverage # data. gcov: gcov $(TOOLS) $(TESTS) clean: rm -rf $(TOOLS) *.o *.dSYM *~ rm -f $(TESTS) *.gcno *.gcda install: $(TOOLS) $(INSTALL_PROG) $(TOOLS) $(SBINDIR)/ ntop-n2n-90215bd/tools/n2n-benchmark.c000066400000000000000000000204231422132035700174460ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #ifndef _MSC_VER /* MinGW has undefined function gettimeofday() warnings without this header * but Visual C++ doesnt even have the header */ #include #endif #include "n2n.h" #define DURATION 2.5 // test duration per algorithm #define PACKETS_BEFORE_GETTIME 2047 // do not check time after every packet but after (2 ^ n - 1) uint8_t PKT_CONTENT[DEFAULT_MTU]; /* Prototypes */ static ssize_t do_encode_packet( uint8_t * pktbuf, size_t bufsize, const n2n_community_t c ); static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, n2n_edge_conf_t *conf, uint8_t *pktbuf); static void run_hashing_benchmark(void); static void run_ecc_benchmark(void); int main(int argc, char * argv[]) { uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t i; n2n_trans_op_t transop_null, transop_tf; n2n_trans_op_t transop_aes; n2n_trans_op_t transop_cc20; n2n_trans_op_t transop_lzo; #ifdef HAVE_ZSTD n2n_trans_op_t transop_zstd; #endif n2n_trans_op_t transop_speck; n2n_edge_conf_t conf; print_n2n_version(); /* Init configuration */ edge_init_conf_defaults(&conf); strncpy((char*)conf.community_name, "abc123def456", sizeof(conf.community_name)); conf.encrypt_key = "SoMEVer!S$cUREPassWORD"; pearson_hash_init(); /* Init transops */ n2n_transop_null_init(&conf, &transop_null); n2n_transop_tf_init(&conf, &transop_tf); n2n_transop_aes_init(&conf, &transop_aes); n2n_transop_cc20_init(&conf, &transop_cc20); n2n_transop_speck_init(&conf, &transop_speck); n2n_transop_lzo_init(&conf, &transop_lzo); #ifdef HAVE_ZSTD n2n_transop_zstd_init(&conf, &transop_zstd); #endif /* Setup packet content */ for (i = 0; i < sizeof(PKT_CONTENT) / sizeof(PKT_CONTENT[0]); i++) { PKT_CONTENT[i] = i & 0x0f; } /* Run the tests */ run_transop_benchmark("null", &transop_null, &conf, pktbuf); run_transop_benchmark("tf", &transop_tf, &conf, pktbuf); run_transop_benchmark("aes", &transop_aes, &conf, pktbuf); run_transop_benchmark("cc20", &transop_cc20, &conf, pktbuf); run_transop_benchmark("speck", &transop_speck, &conf, pktbuf); run_transop_benchmark("lzo1x", &transop_lzo, &conf, pktbuf); #ifdef HAVE_ZSTD run_transop_benchmark("zstd", &transop_zstd, &conf, pktbuf); #endif run_ecc_benchmark(); run_hashing_benchmark(); /* Cleanup */ transop_null.deinit(&transop_null); transop_tf.deinit(&transop_tf); transop_aes.deinit(&transop_aes); transop_cc20.deinit(&transop_cc20); transop_speck.deinit(&transop_speck); transop_lzo.deinit(&transop_lzo); #ifdef HAVE_ZSTD transop_zstd.deinit(&transop_zstd); #endif return 0; } // --- hashing benchmark ------------------------------------------------------------------ static void run_hashing_benchmark(void) { const float target_sec = DURATION; struct timeval t1; struct timeval t2; ssize_t nw; ssize_t target_usec = target_sec * 1e6; ssize_t tdiff = 0; // microseconds size_t num_packets = 0; uint64_t hash; printf("(%s)\t%s\t%.1f sec\t(%u bytes)", "prs64", "hash", target_sec, (unsigned int)sizeof(PKT_CONTENT)); fflush(stdout); gettimeofday( &t1, NULL ); nw = 8; while(tdiff < target_usec) { hash = pearson_hash_64(PKT_CONTENT, sizeof(PKT_CONTENT)); hash++; // clever compiler finds out that we do no use the variable num_packets++; if (!(num_packets & PACKETS_BEFORE_GETTIME)) { gettimeofday( &t2, NULL ); tdiff = ((t2.tv_sec - t1.tv_sec) * 1000000) + (t2.tv_usec - t1.tv_usec); } } float mpps = num_packets / (tdiff / 1e6) / 1e6; printf(" ---> (%u bytes)\t%12u packets\t%8.1f Kpps\t%8.1f MB/s\n", (unsigned int)nw, (unsigned int)num_packets, mpps * 1e3, mpps * sizeof(PKT_CONTENT)); printf("\n"); } // --- ecc benchmark ---------------------------------------------------------------------- static void run_ecc_benchmark(void) { const float target_sec = DURATION; struct timeval t1; struct timeval t2; ssize_t nw; ssize_t target_usec = target_sec * 1e6; ssize_t tdiff = 0; // microseconds size_t num_packets = 0; unsigned char b[32]; unsigned char k[32]; memset(b, 0x00, 31); b[31] = 9; memset(k, 0x55, 32); printf("[%s]\t%s\t%.1f sec\t(%u bytes) ", "curve", "25519", target_sec, 32); fflush(stdout); gettimeofday( &t1, NULL ); nw = 32; while(tdiff < target_usec) { curve25519(b, k, b); num_packets++; gettimeofday( &t2, NULL ); tdiff = ((t2.tv_sec - t1.tv_sec) * 1000000) + (t2.tv_usec - t1.tv_usec); } float mpps = num_packets / (tdiff / 1e6) / 1e6; printf(" ---> (%u bytes)\t%12u ops\t%8.1f Kops/s\n", (unsigned int)nw, (unsigned int)num_packets, mpps * 1e3); printf("\n"); } // --- transop benchmark ------------------------------------------------------------------ static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, n2n_edge_conf_t *conf, uint8_t *pktbuf) { n2n_common_t cmn; n2n_PACKET_t pkt; n2n_mac_t mac_buf; uint8_t decodebuf[N2N_PKT_BUF_SIZE]; const float target_sec = DURATION; struct timeval t1; struct timeval t2; size_t idx; size_t rem; size_t nw; ssize_t target_usec = target_sec * 1e6; ssize_t tdiff; // microseconds size_t num_packets; float mpps; // encryption printf("[%s]\t%s\t%.1f sec\t(%u bytes)", op_name, "encrypt" , target_sec, (unsigned int)sizeof(PKT_CONTENT)); fflush(stdout); memset(mac_buf, 0, sizeof(mac_buf)); num_packets = 0; tdiff = 0; gettimeofday( &t1, NULL ); while(tdiff < target_usec) { nw = do_encode_packet( pktbuf, N2N_PKT_BUF_SIZE, conf->community_name); nw += op_fn->fwd(op_fn, pktbuf+nw, N2N_PKT_BUF_SIZE-nw, PKT_CONTENT, sizeof(PKT_CONTENT), mac_buf); num_packets++; if (!(num_packets & PACKETS_BEFORE_GETTIME)) { gettimeofday( &t2, NULL ); tdiff = ((t2.tv_sec - t1.tv_sec) * 1000000) + (t2.tv_usec - t1.tv_usec); } } mpps = num_packets / (tdiff / 1e6) / 1e6; printf(" ---> (%u bytes)\t%12u packets\t%8.1f Kpps\t%8.1f MB/s\n", (unsigned int)nw, (unsigned int)num_packets, mpps * 1e3, mpps * sizeof(PKT_CONTENT)); // decrpytion printf("\t%s\t%.1f sec\t(%u bytes)", "decrypt" , target_sec, (unsigned int)sizeof(PKT_CONTENT)); fflush(stdout); num_packets = 0; tdiff = 0; gettimeofday( &t1, NULL ); while(tdiff < target_usec) { idx=0; rem=nw; decode_common( &cmn, pktbuf, &rem, &idx); decode_PACKET( &pkt, &cmn, pktbuf, &rem, &idx ); op_fn->rev(op_fn, decodebuf, N2N_PKT_BUF_SIZE, pktbuf+idx, rem, 0); num_packets++; if (!(num_packets & PACKETS_BEFORE_GETTIME)) { gettimeofday( &t2, NULL ); tdiff = ((t2.tv_sec - t1.tv_sec) * 1000000) + (t2.tv_usec - t1.tv_usec); } } mpps = num_packets / (tdiff / 1e6) / 1e6; printf(" <--- (%u bytes)\t%12u packets\t%8.1f Kpps\t%8.1f MB/s\n", (unsigned int)nw, (unsigned int)num_packets, mpps * 1e3, mpps * sizeof(PKT_CONTENT)); if(memcmp(decodebuf, PKT_CONTENT, sizeof(PKT_CONTENT)) != 0) printf("\tpayload decryption failed!\n"); printf("\n"); } static ssize_t do_encode_packet( uint8_t * pktbuf, size_t bufsize, const n2n_community_t c ) { n2n_mac_t destMac={0,1,2,3,4,5}; n2n_common_t cmn; n2n_PACKET_t pkt; size_t idx; memset( &cmn, 0, sizeof(cmn) ); cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_packet; cmn.flags=0; /* no options, not from supernode, no socket */ memcpy( cmn.community, c, N2N_COMMUNITY_SIZE ); memset( &pkt, 0, sizeof(pkt) ); memcpy( pkt.srcMac, destMac, N2N_MAC_SIZE); memcpy( pkt.dstMac, destMac, N2N_MAC_SIZE); pkt.sock.family=0; /* do not encode sock */ idx=0; encode_PACKET( pktbuf, &idx, &cmn, &pkt ); traceEvent( TRACE_DEBUG, "encoded PACKET header of size=%u", (unsigned int)idx ); return idx; } ntop-n2n-90215bd/tools/n2n-decode.c000066400000000000000000000230521422132035700167400ustar00rootroot00000000000000/** * (C) 2019-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ #include #include "n2n.h" #define SNAPLEN 1500 #define TIMEOUT 200 /* *************************************************** */ static int aes_mode = 0; static int running = 1; static char *ifname = NULL; static n2n_edge_conf_t conf; static n2n_trans_op_t transop; static pcap_t *handle; static pcap_dumper_t *dumper; /* *************************************************** */ static void help() { fprintf(stderr, "n2n-decode -i ifname -k key -c community [-B bpf] [-w fname] [-v]" #ifdef N2N_HAVE_AES " [-A]" #endif "\n"); fprintf(stderr, "-i | Specify the capture interface name.\n"); fprintf(stderr, "-c | Specify the community.\n"); fprintf(stderr, "-k | Specify the encryption key.\n"); #ifdef N2N_HAVE_AES fprintf(stderr, "-A | Use AES decryption (default=use twofish).\n"); #endif fprintf(stderr, "-B | Use set a BPF filter for the capture.\n"); fprintf(stderr, "-w | Write decoded PCAP to file.\n"); fprintf(stderr, "-v | Increase verbosity level.\n"); exit(0); } /* *************************************************** */ #ifdef WIN32 BOOL WINAPI term_handler(DWORD sig) #else static void term_handler(int sig) #endif { static int called = 0; if(called) { traceEvent(TRACE_NORMAL, "Ok I am leaving now"); _exit(0); } else { traceEvent(TRACE_NORMAL, "Shutting down..."); called = 1; } running = 0; #ifdef WIN32 return(TRUE); #endif } /* *************************************************** */ static void write_packet(const u_char *packet, struct pcap_pkthdr *hdr) { pcap_dump((unsigned char*)dumper, hdr, packet); pcap_dump_flush(dumper); } /* *************************************************** */ static int decode_encrypted_packet(const u_char *packet, struct pcap_pkthdr *header, n2n_PACKET_t *pkt, int encrypted_offset) { uint8_t decoded_packet[encrypted_offset + N2N_PKT_BUF_SIZE]; int decoded_eth_size; int transop_shift; switch(pkt->transform) { case N2N_TRANSFORM_ID_NULL: /* Not encrypted, dump it */ write_packet(packet, header); break; case N2N_TRANSFORM_ID_TWOFISH: if(aes_mode) { traceEvent(TRACE_INFO, "Skipping twofish encrypted packet"); return(-1); } break; case N2N_TRANSFORM_ID_AES: if(!aes_mode) { traceEvent(TRACE_INFO, "Skipping AES encrypted packet"); return(-1); } break; default: traceEvent(TRACE_INFO, "Skipping unknown transform packet: %d", pkt->transform); return(-2); } decoded_eth_size = transop.rev(&transop, decoded_packet+encrypted_offset, N2N_PKT_BUF_SIZE, packet + encrypted_offset, header->caplen - encrypted_offset, pkt->srcMac); transop_shift = (header->caplen - encrypted_offset) - decoded_eth_size; if(transop_shift >= 0) { int transform_id_offset = encrypted_offset - 2; /* Copy the initial part of the packet */ memcpy(decoded_packet, packet, encrypted_offset); /* Change the packet transform to NULL as there is now plaintext data */ *((u_int16_t*)(decoded_packet + transform_id_offset)) = htons(N2N_TRANSFORM_ID_NULL); // TODO fix IP and UDP chechsums write_packet(decoded_packet, header); return(0); } traceEvent(TRACE_INFO, "Something was wrong in the decoding"); return(-3); } /* *************************************************** */ #define ETH_SIZE 14 #define UDP_SIZE 8 #define MIN_IP_SIZE 20 #define MIN_LEN (ETH_SIZE + UDP_SIZE + MIN_IP_SIZE + sizeof(n2n_common_t)) static int run_packet_loop() { struct pcap_pkthdr header; const u_char *packet; traceEvent(TRACE_NORMAL, "Capturing packets on %s...", ifname); while(running) { n2n_common_t common; n2n_PACKET_t pkt; uint ipsize, common_offset; size_t idx, rem; memset(&common, 0, sizeof(common)); memset(&pkt, 0, sizeof(pkt)); packet = pcap_next(handle, &header); if(!packet) continue; if(header.caplen < MIN_LEN) { traceEvent(TRACE_INFO, "Skipping packet too small: size=%d", header.caplen); continue; } if(ntohs(*(uint16_t*)(packet + 12)) != 0x0800) { traceEvent(TRACE_INFO, "Skipping non IPv4 packet"); continue; } if(packet[ETH_SIZE + 9] != IPPROTO_UDP) { traceEvent(TRACE_INFO, "Skipping non UDP packet"); continue; } ipsize = (packet[ETH_SIZE] & 0x0F) * 4; common_offset = ETH_SIZE + ipsize + UDP_SIZE; idx = common_offset; rem = header.caplen - idx; if(decode_common(&common, packet, &rem, &idx) == -1) { traceEvent(TRACE_INFO, "Skipping packet, decode common failed"); continue; } if(strncmp((char*)conf.community_name, (char*)common.community, N2N_COMMUNITY_SIZE) != 0) { traceEvent(TRACE_INFO, "Skipping packet with non-matching community"); continue; } switch(common.pc) { case n2n_ping: case n2n_register: case n2n_deregister: case n2n_register_ack: case n2n_register_super: case n2n_register_super_ack: case n2n_register_super_nak: case n2n_federation: case n2n_peer_info: case n2n_query_peer: write_packet(packet, &header); break; case n2n_packet: decode_PACKET(&pkt, &common, packet, &rem, &idx); decode_encrypted_packet(packet, &header, &pkt, idx); break; default: traceEvent(TRACE_INFO, "Skipping packet with unknown type: %d", common.pc); continue; } } return(0); } /* *************************************************** */ int main(int argc, char* argv[]) { u_char c; struct bpf_program fcode; char *bpf_filter = NULL, *out_fname = NULL; char errbuf[PCAP_ERRBUF_SIZE]; int rv = 0; FILE *outf = stdout; /* Trace to stderr to leave stdout for the PCAP dump if "-w -" is used */ setTraceFile(stderr); /* Init configuration */ edge_init_conf_defaults(&conf); while((c = getopt(argc, argv, "k:i:B:w:c:v" #ifdef N2N_HAVE_AES "A" #endif )) != '?') { if(c == 255) break; switch(c) { case 'c': strncpy((char*)conf.community_name, optarg, sizeof(conf.community_name)-1); break; case 'i': ifname = strdup(optarg); break; case 'k': conf.encrypt_key = strdup(optarg); break; case 'B': bpf_filter = strdup(optarg); break; #ifdef N2N_HAVE_AES case 'A': aes_mode = 1; break; #endif case 'w': if(strcmp(optarg, "-") != 0) out_fname = strdup(optarg); break; case 'v': /* verbose */ setTraceLevel(getTraceLevel() + 1); break; default: help(); } } if((ifname == NULL) || (conf.encrypt_key == NULL) || (conf.community_name[0] == '\0')) help(); #ifdef N2N_HAVE_AES if(aes_mode) n2n_transop_aes_init(&conf, &transop); else #endif n2n_transop_tf_init(&conf, &transop); if((handle = pcap_create(ifname, errbuf)) == NULL) { traceEvent(TRACE_ERROR, "Cannot open device %s: %s", ifname, errbuf); return(1); } if((pcap_set_timeout(handle, TIMEOUT) != 0) || (pcap_set_snaplen(handle, SNAPLEN) != 0)) { traceEvent(TRACE_ERROR, "Error while setting timeout/snaplen"); return(1); } #ifdef HAVE_PCAP_IMMEDIATE_MODE /* The timeout is not honored unless immediate mode is set. * See https://github.com/mfontanini/libtins/issues/180 */ if(pcap_set_immediate_mode(handle, 1) != 0) { traceEvent(TRACE_ERROR, "Could not set PCAP immediate mode"); return(1); } #endif if(pcap_activate(handle) != 0) { traceEvent(TRACE_ERROR, "pcap_activate failed: %s", pcap_geterr(handle)); } if(pcap_datalink(handle) != DLT_EN10MB) { traceEvent(TRACE_ERROR, "Device %s doesn't provide Ethernet headers - not supported", ifname); return(2); } if(bpf_filter) { bpf_u_int32 net, mask; if(pcap_lookupnet(ifname, &net, &mask, errbuf) == -1) { traceEvent(TRACE_WARNING, "Couldn't get netmask for device %s: %s", ifname, errbuf); net = 0; mask = 0; } if((pcap_compile(handle, &fcode, bpf_filter, 1, net) < 0) || (pcap_setfilter(handle, &fcode) < 0)) { traceEvent(TRACE_ERROR, "Could not set BPF filter: %s", pcap_geterr(handle)); return(3); } } if(out_fname) { outf = fopen(out_fname, "wb"); if(outf == NULL) { traceEvent(TRACE_ERROR, "Could not open %s for write[%d]: %s", errno, strerror(errno)); return(4); } } dumper = pcap_dump_fopen(handle, outf); if(dumper == NULL) { traceEvent(TRACE_ERROR, "Could dump file: %s", pcap_geterr(handle)); return(5); } #ifdef WIN32 SetConsoleCtrlHandler(term_handler, TRUE); #else signal(SIGTERM, term_handler); signal(SIGINT, term_handler); #endif rv = run_packet_loop(); /* Cleanup */ pcap_close(handle); if(conf.encrypt_key) free(conf.encrypt_key); if(bpf_filter) free(bpf_filter); if(ifname) free(ifname); if(out_fname) { fclose(outf); free(out_fname); } return(rv); } ntop-n2n-90215bd/tools/n2n-keygen.c000066400000000000000000000053331422132035700170010ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #include "n2n.h" int main(int argc, char * argv[]) { n2n_private_public_key_t prv; /* 32 bytes private key */ n2n_private_public_key_t bin; /* 32 bytes public key binary output buffer */ char asc[44]; /* 43 bytes + 0-terminator ascii string output */ uint8_t fed = 0; // exactly two parameters required if(argc != 3) { // error message to stderr to not interfere with batch usage fprintf(stderr, "\n" "n2n-keygen tool\n\n" " usage: n2n-keygen \n\n" " or n2n-keygen -F \n\n" " outputs a line to insert at supernode's community file for user-and-\n" " password authentication or a command line parameter with the public\n" " federation key for use at edge's command line, please refer to the\n" " doc/Authentication.md document or the man pages for more details\n\n"); return 1; } // federation mode? if(strcmp(argv[1], "-F") == 0) fed = 1; // derive private key from username and password: // hash username once, hash password twice (so password is bound // to username but username and password are not interchangeable), // finally xor the result // in federation mode: only hash federation name, twice generate_private_key(prv, argv[2]); // hash user name only if required if(!fed) { bind_private_key_to_username(prv, argv[1]); } // calculate the public key into binary output buffer generate_public_key(bin, prv); // clear out the private key memset(prv, 0, sizeof(prv)); // convert binary output to 6-bit-ascii string output bin_to_ascii(asc, bin, sizeof(bin)); // output if(fed) fprintf(stdout, "-P %s\n", asc); else fprintf(stdout, "%c %s %s\n", N2N_USER_KEY_LINE_STARTER, argv[1], asc); return 0; } ntop-n2n-90215bd/tools/tests-auth.c000066400000000000000000000067761422132035700171410ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #include #include "n2n.h" #include "hexdump.h" uint8_t PKT_CONTENT1[]={ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, }; char *PKT_CONTENT2 = "00420mG51WS82GeB30qE3m"; void test_bin_to_ascii (void *buf, unsigned int bufsize) { char *test_name = "bin_to_ascii"; char out[32]; printf("%s: input size = 0x%x\n", test_name, bufsize); fhexdump(0, buf, bufsize, stdout); bin_to_ascii(out, buf, bufsize); printf("%s: output: %s\n", test_name, out); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_ascii_to_bin (char *buf) { char *test_name = "ascii_to_bin"; uint8_t out[32]; memset(out, 0, sizeof(out)); printf("%s: input = %s\n", test_name, buf); ascii_to_bin(out, buf); // TODO: // - it would be nice if the function returned the bufsize, // - or took an allocation size as input printf("%s: output:\n", test_name); fhexdump(0, out, sizeof(out), stdout); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_generate_private_key (char *in, n2n_private_public_key_t prv) { char *test_name = "generate_private_key"; printf("%s: input = %s\n", test_name, in); generate_private_key(prv, in); printf("%s: output:\n", test_name); fhexdump(0, prv, sizeof(n2n_private_public_key_t), stdout); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_generate_public_key (n2n_private_public_key_t prv, n2n_private_public_key_t pub) { char *test_name = "generate_public_key"; printf("%s: input:\n", test_name); fhexdump(0, prv, sizeof(n2n_private_public_key_t), stdout); generate_public_key(pub, prv); printf("%s: output:\n", test_name); fhexdump(0, pub, sizeof(n2n_private_public_key_t), stdout); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_generate_shared_secret (n2n_private_public_key_t prv, n2n_private_public_key_t pub) { char *test_name = "generate_shared_secret"; n2n_private_public_key_t out; printf("%s: input: prv\n", test_name); fhexdump(0, prv, sizeof(n2n_private_public_key_t), stdout); printf("%s: input: pub\n", test_name); fhexdump(0, pub, sizeof(n2n_private_public_key_t), stdout); generate_shared_secret(out, prv, pub); printf("%s: output:\n", test_name); fhexdump(0, out, sizeof(out), stdout); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } int main (int argc, char * argv[]) { test_bin_to_ascii(PKT_CONTENT1, sizeof(PKT_CONTENT1)); test_ascii_to_bin(PKT_CONTENT2); n2n_private_public_key_t prv; memset(prv, 0, sizeof(prv)); n2n_private_public_key_t pub; memset(pub, 0, sizeof(pub)); test_generate_private_key(PKT_CONTENT2, prv); test_generate_public_key(prv, pub); test_generate_shared_secret(prv, pub); return 0; } ntop-n2n-90215bd/tools/tests-compress.c000066400000000000000000000142011422132035700200110ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #include #include #include "n2n.h" #include "hexdump.h" /* heap allocation for compression as per lzo example doc */ #define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); uint8_t PKT_CONTENT[]={ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; static void init_compression_for_benchmark (void) { if(lzo_init() != LZO_E_OK) { traceEvent(TRACE_ERROR, "LZO compression init error"); exit(1); } #ifdef N2N_HAVE_ZSTD // zstd does not require initialization. if it were required, this would be a good place #endif } static void deinit_compression_for_benchmark (void) { // lzo1x does not require de-initialization. if it were required, this would be a good place #ifdef N2N_HAVE_ZSTD // zstd does not require de-initialization. if it were required, this would be a good place #endif } void test_lzo1x () { char *test_name = "lzo1x"; uint8_t compression_buffer[N2N_PKT_BUF_SIZE]; // size allows enough of a reserve required for compression lzo_uint compression_len = sizeof(compression_buffer); if(lzo1x_1_compress(PKT_CONTENT, sizeof(PKT_CONTENT), compression_buffer, &compression_len, wrkmem) != LZO_E_OK) { fprintf(stderr, "%s: compression error\n", test_name); exit(1); } assert(compression_len == 47); printf("%s: output size = 0x%" PRIx64 "\n", test_name, compression_len); fhexdump(0, compression_buffer, compression_len, stdout); uint8_t deflation_buffer[N2N_PKT_BUF_SIZE]; lzo_uint deflated_len; lzo1x_decompress(compression_buffer, compression_len, deflation_buffer, &deflated_len, NULL); assert(deflated_len == sizeof(PKT_CONTENT)); if(memcmp(PKT_CONTENT, deflation_buffer, deflated_len)!=0) { fprintf(stderr, "%s: round-trip buffer mismatch\n", test_name); exit(1); } fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_zstd () { char *test_name = "zstd"; #ifdef N2N_HAVE_ZSTD uint8_t compression_buffer[N2N_PKT_BUF_SIZE]; // size allows enough of a reserve required for compression lzo_uint compression_len = sizeof(compression_buffer); compression_len = N2N_PKT_BUF_SIZE; compression_len = ZSTD_compress(compression_buffer, compression_len, PKT_CONTENT, sizeof(PKT_CONTENT), ZSTD_COMPRESSION_LEVEL); if(ZSTD_isError(compression_len)) { fprintf(stderr, "%s: compression error\n", test_name); exit(1); } assert(compression_len == 33); printf("%s: output size = 0x%" PRIx64 "\n", test_name, compression_len); fhexdump(0, compression_buffer, compression_len, stdout); uint8_t deflation_buffer[N2N_PKT_BUF_SIZE]; int64_t deflated_len = sizeof(deflation_buffer); deflated_len = (int32_t)ZSTD_decompress(deflation_buffer, deflated_len, compression_buffer, compression_len); if(ZSTD_isError(deflated_len)) { fprintf(stderr, "%s: decompression error '%s'\n", test_name, ZSTD_getErrorName(deflated_len)); exit(1); } assert(deflated_len == sizeof(PKT_CONTENT)); if(memcmp(PKT_CONTENT, deflation_buffer, deflated_len)!=0) { fprintf(stderr, "%s: round-trip buffer mismatch\n", test_name); exit(1); } fprintf(stderr, "%s: tested\n", test_name); #else // FIXME - output dummy data to the stdout for easy comparison printf("zstd: output size = 0x21\n"); printf("000: 28 b5 2f fd 60 00 01 bd 00 00 80 00 01 02 03 04 |( / ` |\n"); printf("010: 05 06 07 08 09 0a 0b 0c 0d 0e 0f 01 00 da 47 9d | G |\n"); printf("020: 4b |K|\n"); fprintf(stderr, "%s: not compiled - dummy data output\n", test_name); #endif printf("\n"); } int main (int argc, char * argv[]) { /* Also for compression (init moved here for ciphers get run before in case of lzo init error) */ init_compression_for_benchmark(); printf("%s: input size = 0x%" PRIx64 "\n", "original", sizeof(PKT_CONTENT)); fhexdump(0, PKT_CONTENT, sizeof(PKT_CONTENT), stdout); printf("\n"); test_lzo1x(); test_zstd(); deinit_compression_for_benchmark(); return 0; } ntop-n2n-90215bd/tools/tests-elliptic.c000066400000000000000000000030241422132035700177640ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #include "n2n.h" #include "hexdump.h" void test_curve25519 (unsigned char *pkt_input, unsigned char *key) { char *test_name = "curve25519"; unsigned char pkt_output[32]; curve25519(pkt_output, key, pkt_input); printf("%s: output\n", test_name); fhexdump(0, pkt_output, sizeof(pkt_output), stdout); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } int main (int argc, char * argv[]) { char *test_name = "environment"; unsigned char key[32]; unsigned char pkt_input[32]; memset(pkt_input, 0, 31); pkt_input[31] = 9; memset(key, 0x55, 32); printf("%s: input\n", test_name); fhexdump(0, pkt_input, sizeof(pkt_input), stdout); printf("%s: key\n", test_name); fhexdump(0, key, sizeof(key), stdout); printf("\n"); test_curve25519(pkt_input, key); return 0; } ntop-n2n-90215bd/tools/tests-hashing.c000066400000000000000000000100601422132035700175760ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #include #include "n2n.h" #include "hexdump.h" uint8_t PKT_CONTENT[]={ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; void test_pearson_16 (void *buf, unsigned int bufsize) { char *test_name = "pearson_hash_16"; uint16_t hash = pearson_hash_16(buf, bufsize); printf("%s: output = 0x%" PRIx16 "\n", test_name, hash); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_pearson_32 (void *buf, unsigned int bufsize) { char *test_name = "pearson_hash_32"; uint32_t hash = pearson_hash_32(buf, bufsize); printf("%s: output = 0x%" PRIx32 "\n", test_name, hash); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_pearson_64 (void *buf, unsigned int bufsize) { char *test_name = "pearson_hash_64"; uint64_t hash = pearson_hash_64(buf, bufsize); printf("%s: output = 0x%" PRIx64 "\n", test_name, hash); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_pearson_128 (void *buf, unsigned int bufsize) { char *test_name = "pearson_hash_128"; uint8_t hash[16]; pearson_hash_128(hash, buf, bufsize); printf("%s: output:\n", test_name); fhexdump(0, hash, sizeof(hash), stdout); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_pearson_256 (void *buf, unsigned int bufsize) { char *test_name = "pearson_hash_256"; uint8_t hash[32]; pearson_hash_256(hash, buf, bufsize); printf("%s: output:\n", test_name); fhexdump(0, hash, sizeof(hash), stdout); fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } int main (int argc, char * argv[]) { pearson_hash_init(); char *test_name = "environment"; printf("%s: input size = 0x%" PRIx64 "\n", test_name, sizeof(PKT_CONTENT)); fhexdump(0, PKT_CONTENT, sizeof(PKT_CONTENT), stdout); printf("\n"); test_pearson_256(PKT_CONTENT, sizeof(PKT_CONTENT)); test_pearson_128(PKT_CONTENT, sizeof(PKT_CONTENT)); test_pearson_64(PKT_CONTENT, sizeof(PKT_CONTENT)); test_pearson_32(PKT_CONTENT, sizeof(PKT_CONTENT)); test_pearson_16(PKT_CONTENT, sizeof(PKT_CONTENT)); return 0; } ntop-n2n-90215bd/tools/tests-transform.c000066400000000000000000000163011422132035700201740ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #include #include "n2n.h" #include "hexdump.h" #define DURATION 2.5 // test duration per algorithm #define PACKETS_BEFORE_GETTIME 2047 // do not check time after every packet but after (2 ^ n - 1) uint8_t PKT_CONTENT[]={ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; /* Prototypes */ static ssize_t do_encode_packet ( uint8_t * pktbuf, size_t bufsize, const n2n_community_t c ); static void run_transop_benchmark (const char *op_name, n2n_trans_op_t *op_fn, n2n_edge_conf_t *conf, uint8_t *pktbuf); int main (int argc, char * argv[]) { uint8_t pktbuf[N2N_PKT_BUF_SIZE]; n2n_trans_op_t transop_null, transop_tf; n2n_trans_op_t transop_aes; n2n_trans_op_t transop_cc20; n2n_trans_op_t transop_speck; n2n_trans_op_t transop_lzo; #ifdef HAVE_ZSTD n2n_trans_op_t transop_zstd; #endif n2n_edge_conf_t conf; /* Init configuration */ edge_init_conf_defaults(&conf); strncpy((char *)conf.community_name, "abc123def456", sizeof(conf.community_name)); conf.encrypt_key = "SoMEVer!S$cUREPassWORD"; char *test_name = "environment"; printf("%s: community_name = \"%s\"\n", test_name, conf.community_name); printf("%s: encrypt_key = \"%s\"\n", test_name, conf.encrypt_key); printf("%s: input size = 0x%" PRIx64 "\n", test_name, sizeof(PKT_CONTENT)); fhexdump(0, PKT_CONTENT, sizeof(PKT_CONTENT), stdout); printf("\n"); /* Init transopts */ n2n_transop_null_init(&conf, &transop_null); n2n_transop_tf_init(&conf, &transop_tf); n2n_transop_aes_init(&conf, &transop_aes); n2n_transop_cc20_init(&conf, &transop_cc20); n2n_transop_speck_init(&conf, &transop_speck); n2n_transop_lzo_init(&conf, &transop_lzo); #ifdef HAVE_ZSTD n2n_transop_zstd_init(&conf, &transop_zstd); #endif /* Run the tests */ /* FIXME: interop tests are pretty useless without the expected encrypted buffer data */ run_transop_benchmark("null", &transop_null, &conf, pktbuf); run_transop_benchmark("tf", &transop_tf, &conf, pktbuf); run_transop_benchmark("aes", &transop_aes, &conf, pktbuf); run_transop_benchmark("cc20", &transop_cc20, &conf, pktbuf); run_transop_benchmark("speck", &transop_speck, &conf, pktbuf); run_transop_benchmark("lzo", &transop_lzo, &conf, pktbuf); #ifdef HAVE_ZSTD run_transop_benchmark("zstd", &transop_zstd, &conf, pktbuf); #else // FIXME - output dummy data to the stdout for easy comparison printf("zstd: output size = 0x47\n"); printf("000: 03 02 00 03 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456|\n"); printf("010: 00 00 00 00 00 00 00 00 00 01 02 03 04 05 00 01 | |\n"); printf("020: 02 03 04 05 00 00 28 b5 2f fd 60 00 01 bd 00 00 | ( / ` |\n"); printf("030: 80 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e | |\n"); printf("040: 0f 01 00 da 47 9d 4b | G K|\n"); fprintf(stderr, "%s: not compiled - dummy data output\n", "zstd"); printf("\n"); #endif /* Cleanup */ transop_null.deinit(&transop_null); transop_tf.deinit(&transop_tf); transop_aes.deinit(&transop_aes); transop_cc20.deinit(&transop_cc20); transop_speck.deinit(&transop_speck); transop_lzo.deinit(&transop_lzo); #ifdef HAVE_ZSTD transop_zstd.deinit(&transop_zstd); #endif return 0; } // --- transop benchmark ------------------------------------------------------------------ static void run_transop_benchmark (const char *op_name, n2n_trans_op_t *op_fn, n2n_edge_conf_t *conf, uint8_t *pktbuf) { n2n_common_t cmn; n2n_PACKET_t pkt; n2n_mac_t mac_buf; uint8_t decodebuf[N2N_PKT_BUF_SIZE]; size_t idx; size_t rem; size_t nw; // encryption memset(mac_buf, 0, sizeof(mac_buf)); nw = do_encode_packet( pktbuf, N2N_PKT_BUF_SIZE, conf->community_name); nw += op_fn->fwd(op_fn, pktbuf+nw, N2N_PKT_BUF_SIZE-nw, PKT_CONTENT, sizeof(PKT_CONTENT), mac_buf); printf("%s: output size = 0x%" PRIx64 "\n", op_name, nw); fhexdump(0, pktbuf, nw, stdout); // decrpytion idx=0; rem=nw; decode_common( &cmn, pktbuf, &rem, &idx); decode_PACKET( &pkt, &cmn, pktbuf, &rem, &idx ); op_fn->rev(op_fn, decodebuf, sizeof(decodebuf), pktbuf+idx, rem, 0); if(memcmp(decodebuf, PKT_CONTENT, sizeof(PKT_CONTENT)) != 0) { fprintf(stderr, "%s: round-trip buffer mismatch\n", op_name); exit(1); } fprintf(stderr, "%s: tested\n", op_name); printf("\n"); } static ssize_t do_encode_packet ( uint8_t * pktbuf, size_t bufsize, const n2n_community_t c ) { // FIXME: this is a parameter of the test environment n2n_mac_t destMac={0,1,2,3,4,5}; n2n_common_t cmn; n2n_PACKET_t pkt; size_t idx; memset( &cmn, 0, sizeof(cmn) ); cmn.ttl = N2N_DEFAULT_TTL; cmn.pc = n2n_packet; cmn.flags=0; /* no options, not from supernode, no socket */ memcpy( cmn.community, c, N2N_COMMUNITY_SIZE ); memset( &pkt, 0, sizeof(pkt) ); memcpy( pkt.srcMac, destMac, N2N_MAC_SIZE); memcpy( pkt.dstMac, destMac, N2N_MAC_SIZE); pkt.sock.family=0; /* do not encode sock */ idx=0; encode_PACKET( pktbuf, &idx, &cmn, &pkt ); traceEvent( TRACE_DEBUG, "encoded PACKET header of size=%u", (unsigned int)idx ); return idx; } ntop-n2n-90215bd/tools/tests-wire.c000066400000000000000000000143701422132035700171330ustar00rootroot00000000000000/* * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * */ #include #include "n2n.h" #include "hexdump.h" void init_ip_subnet (n2n_ip_subnet_t * d) { d->net_addr = 0x20212223; d->net_bitlen = 25; } void print_ip_subnet (char *test_name, char *field, n2n_ip_subnet_t * d) { printf("%s: %s.net_addr = 0x%08x\n", test_name, field, d->net_addr); printf("%s: %s.net_bitlen = %i\n", test_name, field, d->net_bitlen); } void init_mac (n2n_mac_t mac, const uint8_t o0, const uint8_t o1, const uint8_t o2, const uint8_t o3, const uint8_t o4, const uint8_t o5) { mac[0] = o0; mac[1] = o1; mac[2] = o2; mac[3] = o3; mac[4] = o4; mac[5] = o5; } void print_mac (char *test_name, char *field, n2n_mac_t mac) { printf("%s: %s[] = %x:%x:%x:%x:%x:%x\n", test_name, field, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } void init_auth (n2n_auth_t *auth) { auth->scheme = n2n_auth_simple_id; auth->token_size = 16; auth->token[0] = 0xfe; auth->token[4] = 0xfd; auth->token[8] = 0xfc; auth->token[15] = 0xfb; } void print_auth (char *test_name, char *field, n2n_auth_t *auth) { printf("%s: %s.scheme = %i\n", test_name, field, auth->scheme); printf("%s: %s.token_size = %i\n", test_name, field, auth->token_size); printf("%s: %s.token[0] = 0x%02x\n", test_name, field, auth->token[0]); } void init_common (n2n_common_t *common, char *community) { memset( common, 0, sizeof(*common) ); common->ttl = N2N_DEFAULT_TTL; common->flags = 0; strncpy( (char *)common->community, community, N2N_COMMUNITY_SIZE); common->community[N2N_COMMUNITY_SIZE - 1] = '\0'; } void print_common (char *test_name, n2n_common_t *common) { printf("%s: common.ttl = %i\n", test_name, common->ttl); printf("%s: common.flags = %i\n", test_name, common->flags); printf("%s: common.community = \"%s\"\n", test_name, common->community); } void test_REGISTER (n2n_common_t *common) { char *test_name = "REGISTER"; common->pc = n2n_register; printf("%s: common.pc = %i\n", test_name, common->pc); n2n_REGISTER_t reg; memset( ®, 0, sizeof(reg) ); init_mac( reg.srcMac, 0,1,2,3,4,5); init_mac( reg.dstMac, 0x10,0x11,0x12,0x13,0x14,0x15); init_ip_subnet(®.dev_addr); strcpy( (char *)reg.dev_desc, "Dummy_Dev_Desc" ); printf("%s: reg.cookie = %i\n", test_name, reg.cookie); print_mac(test_name, "reg.srcMac", reg.srcMac); print_mac(test_name, "reg.dstMac", reg.dstMac); // TODO: print reg.sock print_ip_subnet(test_name, "reg.dev_addr", ®.dev_addr); printf("%s: reg.dev_desc = \"%s\"\n", test_name, reg.dev_desc); printf("\n"); uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx = 0; size_t retval = encode_REGISTER( pktbuf, &idx, common, ®); printf("%s: output retval = 0x%" PRIx64 "\n", test_name, retval); printf("%s: output idx = 0x%" PRIx64 "\n", test_name, idx); fhexdump(0, pktbuf, idx, stdout); // TODO: decode_REGISTER() and print fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_REGISTER_SUPER (n2n_common_t *common) { char *test_name = "REGISTER_SUPER"; common->pc = n2n_register_super; printf("%s: common.pc = %i\n", test_name, common->pc); n2n_REGISTER_SUPER_t reg; memset( ®, 0, sizeof(reg) ); init_mac( reg.edgeMac, 0x20,0x21,0x22,0x23,0x24,0x25); // n2n_sock_t sock init_ip_subnet(®.dev_addr); strcpy( (char *)reg.dev_desc, "Dummy_Dev_Desc" ); init_auth(®.auth); reg.key_time = 600; printf("%s: reg.cookie = %i\n", test_name, reg.cookie); print_mac(test_name, "reg.edgeMac", reg.edgeMac); // TODO: print reg.sock print_ip_subnet(test_name, "reg.dev_addr", ®.dev_addr); printf("%s: reg.dev_desc = \"%s\"\n", test_name, reg.dev_desc); print_auth(test_name, "reg.auth", ®.auth); printf("%s: reg.key_time = %" PRIi32 "\n", test_name, reg.key_time); printf("\n"); uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx = 0; size_t retval = encode_REGISTER_SUPER( pktbuf, &idx, common, ®); printf("%s: output retval = 0x%" PRIx64 "\n", test_name, retval); printf("%s: output idx = 0x%" PRIx64 "\n", test_name, idx); fhexdump(0, pktbuf, idx, stdout); // TODO: decode_REGISTER_SUPER() and print fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } void test_UNREGISTER_SUPER (n2n_common_t *common) { char *test_name = "UNREGISTER_SUPER"; common->pc = n2n_unregister_super; printf("%s: common.pc = %i\n", test_name, common->pc); n2n_UNREGISTER_SUPER_t unreg; memset( &unreg, 0, sizeof(unreg) ); init_auth(&unreg.auth); init_mac( unreg.srcMac, 0x30,0x31,0x32,0x33,0x34,0x35); print_auth(test_name, "unreg.auth", &unreg.auth); print_mac(test_name, "unreg.srcMac", unreg.srcMac); printf("\n"); uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx = 0; size_t retval = encode_UNREGISTER_SUPER( pktbuf, &idx, common, &unreg); printf("%s: output retval = 0x%" PRIx64 "\n", test_name, retval); printf("%s: output idx = 0x%" PRIx64 "\n", test_name, idx); fhexdump(0, pktbuf, idx, stdout); // TODO: decode_UNREGISTER_SUPER() and print fprintf(stderr, "%s: tested\n", test_name); printf("\n"); } int main (int argc, char * argv[]) { char *test_name = "environment"; n2n_common_t common; init_common( &common, "abc123def456z" ); print_common( test_name, &common ); printf("\n"); test_REGISTER(&common); test_REGISTER_SUPER(&common); test_UNREGISTER_SUPER(&common); // TODO: add more wire tests return 0; } ntop-n2n-90215bd/uncrustify.cfg000066400000000000000000000023761422132035700164200ustar00rootroot00000000000000# Initial rules taken from a quick discussion # (See https://github.com/ntop/n2n/commit/00159d0d012c6836fd972af1748833eeaf50fa22#commitcomment-57137247) # 4 space indention (never use tabs) indent_columns = 4 indent_with_tabs = 0 indent_switch_case = 4 # space between name and bracket during function define sp_func_def_paren = force sp_func_proto_paren = force # no space between name and bracket during call sp_func_call_paren = remove # no space after if and while sp_before_sparen = remove #sp_while_paren_open = remove # only in newer uncrustify # block-braces as seen above nl_if_brace = remove nl_brace_else = remove nl_elseif_brace = remove nl_else_brace = remove #nl_before_opening_brace_func_class_def = remove # only in newer uncrustify nl_for_brace = remove nl_while_brace = remove # multi-line parameters with indentation under the opening bracket # looks like this is the default, but might be the following: #indent_func_call_param = false ? # Want to keep var definition alignment #align_keep_extra_space = true ntop-n2n-90215bd/win32/000077500000000000000000000000001422132035700144565ustar00rootroot00000000000000ntop-n2n-90215bd/win32/CMakeLists.txt000066400000000000000000000002121422132035700172110ustar00rootroot00000000000000add_library(n2n_win32 getopt1.c getopt.c wintap.c) target_link_libraries(n2n_win32 PUBLIC ws2_32.lib) ntop-n2n-90215bd/win32/DotNet/000077500000000000000000000000001422132035700156535ustar00rootroot00000000000000ntop-n2n-90215bd/win32/DotNet/n2n.sln000066400000000000000000000024641422132035700170740ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "edge", "n2n.vcproj", "{4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "supernode", "supernode.vcproj", "{BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Debug|Win32.ActiveCfg = Debug|Win32 {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Debug|Win32.Build.0 = Debug|Win32 {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Release|Win32.ActiveCfg = Release|Win32 {4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Release|Win32.Build.0 = Release|Win32 {BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}.Debug|Win32.ActiveCfg = Debug|Win32 {BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}.Debug|Win32.Build.0 = Debug|Win32 {BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}.Release|Win32.ActiveCfg = Release|Win32 {BDB93CAB-BE22-4ED6-9A05-2E4D6F1D76E1}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ntop-n2n-90215bd/win32/DotNet/n2n.suo000066400000000000000000000600001422132035700170740ustar00rootroot00000000000000ĐÏࡱá>₫ÿ ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿưÿÿÿ ," !#%$&.'()*+-₫ÿÿÿ₫ÿÿÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿđ ˆú ŒÉBProjInfoExÿÿÿÿÿÿÿÿÿÿÿÿTaskListUserTasks$ÿÿÿÿÿÿÿÿDebuggerWatches ÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿÿ₫ÿÿÿ₫ÿÿÿ₫ÿÿÿ₫ÿÿÿ ₫ÿÿÿ ₫ÿÿÿ2BC ₫ÿÿÿ"#EH₫ÿÿÿ₫ÿÿÿ(]*₫ÿÿÿ,₫ÿÿÿ[₫ÿÿÿ01₫ÿÿÿ3456789:;<=>?@A₫ÿÿÿ₫ÿÿÿD₫ÿÿÿFG₫ÿÿÿIJKLMNOPQRSTUVWXYZ₫ÿÿÿ\₫ÿÿÿ^_`a₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿÿx₫ÿÿÿ₫ÿÿÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€UW̃ËÆ»HŒĐ]û b\đC &C:\ntop\n2n\win32\€C:\Programmi\Microsoft Visual Studio 9.0\Common7\IDE\vc7\atlmfczC:\Programmi\MicrosoftDebuggerBreakpoints(ÿÿÿÿÿÿÿÿ2DebuggerExceptions&ÿÿÿÿÿÿÿÿÿÿÿÿDebuggerFindSource&ÿÿÿÿDebuggerFindSymbol&ÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿÿ Visual Studio 9.0\Common7\IDE\vc7\crtè” ÿÿ\°[uÈ\uu. Í«4ï₫îÿÍ«4ï₫îÿMultiStartupProj=;4{4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}DebuggerMemoryWindows, ÿÿÿÿ TExternalFilesProjectContents:ÿÿÿÿÿÿÿÿÿÿÿÿ/ŒDocumentWindowPositions0 ÿÿÿÿ DocumentWindowUserData.ÿÿÿÿÿÿÿÿ LSolutionConfiguration,ÿÿÿÿÿÿÿÿÿÿÿÿnObjMgrContentsV8"ÿÿÿÿ‚ClassViewContents$ÿÿÿÿ₫ÿÿÿProjExplorerState$ÿÿÿÿ!J.dwStartupOpt=;?{4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Release|Win32.fBatchBld=;={4911ADD4-08A3-4C9F-B9C9-9492DA10D01D}.Debug|Win32.fBatchBld=;4{1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}.dwStartupOpt=;StartupProject=&{1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51};?{1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}.Release|Win32.fBatchBld=;={1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}.Debug|Win32.fBatchBld=;4{A2FE74E1-B743-11D0-AE1A-00A0C90S$ ưA+ÁH±ÚªÏ¥WLÉlü #Oÿ‡øÏ¤ELç%̉¯##G¶åá}'bm4S8fÂ₫ÂL¤d®—ï9LÉlü #Oÿ‡øÏ¤ELç%̉¯##G¶åá}'bm4Q :C:\ntop\n2n\win32\n2n.vcproj:C:\ntop\n2n\win32\n2n.vcprojZC:\ntop\n2n\win32\supernode\.c:\ntop\n2n\src\edge.c$Bookmarks V001.01XÏ >c:\ntop\n2n\src\win32\wintap.cUnloadedProjects"ÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿÿHiddenSlnFolders"ÿÿÿÿÿÿÿÿÿÿÿÿ₫ÿÿÿOutliningStateDir$ÿÿÿÿÿÿÿÿÿÿÿÿ$̀BookmarkStateÿÿÿÿ%(TaskListShortcuts$ÿÿÿÿÿÿÿÿÿÿÿÿ&OutliningState7 ÿÿÿÿÿÿÿÿÿÿÿÿ'¢VsToolboxService" ÿÿÿÿÿÿÿÿ.OutliningState6 ÿÿÿÿz<‹¡y 7 >c:\ntop\n2n\src\win32\wintap.h́ ¬qÿÿÿÿBCÿÿÿÿÏ8c:\ntop\n2n\src\supernode.c´©’¼ÿÿÿÿ !,zC:\Programmi\Microsoft Visual SC:\Programmi\Microsoft Visual Studio 9.0\VC\include\string.h<open> nReadThread(LPVOID lpArg ) {1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}|supernode\supernode.vcproj|c:\ntop\n2n\src\supernode.c||{8B382828-6202-11D1-8870-0000F87579D2}12” ÿÿ\°[uÈ\uu.0{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|<MiscFiles>|C:\Programmi\Microsoft Visual Studio 9.0\VC\include\string.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}123456œ¦ ÿÿ\°[uÈ\uu.{1F7F0E45-7DE9-4CE2-845F-38D59C2E4F51}|supernode\supernode.vcproj|c:\ntop\n2n\src\win32\wintap.c||{8B382828-6202-11D1-8870-0000F87579D2}12349C9-9492DA10D01D}Í«4ï₫îÿcproj|c:\ntop\n2n\src\win3FFFC3}.dwStartupOpt=; ActiveCfg= Release|Win32;23456” ÿÿsupernode.vcprojZC:\ntop\n2n\win32\supernode\supernode.vcprojproj|c:\ntop\n2n\src\n2n.h|zC:\Programmi\Microsoft Visual Studio 9.0\VC\include\string.h8c:\ntop\n2n\src\supernode.c ZC:\DOCUME~1\ADMINI~1\IMPOST~1\Temp\~vs30.txt>c:\ntop\n2n\src\win32\wintap.cDc:\ntop\n2n\src\win32\n2n_win32.h>c:\ntop\n2n\src\win32\wintap.h ,c:\ntop\n2n\src\n2n.c,c:\ntop\n2n\src\n2n.hxC:\Documents and Settings\Administrator\Desktop\_src\edge.cxc:\Programmi\Microsoft SDKs\Windows\v6.0A\Include\WinSock.h 8C:\ntop\n2n\win32\version.c4c:\ntop\n2n\src\twofish.c @c:\ntop\n2n\src\win32\getopt1.cvc:\Programmi\Microsoft SDKs\Windows\v6.0A\Include\WinReg.h DD4-08A3-4C9F-B9C9-9492DA1tudio 9.0\VC\include\string.h@̀_ÿÿÿÿe.c||{8B382828-6202-11D1-88W8X¨¬%µ¶·G¸ÍÎÏHĐ́íî0đóôơ,öùúû ưüÿÿÿÿpt=; ActiveCfg= Release|Win32;0-0000F87ZC:\ntop\n2n\win32\supernode\zC:\Programmi\Microsoft Visual Studio 9.0\VC\include\string.h8c:\ntop\n2n\src\supernode.c ZC:\DOCUME~1\ADMINI~1\IMPOST~1\Temp\~vs30.txt>c:\ntop\n2n\src\win32\wintap.cDc:\ntop\n2n\src\win32\n2n_win32.h>c:\ntop\n2n\src\win32\wintap.h ,c:\ntop\n2n\src\n2n.c,c:\ntop\n2n\src\n2n.hxC:\Documents and Settings\Administrator\Desktop\_src\edge.cxc:\Programmi\Microsoft SDKs\Windows\v6.0A\Include\WinSock.h 8C:\ntop\n2n\win32\version.c4c:\ntop\n2n\src\twofish.c @c:\ntop\n2n\src\win32\getopt1.cvc:\Programmi\Microsoft SDKs\Windows\v6.0A\Include\WinReg.c:\ntop\n2n\src\edge.cÑN¿ ÿÿÿÿDc:\ntop\n2n\src\win32\n2n_win32.hÄAƯaÿÿÿÿ $EH,c:\ntop\n2n\src\n2n.hmJsÁÿÿÿÿ,c:\ntop\n2n\src\n2n.cZedÔÿÿÿÿtudio 9.0\VC\include\string.h@̀_ÿÿÿÿ !"supernode.vcprojZC:\ntop\n2n\win32\supernode\supernode.vcproj8c:\ntop\n2n\win32\version.c£[nÙ₫ÿÿÿ₫ÿÿÿ₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡ˆ‰‹Œ‘’“”•–—˜™›œŸ ¡¢£¤¥¦§¨©ª₫ÿÿÿÿÿÿÿ­®¯°₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁÂĂÄÅÆÇÈÉÊË̀Í₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿרÙÚÛÜỮßàáâăäåæçèéêë́íî₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷øùúûüư₫ÿÿÿÿÿP>CDE7 `ÿÿÿÿX¨¬%µ¶·G¸ÍÎÏ.h ndows\v6.0A\Include\WinReg_`a bµÿÿÿÿzC:\Programmi\Microsoft Visual Svc:\Programmi\Microsoft SDKs\Windows\v6.0A\Include\WinReg.h%~>n &!3479<>BDRT\adijoprsu†•–˜™›!XM ¤¦ª¬ï/đñ/̣3 3 ## ?'@A'Be7fg7hy#z{#|‘'’“'”­7®¯7°×'ØÙ'Úïđṇ̃##/#01#2VWXYwxyzOutliningState3 ÿÿÿÿÿÿÿÿy<OutliningState1 ÿÿÿÿv>OutliningState2 ÿÿÿÿÿÿÿÿwTOutliningState9 ÿÿÿÿÿÿÿÿ)N‘#’“#”¯3°±3²×)ØÙ)Úï%đñ%̣ 7  7ơ())*)+@%AB%CV%WX%Ylmno!‘!’¬%­®%¯À#ÁÂ#ĂÆÈÛ-ÜƯ-̃÷'øù'ú %  %!!"#!$?!@A!B]+^_+`x%yz%{É}€‚˜7™7›«1¬­1®±³ µF·ĂÅ̃;ßà;áäæ++ # #!-. .1ÿÿÿÿ©®Ơtudio 9.0\VC\include\string.h@̀_@c:\ntop\n2n\src\win32\getopt1.cû™&  "9-19: =>4\ _º¼ÿÿÿÿ  9:=ÿÿÿÿrogrammi\Microsoft Visual SZC:\ntop\n2n\win32\supernode\supernode.vcprojDOVefg)hopqvw |~†9‡ O’rŸ ¢¥¸¹º%¼ÉÊê>́7"238S9t3u…†¾¿,’ÚÛ 4 !(P)78:6;GHL,NU?X‚P’®;¯'”רÜ8Ứị́OutliningState10"ÿÿÿÿÿÿÿÿÿÿÿÿ+HOutliningState8 ÿÿÿÿÀlOutliningState5 ÿÿÿÿÿÿÿÿÿÿÿÿ\OutliningState11" $ÿÿÿÿ† xC:\Documents and Settings\Administrator\Desktop\_src\edge.cÛ%P'+,(;<BACNOP4Rabc'eopq/sœHŸ¨©ªC«»¼½T¾ÎÏỤ̂<ó#̃ ""  5 6" :;< >5GHM =PQVz<|0X‡ˆ‰ ¶ ¹ÈÉ bÿÿÿÿ<ô&'-1.CDF)GÎÏOutliningState14"!%ÿÿÿÿ¬OutliningState13"ÿÿÿÿÿÿÿÿÿÿÿÿÖ<OutliningState12"ÿÿÿÿÿÿÿÿö|OutliningState15"ÿÿÿÿÿÿÿÿÿÿÿÿÑ)ÓƯ/àê ̉êíî8ï %( <= M]m p‚ƒ ‹ ”› ²· ¿ÀĂÈ ̉4Ô âă çxc:\Programmi\Microsoft SDKs\Windows\v6.0A\Include\WinSock.h©ºHÿ $%?@CFNO IOkmnrsw~‡(9¡¤¦®¯²³¹ ½4¿À=ÂºÅÆË̀Óáăñóúü( 467= DDIJ-OAQUWhijnow{}…†“• ¢¬®´¶¼¾ÂÄàăäèé́íṇ̃ô*+.08;<Ÿ«¯°*Ơ%±¶âă Ûă  $&*./-02ÿÿÿÿí ÿÿÿÿ àá åIÿÿÿÿ ÿÿÿÿhilqZC:\ntop\n2n\win32\supernode\supernode.vcproj˜¥®±·¸ÀĂÉÏ4Ñ̉4Ô ă#ä ç#è,ÿÿÿÿ4c:\ntop\n2n\src\twofish.c™ê÷!&x€ ±J²@Œ¹$º¿IÎ(ÏeÁ̉dÔÛbƯèéóøư₫ !"#,5.12;J=N?Ptu‡‘H–´µÇÔHÙÍ')4G5₫ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿDHE**„…œ§:¨³O´º»¿1Á ÄBÅË+̀Đ*̉_ñẠú@û'DSrsz;{†C‡±6²¸6¹¿AÀÇ""ÇËÊÿÿÿÿXmlPackageOptions$" ÿÿÿÿ‚OutliningState16"#ÿÿÿÿ-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿntop-n2n-90215bd/win32/DotNet/n2n.vcproj000066400000000000000000000133471422132035700176050ustar00rootroot00000000000000 ntop-n2n-90215bd/win32/DotNet/supernode.vcproj000066400000000000000000000104461422132035700211110ustar00rootroot00000000000000 ntop-n2n-90215bd/win32/Makefile000066400000000000000000000005031422132035700161140ustar00rootroot00000000000000# # This is not a standalone makefile, it must be called from the toplevel # makefile to inherit the correct environment CFLAGS+=-I../include LDFLAGS+=-L.. .PHONY: all clean install all: n2n_win32.a n2n_win32.a: getopt1.o getopt.o wintap.o $(AR) rcs $@ $+ clean: rm -rf n2n_win32.a *.o *.gcno *.gcda install: true ntop-n2n-90215bd/win32/getopt.c000066400000000000000000000767141422132035700161430ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #ifdef HAVE_CONFIG_H # include #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include #ifdef WIN32 #include #endif /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT<_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ # ifdef HAVE_LIBINTL_H # include # define _(msgid) gettext (msgid) # else # define _(msgid) (msgid) # endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ #ifndef DARWIN char *optarg; #endif /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ #ifndef DARWIN int optind = 1; #endif /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ #ifndef DARWIN #ifdef WIN32 int opterr = 0; #else int opterr = 1; #endif #endif /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ #ifndef DARWIN int optopt = '?'; #endif /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include # define my_index strchr #else #ifndef WIN32 # if HAVE_STRING_H # include # else # include # endif #endif /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } # ifdef text_set_element text_set_element (__libc_subinit, store_args_and_env); # endif /* text_set_element */ # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ static void exchange (char **); #endif static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #ifdef _LIBC /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #ifdef _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { int print_errors = opterr; if (optstring[0] == ':') print_errors = 0; optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (print_errors) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, _("%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (print_errors) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (print_errors) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (print_errors) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (print_errors) fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (print_errors) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt____ (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ ntop-n2n-90215bd/win32/getopt.h000066400000000000000000000151401422132035700161320ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* Declarations for getopt. Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GETOPT_H #ifndef __need_getopt # define _GETOPT_H 1 #endif #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; #ifndef __need_getopt /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { # if defined __STDC__ && __STDC__ const char *name; # else char *name; # endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ # define no_argument 0 # define required_argument 1 # define optional_argument 2 #endif /* need getopt */ /* Get definitions and prototypes for functions to process the arguments in ARGV (ARGC of them, minus the program name) for options given in OPTS. Return the option character from OPTS just read. Return -1 when there are no more options. For unrecognized options, or options missing arguments, `optopt' is set to the option letter, and '?' is returned. The OPTS string is a list of characters which are recognized option letters, optionally followed by colons, specifying that that letter takes an argument, to be placed in `optarg'. If a letter in OPTS is followed by two colons, its argument is optional. This behavior is specific to the GNU `getopt'. The argument `--' causes premature termination of argument scanning, explicitly telling `getopt' that there are no more options. If OPTS begins with `--', then non-option arguments are treated as arguments to the option '\0'. This behavior is specific to the GNU `getopt'. */ #if defined __STDC__ && __STDC__ # ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int __argc, char *const *__argv, const char *__shortopts); # else /* not __GNU_LIBRARY__ */ extern int getopt (); # endif /* __GNU_LIBRARY__ */ # ifndef __need_getopt extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, const struct option *__longopts, int *__longind); extern int getopt_long_only (int __argc, char *const *__argv, const char *__shortopts, const struct option *__longopts, int *__longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int __argc, char *const *__argv, const char *__shortopts, const struct option *__longopts, int *__longind, int __long_only); # endif #else /* not __STDC__ */ extern int getopt (); # ifndef __need_getopt extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); # endif #endif /* __STDC__ */ #ifdef __cplusplus } #endif /* Make sure we later can get all the definitions and declarations. */ #undef __need_getopt #endif /* getopt.h */ ntop-n2n-90215bd/win32/getopt1.c000066400000000000000000000125241422132035700162110ustar00rootroot00000000000000/** * (C) 2007-22 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not see see * */ /* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "getopt.h" #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ ntop-n2n-90215bd/win32/n2n_win32.h000066400000000000000000000066751422132035700163640ustar00rootroot00000000000000/* (C) 2007-22 - Luca Deri */ #ifndef _N2N_WIN32_H_ #define _N2N_WIN32_H_ #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif #define WIN32_LEAN_AND_MEAN #if defined(__MINGW32__) /* should be defined here and before winsock gets included */ #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x501 //Otherwise the linker doesnt find getaddrinfo #endif /* #ifndef _WIN32_WINNT */ #include #endif /* #if defined(__MINGW32__) */ #include #include #include #include #if defined(_MSC_VER) #include #pragma comment(lib,"Iphlpapi.lib") #endif #include #include #include #include "wintap.h" #undef EAFNOSUPPORT #define EAFNOSUPPORT WSAEAFNOSUPPORT #define MAX(a,b) (a > b ? a : b) #define MIN(a,b) (a < b ? a : b) #define snprintf _snprintf #define strdup _strdup #define socklen_t int /* ************************************* */ struct ip { #if BYTE_ORDER == LITTLE_ENDIAN u_char ip_hl:4, /* header length */ ip_v:4; /* version */ #else u_char ip_v:4, /* version */ ip_hl:4; /* header length */ #endif u_char ip_tos; /* type of service */ short ip_len; /* total length */ u_short ip_id; /* identification */ short ip_off; /* fragment offset field */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ u_char ip_ttl; /* time to live */ u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ }; /* ************************************* */ typedef struct tuntap_dev { HANDLE device_handle; char *device_name; char *ifName; int if_idx; OVERLAPPED overlap_read, overlap_write; n2n_mac_t mac_addr; uint32_t ip_addr; uint32_t device_mask; unsigned int mtu; unsigned int metric; unsigned int metric_original; } tuntap_dev; /* ************************************* */ #define index(a, b) strchr(a, b) #define sleep(x) Sleep(x * 1000) /* ************************************* */ #define HAVE_PTHREAD #define pthread_t HANDLE #define pthread_mutex_t HANDLE #define pthread_create(p_thread_handle, attr, thread_func, p_param) \ (*p_thread_handle = CreateThread(0 /* default security flags */, 0 /*default stack*/, \ thread_func, p_param, 0 /* default creation flags */, \ NULL) == 0) #define pthread_cancel(p_thread_handle) \ TerminateThread(p_thread_handle, 0) #define pthread_mutex_init(p_mutex_handle, attr) \ *p_mutex_handle = CreateMutex(NULL /*default security flags */, \ FALSE /* initially not owned */, NULL /* unnamed */) #define pthread_mutex_lock(mutex) \ WaitForSingleObject(*mutex, INFINITE) #define pthread_mutex_trylock(mutex) \ WaitForSingleObject(*mutex, NULL) #define pthread_mutex_unlock(mutex) \ ReleaseMutex(*mutex) /* ************************************* */ #endif ntop-n2n-90215bd/win32/version-msvc.c000066400000000000000000000002111422132035700172470ustar00rootroot00000000000000const char * n2n_sw_version = "2.0.0"; const char * n2n_sw_osName = "Win32"; const char * n2n_sw_buildDate = __DATE__ " " __TIME__; ntop-n2n-90215bd/win32/winconfig.h000066400000000000000000000004301422132035700166070ustar00rootroot00000000000000/* winconfig.h. Win32 replacement for file generated from config.h.in by configure. */ /* OS name */ #ifndef PACKAGE_OSNAME #define PACKAGE_OSNAME "windows" #endif /* Define to the version of this package. */ #ifndef PACKAGE_VERSION #define PACKAGE_VERSION N2N_VERSION #endif ntop-n2n-90215bd/win32/wintap.c000066400000000000000000000346721422132035700161400ustar00rootroot00000000000000/* (C) 2007-22 - Luca Deri */ #include "n2n.h" #include "n2n_win32.h" /* ***************************************************** */ void initWin32() { WSADATA wsaData; int err; err = WSAStartup(MAKEWORD(2, 2), &wsaData ); if( err != 0 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ printf("FATAL ERROR: unable to initialise Winsock 2.x."); exit(EXIT_FAILURE); } } void destroyWin32() { WSACleanup(); } struct win_adapter_info { HANDLE handle; char adapterid[1024]; char adaptername[1024]; }; /* ***************************************************** */ static HANDLE open_tap_device(const char *adapterid) { char tapname[1024]; _snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); return(CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, /* Don't let other processes share or open the resource until the handle's been closed */ 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0)); } /* ***************************************************** */ static void iterate_win_network_adapters( int (*callback)(struct win_adapter_info*, struct tuntap_dev *), void *userdata) { HKEY key, key2; char regpath[1024]; long len, rc; int found = 0; int err, i; struct win_adapter_info adapter; /* Open registry and look for network adapters */ if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key))) { printf("Unable to read registry: [rc=%d]\n", rc); exit(EXIT_FAILURE); /* MSVC Note: If you keep getting rc=2 errors, make sure you set: Project -> Properties -> Configuration Properties -> General -> Character set to: "Use Multi-Byte Character Set" */ } for (i = 0; ; i++) { len = sizeof(adapter.adapterid); if(RegEnumKeyEx(key, i, (LPTSTR)adapter.adapterid, &len, 0, 0, 0, NULL)) break; /* Find out more about this adapter */ _snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapter.adapterid); if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2)) continue; len = sizeof(adapter.adaptername); err = RegQueryValueEx(key2, "Name", 0, 0, adapter.adaptername, &len); RegCloseKey(key2); if(err) continue; adapter.handle = open_tap_device(adapter.adapterid); if(adapter.handle != INVALID_HANDLE_VALUE) { /* Valid device, use the callback */ if(!callback(&adapter, userdata)) break; else CloseHandle(adapter.handle); /* continue */ } } RegCloseKey(key); } /* ***************************************************** */ static int print_adapter_callback(struct win_adapter_info *adapter, struct tuntap_dev *device) { printf(" %s - %s\n", adapter->adapterid, adapter->adaptername); /* continue */ return(1); } void win_print_available_adapters() { iterate_win_network_adapters(print_adapter_callback, NULL); } /* ***************************************************** */ static int lookup_adapter_info_reg(const char *target_adapter, char *regpath, size_t regpath_size) { HKEY key, key2; long len, rc; char index[16]; int err, i; char adapter_name[N2N_IFNAMSIZ]; int rv = 0; if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_INFO_KEY, 0, KEY_READ, &key))) { printf("Unable to read registry: %s, [rc=%d]\n", ADAPTER_INFO_KEY, rc); exit(EXIT_FAILURE); } for(i = 0; ; i++) { len = sizeof(index); if(RegEnumKeyEx(key, i, (LPTSTR)index, &len, 0, 0, 0, NULL)) break; _snprintf(regpath, regpath_size, "%s\\%s", ADAPTER_INFO_KEY, index); if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2)) continue; len = sizeof(adapter_name); err = RegQueryValueEx(key2, "NetCfgInstanceId", 0, 0, adapter_name, &len); RegCloseKey(key2); if(err) continue; if(!strcmp(adapter_name, target_adapter)) { rv = 1; break; } } RegCloseKey(key); return(rv); } /* ***************************************************** */ static void set_interface_mac(struct tuntap_dev *device, const char *mac_str) { char cmd[256]; char mac_buf[18]; char adapter_info_reg[1024]; uint64_t mac = 0; uint8_t *ptr = (uint8_t*)&mac; if(strlen(mac_str) != 17) { printf("Invalid MAC: %s\n", mac_str); exit(EXIT_FAILURE); } /* Remove the colons */ for(int i=0; i<6; i++) { mac_buf[i*2] = mac_str[2*i + i]; mac_buf[i*2+1] = mac_str[2*i + i + 1]; } mac_buf[12] = '\0'; if(!lookup_adapter_info_reg(device->device_name, adapter_info_reg, sizeof(adapter_info_reg))) { printf("Could not determine adapter MAC registry key\n"); exit(EXIT_FAILURE); } _snprintf(cmd, sizeof(cmd), "reg add HKEY_LOCAL_MACHINE\\%s /v MAC /d %s /f > nul", adapter_info_reg, mac_buf); system(cmd); /* Put down then up again to apply */ CloseHandle(device->device_handle); _snprintf(cmd, sizeof(cmd), "netsh interface set interface \"%s\" disabled > nul", device->ifName); system(cmd); _snprintf(cmd, sizeof(cmd), "netsh interface set interface \"%s\" enabled > nul", device->ifName); system(cmd); device->device_handle = open_tap_device(device->device_name); if(device->device_handle == INVALID_HANDLE_VALUE) { printf("Reopening TAP device \"%s\" failed\n", device->device_name); exit(EXIT_FAILURE); } } /* ***************************************************** */ static int choose_adapter_callback(struct win_adapter_info *adapter, struct tuntap_dev *device) { if(device->device_name) { /* A device name filter was set, name must match */ if(strcmp(device->device_name, adapter->adapterid) && strcmp(device->device_name, adapter->adaptername)) { /* Not found, continue */ return(1); } } /* otherwise just pick the first available adapter */ /* Adapter found, break */ device->device_handle = adapter->handle; if(device->device_name) free(device->device_name); device->device_name = _strdup(adapter->adapterid); device->ifName = _strdup(adapter->adaptername); return(0); } /* ***************************************************** */ int open_wintap(struct tuntap_dev *device, const char * devname, const char * address_mode, /* "static" or "dhcp" */ char *device_ip, char *device_mask, const char *device_mac, int mtu, int metric) { char cmd[256]; DWORD len; ULONG status = TRUE; memset(device, 0, sizeof(struct tuntap_dev)); device->device_handle = INVALID_HANDLE_VALUE; device->device_name = devname[0] ? _strdup(devname) : NULL; device->ifName = NULL; device->ip_addr = inet_addr(device_ip); iterate_win_network_adapters(choose_adapter_callback, device); if(device->device_handle == INVALID_HANDLE_VALUE) { if(!devname[0]) printf("No Windows tap devices found, did you run tapinstall.exe?\n"); else printf("Cannot find tap device \"%s\"\n", devname); return -1; } /* ************************************** */ /* interface index, required for routing */ ULONG buffer_len = 0; IP_ADAPTER_INFO *buffer; // get required buffer size and allocate buffer GetAdaptersInfo(NULL, &buffer_len); buffer = malloc(buffer_len); // find device by name and get its index if(buffer && !GetAdaptersInfo(buffer, &buffer_len)) { IP_ADAPTER_INFO *i; for(i = buffer; i != NULL; i = i->Next) { if(!strcmp(device->device_name, i->AdapterName)) { device->if_idx = i->Index; break; } } } free(buffer); /* ************************************** */ if(device_mac[0]) set_interface_mac(device, device_mac); /* Get MAC address from tap device->device_name */ if(!DeviceIoControl(device->device_handle, TAP_IOCTL_GET_MAC, device->mac_addr, sizeof(device->mac_addr), device->mac_addr, sizeof(device->mac_addr), &len, 0)) { printf("Could not get MAC address from Windows tap %s (%s)\n", device->device_name, device->ifName); return -1; } device->mtu = mtu; printf("Open device [name=%s][ip=%s][ifName=%s][MTU=%d][mac=%02X:%02X:%02X:%02X:%02X:%02X]\n", device->device_name, device_ip, device->ifName, device->mtu, device->mac_addr[0] & 0xFF, device->mac_addr[1] & 0xFF, device->mac_addr[2] & 0xFF, device->mac_addr[3] & 0xFF, device->mac_addr[4] & 0xFF, device->mac_addr[5] & 0xFF); /* ****************** */ if ( 0 == strcmp("dhcp", address_mode) ) { _snprintf(cmd, sizeof(cmd), "netsh interface ip set address \"%s\" dhcp > nul", device->ifName); } else { _snprintf(cmd, sizeof(cmd), "netsh interface ip set address \"%s\" static %s %s > nul", device->ifName, device_ip, device_mask); } if(system(cmd) == 0) { device->ip_addr = inet_addr(device_ip); device->device_mask = inet_addr(device_mask); } else printf("WARNING: Unable to set device %s IP address [%s]\n", device->ifName, cmd); /* ****************** */ /* MTU */ _snprintf(cmd, sizeof(cmd), "netsh interface ipv4 set subinterface \"%s\" mtu=%d store=persistent > nul", device->ifName, mtu); if(system(cmd) != 0) printf("WARNING: Unable to set device %s parameters MTU=%d store=persistent [%s]\n", device->ifName, mtu, cmd); /* ****************** */ /* metric */ PMIB_IPINTERFACE_ROW Row; if(metric) { /* try to change only if a value has been given, otherwise leave with default or as set before */ // find & store original metric Row = calloc(1, sizeof(MIB_IPINTERFACE_ROW)); InitializeIpInterfaceEntry(Row); Row->InterfaceIndex = device->if_idx; Row->Family = AF_INET; GetIpInterfaceEntry(Row); device->metric_original = Row->Metric; device->metric = metric; // set new value Row->Metric = metric; // store Row->SitePrefixLength = 0; /* if not set to zero, following function call fails... */ SetIpInterfaceEntry(Row); free(Row); } /* ****************** */ /* set driver media status to 'connected' (i.e. set the interface up) */ if (!DeviceIoControl (device->device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof (status), &status, sizeof (status), &len, NULL)) printf("WARNING: Unable to enable TAP adapter\n"); /* * Initialize overlapped structures */ device->overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); device->overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!device->overlap_read.hEvent || !device->overlap_write.hEvent) { return -1; } return(0); } /* ************************************************ */ int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len) { DWORD read_size, last_err; ResetEvent(tuntap->overlap_read.hEvent); if (ReadFile(tuntap->device_handle, buf, len, &read_size, &tuntap->overlap_read)) { //printf("tun_read(len=%d)\n", read_size); return read_size; } switch (last_err = GetLastError()) { case ERROR_IO_PENDING: WaitForSingleObject(tuntap->overlap_read.hEvent, INFINITE); GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_read, &read_size, FALSE); return read_size; break; default: printf("GetLastError() returned %d\n", last_err); break; } return -1; } /* ************************************************ */ int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len) { DWORD write_size; //printf("tun_write(len=%d)\n", len); ResetEvent(tuntap->overlap_write.hEvent); if (WriteFile(tuntap->device_handle, buf, len, &write_size, &tuntap->overlap_write)) { //printf("DONE tun_write(len=%d)\n", write_size); return write_size; } switch (GetLastError()) { case ERROR_IO_PENDING: WaitForSingleObject(tuntap->overlap_write.hEvent, INFINITE); GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_write, &write_size, FALSE); return write_size; break; default: break; } return -1; } /* ************************************************ */ int tuntap_open(struct tuntap_dev *device, char *dev, const char *address_mode, /* static or dhcp */ char *device_ip, char *device_mask, const char * device_mac, int mtu, int metric) { return(open_wintap(device, dev, address_mode, device_ip, device_mask, device_mac, mtu, metric)); } /* ************************************************ */ void tuntap_close(struct tuntap_dev *tuntap) { PMIB_IPINTERFACE_ROW Row; if(tuntap->metric) { /* only required if a value has been given (and thus stored) */ // find device entry Row = calloc(1, sizeof(MIB_IPINTERFACE_ROW)); InitializeIpInterfaceEntry(Row); Row->InterfaceIndex = tuntap->if_idx; Row->Family = AF_INET; GetIpInterfaceEntry(Row); // restore original value Row->Metric = tuntap->metric_original; // store Row->SitePrefixLength = 0; /* if not set to zero, following function call fails... */ SetIpInterfaceEntry(Row); free(Row); } CloseHandle(tuntap->device_handle); } /* Fill out the ip_addr value from the interface. Called to pick up dynamic * address changes. */ void tuntap_get_address(struct tuntap_dev *tuntap) { } /* ************************************************ */ #if 0 int main(int argc, char* argv[]) { struct tuntap_dev tuntap; int i; int mtu = 1400; printf("Welcome to n2n\n"); initWin32(); open_wintap(&tuntap, "static", "1.2.3.20", "255.255.255.0", mtu, 0); for(i=0; i<10; i++) { u_char buf[MTU]; int rc; rc = tun_read(&tuntap, buf, sizeof(buf)); buf[0]=2; buf[1]=3; buf[2]=4; printf("tun_read returned %d\n", rc); rc = tun_write(&tuntap, buf, rc); printf("tun_write returned %d\n", rc); } // rc = tun_open (device->device_name, IF_MODE_TUN); WSACleanup (); return(0); } #endif ntop-n2n-90215bd/win32/wintap.h000066400000000000000000000046001422132035700161310ustar00rootroot00000000000000/* (C) 2007-22 - Luca Deri */ #ifndef _WINTAP_H_ #define _WINTAP_H_ #undef UNICODE #undef _UNICODE #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif #include #include #include //=============================================== // This file is included both by OpenVPN and // the TAP-Win32 driver and contains definitions // common to both. //=============================================== //============= // TAP IOCTLs //============= #define TAP_CONTROL_CODE(request,method) \ CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) #define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) #define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) #define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) #define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) #define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) #define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) #define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) #define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) //================= // Registry keys //================= #define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" #define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" #define ADAPTER_INFO_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" //====================== // Filesystem prefixes //====================== #define USERMODEDEVICEDIR "\\\\.\\Global\\" #define SYSDEVICEDIR "\\Device\\" #define USERDEVICEDIR "\\DosDevices\\Global\\" #define TAPSUFFIX ".tap" //========================================================= // TAP_COMPONENT_ID -- This string defines the TAP driver // type -- different component IDs can reside in the system // simultaneously. //========================================================= #define TAP_COMPONENT_ID "tap0801" extern void initWin32(); extern void destroyWin32(); extern void win_print_available_adapters(); #endif ntop-n2n-90215bd/wireshark/000077500000000000000000000000001422132035700155135ustar00rootroot00000000000000ntop-n2n-90215bd/wireshark/README.md000066400000000000000000000004131422132035700167700ustar00rootroot00000000000000Wireshark Lua plugin to dissect n2n traffic. Quick load: ``` wireshark -X lua_script:n2n.lua ``` 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. ntop-n2n-90215bd/wireshark/n2n.lua000066400000000000000000000244421422132035700167210ustar00rootroot00000000000000-- (C) 2019 - ntop.org and contributors n2n = Proto("n2n", "n2n Protocol") -- ############################################# PKT_TYPE_PING = 0 PKT_TYPE_REGISTER = 1 PKT_TYPE_DEREGISTER = 2 PKT_TYPE_PACKET = 3 PKT_TYPE_REGISTER_ACK = 4 PKT_TYPE_REGISTER_SUPER = 5 PKT_TYPE_REGISTER_SUPER_ACK = 6 PKT_TYPE_REGISTER_SUPER_NAK = 7 PKT_TYPE_FEDERATION = 8 PKT_TYPE_PEER_INFO = 9 PKT_TYPE_QUERY_PEER = 10 PKT_TRANSFORM_NULL = 1 PKT_TRANSFORM_TWOFISH = 2 PKT_TRANSFORM_AESCBC = 3 FLAG_FROM_SUPERNODE = 0x0020 FLAG_SOCKET = 0x0040 FLAG_OPTIONS = 0x0080 SOCKET_FAMILY_AF_INET = 0x0000 SOCKET_FAMILY_AF_INET6 = 0x8000 -- ############################################# version = ProtoField.uint8("n2n.version", "version", base.DEC) ttl = ProtoField.uint8("n2n.ttl", "ttl", base.DEC) packet_type_mask = 0x001f pkt_type_2_str = { [PKT_TYPE_PING] = "ping", [PKT_TYPE_REGISTER] = "register", [PKT_TYPE_DEREGISTER] = "deregister", [PKT_TYPE_PACKET] = "packet", [PKT_TYPE_REGISTER_ACK] = "register_ack", [PKT_TYPE_REGISTER_SUPER] = "register_super", [PKT_TYPE_REGISTER_SUPER_ACK] = "register_super_ack", [PKT_TYPE_REGISTER_SUPER_NAK] = "register_super_nak", [PKT_TYPE_FEDERATION] = "federation", [PKT_TYPE_PEER_INFO] = "peer_info", [PKT_TYPE_QUERY_PEER] = "query_peer", } packet_type = ProtoField.uint8("n2n.packet_type", "packetType", base.HEX, pkt_type_2_str, packet_type_mask) flags_mask = 0xffe0 flags = ProtoField.uint16("n2n.flags", "Flags", base.HEX, nil, flags_mask) from_supernode_flag = ProtoField.uint16("n2n.flags.from_supernode", "from_supernode", base.BOOLEAN, nil, FLAG_FROM_SUPERNODE) socket_flag = ProtoField.uint16("n2n.flags.socket", "socket", base.BOOLEAN, nil, FLAG_SOCKET) options_flag = ProtoField.uint16("n2n.flags.options", "options", base.BOOLEAN, nil, FLAG_OPTIONS) community = ProtoField.string("n2n.community", "Community", base.ASCII) -- ############################################# src_mac = ProtoField.ether("n2n.src_mac", "Source") dst_mac = ProtoField.ether("n2n.dst_mac", "Destination") socket_info = ProtoField.none("n2n.socket", "Socket Info") socket_family = ProtoField.uint16("n2n.socket.family", "Family", base.HEX, { [0] = "AF_INET", }) socket_port = ProtoField.uint16("n2n.socket.port", "Port") socket_ipv4 = ProtoField.ipv4("n2n.socket.ipv4", "IPv4") socket_ipv6 = ProtoField.ipv6("n2n.socket.ipv6", "IPv6") -- ############################################# peer_info_field = ProtoField.none("n2n.peer_info", "PeerInfo") peer_info_flags = ProtoField.uint16("n2n.peer_info.flags", "Flags") peer_info_mac = ProtoField.ether("n2n.peer_info.query_mac", "Query") query_peer_field = ProtoField.none("n2n.query_peer", "QueryPeer") -- ############################################# packet_field = ProtoField.none("n2n.packet", "Packet") packet_transform = ProtoField.uint16("n2n.packet.transform", "Transform", base.HEX, { [PKT_TRANSFORM_NULL] = "Plaintext", [PKT_TRANSFORM_TWOFISH] = "TwoFish", [PKT_TRANSFORM_AESCBC] = "AES CBC", }) packet_payload = ProtoField.bytes("n2n.packet.payload", "Payload") -- ############################################# register_field = ProtoField.none("n2n.register", "Register") register_cookie = ProtoField.uint32("n2n.register.cookie", "Cookie", base.HEX) register_ack_field = ProtoField.none("n2n.register_ack", "RegisterACK") register_ack_cookie = ProtoField.uint32("n2n.register_ack.cookie", "Cookie", base.HEX) register_super_field = ProtoField.none("n2n.register_super", "RegisterSuper") register_super_cookie = ProtoField.uint32("n2n.register_super.cookie", "Cookie", base.HEX) register_super_auth_schema = ProtoField.uint16("n2n.register_super.auth.schema", "AuthSchema", base.HEX) register_super_auth_data = ProtoField.uint16("n2n.register_super.auth.data", "AuthData", base.HEX) register_super_ack_field = ProtoField.none("n2n.register_super_ack", "RegisterSuperACK") register_super_ack_cookie = ProtoField.uint32("n2n.register_super_ack.cookie", "Cookie", base.HEX) register_super_ack_lifetime = ProtoField.uint16("n2n.register_super_ack.lifetime", "Registration Lifetime", base.DEC) register_super_ack_num_sn = ProtoField.uint8("n2n.register_super_ack.num_sn", "Num Supernodes", base.DEC) -- ############################################# n2n.fields = { version, ttl, packet_type, flags, from_supernode_flag, socket_flag, options_flag, community, -- Generic src_mac, dst_mac, socket_info, socket_family, socket_port, socket_ipv4, socket_ipv6, -- PKT_TYPE_REGISTER register_field, register_cookie, -- PKT_TYPE_PACKET packet_field, packet_transform, packet_payload, -- PKT_TYPE_REGISTER_ACK register_ack_field, register_ack_cookie, -- PKT_TYPE_REGISTER_SUPER register_super_field, register_super_cookie, register_super_auth_schema, register_super_auth_data, -- PKT_TYPE_REGISTER_SUPER_ACK register_super_ack_field, register_super_ack_cookie, register_super_ack_lifetime, register_super_ack_num_sn, -- PKT_TYPE_PEER_INFO peer_info_field, peer_info_flags, peer_info_mac, -- PKT_TYPE_QUERY_PEER query_peer_field, } -- ############################################# function dissect_socket(subtree, buffer, offset) local sock_baselen = 4 local sock_protolen = 0 buffer = buffer(offset) local sock_family = bit.band(buffer(0,4):uint(), 0xFFFF0000) if(sock_family == SOCKET_FAMILY_AF_INET) then sock_protolen = 4 elseif(sock_family == SOCKET_FAMILY_AF_INET6) then sock_protolen = 16 end local totlen = sock_baselen + sock_protolen local socktree = subtree:add(socket_info, buffer(0, totlen)) socktree:add(socket_family, buffer(0, 2)) socktree:add(socket_port, buffer(2, 2)) if(sock_family == SOCKET_FAMILY_AF_INET) then socktree:add(socket_ipv4, buffer(4, sock_protolen)) elseif(sock_family == SOCKET_FAMILY_AF_INET6) then socktree:add(socket_ipv6, buffer(4, sock_protolen)) end return offset+totlen, socktree end -- ############################################# function dissect_register(subtree, buffer, flags) local regtree = subtree:add(register_field, buffer) regtree:add(register_cookie, buffer(0,4)) regtree:add(src_mac, buffer(4,6)) regtree:add(dst_mac, buffer(10,6)) if(bit.band(flags, FLAG_SOCKET) == FLAG_SOCKET) then dissect_socket(regtree, buffer, 16) end return regtree end -- ############################################# function dissect_register_ack(subtree, buffer, flags) local regtree = subtree:add(register_ack_field, buffer) regtree:add(register_ack_cookie, buffer(0,4)) regtree:add(src_mac, buffer(4,6)) regtree:add(dst_mac, buffer(10,6)) return regtree end -- ############################################# function dissect_packet(subtree, buffer, flags, pinfo) local pktree = subtree:add(packet_field, buffer) pktree:add(src_mac, buffer(0,6)) pktree:add(dst_mac, buffer(6,6)) if(bit.band(flags, FLAG_SOCKET) == FLAG_SOCKET) then idx = dissect_socket(pktree, buffer, 12) else idx = 12 end pktree:add(packet_transform, buffer(idx,2)) local payload = pktree:add(packet_payload, buffer(idx+2)) local transform = buffer(idx,2):uint() -- Can only dissect unencrypted data if(transform == PKT_TRANSFORM_NULL) then Dissector.get("eth_withoutfcs"):call(buffer(idx+2):tvb(), pinfo, payload) end return pktree end -- ############################################# function dissect_register_super(subtree, buffer, flags) local regtree = subtree:add(register_super_field, buffer) regtree:add(register_super_cookie, buffer(0,4)) regtree:add(src_mac, buffer(4,6)) regtree:add(register_super_auth_schema, buffer(10,2)) regtree:add(register_super_auth_data, buffer(12,2)) return regtree end -- ############################################# function dissect_register_super_ack(subtree, buffer, flags) local regtree = subtree:add(register_super_ack_field, buffer) regtree:add(register_super_ack_cookie, buffer(0,4)) regtree:add(dst_mac, buffer(4,6)) regtree:add(register_super_ack_lifetime, buffer(10,2)) local idx = dissect_socket(regtree, buffer, 12) regtree:add(register_super_ack_num_sn, buffer(idx, 1)) return regtree end -- ############################################# function dissect_peer_info(subtree, buffer, flags) local peertree = subtree:add(peer_info_field, buffer) peertree:add(peer_info_flags, buffer(0,2)) peertree:add(peer_info_mac, buffer(2,6)) dissect_socket(peertree, buffer, 8) return peertree end -- ############################################# function dissect_query_peer(subtree, buffer, flags) local peertree = subtree:add(query_peer_field, buffer) peertree:add(src_mac, buffer(0,6)) peertree:add(dst_mac, buffer(6,6)) return peertree end -- ############################################# function n2n.dissector(buffer, pinfo, tree) local length = buffer:len() if length < 20 then return end pinfo.cols.protocol = n2n.name local pkt_type = bit.band(buffer(2,2):uint(), packet_type_mask) local subtree = tree:add(n2n, buffer(), string.format("n2n Protocol, Type: %s", pkt_type_2_str[pkt_type] or "Unknown")) -- Common subtree:add(version, buffer(0,1)) subtree:add(ttl, buffer(1,1)) subtree:add(packet_type, buffer(2,2)) local flags_buffer = buffer(2,2) local flags_tree = subtree:add(flags, flags_buffer) subtree:add(community, buffer(4,16)) -- Flags flags_tree:add(from_supernode_flag, flags_buffer) flags_tree:add(socket_flag, flags_buffer) flags_tree:add(options_flag, flags_buffer) -- Packet specific local flags = bit.band(buffer(2,2):uint(), flags_mask) local typebuf = buffer(20) if(pkt_type == PKT_TYPE_REGISTER) then dissect_register(subtree, typebuf, flags) elseif(pkt_type == PKT_TYPE_REGISTER) then dissect_register_ack(subtree, typebuf, flags) elseif(pkt_type == PKT_TYPE_PACKET) then dissect_packet(subtree, typebuf, flags, pinfo) elseif(pkt_type == PKT_TYPE_REGISTER_SUPER) then dissect_register_super(subtree, typebuf, flags) elseif(pkt_type == PKT_TYPE_REGISTER_SUPER_ACK) then dissect_register_super_ack(subtree, typebuf, flags) elseif(pkt_type == PKT_TYPE_PEER_INFO) then dissect_peer_info(subtree, typebuf, flags) elseif(pkt_type == PKT_TYPE_QUERY_PEER) then dissect_query_peer(subtree, typebuf, flags) end end -- ############################################# local udp_port = DissectorTable.get("udp.port") udp_port:add(50001, n2n)